Illumos #2762: zpool command should have better support for feature flags
[zfs.git] / lib / libzfs / libzfs_status.c
index 24725ec..e6e9230 100644 (file)
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 /*
@@ -42,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
@@ -179,6 +182,7 @@ check_status(nvlist_t *config, boolean_t isimport)
        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);
@@ -202,7 +206,7 @@ check_status(nvlist_t *config, boolean_t isimport)
         * Pool last accessed by another system.
         */
        (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
-       if (hostid != 0 && (unsigned long)hostid != gethostid() &&
+       if (hostid != 0 && (unsigned long)hostid != system_hostid &&
            stateval == POOL_STATE_ACTIVE)
                return (ZPOOL_STATUS_HOSTID_MISMATCH);
 
@@ -214,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 &&
@@ -300,9 +318,33 @@ check_status(nvlist_t *config, boolean_t isimport)
        /*
         * 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);
 }