]> git.proxmox.com Git - mirror_zfs.git/blobdiff - cmd/zpool/zpool_main.c
Fix GCC 12 compilation errors
[mirror_zfs.git] / cmd / zpool / zpool_main.c
index b680b6c84cde230f5e8d03812299a7f844a300f0..0b55bf21f448d7f73a9519b65bce7ab5e253b3ee 100644 (file)
@@ -6,7 +6,7 @@
  * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
+ * or https://opensource.org/licenses/CDDL-1.0.
  * See the License for the specific language governing permissions
  * and limitations under the License.
  *
@@ -518,7 +518,7 @@ print_vdev_prop_cb(int prop, void *cb)
  * that command.  Otherwise, iterate over the entire command table and display
  * a complete usage message.
  */
-static _Noreturn void
+static __attribute__((noreturn)) void
 usage(boolean_t requested)
 {
        FILE *fp = requested ? stdout : stderr;
@@ -548,7 +548,7 @@ usage(boolean_t requested)
            (strcmp(current_command->name, "get") == 0) ||
            (strcmp(current_command->name, "list") == 0))) {
 
-               (void) fprintf(fp,
+               (void) fprintf(fp, "%s",
                    gettext("\nthe following properties are supported:\n"));
 
                (void) fprintf(fp, "\n\t%-19s  %s   %s\n\n",
@@ -711,7 +711,7 @@ print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
 
        for (c = 0; c < children; c++) {
                uint64_t is_log = B_FALSE, is_hole = B_FALSE;
-               char *class = "";
+               char *class = (char *)"";
 
                (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
                    &is_hole);
@@ -723,7 +723,7 @@ print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
                (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
                    &is_log);
                if (is_log)
-                       class = VDEV_ALLOC_BIAS_LOG;
+                       class = (char *)VDEV_ALLOC_BIAS_LOG;
                (void) nvlist_lookup_string(child[c],
                    ZPOOL_CONFIG_ALLOCATION_BIAS, &class);
                if (strcmp(match, class) != 0)
@@ -804,7 +804,7 @@ prop_list_contains_feature(nvlist_t *proplist)
  * Add a property pair (name, string-value) into a property nvlist.
  */
 static int
-add_prop_list(const char *propname, char *propval, nvlist_t **props,
+add_prop_list(const char *propname, const char *propval, nvlist_t **props,
     boolean_t poolprop)
 {
        zpool_prop_t prop = ZPOOL_PROP_INVAL;
@@ -905,7 +905,8 @@ add_prop_list(const char *propname, char *propval, nvlist_t **props,
  * Set a default property pair (name, string-value) in a property nvlist
  */
 static int
-add_prop_list_default(const char *propname, char *propval, nvlist_t **props)
+add_prop_list_default(const char *propname, const char *propval,
+    nvlist_t **props)
 {
        char *pval;
 
@@ -1195,6 +1196,7 @@ zpool_do_remove(int argc, char **argv)
                return (1);
 
        if (stop && noop) {
+               zpool_close(zhp);
                (void) fprintf(stderr, gettext("stop request ignored\n"));
                return (0);
        }
@@ -1790,8 +1792,8 @@ zpool_do_create(int argc, char **argv)
                            tname ? tname : poolname, ZFS_TYPE_FILESYSTEM);
                        if (pool != NULL) {
                                if (zfs_mount(pool, NULL, 0) == 0) {
-                                       ret = zfs_shareall(pool);
-                                       zfs_commit_all_shares();
+                                       ret = zfs_share(pool, NULL);
+                                       zfs_commit_shares(NULL);
                                }
                                zfs_close(pool);
                        }
@@ -1987,40 +1989,21 @@ static int
 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max,
     int name_flags)
 {
-       char *name;
-       nvlist_t **child;
-       uint_t c, children;
-       int ret;
-
-       name = zpool_vdev_name(g_zfs, zhp, nv, name_flags);
-       if (strlen(name) + depth > max)
-               max = strlen(name) + depth;
+       static const char *const subtypes[] =
+           {ZPOOL_CONFIG_SPARES, ZPOOL_CONFIG_L2CACHE, ZPOOL_CONFIG_CHILDREN};
 
+       char *name = zpool_vdev_name(g_zfs, zhp, nv, name_flags);
+       max = MAX(strlen(name) + depth, max);
        free(name);
 
-       if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
-           &child, &children) == 0) {
-               for (c = 0; c < children; c++)
-                       if ((ret = max_width(zhp, child[c], depth + 2,
-                           max, name_flags)) > max)
-                               max = ret;
-       }
-
-       if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
-           &child, &children) == 0) {
-               for (c = 0; c < children; c++)
-                       if ((ret = max_width(zhp, child[c], depth + 2,
-                           max, name_flags)) > max)
-                               max = ret;
-       }
-
-       if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
-           &child, &children) == 0) {
-               for (c = 0; c < children; c++)
-                       if ((ret = max_width(zhp, child[c], depth + 2,
-                           max, name_flags)) > max)
-                               max = ret;
-       }
+       nvlist_t **child;
+       uint_t children;
+       for (size_t i = 0; i < ARRAY_SIZE(subtypes); ++i)
+               if (nvlist_lookup_nvlist_array(nv, subtypes[i],
+                   &child, &children) == 0)
+                       for (uint_t c = 0; c < children; ++c)
+                               max = MAX(max_width(zhp, child[c], depth + 2,
+                                   max, name_flags), max);
 
        return (max);
 }
