Make spl directory setable when building rpms and add --buildroot
[zfs.git] / lib / libzfs / libzfs_status.c
index c7eb04e..e6e9230 100644 (file)
  *
  * CDDL HEADER END
  */
+
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 /*
@@ -43,6 +44,7 @@
 #include <string.h>
 #include <unistd.h>
 #include "libzfs_impl.h"
+#include "zfeature_common.h"
 
 /*
  * Message ID table.  This must be kept in sync with the ZPOOL_STATUS_* defines
@@ -104,6 +106,13 @@ vdev_offlined(uint64_t state, uint64_t aux, uint64_t errs)
        return (state == VDEV_STATE_OFFLINE);
 }
 
+/* ARGSUSED */
+static int
+vdev_removed(uint64_t state, uint64_t aux, uint64_t errs)
+{
+       return (state == VDEV_STATE_REMOVED);
+}
+
 /*
  * Detect if any leaf devices that have seen errors or could not be opened.
  */
@@ -131,7 +140,7 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(uint64_t, uint64_t, uint64_t))
                        if (find_vdev_problem(child[c], func))
                                return (B_TRUE);
        } else {
-               verify(nvlist_lookup_uint64_array(vdev, ZPOOL_CONFIG_STATS,
+               verify(nvlist_lookup_uint64_array(vdev, ZPOOL_CONFIG_VDEV_STATS,
                    (uint64_t **)&vs, &c) == 0);
 
                if (func(vs->vs_state, vs->vs_aux,
@@ -166,27 +175,38 @@ check_status(nvlist_t *config, boolean_t isimport)
 {
        nvlist_t *nvroot;
        vdev_stat_t *vs;
-       uint_t vsc;
+       pool_scan_stat_t *ps = NULL;
+       uint_t vsc, psc;
        uint64_t nerr;
        uint64_t version;
        uint64_t stateval;
        uint64_t suspended;
        uint64_t hostid = 0;
+       unsigned long system_hostid = gethostid() & 0xffffffff;
 
        verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
            &version) == 0);
        verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
            &nvroot) == 0);
-       verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_STATS,
+       verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
            (uint64_t **)&vs, &vsc) == 0);
        verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
            &stateval) == 0);
-       (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
+
+       /*
+        * Currently resilvering a vdev
+        */
+       (void) nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_SCAN_STATS,
+           (uint64_t **)&ps, &psc);
+       if (ps && ps->pss_func == POOL_SCAN_RESILVER &&
+           ps->pss_state == DSS_SCANNING)
+               return (ZPOOL_STATUS_RESILVERING);
 
        /*
         * Pool last accessed by another system.
         */
-       if (hostid != 0 && (unsigned long)hostid != gethostid() &&
+       (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
+       if (hostid != 0 && (unsigned long)hostid != system_hostid &&
            stateval == POOL_STATE_ACTIVE)
                return (ZPOOL_STATUS_HOSTID_MISMATCH);
 
@@ -198,6 +218,20 @@ check_status(nvlist_t *config, boolean_t isimport)
                return (ZPOOL_STATUS_VERSION_NEWER);
 
        /*
+        * Unsupported feature(s).
+        */
+       if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
+           vs->vs_aux == VDEV_AUX_UNSUP_FEAT) {
+               nvlist_t *nvinfo;
+
+               verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO,
+                   &nvinfo) == 0);
+               if (nvlist_exists(nvinfo, ZPOOL_CONFIG_CAN_RDONLY))
+                       return (ZPOOL_STATUS_UNSUP_FEAT_WRITE);
+               return (ZPOOL_STATUS_UNSUP_FEAT_READ);
+       }
+
+       /*
         * Check that the config is complete.
         */
        if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
@@ -276,17 +310,41 @@ check_status(nvlist_t *config, boolean_t isimport)
                return (ZPOOL_STATUS_OFFLINE_DEV);
 
        /*
-        * Currently resilvering
+        * Removed device
         */
-       if (!vs->vs_scrub_complete && vs->vs_scrub_type == POOL_SCRUB_RESILVER)
-               return (ZPOOL_STATUS_RESILVERING);
+       if (find_vdev_problem(nvroot, vdev_removed))
+               return (ZPOOL_STATUS_REMOVED_DEV);
 
        /*
         * Outdated, but usable, version
         */
