Skip to content

Commit

Permalink
zpool iostat -M and status -M show media type of vdevs: ssd, hdd, fil…
Browse files Browse the repository at this point in the history
…e or mixed.

Keep track of mixed nonrotational (ssd+hdd) devices.
Only mirrors are mixed.  If a pool consist of several mixed vdevs, it is
mixed if all vdevs are either mixed, or ssd (fully nonrotational).

Pass media type info to zpool cmd (mainly whether devices are solid state, or rotational).
Info is passed in ZPOOL_CONFIG_VDEV_STATS_EX -> ZPOOL_CONFIG_VDEV_MEDIA_TYPE.
  • Loading branch information
inkdot7 committed Jan 12, 2017
1 parent 42b64e5 commit 289a948
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 16 deletions.
74 changes: 63 additions & 11 deletions cmd/zpool/zpool_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,17 @@ enum iostat_type {
IOS_DEFAULT = 0,
IOS_LATENCY = 1,
IOS_QUEUES = 2,
IOS_L_HISTO = 3,
IOS_RQ_HISTO = 4,
IOS_MEDIA_TYPE = 3,
IOS_L_HISTO = 4,
IOS_RQ_HISTO = 5,
IOS_COUNT, /* always last element */
};

/* iostat_type entries as bitmasks */
#define IOS_DEFAULT_M (1ULL << IOS_DEFAULT)
#define IOS_LATENCY_M (1ULL << IOS_LATENCY)
#define IOS_QUEUES_M (1ULL << IOS_QUEUES)
#define IOS_MEDIA_TYPE_M (1ULL << IOS_MEDIA_TYPE)
#define IOS_L_HISTO_M (1ULL << IOS_L_HISTO)
#define IOS_RQ_HISTO_M (1ULL << IOS_RQ_HISTO)

