summaryrefslogtreecommitdiff
path: root/usr/src/cmd/zfs/zfs_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/zfs/zfs_main.c')
-rw-r--r--usr/src/cmd/zfs/zfs_main.c168
1 files changed, 119 insertions, 49 deletions
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c
index 3d037ee469..87abb21171 100644
--- a/usr/src/cmd/zfs/zfs_main.c
+++ b/usr/src/cmd/zfs/zfs_main.c
@@ -157,7 +157,7 @@ static zfs_command_t command_table[] = {
{ "list", zfs_do_list, HELP_LIST },
{ NULL },
{ "set", zfs_do_set, HELP_SET },
- { "get", zfs_do_get, HELP_GET },
+ { "get", zfs_do_get, HELP_GET },
{ "inherit", zfs_do_inherit, HELP_INHERIT },
{ "upgrade", zfs_do_upgrade, HELP_UPGRADE },
{ "userspace", zfs_do_userspace, HELP_USERSPACE },
@@ -201,11 +201,11 @@ get_usage(zfs_help_t idx)
"\tdestroy [-rRd] <snapshot>\n"));
case HELP_GET:
return (gettext("\tget [-rHp] [-d max] "
- "[-o field[,...]] [-s source[,...]]\n"
+ "[-o \"all\" | field[,...]] [-s source[,...]]\n"
"\t <\"all\" | property[,...]> "
"[filesystem|volume|snapshot] ...\n"));
case HELP_INHERIT:
- return (gettext("\tinherit [-r] <property> "
+ return (gettext("\tinherit [-rS] <property> "
"<filesystem|volume|snapshot> ...\n"));
case HELP_UPGRADE:
return (gettext("\tupgrade [-v]\n"
@@ -232,7 +232,7 @@ get_usage(zfs_help_t idx)
case HELP_ROLLBACK:
return (gettext("\trollback [-rRf] <snapshot>\n"));
case HELP_SEND:
- return (gettext("\tsend [-RD] [-[iI] snapshot] <snapshot>\n"));
+ return (gettext("\tsend [-RDp] [-[iI] snapshot] <snapshot>\n"));
case HELP_SET:
return (gettext("\tset <property=value> "
"<filesystem|volume|snapshot> ...\n"));
@@ -787,9 +787,9 @@ badusage:
* zfs destroy [-rRf] <fs, vol>
* zfs destroy [-rRd] <snap>
*
- * -r Recursively destroy all children
- * -R Recursively destroy all dependents, including clones
- * -f Force unmounting of any dependents
+ * -r Recursively destroy all children
+ * -R Recursively destroy all dependents, including clones
+ * -f Force unmounting of any dependents
* -d If we can't destroy now, mark for deferred destruction
*
* Destroys the given dataset. By default, it will unmount any filesystems,
@@ -1068,18 +1068,32 @@ zfs_do_destroy(int argc, char **argv)
return (0);
}
+static boolean_t
+is_recvd_column(zprop_get_cbdata_t *cbp)
+{
+ int i;
+ zfs_get_column_t col;
+
+ for (i = 0; i < ZFS_GET_NCOLS &&
+ (col = cbp->cb_columns[i]) != GET_COL_NONE; i++)
+ if (col == GET_COL_RECVD)
+ return (B_TRUE);
+ return (B_FALSE);
+}
+
/*
- * zfs get [-rHp] [-o field[,field]...] [-s source[,source]...]
- * < all | property[,property]... > < fs | snap | vol > ...
+ * zfs get [-rHp] [-o all | field[,field]...] [-s source[,source]...]
+ * < all | property[,property]... > < fs | snap | vol > ...
*
* -r recurse over any child datasets
* -H scripted mode. Headers are stripped, and fields are separated
* by tabs instead of spaces.
- * -o Set of fields to display. One of "name,property,value,source".
- * Default is all four.
+ * -o Set of fields to display. One of "name,property,value,
+ * received,source". Default is "name,property,value,source".
+ * "all" is an alias for all five.
* -s Set of sources to allow. One of
- * "local,default,inherited,temporary,none". Default is all
- * five.
+ * "local,default,inherited,received,temporary,none". Default is
+ * all six.
* -p Display values in parsable (literal) format.
*
* Prints properties for the given datasets. The user can control which
@@ -1093,16 +1107,19 @@ static int
get_callback(zfs_handle_t *zhp, void *data)
{
char buf[ZFS_MAXPROPLEN];
+ char rbuf[ZFS_MAXPROPLEN];
zprop_source_t sourcetype;
char source[ZFS_MAXNAMELEN];
zprop_get_cbdata_t *cbp = data;
- nvlist_t *userprop = zfs_get_user_props(zhp);
+ nvlist_t *user_props = zfs_get_user_props(zhp);
zprop_list_t *pl = cbp->cb_proplist;
nvlist_t *propval;
char *strval;
char *sourceval;
+ boolean_t received = is_recvd_column(cbp);
for (; pl != NULL; pl = pl->pl_next) {
+ char *recvdval = NULL;
/*
* Skip the special fake placeholder. This will also skip over
* the name property when 'all' is specified.
@@ -1129,9 +1146,14 @@ get_callback(zfs_handle_t *zhp, void *data)
(void) strlcpy(buf, "-", sizeof (buf));
}
+ if (received && (zfs_prop_get_recvd(zhp,
+ zfs_prop_to_name(pl->pl_prop), rbuf, sizeof (rbuf),
+ cbp->cb_literal) == 0))
+ recvdval = rbuf;
+
zprop_print_one_property(zfs_get_name(zhp), cbp,
zfs_prop_to_name(pl->pl_prop),
- buf, sourcetype, source);
+ buf, sourcetype, source, recvdval);
} else if (zfs_prop_userquota(pl->pl_user_prop)) {
sourcetype = ZPROP_SRC_LOCAL;
@@ -1142,9 +1164,9 @@ get_callback(zfs_handle_t *zhp, void *data)
}
zprop_print_one_property(zfs_get_name(zhp), cbp,
- pl->pl_user_prop, buf, sourcetype, source);
+ pl->pl_user_prop, buf, sourcetype, source, NULL);
} else {
- if (nvlist_lookup_nvlist(userprop,
+ if (nvlist_lookup_nvlist(user_props,
pl->pl_user_prop, &propval) != 0) {
if (pl->pl_all)
continue;
@@ -1159,6 +1181,9 @@ get_callback(zfs_handle_t *zhp, void *data)
if (strcmp(sourceval,
zfs_get_name(zhp)) == 0) {
sourcetype = ZPROP_SRC_LOCAL;
+ } else if (strcmp(sourceval,
+ ZPROP_SOURCE_VAL_RECVD) == 0) {
+ sourcetype = ZPROP_SRC_RECEIVED;
} else {
sourcetype = ZPROP_SRC_INHERITED;
(void) strlcpy(source,
@@ -1166,9 +1191,14 @@ get_callback(zfs_handle_t *zhp, void *data)
}
}
+ if (received && (zfs_prop_get_recvd(zhp,
+ pl->pl_user_prop, rbuf, sizeof (rbuf),
+ cbp->cb_literal) == 0))
+ recvdval = rbuf;
+
zprop_print_one_property(zfs_get_name(zhp), cbp,
pl->pl_user_prop, strval, sourcetype,
- source);
+ source, recvdval);
}
}
@@ -1224,10 +1254,10 @@ zfs_do_get(int argc, char **argv)
i = 0;
while (*optarg != '\0') {
static char *col_subopts[] =
- { "name", "property", "value", "source",
- NULL };
+ { "name", "property", "value", "received",
+ "source", "all", NULL };
- if (i == 4) {
+ if (i == ZFS_GET_NCOLS) {
(void) fprintf(stderr, gettext("too "
"many fields given to -o "
"option\n"));
@@ -1246,8 +1276,28 @@ zfs_do_get(int argc, char **argv)
cb.cb_columns[i++] = GET_COL_VALUE;
break;
case 3:
+ cb.cb_columns[i++] = GET_COL_RECVD;
+ flags |= ZFS_ITER_RECVD_PROPS;
+ break;
+ case 4:
cb.cb_columns[i++] = GET_COL_SOURCE;
break;
+ case 5:
+ 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_RECVD;
+ cb.cb_columns[4] = GET_COL_SOURCE;
+ flags |= ZFS_ITER_RECVD_PROPS;
+ i = ZFS_GET_NCOLS;
+ break;
default:
(void) fprintf(stderr,
gettext("invalid column name "
@@ -1262,7 +1312,8 @@ zfs_do_get(int argc, char **argv)
while (*optarg != '\0') {
static char *source_subopts[] = {
"local", "default", "inherited",
- "temporary", "none", NULL };
+ "received", "temporary", "none",
+ NULL };
switch (getsubopt(&optarg, source_subopts,
&value)) {
@@ -1276,9 +1327,12 @@ zfs_do_get(int argc, char **argv)
cb.cb_sources |= ZPROP_SRC_INHERITED;
break;
case 3:
- cb.cb_sources |= ZPROP_SRC_TEMPORARY;
+ cb.cb_sources |= ZPROP_SRC_RECEIVED;
break;
case 4:
+ cb.cb_sources |= ZPROP_SRC_TEMPORARY;
+ break;
+ case 5:
cb.cb_sources |= ZPROP_SRC_NONE;
break;
default:
@@ -1345,9 +1399,10 @@ zfs_do_get(int argc, char **argv)
}
/*
- * inherit [-r] <property> <fs|vol> ...
+ * inherit [-rS] <property> <fs|vol> ...
*
- * -r Recurse over all children
+ * -r Recurse over all children
+ * -S Revert to received value, if any
*
* For each dataset specified on the command line, inherit the given property
* from its parent. Inheriting a property at the pool level will cause it to
@@ -1356,11 +1411,16 @@ zfs_do_get(int argc, char **argv)
* local modifications for each dataset.
*/
+typedef struct inherit_cbdata {
+ const char *cb_propname;
+ boolean_t cb_received;
+} inherit_cbdata_t;
+
static int
inherit_recurse_cb(zfs_handle_t *zhp, void *data)
{
- char *propname = data;
- zfs_prop_t prop = zfs_name_to_prop(propname);
+ inherit_cbdata_t *cb = data;
+ zfs_prop_t prop = zfs_name_to_prop(cb->cb_propname);
/*
* If we're doing it recursively, then ignore properties that
@@ -1370,15 +1430,15 @@ inherit_recurse_cb(zfs_handle_t *zhp, void *data)
!zfs_prop_valid_for_type(prop, zfs_get_type(zhp)))
return (0);
- return (zfs_prop_inherit(zhp, propname) != 0);
+ return (zfs_prop_inherit(zhp, cb->cb_propname, cb->cb_received) != 0);
}
static int
inherit_cb(zfs_handle_t *zhp, void *data)
{
- char *propname = data;
+ inherit_cbdata_t *cb = data;
- return (zfs_prop_inherit(zhp, propname) != 0);
+ return (zfs_prop_inherit(zhp, cb->cb_propname, cb->cb_received) != 0);
}
static int
@@ -1386,16 +1446,21 @@ zfs_do_inherit(int argc, char **argv)
{
int c;
zfs_prop_t prop;
+ inherit_cbdata_t cb = { 0 };
char *propname;
int ret;
int flags = 0;
+ boolean_t received = B_FALSE;
/* check options */
- while ((c = getopt(argc, argv, "r")) != -1) {
+ while ((c = getopt(argc, argv, "rS")) != -1) {
switch (c) {
case 'r':
flags |= ZFS_ITER_RECURSE;
break;
+ case 'S':
+ received = B_TRUE;
+ break;
case '?':
default:
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
@@ -1428,7 +1493,7 @@ zfs_do_inherit(int argc, char **argv)
propname);
return (1);
}
- if (!zfs_prop_inheritable(prop)) {
+ if (!zfs_prop_inheritable(prop) && !received) {
(void) fprintf(stderr, gettext("'%s' property cannot "
"be inherited\n"), propname);
if (prop == ZFS_PROP_QUOTA ||
@@ -1445,12 +1510,15 @@ zfs_do_inherit(int argc, char **argv)
usage(B_FALSE);
}
+ cb.cb_propname = propname;
+ cb.cb_received = received;
+
if (flags & ZFS_ITER_RECURSE) {
ret = zfs_for_each(argc, argv, flags, ZFS_TYPE_DATASET,
- NULL, NULL, 0, inherit_recurse_cb, propname);
+ NULL, NULL, 0, inherit_recurse_cb, &cb);
} else {
ret = zfs_for_each(argc, argv, flags, ZFS_TYPE_DATASET,
- NULL, NULL, 0, inherit_cb, propname);
+ NULL, NULL, 0, inherit_cb, &cb);
}
return (ret);
@@ -1775,11 +1843,11 @@ zfs_do_userspace(int argc, char **argv)
* [-s property [-s property]...] [-S property [-S property]...]
* <dataset> ...
*
- * -r Recurse over all children
- * -d Limit recursion by depth.
- * -H Scripted mode; elide headers and separate columns by tabs
- * -o Control which fields to display.
- * -t Control which object types to display.
+ * -r Recurse over all children
+ * -d Limit recursion by depth.
+ * -H Scripted mode; elide headers and separate columns by tabs
+ * -o Control which fields to display.
+ * -t Control which object types to display.
* -s Specify sort columns, descending order.
* -S Specify sort columns, ascending order.
*
@@ -2176,9 +2244,9 @@ zfs_do_promote(int argc, char **argv)
/*
* zfs rollback [-rRf] <snapshot>
*
- * -r Delete any intervening snapshots before doing rollback
- * -R Delete any snapshots and their clones
- * -f ignored for backwards compatability
+ * -r Delete any intervening snapshots before doing rollback
+ * -R Delete any snapshots and their clones
+ * -f ignored for backwards compatability
*
* Given a filesystem, rollback to a specific snapshot, discarding any changes
* since then and making it the active dataset. If more recent snapshots exist,
@@ -2488,8 +2556,8 @@ usage:
}
/*
- * zfs send [-vD] -R [-i|-I <@snap>] <fs@snap>
- * zfs send [-vD] [-i|-I <@snap>] <fs@snap>
+ * zfs send [-vDp] -R [-i|-I <@snap>] <fs@snap>
+ * zfs send [-vDp] [-i|-I <@snap>] <fs@snap>
*
* Send a backup stream to stdout.
*/
@@ -2504,7 +2572,7 @@ zfs_do_send(int argc, char **argv)
int c, err;
/* check options */
- while ((c = getopt(argc, argv, ":i:I:RDv")) != -1) {
+ while ((c = getopt(argc, argv, ":i:I:RDpv")) != -1) {
switch (c) {
case 'i':
if (fromname)
@@ -2520,6 +2588,9 @@ zfs_do_send(int argc, char **argv)
case 'R':
flags.replicate = B_TRUE;
break;
+ case 'p':
+ flags.props = B_TRUE;
+ break;
case 'v':
flags.verbose = B_TRUE;
break;
@@ -2620,9 +2691,8 @@ static int
zfs_do_receive(int argc, char **argv)
{
int c, err;
- recvflags_t flags;
+ recvflags_t flags = { 0 };
- bzero(&flags, sizeof (recvflags_t));
/* check options */
while ((c = getopt(argc, argv, ":dnuvF")) != -1) {
switch (c) {
@@ -2762,7 +2832,7 @@ zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding)
/*
* zfs hold [-r] [-t] <tag> <snap> ...
*
- * -r Recursively hold
+ * -r Recursively hold
* -t Temporary hold (hidden option)
*
* Apply a user-hold with the given tag to the list of snapshots.
@@ -2776,7 +2846,7 @@ zfs_do_hold(int argc, char **argv)
/*
* zfs release [-r] <tag> <snap> ...
*
- * -r Recursively release
+ * -r Recursively release
*
* Release a user-hold with the given tag from the list of snapshots.
*/