zstream: allow decompress to fix metadata for uncompressed records
If a record is uncompressed on-disk but the block pointer insists otherwise, reading it will return EIO. This commit adds an "off" type to the "zstream decompress" command. Using it will set the compression field in a zfs stream to "off" without changing the record's data. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: George Melikov <mail@gmelikov.ru> Signed-off-by: Alan Somers <asomers@FreeBSD.org> Sponsored by: Axcient Closes #13997
This commit is contained in:
parent
6a42939fcd
commit
a1034ee909
|
@ -115,7 +115,9 @@ zstream_do_decompress(int argc, char *argv[])
|
||||||
if (errno || *end != '\0')
|
if (errno || *end != '\0')
|
||||||
errx(1, "invalid value for offset");
|
errx(1, "invalid value for offset");
|
||||||
if (argv[i]) {
|
if (argv[i]) {
|
||||||
if (0 == strcmp("lz4", argv[i]))
|
if (0 == strcmp("off", argv[i]))
|
||||||
|
type = ZIO_COMPRESS_OFF;
|
||||||
|
else if (0 == strcmp("lz4", argv[i]))
|
||||||
type = ZIO_COMPRESS_LZ4;
|
type = ZIO_COMPRESS_LZ4;
|
||||||
else if (0 == strcmp("lzjb", argv[i]))
|
else if (0 == strcmp("lzjb", argv[i]))
|
||||||
type = ZIO_COMPRESS_LZJB;
|
type = ZIO_COMPRESS_LZJB;
|
||||||
|
@ -127,8 +129,8 @@ zstream_do_decompress(int argc, char *argv[])
|
||||||
type = ZIO_COMPRESS_ZSTD;
|
type = ZIO_COMPRESS_ZSTD;
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "Invalid compression type %s.\n"
|
fprintf(stderr, "Invalid compression type %s.\n"
|
||||||
"Supported types are lz4, lzjb, gzip, zle, "
|
"Supported types are off, lz4, lzjb, gzip, "
|
||||||
"and zstd\n",
|
"zle, and zstd\n",
|
||||||
argv[i]);
|
argv[i]);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
@ -240,6 +242,9 @@ zstream_do_decompress(int argc, char *argv[])
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
zio_decompress_func_t *xfunc = NULL;
|
zio_decompress_func_t *xfunc = NULL;
|
||||||
switch ((enum zio_compress)(intptr_t)p->data) {
|
switch ((enum zio_compress)(intptr_t)p->data) {
|
||||||
|
case ZIO_COMPRESS_OFF:
|
||||||
|
xfunc = NULL;
|
||||||
|
break;
|
||||||
case ZIO_COMPRESS_LZJB:
|
case ZIO_COMPRESS_LZJB:
|
||||||
xfunc = lzjb_decompress;
|
xfunc = lzjb_decompress;
|
||||||
break;
|
break;
|
||||||
|
@ -258,7 +263,6 @@ zstream_do_decompress(int argc, char *argv[])
|
||||||
default:
|
default:
|
||||||
assert(B_FALSE);
|
assert(B_FALSE);
|
||||||
}
|
}
|
||||||
assert(xfunc != NULL);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -266,12 +270,27 @@ zstream_do_decompress(int argc, char *argv[])
|
||||||
*/
|
*/
|
||||||
char *lzbuf = safe_calloc(payload_size);
|
char *lzbuf = safe_calloc(payload_size);
|
||||||
(void) sfread(lzbuf, payload_size, stdin);
|
(void) sfread(lzbuf, payload_size, stdin);
|
||||||
if (0 != xfunc(lzbuf, buf,
|
if (xfunc == NULL) {
|
||||||
|
memcpy(buf, lzbuf, payload_size);
|
||||||
|
drrw->drr_compressiontype =
|
||||||
|
ZIO_COMPRESS_OFF;
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "Resetting "
|
||||||
|
"compression type to off "
|
||||||
|
"for ino %llu offset "
|
||||||
|
"%llu\n",
|
||||||
|
(u_longlong_t)
|
||||||
|
drrw->drr_object,
|
||||||
|
(u_longlong_t)
|
||||||
|
drrw->drr_offset);
|
||||||
|
} else if (0 != xfunc(lzbuf, buf,
|
||||||
payload_size, payload_size, 0)) {
|
payload_size, payload_size, 0)) {
|
||||||
/*
|
/*
|
||||||
* The block must not be compressed,
|
* The block must not be compressed,
|
||||||
* possibly because it gets written
|
* at least not with this compression
|
||||||
* multiple times in this stream.
|
* type, possibly because it gets
|
||||||
|
* written multiple times in this
|
||||||
|
* stream.
|
||||||
*/
|
*/
|
||||||
warnx("decompression failed for "
|
warnx("decompression failed for "
|
||||||
"ino %llu offset %llu",
|
"ino %llu offset %llu",
|
||||||
|
@ -279,11 +298,16 @@ zstream_do_decompress(int argc, char *argv[])
|
||||||
(u_longlong_t)drrw->drr_offset);
|
(u_longlong_t)drrw->drr_offset);
|
||||||
memcpy(buf, lzbuf, payload_size);
|
memcpy(buf, lzbuf, payload_size);
|
||||||
} else if (verbose) {
|
} else if (verbose) {
|
||||||
|
drrw->drr_compressiontype =
|
||||||
|
ZIO_COMPRESS_OFF;
|
||||||
fprintf(stderr, "successfully "
|
fprintf(stderr, "successfully "
|
||||||
"decompressed ino %llu "
|
"decompressed ino %llu "
|
||||||
"offset %llu\n",
|
"offset %llu\n",
|
||||||
(u_longlong_t)drrw->drr_object,
|
(u_longlong_t)drrw->drr_object,
|
||||||
(u_longlong_t)drrw->drr_offset);
|
(u_longlong_t)drrw->drr_offset);
|
||||||
|
} else {
|
||||||
|
drrw->drr_compressiontype =
|
||||||
|
ZIO_COMPRESS_OFF;
|
||||||
}
|
}
|
||||||
free(lzbuf);
|
free(lzbuf);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2020 by Delphix. All rights reserved.
|
.\" Copyright (c) 2020 by Delphix. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
.Dd March 25, 2022
|
.Dd October 4, 2022
|
||||||
.Dt ZSTREAM 8
|
.Dt ZSTREAM 8
|
||||||
.Os
|
.Os
|
||||||
.
|
.
|
||||||
|
@ -96,6 +96,7 @@ Specify the object number and byte offset of each record that you wish to
|
||||||
decompress.
|
decompress.
|
||||||
Optionally specify the compression type.
|
Optionally specify the compression type.
|
||||||
Valid compression types include
|
Valid compression types include
|
||||||
|
.Sy off ,
|
||||||
.Sy gzip ,
|
.Sy gzip ,
|
||||||
.Sy lz4 ,
|
.Sy lz4 ,
|
||||||
.Sy lzjb ,
|
.Sy lzjb ,
|
||||||
|
@ -108,6 +109,11 @@ Every record for that object beginning at that offset will be decompressed, if
|
||||||
possible.
|
possible.
|
||||||
It may not be possible, because the record may be corrupted in some but not
|
It may not be possible, because the record may be corrupted in some but not
|
||||||
all of the stream's snapshots.
|
all of the stream's snapshots.
|
||||||
|
Specifying a compression type of
|
||||||
|
.Sy off
|
||||||
|
will change the stream's metadata accordingly, without attempting decompression.
|
||||||
|
This can be useful if the record is already uncompressed but the metadata
|
||||||
|
insists otherwise.
|
||||||
The repaired stream will be written to standard output.
|
The repaired stream will be written to standard output.
|
||||||
.Bl -tag -width "-v"
|
.Bl -tag -width "-v"
|
||||||
.It Fl v
|
.It Fl v
|
||||||
|
|
Loading…
Reference in New Issue