Skip to content

Commit 9867e8b

Browse files
ahrensbehlendorf
authored andcommitted
Illumos 4891 - want zdb option to dump all metadata
4891 want zdb option to dump all metadata Reviewed by: Sonu Pillai <sonu.pillai@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Christopher Siden <christopher.siden@delphix.com> Reviewed by: Dan McDonald <danmcd@omniti.com> Reviewed by: Richard Lowe <richlowe@richlowe.net> Approved by: Garrett D'Amore <garrett@damore.org> We'd like a way for zdb to dump metadata in a machine-readable format, so that we can bring that back from a customer site for in-house diagnosis. Think of it as a crash dump for zpools, which can be used for post-mortem analysis of a malfunctioning pool References: https://www.illumos.org/issues/4891 illumos/illumos-gate@df15e41 Porting notes: - [cmd/zdb/zdb.c] - a5778ea zdb: Introduce -V for verbatim import - In main() getopt 'opt' variable removed and the code was brought back in line with illumos. - [lib/libzpool/kernel.c] - 1e33ac1 Fix Solaris thread dependency by using pthreads - f0e324f Update utsname support - 4d58b69 Fix vn_open/vn_rdwr error handling - In vn_open() allocate 'dumppath' on heap instead of stack - Properly handle 'dump_fd == -1' error path - Free 'realpath' after added vn_dumpdir_code block Ported-by: kernelOfTruth kerneloftruth@gmail.com Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
1 parent f3c9dca commit 9867e8b

File tree

4 files changed

+62
-10
lines changed

4 files changed

+62
-10
lines changed

cmd/zdb/zdb.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ usage(void)
118118
{
119119
(void) fprintf(stderr,
120120
"Usage: %s [-CumMdibcsDvhLXFPA] [-t txg] [-e [-p path...]] "
121-
"[-U config] [-I inflight I/Os] poolname [object...]\n"
121+
"[-U config] [-I inflight I/Os] [-x dumpdir] poolname [object...]\n"
122122
" %s [-divPA] [-e -p path...] [-U config] dataset "
123123
"[object...]\n"
124124
" %s -mM [-LXFPA] [-t txg] [-e [-p path...]] [-U config] "
@@ -157,7 +157,7 @@ usage(void)
157157
(void) fprintf(stderr, " -R read and display block from a "
158158
"device\n\n");
159159
(void) fprintf(stderr, " Below options are intended for use "
160-
"with other options (except -l):\n");
160+
"with other options:\n");
161161
(void) fprintf(stderr, " -A ignore assertions (-A), enable "
162162
"panic recovery (-AA) or both (-AAA)\n");
163163
(void) fprintf(stderr, " -F attempt automatic rewind within "
@@ -170,12 +170,14 @@ usage(void)
170170
"has altroot/not in a cachefile\n");
171171
(void) fprintf(stderr, " -p <path> -- use one or more with "
172172
"-e to specify path to vdev dir\n");
173+
(void) fprintf(stderr, " -x <dumpdir> -- "
174+
"dump all read blocks into specified directory\n");
173175
(void) fprintf(stderr, " -P print numbers in parseable form\n");
174176
(void) fprintf(stderr, " -t <txg> -- highest txg to use when "
175177
"searching for uberblocks\n");
176178
(void) fprintf(stderr, " -I <number of inflight I/Os> -- "
177-
"specify the maximum number of checksumming I/Os "
178-
"[default is 200]\n");
179+
"specify the maximum number of "
180+
"checksumming I/Os [default is 200]\n");
179181
(void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
180182
"to make only that option verbose\n");
181183
(void) fprintf(stderr, "Default is to dump everything non-verbosely\n");
@@ -3626,7 +3628,6 @@ main(int argc, char **argv)
36263628
int flags = ZFS_IMPORT_MISSING_LOG;
36273629
int rewind = ZPOOL_NEVER_REWIND;
36283630
char *spa_config_path_env;
3629-
const char *opts = "bcdhilmMI:suCDRSAFLXevp:t:U:PV";
36303631
boolean_t target_is_spa = B_TRUE;
36313632

36323633
(void) setrlimit(RLIMIT_NOFILE, &rl);
@@ -3643,7 +3644,8 @@ main(int argc, char **argv)
36433644
if (spa_config_path_env != NULL)
36443645
spa_config_path = spa_config_path_env;
36453646

