]>
Commit | Line | Data |
---|---|---|
75b07eca FG |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Chunwei Chen <david.chen@nutanix.com> | |
3 | Date: Thu, 1 Feb 2018 16:19:36 -0800 | |
4 | Subject: [PATCH] Fix zdb -R decompression | |
5 | MIME-Version: 1.0 | |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | There are some issues in the zdb -R decompression implementation. | |
10 | ||
11 | The first is that ZLE can easily decompress non-ZLE streams. So we add | |
12 | ZDB_NO_ZLE env to make zdb skip ZLE. | |
13 | ||
14 | The second is the random bytes appended to pabd, pbuf2 stuff. This serve | |
15 | no purpose at all, those bytes shouldn't be read during decompression | |
16 | anyway. Instead, we randomize lbuf2, so that we can make sure | |
17 | decompression fill exactly to lsize by bcmp lbuf and lbuf2. | |
18 | ||
19 | The last one is the condition to detect fail is wrong. | |
20 | ||
21 | Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> | |
22 | Reviewed-by: loli10K <ezomori.nozomu@gmail.com> | |
23 | Signed-off-by: Chunwei Chen <david.chen@nutanix.com> | |
24 | Closes #7099 | |
25 | Closes #4984 | |
26 | (cherry picked from commit 18c662b84566cd34e6f6fb982d6a01a415a4e3cd) | |
27 | Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> | |
28 | --- | |
29 | cmd/zdb/zdb.c | 38 ++++++++++++++++++-------------------- | |
30 | man/man8/zdb.8 | 4 +++- | |
31 | 2 files changed, 21 insertions(+), 21 deletions(-) | |
32 | ||
33 | diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c | |
34 | index 0cc1656a8..2d80589ca 100644 | |
35 | --- a/cmd/zdb/zdb.c | |
36 | +++ b/cmd/zdb/zdb.c | |
37 | @@ -3895,13 +3895,6 @@ name: | |
38 | return (NULL); | |
39 | } | |
40 | ||
41 | -/* ARGSUSED */ | |
42 | -static int | |
43 | -random_get_pseudo_bytes_cb(void *buf, size_t len, void *unused) | |
44 | -{ | |
45 | - return (random_get_pseudo_bytes(buf, len)); | |
46 | -} | |
47 | - | |
48 | /* | |
49 | * Read a block from a pool and print it out. The syntax of the | |
50 | * block descriptor is: | |
51 | @@ -4064,17 +4057,8 @@ zdb_read_block(char *thing, spa_t *spa) | |
52 | * every decompress function at every inflated blocksize. | |
53 | */ | |
54 | enum zio_compress c; | |
55 | - void *pbuf2 = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL); | |
56 | void *lbuf2 = umem_alloc(SPA_MAXBLOCKSIZE, UMEM_NOFAIL); | |
57 | ||
58 | - abd_copy_to_buf(pbuf2, pabd, psize); | |
59 | - | |
60 | - VERIFY0(abd_iterate_func(pabd, psize, SPA_MAXBLOCKSIZE - psize, | |
61 | - random_get_pseudo_bytes_cb, NULL)); | |
62 | - | |
63 | - VERIFY0(random_get_pseudo_bytes((uint8_t *)pbuf2 + psize, | |
64 | - SPA_MAXBLOCKSIZE - psize)); | |
65 | - | |
66 | /* | |
67 | * XXX - On the one hand, with SPA_MAXBLOCKSIZE at 16MB, | |
68 | * this could take a while and we should let the user know | |
69 | @@ -4084,13 +4068,29 @@ zdb_read_block(char *thing, spa_t *spa) | |
70 | for (lsize = psize + SPA_MINBLOCKSIZE; | |
71 | lsize <= SPA_MAXBLOCKSIZE; lsize += SPA_MINBLOCKSIZE) { | |
72 | for (c = 0; c < ZIO_COMPRESS_FUNCTIONS; c++) { | |
73 | + /* | |
74 | + * ZLE can easily decompress non zle stream. | |
75 | + * So have an option to disable it. | |
76 | + */ | |
77 | + if (c == ZIO_COMPRESS_ZLE && | |
78 | + getenv("ZDB_NO_ZLE")) | |
79 | + continue; | |
80 | + | |
81 | (void) fprintf(stderr, | |
82 | "Trying %05llx -> %05llx (%s)\n", | |
83 | (u_longlong_t)psize, (u_longlong_t)lsize, | |
84 | zio_compress_table[c].ci_name); | |
85 | + | |
86 | + /* | |
87 | + * We randomize lbuf2, and decompress to both | |
88 | + * lbuf and lbuf2. This way, we will know if | |
89 | + * decompression fill exactly to lsize. | |
90 | + */ | |
91 | + VERIFY0(random_get_pseudo_bytes(lbuf2, lsize)); | |
92 | + | |
93 | if (zio_decompress_data(c, pabd, | |
94 | lbuf, psize, lsize) == 0 && | |
95 | - zio_decompress_data_buf(c, pbuf2, | |
96 | + zio_decompress_data(c, pabd, | |
97 | lbuf2, psize, lsize) == 0 && | |
98 | bcmp(lbuf, lbuf2, lsize) == 0) | |
99 | break; | |
100 | @@ -4098,11 +4098,9 @@ zdb_read_block(char *thing, spa_t *spa) | |
101 | if (c != ZIO_COMPRESS_FUNCTIONS) | |
102 | break; | |
103 | } | |
104 | - | |
105 | - umem_free(pbuf2, SPA_MAXBLOCKSIZE); | |
106 | umem_free(lbuf2, SPA_MAXBLOCKSIZE); | |
107 | ||
108 | - if (lsize <= psize) { | |
109 | + if (lsize > SPA_MAXBLOCKSIZE) { | |
110 | (void) printf("Decompress of %s failed\n", thing); | |
111 | goto out; | |
112 | } | |
113 | diff --git a/man/man8/zdb.8 b/man/man8/zdb.8 | |
114 | index 4e47de7be..d991aae4c 100644 | |
115 | --- a/man/man8/zdb.8 | |
116 | +++ b/man/man8/zdb.8 | |
117 | @@ -246,7 +246,9 @@ and, optionally, | |
118 | .It Sy b Ar offset | |
119 | Print block pointer | |
120 | .It Sy d | |
121 | -Decompress the block | |
122 | +Decompress the block. Set environment variable | |
123 | +.Nm ZBD_NO_ZLE | |
124 | +to skip zle when guessing. | |
125 | .It Sy e | |
126 | Byte swap the block | |
127 | .It Sy g | |
128 | -- | |
129 | 2.14.2 | |
130 |