MFV r316861: 6866 zdb -l should return non-zero if it fails to find any label

illumos/illumos-gate@64723e3611
64723e3611

https://www.illumos.org/issues/6866
  Need this for #6865.
  To be generally more scripting-friendly, overload this issue with adding '-q'
  option which should skip printing any label information.

Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: John Kennedy <john.kennedy@delphix.com>
Approved by: Robert Mustacchi <rm@joyent.com>
Author: Yuri Pankov <yuri.pankov@nexenta.com>

MFC after:	3 weeks
This commit is contained in:
Alan Somers 2017-10-02 22:13:20 +00:00
commit 2091d1c3b9
2 changed files with 58 additions and 41 deletions

View File

@ -15,11 +15,12 @@
.\" Copyright 2012, Richard Lowe.
.\" Copyright (c) 2012, Marcelo Araujo <araujo@FreeBSD.org>.
.\" Copyright (c) 2012, 2014 by Delphix. All rights reserved.
.\" Copyright 2016 Nexenta Systems, Inc.
.\" All Rights Reserved.
.\"
.\" $FreeBSD$
.\"
.Dd July 26, 2014
.Dd October 1, 2017
.Dt ZDB 8
.Os
.Sh NAME
@ -27,7 +28,7 @@
.Nd Display zpool debugging and consistency information
.Sh SYNOPSIS
.Nm
.Op Fl CumdibcsDvhLMXFPA
.Op Fl CmdibcsDvhLMXFPA
.Op Fl e Op Fl p Ar path...
.Op Fl t Ar txg
.Op Fl U Ar cache
@ -64,7 +65,7 @@
.Ar poolname
.Nm
.Fl l
.Op Fl uA
.Op Fl Aqu
.Ar device
.Nm
.Fl C
@ -156,10 +157,15 @@ dataset.
If specified multiple times, display counts of each intent log transaction
type.
.It Fl l Ar device
Display the vdev labels from the specified device.
Read the vdev labels from the specified device.
Return 0 if a valid label was found, 1 if an error occurred, and 2 if no valid
labels were found.
If the
.Fl u
option is also specified, also display the uberblocks on this device.
If the
.Fl q
option is also specified, also display the uberblocks on this device.
.It Fl L
Disable leak tracing and the loading of space maps.
By default,

View File