@@ -2088,15 +2071,13 @@ typedef struct status_cbdata {
 } status_cbdata_t;
 
 /* Return 1 if string is NULL, empty, or whitespace; return 0 otherwise. */
-static int
-is_blank_str(char *str)
+static boolean_t
+is_blank_str(const char *str)
 {
-       while (str != NULL && *str != '\0') {
+       for (; str != NULL && *str != '\0'; ++str)
                if (!isblank(*str))
-                       return (0);
-               str++;
-       }
-       return (1);
+                       return (B_FALSE);
+       return (B_TRUE);
 }
 
 /* Print command output lines for specific vdev in a specific pool */
@@ -2105,7 +2086,7 @@ zpool_print_cmd(vdev_cmd_data_list_t *vcdl, const char *pool, char *path)
 {
        vdev_cmd_data_t *data;
        int i, j;
-       char *val;
+       const char *val;
 
        for (i = 0; i < vcdl->count; i++) {
                if ((strcmp(vcdl->data[i].path, path) != 0) ||
@@ -2136,17 +2117,17 @@ zpool_print_cmd(vdev_cmd_data_list_t *vcdl, const char *pool, char *path)
 
                        printf("%*s", vcdl->uniq_cols_width[j], val);
                        if (j < vcdl->uniq_cols_cnt - 1)
-                               printf("  ");
+                               fputs("  ", stdout);
                }
 
                /* Print out any values that aren't in a column at the end */
                for (j = data->cols_cnt; j < data->lines_cnt; j++) {
                        /* Did we have any columns?  If so print a spacer. */
                        if (vcdl->uniq_cols_cnt > 0)
-                               printf("  ");
+                               fputs("  ", stdout);
 
                        val = data->lines[j];
-                       printf("%s", val ? val : "");
+                       fputs(val ?: "", stdout);
                }
                break;
        }
@@ -2259,7 +2240,7 @@ print_status_trim(vdev_stat_t *vs, boolean_t verbose)
  * Return the color associated with a health string.  This includes returning
  * NULL for no color change.
  */
-static char *
+static const char *
 health_str_to_color(const char *health)
 {
        if (strcmp(health, gettext("FAULTED")) == 0 ||
@@ -2295,7 +2276,7 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
        const char *state;
        char *type;
        char *path = NULL;
-       char *rcolor = NULL, *wcolor = NULL, *ccolor = NULL;
+       const char *rcolor = NULL, *wcolor = NULL, *ccolor = NULL;
 
        if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
            &child, &children) != 0)
@@ -2337,13 +2318,13 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
                        ccolor = ANSI_RED;
 
                if (cb->cb_literal) {
-                       printf(" ");
+                       fputc(' ', stdout);
                        printf_color(rcolor, "%5llu",
                            (u_longlong_t)vs->vs_read_errors);
-                       printf(" ");
+                       fputc(' ', stdout);
                        printf_color(wcolor, "%5llu",
                            (u_longlong_t)vs->vs_write_errors);
-                       printf(" ");
+                       fputc(' ', stdout);
                        printf_color(ccolor, "%5llu",
                            (u_longlong_t)vs->vs_checksum_errors);
                } else {
@@ -2351,11 +2332,11 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
                        zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
                        zfs_nicenum(vs->vs_checksum_errors, cbuf,
                            sizeof (cbuf));
-                       printf(" ");
+                       fputc(' ', stdout);
                        printf_color(rcolor, "%5s", rbuf);
-                       printf(" ");
+                       fputc(' ', stdout);
                        printf_color(wcolor, "%5s", wbuf);
-                       printf(" ");
+                       fputc(' ', stdout);
                        printf_color(ccolor, "%5s", cbuf);
                }
                if (cb->cb_print_slow_ios) {
@@ -2472,7 +2453,7 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
 
        if (vs->vs_scan_removing != 0) {
                (void) printf(gettext("  (removing)"));
-       } else if (vs->vs_noalloc != 0) {
+       } else if (VDEV_STAT_VALID(vs_noalloc, vsc) && vs->vs_noalloc != 0) {
                (void) printf(gettext("  (non-allocating)"));
        }
 
@@ -2482,7 +2463,14 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
        (void) nvlist_lookup_uint64_array(root, ZPOOL_CONFIG_SCAN_STATS,
            (uint64_t **)&ps, &c);
 
-       if (ps != NULL && ps->pss_state == DSS_SCANNING && children == 0) {
+       /*
+        * If you force fault a drive that's resilvering, its scan stats can
+        * get frozen in time, giving the false impression that it's
+        * being resilvered.  That's why we check the state to see if the vdev
+        * is healthy before reporting "resilvering" or "repairing".
+        */
+       if (ps != NULL && ps->pss_state == DSS_SCANNING && children == 0 &&
+           vs->vs_state == VDEV_STATE_HEALTHY) {
                if (vs->vs_scan_processed != 0) {
                        (void) printf(gettext("  (%s)"),
                            (ps->pss_func == POOL_SCAN_RESILVER) ?
@@ -2494,7 +2482,7 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
 
        /* The top-level vdevs have the rebuild stats */
        if (vrs != NULL && vrs->vrs_state == VDEV_REBUILD_ACTIVE &&
-           children == 0) {
+           children == 0 && vs->vs_state == VDEV_STATE_HEALTHY) {
                if (vs->vs_rebuild_processed != 0) {
                        (void) printf(gettext("  (resilvering)"));
                }
@@ -2690,7 +2678,7 @@ print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
                    &is_log);
 
                if (is_log) {
-                       bias = VDEV_ALLOC_CLASS_LOGS;
+                       bias = (char *)VDEV_ALLOC_CLASS_LOGS;
                } else {
                        (void) nvlist_lookup_string(child[c],
                            ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
@@ -2730,8 +2718,8 @@ show_import(nvlist_t *config, boolean_t report_error)
        char *name;
        uint64_t guid;
        uint64_t hostid = 0;
-       char *msgid;
-       char *hostname = "unknown";
+       const char *msgid;
+       const char *hostname = "unknown";
        nvlist_t *nvroot, *nvinfo;
        zpool_status_t reason;
        zpool_errata_t errata;
@@ -3271,7 +3259,7 @@ import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
                        if (first)
                                first = B_FALSE;
                        else if (!do_all)
-                               (void) putchar('\n');
+                               (void) fputc('\n', stdout);
 
                        if (do_all) {
                                err |= do_import(config, NULL, mntopts,
@@ -3785,7 +3773,12 @@ zpool_do_import(int argc, char **argv)
        idata.scan = do_scan;
        idata.policy = policy;
 
-       pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops);
+       libpc_handle_t lpch = {
+               .lpc_lib_handle = g_zfs,
+               .lpc_ops = &libzfs_config_ops,
+               .lpc_printerr = B_TRUE
+       };
+       pools = zpool_search_import(&lpch, &idata);
 
        if (pools != NULL && pool_exists &&
            (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
@@ -3841,7 +3834,7 @@ zpool_do_import(int argc, char **argv)
                 */
                idata.scan = B_TRUE;
                nvlist_free(pools);
-               pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops);
+               pools = zpool_search_import(&lpch, &idata);
 
                err = import_pools(pools, props, mntopts, flags,
                    argc >= 1 ? argv[0] : NULL,
@@ -4867,7 +4860,7 @@ children:
                        (void) nvlist_lookup_uint64(newchild[c],
                            ZPOOL_CONFIG_IS_LOG, &islog);
                        if (islog) {
-                               bias = VDEV_ALLOC_CLASS_LOGS;
+                               bias = (char *)VDEV_ALLOC_CLASS_LOGS;
                        } else {
                                (void) nvlist_lookup_string(newchild[c],
                                    ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
@@ -5401,7 +5394,7 @@ terminal_height(void)
 static void
 print_zpool_script_help(char *name, char *path)
 {
-       char *argv[] = {path, "-h", NULL};
+       char *argv[] = {path, (char *)"-h", NULL};
        char **lines = NULL;
        int lines_cnt = 0;
        int rc;
@@ -5453,7 +5446,7 @@ print_zpool_dir_scripts(char *dirpath)
  * Print out help text for all zpool status/iostat -c scripts.
  */
 static void
-print_zpool_script_list(char *subcommand)
+print_zpool_script_list(const char *subcommand)
 {
        char *dir, *sp, *tmp;
 
@@ -5486,8 +5479,8 @@ get_namewidth_iostat(zpool_handle_t *zhp, void *data)
         * get_namewidth() returns the maximum width of any name in that column
         * for any pool/vdev/device line that will be output.
         */
-       width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_vdevs.cb_name_flags,
-           cb->cb_verbose);
+       width = get_namewidth(zhp, cb->cb_namewidth,
+           cb->cb_vdevs.cb_name_flags | VDEV_NAME_TYPE_ID, cb->cb_verbose);
 
        /*
         * The width we are calculating is the width of the header and also the
@@ -5965,7 +5958,7 @@ print_header(list_cbdata_t *cb)
                        first = B_FALSE;
 
                right_justify = B_FALSE;
-               if (pl->pl_prop != ZPROP_INVAL) {
+               if (pl->pl_prop != ZPROP_USERPROP) {
                        header = zpool_prop_column_name(pl->pl_prop);
                        right_justify = zpool_prop_align_right(pl->pl_prop);
                } else {
@@ -5998,7 +5991,7 @@ print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
        zprop_list_t *pl = cb->cb_proplist;
        boolean_t first = B_TRUE;
        char property[ZPOOL_MAXPROPLEN];
-       char *propstr;
+       const char *propstr;
        boolean_t right_justify;
        size_t width;
 
@@ -6023,7 +6016,7 @@ print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
                }
 
                right_justify = B_FALSE;
-               if (pl->pl_prop != ZPROP_INVAL) {
+               if (pl->pl_prop != ZPROP_USERPROP) {
                        if (zpool_get_prop(zhp, pl->pl_prop, property,
                            sizeof (property), NULL, cb->cb_literal) != 0)
                                propstr = "-";
@@ -6162,7 +6155,7 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
                 * 'toplevel' boolean value is passed to the print_one_column()
                 * to indicate that the value is valid.
                 */
-               if (vs->vs_pspace)
+               if (VDEV_STAT_VALID(vs_pspace, c) && vs->vs_pspace)
                        print_one_column(ZPOOL_PROP_SIZE, vs->vs_pspace, NULL,
                            scripted, B_TRUE, format);
                else
@@ -6233,7 +6226,7 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
 
                        if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
                            &islog) == 0 && islog) {
-                               bias = VDEV_ALLOC_CLASS_LOGS;
+                               bias = (char *)VDEV_ALLOC_CLASS_LOGS;
                        } else {
                                (void) nvlist_lookup_string(child[c],
                                    ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
@@ -6318,8 +6311,8 @@ get_namewidth_list(zpool_handle_t *zhp, void *data)
        list_cbdata_t *cb = data;
        int width;
 
-       width = get_namewidth(zhp, cb->cb_namewidth, cb->cb_name_flags,
-           cb->cb_verbose);
+       width = get_namewidth(zhp, cb->cb_namewidth,
+           cb->cb_name_flags | VDEV_NAME_TYPE_ID, cb->cb_verbose);
 
        if (width < 9)
                width = 9;
@@ -8137,7 +8130,7 @@ status_callback(zpool_handle_t *zhp, void *data)
 {
        status_cbdata_t *cbp = data;
        nvlist_t *config, *nvroot;
-       char *msgid;
+       const char *msgid;
        zpool_status_t reason;
        zpool_errata_t errata;
        const char *health;
@@ -8182,12 +8175,12 @@ status_callback(zpool_handle_t *zhp, void *data)
        printf("  ");
        printf_color(ANSI_BOLD, gettext("pool:"));
        printf(" %s\n", zpool_get_name(zhp));
-       printf(" ");
+       fputc(' ', stdout);
        printf_color(ANSI_BOLD, gettext("state: "));
 
        printf_color(health_str_to_color(health), "%s", health);
 
-       printf("\n");
+       fputc('\n', stdout);
 
        switch (reason) {
        case ZPOOL_STATUS_MISSING_DEV_R:
@@ -10504,8 +10497,8 @@ print_wait_status_row(wait_data_t *wd, zpool_handle_t *zhp, int row)
        pool_checkpoint_stat_t *pcs = NULL;
        pool_scan_stat_t *pss = NULL;
        pool_removal_stat_t *prs = NULL;
-       char *headers[] = {"DISCARD", "FREE", "INITIALIZE", "REPLACE",
-           "REMOVE", "RESILVER", "SCRUB", "TRIM"};
+       const char *const headers[] = {"DISCARD", "FREE", "INITIALIZE",
+           "REPLACE", "REMOVE", "RESILVER", "SCRUB", "TRIM"};
        int col_widths[ZPOOL_WAIT_NUM_ACTIVITIES];
 
        /* Calculate the width of each column */
@@ -10527,7 +10520,7 @@ print_wait_status_row(wait_data_t *wd, zpool_handle_t *zhp, int row)
                        if (wd->wd_enabled[i])
                                (void) printf("%*s", col_widths[i], headers[i]);
                }
-               (void) printf("\n");
+               (void) fputc('\n', stdout);
        }
 
        /* Bytes of work remaining in each activity */
@@ -10814,11 +10807,9 @@ found:;
 }
 
 static int
-find_command_idx(char *command, int *idx)
+find_command_idx(const char *command, int *idx)
 {
-       int i;
-
-       for (i = 0; i < NCOMMAND; i++) {
+       for (int i = 0; i < NCOMMAND; ++i) {
                if (command_table[i].name == NULL)
                        continue;
 
@@ -10837,11 +10828,7 @@ static int
 zpool_do_version(int argc, char **argv)
 {
        (void) argc, (void) argv;
-
-       if (zfs_version_print() == -1)
-               return (1);
-
-       return (0);
+       return (zfs_version_print() != 0);
 }
 
 /*
@@ -10924,7 +10911,7 @@ main(int argc, char **argv)
         * Many commands modify input strings for string parsing reasons.
         * We create a copy to protect the original argv.
         */
-       newargv = malloc((argc + 1) * sizeof (newargv[0]));
+       newargv = safe_malloc((argc + 1) * sizeof (newargv[0]));
        for (i = 0; i < argc; i++)
                newargv[i] = strdup(argv[i]);
        newargv[argc] = NULL;