summaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-raid.c
diff options
context:
space:
mode:
authorJonathan Brassow <jbrassow@redhat.com>2013-04-23 21:42:43 -0400
committerNeilBrown <neilb@suse.de>2013-04-23 21:42:43 -0400
commitbe83651f0050ca8621d58d35dad558e9c45cb18f (patch)
treede79ac9ee9ccc36816a346987024865e72760528 /drivers/md/dm-raid.c
parenta91d5ac04841ca1be340e8610e6d899fc8b419b5 (diff)
DM RAID: Add message/status support for changing sync action
DM RAID: Add message/status support for changing sync action This patch adds a message interface to dm-raid to allow the user to more finely control the sync actions being performed by the MD driver. This gives the user the ability to initiate "check" and "repair" (i.e. scrubbing). Two additional fields have been appended to the status output to provide more information about the type of sync action occurring and the results of those actions, specifically: <sync_action> and <mismatch_cnt>. These new fields will always be populated. This is essentially the device-mapper way of doing what MD controls through the 'sync_action' sysfs file and shows through the 'mismatch_cnt' sysfs file. Signed-off-by: Jonathan Brassow <jbrassow@redhat.com> Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/dm-raid.c')
-rw-r--r--drivers/md/dm-raid.c111
1 files changed, 109 insertions, 2 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 311e3d35b272..1d3fe1a40a9b 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -1279,6 +1279,31 @@ static int raid_map(struct dm_target *ti, struct bio *bio)
1279 return DM_MAPIO_SUBMITTED; 1279 return DM_MAPIO_SUBMITTED;
1280} 1280}
1281 1281
1282static const char *decipher_sync_action(struct mddev *mddev)
1283{
1284 if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
1285 return "frozen";
1286
1287 if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
1288 (!mddev->ro && test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))) {
1289 if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
1290 return "reshape";
1291
1292 if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
1293 if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
1294 return "resync";
1295 else if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
1296 return "check";
1297 return "repair";
1298 }
1299
1300 if (test_bit(MD_RECOVERY_RECOVER, &mddev->recovery))
1301 return "recover";
1302 }
1303
1304 return "idle";
1305}
1306
1282static void raid_status(struct dm_target *ti, status_type_t type, 1307static void raid_status(struct dm_target *ti, status_type_t type,
1283 unsigned status_flags, char *result, unsigned maxlen) 1308 unsigned status_flags, char *result, unsigned maxlen)
1284{ 1309{
@@ -1298,8 +1323,18 @@ static void raid_status(struct dm_target *ti, status_type_t type,
1298 sync = rs->md.recovery_cp; 1323 sync = rs->md.recovery_cp;
1299 1324
1300 if (sync >= rs->md.resync_max_sectors) { 1325 if (sync >= rs->md.resync_max_sectors) {
1326 /*
1327 * Sync complete.
1328 */
1301 array_in_sync = 1; 1329 array_in_sync = 1;
1302 sync = rs->md.resync_max_sectors; 1330 sync = rs->md.resync_max_sectors;
1331 } else if (test_bit(MD_RECOVERY_REQUESTED, &rs->md.recovery)) {
1332 /*
1333 * If "check" or "repair" is occurring, the array has
1334 * undergone and initial sync and the health characters
1335 * should not be 'a' anymore.
1336 */
1337 array_in_sync = 1;
1303 } else { 1338 } else {
1304 /* 1339 /*
1305 * The array may be doing an initial sync, or it may 1340 * The array may be doing an initial sync, or it may
@@ -1311,6 +1346,7 @@ static void raid_status(struct dm_target *ti, status_type_t type,
1311 if (!test_bit(In_sync, &rs->dev[i].rdev.flags)) 1346 if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
1312 array_in_sync = 1; 1347 array_in_sync = 1;
1313 } 1348 }
1349
1314 /* 1350 /*
1315 * Status characters: 1351 * Status characters:
1316 * 'D' = Dead/Failed device 1352 * 'D' = Dead/Failed device
@@ -1339,6 +1375,21 @@ static void raid_status(struct dm_target *ti, status_type_t type,
1339 (unsigned long long) sync, 1375 (unsigned long long) sync,
1340 (unsigned long long) rs->md.resync_max_sectors); 1376 (unsigned long long) rs->md.resync_max_sectors);
1341 1377
1378 /*
1379 * Sync action:
1380 * See Documentation/device-mapper/dm-raid.c for
1381 * information on each of these states.
1382 */
1383 DMEMIT(" %s", decipher_sync_action(&rs->md));
1384
1385 /*
1386 * resync_mismatches/mismatch_cnt
1387 * This field shows the number of discrepancies found when
1388 * performing a "check" of the array.
1389 */
1390 DMEMIT(" %llu",
1391 (unsigned long long)
1392 atomic64_read(&rs->md.resync_mismatches));
1342 break; 1393 break;
1343 case STATUSTYPE_TABLE: 1394 case STATUSTYPE_TABLE:
1344 /* The string you would use to construct this array */ 1395 /* The string you would use to construct this array */
@@ -1425,7 +1476,62 @@ static void raid_status(struct dm_target *ti, status_type_t type,
1425 } 1476 }
1426} 1477}
1427 1478
1428static int raid_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) 1479static int raid_message(struct dm_target *ti, unsigned argc, char **argv)
1480{
1481 struct raid_set *rs = ti->private;
1482 struct mddev *mddev = &rs->md;
1483
1484 if (!strcasecmp(argv[0], "reshape")) {
1485 DMERR("Reshape not supported.");
1486 return -EINVAL;
1487 }
1488
1489 if (!mddev->pers || !mddev->pers->sync_request)
1490 return -EINVAL;
1491
1492 if (!strcasecmp(argv[0], "frozen"))
1493 set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
1494 else
1495 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
1496
1497 if (!strcasecmp(argv[0], "idle") || !strcasecmp(argv[0], "frozen")) {
1498 if (mddev->sync_thread) {
1499 set_bit(MD_RECOVERY_INTR, &mddev->recovery);
1500 md_reap_sync_thread(mddev);
1501 }
1502 } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
1503 test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
1504 return -EBUSY;
1505 else if (!strcasecmp(argv[0], "resync"))
1506 set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
1507 else if (!strcasecmp(argv[0], "recover")) {
1508 set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
1509 set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
1510 } else {
1511 if (!strcasecmp(argv[0], "check"))
1512 set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
1513 else if (!!strcasecmp(argv[0], "repair"))
1514 return -EINVAL;
1515 set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
1516 set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
1517 }
1518 if (mddev->ro == 2) {
1519 /* A write to sync_action is enough to justify
1520 * canceling read-auto mode
1521 */
1522 mddev->ro = 0;
1523 if (!mddev->suspended)
1524 md_wakeup_thread(mddev->sync_thread);
1525 }
1526 set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
1527 if (!mddev->suspended)
1528 md_wakeup_thread(mddev->thread);
1529
1530 return 0;
1531}
1532
1533static int raid_iterate_devices(struct dm_target *ti,
1534 iterate_devices_callout_fn fn, void *data)
1429{ 1535{
1430 struct raid_set *rs = ti->private; 1536 struct raid_set *rs = ti->private;
1431 unsigned i; 1537 unsigned i;
@@ -1482,12 +1588,13 @@ static void raid_resume(struct dm_target *ti)
1482 1588
1483static struct target_type raid_target = { 1589static struct target_type raid_target = {
1484 .name = "raid", 1590 .name = "raid",
1485 .version = {1, 4, 2}, 1591 .version = {1, 5, 0},
1486 .module = THIS_MODULE, 1592 .module = THIS_MODULE,
1487 .ctr = raid_ctr, 1593 .ctr = raid_ctr,
1488 .dtr = raid_dtr, 1594 .dtr = raid_dtr,
1489 .map = raid_map, 1595 .map = raid_map,
1490 .status = raid_status, 1596 .status = raid_status,
1597 .message = raid_message,
1491 .iterate_devices = raid_iterate_devices, 1598 .iterate_devices = raid_iterate_devices,
1492 .io_hints = raid_io_hints, 1599 .io_hints = raid_io_hints,
1493 .presuspend = raid_presuspend, 1600 .presuspend = raid_presuspend,