From: Nigel Cunningham <ncunningham@linuxmail.org>
To: Pavel Machek <pavel@ucw.cz>
Cc: Christoph Hellwig <hch@infradead.org>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
hugang@soulinfo.com, Andrew Morton <akpm@zip.com.au>
Subject: Re: Suspend 2 merge
Date: Fri, 26 Nov 2004 10:46:56 +1100 [thread overview]
Message-ID: <1101426416.27250.147.camel@desktop.cunninghams> (raw)
In-Reply-To: <20041125232200.GG2711@elf.ucw.cz>
Hi.
On Fri, 2004-11-26 at 10:22, Pavel Machek wrote:
> I'd prefer not to get plugins and abstract storage. I'm not sure about
> extents, but as soon as I can get rid of order-8 allocations, things
> should be ok.
Don't you need more than that? Unless things have changed, you still
spend most of your time eating memory so that you only have a few megs
(well, maybe a little more) to write to disk. If you do reduce the
amount of memory you eat, then you need to work to make the I/O faster.
> > > [Okay, at this point I'll understand when you'll put my picture as a
> > > texture to some doom3 monster and shoot me thousand times... Lot of
> > > work went into suspend2, but in the meantime lot of work went into
> > > swsusp1, too...]
> >
> > Not at all. Perhaps I'm overstating the case or not spending enough time
> > looking at your code, but I don't actually think swsusp has changed a
> > lot in the two years since I started working on this. (Want my picture
> > now? :>)
>
> Well, it was rewriten by Patrick so it actually looks okay, and it
> started to work for users...
:> Okay.
> > > > - Speed: All I/O is asynchronous where possible and readahead used where
> > > > not. Routines everywhere optimised to get things done as fast as poss.
> > > > (Think low battery).
> > >
> > > I fixed O(n^2) behaviour in swsusp1 (not yet in). I do not think that
> > > asynchronous I/O is does that much difference.
> >
> > Oh, it makes a huge difference once you're not eating all the memory you
> > can. If I submit I/O one at a time, I do 1 or 2 MB/s. With asynchrounous
> > I/O, I can write 70MB/s and read 110MB/s with compression, 58|58 without
> > compression (that's the maximum throughput of the drive I'm using at the
> > moment). If I can streamline things a further, I should be able to lift
> > that write rate further, too.
>
> Okay, 58MB/sec is better than 1MB/sec. I do not think I want the
> complexity neccessary to get me 70MB/sec.
Fair enough for you, but not everyone can say that. At the end of the
day, I'm not writing this code just for me to use, though. Many of the
features I've added have been added for the benefit of other people; I
assume you'd do the same. Most laptops can't do 58MB/s, so the
difference is much bigger. (My original laptop hard drive did 17/s; with
compression I think it achieved something close to double that,
depending on the data being compressed, of course).
> In some ways, suspend2 is two years ahead of rest of kernel:
> * you have interactive debugging
> * file compression
> * nice splash screen
> * plugin interface for transparent network support
>
> Unfortunately, we do not want compression done like that. It would
> make sense to do compressed-LVM or something like that (that way
> everyone would get the benefit), but it does not make sense to have it
> just for suspend2. And we do not want the rest of features, too,
> unless they work for the rest of kernel.
The cryptoapi provides support for both compression and encryption. I'd
happily make use of that, but we still need a way for the user to choose
what compression/encryption they want and configure it. I'm not at all
adverse to the idea of shifting the lzf compression support into being a
cryptoapi plugin. That shouldn't be hard to do precisely because I have
the plugin system :>.
> > > > - Test bed: Around 10,000 downloads of the 1.0 patch, 2730 to date of
> > > > the 2.1.5 version I released 2 weeks ago.
> > >
> > > Hmm, look at number of downloads of 2.6.9 kernel, I think I win here
> > > ;-)))). SuSE9.2 is actually shipping swsusp1 and advertising it as a
> > > feature. And it seems to work for people...
> >
> > :> But not everyone who uses 2.6.9 uses swsusp. :>
>
> But they should ;-).
I'll beg to differ there :>
> > > > - Swap file support
> > > > - Support for LVM/dm-crypt and siblings
> > > > - Support for having device drivers as modules (resume from an
> > > > initrd/initramfs)
> > >
> > > Okay, you win these.
> >
> > I don't want to have a competition, really. I just want to convince you
> > that I've done some worthwhile work :>
>
> You did wonderfull work -- you shown what is possible with
> suspend2. Now we just need to scale it back to what is practical. It
> needs not only to work, it also needs to be nice, simple, and easy to
> maintain.
I think it is practical. Apart from the bootsplash support, I don't
think I have added any feature because I thought "Hey, this looks like a
fun thing to try.". Every feature has been added because it makes
suspend faster, more reliable, more user friendly, more versatile or the
like. If we want Linux to get adopted by desktop users, it needs to have
these features. Making it harder to use by forcing people to reboot to
change a parameter or forcing them to do an ls in /dev with obscure
parameters (to get the major and minor numbers) when they already know
they want /dev/sda1 isn't user friendly. Obviously user friendliness is
more important to me than to you. That's fine, but let's agree to differ
and let the software be more helpful rather than less.
> > > > - Designed to save as much of memory as possible rather than as little
> > > > (making the system more responsive post-resume).
> > >
> > > hugang already has a patch, but I'm not 100% sure if I want it
> > > in. Yes, people seem to like this feature, but it complicates
> > > *design*, quite a lot.
> >
> > It does. But if there were fundamental flaws in the approach, we would
> > have found them by now. Since you're using bio calls and not swap's own
> > read/write functions, you shouldn't have any problems.
>
> I believe it has at least one pretty bad flaw: it has hooks all over
> the place and will be nightmare to maintain. Puting suspend hooks into
> memory allocation is not nice.
That's a big statement.
"Hooks all over the place" was a phrase first used to refer to the
attempts at making freezing more reliable. That's irrelevant now with
the simplified three stages to freezing. The hooks are the same as for
swsusp1 there.
The hooks you've seen in the rest of the kernel are generally only
further supplements to the freezing, so that swsusp should probably have
them too.
The hooks in the memory management are minimal and wrapped in
unlikely(), so they shouldn't really be a problem in the normal flow of
things. While suspend is running, they serve a good and necessary
purpose. Using high level routines, we can't guarantee that new slab
pages, for example, aren't allocated while we're writing the LRU pages.
If you can't be sure of that and don't want to satisfy allocations from
a memory pool, you'll need to recheck that your saving all the pages
after writing LRU. And if you do that, you might need to allocate more
memory for the metadata, which might mean freeing an LRU page or two,
which will make your image inconsistent. A memory pool is a simple and
effective solution to that issue: we know exactly what pages may be
allocated when we do our atomic copy, and we copy them without having to
figure out which ones were actually used.
> swsusp1 is pretty self-contained. As long as drivers stop the DMA and
> NMI does nothing wrong, atomic snapshot will indeed be atomic.
>
> Can you list conditions neccessary for suspend2 to work?
Not really sure what you mean. At the moment, the main hinderance to it
working properly is driver model support (USB, DRI, as said previously).
That forces us to have a userspace script to compile as modules and
stop/unload support around kernel call. Given that these things are
done, and that suspend is able to get enough memory to do it's work
(almost never a problem), suspend should always work.
Regards,
Nigel
--
Nigel Cunningham
Pastoral Worker
Christian Reformed Church of Tuggeranong
PO Box 1004, Tuggeranong, ACT 2901
You see, at just the right time, when we were still powerless, Christ
died for the ungodly. -- Romans 5:6
next prev parent reply other threads:[~2004-11-26 21:41 UTC|newest]
Thread overview: 245+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-11-24 12:56 Suspend 2 merge Nigel Cunningham
2004-11-24 12:56 ` Suspend2 merge: 1/51: Device trees Nigel Cunningham
2004-11-24 12:56 ` Suspend2 merge: 2/51: Find class by name Nigel Cunningham
2004-11-24 12:57 ` Suspend 2 merge: 3/51: e820 table support Nigel Cunningham
2004-11-25 16:53 ` Pavel Machek
2004-11-24 12:57 ` Suspend 2 merge: 4/51: Get module list Nigel Cunningham
2004-11-25 16:56 ` Pavel Machek
2004-11-25 21:25 ` Nigel Cunningham
2004-11-25 21:32 ` Pavel Machek
2004-11-24 12:57 ` Suspend 2 merge: 5/51: Workthread freezer support Nigel Cunningham
2004-11-25 16:57 ` Pavel Machek
2004-11-24 12:57 ` Suspend 2 merge: 7/51: Reboot handler hook Nigel Cunningham
2004-11-24 13:07 ` Christoph Hellwig
2004-11-24 20:19 ` Nigel Cunningham
2004-11-25 2:37 ` Nigel Cunningham
2004-11-24 12:57 ` Suspend 2 merge: 8/51: /proc/acpi/sleep hook Nigel Cunningham
2004-11-24 13:13 ` Christoph Hellwig
2004-11-24 12:57 ` Suspend 2 merge: 9/51: init/* changes Nigel Cunningham
2004-11-25 17:07 ` Pavel Machek
2004-11-25 21:36 ` Nigel Cunningham
2004-11-25 21:45 ` Pavel Machek
2004-11-25 21:51 ` Nigel Cunningham
2004-11-25 21:58 ` Pavel Machek
2004-11-25 22:03 ` Nigel Cunningham
2004-11-25 22:30 ` Pavel Machek
2004-11-27 2:14 ` Matthew Garrett
2004-11-27 7:22 ` Pavel Machek
2004-11-27 9:31 ` Herbert Xu
2004-11-27 13:21 ` Matthew Garrett
2004-11-27 16:20 ` Pavel Machek
2004-11-28 22:43 ` Nigel Cunningham
2004-11-24 12:57 ` Suspend 2 merge: 10/51: Exports for suspend built as modules Nigel Cunningham
2004-11-24 13:12 ` Christoph Hellwig
2004-11-24 21:52 ` Nigel Cunningham
2004-11-24 14:44 ` Ingo Molnar
2004-11-24 20:46 ` Nigel Cunningham
2004-11-25 18:07 ` Pavel Machek
2004-11-25 21:40 ` Nigel Cunningham
2004-11-25 21:50 ` Pavel Machek
2004-11-24 12:57 ` Suspend 2 merge: 11/51: Export vt functions Nigel Cunningham
2004-11-24 12:57 ` Suspend 2 merge:L 12/51: Disable OOM killer when suspending Nigel Cunningham
2004-11-25 18:12 ` Pavel Machek
2004-11-25 21:47 ` Nigel Cunningham
2004-11-25 21:54 ` Pavel Machek
2004-11-24 12:57 ` Suspend 2 merge: 13/51: Disable highmem tlb flush for copyback Nigel Cunningham
2004-11-25 18:13 ` Pavel Machek
2004-11-24 12:57 ` Suspend 2 merge: 14/51: Disable page alloc failure message when suspending Nigel Cunningham
2004-11-24 14:15 ` Christoph Hellwig
2004-11-24 20:46 ` Nigel Cunningham
2004-11-24 16:00 ` Dave Hansen
2004-11-24 21:06 ` Nigel Cunningham
2004-11-24 22:25 ` Dave Hansen
2004-11-25 18:15 ` Pavel Machek
2004-11-25 21:49 ` Nigel Cunningham
2004-11-25 21:56 ` Pavel Machek
2004-11-25 22:46 ` Nigel Cunningham
2004-11-25 23:22 ` Pavel Machek
2004-11-24 12:58 ` Suspend 2 merge: 15/51: Disable pdflush during suspend Nigel Cunningham
2004-11-24 12:58 ` Suspend 2 merge: 16/51: Disable cache reaping " Nigel Cunningham
2004-11-25 18:18 ` Pavel Machek
2004-11-25 22:00 ` Nigel Cunningham
2004-11-24 12:58 ` Suspend 2 merge: 17/51: Disable MCE checking " Nigel Cunningham
2004-11-25 18:19 ` Pavel Machek
2004-11-25 22:05 ` Nigel Cunningham
2004-11-25 22:31 ` Pavel Machek
2004-11-25 22:38 ` Nigel Cunningham
2004-11-25 22:45 ` Pavel Machek
2004-11-24 12:58 ` Suspend 2 merge: 18/51: Debug page_alloc support Nigel Cunningham
2004-11-24 16:02 ` Dave Hansen
2004-11-24 20:17 ` Nigel Cunningham
2004-11-24 22:26 ` Dave Hansen
2004-11-25 18:21 ` Pavel Machek
2004-11-25 22:06 ` Nigel Cunningham
2004-11-24 12:58 ` Suspend 2 merge: 19/51: Remove MTRR sysdev support Nigel Cunningham
2004-11-24 16:27 ` Zwane Mwaikambo
2004-11-24 20:17 ` Nigel Cunningham
2004-11-25 18:22 ` Pavel Machek
2004-11-28 22:34 ` Nigel Cunningham
2004-11-24 12:58 ` Suspend 2 merge: 20/51: Timer freezer (experimental) Nigel Cunningham
2004-11-24 12:58 ` Suspend 2 merge: 21/51: Refrigerator upgrade Nigel Cunningham
2004-11-25 18:33 ` Pavel Machek
2004-11-25 22:10 ` Nigel Cunningham
2004-11-25 22:36 ` Pavel Machek
2004-11-25 22:49 ` Nigel Cunningham
2004-11-25 23:25 ` Pavel Machek
2004-11-25 23:49 ` Nigel Cunningham
2004-11-26 0:05 ` Pavel Machek
2004-11-26 0:12 ` Nigel Cunningham
2004-11-26 0:18 ` Pavel Machek
2004-11-27 17:18 ` Pavel Machek
2004-11-26 21:00 ` Christoph Hellwig
2004-11-24 12:58 ` Suspend 2 merge: 22/51: Suspend2 lowlevel code Nigel Cunningham
2004-11-24 16:42 ` Zwane Mwaikambo
2004-11-24 21:20 ` Nigel Cunningham
2004-11-24 21:55 ` Zwane Mwaikambo
2004-11-24 21:56 ` Nigel Cunningham
2004-11-25 18:39 ` Pavel Machek
2004-11-25 22:15 ` Nigel Cunningham
2004-11-25 22:38 ` Pavel Machek
2004-11-24 12:58 ` Suspend 2 merge: 23/51: PPC support Nigel Cunningham
2004-11-25 18:40 ` Pavel Machek
2004-11-25 22:15 ` Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 24/51: Keyboard and serial console hooks Nigel Cunningham
2004-11-24 13:29 ` Christoph Hellwig
2004-11-24 18:47 ` Yaroslav Rastrigin
2004-11-24 21:38 ` Nigel Cunningham
2004-11-24 21:57 ` Jan Rychter
2004-11-24 23:02 ` Christoph Hellwig
2004-11-25 1:22 ` Jan Rychter
2004-11-25 10:08 ` Christoph Hellwig
2004-11-26 20:21 ` pb
2004-11-25 19:28 ` Pavel Machek
2004-11-28 22:34 ` Nigel Cunningham
2004-11-28 23:39 ` Pavel Machek
2004-11-29 22:15 ` Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 25/51: Documentation Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 26/51: Kconfig and makefile Nigel Cunningham
2004-11-24 16:34 ` Roman Zippel
2004-11-24 21:11 ` Nigel Cunningham
2004-11-24 21:46 ` Roman Zippel
2004-11-24 21:53 ` Nigel Cunningham
2004-11-25 2:37 ` Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 27/51: Block I/O module Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 28/51: Suspend memory pool hooks Nigel Cunningham
2004-11-25 19:34 ` Pavel Machek
2004-11-24 12:59 ` Suspend 2 merge: 29/51: Clear swapfile bdev in swapoff Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 30/51: Enable slab alloc fallback to suspend memory pool Nigel Cunningham
2004-11-25 19:36 ` Pavel Machek
2004-11-24 12:59 ` Suspend 2 merge: 31/51: Export tlb flushing Nigel Cunningham
2004-11-24 15:32 ` Martin J. Bligh
2004-11-24 21:04 ` Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 32/51: Make show task non-static Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 33/51: More documentation Nigel Cunningham
2004-11-24 13:00 ` Suspend 2 merge: 34/51: Includes Nigel Cunningham
2004-11-24 13:25 ` Christoph Hellwig
2004-11-24 20:17 ` Nigel Cunningham
2004-11-24 23:19 ` Matthew Garrett
2004-11-25 2:43 ` Nigel Cunningham
2004-11-24 13:00 ` Suspend 2 merge: 35/51: Code always built in to the kernel Nigel Cunningham
2004-11-25 23:32 ` Pavel Machek
2004-11-25 23:57 ` Nigel Cunningham
2004-11-26 0:08 ` Pavel Machek
2004-11-26 0:17 ` Nigel Cunningham
2004-11-26 0:23 ` Pavel Machek
2004-11-27 2:19 ` Matthew Garrett
2004-11-28 22:39 ` Nigel Cunningham
2004-11-27 9:00 ` Jan Rychter
2004-11-27 17:22 ` Pavel Machek
2004-11-24 13:00 ` Suspend 2 merge: 36/51: Highlevel I/O routines Nigel Cunningham
2004-11-25 23:36 ` Pavel Machek
2004-11-27 1:39 ` Tomas Carnecky
2004-11-24 13:00 ` Suspend 2 merge: 37/51: Memory pool support Nigel Cunningham
2004-11-25 23:37 ` Pavel Machek
2004-11-24 13:00 ` Suspend 2 merge: 38/51: Page directory support Nigel Cunningham
2004-11-24 13:01 ` Suspend 2 merge: 39/51: Plugins support Nigel Cunningham
2004-11-24 13:01 ` Suspend 2 merge: 40/51: Prepare image Nigel Cunningham
2004-11-24 13:01 ` Suspend 2 merge: 41/51: Ranges (extents) Nigel Cunningham
2004-11-24 13:01 ` Suspend 2 merge: 42/51: Suspend.c Nigel Cunningham
2004-11-24 16:52 ` Zwane Mwaikambo
2004-11-24 21:23 ` Nigel Cunningham
2004-11-25 23:43 ` Pavel Machek
2004-11-24 13:01 ` Suspend 2 merge: 43/51: Utility functions Nigel Cunningham
2004-11-25 23:46 ` Pavel Machek
2004-11-26 0:04 ` Nigel Cunningham
2004-11-27 16:11 ` Dave Hansen
2004-11-28 21:36 ` Nigel Cunningham
2004-11-24 13:01 ` Suspend 2 merge: 44/51: Text UI plugin Nigel Cunningham
2004-11-24 13:02 ` Suspend 2 merge: 45/51: Bootsplash support Nigel Cunningham
2004-11-24 13:02 ` Suspend 2 merge: 46/51: LZF support Nigel Cunningham
2004-11-24 23:01 ` Bartlomiej Zolnierkiewicz
2004-11-25 2:38 ` Nigel Cunningham
2004-11-25 6:32 ` hugang
2004-11-25 6:52 ` Dmitry Torokhov
2004-11-25 7:07 ` hugang
2004-11-25 10:10 ` Christoph Hellwig
2004-11-24 13:02 ` Suspend 2 merge: 47/51: GZIP support Nigel Cunningham
2004-11-25 23:50 ` Pavel Machek
2004-11-24 13:02 ` Suspend 2 merge: 48/51: Swapwriter Nigel Cunningham
2004-11-25 23:55 ` Pavel Machek
2004-11-26 0:05 ` Nigel Cunningham
2004-11-24 13:02 ` Suspend 2 merge: 49/51: Checksumming Nigel Cunningham
2004-11-25 23:56 ` Pavel Machek
2004-11-26 0:00 ` Nigel Cunningham
2004-11-26 0:14 ` Pavel Machek
2004-11-29 9:55 ` Rob Landley
2004-11-30 0:24 ` Nigel Cunningham
2004-11-29 23:30 ` Rob Landley
2004-11-30 0:49 ` Nigel Cunningham
2004-11-30 13:07 ` Pavel Machek
2004-11-30 21:45 ` Nigel Cunningham
2004-11-30 13:02 ` Pavel Machek
2004-11-30 13:38 ` Matthew Garrett
2004-11-30 22:38 ` Pavel Machek
2004-12-02 21:31 ` Rob Landley
2004-11-24 13:02 ` Suspend 2 merge: 50/51: Device mapper support Nigel Cunningham
2004-11-25 23:58 ` Pavel Machek
2004-11-26 0:07 ` Nigel Cunningham
2004-12-02 20:40 ` Alasdair G Kergon
2004-12-02 21:04 ` Nigel Cunningham
2004-12-02 21:49 ` Alasdair G Kergon
2004-12-02 22:08 ` Nigel Cunningham
2004-12-03 17:47 ` Alasdair G Kergon
2004-12-03 19:57 ` Nigel Cunningham
2004-12-03 20:12 ` Alasdair G Kergon
2004-12-14 0:47 ` Nigel Cunningham
2004-11-24 13:03 ` Suspend 2 merge: 51/51: Notes Nigel Cunningham
2004-11-26 0:01 ` Pavel Machek
2004-11-26 0:09 ` Nigel Cunningham
2004-11-26 0:24 ` Pavel Machek
2004-11-24 13:03 ` Suspend 2 merge: 6/51 Nigel Cunningham
2004-11-24 13:28 ` Suspend 2 merge Christoph Hellwig
2004-11-24 20:46 ` Nigel Cunningham
2004-11-25 19:20 ` Pavel Machek
2004-11-25 22:34 ` Nigel Cunningham
2004-11-25 23:22 ` Pavel Machek
2004-11-25 23:46 ` Nigel Cunningham [this message]
2004-11-26 0:39 ` Pavel Machek
2004-11-26 9:08 ` Nigel Cunningham
2004-11-26 12:38 ` Pavel Machek
2004-11-26 15:54 ` Christoph Hellwig
2004-11-26 22:36 ` Pavel Machek
2004-11-28 22:35 ` Nigel Cunningham
2004-11-28 23:55 ` Pavel Machek
2004-11-29 3:20 ` Nigel Cunningham
2004-11-29 13:03 ` Pavel Machek
2004-11-30 0:24 ` Nigel Cunningham
2004-11-30 10:19 ` Pavel Machek
[not found] ` <20041126043203.GA2713@hugang.soulinfo.com>
2004-11-26 9:08 ` Nigel Cunningham
2004-11-26 13:37 ` Pavel Machek
2004-11-26 13:31 ` Pavel Machek
[not found] ` <20041126082109.GA842@hugang.soulinfo.com>
2004-11-26 13:25 ` Pavel Machek
2004-11-28 21:40 ` Nigel Cunningham
2004-11-29 9:34 ` Stefan Seyfried
2004-11-29 22:20 ` Nigel Cunningham
2004-11-29 22:34 ` Pavel Machek
2004-11-30 12:16 ` Stefan Seyfried
2004-11-30 21:16 ` Nigel Cunningham
2004-11-30 22:20 ` Pavel Machek
2004-12-01 9:27 ` Nigel Cunningham
2004-12-01 10:08 ` Pavel Machek
2004-12-01 20:39 ` Nigel Cunningham
-- strict thread matches above, loose matches on Subject: below --
2004-11-27 22:07 linux
2004-11-27 22:25 ` Pavel Machek
2004-11-28 8:29 ` Wichert Akkerman
2004-11-28 11:37 ` Pavel Machek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1101426416.27250.147.camel@desktop.cunninghams \
--to=ncunningham@linuxmail.org \
--cc=akpm@zip.com.au \
--cc=hch@infradead.org \
--cc=hugang@soulinfo.com \
--cc=linux-kernel@vger.kernel.org \
--cc=pavel@ucw.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox