mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 10:37:35 +03:00
zdb: add -B option to generate backup stream
This is more-or-less like `zfs send`, but specifying the snapshot by its objset id for situations where it can't be referenced any other way. Sponsored-By: Klara, Inc. Reviewed-by: Tino Reichardt <milky-zfs@mcmilk.de> Reviewed-by: WHR <msl0000023508@gmail.com> Signed-off-by: Rob Norris <rob.norris@klarasystems.com> Closes #14642
This commit is contained in:
committed by
Brian Behlendorf
parent
2b9f8ba673
commit
8653f1de48
+92
-5
@@ -33,6 +33,7 @@
|
||||
* under sponsorship from the FreeBSD Foundation.
|
||||
* Copyright (c) 2021 Allan Jude
|
||||
* Copyright (c) 2021 Toomas Soome <tsoome@me.com>
|
||||
* Copyright (c) 2023, Klara Inc.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -789,6 +790,9 @@ usage(void)
|
||||
"\t\t[<poolname>[/<dataset | objset id>] [<object | range> ...]]\n"
|
||||
"\t%s [-AdiPv] [-e [-V] [-p <path> ...]] [-U <cache>] [-K <key>]\n"
|
||||
"\t\t[<poolname>[/<dataset | objset id>] [<object | range> ...]\n"
|
||||
"\t%s -B [-e [-V] [-p <path> ...]] [-I <inflight I/Os>]\n"
|
||||
"\t\t[-o <var>=<value>]... [-t <txg>] [-U <cache>] [-x <dumpdir>]\n"
|
||||
"\t\t[-K <key>] <poolname>/<objset id> [<backupflags>]\n"
|
||||
"\t%s [-v] <bookmark>\n"
|
||||
"\t%s -C [-A] [-U <cache>]\n"
|
||||
"\t%s -l [-Aqu] <device>\n"
|
||||
@@ -802,7 +806,7 @@ usage(void)
|
||||
"\t%s -S [-AP] [-e [-V] [-p <path> ...]] [-U <cache>] "
|
||||
"<poolname>\n\n",
|
||||
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname,
|
||||
cmdname, cmdname, cmdname, cmdname);
|
||||
cmdname, cmdname, cmdname, cmdname, cmdname);
|
||||
|
||||
(void) fprintf(stderr, " Dataset name must include at least one "
|
||||
"separator character '/' or '@'\n");
|
||||
@@ -825,6 +829,8 @@ usage(void)
|
||||
(void) fprintf(stderr, " Options to control amount of output:\n");
|
||||
(void) fprintf(stderr, " -b --block-stats "
|
||||
"block statistics\n");
|
||||
(void) fprintf(stderr, " -B --backup "
|
||||
"backup stream\n");
|
||||
(void) fprintf(stderr, " -c --checksum "
|
||||
"checksum all metadata (twice for all data) blocks\n");
|
||||
(void) fprintf(stderr, " -C --config "
|
||||
@@ -4875,6 +4881,81 @@ dump_path(char *ds, char *path, uint64_t *retobj)
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
dump_backup_bytes(objset_t *os, void *buf, int len, void *arg)
|
||||
{
|
||||
const char *p = (const char *)buf;
|
||||
ssize_t nwritten;
|
||||
|
||||
(void) os;
|
||||
(void) arg;
|
||||
|
||||
/* Write the data out, handling short writes and signals. */
|
||||
while ((nwritten = write(STDOUT_FILENO, p, len)) < len) {
|
||||
if (nwritten < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return (errno);
|
||||
}
|
||||
p += nwritten;
|
||||
len -= nwritten;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_backup(const char *pool, uint64_t objset_id, const char *flagstr)
|
||||
{
|
||||
boolean_t embed = B_FALSE;
|
||||
boolean_t large_block = B_FALSE;
|
||||
boolean_t compress = B_FALSE;
|
||||
boolean_t raw = B_FALSE;
|
||||
|
||||
const char *c;
|
||||
for (c = flagstr; c != NULL && *c != '\0'; c++) {
|
||||
switch (*c) {
|
||||
case 'e':
|
||||
embed = B_TRUE;
|
||||
break;
|
||||
case 'L':
|
||||
large_block = B_TRUE;
|
||||
break;
|
||||
case 'c':
|
||||
compress = B_TRUE;
|
||||
break;
|
||||
case 'w':
|
||||
raw = B_TRUE;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "dump_backup: invalid flag "
|
||||
"'%c'\n", *c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isatty(STDOUT_FILENO)) {
|
||||
fprintf(stderr, "dump_backup: stream cannot be written "
|
||||
"to a terminal\n");
|
||||
return;
|
||||
}
|
||||
|
||||
offset_t off = 0;
|
||||
dmu_send_outparams_t out = {
|
||||
.dso_outfunc = dump_backup_bytes,
|
||||
.dso_dryrun = B_FALSE,
|
||||
};
|
||||
|
||||
int err = dmu_send_obj(pool, objset_id, /* fromsnap */0, embed,
|
||||
large_block, compress, raw, /* saved */ B_FALSE, STDOUT_FILENO,
|
||||
&off, &out);
|
||||
if (err != 0) {
|
||||
fprintf(stderr, "dump_backup: dmu_send_obj: %s\n",
|
||||
strerror(err));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
zdb_copy_object(objset_t *os, uint64_t srcobj, char *destfile)
|
||||
{
|
||||
@@ -8695,6 +8776,7 @@ main(int argc, char **argv)
|
||||
struct option long_options[] = {
|
||||
{"ignore-assertions", no_argument, NULL, 'A'},
|
||||
{"block-stats", no_argument, NULL, 'b'},
|
||||
{"backup", no_argument, NULL, 'B'},
|
||||
{"checksum", no_argument, NULL, 'c'},
|
||||
{"config", no_argument, NULL, 'C'},
|
||||
{"datasets", no_argument, NULL, 'd'},
|
||||
@@ -8736,10 +8818,11 @@ main(int argc, char **argv)
|
||||
};
|
||||
|
||||
while ((c = getopt_long(argc, argv,
|
||||
"AbcCdDeEFGhiI:kK:lLmMNo:Op:PqrRsSt:uU:vVx:XYyZ",
|
||||
"AbBcCdDeEFGhiI:kK:lLmMNo:Op:PqrRsSt:uU:vVx:XYyZ",
|
||||
long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'b':
|
||||
case 'B':
|
||||
case 'c':
|
||||
case 'C':
|
||||
case 'd':
|
||||
@@ -8887,7 +8970,7 @@ main(int argc, char **argv)
|
||||
verbose = MAX(verbose, 1);
|
||||
|
||||
for (c = 0; c < 256; c++) {
|
||||
if (dump_all && strchr("AeEFkKlLNOPrRSXy", c) == NULL)
|
||||
if (dump_all && strchr("ABeEFkKlLNOPrRSXy", c) == NULL)
|
||||
dump_opt[c] = 1;
|
||||
if (dump_opt[c])
|
||||
dump_opt[c] += verbose;
|
||||
@@ -9073,7 +9156,8 @@ main(int argc, char **argv)
|
||||
checkpoint_pool, error);
|
||||
}
|
||||
|
||||
} else if (target_is_spa || dump_opt['R'] || objset_id == 0) {
|
||||
} else if (target_is_spa || dump_opt['R'] || dump_opt['B'] ||
|
||||
objset_id == 0) {
|
||||
zdb_set_skip_mmp(target);
|
||||
error = spa_open_rewind(target, &spa, FTAG, policy,
|
||||
NULL);
|
||||
@@ -9209,7 +9293,10 @@ retry_lookup:
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
if (os != NULL) {
|
||||
if (dump_opt['B']) {
|
||||
dump_backup(target, objset_id,
|
||||
argc > 0 ? argv[0] : NULL);
|
||||
} else if (os != NULL) {
|
||||
dump_objset(os);
|
||||
} else if (zopt_object_args > 0 && !dump_opt['m']) {
|
||||
dump_objset(spa->spa_meta_objset);
|
||||
|
||||
Reference in New Issue
Block a user