diff options
author | Heinz Mauelshagen <heinzm@redhat.com> | 2016-05-19 12:49:32 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2016-06-14 17:09:35 -0400 |
commit | 7b34df74d27b2a2350426daec80cda5d3c873622 (patch) | |
tree | 3a518bf2edc5e9458ebd120e3e102e055a859e38 /drivers/md/dm-raid.c | |
parent | 4763e543a679053be345e1129bcb5df78f849294 (diff) |
dm raid: enhance super_sync() to support new superblock members
Add transferring the new takeover/reshape related superblock
members introduced to the super_sync() function:
- add/move supporting functions
- add failed devices bitfield transfer functions to retrieve the
bitfield from superblock format or update it in the superblock
- add code to transfer all new members
Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-raid.c')
-rw-r--r-- | drivers/md/dm-raid.c | 75 |
1 files changed, 65 insertions, 10 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index bc5a53dfaa07..28420337f880 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -214,6 +214,12 @@ static bool _test_flags(uint32_t flags, uint32_t all_flags) | |||
214 | return (flags & all_flags) ? true : false; | 214 | return (flags & all_flags) ? true : false; |
215 | } | 215 | } |
216 | 216 | ||
217 | /* Clear (multiple) @flags in @all_flags */ | ||
218 | static void _clear_flags(uint32_t flags, uint32_t *all_flags) | ||
219 | { | ||
220 | *all_flags &= ~flags; | ||
221 | } | ||
222 | |||
217 | /* Return true if single @flag is set in @*flags, else set it and return false */ | 223 | /* Return true if single @flag is set in @*flags, else set it and return false */ |
218 | static bool _test_and_set_flag(uint32_t flag, uint32_t *flags) | 224 | static bool _test_and_set_flag(uint32_t flag, uint32_t *flags) |
219 | { | 225 | { |
@@ -1289,31 +1295,54 @@ static void sb_retrieve_failed_devices(struct dm_raid_superblock *sb, uint64_t * | |||
1289 | } | 1295 | } |
1290 | } | 1296 | } |
1291 | 1297 | ||
1298 | static void sb_update_failed_devices(struct dm_raid_superblock *sb, uint64_t *failed_devices) | ||
1299 | { | ||
1300 | int i = ARRAY_SIZE(sb->extended_failed_devices); | ||
1301 | |||
1302 | sb->failed_devices = cpu_to_le64(failed_devices[0]); | ||
1303 | while (i--) | ||
1304 | sb->extended_failed_devices[i] = cpu_to_le64(failed_devices[i+1]); | ||
1305 | } | ||
1306 | |||
1307 | /* | ||
1308 | * Synchronize the superblock members with the raid set properties | ||
1309 | * | ||
1310 | * All superblock data is little endian. | ||
1311 | */ | ||
1292 | static void super_sync(struct mddev *mddev, struct md_rdev *rdev) | 1312 | static void super_sync(struct mddev *mddev, struct md_rdev *rdev) |
1293 | { | 1313 | { |
1294 | int i; | 1314 | bool update_failed_devices = false; |
1295 | uint64_t failed_devices; | 1315 | unsigned int i; |
1316 | uint64_t failed_devices[DISKS_ARRAY_ELEMS]; | ||
1296 | struct dm_raid_superblock *sb; | 1317 | struct dm_raid_superblock *sb; |
1297 | struct raid_set *rs = container_of(mddev, struct raid_set, md); | 1318 | struct raid_set *rs = container_of(mddev, struct raid_set, md); |
1298 | 1319 | ||
1320 | /* No metadata device, no superblock */ | ||
1321 | if (!rdev->meta_bdev) | ||
1322 | return; | ||
1323 | |||
1324 | BUG_ON(!rdev->sb_page); | ||
1325 | |||
1299 | sb = page_address(rdev->sb_page); | 1326 | sb = page_address(rdev->sb_page); |
1300 | failed_devices = le64_to_cpu(sb->failed_devices); | ||
1301 | 1327 | ||
1302 | for (i = 0; i < mddev->raid_disks; i++) | 1328 | sb_retrieve_failed_devices(sb, failed_devices); |
1303 | if (!rs->dev[i].data_dev || | ||
1304 | test_bit(Faulty, &(rs->dev[i].rdev.flags))) | ||
1305 | failed_devices |= (1ULL << i); | ||
1306 | 1329 | ||
1307 | memset(sb + 1, 0, rdev->sb_size - sizeof(*sb)); | 1330 | for (i = 0; i < rs->raid_disks; i++) |
1331 | if (!rs->dev[i].data_dev || test_bit(Faulty, &rs->dev[i].rdev.flags)) { | ||
1332 | update_failed_devices = true; | ||
1333 | set_bit(i, (void *) failed_devices); | ||
1334 | } | ||
1335 | |||
1336 | if (update_failed_devices) | ||
1337 | sb_update_failed_devices(sb, failed_devices); | ||
1308 | 1338 | ||
1309 | sb->magic = cpu_to_le32(DM_RAID_MAGIC); | 1339 | sb->magic = cpu_to_le32(DM_RAID_MAGIC); |
1310 | sb->compat_features = cpu_to_le32(0); /* No features yet */ | 1340 | sb->compat_features = cpu_to_le32(0); /* Don't set reshape flag yet */ |
1311 | 1341 | ||
1312 | sb->num_devices = cpu_to_le32(mddev->raid_disks); | 1342 | sb->num_devices = cpu_to_le32(mddev->raid_disks); |
1313 | sb->array_position = cpu_to_le32(rdev->raid_disk); | 1343 | sb->array_position = cpu_to_le32(rdev->raid_disk); |
1314 | 1344 | ||
1315 | sb->events = cpu_to_le64(mddev->events); | 1345 | sb->events = cpu_to_le64(mddev->events); |
1316 | sb->failed_devices = cpu_to_le64(failed_devices); | ||
1317 | 1346 | ||
1318 | sb->disk_recovery_offset = cpu_to_le64(rdev->recovery_offset); | 1347 | sb->disk_recovery_offset = cpu_to_le64(rdev->recovery_offset); |
1319 | sb->array_resync_offset = cpu_to_le64(mddev->recovery_cp); | 1348 | sb->array_resync_offset = cpu_to_le64(mddev->recovery_cp); |
@@ -1321,6 +1350,32 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev) | |||
1321 | sb->level = cpu_to_le32(mddev->level); | 1350 | sb->level = cpu_to_le32(mddev->level); |
1322 | sb->layout = cpu_to_le32(mddev->layout); | 1351 | sb->layout = cpu_to_le32(mddev->layout); |
1323 | sb->stripe_sectors = cpu_to_le32(mddev->chunk_sectors); | 1352 | sb->stripe_sectors = cpu_to_le32(mddev->chunk_sectors); |
1353 | |||
1354 | sb->new_level = cpu_to_le32(mddev->new_level); | ||
1355 | sb->new_layout = cpu_to_le32(mddev->new_layout); | ||
1356 | sb->new_stripe_sectors = cpu_to_le32(mddev->new_chunk_sectors); | ||
1357 | |||
1358 | sb->delta_disks = cpu_to_le32(mddev->delta_disks); | ||
1359 | |||
1360 | smp_rmb(); /* Make sure we access most recent reshape position */ | ||
1361 | sb->reshape_position = cpu_to_le64(mddev->reshape_position); | ||
1362 | if (le64_to_cpu(sb->reshape_position) != MaxSector) { | ||
1363 | /* Flag ongoing reshape */ | ||
1364 | sb->flags |= cpu_to_le32(SB_FLAG_RESHAPE_ACTIVE); | ||
1365 | |||
1366 | if (mddev->delta_disks < 0 || mddev->reshape_backwards) | ||
1367 | sb->flags |= cpu_to_le32(SB_FLAG_RESHAPE_BACKWARDS); | ||
1368 | } else | ||
1369 | /* Flag no reshape */ | ||
1370 | _clear_flags(cpu_to_le32(SB_FLAG_RESHAPE_ACTIVE|SB_FLAG_RESHAPE_BACKWARDS), &sb->flags); | ||
1371 | |||
1372 | sb->array_sectors = cpu_to_le64(mddev->array_sectors); | ||
1373 | sb->data_offset = cpu_to_le64(rdev->data_offset); | ||
1374 | sb->new_data_offset = cpu_to_le64(rdev->new_data_offset); | ||
1375 | sb->sectors = cpu_to_le64(rdev->sectors); | ||
1376 | |||
1377 | /* Zero out the rest of the payload after the size of the superblock */ | ||
1378 | memset(sb + 1, 0, rdev->sb_size - sizeof(*sb)); | ||
1324 | } | 1379 | } |
1325 | 1380 | ||
1326 | /* | 1381 | /* |