@ -23,6 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Nexenta Systems, Inc.
*/
#include <stdio.h>
@ -120,7 +121,7 @@ static void
usage(void)
{
(void) fprintf(stderr,
"Usage: %s [-CumMdibcsDvhLXFPAG] [-t txg] [-e [-p path...]] "
"Usage: %s [-CmMdibcsDvhLXFPAG] [-t txg] [-e [-p path...]] "
"[-U config] [-I inflight I/Os] [-x dumpdir] [-o var=value] "
"poolname [object...]\n"
" %s [-divPA] [-e -p path...] [-U config] dataset "
@ -130,7 +131,7 @@ usage(void)
" %s -R [-A] [-e [-p path...]] poolname "
"vdev:offset:size[:flags]\n"
" %s -S [-PA] [-e [-p path...]] [-U config] poolname\n"
" %s -l [-uA] device\n"
" %s -l [-Aqu] device\n"
" %s -C [-A] [-U config]\n\n",
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname);
@ -141,7 +142,6 @@ usage(void)
(void) fprintf(stderr, " If object numbers are specified, only "
"those objects are dumped\n\n");
(void) fprintf(stderr, " Options to control amount of output:\n");
(void) fprintf(stderr, " -u uberblock\n");
(void) fprintf(stderr, " -d dataset(s)\n");
(void) fprintf(stderr, " -i intent logs\n");
(void) fprintf(stderr, " -C config (or cachefile if alone)\n");
@ -155,7 +155,7 @@ usage(void)
(void) fprintf(stderr, " -D dedup statistics\n");
(void) fprintf(stderr, " -S simulate dedup to measure effect\n");
(void) fprintf(stderr, " -v verbose (applies to all others)\n");
(void) fprintf(stderr, " -l dump label contents\n");
(void) fprintf(stderr, " -l read label contents\n");
(void) fprintf(stderr, " -L disable leak tracking (do not "
"load spacemaps)\n");
(void) fprintf(stderr, " -R read and display block from a "
@ -186,6 +186,8 @@ usage(void)
"exiting\n");
(void) fprintf(stderr, " -o <variable>=<value> set global "
"variable to an unsigned 32-bit integer value\n");
(void) fprintf(stderr, " -q don't print label contents\n");
(void) fprintf(stderr, " -u uberblock\n");
(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");
@ -2159,45 +2161,48 @@ dump_label_uberblocks(vdev_label_t *lbl, uint64_t ashift)
}
}
static void
static int
dump_label(const char *dev)
{
int fd;
vdev_label_t label;
char *path, *buf = label.vl_vdev_phys.vp_nvlist;
char path[MAXPATHLEN];
char *buf = label.vl_vdev_phys.vp_nvlist;
size_t buflen = sizeof (label.vl_vdev_phys.vp_nvlist);
struct stat64 statbuf;
uint64_t psize, ashift;
int len = strlen(dev) + 1;
boolean_t label_found = B_FALSE;
if (strncmp(dev, ZFS_DISK_ROOTD, strlen(ZFS_DISK_ROOTD)) == 0) {
len++;
path = malloc(len);
(void) snprintf(path, len, "%s%s", ZFS_RDISK_ROOTD,
dev + strlen(ZFS_DISK_ROOTD));
} else {
path = strdup(dev);
(void) strlcpy(path, dev, sizeof (path));
if (dev[0] == '/') {
if (strncmp(dev, ZFS_DISK_ROOTD,
strlen(ZFS_DISK_ROOTD)) == 0) {
(void) snprintf(path, sizeof (path), "%s%s",
ZFS_RDISK_ROOTD, dev + strlen(ZFS_DISK_ROOTD));
}
} else if (stat64(path, &statbuf) != 0) {
char *s;
(void) snprintf(path, sizeof (path), "%s%s", ZFS_RDISK_ROOTD,
dev);
if ((s = strrchr(dev, 's')) == NULL || !isdigit(*(s + 1)))
(void) strlcat(path, "s0", sizeof (path));
}
if ((fd = open64(path, O_RDONLY)) < 0) {
(void) printf("cannot open '%s': %s\n", path, strerror(errno));
free(path);
exit(1);
}
if (fstat64(fd, &statbuf) != 0) {
if (stat64(path, &statbuf) != 0) {
(void) printf("failed to stat '%s': %s\n", path,
strerror(errno));
free(path);
(void) close(fd);
exit(1);
}
if (S_ISBLK(statbuf.st_mode)) {
(void) printf("cannot use '%s': character device required\n",
path);
free(path);
(void) close(fd);
exit(1);
}
if ((fd = open64(path, O_RDONLY)) < 0) {
(void) printf("cannot open '%s': %s\n", path, strerror(errno));
exit(1);
}
@ -2207,36 +2212,43 @@ dump_label(const char *dev)
for (int l = 0; l < VDEV_LABELS; l++) {
nvlist_t *config = NULL;
(void) printf("--------------------------------------------\n");
(void) printf("LABEL %d\n", l);
(void) printf("--------------------------------------------\n");
if (!dump_opt['q']) {
(void) printf("------------------------------------\n");
(void) printf("LABEL %d\n", l);
(void) printf("------------------------------------\n");
}
if (pread64(fd, &label, sizeof (label),
vdev_label_offset(psize, l, 0)) != sizeof (label)) {
(void) printf("failed to read label %d\n", l);
if (!dump_opt['q'])
(void) printf("failed to read label %d\n", l);
continue;
}
if (nvlist_unpack(buf, buflen, &config, 0) != 0) {
(void) printf("failed to unpack label %d\n", l);
if (!dump_opt['q'])
(void) printf("failed to unpack label %d\n", l);
ashift = SPA_MINBLOCKSHIFT;
} else {
nvlist_t *vdev_tree = NULL;
dump_nvlist(config, 4);
if (!dump_opt['q'])
dump_nvlist(config, 4);
if ((nvlist_lookup_nvlist(config,
ZPOOL_CONFIG_VDEV_TREE, &vdev_tree) != 0) ||
(nvlist_lookup_uint64(vdev_tree,
ZPOOL_CONFIG_ASHIFT, &ashift) != 0))
ashift = SPA_MINBLOCKSHIFT;
nvlist_free(config);
label_found = B_TRUE;
}
if (dump_opt['u'])
dump_label_uberblocks(&label, ashift);
}
free(path);
(void) close(fd);
return (label_found ? 0 : 2);
}
static uint64_t dataset_feature_count[SPA_FEATURES];
@ -3617,7 +3629,7 @@ main(int argc, char **argv)
spa_config_path = spa_config_path_env;
while ((c = getopt(argc, argv,
"bcdhilmMI:suCDRSAFLXx:evp:t:U:PGo:")) != -1) {
"bcdhilmMI:suCDRSAFLXx:evp:t:U:PGo:q")) != -1) {
switch (c) {
case 'b':
case 'c':
@ -3643,6 +3655,7 @@ main(int argc, char **argv)
case 'X':
case 'e':
case 'P':
case 'q':
dump_opt[c]++;
break;
case 'I':
@ -3751,10 +3764,8 @@ main(int argc, char **argv)
usage();
}
if (dump_opt['l']) {
dump_label(argv[0]);
return (0);
}
if (dump_opt['l'])
return (dump_label(argv[0]));
if (dump_opt['X'] || dump_opt['F'])
rewind = ZPOOL_DO_REWIND |