Skip to content

Commit

Permalink
zpool iostat -k and status -k show type of vdevs: ssd, hdd, file or m…
Browse files Browse the repository at this point in the history
…ixed.

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 info to zpool cmd whether devices are solid state, or rotational.
Info is passed in ZPOOL_CONFIG_VDEV_STATS_EX -> ZPOOL_CONFIG_VDEV_TYPE.
  • Loading branch information
inkdot7 committed Jan 11, 2017
1 parent 42b64e5 commit 4f487f3
Show file tree
Hide file tree
Showing 8 changed files with 129 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_ROT_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_ROT_TYPE_M (1ULL << IOS_ROT_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_ROT_TYPE] = {
ZPOOL_CONFIG_VDEV_ROT_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] [-ghHkLpPvy] "
"[[-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] [-gkLPvxD] [-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 *
rot_type_mark(nvlist_t *nv)
{
nvlist_t *nvx;
uint64_t type = VDEV_ROT_TYPE_UNKNOWN;

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

switch (type) {
case VDEV_ROT_TYPE_SSD:
return ("ssd");
case VDEV_ROT_TYPE_FILE:
return ("file");
case VDEV_ROT_TYPE_MIXED:
return ("mix");
case VDEV_ROT_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_rot_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_rot_type)
(void) printf(" %4s", rot_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_ROT_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_ROT_TYPE] = {{"type"}, {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_ROT_TYPE] = 4, /* type/file/ssd/hdd/mix */
};

if (cb->cb_literal)
if (cb->cb_literal || type == IOS_ROT_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_ROT_TYPE_M)
printf("%s%4s", cb->cb_scripted ? "\t" : " ",
rot_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] [-ghHkLpPvy] [[-lq]|[-r|-w]] [-n name] [-T d|u]
* [[ pool ...]|[pool vdev ...]|[vdev ...]]
* [interval [count]]
*
Expand All @@ -3972,6 +4013,7 @@ fsleep(float sec) {
* -p Display values in parsable (exact) format.
* -H Scripted mode. Don't display headers, and separate properties
* by a single tab.
* -k Display type of device, e.g. solid-state or mixed.
* -l Display average latency
* -q Display queue depths
* -w Display latency histograms
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 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:vyhpklqrwH")) != -1) {
switch (c) {
case 'c':
cmd = optarg;
Expand All @@ -4033,6 +4076,9 @@ zpool_do_iostat(int argc, char **argv)
case 'p':
parsable = B_TRUE;
break;
case 'k':
type = B_TRUE;
break;
case 'l':
latency = 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 (type)
cb.cb_flags |= IOS_ROT_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_rot_type ? " TYPE" : "");
print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0,
B_FALSE);

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

/*
* zpool status [-c CMD] [-gLPvx] [-T d|u] [pool] ... [interval [count]]
* zpool status [-c CMD] [-gkLPvx] [-T d|u] [pool] ... [interval [count]]
*
* -c CMD For each vdev, run command CMD
* -g Display guid for individual vdev name.
* -k Display type of device, e.g. solid-state or mixed.
* -L Follow links when resolving vdev path name.
* -P Display full path for vdev name.
* -v Display complete error logs
Expand All @@ -6092,14 +6141,17 @@ 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:gkLPvxDT:")) != -1) {
switch (c) {
case 'c':
cmd = optarg;
break;
case 'g':
cb.cb_name_flags |= VDEV_NAME_GUID;
break;
case 'k':
cb.cb_rot_type = B_TRUE;
break;
case 'L':
cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
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_ROT_TYPE "rot_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_rot_type_info {
VDEV_ROT_TYPE_UNKNOWN = 0, /* not set yet */
VDEV_ROT_TYPE_SSD, /* device is solid state */
VDEV_ROT_TYPE_FILE, /* device is file backed */
VDEV_ROT_TYPE_MIXED, /* device has both types */
VDEV_ROT_TYPE_HDD /* device is not solid state */
} vdev_rot_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_rot_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-ghHkLpPvy\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-gkLPvxD\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-ghHkLpPvy\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 @@ -1585,6 +1585,15 @@ Display vdev GUIDs instead of the normal device names. These GUIDs can be used i
Scripted mode. Do not display headers, and separate fields by a single tab instead of arbitrary space.
.RE

.sp
.ne 2
.na
\fB\fB-k\fR\fR
.ad
.RS 12n
Display the 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-gkLPvxD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]]
.ad
.sp .6
.RS 4n
Expand Down Expand Up @@ -2133,6 +2142,15 @@ in parallel for each vdev for performance.
Display vdev GUIDs instead of the normal device names. These GUIDs can be used innplace of device names for the zpool detach/offline/remove/replace commands.
.RE

.sp
.ne 2
.na
\fB\fB-k\fR\fR
.ad
.RS 12n
Display the 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_rot_type = VDEV_ROT_TYPE_FILE;
else
vsx->vsx_rot_type = VDEV_ROT_TYPE_SSD;
} else if (vd->vdev_nonrot_mix)
vsx->vsx_rot_type = VDEV_ROT_TYPE_MIXED;
else
vsx->vsx_rot_type = VDEV_ROT_TYPE_HDD;
}
}

void
Expand Down
Loading

0 comments on commit 4f487f3

Please sign in to comment.