in dm-raid.c [3510:3714]
static void raid_status(struct dm_target *ti, status_type_t type,
unsigned int status_flags, char *result, unsigned int maxlen)
{
struct raid_set *rs = ti->private;
struct mddev *mddev = &rs->md;
struct r5conf *conf = mddev->private;
int i, max_nr_stripes = conf ? conf->max_nr_stripes : 0;
unsigned long recovery;
unsigned int raid_param_cnt = 1; /* at least 1 for chunksize */
unsigned int sz = 0;
unsigned int rebuild_writemostly_count = 0;
sector_t progress, resync_max_sectors, resync_mismatches;
enum sync_state state;
struct raid_type *rt;
switch (type) {
case STATUSTYPE_INFO:
/* *Should* always succeed */
rt = get_raid_type_by_ll(mddev->new_level, mddev->new_layout);
if (!rt)
return;
DMEMIT("%s %d ", rt->name, mddev->raid_disks);
/* Access most recent mddev properties for status output */
smp_rmb();
/* Get sensible max sectors even if raid set not yet started */
resync_max_sectors = test_bit(RT_FLAG_RS_PRERESUMED, &rs->runtime_flags) ?
mddev->resync_max_sectors : mddev->dev_sectors;
recovery = rs->md.recovery;
state = decipher_sync_action(mddev, recovery);
progress = rs_get_progress(rs, recovery, state, resync_max_sectors);
resync_mismatches = (mddev->last_sync_action && !strcasecmp(mddev->last_sync_action, "check")) ?
atomic64_read(&mddev->resync_mismatches) : 0;
/* HM FIXME: do we want another state char for raid0? It shows 'D'/'A'/'-' now */
for (i = 0; i < rs->raid_disks; i++)
DMEMIT(__raid_dev_status(rs, &rs->dev[i].rdev));
/*
* In-sync/Reshape ratio:
* The in-sync ratio shows the progress of:
* - Initializing the raid set
* - Rebuilding a subset of devices of the raid set
* The user can distinguish between the two by referring
* to the status characters.
*
* The reshape ratio shows the progress of
* changing the raid layout or the number of
* disks of a raid set
*/
DMEMIT(" %llu/%llu", (unsigned long long) progress,
(unsigned long long) resync_max_sectors);
/*
* v1.5.0+:
*
* Sync action:
* See Documentation/admin-guide/device-mapper/dm-raid.rst for
* information on each of these states.
*/
DMEMIT(" %s", sync_str(state));
/*
* v1.5.0+:
*
* resync_mismatches/mismatch_cnt
* This field shows the number of discrepancies found when
* performing a "check" of the raid set.
*/
DMEMIT(" %llu", (unsigned long long) resync_mismatches);
/*
* v1.9.0+:
*
* data_offset (needed for out of space reshaping)
* This field shows the data offset into the data
* image LV where the first stripes data starts.
*
* We keep data_offset equal on all raid disks of the set,
* so retrieving it from the first raid disk is sufficient.
*/
DMEMIT(" %llu", (unsigned long long) rs->dev[0].rdev.data_offset);
/*
* v1.10.0+:
*/
DMEMIT(" %s", test_bit(__CTR_FLAG_JOURNAL_DEV, &rs->ctr_flags) ?
__raid_dev_status(rs, &rs->journal_dev.rdev) : "-");
break;
case STATUSTYPE_TABLE:
/* Report the table line string you would use to construct this raid set */
/*
* Count any rebuild or writemostly argument pairs and subtract the
* hweight count being added below of any rebuild and writemostly ctr flags.
*/
for (i = 0; i < rs->raid_disks; i++) {
rebuild_writemostly_count += (test_bit(i, (void *) rs->rebuild_disks) ? 2 : 0) +
(test_bit(WriteMostly, &rs->dev[i].rdev.flags) ? 2 : 0);
}
rebuild_writemostly_count -= (test_bit(__CTR_FLAG_REBUILD, &rs->ctr_flags) ? 2 : 0) +
(test_bit(__CTR_FLAG_WRITE_MOSTLY, &rs->ctr_flags) ? 2 : 0);
/* Calculate raid parameter count based on ^ rebuild/writemostly argument counts and ctr flags set. */
raid_param_cnt += rebuild_writemostly_count +
hweight32(rs->ctr_flags & CTR_FLAG_OPTIONS_NO_ARGS) +
hweight32(rs->ctr_flags & CTR_FLAG_OPTIONS_ONE_ARG) * 2;
/* Emit table line */
/* This has to be in the documented order for userspace! */
DMEMIT("%s %u %u", rs->raid_type->name, raid_param_cnt, mddev->new_chunk_sectors);
if (test_bit(__CTR_FLAG_SYNC, &rs->ctr_flags))
DMEMIT(" %s", dm_raid_arg_name_by_flag(CTR_FLAG_SYNC));
if (test_bit(__CTR_FLAG_NOSYNC, &rs->ctr_flags))
DMEMIT(" %s", dm_raid_arg_name_by_flag(CTR_FLAG_NOSYNC));
if (test_bit(__CTR_FLAG_REBUILD, &rs->ctr_flags))
for (i = 0; i < rs->raid_disks; i++)
if (test_bit(i, (void *) rs->rebuild_disks))
DMEMIT(" %s %u", dm_raid_arg_name_by_flag(CTR_FLAG_REBUILD), i);
if (test_bit(__CTR_FLAG_DAEMON_SLEEP, &rs->ctr_flags))
DMEMIT(" %s %lu", dm_raid_arg_name_by_flag(CTR_FLAG_DAEMON_SLEEP),
mddev->bitmap_info.daemon_sleep);
if (test_bit(__CTR_FLAG_MIN_RECOVERY_RATE, &rs->ctr_flags))
DMEMIT(" %s %d", dm_raid_arg_name_by_flag(CTR_FLAG_MIN_RECOVERY_RATE),
mddev->sync_speed_min);
if (test_bit(__CTR_FLAG_MAX_RECOVERY_RATE, &rs->ctr_flags))
DMEMIT(" %s %d", dm_raid_arg_name_by_flag(CTR_FLAG_MAX_RECOVERY_RATE),
mddev->sync_speed_max);
if (test_bit(__CTR_FLAG_WRITE_MOSTLY, &rs->ctr_flags))
for (i = 0; i < rs->raid_disks; i++)
if (test_bit(WriteMostly, &rs->dev[i].rdev.flags))
DMEMIT(" %s %d", dm_raid_arg_name_by_flag(CTR_FLAG_WRITE_MOSTLY),
rs->dev[i].rdev.raid_disk);
if (test_bit(__CTR_FLAG_MAX_WRITE_BEHIND, &rs->ctr_flags))
DMEMIT(" %s %lu", dm_raid_arg_name_by_flag(CTR_FLAG_MAX_WRITE_BEHIND),
mddev->bitmap_info.max_write_behind);
if (test_bit(__CTR_FLAG_STRIPE_CACHE, &rs->ctr_flags))
DMEMIT(" %s %d", dm_raid_arg_name_by_flag(CTR_FLAG_STRIPE_CACHE),
max_nr_stripes);
if (test_bit(__CTR_FLAG_REGION_SIZE, &rs->ctr_flags))
DMEMIT(" %s %llu", dm_raid_arg_name_by_flag(CTR_FLAG_REGION_SIZE),
(unsigned long long) to_sector(mddev->bitmap_info.chunksize));
if (test_bit(__CTR_FLAG_RAID10_COPIES, &rs->ctr_flags))
DMEMIT(" %s %d", dm_raid_arg_name_by_flag(CTR_FLAG_RAID10_COPIES),
raid10_md_layout_to_copies(mddev->layout));
if (test_bit(__CTR_FLAG_RAID10_FORMAT, &rs->ctr_flags))
DMEMIT(" %s %s", dm_raid_arg_name_by_flag(CTR_FLAG_RAID10_FORMAT),
raid10_md_layout_to_format(mddev->layout));
if (test_bit(__CTR_FLAG_DELTA_DISKS, &rs->ctr_flags))
DMEMIT(" %s %d", dm_raid_arg_name_by_flag(CTR_FLAG_DELTA_DISKS),
max(rs->delta_disks, mddev->delta_disks));
if (test_bit(__CTR_FLAG_DATA_OFFSET, &rs->ctr_flags))
DMEMIT(" %s %llu", dm_raid_arg_name_by_flag(CTR_FLAG_DATA_OFFSET),
(unsigned long long) rs->data_offset);
if (test_bit(__CTR_FLAG_JOURNAL_DEV, &rs->ctr_flags))
DMEMIT(" %s %s", dm_raid_arg_name_by_flag(CTR_FLAG_JOURNAL_DEV),
__get_dev_name(rs->journal_dev.dev));
if (test_bit(__CTR_FLAG_JOURNAL_MODE, &rs->ctr_flags))
DMEMIT(" %s %s", dm_raid_arg_name_by_flag(CTR_FLAG_JOURNAL_MODE),
md_journal_mode_to_dm_raid(rs->journal_dev.mode));
DMEMIT(" %d", rs->raid_disks);
for (i = 0; i < rs->raid_disks; i++)
DMEMIT(" %s %s", __get_dev_name(rs->dev[i].meta_dev),
__get_dev_name(rs->dev[i].data_dev));
break;
case STATUSTYPE_IMA:
rt = get_raid_type_by_ll(mddev->new_level, mddev->new_layout);
if (!rt)
return;
DMEMIT_TARGET_NAME_VERSION(ti->type);
DMEMIT(",raid_type=%s,raid_disks=%d", rt->name, mddev->raid_disks);
/* Access most recent mddev properties for status output */
smp_rmb();
recovery = rs->md.recovery;
state = decipher_sync_action(mddev, recovery);
DMEMIT(",raid_state=%s", sync_str(state));
for (i = 0; i < rs->raid_disks; i++) {
DMEMIT(",raid_device_%d_status=", i);
DMEMIT(__raid_dev_status(rs, &rs->dev[i].rdev));
}
if (rt_is_raid456(rt)) {
DMEMIT(",journal_dev_mode=");
switch (rs->journal_dev.mode) {
case R5C_JOURNAL_MODE_WRITE_THROUGH:
DMEMIT("%s",
_raid456_journal_mode[R5C_JOURNAL_MODE_WRITE_THROUGH].param);
break;
case R5C_JOURNAL_MODE_WRITE_BACK:
DMEMIT("%s",
_raid456_journal_mode[R5C_JOURNAL_MODE_WRITE_BACK].param);
break;
default:
DMEMIT("invalid");
break;
}
}
DMEMIT(";");
break;
}
}