aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2009-08-06 15:53:57 +1000
committerGreg Kroah-Hartman <gregkh@suse.de>2009-08-16 14:18:57 -0700
commitf3b3108f63f7a25f21335555bec0929d6ea3f327 (patch)
tree7fa040d0647968c93e6868d2153b5f3f8dde9687
parent731663efa41227703ec74f82233215ce7194bc1d (diff)
md: Handle growth of v1.x metadata correctly.
commit 70471dafe3390243c598a3165dfb86b8b8b3f4fe upstream. The v1.x metadata does not have a fixed size and can grow when devices are added. If it grows enough to require an extra sector of storage, we need to update the 'sb_size' to match. Without this, md can write out an incomplete superblock with a bad checksum, which will be rejected when trying to re-assemble the array. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/md/md.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 6021dea894d..751a315caa5 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1410,8 +1410,14 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
if (rdev2->desc_nr+1 > max_dev)
max_dev = rdev2->desc_nr+1;
- if (max_dev > le32_to_cpu(sb->max_dev))
+ if (max_dev > le32_to_cpu(sb->max_dev)) {
+ int bmask;
sb->max_dev = cpu_to_le32(max_dev);
+ rdev->sb_size = max_dev * 2 + 256;
+ bmask = queue_hardsect_size(rdev->bdev->bd_disk->queue)-1;
+ if (rdev->sb_size & bmask)
+ rdev->sb_size = (rdev->sb_size | bmask) + 1;
+ }
for (i=0; i<max_dev;i++)
sb->dev_roles[i] = cpu_to_le16(0xfffe);