diff options
author | NeilBrown <neilb@suse.de> | 2009-08-02 20:59:57 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2009-08-02 20:59:57 -0400 |
commit | 70471dafe3390243c598a3165dfb86b8b8b3f4fe (patch) | |
tree | febb8dfdbbb981370e1ea046714628bf6b790e5a /drivers | |
parent | 3673f305faf1bc66ead751344f8262ace851ff44 (diff) |
md: Handle growth of v1.x metadata correctly.
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.
Cc: stable@kernel.org
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/md.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 249b2896d4ea..52c988b072d0 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1399,8 +1399,14 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1399 | if (rdev2->desc_nr+1 > max_dev) | 1399 | if (rdev2->desc_nr+1 > max_dev) |
1400 | max_dev = rdev2->desc_nr+1; | 1400 | max_dev = rdev2->desc_nr+1; |
1401 | 1401 | ||
1402 | if (max_dev > le32_to_cpu(sb->max_dev)) | 1402 | if (max_dev > le32_to_cpu(sb->max_dev)) { |
1403 | int bmask; | ||
1403 | sb->max_dev = cpu_to_le32(max_dev); | 1404 | sb->max_dev = cpu_to_le32(max_dev); |
1405 | rdev->sb_size = max_dev * 2 + 256; | ||
1406 | bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1; | ||
1407 | if (rdev->sb_size & bmask) | ||
1408 | rdev->sb_size = (rdev->sb_size | bmask) + 1; | ||
1409 | } | ||
1404 | for (i=0; i<max_dev;i++) | 1410 | for (i=0; i<max_dev;i++) |
1405 | sb->dev_roles[i] = cpu_to_le16(0xfffe); | 1411 | sb->dev_roles[i] = cpu_to_le16(0xfffe); |
1406 | 1412 | ||