OpenZFS 3993, 4700

3993 zpool(1M) and zfs(1M) should support -p for "list" and "get"
4700 "zpool get" doesn't support -H or -o options

Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Robert Mustacchi <rm@joyent.com>
Ported by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>

OpenZFS-issue: https://www.illumos.org/issues/3993
OpenZFS-issue: https://www.illumos.org/issues/4700
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/c58b352

Porting notes:
I removed ZoL's zpool_get_prop_literal() in favor of
zpool_get_prop(..., boolean_t literal) since that's what OpenZFS
uses.  The functionality is the same.
This commit is contained in:
Adam Stevko 2016-05-09 14:03:18 -07:00 committed by Brian Behlendorf
parent f00828e5d9
commit 2a8b84b747
5 changed files with 139 additions and 50 deletions

View File

@ -242,7 +242,7 @@ get_usage(zpool_help_t idx) {
case HELP_LABELCLEAR: case HELP_LABELCLEAR:
return (gettext("\tlabelclear [-f] <vdev>\n")); return (gettext("\tlabelclear [-f] <vdev>\n"));
case HELP_LIST: case HELP_LIST:
return (gettext("\tlist [-gHLPv] [-o property[,...]] " return (gettext("\tlist [-gHLpPv] [-o property[,...]] "
"[-T d|u] [pool] ... [interval [count]]\n")); "[-T d|u] [pool] ... [interval [count]]\n"));
case HELP_OFFLINE: case HELP_OFFLINE:
return (gettext("\toffline [-t] <pool> <device> ...\n")); return (gettext("\toffline [-t] <pool> <device> ...\n"));
@ -267,8 +267,8 @@ get_usage(zpool_help_t idx) {
case HELP_EVENTS: case HELP_EVENTS:
return (gettext("\tevents [-vHfc]\n")); return (gettext("\tevents [-vHfc]\n"));
case HELP_GET: case HELP_GET:
return (gettext("\tget [-pH] <\"all\" | property[,...]> " return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
"<pool> ...\n")); "<\"all\" | property[,...]> <pool> ...\n"));
case HELP_SET: case HELP_SET:
return (gettext("\tset <property=value> <pool> \n")); return (gettext("\tset <property=value> <pool> \n"));
case HELP_SPLIT: case HELP_SPLIT:
@ -3024,6 +3024,7 @@ typedef struct list_cbdata {
int cb_namewidth; int cb_namewidth;
boolean_t cb_scripted; boolean_t cb_scripted;
zprop_list_t *cb_proplist; zprop_list_t *cb_proplist;
boolean_t cb_literal;
} list_cbdata_t; } list_cbdata_t;
/* /*
@ -3115,7 +3116,7 @@ print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
right_justify = B_FALSE; right_justify = B_FALSE;
if (pl->pl_prop != ZPROP_INVAL) { if (pl->pl_prop != ZPROP_INVAL) {
if (zpool_get_prop(zhp, pl->pl_prop, property, if (zpool_get_prop(zhp, pl->pl_prop, property,
sizeof (property), NULL) != 0) sizeof (property), NULL, cb->cb_literal) != 0)
propstr = "-"; propstr = "-";
else else
propstr = property; propstr = property;
@ -3325,7 +3326,7 @@ list_callback(zpool_handle_t *zhp, void *data)
} }
/* /*
* zpool list [-gHLP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]] * zpool list [-gHLpP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
* *
* -g Display guid for individual vdev name. * -g Display guid for individual vdev name.
* -H Scripted mode. Don't display headers, and separate properties * -H Scripted mode. Don't display headers, and separate properties
@ -3334,6 +3335,7 @@ list_callback(zpool_handle_t *zhp, void *data)
* -o List of properties to display. Defaults to * -o List of properties to display. Defaults to
* "name,size,allocated,free,expandsize,fragmentation,capacity," * "name,size,allocated,free,expandsize,fragmentation,capacity,"
* "dedupratio,health,altroot" * "dedupratio,health,altroot"
* -p Display values in parsable (exact) format.
* -P Display full path for vdev name. * -P Display full path for vdev name.
* -T Display a timestamp in date(1) or Unix format * -T Display a timestamp in date(1) or Unix format
* *
@ -3355,7 +3357,7 @@ zpool_do_list(int argc, char **argv)
boolean_t first = B_TRUE; boolean_t first = B_TRUE;
/* check options */ /* check options */
while ((c = getopt(argc, argv, ":gHLo:PT:v")) != -1) { while ((c = getopt(argc, argv, ":gHLo:pPT:v")) != -1) {
switch (c) { switch (c) {
case 'g': case 'g':
cb.cb_name_flags |= VDEV_NAME_GUID; cb.cb_name_flags |= VDEV_NAME_GUID;
@ -3372,6 +3374,9 @@ zpool_do_list(int argc, char **argv)
case 'P': case 'P':
cb.cb_name_flags |= VDEV_NAME_PATH; cb.cb_name_flags |= VDEV_NAME_PATH;
break; break;
case 'p':
cb.cb_literal = B_TRUE;
break;
case 'T': case 'T':
get_timestamp_arg(*optarg); get_timestamp_arg(*optarg);
break; break;
@ -5886,7 +5891,7 @@ get_callback(zpool_handle_t *zhp, void *data)
NULL, NULL); NULL, NULL);
} }
} else { } else {
if (zpool_get_prop_literal(zhp, pl->pl_prop, value, if (zpool_get_prop(zhp, pl->pl_prop, value,
sizeof (value), &srctype, cbp->cb_literal) != 0) sizeof (value), &srctype, cbp->cb_literal) != 0)
continue; continue;
@ -5898,24 +5903,99 @@ get_callback(zpool_handle_t *zhp, void *data)
return (0); return (0);
} }
/*
* zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
*
* -H Scripted mode. Don't display headers, and separate properties
* by a single tab.
* -o List of columns to display. Defaults to
* "name,property,value,source".
* -p Diplay values in parsable (exact) format.
*
* Get properties of pools in the system. Output space statistics
* for each one as well as other attributes.
*/
int int
zpool_do_get(int argc, char **argv) zpool_do_get(int argc, char **argv)
{ {
zprop_get_cbdata_t cb = { 0 }; zprop_get_cbdata_t cb = { 0 };
zprop_list_t fake_name = { 0 }; zprop_list_t fake_name = { 0 };
int c, ret; int ret;
int c, i;
char *value;
cb.cb_first = B_TRUE;
/*
* Set up default columns and sources.
*/
cb.cb_sources = ZPROP_SRC_ALL;
cb.cb_columns[0] = GET_COL_NAME;
cb.cb_columns[1] = GET_COL_PROPERTY;
cb.cb_columns[2] = GET_COL_VALUE;
cb.cb_columns[3] = GET_COL_SOURCE;
cb.cb_type = ZFS_TYPE_POOL;
/* check options */ /* check options */
while ((c = getopt(argc, argv, "pH")) != -1) { while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
switch (c) { switch (c) {
case 'p': case 'p':
cb.cb_literal = B_TRUE; cb.cb_literal = B_TRUE;
break; break;
case 'H': case 'H':
cb.cb_scripted = B_TRUE; cb.cb_scripted = B_TRUE;
break; break;
case 'o':
bzero(&cb.cb_columns, sizeof (cb.cb_columns));
i = 0;
while (*optarg != '\0') {
static char *col_subopts[] =
{ "name", "property", "value", "source",
"all", NULL };
if (i == ZFS_GET_NCOLS) {
(void) fprintf(stderr, gettext("too "
"many fields given to -o "
"option\n"));
usage(B_FALSE);
}
switch (getsubopt(&optarg, col_subopts,
&value)) {
case 0:
cb.cb_columns[i++] = GET_COL_NAME;
break;
case 1:
cb.cb_columns[i++] = GET_COL_PROPERTY;
break;
case 2:
cb.cb_columns[i++] = GET_COL_VALUE;
break;
case 3:
cb.cb_columns[i++] = GET_COL_SOURCE;
break;
case 4:
if (i > 0) {
(void) fprintf(stderr,
gettext("\"all\" conflicts "
"with specific fields "
"given to -o option\n"));
usage(B_FALSE);
}
cb.cb_columns[0] = GET_COL_NAME;
cb.cb_columns[1] = GET_COL_PROPERTY;
cb.cb_columns[2] = GET_COL_VALUE;
cb.cb_columns[3] = GET_COL_SOURCE;
i = ZFS_GET_NCOLS;
break;
default:
(void) fprintf(stderr,
gettext("invalid column name "
"'%s'\n"), value);
usage(B_FALSE);
}
}
break;
case '?': case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"), (void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt); optopt);
@ -5932,15 +6012,8 @@ zpool_do_get(int argc, char **argv)
usage(B_FALSE); usage(B_FALSE);
} }
cb.cb_first = B_TRUE; if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
cb.cb_sources = ZPROP_SRC_ALL; ZFS_TYPE_POOL) != 0)
cb.cb_columns[0] = GET_COL_NAME;
cb.cb_columns[1] = GET_COL_PROPERTY;
cb.cb_columns[2] = GET_COL_VALUE;
cb.cb_columns[3] = GET_COL_SOURCE;
cb.cb_type = ZFS_TYPE_POOL;
if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
usage(B_FALSE); usage(B_FALSE);
argc--; argc--;

View File

@ -287,8 +287,6 @@ extern int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *, char *);
*/ */
extern int zpool_set_prop(zpool_handle_t *, const char *, const char *); extern int zpool_set_prop(zpool_handle_t *, const char *, const char *);
extern int zpool_get_prop(zpool_handle_t *, zpool_prop_t, char *, extern int zpool_get_prop(zpool_handle_t *, zpool_prop_t, char *,
size_t proplen, zprop_source_t *);
extern int zpool_get_prop_literal(zpool_handle_t *, zpool_prop_t, char *,
size_t proplen, zprop_source_t *, boolean_t literal); size_t proplen, zprop_source_t *, boolean_t literal);
extern uint64_t zpool_get_prop_int(zpool_handle_t *, zpool_prop_t, extern uint64_t zpool_get_prop_int(zpool_handle_t *, zpool_prop_t,
zprop_source_t *); zprop_source_t *);

