md: Fix forward incompatibility from configurable logical block size

Commit 62ed1b582246 ("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: 62ed1b582246 ("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>

authored by Li Nan and committed by Yu Kuai a4166f1c 864466c3

Changed files
+44 -4
drivers
md
+44 -4
drivers/md/md.c
··· 5980 5980 if (mddev->major_version == 0) 5981 5981 return -EINVAL; 5982 5982 5983 - if (mddev->pers) 5984 - return -EBUSY; 5985 - 5986 5983 err = kstrtouint(buf, 10, &lbs); 5987 5984 if (err < 0) 5988 5985 return -EINVAL; 5986 + 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 + } 5989 6009 5990 6010 err = mddev_lock(mddev); 5991 6011 if (err) ··· 6182 6162 mdname(mddev)); 6183 6163 return -EINVAL; 6184 6164 } 6185 - mddev->logical_block_size = lim->logical_block_size; 6165 + 6166 + /* Only 1.x meta needs to set logical block size */ 6167 + if (mddev->major_version == 0) 6168 + return 0; 6169 + 6170 + /* 6171 + * Fix forward compatibility issue. Only set LBS by default for 6172 + * new arrays, mddev->events == 0 indicates the array was just 6173 + * created. When assembling an array, read LBS from the superblock 6174 + * instead — LBS is 0 in superblocks created by old kernels. 6175 + */ 6176 + if (!mddev->events) { 6177 + pr_info("%s: array will not be assembled in old kernels that lack configurable LBS support (<= 6.18)\n", 6178 + mdname(mddev)); 6179 + mddev->logical_block_size = lim->logical_block_size; 6180 + } 6181 + 6182 + if (!mddev->logical_block_size) 6183 + pr_warn("%s: echo current LBS to md/logical_block_size to prevent data loss issues from LBS changes.\n" 6184 + "\tNote: After setting, array will not be assembled in old kernels (<= 6.18)\n", 6185 + mdname(mddev)); 6186 6186 6187 6187 return 0; 6188 6188 }