[packages/kernel/LINUX_6_18] md: read the logical_block_size superblock field written by 6.19+
arekm
arekm at pld-linux.org
Sun Aug 23 20:52:11 CEST 2026
commit 0ed6fb7e2a958cbd1129ea4ffeb565759584a8ab
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Sun Aug 23 19:01:27 2026 +0200
md: read the logical_block_size superblock field written by 6.19+
Arrays created under >= 6.19 carry it and were rejected here with a silent -EINVAL.
kernel-md-lbs-forward-compat.patch | 124 +++++++++++++++++++++++++++++++++++++
kernel.spec | 2 +
2 files changed, 126 insertions(+)
---
diff --git a/kernel.spec b/kernel.spec
index f6bb6215..84647e47 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -167,6 +167,7 @@ Patch500: kernel-rt.patch
Patch2000: kernel-small_fixes.patch
Patch2001: kernel-pwc-uncompress.patch
+Patch2002: kernel-md-lbs-forward-compat.patch
# for rescuecd
# based on ftp://ftp.leg.uct.ac.za/pub/linux/rip/tmpfs_root-2.6.30.diff.gz
@@ -596,6 +597,7 @@ rm -f localversion-rt
# Small fixes:
#patch -P2000 -p1
%patch -P2001 -p1
+%patch -P2002 -p1
chmod 755 tools/objtool/sync-check.sh
diff --git a/kernel-md-lbs-forward-compat.patch b/kernel-md-lbs-forward-compat.patch
new file mode 100644
index 00000000..7aa27162
--- /dev/null
+++ b/kernel-md-lbs-forward-compat.patch
@@ -0,0 +1,124 @@
+Subject: md: understand the logical_block_size superblock field
+
+Kernels >= 6.19 carve logical_block_size out of mdp_superblock_1.pad3
+(upstream 62ed1b582246 "md: allow configuring logical block size") and
+record it in every array they create, as well as in any array whose
+logical block size an admin pins through md/logical_block_size. Kernels
+of this vintage reject any superblock with non-zero padding in
+super_1_load(), so such an array does not assemble here at all:
+
+ md: sdb4 does not have a valid v1.2 superblock, not importing!
+ md: md_import_device returned -22
+
+mdadm --examine calls the superblock healthy and nothing is logged, so
+the failure reads like broken disks. Upstream treats it as expected
+(a4166f1c4893): a kernel that does not know the field would assemble the
+array with a different logical block size and lose data.
+
+So learn the field rather than ignore it. Backport the metadata-reading
+half of 62ed1b582246: the recorded size is followed when stacking queue
+limits, exactly as >= 6.19 does, so the array comes up with the same
+logical block size on both. That is what makes assembling it here safe.
+The field is deliberately never introduced here and there is no sysfs
+knob to set it - this kernel only follows what a newer one recorded.
+
+Also give the padding check a pr_warn (from upstream 9c47127a807d) so the
+next forward-incompatible feature is diagnosable rather than silent.
+
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -1866,9 +1866,12 @@
+ }
+ if (sb->pad0 ||
+ sb->pad3[0] ||
+- memcmp(sb->pad3, sb->pad3+1, sizeof(sb->pad3) - sizeof(sb->pad3[1])))
++ memcmp(sb->pad3, sb->pad3+1, sizeof(sb->pad3) - sizeof(sb->pad3[1]))) {
+ /* Some padding is non-zero, might be a new feature */
++ pr_warn("md: some padding is non-zero on %pg, might be a new feature\n",
++ rdev->bdev);
+ return -EINVAL;
++ }
+
+ rdev->preferred_minor = 0xffff;
+ rdev->data_offset = le64_to_cpu(sb->data_offset);
+@@ -2009,6 +2012,7 @@
+ mddev->layout = le32_to_cpu(sb->layout);
+ mddev->raid_disks = le32_to_cpu(sb->raid_disks);
+ mddev->dev_sectors = le64_to_cpu(sb->size);
++ mddev->logical_block_size = le32_to_cpu(sb->logical_block_size);
+ mddev->events = ev1;
+ mddev->bitmap_info.offset = 0;
+ mddev->bitmap_info.space = 0;
+@@ -2218,6 +2222,13 @@
+ sb->chunksize = cpu_to_le32(mddev->chunk_sectors);
+ sb->level = cpu_to_le32(mddev->level);
+ sb->layout = cpu_to_le32(mddev->layout);
++ /*
++ * Keep an already recorded size in sync across members, but never
++ * record one here: kernels that do not know this field reject every
++ * superblock whose padding is non-zero.
++ */
++ if (mddev->logical_block_size)
++ sb->logical_block_size = cpu_to_le32(mddev->logical_block_size);
+ if (test_bit(FailFast, &rdev->flags))
+ sb->devflags |= FailFast1;
+ else
+@@ -6098,6 +6109,14 @@
+ {
+ struct md_rdev *rdev;
+
++ /*
++ * Honour the size recorded by a newer kernel so the array comes up
++ * with the same logical block size there and here. Members can only
++ * raise it further, exactly as on those kernels.
++ */
++ if (mddev->logical_block_size > lim->logical_block_size)
++ lim->logical_block_size = mddev->logical_block_size;
++
+ rdev_for_each(rdev, mddev) {
+ queue_limits_stack_bdev(lim, rdev->bdev, rdev->data_offset,
+ mddev->gendisk->disk_name);
+@@ -6106,6 +6125,13 @@
+ return -EINVAL;
+ }
+
++ /* metadata I/O is done in single pages, so it cannot exceed one */
++ if (lim->logical_block_size > PAGE_SIZE) {
++ pr_err("%s: logical_block_size must not be larger than PAGE_SIZE\n",
++ mdname(mddev));
++ return -EINVAL;
++ }
++
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(mddev_stack_rdev_limits);
+@@ -6860,6 +6886,7 @@
+ mddev->chunk_sectors = 0;
+ mddev->ctime = mddev->utime = 0;
+ mddev->layout = 0;
++ mddev->logical_block_size = 0;
+ mddev->max_disks = 0;
+ mddev->events = 0;
+ mddev->can_decrease_events = 0;
+--- a/drivers/md/md.h
++++ b/drivers/md/md.h
+@@ -439,6 +439,7 @@
+ sector_t array_sectors; /* exported array size */
+ int external_size; /* size managed
+ * externally */
++ unsigned int logical_block_size;
+ __u64 events;
+ /* If the last 'event' was simply a clean->dirty transition, and
+ * we didn't write it to the spares, then it is safe and simple
+--- a/include/uapi/linux/raid/md_p.h
++++ b/include/uapi/linux/raid/md_p.h
+@@ -291,7 +291,8 @@
+ __le64 resync_offset; /* data before this offset (from data_offset) known to be in sync */
+ __le32 sb_csum; /* checksum up to devs[max_dev] */
+ __le32 max_dev; /* size of devs[] array to consider */
+- __u8 pad3[64-32]; /* set to 0 when writing */
++ __le32 logical_block_size; /* same as q->limits->logical_block_size */
++ __u8 pad3[64-36]; /* set to 0 when writing */
+
+ /* device state information. Indexed by dev_number.
+ * 2 bytes per device
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/kernel.git/commitdiff/907ddb8f153c34d50903538ba5efa5750a8c0c64
More information about the pld-cvs-commit
mailing list