Skip to content

Commit 9ba02b3

Browse files
committed
Address review comments.
Signed-off-by: Rich Ercolani <[email protected]>
1 parent be8ba70 commit 9ba02b3

File tree

3 files changed

+125
-143
lines changed

3 files changed

+125
-143
lines changed

cmd/zdb/zdb.c

Lines changed: 0 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2202,90 +2202,6 @@ blkid2offset(const dnode_phys_t *dnp, const blkptr_t *bp,
22022202
dnp->dn_datablkszsec << SPA_MINBLOCKSHIFT);
22032203
}
22042204

2205-
static uint32_t
2206-
zfs_get_hdrversion(const zfs_zstdhdr_t *blob)
2207-
{
2208-
/*
2209-
* So we're searching 4 bytes to figure out where the version
2210-
* and level bytes are. The level bytes can cover the whole range
2211-
* of uint8_t, and so are not helpful. Fortunately, the version
2212-
* field is going to have a leading 00 from now until version
2213-
* 6.55.56 or higher with how it's represented, so we can dig
2214-
* that out, and know that wherever we found it, the two bytes
2215-
* "next" to it in the range are the other version bytes, in order,
2216-
* and whichever byte remains is the level field.
2217-
*/
2218-
uint32_t version = blob->raw_version_level;
2219-
uint8_t findme = 0xff;
2220-
int shift;
2221-
for (shift = 0; shift < 4; shift++) {
2222-
findme = BF32_GET(version, 8*shift, 8);
2223-
if (findme == 0)
2224-
break;
2225-
}
2226-
switch (shift) {
2227-
case 0:
2228-
version = BSWAP_32(version);
2229-
version = BF32_GET(version, 8, 24);
2230-
break;
2231-
case 1:
2232-
version = BSWAP_32(version);
2233-
version = BF32_GET(version, 0, 24);
2234-
break;
2235-
case 2:
2236-
version = BF32_GET(version, 0, 24);
2237-
break;
2238-
case 3:
2239-
version = BF32_GET(version, 8, 24);
2240-
break;
2241-
default:
2242-
version = 0;
2243-
break;
2244-
}
2245-
return (version);
2246-
}
2247-
2248-
static uint8_t
2249-
zfs_get_hdrlevel(const zfs_zstdhdr_t *blob)
2250-
{
2251-
/*
2252-
* So we're searching 4 bytes to figure out where the version
2253-
* and level bytes are. The level bytes can cover the whole range
2254-
* of uint8_t, and so are not helpful. Fortunately, the version
2255-
* field is going to have a leading 00 from now until version
2256-
* 6.55.56 or higher with how it's represented, so we can dig
2257-
* that out, and know that wherever we found it, the two bytes
2258-
* "next" to it in the range are the other version bytes, in order,
2259-
* and whichever byte remains is the level field.
2260-
*/
2261-
uint32_t level = blob->raw_version_level;
2262-
uint8_t findme = 0xff;
2263-
int shift;
2264-
for (shift = 0; shift < 4; shift++) {
2265-
findme = BF32_GET(level, 8*shift, 8);
2266-
if (findme == 0)
2267-
break;
2268-
}
2269-
switch (shift) {
2270-
case 0:
2271-
level = BF32_GET(level, 24, 8);
2272-
break;
2273-
case 1:
2274-
level = BF32_GET(level, 0, 8);
2275-
break;
2276-
case 2:
2277-
level = BF32_GET(level, 24, 8);
2278-
break;
2279-
case 3:
2280-
level = BF32_GET(level, 0, 8);
2281-
break;
2282-
default:
2283-
level = 0;
2284-
break;
2285-
}
2286-
return (level);
2287-
}
2288-
22892205
static void
22902206
snprintf_zstd_header(spa_t *spa, char *blkbuf, size_t buflen,
22912207
const blkptr_t *bp)

include/sys/zstd/zstd.h

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ typedef struct zfs_zstd_header {
6666
char data[];
6767
} zfs_zstdhdr_t;
6868

69+
/*
70+
* Simple struct to pass the data from raw_version_level around.
71+
*/
72+
typedef struct zfs_zstd_meta {
73+
uint8_t level;
74+
uint32_t version;
75+
} zfs_zstdmeta_t;
76+
6977
/*
7078
* kstat helper macros
7179
*/
@@ -89,6 +97,123 @@ int zfs_zstd_decompress(void *s_start, void *d_start, size_t s_len,
8997
size_t d_len, int n);
9098
void zfs_zstd_cache_reap_now(void);
9199