View File

@ -2372,8 +2372,8 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
} }
if ((zpool_get_prop(zhp->zpool_hdl, if ((zpool_get_prop(zhp->zpool_hdl,
ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL)) || ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL,
(strcmp(root, "-") == 0)) B_FALSE)) || (strcmp(root, "-") == 0))
root[0] = '\0'; root[0] = '\0';
/* /*
* Special case an alternate root of '/'. This will * Special case an alternate root of '/'. This will

View File

@ -235,22 +235,12 @@ zpool_pool_state_to_name(pool_state_t state)
return (gettext("UNKNOWN")); return (gettext("UNKNOWN"));
} }
/*
* API compatibility wrapper around zpool_get_prop_literal
*/
int
zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
zprop_source_t *srctype)
{
return (zpool_get_prop_literal(zhp, prop, buf, len, srctype, B_FALSE));
}
/* /*
* Get a zpool property value for 'prop' and return the value in * Get a zpool property value for 'prop' and return the value in
* a pre-allocated buffer. * a pre-allocated buffer.
*/ */
int int
zpool_get_prop_literal(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
size_t len, zprop_source_t *srctype, boolean_t literal) size_t len, zprop_source_t *srctype, boolean_t literal)
{ {
uint64_t intval; uint64_t intval;
@ -283,9 +273,7 @@ zpool_get_prop_literal(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
(void) strlcpy(buf, (void) strlcpy(buf,
zpool_get_prop_string(zhp, prop, &src), zpool_get_prop_string(zhp, prop, &src),
len); len);
if (srctype != NULL) break;
*srctype = src;
return (0);
} }
/* FALLTHROUGH */ /* FALLTHROUGH */
default: default:
@ -337,8 +325,13 @@ zpool_get_prop_literal(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
break; break;
case ZPOOL_PROP_CAPACITY: case ZPOOL_PROP_CAPACITY:
(void) snprintf(buf, len, "%llu%%", if (literal) {
(u_longlong_t)intval); (void) snprintf(buf, len, "%llu",
(u_longlong_t)intval);
} else {
(void) snprintf(buf, len, "%llu%%",
(u_longlong_t)intval);
}
break; break;
case ZPOOL_PROP_FRAGMENTATION: case ZPOOL_PROP_FRAGMENTATION:
@ -443,7 +436,7 @@ zpool_is_bootable(zpool_handle_t *zhp)
char bootfs[ZPOOL_MAXNAMELEN]; char bootfs[ZPOOL_MAXNAMELEN];
return (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs, return (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs,
sizeof (bootfs), NULL) == 0 && strncmp(bootfs, "-", sizeof (bootfs), NULL, B_FALSE) == 0 && strncmp(bootfs, "-",
sizeof (bootfs)) != 0); sizeof (bootfs)) != 0);
} }
@ -873,7 +866,7 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp)
if (entry->pl_prop != ZPROP_INVAL && if (entry->pl_prop != ZPROP_INVAL &&
zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf), zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf),
NULL) == 0) { NULL, B_FALSE) == 0) {
if (strlen(buf) > entry->pl_width) if (strlen(buf) > entry->pl_width)
entry->pl_width = strlen(buf); entry->pl_width = strlen(buf);
} }

