Changeset View
Changeset View
Standalone View
Standalone View
head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
Show First 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | typedef struct dedup_arg { | ||||
int outputfd; | int outputfd; | ||||
libzfs_handle_t *dedup_hdl; | libzfs_handle_t *dedup_hdl; | ||||
} dedup_arg_t; | } dedup_arg_t; | ||||
typedef struct progress_arg { | typedef struct progress_arg { | ||||
zfs_handle_t *pa_zhp; | zfs_handle_t *pa_zhp; | ||||
int pa_fd; | int pa_fd; | ||||
boolean_t pa_parsable; | boolean_t pa_parsable; | ||||
boolean_t pa_astitle; | |||||
uint64_t pa_size; | |||||
} progress_arg_t; | } progress_arg_t; | ||||
typedef struct dataref { | typedef struct dataref { | ||||
uint64_t ref_guid; | uint64_t ref_guid; | ||||
uint64_t ref_object; | uint64_t ref_object; | ||||
uint64_t ref_offset; | uint64_t ref_offset; | ||||
} dataref_t; | } dataref_t; | ||||
▲ Show 20 Lines • Show All 829 Lines • ▼ Show 20 Lines | |||||
typedef struct send_dump_data { | typedef struct send_dump_data { | ||||
/* these are all just the short snapname (the part after the @) */ | /* these are all just the short snapname (the part after the @) */ | ||||
const char *fromsnap; | const char *fromsnap; | ||||
const char *tosnap; | const char *tosnap; | ||||
char prevsnap[ZFS_MAX_DATASET_NAME_LEN]; | char prevsnap[ZFS_MAX_DATASET_NAME_LEN]; | ||||
uint64_t prevsnap_obj; | uint64_t prevsnap_obj; | ||||
boolean_t seenfrom, seento, replicate, doall, fromorigin; | boolean_t seenfrom, seento, replicate, doall, fromorigin; | ||||
boolean_t verbose, dryrun, parsable, progress, embed_data, std_out; | boolean_t verbose, dryrun, parsable, progress, embed_data, std_out; | ||||
boolean_t progressastitle; | |||||
boolean_t large_block, compress; | boolean_t large_block, compress; | ||||
int outfd; | int outfd; | ||||
boolean_t err; | boolean_t err; | ||||
nvlist_t *fss; | nvlist_t *fss; | ||||
nvlist_t *snapholds; | nvlist_t *snapholds; | ||||
avl_tree_t *fsavl; | avl_tree_t *fsavl; | ||||
snapfilter_cb_t *filter_cb; | snapfilter_cb_t *filter_cb; | ||||
void *filter_cb_arg; | void *filter_cb_arg; | ||||
▲ Show 20 Lines • Show All 164 Lines • ▼ Show 20 Lines | |||||
static void * | static void * | ||||
send_progress_thread(void *arg) | send_progress_thread(void *arg) | ||||
{ | { | ||||
progress_arg_t *pa = arg; | progress_arg_t *pa = arg; | ||||
zfs_cmd_t zc = { 0 }; | zfs_cmd_t zc = { 0 }; | ||||
zfs_handle_t *zhp = pa->pa_zhp; | zfs_handle_t *zhp = pa->pa_zhp; | ||||
libzfs_handle_t *hdl = zhp->zfs_hdl; | libzfs_handle_t *hdl = zhp->zfs_hdl; | ||||
unsigned long long bytes; | unsigned long long bytes, total; | ||||
char buf[16]; | char buf[16]; | ||||
time_t t; | time_t t; | ||||
struct tm *tm; | struct tm *tm; | ||||
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); | (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); | ||||
if (!pa->pa_parsable) | if (!pa->pa_parsable && !pa->pa_astitle) | ||||
(void) fprintf(stderr, "TIME SENT SNAPSHOT\n"); | (void) fprintf(stderr, "TIME SENT SNAPSHOT\n"); | ||||
/* | /* | ||||
* Print the progress from ZFS_IOC_SEND_PROGRESS every second. | * Print the progress from ZFS_IOC_SEND_PROGRESS every second. | ||||
*/ | */ | ||||
for (;;) { | for (;;) { | ||||
(void) sleep(1); | (void) sleep(1); | ||||
zc.zc_cookie = pa->pa_fd; | zc.zc_cookie = pa->pa_fd; | ||||
if (zfs_ioctl(hdl, ZFS_IOC_SEND_PROGRESS, &zc) != 0) | if (zfs_ioctl(hdl, ZFS_IOC_SEND_PROGRESS, &zc) != 0) | ||||
return ((void *)-1); | return ((void *)-1); | ||||
(void) time(&t); | (void) time(&t); | ||||
tm = localtime(&t); | tm = localtime(&t); | ||||
bytes = zc.zc_cookie; | bytes = zc.zc_cookie; | ||||
if (pa->pa_parsable) { | if (pa->pa_astitle) { | ||||
int pct; | |||||
if (pa->pa_size > bytes) | |||||
pct = 100 * bytes / pa->pa_size; | |||||
else | |||||
pct = 100; | |||||
setproctitle("sending %s (%d%%: %llu/%llu)", | |||||
zhp->zfs_name, pct, bytes, pa->pa_size); | |||||
} else if (pa->pa_parsable) { | |||||
(void) fprintf(stderr, "%02d:%02d:%02d\t%llu\t%s\n", | (void) fprintf(stderr, "%02d:%02d:%02d\t%llu\t%s\n", | ||||
tm->tm_hour, tm->tm_min, tm->tm_sec, | tm->tm_hour, tm->tm_min, tm->tm_sec, | ||||
bytes, zhp->zfs_name); | bytes, zhp->zfs_name); | ||||
} else { | } else { | ||||
zfs_nicenum(bytes, buf, sizeof (buf)); | zfs_nicenum(bytes, buf, sizeof (buf)); | ||||
(void) fprintf(stderr, "%02d:%02d:%02d %5s %s\n", | (void) fprintf(stderr, "%02d:%02d:%02d %5s %s\n", | ||||
tm->tm_hour, tm->tm_min, tm->tm_sec, | tm->tm_hour, tm->tm_min, tm->tm_sec, | ||||
buf, zhp->zfs_name); | buf, zhp->zfs_name); | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | dump_snapshot(zfs_handle_t *zhp, void *arg) | ||||
progress_arg_t pa = { 0 }; | progress_arg_t pa = { 0 }; | ||||
pthread_t tid; | pthread_t tid; | ||||
char *thissnap; | char *thissnap; | ||||
enum lzc_send_flags flags = 0; | enum lzc_send_flags flags = 0; | ||||
int err; | int err; | ||||
boolean_t isfromsnap, istosnap, fromorigin; | boolean_t isfromsnap, istosnap, fromorigin; | ||||
boolean_t exclude = B_FALSE; | boolean_t exclude = B_FALSE; | ||||
FILE *fout = sdd->std_out ? stdout : stderr; | FILE *fout = sdd->std_out ? stdout : stderr; | ||||
uint64_t size = 0; | |||||
err = 0; | err = 0; | ||||
thissnap = strchr(zhp->zfs_name, '@') + 1; | thissnap = strchr(zhp->zfs_name, '@') + 1; | ||||
isfromsnap = (sdd->fromsnap != NULL && | isfromsnap = (sdd->fromsnap != NULL && | ||||
strcmp(sdd->fromsnap, thissnap) == 0); | strcmp(sdd->fromsnap, thissnap) == 0); | ||||
if (!sdd->seenfrom && isfromsnap) { | if (!sdd->seenfrom && isfromsnap) { | ||||
gather_holds(zhp, sdd); | gather_holds(zhp, sdd); | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | if (exclude || (sdd->filter_cb != NULL && | ||||
zfs_close(zhp); | zfs_close(zhp); | ||||
return (0); | return (0); | ||||
} | } | ||||
gather_holds(zhp, sdd); | gather_holds(zhp, sdd); | ||||
fromorigin = sdd->prevsnap[0] == '\0' && | fromorigin = sdd->prevsnap[0] == '\0' && | ||||
(sdd->fromorigin || sdd->replicate); | (sdd->fromorigin || sdd->replicate); | ||||
if (sdd->verbose) { | if (sdd->progress && sdd->dryrun) { | ||||
uint64_t size = 0; | |||||
(void) estimate_ioctl(zhp, sdd->prevsnap_obj, | (void) estimate_ioctl(zhp, sdd->prevsnap_obj, | ||||
fromorigin, flags, &size); | fromorigin, flags, &size); | ||||
sdd->size += size; | |||||
} | |||||
if (sdd->verbose) { | |||||
send_print_verbose(fout, zhp->zfs_name, | send_print_verbose(fout, zhp->zfs_name, | ||||
sdd->prevsnap[0] ? sdd->prevsnap : NULL, | sdd->prevsnap[0] ? sdd->prevsnap : NULL, | ||||
size, sdd->parsable); | size, sdd->parsable); | ||||
sdd->size += size; | |||||
} | } | ||||
if (!sdd->dryrun) { | if (!sdd->dryrun) { | ||||
/* | /* | ||||
* If progress reporting is requested, spawn a new thread to | * If progress reporting is requested, spawn a new thread to | ||||
* poll ZFS_IOC_SEND_PROGRESS at a regular interval. | * poll ZFS_IOC_SEND_PROGRESS at a regular interval. | ||||
*/ | */ | ||||
if (sdd->progress) { | if (sdd->progress) { | ||||
pa.pa_zhp = zhp; | pa.pa_zhp = zhp; | ||||
pa.pa_fd = sdd->outfd; | pa.pa_fd = sdd->outfd; | ||||
pa.pa_parsable = sdd->parsable; | pa.pa_parsable = sdd->parsable; | ||||
pa.pa_size = sdd->size; | |||||
pa.pa_astitle = sdd->progressastitle; | |||||
if ((err = pthread_create(&tid, NULL, | if ((err = pthread_create(&tid, NULL, | ||||
send_progress_thread, &pa)) != 0) { | send_progress_thread, &pa)) != 0) { | ||||
zfs_close(zhp); | zfs_close(zhp); | ||||
return (err); | return (err); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 266 Lines • ▼ Show 20 Lines | zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *flags, int outfd, | ||||
char errbuf[1024]; | char errbuf[1024]; | ||||
char *toname; | char *toname; | ||||
char *fromname = NULL; | char *fromname = NULL; | ||||
uint64_t resumeobj, resumeoff, toguid, fromguid, bytes; | uint64_t resumeobj, resumeoff, toguid, fromguid, bytes; | ||||
zfs_handle_t *zhp; | zfs_handle_t *zhp; | ||||
int error = 0; | int error = 0; | ||||
char name[ZFS_MAX_DATASET_NAME_LEN]; | char name[ZFS_MAX_DATASET_NAME_LEN]; | ||||
enum lzc_send_flags lzc_flags = 0; | enum lzc_send_flags lzc_flags = 0; | ||||
uint64_t size = 0; | |||||
FILE *fout = (flags->verbose && flags->dryrun) ? stdout : stderr; | FILE *fout = (flags->verbose && flags->dryrun) ? stdout : stderr; | ||||
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, | (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, | ||||
"cannot resume send")); | "cannot resume send")); | ||||
nvlist_t *resume_nvl = | nvlist_t *resume_nvl = | ||||
zfs_send_resume_token_to_nvlist(hdl, resume_token); | zfs_send_resume_token_to_nvlist(hdl, resume_token); | ||||
if (resume_nvl == NULL) { | if (resume_nvl == NULL) { | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | if (guid_to_name(hdl, toname, fromguid, B_TRUE, name) != 0) { | ||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, | zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, | ||||
"incremental source %#llx no longer exists"), | "incremental source %#llx no longer exists"), | ||||
(longlong_t)fromguid); | (longlong_t)fromguid); | ||||
return (zfs_error(hdl, EZFS_BADPATH, errbuf)); | return (zfs_error(hdl, EZFS_BADPATH, errbuf)); | ||||
} | } | ||||
fromname = name; | fromname = name; | ||||
} | } | ||||
if (flags->verbose) { | if (flags->progress) { | ||||
uint64_t size = 0; | |||||
error = lzc_send_space(zhp->zfs_name, fromname, | error = lzc_send_space(zhp->zfs_name, fromname, | ||||
lzc_flags, &size); | lzc_flags, &size); | ||||
if (error == 0) | if (error == 0) | ||||
size = MAX(0, (int64_t)(size - bytes)); | size = MAX(0, (int64_t)(size - bytes)); | ||||
} | |||||
if (flags->verbose) { | |||||
send_print_verbose(fout, zhp->zfs_name, fromname, | send_print_verbose(fout, zhp->zfs_name, fromname, | ||||
size, flags->parsable); | size, flags->parsable); | ||||
} | } | ||||
if (!flags->dryrun) { | if (!flags->dryrun) { | ||||
progress_arg_t pa = { 0 }; | progress_arg_t pa = { 0 }; | ||||
pthread_t tid; | pthread_t tid; | ||||
/* | /* | ||||
* If progress reporting is requested, spawn a new thread to | * If progress reporting is requested, spawn a new thread to | ||||
* poll ZFS_IOC_SEND_PROGRESS at a regular interval. | * poll ZFS_IOC_SEND_PROGRESS at a regular interval. | ||||
*/ | */ | ||||
if (flags->progress) { | if (flags->progress) { | ||||
pa.pa_zhp = zhp; | pa.pa_zhp = zhp; | ||||
pa.pa_fd = outfd; | pa.pa_fd = outfd; | ||||
pa.pa_parsable = flags->parsable; | pa.pa_parsable = flags->parsable; | ||||
pa.pa_size = size; | |||||
pa.pa_astitle = flags->progressastitle; | |||||
error = pthread_create(&tid, NULL, | error = pthread_create(&tid, NULL, | ||||
send_progress_thread, &pa); | send_progress_thread, &pa); | ||||
if (error != 0) { | if (error != 0) { | ||||
zfs_close(zhp); | zfs_close(zhp); | ||||
return (error); | return (error); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap, | ||||
sdd.replicate = flags->replicate; | sdd.replicate = flags->replicate; | ||||
sdd.doall = flags->doall; | sdd.doall = flags->doall; | ||||
sdd.fromorigin = flags->fromorigin; | sdd.fromorigin = flags->fromorigin; | ||||
sdd.fss = fss; | sdd.fss = fss; | ||||
sdd.fsavl = fsavl; | sdd.fsavl = fsavl; | ||||
sdd.verbose = flags->verbose; | sdd.verbose = flags->verbose; | ||||
sdd.parsable = flags->parsable; | sdd.parsable = flags->parsable; | ||||
sdd.progress = flags->progress; | sdd.progress = flags->progress; | ||||
sdd.progressastitle = flags->progressastitle; | |||||
sdd.dryrun = flags->dryrun; | sdd.dryrun = flags->dryrun; | ||||
sdd.large_block = flags->largeblock; | sdd.large_block = flags->largeblock; | ||||
sdd.embed_data = flags->embed_data; | sdd.embed_data = flags->embed_data; | ||||
sdd.compress = flags->compress; | sdd.compress = flags->compress; | ||||
sdd.filter_cb = filter_func; | sdd.filter_cb = filter_func; | ||||
sdd.filter_cb_arg = cb_arg; | sdd.filter_cb_arg = cb_arg; | ||||
if (debugnvp) | if (debugnvp) | ||||
sdd.debugnv = *debugnvp; | sdd.debugnv = *debugnvp; | ||||
Show All 20 Lines | if (sdd.cleanup_fd < 0) { | ||||
err = errno; | err = errno; | ||||
goto stderr_out; | goto stderr_out; | ||||
} | } | ||||
sdd.snapholds = fnvlist_alloc(); | sdd.snapholds = fnvlist_alloc(); | ||||
} else { | } else { | ||||
sdd.cleanup_fd = -1; | sdd.cleanup_fd = -1; | ||||
sdd.snapholds = NULL; | sdd.snapholds = NULL; | ||||
} | } | ||||
if (flags->verbose || sdd.snapholds != NULL) { | if (flags->progress || sdd.snapholds != NULL) { | ||||
/* | /* | ||||
* Do a verbose no-op dry run to get all the verbose output | * Do a verbose no-op dry run to get all the verbose output | ||||
* or to gather snapshot hold's before generating any data, | * or to gather snapshot hold's before generating any data, | ||||
* then do a non-verbose real run to generate the streams. | * then do a non-verbose real run to generate the streams. | ||||
*/ | */ | ||||
sdd.dryrun = B_TRUE; | sdd.dryrun = B_TRUE; | ||||
err = dump_filesystems(zhp, &sdd); | err = dump_filesystems(zhp, &sdd); | ||||
▲ Show 20 Lines • Show All 1,881 Lines • Show Last 20 Lines |