* [PATCH 0/3] mtd: block2mtd: convert to folios
@ 2026-10-15 3:34 Tal Zussman
2026-10-15 3:34 ` [PATCH 1/3] mtd: block2mtd: convert block2mtd_read() " Tal Zussman
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Tal Zussman @ 2026-10-15 3:34 UTC (permalink / raw)
To: Joern Engel, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Matthew Wilcox (Oracle), linux-mtd, linux-kernel, Tal Zussman
block2mtd still goes through the page wrappers around the folio page
cache API, each of which hides a compound_head() call. Convert the read,
write and erase paths to use folios directly. This removes a
compound_head() call per page in the read path and four per page in the
write and erase paths, and leaves the driver with no struct page usage.
Tested on KVM with the MTD test modules and fsx/fsstress on UBIFS with
no errors.
The numbers below are from mtd_speedtest, in MiB/s, by folio size,
except the last row, which is from the MEMERASE ioctl:
+------------------------------+-------+--------+---------+---------+
| Test | Folio | Base | Patched | Change |
+------------------------------+-------+--------+---------+---------+
| Eraseblock read (128 KiB) | 4K | 12545 | 12863 | +2.5% |
| | 16K | 12998 | 17229 | +32.6% |
| | 64K | 13009 | 19135 | +47.1% |
+------------------------------+-------+--------+---------+---------+
| Eraseblock write (128 KiB) | 4K | 8773 | 8063 | noisy* |
| | 16K | 9529 | 13448 | +41.1% |
| | 64K | 9636 | 15934 | +65.4% |
+------------------------------+-------+--------+---------+---------+
| Page read (512 B) | 4K | 3332 | 3501 | +5.1% |
| | 16K | 3332 | 3462 | +3.9% |
| | 64K | 3330 | 3479 | +4.5% |
+------------------------------+-------+--------+---------+---------+
| Page write (512 B) | 4K | 2001 | 2054 | +2.6% |
| | 16K | 2000 | 2059 | +3.0% |
| | 64K | 2001 | 2064 | +3.1% |
+------------------------------+-------+--------+---------+---------+
| 2-page read (1 KiB) | 4K | 5262 | 5436 | +3.3% |
| | 16K | 5292 | 5327 | +0.7% |
| | 64K | 5312 | 5385 | +1.4% |
+------------------------------+-------+--------+---------+---------+
| 2-page write (1 KiB) | 4K | 3635 | 3712 | +2.1% |
| | 16K | 3650 | 3725 | +2.1% |
| | 64K | 3665 | 3768 | +2.8% |
+------------------------------+-------+--------+---------+---------+
| Erase, blocks hold data | 4K | 15013 | ~15900 | ~+6%* |
| (mtd_speedtest) | 16K | 15222 | 22849 | +50.1% |
| | 64K | 15280 | 24233 | +58.6% |
+------------------------------+-------+--------+---------+---------+
| Erase, already erased | 4K | 9558 | 13727 | +43.6% |
| (MEMERASE ioctl) | 16K | 9558 | 16580 | +73.5% |
| | 64K | 9626 | 17754 | +84.4% |
+------------------------------+-------+--------+---------+---------+
---
Tal Zussman (3):
mtd: block2mtd: convert block2mtd_read() to folios
mtd: block2mtd: convert _block2mtd_write() to folios
mtd: block2mtd: convert _block2mtd_erase() to folios
drivers/mtd/devices/block2mtd.c | 120 +++++++++++++++++-----------------------
1 file changed, 51 insertions(+), 69 deletions(-)
---
base-commit: 2f7fa8d90694d21dce68ceabd8383252b111cfea
change-id: 20261012-block2mtd-folio-9ccb6639c05a
Best regards,
--
Tal Zussman <tz2294@columbia.edu>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/3] mtd: block2mtd: convert block2mtd_read() to folios
2026-10-15 3:34 [PATCH 0/3] mtd: block2mtd: convert to folios Tal Zussman
@ 2026-10-15 3:34 ` Tal Zussman
2026-10-15 3:34 ` [PATCH 2/3] mtd: block2mtd: convert _block2mtd_write() " Tal Zussman
` (2 subsequent siblings)
3 siblings, 0 replies; 9+ messages in thread
From: Tal Zussman @ 2026-10-15 3:34 UTC (permalink / raw)
To: Joern Engel, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Matthew Wilcox (Oracle), linux-mtd, linux-kernel, Tal Zussman
Look the folio up with read_mapping_folio() instead of
read_mapping_page() and copy from it directly. This removes a hidden
compound_head() call per page.
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
drivers/mtd/devices/block2mtd.c | 28 +++++++++++-----------------
1 file changed, 11 insertions(+), 17 deletions(-)
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 03e80b2c4f5a..f28e49130197 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -106,30 +106,24 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
{
struct block2mtd_dev *dev = mtd->priv;
struct address_space *mapping = dev->bdev_file->f_mapping;
- struct page *page;
- pgoff_t index = from >> PAGE_SHIFT;
- int offset = from & (PAGE_SIZE-1);
- int cpylen;
+ struct folio *folio;
+ size_t offset, cpylen;
while (len) {
- if ((offset + len) > PAGE_SIZE)
- cpylen = PAGE_SIZE - offset; // multiple pages
- else
- cpylen = len; // this page
- len = len - cpylen;
-
- page = page_read(mapping, index);
- if (IS_ERR(page))
- return PTR_ERR(page);
+ folio = read_mapping_folio(mapping, from >> PAGE_SHIFT, NULL);
+ if (IS_ERR(folio))
+ return PTR_ERR(folio);
- memcpy(buf, page_address(page) + offset, cpylen);
- put_page(page);
+ offset = offset_in_folio(folio, from);
+ cpylen = min(len, folio_size(folio) - offset);
+ memcpy(buf, folio_address(folio) + offset, cpylen);
+ folio_put(folio);
if (retlen)
*retlen += cpylen;
buf += cpylen;
- offset = 0;
- index++;
+ from += cpylen;
+ len -= cpylen;
}
return 0;
}
--
2.39.5
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/3] mtd: block2mtd: convert _block2mtd_write() to folios
2026-10-15 3:34 [PATCH 0/3] mtd: block2mtd: convert to folios Tal Zussman
2026-10-15 3:34 ` [PATCH 1/3] mtd: block2mtd: convert block2mtd_read() " Tal Zussman
@ 2026-10-15 3:34 ` Tal Zussman
2026-10-15 3:34 ` [PATCH 3/3] mtd: block2mtd: convert _block2mtd_erase() " Tal Zussman
2026-10-15 18:39 ` [PATCH 0/3] mtd: block2mtd: convert " Jörn Engel
3 siblings, 0 replies; 9+ messages in thread
From: Tal Zussman @ 2026-10-15 3:34 UTC (permalink / raw)
To: Joern Engel, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Matthew Wilcox (Oracle), linux-mtd, linux-kernel, Tal Zussman
Write through a folio instead of a page, looking it up with
read_mapping_folio() instead of page_read(). This removes four hidden
compound_head() calls per page.
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
drivers/mtd/devices/block2mtd.c | 39 +++++++++++++++++----------------------
1 file changed, 17 insertions(+), 22 deletions(-)
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index f28e49130197..910669d6bb94 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -133,38 +133,33 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf,
loff_t to, size_t len, size_t *retlen)
{
- struct page *page;
struct address_space *mapping = dev->bdev_file->f_mapping;
- pgoff_t index = to >> PAGE_SHIFT; // page index
- int offset = to & ~PAGE_MASK; // page offset
- int cpylen;
+ struct folio *folio;
+ size_t offset, cpylen;
+ void *p;
while (len) {
- if ((offset+len) > PAGE_SIZE)
- cpylen = PAGE_SIZE - offset; // multiple pages
- else
- cpylen = len; // this page
- len = len - cpylen;
-
- page = page_read(mapping, index);
- if (IS_ERR(page))
- return PTR_ERR(page);
+ folio = read_mapping_folio(mapping, to >> PAGE_SHIFT, NULL);
+ if (IS_ERR(folio))
+ return PTR_ERR(folio);
- if (memcmp(page_address(page)+offset, buf, cpylen)) {
- lock_page(page);
- memcpy(page_address(page) + offset, buf, cpylen);
- set_page_dirty(page);
- unlock_page(page);
+ offset = offset_in_folio(folio, to);
+ cpylen = min(len, folio_size(folio) - offset);
+ p = folio_address(folio) + offset;
+ if (memcmp(p, buf, cpylen)) {
+ folio_lock(folio);
+ memcpy(p, buf, cpylen);
+ folio_mark_dirty(folio);
+ folio_unlock(folio);
balance_dirty_pages_ratelimited(mapping);
}
- put_page(page);
+ folio_put(folio);
if (retlen)
*retlen += cpylen;
-
buf += cpylen;
- offset = 0;
- index++;
+ to += cpylen;
+ len -= cpylen;
}
return 0;
}
--
2.39.5
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/3] mtd: block2mtd: convert _block2mtd_erase() to folios
2026-10-15 3:34 [PATCH 0/3] mtd: block2mtd: convert to folios Tal Zussman
2026-10-15 3:34 ` [PATCH 1/3] mtd: block2mtd: convert block2mtd_read() " Tal Zussman
2026-10-15 3:34 ` [PATCH 2/3] mtd: block2mtd: convert _block2mtd_write() " Tal Zussman
@ 2026-10-15 3:34 ` Tal Zussman
2026-10-15 3:45 ` sashiko-bot
2026-10-15 18:39 ` [PATCH 0/3] mtd: block2mtd: convert " Jörn Engel
3 siblings, 1 reply; 9+ messages in thread
From: Tal Zussman @ 2026-10-15 3:34 UTC (permalink / raw)
To: Joern Engel, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Matthew Wilcox (Oracle), linux-mtd, linux-kernel, Tal Zussman
Erase through a folio instead of a page, and use memchr_inv() to check
whether a range still needs erasing instead of the open-coded scan.
This removes four hidden compound_head() calls per page, and the last
user of page_read(), so remove that too.
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
---
drivers/mtd/devices/block2mtd.c | 51 ++++++++++++++++++-----------------------
1 file changed, 22 insertions(+), 29 deletions(-)
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 910669d6bb94..a1d24fef415d 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -47,40 +47,33 @@ struct block2mtd_dev {
static LIST_HEAD(blkmtd_device_list);
-static struct page *page_read(struct address_space *mapping, pgoff_t index)
-{
- return read_mapping_page(mapping, index, NULL);
-}
-
/* erase a specified part of the device */
static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len)
{
struct address_space *mapping = dev->bdev_file->f_mapping;
- struct page *page;
- pgoff_t index = to >> PAGE_SHIFT; // page index
- int pages = len >> PAGE_SHIFT;
- u_long *p;
- u_long *max;
-
- while (pages) {
- page = page_read(mapping, index);
- if (IS_ERR(page))
- return PTR_ERR(page);
-
- max = page_address(page) + PAGE_SIZE;
- for (p=page_address(page); p<max; p++)
- if (*p != -1UL) {
- lock_page(page);
- memset(page_address(page), 0xff, PAGE_SIZE);
- set_page_dirty(page);
- unlock_page(page);
- balance_dirty_pages_ratelimited(mapping);
- break;
- }
+ struct folio *folio;
+ size_t offset, chunk;
+ void *p;
+
+ while (len) {
+ folio = read_mapping_folio(mapping, to >> PAGE_SHIFT, NULL);
+ if (IS_ERR(folio))
+ return PTR_ERR(folio);
+
+ offset = offset_in_folio(folio, to);
+ chunk = min(len, folio_size(folio) - offset);
+ p = folio_address(folio) + offset;
+ if (memchr_inv(p, 0xff, chunk)) {
+ folio_lock(folio);
+ memset(p, 0xff, chunk);
+ folio_mark_dirty(folio);
+ folio_unlock(folio);
+ balance_dirty_pages_ratelimited(mapping);
+ }
+ folio_put(folio);
- put_page(page);
- pages--;
- index++;
+ to += chunk;
+ len -= chunk;
}
return 0;
}
--
2.39.5
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] mtd: block2mtd: convert _block2mtd_erase() to folios
2026-10-15 3:34 ` [PATCH 3/3] mtd: block2mtd: convert _block2mtd_erase() " Tal Zussman
@ 2026-10-15 3:45 ` sashiko-bot
2026-10-15 9:14 ` Miquel Raynal
0 siblings, 1 reply; 9+ messages in thread
From: sashiko-bot @ 2026-10-15 3:45 UTC (permalink / raw)
To: Tal Zussman, Joern Engel, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra
Cc: Matthew Wilcox (Oracle), linux-mtd
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] mm: missing folio->mapping re-validation after folio_lock()
--
commit 5d3ba379c345de78b1eb892e6685b2e8f75987f5
Author: Tal Zussman <tz2294@columbia.edu>
mtd: block2mtd: convert _block2mtd_erase() to folios
Erase through a folio instead of a page, and use memchr_inv() to check
whether a range still needs erasing instead of the open-coded scan.
This removes four hidden compound_head() calls per page, and the last
user of page_read(), so remove that too.
> diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
> index 910669d6bb943..a1d24fef415dd 100644
> --- a/drivers/mtd/devices/block2mtd.c
> +++ b/drivers/mtd/devices/block2mtd.c
[ ... ]
> /* erase a specified part of the device */
> static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len)
> {
> struct address_space *mapping = dev->bdev_file->f_mapping;
[ ... ]
> + while (len) {
> + folio = read_mapping_folio(mapping, to >> PAGE_SHIFT, NULL);
> + if (IS_ERR(folio))
> + return PTR_ERR(folio);
> +
> + offset = offset_in_folio(folio, to);
> + chunk = min(len, folio_size(folio) - offset);
> + p = folio_address(folio) + offset;
> + if (memchr_inv(p, 0xff, chunk)) {
> + folio_lock(folio);
> + memset(p, 0xff, chunk);
> + folio_mark_dirty(folio);
> + folio_unlock(folio);
[Severity: Medium]
Could _block2mtd_erase() modify a truncated folio here?
If the folio is truncated from the page cache while waiting for folio_lock(),
we could proceed with modifying the memory without it ever being written back
to the device. Should this re-validate that folio->mapping == mapping after
acquiring the lock?
> + balance_dirty_pages_ratelimited(mapping);
> + }
> + folio_put(folio);
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261014-block2mtd-folio-v1-0-19d24ae676ee@columbia.edu?part=3
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] mtd: block2mtd: convert _block2mtd_erase() to folios
2026-10-15 3:45 ` sashiko-bot
@ 2026-10-15 9:14 ` Miquel Raynal
2026-10-15 15:19 ` Tal Zussman
0 siblings, 1 reply; 9+ messages in thread
From: Miquel Raynal @ 2026-10-15 9:14 UTC (permalink / raw)
To: sashiko-bot
Cc: Tal Zussman, Joern Engel, Richard Weinberger, Vignesh Raghavendra,
sashiko-reviews, Matthew Wilcox, linux-mtd
Hi Tal,
On 15/10/2026 at 03:45:56 GMT, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] mm: missing folio->mapping re-validation after folio_lock()
TBH, I don't know the folio API so I'll let you determine whether this
is a real issue or not.
Miquèl
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] mtd: block2mtd: convert _block2mtd_erase() to folios
2026-10-15 9:14 ` Miquel Raynal
@ 2026-10-15 15:19 ` Tal Zussman
2026-10-15 18:34 ` Jörn Engel
0 siblings, 1 reply; 9+ messages in thread
From: Tal Zussman @ 2026-10-15 15:19 UTC (permalink / raw)
To: Miquel Raynal, sashiko-bot
Cc: Joern Engel, Richard Weinberger, Vignesh Raghavendra,
sashiko-reviews, Matthew Wilcox (Oracle), linux-mtd
On 10/15/26 5:14 AM, Miquel Raynal wrote:
> Hi Tal,
>
> On 15/10/2026 at 03:45:56 GMT, sashiko-bot@kernel.org wrote:
>
>> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>> - [Medium] mm: missing folio->mapping re-validation after folio_lock()
>
> TBH, I don't know the folio API so I'll let you determine whether this
> is a real issue or not.
>
> Miquèl
>
It seems like it's a real but very rare pre-existing issue. It would require
invalidate_mapping_pages() to be called between the read_mapping_folio() and
folio_lock(), which isn't something that should happen here on any normal
workload. In any case, the fix is to check the mapping and retry if the
check fails. I'll add a patch at the start of the series fixing this for
erase and write.
Thanks,
Tal
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] mtd: block2mtd: convert _block2mtd_erase() to folios
2026-10-15 15:19 ` Tal Zussman
@ 2026-10-15 18:34 ` Jörn Engel
0 siblings, 0 replies; 9+ messages in thread
From: Jörn Engel @ 2026-10-15 18:34 UTC (permalink / raw)
To: Tal Zussman
Cc: Miquel Raynal, sashiko-bot, Joern Engel, Richard Weinberger,
Vignesh Raghavendra, sashiko-reviews, Matthew Wilcox (Oracle),
linux-mtd
On Thu, Oct 15, 2026 at 11:19:23AM -0400, Tal Zussman wrote:
>
> It seems like it's a real but very rare pre-existing issue.
You should drop the "but very rare" bit. ;)
When it comes to bugs, being rare and hard to hit doesn't improve
things, it makes them worse. Rare bugs result in crazy bug reports that
you cannot reproduce. Instead of spending a few hours on them, they can
cost you days, weeks or months.
They are also often non-trivial to fix. Instead of taking a bug report
and saying "ah, here is the problem", several times I've had to come up
with new debug code, make it robust enough to ship into production
(because rare bugs only reproduce at scale, which means on production
systems), refine it once or twice and then finally get enough
information to fix the bug.
On the plus side, such debug infrastructure tends to provide enough
clues to fix many bugs, not just one troublemaker.
Jörn
--
The cost of changing business rules is much more expensive for software
than for a secretaty.
-- unknown
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/3] mtd: block2mtd: convert to folios
2026-10-15 3:34 [PATCH 0/3] mtd: block2mtd: convert to folios Tal Zussman
` (2 preceding siblings ...)
2026-10-15 3:34 ` [PATCH 3/3] mtd: block2mtd: convert _block2mtd_erase() " Tal Zussman
@ 2026-10-15 18:39 ` Jörn Engel
3 siblings, 0 replies; 9+ messages in thread
From: Jörn Engel @ 2026-10-15 18:39 UTC (permalink / raw)
To: Tal Zussman
Cc: Joern Engel, Miquel Raynal, Richard Weinberger,
Vignesh Raghavendra, Matthew Wilcox (Oracle), linux-mtd,
linux-kernel
On Wed, Oct 14, 2026 at 11:34:53PM -0400, Tal Zussman wrote:
>
> The numbers below are from mtd_speedtest, in MiB/s, by folio size,
> except the last row, which is from the MEMERASE ioctl:
>
> +------------------------------+-------+--------+---------+---------+
> | Test | Folio | Base | Patched | Change |
> +------------------------------+-------+--------+---------+---------+
> | Eraseblock read (128 KiB) | 4K | 12545 | 12863 | +2.5% |
> | | 16K | 12998 | 17229 | +32.6% |
> | | 64K | 13009 | 19135 | +47.1% |
> +------------------------------+-------+--------+---------+---------+
Thank you! Code size goes down, code seems subjectively easier to read
and performance goes up. Good stuff!
The one pet complaint I have is that benchmarks should measure badness,
not goodness. Humans tend to prioritize the big numbers. If you
measure the bad thing (time in this case), they focus on the worst areas
where most time is spent. If you measure the good thing, they tend to
improve things that are already too good to worry about even further.
Maybe you are immune to such psychological effects, but I am not and
measuring time instead of throughput makes a difference to my mind.
Jörn
--
The cheapest, fastest and most reliable components of a computer
system are those that aren't there.
-- Gordon Bell, DEC labratories
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-10-15 18:39 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-15 3:34 [PATCH 0/3] mtd: block2mtd: convert to folios Tal Zussman
2026-10-15 3:34 ` [PATCH 1/3] mtd: block2mtd: convert block2mtd_read() " Tal Zussman
2026-10-15 3:34 ` [PATCH 2/3] mtd: block2mtd: convert _block2mtd_write() " Tal Zussman
2026-10-15 3:34 ` [PATCH 3/3] mtd: block2mtd: convert _block2mtd_erase() " Tal Zussman
2026-10-15 3:45 ` sashiko-bot
2026-10-15 9:14 ` Miquel Raynal
2026-10-15 15:19 ` Tal Zussman
2026-10-15 18:34 ` Jörn Engel
2026-10-15 18:39 ` [PATCH 0/3] mtd: block2mtd: convert " Jörn Engel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.