diff options
Diffstat (limited to 'usr/src/cmd/zpool/zpool_main.c')
-rw-r--r-- | usr/src/cmd/zpool/zpool_main.c | 343 |
1 files changed, 260 insertions, 83 deletions
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); |