Print this page
4168 ztest assertion failure in dbuf_undirty
4169 verbatim import causes zdb to segfault
4170 zhack leaves pool in ACTIVE state
Reviewed by: Adam Leventhal <ahl@delphix.com>
Reviewed by: Eric Schrock <eric.schrock@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>

@@ -18,11 +18,11 @@
  *
  * CDDL HEADER END
  */
 
 /*
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  * Copyright (c) 2013 Steven Hartland. All rights reserved.
  */
 
 /*
  * zhack is a debugging tool that can write changes to ZFS pool using libzpool

@@ -83,14 +83,19 @@
         exit(1);
 }
 
 
 static void
-fatal(const char *fmt, ...)
+fatal(spa_t *spa, void *tag, const char *fmt, ...)
 {
         va_list ap;
 
+        if (spa != NULL) {
+                spa_close(spa, tag);
+                (void) spa_export(g_pool, NULL, B_TRUE, B_FALSE);
+        }
+
         va_start(ap, fmt);
         (void) fprintf(stderr, "%s: ", cmdname);
         (void) vfprintf(stderr, fmt, ap);
         va_end(ap);
         (void) fprintf(stderr, "\n");

@@ -157,17 +162,18 @@
         if (nvlist_empty(pools)) {
                 if (!g_importargs.can_be_active) {
                         g_importargs.can_be_active = B_TRUE;
                         if (zpool_search_import(g_zfs, &g_importargs) != NULL ||
                             spa_open(target, &spa, FTAG) == 0) {
-                                fatal("cannot import '%s': pool is active; run "
-                                    "\"zpool export %s\" first\n",
-                                    g_pool, g_pool);
+                                fatal(spa, FTAG, "cannot import '%s': pool is "
+                                    "active; run " "\"zpool export %s\" "
+                                    "first\n", g_pool, g_pool);
                         }
                 }
 
-                fatal("cannot import '%s': no such pool available\n", g_pool);
+                fatal(NULL, FTAG, "cannot import '%s': no such pool "
+                    "available\n", g_pool);
         }
 
         elem = nvlist_next_nvpair(pools, NULL);
         name = nvpair_name(elem);
         verify(nvpair_value_nvlist(elem, &config) == 0);

@@ -184,11 +190,12 @@
         zfeature_checks_disable = B_FALSE;
         if (error == EEXIST)
                 error = 0;
 
         if (error)
-                fatal("can't import '%s': %s", name, strerror(error));
+                fatal(NULL, FTAG, "can't import '%s': %s", name,
+                    strerror(error));
 }
 
 static void
 zhack_spa_open(const char *target, boolean_t readonly, void *tag, spa_t **spa)
 {

@@ -199,14 +206,15 @@
         zfeature_checks_disable = B_TRUE;
         err = spa_open(target, spa, tag);
         zfeature_checks_disable = B_FALSE;
 
         if (err != 0)
-                fatal("cannot open '%s': %s", target, strerror(err));
+                fatal(*spa, FTAG, "cannot open '%s': %s", target,
+                    strerror(err));
         if (spa_version(*spa) < SPA_VERSION_FEATURES) {
-                fatal("'%s' has version %d, features not enabled", target,
-                    (int)spa_version(*spa));
+                fatal(*spa, FTAG, "'%s' has version %d, features not enabled",
+                    target, (int)spa_version(*spa));
         }
 }
 
 static void
 dump_obj(objset_t *os, uint64_t obj, const char *name)

@@ -334,19 +342,20 @@
         }
         target = argv[0];
         feature.fi_guid = argv[1];
 
         if (!zfeature_is_valid_guid(feature.fi_guid))
-                fatal("invalid feature guid: %s", feature.fi_guid);
+                fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid);
 
         zhack_spa_open(target, B_FALSE, FTAG, &spa);
         mos = spa->spa_meta_objset;
 
         if (0 == zfeature_lookup_guid(feature.fi_guid, NULL))
-                fatal("'%s' is a real feature, will not enable");
+                fatal(spa, FTAG, "'%s' is a real feature, will not enable");
         if (0 == zap_contains(mos, spa->spa_feat_desc_obj, feature.fi_guid))
-                fatal("feature already enabled: %s", feature.fi_guid);
+                fatal(spa, FTAG, "feature already enabled: %s",
+                    feature.fi_guid);
 
         VERIFY0(dsl_sync_task(spa_name(spa), NULL,
             feature_enable_sync, &feature, 5));
 
         spa_close(spa, FTAG);

@@ -421,30 +430,32 @@
         }
         target = argv[0];
         feature.fi_guid = argv[1];
 
         if (!zfeature_is_valid_guid(feature.fi_guid))
-                fatal("invalid feature guid: %s", feature.fi_guid);
+                fatal(NULL, FTAG, "invalid feature guid: %s", feature.fi_guid);
 
         zhack_spa_open(target, B_FALSE, FTAG, &spa);
         mos = spa->spa_meta_objset;
 
         if (0 == zfeature_lookup_guid(feature.fi_guid, NULL))
-                fatal("'%s' is a real feature, will not change refcount");
+                fatal(spa, FTAG, "'%s' is a real feature, will not change "
+                    "refcount");
 
         if (0 == zap_contains(mos, spa->spa_feat_for_read_obj,
             feature.fi_guid)) {
                 feature.fi_can_readonly = B_FALSE;
         } else if (0 == zap_contains(mos, spa->spa_feat_for_write_obj,
             feature.fi_guid)) {
                 feature.fi_can_readonly = B_TRUE;
         } else {
-                fatal("feature is not enabled: %s", feature.fi_guid);
+                fatal(spa, FTAG, "feature is not enabled: %s", feature.fi_guid);
         }
 
         if (decr && !spa_feature_is_active(spa, &feature))
-                fatal("feature refcount already 0: %s", feature.fi_guid);
+                fatal(spa, FTAG, "feature refcount already 0: %s",
+                    feature.fi_guid);
 
         VERIFY0(dsl_sync_task(spa_name(spa), NULL,
             decr ? feature_decr_sync : feature_incr_sync, &feature, 5));
 
         spa_close(spa, FTAG);

@@ -528,12 +539,12 @@
                 (void) fprintf(stderr, "error: unknown subcommand: %s\n",
                     subcommand);
                 usage();
         }
 
-        if (!g_readonly && spa_export(g_pool, NULL, B_TRUE, B_TRUE) != 0) {
-                fatal("pool export failed; "
+        if (!g_readonly && spa_export(g_pool, NULL, B_TRUE, B_FALSE) != 0) {
+                fatal(NULL, FTAG, "pool export failed; "
                     "changes may not be committed to disk\n");
         }
 
         libzfs_fini(g_zfs);
         kernel_fini();