MFV r267568:

4891 want zdb option to dump all metadata

illumos/illumos-gate@df15e419cb

MFC after:	2 weeks
This commit is contained in:
Xin LI 2014-07-01 08:20:34 +00:00
commit 6bab9dd0e4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=268084
4 changed files with 49 additions and 7 deletions

View File

@ -14,12 +14,12 @@
.\"
.\" Copyright 2012, Richard Lowe.
.\" Copyright (c) 2012, Marcelo Araujo <araujo@FreeBSD.org>.
.\" Copyright (c) 2012 by Delphix. All rights reserved.
.\" Copyright (c) 2012, 2014 by Delphix. All rights reserved.
.\" All Rights Reserved.
.\"
.\" $FreeBSD$
.\"
.Dd March 20, 2014
.Dd July 1, 2014
.Dt ZDB 8
.Os
.Sh NAME
@ -32,6 +32,7 @@
.Op Fl t Ar txg
.Op Fl U Ar cache
.Op Fl M Ar inflight I/Os
.Op Fl x Ar dumpdir
.Ar poolname
.Op Ar object ...
.Nm
@ -217,6 +218,14 @@ Operate on an exported pool, not present in
The
.Fl p
flag specifies the path under which devices are to be searched.
.It Fl x Ar dumpdir
All blocks accessed will be copied to files in the specified directory.
The blocks will be placed in sparse files whose name is the same as
that of the file or device read. zdb can be then run on the generated files.
Note that the
.Fl bbc
flags are sufficient to access (and thus copy)
all metadata on the pool.
.It Fl F
Attempt to make an unreadable pool readable by trying progressively older
transactions.

View File

@ -112,7 +112,7 @@ usage(void)
{
(void) fprintf(stderr,
"Usage: %s [-CumdibcsDvhLXFPA] [-t txg] [-e [-p path...]] "
"[-U config] [-M inflight I/Os] poolname [object...]\n"
"[-U config] [-M inflight I/Os] [-x dumpdir] poolname [object...]\n"
" %s [-divPA] [-e -p path...] [-U config] dataset "
"[object...]\n"
" %s -m [-LXFPA] [-t txg] [-e [-p path...]] [-U config] "
@ -150,7 +150,7 @@ usage(void)
(void) fprintf(stderr, " -R read and display block from a "
"device\n\n");
(void) fprintf(stderr, " Below options are intended for use "
"with other options (except -l):\n");
"with other options:\n");
(void) fprintf(stderr, " -A ignore assertions (-A), enable "
"panic recovery (-AA) or both (-AAA)\n");
(void) fprintf(stderr, " -F attempt automatic rewind within "
@ -163,11 +163,14 @@ usage(void)
"has altroot/not in a cachefile\n");
(void) fprintf(stderr, " -p <path> -- use one or more with "
"-e to specify path to vdev dir\n");
(void) fprintf(stderr, " -P print numbers in parseable form\n");
(void) fprintf(stderr, " -x <dumpdir> -- "
"dump all read blocks into specified directory\n");
(void) fprintf(stderr, " -P print numbers in parseable form\n");
(void) fprintf(stderr, " -t <txg> -- highest txg to use when "
"searching for uberblocks\n");
(void) fprintf(stderr, " -M <number of inflight I/Os> -- "
"specify the maximum number of checksumming I/Os [default is 200]");
"specify the maximum number of "
"checksumming I/Os [default is 200]\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");
@ -3355,7 +3358,8 @@ main(int argc, char **argv)
dprintf_setup(&argc, argv);
while ((c = getopt(argc, argv, "bcdhilmM:suCDRSAFLXevp:t:U:P")) != -1) {
while ((c = getopt(argc, argv,
"bcdhilmM:suCDRSAFLXx:evp:t:U:P")) != -1) {
switch (c) {
case 'b':
case 'c':
@ -3408,6 +3412,9 @@ main(int argc, char **argv)
}
searchdirs[nsearch++] = optarg;
break;
case 'x':
vn_dumpdir = optarg;
break;
case 't':
max_txg = strtoull(optarg, NULL, 0);
if (max_txg < TXG_INITIAL) {

View File

@ -31,6 +31,7 @@
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#include <libgen.h>
#include <sys/spa.h>
#include <sys/stat.h>
#include <sys/processor.h>
@ -52,6 +53,9 @@ char hw_serial[HW_HOSTID_LEN];
kmutex_t cpu_lock;
#endif
/* If set, all blocks read will be copied to the specified directory. */
char *vn_dumpdir = NULL;
struct utsname utsname = {
"userland", "libzpool", "1", "1", "na"
};
@ -415,6 +419,7 @@ int
vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
{
int fd;
int dump_fd;
vnode_t *vp;
int old_umask;
char realpath[MAXPATHLEN];
@ -463,6 +468,17 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
if (flags & FCREAT)
(void) umask(old_umask);
if (vn_dumpdir != NULL) {
char dumppath[MAXPATHLEN];
(void) snprintf(dumppath, sizeof (dumppath),
"%s/%s", vn_dumpdir, basename(realpath));
dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666);
if (dump_fd == -1)
return (errno);
} else {
dump_fd = -1;
}
if (fd == -1)
return (errno);
@ -478,6 +494,7 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
vp->v_fd = fd;
vp->v_size = st.st_size;
vp->v_path = spa_strdup(path);
vp->v_dump_fd = dump_fd;
return (0);
}
@ -510,6 +527,11 @@ vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
if (uio == UIO_READ) {
iolen = pread64(vp->v_fd, addr, len, offset);
if (vp->v_dump_fd != -1) {
int status =
pwrite64(vp->v_dump_fd, addr, iolen, offset);
ASSERT(status != -1);
}
} else {
/*
* To simulate partial disk writes, we split writes into two
@ -536,6 +558,8 @@ void
vn_close(vnode_t *vp, int openflag, cred_t *cr, kthread_t *td)
{
close(vp->v_fd);
if (vp->v_dump_fd != -1)
close(vp->v_dump_fd);
spa_strfree(vp->v_path);
umem_free(vp, sizeof (vnode_t));
}

View File

@ -424,8 +424,10 @@ typedef struct vnode {
uint64_t v_size;
int v_fd;
char *v_path;
int v_dump_fd;
} vnode_t;
extern char *vn_dumpdir;
#define AV_SCANSTAMP_SZ 32 /* length of anti-virus scanstamp */
typedef struct xoptattr {