-       if (version < SPA_VERSION)
+       if (SPA_VERSION_IS_SUPPORTED(version) && version != SPA_VERSION)
                return (ZPOOL_STATUS_VERSION_OLDER);
 
+       /*
+        * Usable pool with disabled features
+        */
+       if (version >= SPA_VERSION_FEATURES) {
+               int i;
+               nvlist_t *feat;
+
+               if (isimport) {
+                       feat = fnvlist_lookup_nvlist(config,
+                           ZPOOL_CONFIG_LOAD_INFO);
+                       feat = fnvlist_lookup_nvlist(feat,
+                           ZPOOL_CONFIG_ENABLED_FEAT);
+               } else {
+                       feat = fnvlist_lookup_nvlist(config,
+                           ZPOOL_CONFIG_FEATURE_STATS);
+               }
+
+               for (i = 0; i < SPA_FEATURES; i++) {
+                       zfeature_info_t *fi = &spa_feature_table[i];
+                       if (!nvlist_exists(feat, fi->fi_guid))
+                               return (ZPOOL_STATUS_FEAT_DISABLED);
+               }
+       }
+
        return (ZPOOL_STATUS_OK);
 }
 
@@ -315,3 +373,68 @@ zpool_import_status(nvlist_t *config, char **msgid)
 
        return (ret);
 }
+
+static void
+dump_ddt_stat(const ddt_stat_t *dds, int h)
+{
+       char refcnt[6];
+       char blocks[6], lsize[6], psize[6], dsize[6];
+       char ref_blocks[6], ref_lsize[6], ref_psize[6], ref_dsize[6];
+
+       if (dds == NULL || dds->dds_blocks == 0)
+               return;
+
+       if (h == -1)
+               (void) strcpy(refcnt, "Total");
+       else
+               zfs_nicenum(1ULL << h, refcnt, sizeof (refcnt));
+
+       zfs_nicenum(dds->dds_blocks, blocks, sizeof (blocks));
+       zfs_nicenum(dds->dds_lsize, lsize, sizeof (lsize));
+       zfs_nicenum(dds->dds_psize, psize, sizeof (psize));
+       zfs_nicenum(dds->dds_dsize, dsize, sizeof (dsize));
+       zfs_nicenum(dds->dds_ref_blocks, ref_blocks, sizeof (ref_blocks));
+       zfs_nicenum(dds->dds_ref_lsize, ref_lsize, sizeof (ref_lsize));
+       zfs_nicenum(dds->dds_ref_psize, ref_psize, sizeof (ref_psize));
+       zfs_nicenum(dds->dds_ref_dsize, ref_dsize, sizeof (ref_dsize));
+
+       (void) printf("%6s   %6s   %5s   %5s   %5s   %6s   %5s   %5s   %5s\n",
+           refcnt,
+           blocks, lsize, psize, dsize,
+           ref_blocks, ref_lsize, ref_psize, ref_dsize);
+}
+
+/*
+ * Print the DDT histogram and the column totals.
+ */
+void
+zpool_dump_ddt(const ddt_stat_t *dds_total, const ddt_histogram_t *ddh)
+{
+       int h;
+
+       (void) printf("\n");
+
+       (void) printf("bucket   "
+           "           allocated             "
+           "          referenced          \n");
+       (void) printf("______   "
+           "______________________________   "
+           "______________________________\n");
+
+       (void) printf("%6s   %6s   %5s   %5s   %5s   %6s   %5s   %5s   %5s\n",
+           "refcnt",
+           "blocks", "LSIZE", "PSIZE", "DSIZE",
+           "blocks", "LSIZE", "PSIZE", "DSIZE");
+
+       (void) printf("%6s   %6s   %5s   %5s   %5s   %6s   %5s   %5s   %5s\n",
+           "------",
+           "------", "-----", "-----", "-----",
+           "------", "-----", "-----", "-----");
+
+       for (h = 0; h < 64; h++)
+               dump_ddt_stat(&ddh->ddh_stat[h], h);
+
+       dump_ddt_stat(dds_total, -1);
+
+       (void) printf("\n");
+}