3646-
while ((c = getopt(argc, argv, opts)) != -1) {
3647+
while ((c = getopt(argc, argv,
3648+
"bcdhilmMI:suCDRSAFLXx:evp:t:U:PV")) != -1) {
36473649
switch (c) {
36483650
case 'b':
36493651
case 'c':
@@ -3697,6 +3699,9 @@ main(int argc, char **argv)
36973699
}
36983700
searchdirs[nsearch++] = optarg;
36993701
break;
3702+
case 'x':
3703+
vn_dumpdir = optarg;
3704+
break;
37003705
case 't':
37013706
max_txg = strtoull(optarg, NULL, 0);
37023707
if (max_txg < TXG_INITIAL) {

include/sys/zfs_context.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,8 +500,10 @@ typedef struct vnode {
500500
uint64_t v_size;
501501
int v_fd;
502502
char *v_path;
503+
int v_dump_fd;
503504
} vnode_t;
504505

506+
extern char *vn_dumpdir;
505507
#define AV_SCANSTAMP_SZ 32 /* length of anti-virus scanstamp */
506508

507509
typedef struct xoptattr {

lib/libzpool/kernel.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <stdlib.h>
3030
#include <string.h>
3131
#include <zlib.h>
32+
#include <libgen.h>
3233
#include <sys/signal.h>
3334
#include <sys/spa.h>
3435
#include <sys/stat.h>
@@ -50,6 +51,9 @@ char hw_serial[HW_HOSTID_LEN];
5051
struct utsname hw_utsname;
5152
vmem_t *zio_arena = NULL;
5253

54+
/* If set, all blocks read will be copied to the specified directory. */
55+
char *vn_dumpdir = NULL;
56+
5357
/* this only exists to have its address taken */
5458
struct proc p0;
5559

@@ -588,6 +592,7 @@ int
588592
vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
589593
{
590594
int fd;
595+
int dump_fd;
591596
vnode_t *vp;
592597
int old_umask = 0;
593598
char *realpath;
@@ -655,13 +660,31 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
655660
* FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
656661
*/
657662
fd = open64(realpath, flags - FREAD, mode);
658-
free(realpath);
663+
err = errno;
659664

660665
if (flags & FCREAT)
661666
(void) umask(old_umask);
662667

668+
if (vn_dumpdir != NULL) {
669+
char *dumppath = umem_zalloc(MAXPATHLEN, UMEM_NOFAIL);
670+
(void) snprintf(dumppath, MAXPATHLEN,
671+
"%s/%s", vn_dumpdir, basename(realpath));
672+
dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666);
673+
umem_free(dumppath, MAXPATHLEN);
674+
if (dump_fd == -1) {
675+
err = errno;
676+
free(realpath);
677+
close(fd);
678+
return (err);
679+
}
680+
} else {
681+
dump_fd = -1;
682+
}
683+
684+
free(realpath);
685+
663686
if (fd == -1)
664-
return (errno);
687+
return (err);
665688

666689
if (fstat64_blk(fd, &st) == -1) {
667690
err = errno;
@@ -676,6 +699,7 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
676699
vp->v_fd = fd;
677700
vp->v_size = st.st_size;
678701
vp->v_path = spa_strdup(path);
702+
vp->v_dump_fd = dump_fd;
679703

680704
return (0);
681705
}
@@ -708,6 +732,11 @@ vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
708732

709733
if (uio == UIO_READ) {
710734
rc = pread64(vp->v_fd, addr, len, offset);
735+
if (vp->v_dump_fd != -1) {
736+
int status =
737+
pwrite64(vp->v_dump_fd, addr, rc, offset);
738+
ASSERT(status != -1);
739+
}
711740
} else {
712741
/*
713742
* To simulate partial disk writes, we split writes into two
@@ -750,6 +779,8 @@ void
750779
vn_close(vnode_t *vp)
751780
{
752781
close(vp->v_fd);
782+
if (vp->v_dump_fd != -1)
783+
close(vp->v_dump_fd);
753784
spa_strfree(vp->v_path);
754785
umem_free(vp, sizeof (vnode_t));
755786
}

man/man8/zdb.8

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
.\"
1212
.\"
1313
.\" Copyright 2012, Richard Lowe.
14-
.\" Copyright (c) 2012 by Delphix. All rights reserved.
14+
.\" Copyright (c) 2012, 2014 by Delphix. All rights reserved.
1515
.\"
1616
.TH "ZDB" "8" "February 15, 2012" "" ""
1717

@@ -20,7 +20,7 @@
2020

2121
.SH "SYNOPSIS"
2222
\fBzdb\fR [-CumdibcsDvhLMXFPA] [-e [-p \fIpath\fR...]] [-t \fItxg\fR]
23-
[-U \fIcache\fR] [-I \fIinflight I/Os\fR]
23+
[-U \fIcache\fR] [-I \fIinflight I/Os\fR] [-x \fIdumpdir\fR]
2424
[\fIpoolname\fR [\fIobject\fR ...]]
2525

2626
.P
@@ -372,6 +372,20 @@ Operate on an exported pool, not present in \fB/etc/zfs/zpool.cache\fR. The
372372
\fB-p\fR flag specifies the path under which devices are to be searched.
373373
.RE
374374

375+
.sp
376+
.ne 2
377+
.na
378+
\fB-x\fR \fIdumpdir\fR
379+
.ad
380+
.sp .6
381+
.RS 4n
382+
All blocks accessed will be copied to files in the specified directory.
383+
The blocks will be placed in sparse files whose name is the same as
384+
that of the file or device read. zdb can be then run on the generated files.
385+
Note that the \fB-bbc\fR flags are sufficient to access (and thus copy)
386+
all metadata on the pool.
387+
.RE
388+
375389
.sp
376390
.ne 2
377391
.na

0 commit comments

Comments
 (0)