summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChunwei Chen <[email protected]>2018-02-01 16:19:36 -0800
committerBrian Behlendorf <[email protected]>2018-02-09 10:11:02 -0800
commit950e17c215be4e6da72a61b0431337643a82b509 (patch)
tree9e315a3599e3085703a8f5772eed762e1464ddc1
parent0c0b0ad48addf342fcff29253a40282c00d5ce65 (diff)
Fix zdb -R decompression
There are some issues in the zdb -R decompression implementation. The first is that ZLE can easily decompress non-ZLE streams. So we add ZDB_NO_ZLE env to make zdb skip ZLE. The second is the random bytes appended to pabd, pbuf2 stuff. This serve no purpose at all, those bytes shouldn't be read during decompression anyway. Instead, we randomize lbuf2, so that we can make sure decompression fill exactly to lsize by bcmp lbuf and lbuf2. The last one is the condition to detect fail is wrong. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: loli10K <[email protected]> Signed-off-by: Chunwei Chen <[email protected]> Closes #7099 Closes #4984
-rw-r--r--cmd/zdb/zdb.c38
-rw-r--r--man/man8/zdb.84
2 files changed, 21 insertions, 21 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c
index c381d02a3..4c0a8245f 100644
--- a/cmd/zdb/zdb.c
+++ b/cmd/zdb/zdb.c
@@ -3984,13 +3984,6 @@ name:
return (NULL);
}
-/* ARGSUSED */
-static int
-random_get_pseudo_bytes_cb(void *buf, size_t len, void *unused)
-{
- return (random_get_pseudo_bytes(buf, len));
-}
-
/*
* Read a block from a pool and print it out. The syntax of the
* block descriptor is:
@@ -4160,17 +4153,8 @@ zdb_read_block(char *thing, spa_t *spa)
* every decompress function at every inflated blocksize.
*/
enum zio_compress c;
- void *pbuf2 = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
void *lbuf2 = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL);
- abd_copy_to_buf(pbuf2, pabd, psize);
-
- VERIFY0(abd_iterate_func(pabd, psize, SPA_MAXBLOCKSIZE - psize,
- random_get_pseudo_bytes_cb, NULL));
-
- VERIFY0(random_get_pseudo_bytes((uint8_t *)pbuf2 + psize,
- SPA_MAXBLOCKSIZE - psize));
-
/*
* XXX - On the one hand, with SPA_MAXBLOCKSIZE at 16MB,
* this could take a while and we should let the user know
@@ -4180,13 +4164,29 @@ zdb_read_block(char *thing, spa_t *spa)
for (lsize = psize + SPA_MINBLOCKSIZE;
lsize <= SPA_MAXBLOCKSIZE; lsize += SPA_MINBLOCKSIZE) {
for (c = 0; c < ZIO_COMPRESS_FUNCTIONS; c++) {
+ /*
+ * ZLE can easily decompress non zle stream.
+ * So have an option to disable it.
+ */
+ if (c == ZIO_COMPRESS_ZLE &&
+ getenv("ZDB_NO_ZLE"))
+ continue;
+
(void) fprintf(stderr,
"Trying %05llx -> %05llx (%s)\n",
(u_longlong_t)psize, (u_longlong_t)lsize,
zio_compress_table[c].ci_name);
+
+ /*
+ * We randomize lbuf2, and decompress to both
+ * lbuf and lbuf2. This way, we will know if
+ * decompression fill exactly to lsize.
+ */
+ VERIFY0(random_get_pseudo_bytes(lbuf2, lsize));
+
if (zio_decompress_data(c, pabd,
lbuf, psize, lsize) == 0 &&
- zio_decompress_data_buf(c, pbuf2,
+ zio_decompress_data(c, pabd,
lbuf2, psize, lsize) == 0 &&
bcmp(lbuf, lbuf2, lsize) == 0)
break;
@@ -4194,11 +4194,9 @@ zdb_read_block(char *thing, spa_t *spa)
if (c != ZIO_COMPRESS_FUNCTIONS)
break;
}
-
- umem_free(pbuf2, SPA_MAXBLOCKSIZE);
umem_free(lbuf2, SPA_MAXBLOCKSIZE);
- if (lsize <= psize) {
+ if (lsize > SPA_MAXBLOCKSIZE) {
(void) printf("Decompress of %s failed\n", thing);
goto out;
}
diff --git a/man/man8/zdb.8 b/man/man8/zdb.8
index d69d6f529..0ce4d852d 100644
--- a/man/man8/zdb.8
+++ b/man/man8/zdb.8
@@ -248,7 +248,9 @@ and, optionally,
.It Sy b Ar offset
Print block pointer
.It Sy d
-Decompress the block
+Decompress the block. Set environment variable
+.Nm ZBD_NO_ZLE
+to skip zle when guessing.
.It Sy e
Byte swap the block
.It Sy g