]> git.proxmox.com Git - mirror_zfs.git/commitdiff
zdb: add missing cleanup for early return
authorAmeer Hamza <ahamza@ixsystems.com>
Thu, 9 May 2024 14:31:57 +0000 (19:31 +0500)
committerGitHub <noreply@github.com>
Thu, 9 May 2024 14:31:57 +0000 (07:31 -0700)
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Don Brady <don.brady@klarasystems.com>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Signed-off-by: Ameer Hamza <ahamza@ixsystems.com>
Closes #16152

cmd/zdb/zdb.c

index 449b6bf2ccb3c68e54f7d26017eaaef0a99d0bbf..ce80c0aa59066ae9d8d614f1248c5d6cccbca939 100644 (file)
@@ -120,6 +120,9 @@ static int flagbits[256];
 static uint64_t max_inflight_bytes = 256 * 1024 * 1024; /* 256MB */
 static int leaked_objects = 0;
 static range_tree_t *mos_refd_objs;
+static spa_t *spa;
+static objset_t *os;
+static boolean_t kernel_init_done;
 
 static void snprintf_blkptr_compact(char *, size_t, const blkptr_t *,
     boolean_t);
@@ -131,6 +134,7 @@ static int dump_bpobj_cb(void *arg, const blkptr_t *bp, boolean_t free,
 
 
 static void zdb_print_blkptr(const blkptr_t *bp, int flags);
+static void zdb_exit(int reason);
 
 typedef struct sublivelist_verify_block_refcnt {
        /* block pointer entry in livelist being verified */
@@ -818,7 +822,7 @@ usage(void)
        (void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
            "to make only that option verbose\n");
        (void) fprintf(stderr, "Default is to dump everything non-verbosely\n");
-       exit(1);
+       zdb_exit(1);
 }
 
 static void
@@ -849,7 +853,7 @@ fatal(const char *fmt, ...)
 
        dump_debug_buffer();
 
-       exit(1);
+       zdb_exit(1);
 }
 
 static void
@@ -2276,7 +2280,7 @@ snprintf_zstd_header(spa_t *spa, char *blkbuf, size_t buflen,
                buf = malloc(SPA_MAXBLOCKSIZE);
                if (buf == NULL) {
                        (void) fprintf(stderr, "out of memory\n");
-                       exit(1);
+                       zdb_exit(1);
                }
                decode_embedded_bp_compressed(bp, buf);
                memcpy(&zstd_hdr, buf, sizeof (zstd_hdr));
@@ -3231,6 +3235,23 @@ fuid_table_destroy(void)
        }
 }
 