View File

@ -67,7 +67,7 @@ zpool \- configures ZFS storage pools
.LP .LP
.nf .nf
\fBzpool get\fR [\fB-pH\fR] "\fIall\fR" | \fIproperty\fR[,...] \fIpool\fR ... \fBzpool get\fR [\fB-Hp\fR] [\fB-o \fR\fIfield\fR[,...]] "\fIall\fR" | \fIproperty\fR[,...] \fIpool\fR ...
.fi .fi
.LP .LP
@ -105,7 +105,7 @@ zpool \- configures ZFS storage pools
.LP .LP
.nf .nf
\fBzpool list\fR [\fB-T\fR d | u ] [\fB-HgLPv\fR] [\fB-o\fR \fIproperty\fR[,...]] [\fIpool\fR] ... \fBzpool list\fR [\fB-T\fR d | u ] [\fB-HgLpPv\fR] [\fB-o\fR \fIproperty\fR[,...]] [\fIpool\fR] ...
[\fIinterval\fR[\fIcount\fR]] [\fIinterval\fR[\fIcount\fR]]
.fi .fi
@ -1199,7 +1199,8 @@ This command will forcefully export the pool even if it has a shared spare that
.ne 2 .ne 2
.mk .mk
.na .na
\fB\fBzpool get\fR [\fB-p\fR] "\fIall\fR" | \fIproperty\fR[,...] \fIpool\fR ...\fR \fB\fBzpool get\fR [\fB-Hp\fR] [\fB-o \fR\fIfield\fR[,...]] "\fIall\fR" | \fIproperty\fR[,...]
\fIpool\fR ...\fR
.ad .ad
.sp .6 .sp .6
.RS 4n .RS 4n
@ -1207,7 +1208,7 @@ Retrieves the given list of properties (or all properties if "\fBall\fR" is used
.sp .sp
.in +2 .in +2
.nf .nf
name Name of storage pool name Name of storage pool
property Property name property Property name
value Property value value Property value
source Property source, either 'default' or 'local'. source Property source, either 'default' or 'local'.
@ -1216,6 +1217,18 @@ Retrieves the given list of properties (or all properties if "\fBall\fR" is used
.sp .sp
See the "Properties" section for more information on the available pool properties. See the "Properties" section for more information on the available pool properties.
.sp
.ne 2
.mk
.na
\fB\fB-H\fR\fR
.ad
.RS 6n
.rt
Scripted mode. Do not display headers, and separate fields by a single tab instead of arbitrary space.
.RE
.sp .sp
.ne 2 .ne 2
.mk .mk
@ -1231,13 +1244,13 @@ Display numbers in parseable (exact) values.
.ne 2 .ne 2
.mk .mk
.na .na
\fB\fB-H\fR\fR \fB\fB-o\fR \fIfield\fR\fR
.ad .ad
.RS 6n .RS 12n
.rt .rt
Scripted mode. Do not display headers, and separate fields by a single tab instead of arbitrary space. A comma-separated list of columns to display. \fBname,property,value,source\fR
is the default value.
.RE .RE
.RE .RE
.sp .sp
@ -1765,7 +1778,7 @@ Treat exported or foreign devices as inactive.
.ne 2 .ne 2
.mk .mk
.na .na
\fB\fBzpool list\fR [\fB-T\fR \fBd\fR | \fBu\fR] [\fB-HgLPv\fR] [\fB-o\fR \fIprops\fR[,...]] [\fIpool\fR] ... [\fIinterval\fR[\fIcount\fR]]\fR \fB\fBzpool list\fR [\fB-T\fR \fBd\fR | \fBu\fR] [\fB-HgLpPv\fR] [\fB-o\fR \fIprops\fR[,...]] [\fIpool\fR] ... [\fIinterval\fR[\fIcount\fR]]\fR
.ad .ad
.sp .6 .sp .6
.RS 4n .RS 4n
@ -1803,6 +1816,17 @@ 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. 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 .RE
.sp
.ne 2
.mk
.na
\fB\fB-p\fR\fR
.ad
.RS 12n
.rt
Display numbers in parsable (exact) values.
.RE
.sp .sp
.ne 2 .ne 2
.mk .mk
@ -1814,6 +1838,7 @@ Display real paths for vdevs resolving all symbolic links. This can be used to l
Display full paths for vdevs instead of only the last component of the path. This can be used in conjunction with the \fB-L\fR flag. Display full paths for vdevs instead of only the last component of the path. This can be used in conjunction with the \fB-L\fR flag.
.RE .RE
.sp
.ne 2 .ne 2
.mk .mk
.na .na