aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeinz Mauelshagen <heinzm@redhat.com>2017-06-23 11:27:01 -0400
committerMike Snitzer <snitzer@redhat.com>2017-06-23 12:16:15 -0400
commitc4d097d13052d1e6f29b8798264aed6135d99568 (patch)
treed67e5acc7bbc9657e1814e4d71678d22fe853eda
parentfeb7695fe9fb83084aa29de0094774f4c9d4c9fc (diff)
dm raid: fix oops on upgrading to extended superblock format
When a RAID set was created on dm-raid version < 1.9.0 (old RAID superblock format), all of the new 1.9.0 members of the superblock are uninitialized (zero) -- including the device sectors member needed to support shrinking. All the other accesses to superblock fields new in 1.9.0 were reviewed and verified to be properly guarded against invalid use. The 'sectors' member was the only one used when the superblock version is < 1.9. Don't access the superblock's >= 1.9.0 'sectors' member unconditionally. Also add respective comments. Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
-rw-r--r--drivers/md/dm-raid.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 7d893228c40f..b4b75dad816a 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -1927,7 +1927,7 @@ struct dm_raid_superblock {
1927 /******************************************************************** 1927 /********************************************************************
1928 * BELOW FOLLOW V1.9.0 EXTENSIONS TO THE PRISTINE SUPERBLOCK FORMAT!!! 1928 * BELOW FOLLOW V1.9.0 EXTENSIONS TO THE PRISTINE SUPERBLOCK FORMAT!!!
1929 * 1929 *
1930 * FEATURE_FLAG_SUPPORTS_V190 in the features member indicates that those exist 1930 * FEATURE_FLAG_SUPPORTS_V190 in the compat_features member indicates that those exist
1931 */ 1931 */
1932 1932
1933 __le32 flags; /* Flags defining array states for reshaping */ 1933 __le32 flags; /* Flags defining array states for reshaping */
@@ -2092,6 +2092,11 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev)
2092 sb->layout = cpu_to_le32(mddev->layout); 2092 sb->layout = cpu_to_le32(mddev->layout);
2093 sb->stripe_sectors = cpu_to_le32(mddev->chunk_sectors); 2093 sb->stripe_sectors = cpu_to_le32(mddev->chunk_sectors);
2094 2094
2095 /********************************************************************
2096 * BELOW FOLLOW V1.9.0 EXTENSIONS TO THE PRISTINE SUPERBLOCK FORMAT!!!
2097 *
2098 * FEATURE_FLAG_SUPPORTS_V190 in the compat_features member indicates that those exist
2099 */
2095 sb->new_level = cpu_to_le32(mddev->new_level); 2100 sb->new_level = cpu_to_le32(mddev->new_level);
2096 sb->new_layout = cpu_to_le32(mddev->new_layout); 2101 sb->new_layout = cpu_to_le32(mddev->new_layout);
2097 sb->new_stripe_sectors = cpu_to_le32(mddev->new_chunk_sectors); 2102 sb->new_stripe_sectors = cpu_to_le32(mddev->new_chunk_sectors);
@@ -2438,8 +2443,14 @@ static int super_validate(struct raid_set *rs, struct md_rdev *rdev)
2438 mddev->bitmap_info.default_offset = mddev->bitmap_info.offset; 2443 mddev->bitmap_info.default_offset = mddev->bitmap_info.offset;
2439 2444
2440 if (!test_and_clear_bit(FirstUse, &rdev->flags)) { 2445 if (!test_and_clear_bit(FirstUse, &rdev->flags)) {
2441 /* Retrieve device size stored in superblock to be prepared for shrink */ 2446 /*
2442 rdev->sectors = le64_to_cpu(sb->sectors); 2447 * Retrieve rdev size stored in superblock to be prepared for shrink.
2448 * Check extended superblock members are present otherwise the size
2449 * will not be set!
2450 */
2451 if (le32_to_cpu(sb->compat_features) & FEATURE_FLAG_SUPPORTS_V190)
2452 rdev->sectors = le64_to_cpu(sb->sectors);
2453
2443 rdev->recovery_offset = le64_to_cpu(sb->disk_recovery_offset); 2454 rdev->recovery_offset = le64_to_cpu(sb->disk_recovery_offset);
2444 if (rdev->recovery_offset == MaxSector) 2455 if (rdev->recovery_offset == MaxSector)
2445 set_bit(In_sync, &rdev->flags); 2456 set_bit(In_sync, &rdev->flags);