Merge tag 'trace-fixes-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/rosted...
[deliverable/linux.git] / drivers / md / dm-raid.c
index 311e3d35b272e4ae30fa32b3bca9f567394896ef..1d3fe1a40a9bfdaea27bdaeb44208443f08f2d95 100644 (file)
@@ -1279,6 +1279,31 @@ static int raid_map(struct dm_target *ti, struct bio *bio)
        return DM_MAPIO_SUBMITTED;
 }
 
+static const char *decipher_sync_action(struct mddev *mddev)
+{
+       if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
+               return "frozen";
+
+       if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
+           (!mddev->ro && test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))) {
+               if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
+                       return "reshape";
+
+               if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+                       if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
+                               return "resync";
+                       else if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
+                               return "check";
+                       return "repair";
+               }
+
+               if (test_bit(MD_RECOVERY_RECOVER, &mddev->recovery))
+                       return "recover";
+       }
+
+       return "idle";
+}
+
 static void raid_status(struct dm_target *ti, status_type_t type,
                        unsigned status_flags, char *result, unsigned maxlen)
 {
@@ -1298,8 +1323,18 @@ static void raid_status(struct dm_target *ti, status_type_t type,
                        sync = rs->md.recovery_cp;
 
                if (sync >= rs->md.resync_max_sectors) {
+                       /*
+                        * Sync complete.
+                        */
                        array_in_sync = 1;
                        sync = rs->md.resync_max_sectors;
+               } else if (test_bit(MD_RECOVERY_REQUESTED, &rs->md.recovery)) {
+                       /*
+                        * If "check" or "repair" is occurring, the array has
+                        * undergone and initial sync and the health characters
+                        * should not be 'a' anymore.
+                        */
+                       array_in_sync = 1;
                } else {
                        /*
                         * 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,
                                if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
                                        array_in_sync = 1;
                }
+
                /*
                 * Status characters:
                 *  'D' = Dead/Failed device
@@ -1339,6 +1375,21 @@ static void raid_status(struct dm_target *ti, status_type_t type,
                       (unsigned long long) sync,
                       (unsigned long long) rs->md.resync_max_sectors);
 
+               /*
+                * Sync action:
+                *   See Documentation/device-mapper/dm-raid.c for
+                *   information on each of these states.
+                */
+               DMEMIT(" %s", decipher_sync_action(&rs->md));
+
+               /*
+                * resync_mismatches/mismatch_cnt
+                *   This field shows the number of discrepancies found when
+                *   performing a "check" of the array.
+                */
+               DMEMIT(" %llu",
+                      (unsigned long long)
+                      atomic64_read(&rs->md.resync_mismatches));
                break;
        case STATUSTYPE_TABLE:
                /* 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,
        }
 }
 
-static int raid_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data)
+static int raid_message(struct dm_target *ti, unsigned argc, char **argv)
+{
+       struct raid_set *rs = ti->private;
+       struct mddev *mddev = &rs->md;
+
+       if (!strcasecmp(argv[0], "reshape")) {
+               DMERR("Reshape not supported.");
+               return -EINVAL;
+       }
+
+       if (!mddev->pers || !mddev->pers->sync_request)
+               return -EINVAL;
+
+       if (!strcasecmp(argv[0], "frozen"))
+               set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+       else
+               clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+
+       if (!strcasecmp(argv[0], "idle") || !strcasecmp(argv[0], "frozen")) {
+               if (mddev->sync_thread) {
+                       set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+                       md_reap_sync_thread(mddev);
+               }
+       } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
+                  test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
+               return -EBUSY;
+       else if (!strcasecmp(argv[0], "resync"))
+               set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+       else if (!strcasecmp(argv[0], "recover")) {
+               set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
+               set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+       } else {
+               if (!strcasecmp(argv[0], "check"))
+                       set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+               else if (!!strcasecmp(argv[0], "repair"))
+                       return -EINVAL;
+               set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
+               set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+       }
+       if (mddev->ro == 2) {
+               /* A write to sync_action is enough to justify
+                * canceling read-auto mode
+                */
+               mddev->ro = 0;
+               if (!mddev->suspended)
+                       md_wakeup_thread(mddev->sync_thread);
+       }
+       set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+       if (!mddev->suspended)
+               md_wakeup_thread(mddev->thread);
+
+       return 0;
+}
+
+static int raid_iterate_devices(struct dm_target *ti,
+                               iterate_devices_callout_fn fn, void *data)
 {
        struct raid_set *rs = ti->private;
        unsigned i;
@@ -1482,12 +1588,13 @@ static void raid_resume(struct dm_target *ti)
 
 static struct target_type raid_target = {
        .name = "raid",
-       .version = {1, 4, 2},
+       .version = {1, 5, 0},
        .module = THIS_MODULE,
        .ctr = raid_ctr,
        .dtr = raid_dtr,
        .map = raid_map,
        .status = raid_status,
+       .message = raid_message,
        .iterate_devices = raid_iterate_devices,
        .io_hints = raid_io_hints,
        .presuspend = raid_presuspend,
This page took 0.04211 seconds and 5 git commands to generate.