X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=cmd%2Fzpool%2Fzpool_main.c;h=bad4e2a4f07d6b2a17f76f1004341ad2d6aa343c;hb=b4ead57cfb410247eee4d2a8a6e488cf4542ac77;hp=4fe14c82798441f7ed680fbf56295e12fbd204cc;hpb=b8864a233c569edcc57c686f3ea8cd1ae3b89153;p=zfs.git diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index 4fe14c8..bad4e2a 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include @@ -77,6 +79,7 @@ static int zpool_do_export(int, char **); static int zpool_do_upgrade(int, char **); static int zpool_do_history(int, char **); +static int zpool_do_events(int, char **); static int zpool_do_get(int, char **); static int zpool_do_set(int, char **); @@ -119,6 +122,7 @@ typedef enum { HELP_SCRUB, HELP_STATUS, HELP_UPGRADE, + HELP_EVENTS, HELP_GET, HELP_SET, HELP_SPLIT @@ -167,6 +171,8 @@ static zpool_command_t command_table[] = { { "upgrade", zpool_do_upgrade, HELP_UPGRADE }, { NULL }, { "history", zpool_do_history, HELP_HISTORY }, + { "events", zpool_do_events, HELP_EVENTS }, + { NULL }, { "get", zpool_do_get, HELP_GET }, { "set", zpool_do_set, HELP_SET }, }; @@ -234,6 +240,8 @@ get_usage(zpool_help_t idx) { return (gettext("\tupgrade\n" "\tupgrade -v\n" "\tupgrade [-V version] <-a | pool ...>\n")); + case HELP_EVENTS: + return (gettext("\tevents [-vHfc]\n")); case HELP_GET: return (gettext("\tget <\"all\" | property[,...]> " " ...\n")); @@ -1584,7 +1592,7 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts, * -c Read pool information from a cachefile instead of searching * devices. * - * -d Scan in a specific directory, other than /dev/dsk. More than + * -d Scan in a specific directory, other than /dev/. More than * one directory can be specified using multiple '-d' options. * * -D Scan for previously destroyed pools or import all or only @@ -1765,12 +1773,6 @@ zpool_do_import(int argc, char **argv) nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0) goto error; - if (searchdirs == NULL) { - searchdirs = safe_malloc(sizeof (char *)); - searchdirs[0] = "/dev/dsk"; - nsearch = 1; - } - /* check argument count */ if (do_all) { if (argc != 0) { @@ -1791,7 +1793,9 @@ zpool_do_import(int argc, char **argv) if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) { (void) fprintf(stderr, gettext("cannot " "discover pools: permission denied\n")); - free(searchdirs); + if (searchdirs != NULL) + free(searchdirs); + nvlist_free(policy); return (1); } @@ -1859,7 +1863,8 @@ zpool_do_import(int argc, char **argv) } if (err == 1) { - free(searchdirs); + if (searchdirs != NULL) + free(searchdirs); nvlist_free(policy); return (1); } @@ -1960,7 +1965,8 @@ error: nvlist_free(props); nvlist_free(pools); nvlist_free(policy); - free(searchdirs); + if (searchdirs != NULL) + free(searchdirs); return (err ? 1 : 0); } @@ -2202,7 +2208,7 @@ get_interval_count(int *argcp, char **argv, unsigned long *iv, unsigned long *cnt) { unsigned long interval = 0, count = 0; - int argc = *argcp, errno; + int argc = *argcp; /* * Determine if the last argument is an integer or a pool name @@ -2603,33 +2609,6 @@ zpool_do_list(int argc, char **argv) return (ret); } -static nvlist_t * -zpool_get_vdev_by_name(nvlist_t *nv, char *name) -{ - nvlist_t **child; - uint_t c, children; - nvlist_t *match; - char *path; - - if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, - &child, &children) != 0) { - verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0); - if (strncmp(name, "/dev/dsk/", 9) == 0) - name += 9; - if (strncmp(path, "/dev/dsk/", 9) == 0) - path += 9; - if (strcmp(name, path) == 0) - return (nv); - return (NULL); - } - - for (c = 0; c < children; c++) - if ((match = zpool_get_vdev_by_name(child[c], name)) != NULL) - return (match); - - return (NULL); -} - static int zpool_do_attach_or_replace(int argc, char **argv, int replacing) { @@ -3269,7 +3248,7 @@ print_scan_status(pool_scan_stat_t *ps) */ if (ps->pss_state == DSS_FINISHED) { uint64_t minutes_taken = (end - start) / 60; - char *fmt; + char *fmt = NULL; if (ps->pss_func == POOL_SCAN_SCRUB) { fmt = gettext("scrub repaired %s in %lluh%um with " @@ -4237,6 +4216,336 @@ zpool_do_history(int argc, char **argv) return (ret); } +typedef struct ev_opts { + int verbose; + int scripted; + int follow; + int clear; +} ev_opts_t; + +static void +zpool_do_events_short(nvlist_t *nvl) +{ + char ctime_str[26], str[32], *ptr; + int64_t *tv; + uint_t n; + + verify(nvlist_lookup_int64_array(nvl, FM_EREPORT_TIME, &tv, &n) == 0); + memset(str, ' ', 32); + (void) ctime_r((const time_t *)&tv[0], ctime_str); + (void) strncpy(str, ctime_str+4, 6); /* 'Jun 30' */ + (void) strncpy(str+7, ctime_str+20, 4); /* '1993' */ + (void) strncpy(str+12, ctime_str+11, 8); /* '21:49:08' */ + (void) sprintf(str+20, ".%09lld", (longlong_t)tv[1]);/* '.123456789' */ + (void) printf(gettext("%s "), str); + + verify(nvlist_lookup_string(nvl, FM_CLASS, &ptr) == 0); + (void) printf(gettext("%s\n"), ptr); +} + +static void +zpool_do_events_nvprint(nvlist_t *nvl, int depth) +{ + nvpair_t *nvp; + + for (nvp = nvlist_next_nvpair(nvl, NULL); + nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp)) { + + data_type_t type = nvpair_type(nvp); + const char *name = nvpair_name(nvp); + + boolean_t b; + uint8_t i8; + uint16_t i16; + uint32_t i32; + uint64_t i64; + char *str; + nvlist_t *cnv; + + printf(gettext("%*s%s = "), depth, "", name); + + switch (type) { + case DATA_TYPE_BOOLEAN: + printf(gettext("%s"), "1"); + break; + + case DATA_TYPE_BOOLEAN_VALUE: + (void) nvpair_value_boolean_value(nvp, &b); + printf(gettext("%s"), b ? "1" : "0"); + break; + + case DATA_TYPE_BYTE: + (void) nvpair_value_byte(nvp, &i8); + printf(gettext("0x%x"), i8); + break; + + case DATA_TYPE_INT8: + (void) nvpair_value_int8(nvp, (void *)&i8); + printf(gettext("0x%x"), i8); + break; + + case DATA_TYPE_UINT8: + (void) nvpair_value_uint8(nvp, &i8); + printf(gettext("0x%x"), i8); + break; + + case DATA_TYPE_INT16: + (void) nvpair_value_int16(nvp, (void *)&i16); + printf(gettext("0x%x"), i16); + break; + + case DATA_TYPE_UINT16: + (void) nvpair_value_uint16(nvp, &i16); + printf(gettext("0x%x"), i16); + break; + + case DATA_TYPE_INT32: + (void) nvpair_value_int32(nvp, (void *)&i32); + printf(gettext("0x%x"), i32); + break; + + case DATA_TYPE_UINT32: + (void) nvpair_value_uint32(nvp, &i32); + printf(gettext("0x%x"), i32); + break; + + case DATA_TYPE_INT64: + (void) nvpair_value_int64(nvp, (void *)&i64); + printf(gettext("0x%llx"), (u_longlong_t)i64); + break; + + case DATA_TYPE_UINT64: + (void) nvpair_value_uint64(nvp, &i64); + printf(gettext("0x%llx"), (u_longlong_t)i64); + break; + + case DATA_TYPE_HRTIME: + (void) nvpair_value_hrtime(nvp, (void *)&i64); + printf(gettext("0x%llx"), (u_longlong_t)i64); + break; + + case DATA_TYPE_STRING: + (void) nvpair_value_string(nvp, &str); + printf(gettext("\"%s\""), str ? str : ""); + break; + + case DATA_TYPE_NVLIST: + printf(gettext("(embedded nvlist)\n")); + (void) nvpair_value_nvlist(nvp, &cnv); + zpool_do_events_nvprint(cnv, depth + 8); + printf(gettext("%*s(end %s)"), depth, "", name); + break; + + case DATA_TYPE_NVLIST_ARRAY: { + nvlist_t **val; + uint_t i, nelem; + + (void) nvpair_value_nvlist_array(nvp, &val, &nelem); + printf(gettext("(%d embedded nvlists)\n"), nelem); + for (i = 0; i < nelem; i++) { + printf(gettext("%*s%s[%d] = %s\n"), + depth, "", name, i, "(embedded nvlist)"); + zpool_do_events_nvprint(val[i], depth + 8); + printf(gettext("%*s(end %s[%i])\n"), + depth, "", name, i); + } + printf(gettext("%*s(end %s)\n"), depth, "", name); + } + break; + + case DATA_TYPE_INT8_ARRAY: { + int8_t *val; + uint_t i, nelem; + + (void) nvpair_value_int8_array(nvp, &val, &nelem); + for (i = 0; i < nelem; i++) + printf(gettext("0x%x "), val[i]); + + break; + } + + case DATA_TYPE_UINT8_ARRAY: { + uint8_t *val; + uint_t i, nelem; + + (void) nvpair_value_uint8_array(nvp, &val, &nelem); + for (i = 0; i < nelem; i++) + printf(gettext("0x%x "), val[i]); + + break; + } + + case DATA_TYPE_INT16_ARRAY: { + int16_t *val; + uint_t i, nelem; + + (void) nvpair_value_int16_array(nvp, &val, &nelem); + for (i = 0; i < nelem; i++) + printf(gettext("0x%x "), val[i]); + + break; + } + + case DATA_TYPE_UINT16_ARRAY: { + uint16_t *val; + uint_t i, nelem; + + (void) nvpair_value_uint16_array(nvp, &val, &nelem); + for (i = 0; i < nelem; i++) + printf(gettext("0x%x "), val[i]); + + break; + } + + case DATA_TYPE_INT32_ARRAY: { + int32_t *val; + uint_t i, nelem; + + (void) nvpair_value_int32_array(nvp, &val, &nelem); + for (i = 0; i < nelem; i++) + printf(gettext("0x%x "), val[i]); + + break; + } + + case DATA_TYPE_UINT32_ARRAY: { + uint32_t *val; + uint_t i, nelem; + + (void) nvpair_value_uint32_array(nvp, &val, &nelem); + for (i = 0; i < nelem; i++) + printf(gettext("0x%x "), val[i]); + + break; + } + + case DATA_TYPE_INT64_ARRAY: { + int64_t *val; + uint_t i, nelem; + + (void) nvpair_value_int64_array(nvp, &val, &nelem); + for (i = 0; i < nelem; i++) + printf(gettext("0x%llx "), (u_longlong_t)val[i]); + + break; + } + + case DATA_TYPE_UINT64_ARRAY: { + uint64_t *val; + uint_t i, nelem; + + (void) nvpair_value_uint64_array(nvp, &val, &nelem); + for (i = 0; i < nelem; i++) + printf(gettext("0x%llx "), (u_longlong_t)val[i]); + + break; + } + + case DATA_TYPE_STRING_ARRAY: + case DATA_TYPE_BOOLEAN_ARRAY: + case DATA_TYPE_BYTE_ARRAY: + case DATA_TYPE_DOUBLE: + case DATA_TYPE_UNKNOWN: + printf(gettext("")); + break; + } + + printf(gettext("\n")); + } +} + +static int +zpool_do_events_next(ev_opts_t *opts) +{ + nvlist_t *nvl; + int cleanup_fd, ret, dropped; + + cleanup_fd = open(ZFS_DEV, O_RDWR); + VERIFY(cleanup_fd >= 0); + + if (!opts->scripted) + (void) printf(gettext("%-30s %s\n"), "TIME", "CLASS"); + + while (1) { + ret = zpool_events_next(g_zfs, &nvl, &dropped, + !!opts->follow, cleanup_fd); + if (ret || nvl == NULL) + break; + + if (dropped > 0) + (void) printf(gettext("dropped %d events\n"), dropped); + + zpool_do_events_short(nvl); + + if (opts->verbose) { + zpool_do_events_nvprint(nvl, 8); + printf(gettext("\n")); + } + + nvlist_free(nvl); + } + + VERIFY(0 == close(cleanup_fd)); + + return (ret); +} + +static int +zpool_do_events_clear(ev_opts_t *opts) +{ + int count, ret; + + ret = zpool_events_clear(g_zfs, &count); + if (!ret) + (void) printf(gettext("cleared %d events\n"), count); + + return (ret); +} + +/* + * zpool events [-vfc] + * + * Displays events logs by ZFS. + */ +int +zpool_do_events(int argc, char **argv) +{ + ev_opts_t opts = { 0 }; + int ret; + int c; + + /* check options */ + while ((c = getopt(argc, argv, "vHfc")) != -1) { + switch (c) { + case 'v': + opts.verbose = 1; + break; + case 'H': + opts.scripted = 1; + break; + case 'f': + opts.follow = 1; + break; + case 'c': + opts.clear = 1; + break; + case '?': + (void) fprintf(stderr, gettext("invalid option '%c'\n"), + optopt); + usage(B_FALSE); + } + } + argc -= optind; + argv += optind; + + if (opts.clear) + ret = zpool_do_events_clear(&opts); + else + ret = zpool_do_events_next(&opts); + + return ret; +} + static int get_callback(zpool_handle_t *zhp, void *data) { @@ -4392,20 +4701,12 @@ int main(int argc, char **argv) { int ret; - int i; + int i = 0; char *cmdname; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); - if ((g_zfs = libzfs_init()) == NULL) { - (void) fprintf(stderr, gettext("internal error: failed to " - "initialize ZFS library\n")); - return (1); - } - - libzfs_print_on_error(g_zfs, B_TRUE); - opterr = 0; /* @@ -4421,9 +4722,15 @@ main(int argc, char **argv) /* * Special case '-?' */ - if (strcmp(cmdname, "-?") == 0) + if ((strcmp(cmdname, "-?") == 0) || + strcmp(cmdname, "--help") == 0) usage(B_TRUE); + if ((g_zfs = libzfs_init()) == NULL) + return (1); + + libzfs_print_on_error(g_zfs, B_TRUE); + zpool_set_history_str("zpool", argc, argv, history_str); verify(zpool_stage_history(g_zfs, history_str) == 0); @@ -4450,6 +4757,7 @@ main(int argc, char **argv) (void) fprintf(stderr, gettext("unrecognized " "command '%s'\n"), cmdname); usage(B_FALSE); + ret = 1; } libzfs_fini(g_zfs);