diff options
author | Matthew Ahrens <[email protected]> | 2016-01-01 14:42:58 +0100 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2016-01-11 11:36:54 -0800 |
commit | 9867e8be2a7182ce9b5eb28ed1d142e2ee60d69d (patch) | |
tree | cb7ac04486ec11670cecc1c953b4469055713ab1 /lib | |
parent | f3c9dca0937a7ca4fde2e47093cdae69f92dfb07 (diff) |
Illumos 4891 - want zdb option to dump all metadata
4891 want zdb option to dump all metadata
Reviewed by: Sonu Pillai <[email protected]>
Reviewed by: George Wilson <[email protected]>
Reviewed by: Christopher Siden <[email protected]>
Reviewed by: Dan McDonald <[email protected]>
Reviewed by: Richard Lowe <[email protected]>
Approved by: Garrett D'Amore <[email protected]>
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
https://github.com/illumos/illumos-gate/commit/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 [email protected]
Signed-off-by: Brian Behlendorf <[email protected]>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libzpool/kernel.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c index a45102699..31d3336a8 100644 --- a/lib/libzpool/kernel.c +++ b/lib/libzpool/kernel.c @@ -29,6 +29,7 @@ #include <stdlib.h> #include <string.h> #include <zlib.h> +#include <libgen.h> #include <sys/signal.h> #include <sys/spa.h> #include <sys/stat.h> @@ -50,6 +51,9 @@ char hw_serial[HW_HOSTID_LEN]; struct utsname hw_utsname; vmem_t *zio_arena = NULL; +/* If set, all blocks read will be copied to the specified directory. */ +char *vn_dumpdir = NULL; + /* this only exists to have its address taken */ struct proc p0; @@ -588,6 +592,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 = 0; char *realpath; @@ -655,13 +660,31 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR. */ fd = open64(realpath, flags - FREAD, mode); - free(realpath); + err = errno; if (flags & FCREAT) (void) umask(old_umask); + if (vn_dumpdir != NULL) { + char *dumppath = umem_zalloc(MAXPATHLEN, UMEM_NOFAIL); + (void) snprintf(dumppath, MAXPATHLEN, + "%s/%s", vn_dumpdir, basename(realpath)); + dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666); + umem_free(dumppath, MAXPATHLEN); + if (dump_fd == -1) { + err = errno; + free(realpath); + close(fd); + return (err); + } + } else { + dump_fd = -1; + } + + free(realpath); + if (fd == -1) - return (errno); + return (err); if (fstat64_blk(fd, &st) == -1) { err = errno; @@ -676,6 +699,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); } @@ -708,6 +732,11 @@ vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, if (uio == UIO_READ) { rc = pread64(vp->v_fd, addr, len, offset); + if (vp->v_dump_fd != -1) { + int status = + pwrite64(vp->v_dump_fd, addr, rc, offset); + ASSERT(status != -1); + } } else { /* * To simulate partial disk writes, we split writes into two @@ -750,6 +779,8 @@ void vn_close(vnode_t *vp) { 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)); } |