Print this page
2882 implement libzfs_core
2883 changing "canmount" property to "on" should not always remount dataset
2900 "zfs snapshot" should be able to create multiple, arbitrary snapshots at once
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Chris Siden <christopher.siden@delphix.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Bill Pijewski <wdp@joyent.com>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>

*** 183,195 **** { "set", zpool_do_set, HELP_SET }, }; #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) ! zpool_command_t *current_command; static char history_str[HIS_MAX_RECORD_LEN]; ! static uint_t timestamp_fmt = NODATE; static const char * get_usage(zpool_help_t idx) { switch (idx) { --- 183,195 ---- { "set", zpool_do_set, HELP_SET }, }; #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) ! static zpool_command_t *current_command; static char history_str[HIS_MAX_RECORD_LEN]; ! static boolean_t log_history = B_TRUE; static uint_t timestamp_fmt = NODATE; static const char * get_usage(zpool_help_t idx) { switch (idx) {
*** 933,943 **** (void) fprintf(stderr, gettext("could not destroy '%s': " "could not unmount datasets\n"), zpool_get_name(zhp)); return (1); } ! ret = (zpool_destroy(zhp) != 0); zpool_close(zhp); return (ret); } --- 933,946 ---- (void) fprintf(stderr, gettext("could not destroy '%s': " "could not unmount datasets\n"), zpool_get_name(zhp)); return (1); } ! /* The history must be logged as part of the export */ ! log_history = B_FALSE; ! ! ret = (zpool_destroy(zhp, history_str) != 0); zpool_close(zhp); return (ret); }
*** 997,1010 **** ret = 1; zpool_close(zhp); continue; } if (hardforce) { ! if (zpool_export_force(zhp) != 0) ret = 1; ! } else if (zpool_export(zhp, force) != 0) { ret = 1; } zpool_close(zhp); } --- 1000,1016 ---- ret = 1; zpool_close(zhp); continue; } + /* The history must be logged as part of the export */ + log_history = B_FALSE; + if (hardforce) { ! if (zpool_export_force(zhp, history_str) != 0) ret = 1; ! } else if (zpool_export(zhp, force, history_str) != 0) { ret = 1; } zpool_close(zhp); }
*** 4267,4276 **** --- 4273,4290 ---- ret = zpool_upgrade(zhp, cbp->cb_version); if (!ret) { (void) printf(gettext("Successfully upgraded " "'%s'\n\n"), zpool_get_name(zhp)); } + /* + * If they did "zpool upgrade -a", then we could + * be doing ioctls to different pools. We need + * to log this history once to each pool, and bypass + * the normal history logging that happens in main(). + */ + (void) zpool_log_history(g_zfs, history_str); + log_history = B_FALSE; } } else if (cbp->cb_newer && !SPA_VERSION_IS_SUPPORTED(version)) { assert(!cbp->cb_all); if (cbp->cb_first) {
*** 4489,4500 **** return (ret); } typedef struct hist_cbdata { boolean_t first; ! int longfmt; ! int internal; } hist_cbdata_t; /* * Print out the command history for a specific pool. */ --- 4503,4514 ---- return (ret); } typedef struct hist_cbdata { boolean_t first; ! boolean_t longfmt; ! boolean_t internal; } hist_cbdata_t; /* * Print out the command history for a specific pool. */
*** 4502,4526 **** get_history_one(zpool_handle_t *zhp, void *data) { nvlist_t *nvhis; 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; cb->first = B_FALSE; (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); --- 4516,4527 ----
*** 4528,4595 **** return (ret); verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, &records, &numrecords) == 0); for (i = 0; i < numrecords; i++) { ! if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME, ! &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", - zfs_history_event_names[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); --- 4529,4626 ---- return (ret); verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD, &records, &numrecords) == 0); for (i = 0; i < numrecords; i++) { ! nvlist_t *rec = records[i]; ! char tbuf[30] = ""; ! if (nvlist_exists(rec, ZPOOL_HIST_TIME)) { ! time_t tsec; ! struct tm t; ! ! tsec = fnvlist_lookup_uint64(records[i], ! ZPOOL_HIST_TIME); ! (void) localtime_r(&tsec, &t); ! (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); ! } ! if (nvlist_exists(rec, ZPOOL_HIST_CMD)) { ! (void) printf("%s %s", tbuf, ! fnvlist_lookup_string(rec, ZPOOL_HIST_CMD)); ! } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) { ! int ievent = ! fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT); ! if (!cb->internal) continue; ! if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) { ! (void) printf("%s unrecognized record:\n", ! tbuf); ! dump_nvlist(rec, 4); continue; } ! (void) printf("%s [internal %s txg:%lld] %s", tbuf, ! zfs_history_event_names[ievent], ! fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), ! fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR)); ! } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) { ! if (!cb->internal) ! continue; ! (void) printf("%s [txg:%lld] %s", tbuf, ! fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG), ! fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME)); ! if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) { ! (void) printf(" %s (%llu)", ! fnvlist_lookup_string(rec, ! ZPOOL_HIST_DSNAME), ! fnvlist_lookup_uint64(rec, ! ZPOOL_HIST_DSID)); ! } ! (void) printf(" %s", fnvlist_lookup_string(rec, ! ZPOOL_HIST_INT_STR)); ! } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) { ! if (!cb->internal) ! continue; ! (void) printf("%s ioctl %s\n", tbuf, ! fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL)); ! if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) { ! (void) printf(" input:\n"); ! dump_nvlist(fnvlist_lookup_nvlist(rec, ! ZPOOL_HIST_INPUT_NVL), 8); ! } ! if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) { ! (void) printf(" output:\n"); ! dump_nvlist(fnvlist_lookup_nvlist(rec, ! ZPOOL_HIST_OUTPUT_NVL), 8); ! } ! } else { ! if (!cb->internal) ! continue; ! (void) printf("%s unrecognized record:\n", tbuf); ! dump_nvlist(rec, 4); ! } if (!cb->longfmt) { (void) printf("\n"); continue; } (void) printf(" ["); ! if (nvlist_exists(rec, ZPOOL_HIST_WHO)) { ! uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO); ! struct passwd *pwd = getpwuid(who); ! (void) printf("user %d ", (int)who); ! if (pwd != NULL) ! (void) printf("(%s) ", pwd->pw_name); ! } ! if (nvlist_exists(rec, ZPOOL_HIST_HOST)) { ! (void) printf("on %s", ! fnvlist_lookup_string(rec, ZPOOL_HIST_HOST)); ! } ! if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) { ! (void) printf(":%s", ! fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE)); } (void) printf("]"); (void) printf("\n"); } (void) printf("\n"); nvlist_free(nvhis);
*** 4600,4611 **** /* * zpool history <pool> * * Displays the history of commands that modified pools. */ - - int zpool_do_history(int argc, char **argv) { hist_cbdata_t cbdata = { 0 }; int ret; --- 4631,4640 ----
*** 4614,4627 **** 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); --- 4643,4656 ---- cbdata.first = B_TRUE; /* check options */ while ((c = getopt(argc, argv, "li")) != -1) { switch (c) { case 'l': ! cbdata.longfmt = B_TRUE; break; case 'i': ! cbdata.internal = B_TRUE; break; case '?': (void) fprintf(stderr, gettext("invalid option '%c'\n"), optopt); usage(B_FALSE);
*** 4842,4853 **** * Special case '-?' */ if (strcmp(cmdname, "-?") == 0) usage(B_TRUE); ! zpool_set_history_str("zpool", argc, argv, history_str); ! verify(zpool_stage_history(g_zfs, history_str) == 0); /* * Run the appropriate command. */ if (find_command_idx(cmdname, &i) == 0) { --- 4871,4881 ---- * Special case '-?' */ if (strcmp(cmdname, "-?") == 0) usage(B_TRUE); ! zfs_save_arguments(argc, argv, history_str, sizeof (history_str)); /* * Run the appropriate command. */ if (find_command_idx(cmdname, &i) == 0) {
*** 4870,4879 **** --- 4898,4910 ---- (void) fprintf(stderr, gettext("unrecognized " "command '%s'\n"), cmdname); usage(B_FALSE); } + if (ret == 0 && log_history) + (void) zpool_log_history(g_zfs, history_str); + libzfs_fini(g_zfs); /* * The 'ZFS_ABORT' environment variable causes us to dump core on exit * for the purposes of running ::findleaks.