+static void
+zdb_exit(int reason)
+{
+       if (os != NULL) {
+               close_objset(os, FTAG);
+       } else if (spa != NULL) {
+               spa_close(spa, FTAG);
+       }
+
+       fuid_table_destroy();
+
+       if (kernel_init_done)
+               kernel_fini();
+
+       exit(reason);
+}
+
 /*
  * print uid or gid information.
  * For normal POSIX id just the id is printed in decimal format.
@@ -4161,32 +4182,32 @@ dump_cachefile(const char *cachefile)
        if ((fd = open64(cachefile, O_RDONLY)) < 0) {
                (void) printf("cannot open '%s': %s\n", cachefile,
                    strerror(errno));
-               exit(1);
+               zdb_exit(1);
        }
 
        if (fstat64(fd, &statbuf) != 0) {
                (void) printf("failed to stat '%s': %s\n", cachefile,
                    strerror(errno));
-               exit(1);
+               zdb_exit(1);
        }
 
        if ((buf = malloc(statbuf.st_size)) == NULL) {
                (void) fprintf(stderr, "failed to allocate %llu bytes\n",
                    (u_longlong_t)statbuf.st_size);
-               exit(1);
+               zdb_exit(1);
        }
 
        if (read(fd, buf, statbuf.st_size) != statbuf.st_size) {
                (void) fprintf(stderr, "failed to read %llu bytes\n",
                    (u_longlong_t)statbuf.st_size);
-               exit(1);
+               zdb_exit(1);
        }
 
        (void) close(fd);
 
        if (nvlist_unpack(buf, statbuf.st_size, &config, 0) != 0) {
                (void) fprintf(stderr, "failed to unpack nvlist\n");
-               exit(1);
+               zdb_exit(1);
        }
 
        free(buf);
@@ -5102,14 +5123,14 @@ dump_label(const char *dev)
 
        if ((fd = open64(path, O_RDONLY)) < 0) {
                (void) printf("cannot open '%s': %s\n", path, strerror(errno));
-               exit(1);
+               zdb_exit(1);
        }
 
        if (fstat64_blk(fd, &statbuf) != 0) {
                (void) printf("failed to stat '%s': %s\n", path,
                    strerror(errno));
                (void) close(fd);
-               exit(1);
+               zdb_exit(1);
        }
 
        if (S_ISBLK(statbuf.st_mode) && zfs_dev_flush(fd) != 0)
@@ -8221,7 +8242,7 @@ dump_zpool(spa_t *spa)
 
        if (rc != 0) {
                dump_debug_buffer();
-               exit(rc);
+               zdb_exit(rc);
        }
 }
 
@@ -8825,18 +8846,18 @@ zdb_embedded_block(char *thing)
            words + 12, words + 13, words + 14, words + 15);
        if (err != 16) {
                (void) fprintf(stderr, "invalid input format\n");
-               exit(1);
+               zdb_exit(1);
        }
        ASSERT3U(BPE_GET_LSIZE(&bp), <=, SPA_MAXBLOCKSIZE);
        buf = malloc(SPA_MAXBLOCKSIZE);
        if (buf == NULL) {
                (void) fprintf(stderr, "out of memory\n");
-               exit(1);
+               zdb_exit(1);
        }
        err = decode_embedded_bp(&bp, buf, BPE_GET_LSIZE(&bp));
        if (err != 0) {
                (void) fprintf(stderr, "decode failed: %u\n", err);
-               exit(1);
+               zdb_exit(1);
        }
        zdb_dump_block_raw(buf, BPE_GET_LSIZE(&bp), 0);
        free(buf);
@@ -8863,8 +8884,6 @@ int
 main(int argc, char **argv)
 {
        int c;
-       spa_t *spa = NULL;
-       objset_t *os = NULL;
        int dump_all = 1;
        int verbose = 0;
        int error = 0;
@@ -9093,6 +9112,7 @@ main(int argc, char **argv)
        spa_mode_readable_spacemaps = B_TRUE;
 
        kernel_init(SPA_MODE_READ);
+       kernel_init_done = B_TRUE;
 
        if (dump_all)
                verbose = MAX(verbose, 1);
@@ -9116,19 +9136,23 @@ main(int argc, char **argv)
                if (argc != 1)
                        usage();
                zdb_embedded_block(argv[0]);
-               return (0);
+               error = 0;
+               goto fini;
        }
 
        if (argc < 1) {
                if (!dump_opt['e'] && dump_opt['C']) {
                        dump_cachefile(spa_config_path);
-                       return (0);
+                       error = 0;
+                       goto fini;
                }
                usage();
        }
 
-       if (dump_opt['l'])
-               return (dump_label(argv[0]));
+       if (dump_opt['l']) {
+               error = dump_label(argv[0]);
+               goto fini;
+       }
 
        if (dump_opt['X'] || dump_opt['F'])
                rewind = ZPOOL_DO_REWIND |
@@ -9183,7 +9207,8 @@ main(int argc, char **argv)
                } else if (objset_str && !zdb_numeric(objset_str + 1) &&
                    dump_opt['N']) {
                        printf("Supply a numeric objset ID with -N\n");
-                       exit(1);
+                       error = 1;
+                       goto fini;
                }
        } else {
                target_pool = target;
@@ -9240,7 +9265,8 @@ main(int argc, char **argv)
                if (argc != 2)
                        usage();
                dump_opt['v'] = verbose + 3;
-               return (dump_path(argv[0], argv[1], NULL));
+               error = dump_path(argv[0], argv[1], NULL);
+               goto fini;
        }
 
        if (dump_opt['r']) {
@@ -9328,7 +9354,7 @@ main(int argc, char **argv)
                                fatal("can't dump '%s': %s", target,
                                    strerror(error));
                        }
-                       return (error);
+                       goto fini;
                } else {
                        target_pool = strdup(target);
                        if (strpbrk(target, "/@") != NULL)
@@ -9458,9 +9484,10 @@ retry_lookup:
                        free(checkpoint_target);
        }
 
+fini:
        if (os != NULL) {
                close_objset(os, FTAG);
-       } else {
+       } else if (spa != NULL) {
                spa_close(spa, FTAG);
        }
 
@@ -9468,7 +9495,8 @@ retry_lookup:
 
        dump_debug_buffer();
 
-       kernel_fini();
+       if (kernel_init_done)
+               kernel_fini();
 
        return (error);
 }