Expand Down Expand Up @@ -197,6 +199,9 @@ static const char *vsx_type_to_nvlist[IOS_COUNT][11] = {
ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE,
ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE,
NULL},
[IOS_MEDIA_TYPE] = {
ZPOOL_CONFIG_VDEV_MEDIA_TYPE,
NULL},
[IOS_RQ_HISTO] = {
ZPOOL_CONFIG_VDEV_SYNC_IND_R_HISTO,
ZPOOL_CONFIG_VDEV_SYNC_AGG_R_HISTO,
Expand Down Expand Up @@ -312,7 +317,7 @@ get_usage(zpool_help_t idx) {
"[-R root] [-F [-n]]\n"
"\t <pool | id> [newpool]\n"));
case HELP_IOSTAT:
return (gettext("\tiostat [-c CMD] [-T d | u] [-ghHLpPvy] "
return (gettext("\tiostat [-c CMD] [-T d | u] [-ghHLMpPvy] "
"[[-lq]|[-r|-w]]\n"
"\t [[pool ...]|[pool vdev ...]|[vdev ...]] "
"[interval [count]]\n"));
Expand All @@ -335,7 +340,7 @@ get_usage(zpool_help_t idx) {
case HELP_SCRUB:
return (gettext("\tscrub [-s] <pool> ...\n"));
case HELP_STATUS:
return (gettext("\tstatus [-c CMD] [-gLPvxD] [-T d|u] [pool]"
return (gettext("\tstatus [-c CMD] [-gLMPvxD] [-T d|u] [pool]"
" ... [interval [count]]\n"));
case HELP_UPGRADE:
return (gettext("\tupgrade\n"
Expand Down Expand Up @@ -1455,6 +1460,30 @@ max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max,
return (max);
}

static const char *
media_type_mark(nvlist_t *nv)
{
nvlist_t *nvx;
uint64_t type = VDEV_MEDIA_TYPE_UNKNOWN;

if (nvlist_lookup_nvlist(nv, ZPOOL_CONFIG_VDEV_STATS_EX, &nvx) == 0)
nvlist_lookup_uint64(nvx, ZPOOL_CONFIG_VDEV_MEDIA_TYPE,
&type);

switch (type) {
case VDEV_MEDIA_TYPE_SSD:
return ("ssd");
case VDEV_MEDIA_TYPE_FILE:
return ("file");
case VDEV_MEDIA_TYPE_MIXED:
return ("mix");
case VDEV_MEDIA_TYPE_HDD:
return ("hdd");
default:
return ("-");
}
}

typedef struct spare_cbdata {
uint64_t cb_guid;
zpool_handle_t *cb_zhp;
Expand Down Expand Up @@ -1509,6 +1538,7 @@ typedef struct status_cbdata {
boolean_t cb_explain;
boolean_t cb_first;
boolean_t cb_dedup_stats;
boolean_t cb_media_type;
boolean_t cb_print_status;
vdev_cmd_data_list_t *vcdl;
} status_cbdata_t;
Expand Down Expand Up @@ -1572,8 +1602,13 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
(void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
} else {
(void) printf(" ");
}

if (cb->cb_media_type)
(void) printf(" %5s", media_type_mark(nv));

if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
&notpresent) == 0) {
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
Expand Down Expand Up @@ -2628,6 +2663,7 @@ static const name_and_columns_t iostat_top_labels[][IOSTAT_MAX_LABELS] =
[IOS_QUEUES] = {{"syncq_read", 2}, {"syncq_write", 2},
{"asyncq_read", 2}, {"asyncq_write", 2}, {"scrubq_read", 2},
{NULL}},
[IOS_MEDIA_TYPE] = {{"", 1}, {NULL}},
[IOS_L_HISTO] = {{"total_wait", 2}, {"disk_wait", 2},
{"sync_queue", 2}, {"async_queue", 2}, {NULL}},
[IOS_RQ_HISTO] = {{"sync_read", 2}, {"sync_write", 2},
Expand All @@ -2644,6 +2680,7 @@ static const name_and_columns_t iostat_bottom_labels[][IOSTAT_MAX_LABELS] =
{"write"}, {"read"}, {"write"}, {"wait"}, {NULL}},
[IOS_QUEUES] = {{"pend"}, {"activ"}, {"pend"}, {"activ"}, {"pend"},
{"activ"}, {"pend"}, {"activ"}, {"pend"}, {"activ"}, {NULL}},
[IOS_MEDIA_TYPE] = {{"media"}, {NULL}},
[IOS_L_HISTO] = {{"read"}, {"write"}, {"read"}, {"write"}, {"read"},
{"write"}, {"read"}, {"write"}, {"scrub"}, {NULL}},
[IOS_RQ_HISTO] = {{"ind"}, {"agg"}, {"ind"}, {"agg"}, {"ind"}, {"agg"},
Expand Down Expand Up @@ -2706,9 +2743,10 @@ default_column_width(iostat_cbdata_t *cb, enum iostat_type type)
[IOS_DEFAULT] = 15, /* 1PB capacity */
[IOS_LATENCY] = 10, /* 1B ns = 10sec */
[IOS_QUEUES] = 6, /* 1M queue entries */
[IOS_MEDIA_TYPE] = 5, /* type/file/ssd/hdd/mix */
};

if (cb->cb_literal)
if (cb->cb_literal || type == IOS_MEDIA_TYPE)
column_width = widths[type];

return (column_width);
Expand Down Expand Up @@ -3411,6 +3449,9 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
print_iostat_latency(cb, oldnv, newnv, scale);
if (cb->cb_flags & IOS_QUEUES_M)
print_iostat_queues(cb, oldnv, newnv, scale);
if (cb->cb_flags & IOS_MEDIA_TYPE_M)
printf("%s%5s", cb->cb_scripted ? "\t" : " ",
media_type_mark(newnv));
if (cb->cb_flags & IOS_ANYHISTO_M) {
printf("\n");
print_iostat_histos(cb, oldnv, newnv, scale, name);
Expand Down Expand Up @@ -3959,7 +4000,7 @@ fsleep(float sec) {


/*
* zpool iostat [-c CMD] [-ghHLpPvy] [[-lq]|[-r|-w]] [-n name] [-T d|u]
* zpool iostat [-c CMD] [-ghHLMpPvy] [[-lq]|[-r|-w]] [-n name] [-T d|u]
* [[ pool ...]|[pool vdev ...]|[vdev ...]]
* [interval [count]]
*
Expand All @@ -3973,6 +4014,7 @@ fsleep(float sec) {
* -H Scripted mode. Don't display headers, and separate properties
* by a single tab.
* -l Display average latency
* -M Display media type of device, e.g. solid-state or mixed.
* -q Display queue depths
* -w Display latency histograms
* -r Display request size histogram
Expand Down Expand Up @@ -4000,6 +4042,7 @@ zpool_do_iostat(int argc, char **argv)
boolean_t guid = B_FALSE;
boolean_t follow_links = B_FALSE;
boolean_t full_name = B_FALSE;
boolean_t media_type = B_FALSE;
iostat_cbdata_t cb = { 0 };
char *cmd = NULL;

Expand All @@ -4010,7 +4053,7 @@ zpool_do_iostat(int argc, char **argv)
uint64_t unsupported_flags;

/* check options */
while ((c = getopt(argc, argv, "c:gLPT:vyhplqrwH")) != -1) {
while ((c = getopt(argc, argv, "c:gLPT:vyhplMqrwH")) != -1) {
switch (c) {
case 'c':
cmd = optarg;
Expand All @@ -4021,6 +4064,9 @@ zpool_do_iostat(int argc, char **argv)
case 'L':
follow_links = B_TRUE;
break;
case 'M':
media_type = B_TRUE;
break;
case 'P':
full_name = B_TRUE;
break;
Expand Down Expand Up @@ -4188,6 +4234,8 @@ zpool_do_iostat(int argc, char **argv)
cb.cb_flags |= IOS_LATENCY_M;
if (queues)
cb.cb_flags |= IOS_QUEUES_M;
if (media_type)
cb.cb_flags |= IOS_MEDIA_TYPE_M;
}

/*
Expand Down Expand Up @@ -6006,9 +6054,9 @@ status_callback(zpool_handle_t *zhp, void *data)
cbp->cb_namewidth = 10;

(void) printf(gettext("config:\n\n"));
(void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"),
(void) printf(gettext("\t%-*s %-8s %5s %5s %5s%s\n"),
cbp->cb_namewidth, "NAME", "STATE", "READ", "WRITE",
"CKSUM");
"CKSUM", cbp->cb_media_type ? " MEDIA" : "");
print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0,
B_FALSE);

Expand Down Expand Up @@ -6068,11 +6116,12 @@ status_callback(zpool_handle_t *zhp, void *data)
}

/*
* zpool status [-c CMD] [-gLPvx] [-T d|u] [pool] ... [interval [count]]
* zpool status [-c CMD] [-gLMPvx] [-T d|u] [pool] ... [interval [count]]
*
* -c CMD For each vdev, run command CMD
* -g Display guid for individual vdev name.
* -L Follow links when resolving vdev path name.
* -M Display media type of device, e.g. solid-state or mixed.
* -P Display full path for vdev name.
* -v Display complete error logs
* -x Display only pools with potential problems
Expand All @@ -6092,7 +6141,7 @@ zpool_do_status(int argc, char **argv)
char *cmd = NULL;

/* check options */
while ((c = getopt(argc, argv, "c:gLPvxDT:")) != -1) {
while ((c = getopt(argc, argv, "c:gLMPvxDT:")) != -1) {
switch (c) {
case 'c':
cmd = optarg;
Expand All @@ -6103,6 +6152,9 @@ zpool_do_status(int argc, char **argv)
case 'L':
cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
break;
case 'M':
cb.cb_media_type = B_TRUE;
break;
case 'P':
cb.cb_name_flags |= VDEV_NAME_PATH;
break;
Expand Down
16 changes: 16 additions & 0 deletions include/sys/fs/zfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,9 @@ typedef struct zpool_rewind_policy {
/* vdev enclosure sysfs path */
#define ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH "vdev_enc_sysfs_path"

/* Type (ssd, file, mix, hdd) (part of vdev_stat_ex_t) */
#define ZPOOL_CONFIG_VDEV_MEDIA_TYPE "media_type"

#define ZPOOL_CONFIG_WHOLE_DISK "whole_disk"
#define ZPOOL_CONFIG_ERRCOUNT "error_count"
#define ZPOOL_CONFIG_NOT_PRESENT "not_present"
Expand Down Expand Up @@ -730,6 +733,14 @@ typedef enum vdev_aux {
VDEV_AUX_SPLIT_POOL /* vdev was split off into another pool */
} vdev_aux_t;

typedef enum vdev_media_type_info {
VDEV_MEDIA_TYPE_UNKNOWN = 0, /* not set yet */
VDEV_MEDIA_TYPE_SSD, /* device is solid state */
VDEV_MEDIA_TYPE_FILE, /* device is file backed */
VDEV_MEDIA_TYPE_MIXED, /* device has both types */
VDEV_MEDIA_TYPE_HDD /* device is not solid state */
} vdev_media_type_info_t;

/*
* pool state. The following states are written to disk as part of the normal
* SPA lifecycle: ACTIVE, EXPORTED, DESTROYED, SPARE, L2CACHE. The remaining
Expand Down Expand Up @@ -887,6 +898,11 @@ typedef struct vdev_stat_ex {
uint64_t vsx_agg_histo[ZIO_PRIORITY_NUM_QUEUEABLE]
[VDEV_RQ_HISTO_BUCKETS];

/*
* Rotational type of vdev (ssd, file, mixed, hdd).
* Exported as one value.
*/
uint64_t vsx_media_type;
} vdev_stat_ex_t;

/*
Expand Down
1 change: 1 addition & 0 deletions include/sys/vdev_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ struct vdev {
boolean_t vdev_expanding; /* expand the vdev? */
boolean_t vdev_reopening; /* reopen in progress? */
boolean_t vdev_nonrot; /* true if solid state */
boolean_t vdev_nonrot_mix; /* true if partial solid state */
int vdev_open_error; /* error on last open */
kthread_t *vdev_open_thread; /* thread opening children */
uint64_t vdev_crtxg; /* txg when top-level was added */
Expand Down
26 changes: 22 additions & 4 deletions man/man8/zpool.8
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ zpool \- configures ZFS storage pools

.LP
.nf
\fB\fBzpool iostat\fR [\fB-c\fR \fBCMD\fR] [\fB-T\fR \fBd\fR | \fBu\fR] [\fB-ghHLpPvy\fR] [\fB-lq\fR]|[\fB-r\fR|-\fBw\fR]]
\fB\fBzpool iostat\fR [\fB-c\fR \fBCMD\fR] [\fB-T\fR \fBd\fR | \fBu\fR] [\fB-ghHLMpPvy\fR] [\fB-lq\fR]|[\fB-r\fR|-\fBw\fR]]
[[\fIpool\fR ...]|[\fIpool vdev\fR ...]|[\fIvdev\fR ...]] [\fIinterval\fR[\fIcount\fR]]\fR

.fi
Expand Down Expand Up @@ -159,7 +159,7 @@ zpool \- configures ZFS storage pools

.LP
.nf
\fBzpool status\fR [\fB-c\fR \fBCMD\fR] [\fB-gLPvxD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]]
\fBzpool status\fR [\fB-c\fR \fBCMD\fR] [\fB-gLMPvxD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]]
.fi

.LP
Expand Down Expand Up @@ -1523,7 +1523,7 @@ Scan using the default search path, the libblkid cache will not be consulted. A
.sp
.ne 2
.na
\fB\fBzpool iostat\fR [\fB-c\fR \fBCMD\fR] [\fB-T\fR \fBd\fR | \fBu\fR] [\fB-ghHLpPvy\fR] [[\fB-lq\fR]|[\fB-r\fR|\fB-w\fR]] [[\fIpool\fR ...]|[\fIpool vdev\fR ...]|[\fIvdev\fR ...]] [\fIinterval\fR[\fIcount\fR]]\fR
\fB\fBzpool iostat\fR [\fB-c\fR \fBCMD\fR] [\fB-T\fR \fBd\fR | \fBu\fR] [\fB-ghHLMpPvy\fR] [[\fB-lq\fR]|[\fB-r\fR|\fB-w\fR]] [[\fIpool\fR ...]|[\fIpool vdev\fR ...]|[\fIvdev\fR ...]] [\fIinterval\fR[\fIcount\fR]]\fR

.ad
.sp .6
Expand Down Expand Up @@ -1594,6 +1594,15 @@ Scripted mode. Do not display headers, and separate fields by a single tab inste
Display real paths for vdevs resolving all symbolic links. This can be used to look up the current block device name regardless of the /dev/disk/ path used to open it.
.RE

.sp
.ne 2
.na
\fB\fB-M\fR\fR
.ad
.RS 12n
Display the media type of device a pool or vdev is based on: ssd, hdd or file. Mixed mirror vdevs that have both ssd (or file) and hdd members are marked "mix". A pool is considered mixed if all members are at least mixed, i.e. no pure hdd.
.RE

.sp
.ne 2
.na
Expand Down Expand Up @@ -2099,7 +2108,7 @@ Sets the specified property for \fInewpool\fR. See the “Properties” section
.sp
.ne 2
.na
\fBzpool status\fR [\fB-c\fR \fBCMD\fR] [\fB-gLPvxD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]]
\fBzpool status\fR [\fB-c\fR \fBCMD\fR] [\fB-gLMPvxD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]]
.ad
.sp .6
.RS 4n
Expand Down Expand Up @@ -2142,6 +2151,15 @@ Display vdev GUIDs instead of the normal device names. These GUIDs can be used i
Display real paths for vdevs resolving all symbolic links. This can be used to look up the current block device name regardless of the /dev/disk/ path used to open it.
.RE

.sp
.ne 2
.na
\fB\fB-M\fR\fR
.ad
.RS 12n
Display the media type of device a pool or vdev is based on: ssd, hdd or file. Mixed mirror vdevs that have both ssd (or file) and hdd members are marked "mix". A pool is considered mixed if all members are at least mixed, i.e. no pure hdd.
.RE

.sp
.ne 2
.na
Expand Down
24 changes: 23 additions & 1 deletion module/zfs/vdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,7 @@ vdev_open_children(vdev_t *vd)
taskq_t *tq;
int children = vd->vdev_children;
int c;
boolean_t nonrot_some;

/*
* in order to handle pools on top of zvols, do the opens
Expand All @@ -1198,9 +1199,19 @@ vdev_open_children(vdev_t *vd)
}

vd->vdev_nonrot = B_TRUE;
vd->vdev_nonrot_mix = B_TRUE;
nonrot_some = B_FALSE;

for (c = 0; c < children; c++)
for (c = 0; c < children; c++) {
vd->vdev_nonrot &= vd->vdev_child[c]->vdev_nonrot;
vd->vdev_nonrot_mix &= vd->vdev_child[c]->vdev_nonrot_mix |
vd->vdev_child[c]->vdev_nonrot;
nonrot_some |= vd->vdev_child[c]->vdev_nonrot;
}
if (vd->vdev_ops == &vdev_mirror_ops)
vd->vdev_nonrot_mix |= nonrot_some;
if (vd->vdev_nonrot)
vd->vdev_nonrot_mix = B_FALSE;
}

/*
Expand Down Expand Up @@ -2895,6 +2906,17 @@ vdev_get_stats_ex_impl(vdev_t *vd, vdev_stat_t *vs, vdev_stat_ex_t *vsx)
&vd->vdev_queue.vq_class[t].vqc_queued_tree);
}
}
if (vsx) {
if (vd->vdev_nonrot) {
if (vd->vdev_ops == &vdev_file_ops)
vsx->vsx_media_type = VDEV_MEDIA_TYPE_FILE;
else
vsx->vsx_media_type = VDEV_MEDIA_TYPE_SSD;
} else if (vd->vdev_nonrot_mix)
vsx->vsx_media_type = VDEV_MEDIA_TYPE_MIXED;
else
vsx->vsx_media_type = VDEV_MEDIA_TYPE_HDD;
}
}

void
Expand Down
Loading

0 comments on commit 289a948

Please sign in to comment.