summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c31
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c31
-rw-r--r--usr/src/cmd/truss/codes.c10
-rw-r--r--usr/src/cmd/zdb/zdb.c3
-rw-r--r--usr/src/cmd/zfs/Makefile4
-rw-r--r--usr/src/cmd/zfs/zfs_main.c581
-rw-r--r--usr/src/cmd/zpool/zpool_main.c343
-rw-r--r--usr/src/cmd/ztest/ztest.c2
8 files changed, 824 insertions, 181 deletions
diff --git a/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c b/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c
index 3822265013..69e8c95725 100644
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c
+++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c
@@ -450,18 +450,31 @@ create_zfs(tgt_node_t *x, ucred_t *cred)
xmlTextReaderPtr r;
const priv_set_t *eset;
- eset = ucred_getprivset(cred, PRIV_EFFECTIVE);
- if (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) :
- ucred_geteuid(cred) != 0) {
- xml_rtn_msg(&msg, ERR_NO_PERMISSION);
+ if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) {
+ xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
goto error;
}
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
+ if (((zh = libzfs_init()) == NULL) ||
+ ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_ANY)) == NULL)) {
+ xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
goto error;
}
+ eset = ucred_getprivset(cred, PRIV_EFFECTIVE);
+ if (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) :
+ ucred_geteuid(cred) != 0) {
+
+ /*
+ * See if user has ZFS dataset permissions to do operation
+ */
+ if (zfs_iscsi_perm_check(zh, dataset, cred) != 0) {
+ xml_rtn_msg(&msg, ERR_NO_PERMISSION);
+ goto error;
+ }
+ }
+
+
while ((dnode = tgt_node_next(targets_config, XML_ELEMENT_TARG,
dnode)) != NULL) {
if (strcmp(dnode->x_value, dataset) == 0) {
@@ -470,12 +483,6 @@ create_zfs(tgt_node_t *x, ucred_t *cred)
}
}
- if (((zh = libzfs_init()) == NULL) ||
- ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_ANY)) == NULL)) {
- xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
- goto error;
- }
-
prop_len = 1024;
if ((prop = malloc(prop_len)) == NULL) {
xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
diff --git a/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c b/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c
index 0f907bb977..dd3c1f4434 100644
--- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c
+++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c
@@ -37,6 +37,7 @@
#include <unistd.h>
#include <priv.h>
#include <syslog.h>
+#include <libzfs.h>
#include <iscsitgt_impl.h>
#include "utility.h"
@@ -94,21 +95,37 @@ remove_zfs(tgt_node_t *x, ucred_t *cred)
{
char *prop;
char *msg = NULL;
- tgt_node_t *targ = NULL;
+ tgt_node_t *targ = NULL;
const priv_set_t *eset;
+ libzfs_handle_t *zh = NULL;
- eset = ucred_getprivset(cred, PRIV_EFFECTIVE);
- if (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) :
- ucred_geteuid(cred) != 0) {
- xml_rtn_msg(&msg, ERR_NO_PERMISSION);
+ if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) {
+ xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
return (msg);
}
- if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) {
- xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
+ if ((zh = libzfs_init()) == NULL) {
+ xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
+ free(prop);
return (msg);
}
+ eset = ucred_getprivset(cred, PRIV_EFFECTIVE);
+ if (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) :
+ ucred_geteuid(cred) != 0) {
+ /*
+ * See if user has ZFS dataset permissions to do operation
+ */
+ if (zfs_iscsi_perm_check(zh, prop, cred) != 0) {
+ xml_rtn_msg(&msg, ERR_NO_PERMISSION);
+ free(prop);
+ libzfs_fini(zh);
+ return (msg);
+ }
+ }
+
+ libzfs_fini(zh);
+
while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ))
!= NULL) {
if (strcmp(targ->x_value, prop) == 0)
diff --git a/usr/src/cmd/truss/codes.c b/usr/src/cmd/truss/codes.c
index dbc2ccca9e..4e59786350 100644
--- a/usr/src/cmd/truss/codes.c
+++ b/usr/src/cmd/truss/codes.c
@@ -864,8 +864,6 @@ const struct ioc {
"zfs_cmd_t" },
{ (uint_t)ZFS_IOC_POOL_GET_HISTORY, "ZFS_IOC_POOL_GET_HISTORY",
"zfs_cmd_t" },
- { (uint_t)ZFS_IOC_POOL_LOG_HISTORY, "ZFS_IOC_POOL_LOG_HISTORY",
- "zfs_cmd_t" },
{ (uint_t)ZFS_IOC_VDEV_ADD, "ZFS_IOC_VDEV_ADD",
"zfs_cmd_t" },
{ (uint_t)ZFS_IOC_VDEV_REMOVE, "ZFS_IOC_VDEV_REMOVE",
@@ -926,6 +924,14 @@ const struct ioc {
"zfs_cmd_t" },
{ (uint_t)ZFS_IOC_POOL_GET_PROPS, "ZFS_IOC_POOL_GET_PROPS",
"zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_SET_FSACL, "ZFS_IOC_SET_FSACL",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_GET_FSACL, "ZFS_IOC_GET_FSACL",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_ISCSI_PERM_CHECK, "ZFS_IOC_ISCSI_PERM_CHECK",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_SHARE, "ZFS_IOC_SHARE",
+ "zfs_cmd_t" },
/* kssl ioctls */
{ (uint_t)KSSL_ADD_ENTRY, "KSSL_ADD_ENTRY",
diff --git a/usr/src/cmd/zdb/zdb.c b/usr/src/cmd/zdb/zdb.c
index 41d61d2904..23cf656ebe 100644
--- a/usr/src/cmd/zdb/zdb.c
+++ b/usr/src/cmd/zdb/zdb.c
@@ -700,6 +700,8 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
(void) printf("\t\treserved = %s\n", resv);
(void) printf("\t\tprops_zapobj = %llu\n",
(u_longlong_t)dd->dd_props_zapobj);
+ (void) printf("\t\tdeleg_zapobj = %llu\n",
+ (u_longlong_t)dd->dd_deleg_zapobj);
}
/*ARGSUSED*/
@@ -888,6 +890,7 @@ static object_viewer_t *object_viewer[DMU_OT_NUMTYPES] = {
dump_uint8, /* SPA history */
dump_uint64, /* SPA history offsets */
dump_zap, /* Pool properties */
+ dump_zap, /* DSL permissions */
};
static void
diff --git a/usr/src/cmd/zfs/Makefile b/usr/src/cmd/zfs/Makefile
index 9b80822041..4761bea33e 100644
--- a/usr/src/cmd/zfs/Makefile
+++ b/usr/src/cmd/zfs/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -38,7 +38,7 @@ LINKPROGS= mount umount
ROOTETCFSTYPE= $(ROOTETC)/fs/$(FSTYPE)
USRLIBFSTYPE= $(ROOTLIB)/fs/$(FSTYPE)
-LDLIBS += -lzfs -luutil -lumem -lnvpair
+LDLIBS += -lzfs -luutil -lumem -lnvpair -lavl
C99MODE= -xc99=%all
C99LMODE= -Xc99=%all
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c
index 84dfaafedd..fd178add9e 100644
--- a/usr/src/cmd/zfs/zfs_main.c
+++ b/usr/src/cmd/zfs/zfs_main.c
@@ -32,6 +32,7 @@
#include <libgen.h>
#include <libintl.h>
#include <libuutil.h>
+#include <libnvpair.h>
#include <locale.h>
#include <stddef.h>
#include <stdio.h>
@@ -45,8 +46,10 @@
#include <sys/mnttab.h>
#include <sys/mount.h>
#include <sys/stat.h>
+#include <sys/avl.h>
#include <libzfs.h>
+#include <libuutil.h>
#include "zfs_iter.h"
#include "zfs_util.h"
@@ -72,6 +75,8 @@ static int zfs_do_unshare(int argc, char **argv);
static int zfs_do_send(int argc, char **argv);
static int zfs_do_receive(int argc, char **argv);
static int zfs_do_promote(int argc, char **argv);
+static int zfs_do_allow(int argc, char **argv);
+static int zfs_do_unallow(int argc, char **argv);
/*
* These libumem hooks provide a reasonable set of defaults for the allocator's
@@ -106,7 +111,9 @@ typedef enum {
HELP_SHARE,
HELP_SNAPSHOT,
HELP_UNMOUNT,
- HELP_UNSHARE
+ HELP_UNSHARE,
+ HELP_ALLOW,
+ HELP_UNALLOW
} zfs_help_t;
typedef struct zfs_command {
@@ -150,6 +157,10 @@ static zfs_command_t command_table[] = {
{ NULL },
{ "send", zfs_do_send, HELP_SEND },
{ "receive", zfs_do_receive, HELP_RECEIVE },
+ { NULL },
+ { "allow", zfs_do_allow, HELP_ALLOW },
+ { NULL },
+ { "unallow", zfs_do_unallow, HELP_UNALLOW },
};
#define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
@@ -220,6 +231,47 @@ get_usage(zfs_help_t idx)
case HELP_UNSHARE:
return (gettext("\tunshare [-f] -a\n"
"\tunshare [-f] <filesystem|mountpoint>\n"));
+ case HELP_ALLOW:
+ return (gettext("\tallow [-l][-d] <everyone|user|group>[,"
+ "<everyone|user|group>...]\n\t "
+ "<perm>|@<setname>[,<perm>|@<setname>...]\n\t"
+ " <filesystem|volume\n"
+ "\tallow [-l] [-d] -u <user> "
+ "<perm>|@<setname>[,<perm>|@<setname>...]\n\t"
+ " <filesystem|volume>\n"
+ "\tallow [-l] [-d] -g <group> "
+ "<perm>|@<setname>[,<perm>|@<setname>...]\n\t"
+ " <filesystem|volume>\n"
+ "\tallow [-l] [-d] -e "
+ "<perm>|@<setname>[,<perm>|@<setname>...]\n\t"
+ " <filesystem|volume>\n"
+ "\tallow -c "
+ "<perm>|@<setname>[,<perm>|@<setname>...]\n\t"
+ " <filesystem|volume>\n"
+ "\tallow -s @setname "
+ "<perm>|@<setname>[,<perm>|@<setname>...]\n\t"
+ " <filesystem|volume>\n"));
+
+ case HELP_UNALLOW:
+ return (gettext("\tunallow [-r][-l][-d] <everyone|user|group>[,"
+ "<everyone|user|group>...] \n\t "
+ "[<perm>|@<setname>[,<perm>|@<setname>...]]\n\t"
+ " <filesystem|volume>\n"
+ "\tunallow [-r][-l][-d] -u user "
+ "[<perm>|@<setname>[,<perm>|@<setname>...]]\n\t"
+ " <filesystem|volume>\n"
+ "\tunallow [-r][-l][-d] -g group "
+ "[<perm>|@<setname>[,<perm>|@<setname>...]]\n\t"
+ " <filesystem|volume>\n"
+ "\tunallow [-r][-l][-d] -e "
+ "[<perm>|@<setname>[,<perm>|@<setname>...]]\n\t"
+ " <filesystem|volume>\n"
+ "\tunallow [-r] -c "
+ "[<perm>|@<setname>[,<perm>|@<setname>...]]\n\t"
+ " <filesystem|volume>\n"
+ "\tunallow [-r] -s @setname "
+ "[<perm>|@<setname>[,<perm>|@<setname>...]]\n\t"
+ " <filesystem|volume> \n\t"));
}
abort();
@@ -426,8 +478,6 @@ zfs_do_clone(int argc, char **argv)
ret = zfs_share(clone);
zfs_close(clone);
}
- zpool_log_history(g_zfs, argc + optind, argv - optind, argv[1],
- B_FALSE, B_FALSE);
}
zfs_close(zhp);
@@ -598,11 +648,6 @@ zfs_do_create(int argc, char **argv)
if (zfs_create(g_zfs, argv[0], type, props) != 0)
goto error;
- if (propval != NULL)
- *(propval - 1) = '=';
- zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
- B_FALSE, B_FALSE);
-
if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL)
goto error;
@@ -848,9 +893,6 @@ zfs_do_destroy(int argc, char **argv)
if (ret) {
(void) fprintf(stderr,
gettext("no snapshots destroyed\n"));
- } else {
- zpool_log_history(g_zfs, argc + optind, argv - optind,
- argv[0], B_FALSE, B_FALSE);
}
return (ret != 0);
}
@@ -890,7 +932,6 @@ zfs_do_destroy(int argc, char **argv)
return (1);
}
-
if (cb.cb_error ||
zfs_iter_dependents(zhp, B_FALSE, destroy_callback, &cb) != 0) {
zfs_close(zhp);
@@ -901,11 +942,10 @@ zfs_do_destroy(int argc, char **argv)
* Do the real thing. The callback will close the handle regardless of
* whether it succeeds or not.
*/
+
if (destroy_callback(zhp, &cb) != 0)
return (1);
- zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
- B_FALSE, B_FALSE);
return (0);
}
@@ -1181,20 +1221,14 @@ zfs_do_get(int argc, char **argv)
* useful for setting a property on a hierarchy-wide basis, regardless of any
* local modifications for each dataset.
*/
-typedef struct inherit_cbdata {
- char *cb_propname;
- boolean_t cb_any_successful;
-} inherit_cbdata_t;
static int
inherit_callback(zfs_handle_t *zhp, void *data)
{
- inherit_cbdata_t *cbp = data;
+ char *propname = data;
int ret;
- ret = zfs_prop_inherit(zhp, cbp->cb_propname);
- if (ret == 0)
- cbp->cb_any_successful = B_TRUE;
+ ret = zfs_prop_inherit(zhp, propname);
return (ret != 0);
}
@@ -1204,7 +1238,7 @@ zfs_do_inherit(int argc, char **argv)
boolean_t recurse = B_FALSE;
int c;
zfs_prop_t prop;
- inherit_cbdata_t cb;
+ char *propname;
int ret;
/* check options */
@@ -1234,43 +1268,35 @@ zfs_do_inherit(int argc, char **argv)
usage(B_FALSE);
}
- cb.cb_propname = argv[0];
+ propname = argv[0];
argc--;
argv++;
- if ((prop = zfs_name_to_prop(cb.cb_propname)) != ZFS_PROP_INVAL) {
+ if ((prop = zfs_name_to_prop(propname)) != ZFS_PROP_INVAL) {
if (zfs_prop_readonly(prop)) {
(void) fprintf(stderr, gettext(
"%s property is read-only\n"),
- cb.cb_propname);
+ propname);
return (1);
}
if (!zfs_prop_inheritable(prop)) {
(void) fprintf(stderr, gettext("'%s' property cannot "
- "be inherited\n"), cb.cb_propname);
+ "be inherited\n"), propname);
if (prop == ZFS_PROP_QUOTA ||
prop == ZFS_PROP_RESERVATION)
(void) fprintf(stderr, gettext("use 'zfs set "
- "%s=none' to clear\n"), cb.cb_propname);
+ "%s=none' to clear\n"), propname);
return (1);
}
- } else if (!zfs_prop_user(cb.cb_propname)) {
- (void) fprintf(stderr, gettext(
- "invalid property '%s'\n"),
- cb.cb_propname);
+ } else if (!zfs_prop_user(propname)) {
+ (void) fprintf(stderr, gettext("invalid property '%s'\n"),
+ propname);
usage(B_FALSE);
}
- cb.cb_any_successful = B_FALSE;
-
ret = zfs_for_each(argc, argv, recurse,
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, NULL, NULL,
- inherit_callback, &cb, B_FALSE);
-
- if (cb.cb_any_successful) {
- zpool_log_history(g_zfs, argc + optind + 1, argv - optind - 1,
- argv[0], B_FALSE, B_FALSE);
- }
+ inherit_callback, propname, B_FALSE);
return (ret);
}
@@ -1606,10 +1632,6 @@ zfs_do_rename(int argc, char **argv)
ret = (zfs_rename(zhp, argv[1], recurse) != 0);
- if (!ret)
- zpool_log_history(g_zfs, argc + optind, argv - optind, argv[1],
- B_FALSE, B_FALSE);
-
zfs_close(zhp);
return (ret);
}
@@ -1650,8 +1672,6 @@ zfs_do_promote(int argc, char **argv)
ret = (zfs_promote(zhp) != 0);
- if (!ret)
- zpool_log_history(g_zfs, argc, argv, argv[1], B_FALSE, B_FALSE);
zfs_close(zhp);
return (ret);
@@ -1820,11 +1840,6 @@ zfs_do_rollback(int argc, char **argv)
*/
ret = zfs_rollback(zhp, snap, force);
- if (!ret) {
- zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
- B_FALSE, B_FALSE);
- }
-
out:
zfs_close(snap);
zfs_close(zhp);
@@ -1843,7 +1858,6 @@ out:
typedef struct set_cbdata {
char *cb_propname;
char *cb_value;
- boolean_t cb_any_successful;
} set_cbdata_t;
static int
@@ -1864,7 +1878,6 @@ set_callback(zfs_handle_t *zhp, void *data)
}
return (1);
}
- cbp->cb_any_successful = B_TRUE;
return (0);
}
@@ -1902,7 +1915,6 @@ zfs_do_set(int argc, char **argv)
*cb.cb_value = '\0';
cb.cb_value++;
- cb.cb_any_successful = B_FALSE;
if (*cb.cb_propname == '\0') {
(void) fprintf(stderr,
@@ -1910,14 +1922,10 @@ zfs_do_set(int argc, char **argv)
usage(B_FALSE);
}
+
ret = zfs_for_each(argc - 2, argv + 2, B_FALSE,
ZFS_TYPE_ANY, NULL, NULL, set_callback, &cb, B_FALSE);
- if (cb.cb_any_successful) {
- *(cb.cb_value - 1) = '=';
- zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE);
- }
-
return (ret);
}
@@ -1963,10 +1971,6 @@ zfs_do_snapshot(int argc, char **argv)
ret = zfs_snapshot(g_zfs, argv[0], recursive);
if (ret && recursive)
(void) fprintf(stderr, gettext("no snapshots were created\n"));
- if (!ret) {
- zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
- B_FALSE, B_FALSE);
- }
return (ret != 0);
}
@@ -2117,12 +2121,386 @@ zfs_do_receive(int argc, char **argv)
err = zfs_receive(g_zfs, argv[0], isprefix, verbose, dryrun, force,
STDIN_FILENO);
- if (!err) {
- zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
- B_FALSE, B_FALSE);
+ return (err != 0);
+}
+
+typedef struct allow_cb {
+ int a_permcnt;
+ size_t a_treeoffset;
+} allow_cb_t;
+
+static void
+zfs_print_perms(avl_tree_t *tree)
+{
+ zfs_perm_node_t *permnode;
+
+ permnode = avl_first(tree);
+ while (permnode != NULL) {
+ (void) printf("%s", permnode->z_pname);
+ permnode = AVL_NEXT(tree, permnode);
+ if (permnode)
+ (void) printf(",");
+ else
+ (void) printf("\n");
}
+}
- return (err != 0);
+/*
+ * Iterate over user/groups/everyone/... and the call perm_iter
+ * function to print actual permission when tree has >0 nodes.
+ */
+static void
+zfs_iter_perms(avl_tree_t *tree, const char *banner, allow_cb_t *cb)
+{
+ zfs_allow_node_t *item;
+ avl_tree_t *ptree;
+
+ item = avl_first(tree);
+ while (item) {
+ ptree = (void *)((char *)item + cb->a_treeoffset);
+ if (avl_numnodes(ptree)) {
+ if (cb->a_permcnt++ == 0)
+ (void) printf("%s\n", banner);
+ (void) printf("\t%s", item->z_key);
+ /*
+ * Avoid an extra space being printed
+ * for "everyone" which is keyed with a null
+ * string
+ */
+ if (item->z_key[0] != '\0')
+ (void) printf(" ");
+ zfs_print_perms(ptree);
+ }
+ item = AVL_NEXT(tree, item);
+ }
+}
+
+#define LINES "-------------------------------------------------------------\n"
+static int
+zfs_print_allows(char *ds)
+{
+ zfs_allow_t *curperms, *perms;
+ zfs_handle_t *zhp;
+ allow_cb_t allowcb = { 0 };
+ char banner[MAXPATHLEN];
+
+ if (ds[0] == '-')
+ usage(B_FALSE);
+
+ if (strrchr(ds, '@')) {
+ (void) fprintf(stderr, gettext("Snapshots don't have 'allow'"
+ " permissions\n"));
+ return (1);
+ }
+ if ((zhp = zfs_open(g_zfs, ds, ZFS_TYPE_ANY)) == NULL)
+ return (1);
+
+ if (zfs_perm_get(zhp, &perms)) {
+ (void) fprintf(stderr,
+ gettext("Failed to retrieve 'allows' on %s\n"), ds);
+ zfs_close(zhp);
+ return (1);
+ }
+
+ zfs_close(zhp);
+
+ if (perms != NULL)
+ (void) printf("%s", LINES);
+ for (curperms = perms; curperms; curperms = curperms->z_next) {
+
+ (void) snprintf(banner, sizeof (banner),
+ "Permission sets on (%s)", curperms->z_setpoint);
+ allowcb.a_treeoffset =
+ offsetof(zfs_allow_node_t, z_localdescend);
+ allowcb.a_permcnt = 0;
+ zfs_iter_perms(&curperms->z_sets, banner, &allowcb);
+
+ (void) snprintf(banner, sizeof (banner),
+ "Create time permissions on (%s)", curperms->z_setpoint);
+ allowcb.a_treeoffset =
+ offsetof(zfs_allow_node_t, z_localdescend);
+ allowcb.a_permcnt = 0;
+ zfs_iter_perms(&curperms->z_crperms, banner, &allowcb);
+
+
+ (void) snprintf(banner, sizeof (banner),
+ "Local permissions on (%s)", curperms->z_setpoint);
+ allowcb.a_treeoffset = offsetof(zfs_allow_node_t, z_local);
+ allowcb.a_permcnt = 0;
+ zfs_iter_perms(&curperms->z_user, banner, &allowcb);
+ zfs_iter_perms(&curperms->z_group, banner, &allowcb);
+ zfs_iter_perms(&curperms->z_everyone, banner, &allowcb);
+
+ (void) snprintf(banner, sizeof (banner),
+ "Descendent permissions on (%s)", curperms->z_setpoint);
+ allowcb.a_treeoffset = offsetof(zfs_allow_node_t, z_descend);
+ allowcb.a_permcnt = 0;
+ zfs_iter_perms(&curperms->z_user, banner, &allowcb);
+ zfs_iter_perms(&curperms->z_group, banner, &allowcb);
+ zfs_iter_perms(&curperms->z_everyone, banner, &allowcb);
+
+ (void) snprintf(banner, sizeof (banner),
+ "Local+Descendent permissions on (%s)",
+ curperms->z_setpoint);
+ allowcb.a_treeoffset =
+ offsetof(zfs_allow_node_t, z_localdescend);
+ allowcb.a_permcnt = 0;
+ zfs_iter_perms(&curperms->z_user, banner, &allowcb);
+ zfs_iter_perms(&curperms->z_group, banner, &allowcb);
+ zfs_iter_perms(&curperms->z_everyone, banner, &allowcb);
+
+ (void) printf("%s", LINES);
+ }
+ zfs_free_allows(perms);
+ return (0);
+}
+
+#define ALLOWOPTIONS "ldcsu:g:e"
+#define UNALLOWOPTIONS "ldcsu:g:er"
+
+/*
+ * Validate options, and build necessary datastructure to display/remove/add
+ * permissions.
+ * Returns 0 - If permissions should be added/removed
+ * Returns 1 - If permissions should be displayed.
+ * Returns -1 - on failure
+ */
+int
+parse_allow_args(int *argc, char **argv[], boolean_t unallow,
+ char **ds, int *recurse, nvlist_t **zperms)
+{
+ int c;
+ char *options = unallow ? UNALLOWOPTIONS : ALLOWOPTIONS;
+ zfs_deleg_inherit_t deleg_type = ZFS_DELEG_NONE;
+ zfs_deleg_who_type_t who_type = ZFS_DELEG_WHO_UNKNOWN;
+ char *who;
+ char *perms = NULL;
+ zfs_handle_t *zhp;
+
+ while ((c = getopt(*argc, *argv, options)) != -1) {
+ switch (c) {
+ case 'l':
+ if (who_type == ZFS_DELEG_CREATE ||
+ who_type == ZFS_DELEG_NAMED_SET)
+ usage(B_FALSE);
+
+ deleg_type |= ZFS_DELEG_PERM_LOCAL;
+ break;
+ case 'd':
+ if (who_type == ZFS_DELEG_CREATE ||
+ who_type == ZFS_DELEG_NAMED_SET)
+ usage(B_FALSE);
+
+ deleg_type |= ZFS_DELEG_PERM_DESCENDENT;
+ break;
+ case 'r':
+ *recurse = B_TRUE;
+ break;
+ case 'c':
+ if (who_type != ZFS_DELEG_WHO_UNKNOWN)
+ usage(B_FALSE);
+ if (deleg_type)
+ usage(B_FALSE);
+ who_type = ZFS_DELEG_CREATE;
+ break;
+ case 's':
+ if (who_type != ZFS_DELEG_WHO_UNKNOWN)
+ usage(B_FALSE);
+ if (deleg_type)
+ usage(B_FALSE);
+ who_type = ZFS_DELEG_NAMED_SET;
+ break;
+ case 'u':
+ if (who_type != ZFS_DELEG_WHO_UNKNOWN)
+ usage(B_FALSE);
+ who_type = ZFS_DELEG_USER;
+ who = optarg;
+ break;
+ case 'g':
+ if (who_type != ZFS_DELEG_WHO_UNKNOWN)
+ usage(B_FALSE);
+ who_type = ZFS_DELEG_GROUP;
+ who = optarg;
+ break;
+ case 'e':
+ if (who_type != ZFS_DELEG_WHO_UNKNOWN)
+ usage(B_FALSE);
+ who_type = ZFS_DELEG_EVERYONE;
+ break;
+ default:
+ usage(B_FALSE);
+ break;
+ }
+ }
+
+ if (deleg_type == 0)
+ deleg_type = ZFS_DELEG_PERM_LOCALDESCENDENT;
+
+ *argc -= optind;
+ *argv += optind;
+
+ if (unallow == B_FALSE && *argc == 1) {
+ /*
+ * Only print permissions if no options were processed
+ */
+ if (optind == 1)
+ return (1);
+ else
+ usage(B_FALSE);
+ }
+
+ /*
+ * initialize variables for zfs_build_perms based on number
+ * of arguments.
+ * 3 arguments ==> zfs [un]allow joe perm,perm,perm <dataset> or
+ * zfs [un]allow -s @set1 perm,perm <dataset>
+ * 2 arguments ==> zfs [un]allow -c perm,perm <dataset> or
+ * zfs [un]allow -u|-g <name> perm <dataset> or
+ * zfs [un]allow -e perm,perm <dataset>
+ * zfs unallow joe <dataset>
+ * zfs unallow -s @set1 <dataset>
+ * 1 argument ==> zfs [un]allow -e <dataset> or
+ * zfs [un]allow -c <dataset>
+ */
+
+ switch (*argc) {
+ case 3:
+ perms = (*argv)[1];
+ who = (*argv)[0];
+ *ds = (*argv)[2];
+
+ /*
+ * advance argc/argv for do_allow cases.
+ * for do_allow case make sure who have a know who type
+ * and its not a permission set.
+ */
+ if (unallow == B_TRUE) {
+ *argc -= 2;
+ *argv += 2;
+ } else if (who_type != ZFS_DELEG_WHO_UNKNOWN &&
+ who_type != ZFS_DELEG_NAMED_SET)
+ usage(B_FALSE);
+ break;
+
+ case 2:
+ if (unallow == B_TRUE && (who_type == ZFS_DELEG_EVERYONE ||
+ who_type == ZFS_DELEG_CREATE || who != NULL)) {
+ perms = (*argv)[0];
+ *ds = (*argv)[1];
+ } else {
+ if (unallow == B_FALSE &&
+ (who_type == ZFS_DELEG_WHO_UNKNOWN ||
+ who_type == ZFS_DELEG_NAMED_SET))
+ usage(B_FALSE);
+ else if (who_type == ZFS_DELEG_WHO_UNKNOWN ||
+ who_type == ZFS_DELEG_NAMED_SET)
+ who = (*argv)[0];
+ else if (who_type != ZFS_DELEG_NAMED_SET)
+ perms = (*argv)[0];
+ *ds = (*argv)[1];
+ }
+ if (unallow == B_TRUE) {
+ (*argc)--;
+ (*argv)++;
+ }
+ break;
+
+ case 1:
+ if (unallow == B_FALSE)
+ usage(B_FALSE);
+ if (who == NULL && who_type != ZFS_DELEG_CREATE &&
+ who_type != ZFS_DELEG_EVERYONE)
+ usage(B_FALSE);
+ *ds = (*argv)[0];
+ break;
+
+ default:
+ usage(B_FALSE);
+ }
+
+ if (strrchr(*ds, '@')) {
+ (void) fprintf(stderr,
+ gettext("Can't set or remove 'allow' permissions "
+ "on snapshots.\n"));
+ return (-1);
+ }
+
+ if ((zhp = zfs_open(g_zfs, *ds, ZFS_TYPE_ANY)) == NULL)
+ return (-1);
+
+ if ((zfs_build_perms(zhp, who, perms,
+ who_type, deleg_type, zperms)) != 0) {
+ zfs_close(zhp);
+ return (-1);
+ }
+ zfs_close(zhp);
+ return (0);
+}
+
+static int
+zfs_do_allow(int argc, char **argv)
+{
+ char *ds;
+ nvlist_t *zperms = NULL;
+ zfs_handle_t *zhp;
+ int unused;
+ int ret;
+
+ if ((ret = parse_allow_args(&argc, &argv, B_FALSE, &ds,
+ &unused, &zperms)) == -1)
+ return (1);
+
+ if (ret == 1)
+ return (zfs_print_allows(argv[0]));
+
+ if ((zhp = zfs_open(g_zfs, ds, ZFS_TYPE_ANY)) == NULL)
+ return (1);
+
+ if (zfs_perm_set(zhp, zperms)) {
+ zfs_close(zhp);
+ nvlist_free(zperms);
+ return (1);
+ }
+ nvlist_free(zperms);
+ zfs_close(zhp);
+
+ return (0);
+}
+
+static int
+unallow_callback(zfs_handle_t *zhp, void *data)
+{
+ nvlist_t *nvp = (nvlist_t *)data;
+ int error;
+
+ error = zfs_perm_remove(zhp, nvp);
+ if (error) {
+ (void) fprintf(stderr, gettext("Failed to remove permissions "
+ "on %s\n"), zfs_get_name(zhp));
+ }
+ return (error);
+}
+
+static int
+zfs_do_unallow(int argc, char **argv)
+{
+ int recurse = B_FALSE;
+ char *ds;
+ int error;
+ nvlist_t *zperms = NULL;
+
+ if (parse_allow_args(&argc, &argv, B_TRUE,
+ &ds, &recurse, &zperms) == -1)
+ return (1);
+
+ error = zfs_for_each(argc, argv, recurse,
+ ZFS_TYPE_FILESYSTEM|ZFS_TYPE_VOLUME, NULL,
+ NULL, unallow_callback, (void *)zperms, B_FALSE);
+
+ if (zperms)
+ nvlist_free(zperms);
+
+ return (error);
}
typedef struct get_all_cbdata {
@@ -3143,6 +3521,34 @@ do_volcheck(boolean_t isinit)
return (zpool_iter(g_zfs, volcheck, &isinit) ? 1 : 0);
}
+static int
+find_command_idx(char *command, int *idx)
+{
+ int i;
+
+ for (i = 0; i < NCOMMAND; i++) {
+ if (command_table[i].name == NULL)
+ continue;
+
+ if (strcmp(command, command_table[i].name) == 0) {
+ *idx = i;
+ return (0);
+ }
+ }
+ return (1);
+}
+
+zfs_prop_t
+propset_cb(zfs_prop_t prop, void *data)
+{
+ char *cmdname = (char *)data;
+
+ if (strcmp(cmdname, zfs_prop_to_name(prop)) == 0)
+ return (prop);
+
+ return (ZFS_PROP_CONT);
+}
+
int
main(int argc, char **argv)
{
@@ -3150,6 +3556,8 @@ main(int argc, char **argv)
int i;
char *progname;
char *cmdname;
+ char *str;
+ boolean_t found = B_FALSE;
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
@@ -3162,6 +3570,8 @@ main(int argc, char **argv)
return (1);
}
+ zpool_stage_history(g_zfs, argc, argv, B_TRUE, B_FALSE);
+
libzfs_print_on_error(g_zfs, B_TRUE);
if ((mnttab_file = fopen(MNTTAB, "r")) == NULL) {
@@ -3220,18 +3630,41 @@ main(int argc, char **argv)
/*
* Run the appropriate command.
*/
- for (i = 0; i < NCOMMAND; i++) {
- if (command_table[i].name == NULL)
- continue;
+ if (find_command_idx(cmdname, &i) == 0) {
+ current_command = &command_table[i];
+ ret = command_table[i].func(argc - 1, argv + 1);
+ found = B_TRUE;
+ }
- if (strcmp(cmdname, command_table[i].name) == 0) {
+ /*
+ * Check and see if they are doing property=value
+ */
+ if (found == B_FALSE &&
+ ((str = strchr(cmdname, '=')) != NULL)) {
+ *str = '\0';
+ if (zfs_prop_iter(propset_cb, cmdname,
+ B_FALSE) != ZFS_PROP_INVAL)
+ found = B_TRUE;
+
+ if (found == B_FALSE && zfs_prop_user(cmdname))
+ found = B_TRUE;
+
+ if (found == B_TRUE &&
+ find_command_idx("set", &i) == 0) {
+ *str = '=';
current_command = &command_table[i];
- ret = command_table[i].func(argc - 1, argv + 1);
- break;
+ ret = command_table[i].func(argc, argv);
+ } else {
+ (void) fprintf(stderr,
+ gettext("invalid property '%s'\n"),
+ cmdname);
+ found = B_TRUE;
+ ret = 1;
}
+
}
- if (i == NCOMMAND) {
+ if (found == B_FALSE) {
(void) fprintf(stderr, gettext("unrecognized "
"command '%s'\n"), cmdname);
usage(B_FALSE);
diff --git a/usr/src/cmd/zpool/zpool_main.c b/usr/src/cmd/zpool/zpool_main.c
index 6dc540299f..0bd2146ec5 100644
--- a/usr/src/cmd/zpool/zpool_main.c
+++ b/usr/src/cmd/zpool/zpool_main.c
@@ -41,6 +41,8 @@
#include <strings.h>
#include <unistd.h>
#include <priv.h>
+#include <pwd.h>
+#include <zone.h>
#include <sys/fs/zfs.h>
#include <sys/stat.h>
@@ -188,12 +190,13 @@ get_usage(zpool_help_t idx) {
case HELP_EXPORT:
return (gettext("\texport [-f] <pool> ...\n"));
case HELP_HISTORY:
- return (gettext("\thistory [<pool>]\n"));
+ return (gettext("\thistory [-il] [<pool>] ...\n"));
case HELP_IMPORT:
return (gettext("\timport [-d dir] [-D]\n"
- "\timport [-d dir] [-D] [-f] [-o opts] [-R root] -a\n"
- "\timport [-d dir] [-D] [-f] [-o opts] [-R root ]"
- " <pool | id> [newpool]\n"));
+ "\timport [-p property=value] [-d dir] [-D] [-f] "
+ "[-o opts] [-R root] -a\n"
+ "\timport [-p property=value] [-d dir] [-D] [-f] \n"
+ "\t [-o opts] [-R root ] <pool | id> [newpool]\n"));
case HELP_IOSTAT:
return (gettext("\tiostat [-v] [pool] ... [interval "
"[count]]\n"));
@@ -524,10 +527,6 @@ zpool_do_add(int argc, char **argv)
ret = 0;
} else {
ret = (zpool_add(zhp, nvroot) != 0);
- if (!ret) {
- zpool_log_history(g_zfs, argc + 1 + optind,
- argv - 1 - optind, poolname, B_TRUE, B_FALSE);
- }
}
nvlist_free(nvroot);
@@ -569,10 +568,6 @@ zpool_do_remove(int argc, char **argv)
return (1);
ret = (zpool_vdev_remove(zhp, argv[1]) != 0);
- if (!ret) {
- zpool_log_history(g_zfs, ++argc, --argv, poolname, B_TRUE,
- B_FALSE);
- }
return (ret);
}
@@ -767,8 +762,6 @@ zpool_do_create(int argc, char **argv)
ret = zfs_share_nfs(pool);
zfs_close(pool);
}
- zpool_log_history(g_zfs, argc + optind, argv - optind,
- poolname, B_TRUE, B_TRUE);
} else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
(void) fprintf(stderr, gettext("pool name may have "
"been omitted\n"));
@@ -841,9 +834,6 @@ zpool_do_destroy(int argc, char **argv)
return (1);
}
- zpool_log_history(g_zfs, argc + optind, argv - optind, pool, B_TRUE,
- B_FALSE);
-
ret = (zpool_destroy(zhp) != 0);
zpool_close(zhp);
@@ -904,9 +894,6 @@ zpool_do_export(int argc, char **argv)
continue;
}
- zpool_log_history(g_zfs, argc + optind, argv - optind, argv[i],
- B_TRUE, B_FALSE);
-
if (zpool_export(zhp) != 0)
ret = 1;
@@ -1219,12 +1206,13 @@ show_import(nvlist_t *config)
*/
static int
do_import(nvlist_t *config, const char *newname, const char *mntopts,
- const char *altroot, int force, int argc, char **argv)
+ const char *altroot, int force, nvlist_t *props)
{
zpool_handle_t *zhp;
char *name;
uint64_t state;
uint64_t version;
+ int error = 0;
verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
&name) == 0);
@@ -1277,17 +1265,33 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
if (newname != NULL)
name = (char *)newname;
- zpool_log_history(g_zfs, argc, argv, name, B_TRUE, B_FALSE);
-
verify((zhp = zpool_open(g_zfs, name)) != NULL);
+ if (props) {
+ nvpair_t *pair = nvlist_next_nvpair(props, NULL);
+ char *value;
+
+ if (pair != NULL) {
+ do {
+ verify((nvpair_value_string(pair,
+ &value)) == 0);
+
+ if ((error = zpool_set_prop(zhp,
+ nvpair_name(pair), value)) != 0)
+ break;
+
+ } while (pair = nvlist_next_nvpair(props, pair));
+ }
+ }
+
+
if (zpool_enable_datasets(zhp, mntopts, 0) != 0) {
zpool_close(zhp);
return (1);
}
zpool_close(zhp);
- return (0);
+ return (error);
}
/*
@@ -1309,6 +1313,10 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
*
* -a Import all pools found.
*
+ * -o temporary mount options.
+ *
+ * -p property=value
+ *
* The import command scans for pools to import, and import pools based on pool
* name and GUID. The pool can also be renamed as part of the import process.
*/
@@ -1329,12 +1337,15 @@ zpool_do_import(int argc, char **argv)
nvlist_t *config;
uint64_t searchguid;
char *searchname;
+ char *propname;
+ char *propval, *strval;
nvlist_t *found_config;
+ nvlist_t *props = NULL;
boolean_t first;
uint64_t pool_state;
/* check options */
- while ((c = getopt(argc, argv, ":Dfd:R:ao:")) != -1) {
+ while ((c = getopt(argc, argv, ":Dfd:R:ao:p:")) != -1) {
switch (c) {
case 'a':
do_all = B_TRUE;
@@ -1369,6 +1380,48 @@ zpool_do_import(int argc, char **argv)
"'%c' option\n"), optopt);
usage(B_FALSE);
break;
+ case 'p':
+ if (props == NULL &&
+ nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
+ (void) fprintf(stderr,
+ gettext("internal error: "
+ "out of memory\n"));
+ err = B_TRUE;
+ goto error;
+ }
+
+ propname = optarg;
+ if ((propval = strchr(propname, '=')) == NULL) {
+ (void) fprintf(stderr, gettext("missing "
+ "'=' for -o option\n"));
+ err = B_TRUE;
+ goto error;
+ }
+ *propval = '\0';
+ propval++;
+
+ if (zpool_name_to_prop(propname) == ZFS_PROP_INVAL) {
+ (void) fprintf(stderr,
+ gettext("property '%s' is "
+ "not a valid pool property\n"), propname);
+ err = B_TRUE;
+ goto error;
+ }
+
+ if (nvlist_lookup_string(props, propname,
+ &strval) == 0) {
+ (void) fprintf(stderr, gettext("property '%s' "
+ "specified multiple times\n"), propname);
+ err = B_TRUE;
+ goto error;
+ }
+ if (nvlist_add_string(props, propname, propval) != 0) {
+ (void) fprintf(stderr, gettext("internal "
+ "error: out of memory\n"));
+ err = B_TRUE;
+ goto error;
+ }
+ break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -1463,8 +1516,7 @@ zpool_do_import(int argc, char **argv)
if (do_all)
err |= do_import(config, NULL, mntopts,
- altroot, do_force, argc + optind,
- argv - optind);
+ altroot, do_force, props);
else
show_import(config);
} else if (searchname != NULL) {
@@ -1512,8 +1564,7 @@ zpool_do_import(int argc, char **argv)
err = B_TRUE;
} else {
err |= do_import(found_config, argc == 1 ? NULL :
- argv[1], mntopts, altroot, do_force, argc + optind,
- argv - optind);
+ argv[1], mntopts, altroot, do_force, props);
}
}
@@ -1525,6 +1576,9 @@ zpool_do_import(int argc, char **argv)
(void) fprintf(stderr,
gettext("no pools available to import\n"));
+error:
+ if (props)
+ nvlist_free(props);
nvlist_free(pools);
free(searchdirs);
@@ -2172,8 +2226,6 @@ zpool_do_attach_or_replace(int argc, char **argv, int replacing)
char *poolname, *old_disk, *new_disk;
zpool_handle_t *zhp;
int ret;
- int log_argc;
- char **log_argv;
/* check options */
while ((c = getopt(argc, argv, "f")) != -1) {
@@ -2188,8 +2240,6 @@ zpool_do_attach_or_replace(int argc, char **argv, int replacing)
}
}
- log_argc = argc;
- log_argv = argv;
argc -= optind;
argv += optind;
@@ -2247,11 +2297,6 @@ zpool_do_attach_or_replace(int argc, char **argv, int replacing)
ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
- if (!ret) {
- zpool_log_history(g_zfs, log_argc, log_argv, poolname, B_TRUE,
- B_FALSE);
- }
-
nvlist_free(nvroot);
zpool_close(zhp);
@@ -2341,10 +2386,6 @@ zpool_do_detach(int argc, char **argv)
ret = zpool_vdev_detach(zhp, path);
- if (!ret) {
- zpool_log_history(g_zfs, argc + optind, argv - optind, poolname,
- B_TRUE, B_FALSE);
- }
zpool_close(zhp);
return (ret);
@@ -2411,10 +2452,6 @@ zpool_do_online(int argc, char **argv)
}
}
- if (!ret) {
- zpool_log_history(g_zfs, argc + optind, argv - optind, poolname,
- B_TRUE, B_FALSE);
- }
zpool_close(zhp);
return (ret);
@@ -2477,10 +2514,6 @@ zpool_do_offline(int argc, char **argv)
ret = 1;
}
- if (!ret) {
- zpool_log_history(g_zfs, argc + optind, argv - optind, poolname,
- B_TRUE, B_FALSE);
- }
zpool_close(zhp);
return (ret);
@@ -2517,8 +2550,6 @@ zpool_do_clear(int argc, char **argv)
if (zpool_clear(zhp, device) != 0)
ret = 1;
- if (!ret)
- zpool_log_history(g_zfs, argc, argv, pool, B_TRUE, B_FALSE);
zpool_close(zhp);
return (ret);
@@ -2547,11 +2578,6 @@ scrub_callback(zpool_handle_t *zhp, void *data)
err = zpool_scrub(zhp, cb->cb_type);
- if (!err) {
- zpool_log_history(g_zfs, cb->cb_argc, cb->cb_argv,
- zpool_get_name(zhp), B_TRUE, B_FALSE);
- }
-
return (err != 0);
}
@@ -3223,9 +3249,6 @@ upgrade_cb(zpool_handle_t *zhp, void *arg)
cbp->cb_first = B_FALSE;
ret = zpool_upgrade(zhp);
if (!ret) {
- zpool_log_history(g_zfs, cbp->cb_argc,
- cbp->cb_argv, zpool_get_name(zhp), B_TRUE,
- B_FALSE);
(void) printf(gettext("Successfully upgraded "
"'%s'\n"), zpool_get_name(zhp));
}
@@ -3257,7 +3280,6 @@ upgrade_one(zpool_handle_t *zhp, void *data)
nvlist_t *config;
uint64_t version;
int ret;
- upgrade_cbdata_t *cbp = data;
config = zpool_get_config(zhp, NULL);
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
@@ -3278,8 +3300,6 @@ upgrade_one(zpool_handle_t *zhp, void *data)
ret = zpool_upgrade(zhp);
if (!ret) {
- zpool_log_history(g_zfs, cbp->cb_argc, cbp->cb_argv,
- zpool_get_name(zhp), B_TRUE, B_FALSE);
(void) printf(gettext("Successfully upgraded '%s' "
"from version %llu to version %llu\n"), zpool_get_name(zhp),
(u_longlong_t)version, (u_longlong_t)ZFS_VERSION);
@@ -3357,8 +3377,9 @@ zpool_do_upgrade(int argc, char **argv)
(void) printf(gettext(" 4 zpool history\n"));
(void) printf(gettext(" 5 Compression using the gzip "
"algorithm\n"));
- (void) printf(gettext(" 6 pool properties "));
+ (void) printf(gettext(" 6 pool properties\n"));
(void) printf(gettext(" 7 Separate intent log devices\n"));
+ (void) printf(gettext(" 8 Delegated administration\n"));
(void) printf(gettext("For more information on a particular "
"version, including supported releases, see:\n\n"));
(void) printf("http://www.opensolaris.org/os/community/zfs/"
@@ -3399,6 +3420,49 @@ zpool_do_upgrade(int argc, char **argv)
return (ret);
}
+typedef struct hist_cbdata {
+ boolean_t first;
+ int longfmt;
+ int internal;
+} hist_cbdata_t;
+
+char *hist_event_table[LOG_END] = {
+ "invalid event",
+ "pool create",
+ "vdev add",
+ "pool remove",
+ "pool destroy",
+ "pool export",
+ "pool import",
+ "vdev attach",
+ "vdev replace",
+ "vdev detach",
+ "vdev online",
+ "vdev offline",
+ "vdev upgrade",
+ "pool clear",
+ "pool scrub",
+ "pool property set",
+ "create",
+ "clone",
+ "destroy",
+ "destroy_begin_sync",
+ "inherit",
+ "property set",
+ "quota set",
+ "permission update",
+ "permission remove",
+ "permission who remove",
+ "promote",
+ "receive",
+ "rename",
+ "reservation set",
+ "replay_inc_sync",
+ "replay_full_sync",
+ "rollback",
+ "snapshot",
+};
+
/*
* Print out the command history for a specific pool.
*/
@@ -3409,13 +3473,22 @@ get_history_one(zpool_handle_t *zhp, void *data)
nvlist_t **records;
uint_t numrecords;
char *cmdstr;
+ char *pathstr;
uint64_t dst_time;
time_t tsec;
struct tm t;
char tbuf[30];
int ret, i;
+ uint64_t who;
+ struct passwd *pwd;
+ char *hostname;
+ char *zonename;
+ char internalstr[MAXPATHLEN];
+ hist_cbdata_t *cb = (hist_cbdata_t *)data;
+ uint64_t txg;
+ uint64_t ievent;
- *(boolean_t *)data = B_FALSE;
+ cb->first = B_FALSE;
(void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
@@ -3426,14 +3499,65 @@ get_history_one(zpool_handle_t *zhp, void *data)
&records, &numrecords) == 0);
for (i = 0; i < numrecords; i++) {
if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME,
- &dst_time) == 0) {
- verify(nvlist_lookup_string(records[i], ZPOOL_HIST_CMD,
- &cmdstr) == 0);
- tsec = dst_time;
- (void) localtime_r(&tsec, &t);
- (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
- (void) printf("%s %s\n", tbuf, cmdstr);
+ &dst_time) != 0)
+ continue;
+
+ /* is it an internal event or a standard event? */
+ if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD,
+ &cmdstr) != 0) {
+ if (cb->internal == 0)
+ continue;
+
+ if (nvlist_lookup_uint64(records[i],
+ ZPOOL_HIST_INT_EVENT, &ievent) != 0)
+ continue;
+ verify(nvlist_lookup_uint64(records[i],
+ ZPOOL_HIST_TXG, &txg) == 0);
+ verify(nvlist_lookup_string(records[i],
+ ZPOOL_HIST_INT_STR, &pathstr) == 0);
+ if (ievent > LOG_END)
+ continue;
+ (void) snprintf(internalstr,
+ sizeof (internalstr),
+ "[internal %s txg:%lld] %s",
+ hist_event_table[ievent], txg,
+ pathstr);
+ cmdstr = internalstr;
}
+ tsec = dst_time;
+ (void) localtime_r(&tsec, &t);
+ (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
+ (void) printf("%s %s", tbuf, cmdstr);
+
+ if (!cb->longfmt) {
+ (void) printf("\n");
+ continue;
+ }
+ (void) printf(" [");
+ if (nvlist_lookup_uint64(records[i],
+ ZPOOL_HIST_WHO, &who) == 0) {
+ pwd = getpwuid((uid_t)who);
+ if (pwd)
+ (void) printf("user %s on",
+ pwd->pw_name);
+ else
+ (void) printf("user %d on",
+ (int)who);
+ } else {
+ (void) printf(gettext("no info]\n"));
+ continue;
+ }
+ if (nvlist_lookup_string(records[i],
+ ZPOOL_HIST_HOST, &hostname) == 0) {
+ (void) printf(" %s", hostname);
+ }
+ if (nvlist_lookup_string(records[i],
+ ZPOOL_HIST_ZONE, &zonename) == 0) {
+ (void) printf(":%s", zonename);
+ }
+
+ (void) printf("]");
+ (void) printf("\n");
}
(void) printf("\n");
nvlist_free(nvhis);
@@ -3446,19 +3570,38 @@ get_history_one(zpool_handle_t *zhp, void *data)
*
* Displays the history of commands that modified pools.
*/
+
+
int
zpool_do_history(int argc, char **argv)
{
- boolean_t first = B_TRUE;
+ hist_cbdata_t cbdata = { 0 };
int ret;
+ int c;
+ cbdata.first = B_TRUE;
+ /* check options */
+ while ((c = getopt(argc, argv, "li")) != -1) {
+ switch (c) {
+ case 'l':
+ cbdata.longfmt = 1;
+ break;
+ case 'i':
+ cbdata.internal = 1;
+ break;
+ case '?':
+ (void) fprintf(stderr, gettext("invalid option '%c'\n"),
+ optopt);
+ usage(B_FALSE);
+ }
+ }
argc -= optind;
argv += optind;
ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
- &first);
+ &cbdata);
- if (argc == 0 && first == B_TRUE) {
+ if (argc == 0 && cbdata.first == B_TRUE) {
(void) printf(gettext("no pools available\n"));
return (0);
}
@@ -3593,11 +3736,6 @@ zpool_do_set(int argc, char **argv)
error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
set_callback, &cb);
- if (cb.cb_any_successful) {
- *(cb.cb_value - 1) = '=';
- zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE);
- }
-
return (error);
}
@@ -3618,13 +3756,25 @@ find_command_idx(char *command, int *idx)
return (1);
}
+zpool_prop_t
+propset_cb(zpool_prop_t prop, void *data)
+{
+ char *cmdname = (char *)data;
+
+ if (strcmp(cmdname, zpool_prop_to_name(prop)) == 0)
+ return (prop);
+
+ return (ZFS_PROP_CONT);
+}
+
int
main(int argc, char **argv)
{
int ret;
int i;
char *cmdname;
- int found = 0;
+ boolean_t found = B_FALSE;
+ char *str;
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
@@ -3649,6 +3799,12 @@ main(int argc, char **argv)
cmdname = argv[1];
+ /* Handle special case of pool create for staging history */
+ if (strcmp(cmdname, "create") != 0)
+ zpool_stage_history(g_zfs, argc, argv, B_FALSE, B_FALSE);
+ else
+ zpool_stage_history(g_zfs, argc, argv, B_FALSE, B_TRUE);
+
/*
* Special case '-?'
*/
@@ -3661,7 +3817,7 @@ main(int argc, char **argv)
if (find_command_idx(cmdname, &i) == 0) {
current_command = &command_table[i];
ret = command_table[i].func(argc - 1, argv + 1);
- found++;
+ found = B_TRUE;
}
/*
@@ -3674,7 +3830,28 @@ main(int argc, char **argv)
return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
}
- if (!found) {
+ /* is this a zpool property=value */
+ if (found == B_FALSE && ((str = strchr(cmdname, '=')) != NULL)) {
+ *str = '\0';
+ if (zpool_prop_iter(propset_cb, cmdname,
+ B_FALSE) != ZFS_PROP_INVAL) {
+ if (find_command_idx("set", &i) == 0) {
+ *str = '=';
+ current_command = &command_table[i];
+ ret = command_table[i].func(argc, argv);
+ found = B_TRUE;
+ }
+ }
+
+ if (found == B_FALSE) {
+ *str = '=';
+ (void) fprintf(stderr,
+ gettext("invalid property '%s'\n"), cmdname);
+ found = B_TRUE;
+ }
+ }
+
+ if (found == B_FALSE) {
(void) fprintf(stderr, gettext("unrecognized "
"command '%s'\n"), cmdname);
usage(B_FALSE);
diff --git a/usr/src/cmd/ztest/ztest.c b/usr/src/cmd/ztest/ztest.c
index 04f97821f9..289108f605 100644
--- a/usr/src/cmd/ztest/ztest.c
+++ b/usr/src/cmd/ztest/ztest.c
@@ -1089,7 +1089,7 @@ ztest_vdev_LUN_growth(ztest_args_t *za)
/* ARGSUSED */
static void
-ztest_create_cb(objset_t *os, void *arg, dmu_tx_t *tx)
+ztest_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx)
{
/*
* Create the directory object.