100+
/*
101+
* So, the reason we have all these complicated set/get functions is that
102+
* originally, in the zstd "header" we wrote out to disk, we used a 32-bit
103+
* bitfield to store the "level" (8 bits) and "version" (24 bits).
104+
*
105+
* Unfortunately, bitfields make few promises about how they're arranged in
106+
* memory...
107+
*
108+
* As a consequence, we wound up with little endian platforms with a layout
109+
* like this in memory:
110+
*
111+
* 32 24 16 8 0
112+
* +-------+-------+-------+-------+
113+
* | level | 0 | version |
114+
* +-------+-------+-------+-------+
115+
*
116+
* ...and then, after being run through BE_32(), serializing this out to
117+
* disk (BS16 indicates an order swap between the two bytes):
118+
*
119+
* 32 24 16 8 0
120+
* +-------+-------+-------+-------+
121+
* | BS16(version) | 0 | level |
122+
* +-------+-------+-------+-------+
123+
*
124+
* while on big-endian systems, since BE_32() is a noop there, both in
125+
* memory and on disk, we wind up with:
126+
*
127+
* 32 24 16 8 0
128+
* +-------+-------+-------+-------+
129+
* | 0 | version | level |
130+
* +-------+-------+-------+-------+
131+
*
132+
* (The "0" byte is part of the version field, but will remain 0 until
133+
* version 6.55.36, so it is useful both for illustration purposes
134+
* and for the "get" code below to know which possible layout of the
135+
* header we're dealing with.)
136+
*
137+
* So now we use the BF32_SET macros to get consistent behavior (the
138+
* BSWAP_32(LE) encoding, since x86 currently rules the world) across
139+
* platforms, but the "get" behavior requires that we check each of the
140+
* bytes in the aforementioned former-bitfield for 0x00, and from there,
141+
* we can know which possible layout we're dealing with. (Only the two
142+
* that have been observed in the wild are illustrated above, but handlers
143+
* for all 4 positions of 0x00 are implemented.
144+
*/
145+
146+
static inline void
147+
zfs_get_hdrmeta(const zfs_zstdhdr_t *blob, zfs_zstdmeta_t *res)
148+
{
149+
uint32_t raw = blob->raw_version_level;
150+
uint8_t findme = 0xff;
151+
int shift;
152+
for (shift = 0; shift < 4; shift++) {
153+
findme = BF32_GET(raw, 8*shift, 8);
154+
if (findme == 0)
155+
break;
156+
}
157+
switch (shift) {
158+
case 0:
159+
res->level = BF32_GET(raw, 24, 8);
160+
res->version = BSWAP_32(raw);
161+
res->version = BF32_GET(res->version, 8, 24);
162+
break;
163+
case 1:
164+
res->level = BF32_GET(raw, 0, 8);
165+
res->version = BSWAP_32(raw);
166+
res->version = BF32_GET(res->version, 0, 24);
167+
break;
168+
case 2:
169+
res->level = BF32_GET(raw, 24, 8);
170+
res->version = BF32_GET(raw, 0, 24);
171+
break;
172+
case 3:
173+
res->level = BF32_GET(raw, 0, 8);
174+
res->version = BF32_GET(raw, 8, 24);
175+
break;
176+
default:
177+
res->level = 0;
178+
res->version = 0;
179+
break;
180+
}
181+
}
182+
183+
static inline uint8_t
184+
zfs_get_hdrlevel(const zfs_zstdhdr_t *blob)
185+
{
186+
uint8_t level = 0;
187+
zfs_zstdmeta_t res;
188+
zfs_get_hdrmeta(blob, &res);
189+
level = res.level;
190+
return (level);
191+
}
192+
193+
static inline uint32_t
194+
zfs_get_hdrversion(const zfs_zstdhdr_t *blob)
195+
{
196+
uint32_t version = 0;
197+
zfs_zstdmeta_t res;
198+
zfs_get_hdrmeta(blob, &res);
199+
version = res.version;
200+
return (version);
201+
202+
}
203+
204+
static inline void
205+
zfs_set_hdrversion(zfs_zstdhdr_t *blob, uint32_t version)
206+
{
207+
BF32_SET(blob->raw_version_level, 0, 24, version);
208+
}
209+
210+
static inline void
211+
zfs_set_hdrlevel(zfs_zstdhdr_t *blob, uint8_t level)
212+
{
213+
BF32_SET(blob->raw_version_level, 24, 8, level);
214+
}
215+
216+
92217
#ifdef __cplusplus
93218
}
94219
#endif

module/zstd/zfs_zstd.c

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -361,65 +361,6 @@ zstd_enum_to_level(enum zio_zstd_levels level, int16_t *zstd_level)
361361
return (1);
362362
}
363363

364-
/*
365-
* Since it was never used, it's not here, but if you need it,
366-
* a copy of zfs_get_hdrversion can be found in zdb.c
367-
*/
368-
369-
static size_t
370-
zfs_set_hdrversion(zfs_zstdhdr_t *blob, uint32_t version)
371-
{
372-
BF32_SET(blob->raw_version_level, 0, 24, version);
373-
return (0);
374-
}
375-
376-
static uint8_t
377-
zfs_get_hdrlevel(const zfs_zstdhdr_t *blob)
378-
{
379-
/*
380-
* So we're searching 4 bytes to figure out where the version
381-
* and level bytes are. The level bytes can cover the whole range
382-
* of uint8_t, and so are not helpful. Fortunately, the version
383-
* field is going to have a leading 00 from now until version
384-
* 6.55.56 or higher with how it's represented, so we can dig
385-
* that out, and know that wherever we found it, the two bytes
386-
* "next" to it in the range are the other version bytes, in order,
387-
* and whichever byte remains is the level field.
388-
*/
389-
uint32_t level = blob->raw_version_level;
390-
uint8_t findme = 0xff;
391-
int shift;
392-
for (shift = 0; shift < 4; shift++) {
393-
findme = BF32_GET(level, 8*shift, 8);
394-
if (findme == 0)
395-
break;
396-
}
397-
switch (shift) {
398-
case 0:
399-
level = BF32_GET(level, 24, 8);
400-
break;
401-
case 1:
402-
level = BF32_GET(level, 0, 8);
403-
break;
404-
case 2:
405-
level = BF32_GET(level, 24, 8);
406-
break;
407-
case 3:
408-
level = BF32_GET(level, 0, 8);
409-
break;
410-
default:
411-
level = 0;
412-
break;
413-
}
414-
return (level);
415-
}
416-
417-
static size_t
418-
zfs_set_hdrlevel(zfs_zstdhdr_t *blob, uint8_t level)
419-
{
420-
BF32_SET(blob->raw_version_level, 24, 8, level);
421-
return (0);
422-
}
423364

424365
/* Compress block using zstd */
425366
size_t

0 commit comments

Comments
 (0)