Skip to content

Commit a4166f1

Browse files
Li Nanhailan94
authored andcommitted
md: Fix forward incompatibility from configurable logical block size
Commit 62ed1b5 ("md: allow configuring logical block size") used reserved pad to add 'logical_block_size' to metadata. RAID rejects non-zero reserved pad, so arrays fail when rolling back to old kernels after booting new ones. Set 'logical_block_size' only for newly created arrays to support rollback to old kernels. Importantly new arrays still won't work on old kernels to prevent data loss issue from LBS changes. For arrays created on old kernels which confirmed not to rollback, configure LBS by echo current LBS (queue/logical_block_size) to md/logical_block_size. Fixes: 62ed1b5 ("md: allow configuring logical block size") Reported-by: BugReports <bugreports61@gmail.com> Closes: https://lore.kernel.org/linux-raid/825e532d-d1e1-44bb-5581-692b7c091796@huaweicloud.com/T/#t Signed-off-by: Li Nan <linan122@huawei.com> Link: https://lore.kernel.org/linux-raid/20251226024221.724201-2-linan666@huaweicloud.com Signed-off-by: Yu Kuai <yukuai@fnnas.com>
1 parent 864466c commit a4166f1

1 file changed

Lines changed: 44 additions & 4 deletions

File tree

drivers/md/md.c

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5980,13 +5980,33 @@ lbs_store(struct mddev *mddev, const char *buf, size_t len)
59805980
if (mddev->major_version == 0)
59815981
return -EINVAL;
59825982

5983-
if (mddev->pers)
5984-
return -EBUSY;
5985-
59865983
err = kstrtouint(buf, 10, &lbs);
59875984
if (err < 0)
59885985
return -EINVAL;
59895986

5987+
if (mddev->pers) {
5988+
unsigned int curr_lbs;
5989+
5990+
if (mddev->logical_block_size)
5991+
return -EBUSY;
5992+
/*
5993+
* To fix forward compatibility issues, LBS is not
5994+
* configured for arrays from old kernels (<=6.18) by default.
5995+
* If the user confirms no rollback to old kernels,
5996+
* enable LBS by writing current LBS — to prevent data
5997+
* loss from LBS changes.
5998+
*/
5999+
curr_lbs = queue_logical_block_size(mddev->gendisk->queue);
6000+
if (lbs != curr_lbs)
6001+
return -EINVAL;
6002+
6003+
mddev->logical_block_size = curr_lbs;
6004+
set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
6005+
pr_info("%s: logical block size configured successfully, array will not be assembled in old kernels (<= 6.18)\n",
6006+
mdname(mddev));
6007+
return len;
6008+
}
6009+
59906010
err = mddev_lock(mddev);
59916011
if (err)
59926012
goto unlock;
@@ -6162,7 +6182,27 @@ int mddev_stack_rdev_limits(struct mddev *mddev, struct queue_limits *lim,
61626182
mdname(mddev));
61636183
return -EINVAL;
61646184
}
6165-
mddev->logical_block_size = lim->logical_block_size;
6185+
6186+
/* Only 1.x meta needs to set logical block size */
6187+
if (mddev->major_version == 0)
6188+
return 0;
6189+
6190+
/*
6191+
* Fix forward compatibility issue. Only set LBS by default for
6192+
* new arrays, mddev->events == 0 indicates the array was just
6193+
* created. When assembling an array, read LBS from the superblock
6194+
* instead — LBS is 0 in superblocks created by old kernels.
6195+
*/
6196+
if (!mddev->events) {
6197+
pr_info("%s: array will not be assembled in old kernels that lack configurable LBS support (<= 6.18)\n",
6198+
mdname(mddev));
6199+
mddev->logical_block_size = lim->logical_block_size;
6200+
}
6201+
6202+
if (!mddev->logical_block_size)
6203+
pr_warn("%s: echo current LBS to md/logical_block_size to prevent data loss issues from LBS changes.\n"
6204+
"\tNote: After setting, array will not be assembled in old kernels (<= 6.18)\n",
6205+
mdname(mddev));
61666206

61676207
return 0;
61686208
}

0 commit comments

Comments
 (0)