From 1ca595de843852d0606140a1cefc1598b3345e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Thu, 27 Jul 2023 01:36:47 +0200 Subject: [PATCH] libzfs: sendrecv: always start the progress thread, but not the timer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current semantics are preserved, /except/ no-flag "zfs send" can now receive SIGUSR1/SIGINFO will write the progress. Closes: https://101010.pl/@ed1conf@bsd.network/110731819189629373 Signed-off-by: Ahelenia ZiemiaƄska --- lib/libzfs/libzfs_sendrecv.c | 51 ++++++++++++++++++++---------------- man/man8/zfs-send.8 | 18 ++++++++++++- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index 229d3c65ea85..e9bc78aa8d39 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -928,16 +928,24 @@ zfs_send_progress(zfs_handle_t *zhp, int fd, uint64_t *bytes_written, return (0); } +static volatile boolean_t send_progress_thread_signal_duetotimer; static void -signal_nop(int sig) +send_progress_thread_act(int sig, siginfo_t *info, void *ucontext) { - (void) sig; + (void) sig, (void) ucontext; + send_progress_thread_signal_duetotimer = info->si_code == SI_TIMER; } +struct timer_desirability { + timer_t timer; + boolean_t desired; +}; static void timer_delete_cleanup(void *timer) { - timer_delete(timer); + struct timer_desirability *td = timer; + if (td->desired) + timer_delete(td->timer); } #ifdef SIGINFO @@ -967,22 +975,24 @@ send_progress_thread(void *arg) int err; const struct sigaction signal_action = - {.sa_handler = signal_nop}; + {.sa_sigaction = send_progress_thread_act, .sa_flags = SA_SIGINFO}; struct sigevent timer_cfg = {.sigev_notify = SIGEV_SIGNAL, .sigev_signo = SIGUSR1}; const struct itimerspec timer_time = {.it_value = {.tv_sec = 1}, .it_interval = {.tv_sec = 1}}; - timer_t timer; + struct timer_desirability timer = {}; sigaction(SIGUSR1, &signal_action, NULL); #ifdef SIGINFO sigaction(SIGINFO, &signal_action, NULL); #endif - if (timer_create(CLOCK_MONOTONIC, &timer_cfg, &timer)) - return ((void *)(uintptr_t)errno); - pthread_cleanup_push(timer_delete_cleanup, timer); - (void) timer_settime(timer, 0, &timer_time, NULL); + if ((timer.desired = pa->pa_progress || pa->pa_astitle)) { + if (timer_create(CLOCK_MONOTONIC, &timer_cfg, &timer.timer)) + return ((void *)(uintptr_t)errno); + (void) timer_settime(timer.timer, 0, &timer_time, NULL); + } + pthread_cleanup_push(timer_delete_cleanup, &timer); if (!pa->pa_parsable && pa->pa_progress) { (void) fprintf(stderr, @@ -1034,7 +1044,8 @@ send_progress_thread(void *arg) (void) fprintf(stderr, "%02d:%02d:%02d\t%llu\t%s\n", tm.tm_hour, tm.tm_min, tm.tm_sec, (u_longlong_t)bytes, zhp->zfs_name); - } else if (pa->pa_progress) { + } else if (pa->pa_progress || + !send_progress_thread_signal_duetotimer) { zfs_nicebytes(bytes, buf, sizeof (buf)); (void) fprintf(stderr, "%02d:%02d:%02d %5s %s\n", tm.tm_hour, tm.tm_min, tm.tm_sec, @@ -1246,7 +1257,7 @@ dump_snapshot(zfs_handle_t *zhp, void *arg) * poll ZFS_IOC_SEND_PROGRESS at a regular interval. */ sigset_t oldmask; - if (sdd->progress || sdd->progressastitle) { + { pa.pa_zhp = zhp; pa.pa_fd = sdd->outfd; pa.pa_parsable = sdd->parsable; @@ -1267,8 +1278,7 @@ dump_snapshot(zfs_handle_t *zhp, void *arg) err = dump_ioctl(zhp, sdd->prevsnap, sdd->prevsnap_obj, fromorigin, sdd->outfd, flags, sdd->debugnv); - if ((sdd->progress || sdd->progressastitle) && - send_progress_thread_exit(zhp->zfs_hdl, tid, &oldmask)) + if (send_progress_thread_exit(zhp->zfs_hdl, tid, &oldmask)) return (-1); } @@ -1612,7 +1622,7 @@ estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags, pthread_t ptid; sigset_t oldmask; - if (flags->progress || flags->progressastitle) { + { pa.pa_zhp = zhp; pa.pa_fd = fd; pa.pa_parsable = flags->parsable; @@ -1634,8 +1644,7 @@ estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags, redactbook, fd, &size); *sizep = size; - if ((flags->progress || flags->progressastitle) && - send_progress_thread_exit(zhp->zfs_hdl, ptid, &oldmask)) + if (send_progress_thread_exit(zhp->zfs_hdl, ptid, &oldmask)) return (-1); if (!flags->progress && !flags->parsable) @@ -1931,7 +1940,7 @@ zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags, * If progress reporting is requested, spawn a new thread to * poll ZFS_IOC_SEND_PROGRESS at a regular interval. */ - if (flags->progress || flags->progressastitle) { + { pa.pa_zhp = zhp; pa.pa_fd = outfd; pa.pa_parsable = flags->parsable; @@ -1957,8 +1966,7 @@ zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags, if (redact_book != NULL) free(redact_book); - if ((flags->progressastitle || flags->progress) && - send_progress_thread_exit(hdl, tid, &oldmask)) { + if (send_progress_thread_exit(hdl, tid, &oldmask)) { zfs_close(zhp); return (-1); } @@ -2744,7 +2752,7 @@ zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd, * ZFS_IOC_SEND_PROGRESS at a regular interval. */ sigset_t oldmask; - if (flags->progress || flags->progressastitle) { + { pa.pa_zhp = zhp; pa.pa_fd = fd; pa.pa_parsable = flags->parsable; @@ -2767,8 +2775,7 @@ zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd, err = lzc_send_redacted(name, from, fd, lzc_flags_from_sendflags(flags), redactbook); - if ((flags->progress || flags->progressastitle) && - send_progress_thread_exit(hdl, ptid, &oldmask)) + if (send_progress_thread_exit(hdl, ptid, &oldmask)) return (-1); if (err == 0 && (flags->props || flags->holds || flags->backup)) { diff --git a/man/man8/zfs-send.8 b/man/man8/zfs-send.8 index 8cc6ae6ad59b..ba604bf77855 100644 --- a/man/man8/zfs-send.8 +++ b/man/man8/zfs-send.8 @@ -29,7 +29,7 @@ .\" Copyright 2018 Nexenta Systems, Inc. .\" Copyright 2019 Joyent, Inc. .\" -.Dd January 12, 2023 +.Dd July 27, 2023 .Dt ZFS-SEND 8 .Os . @@ -297,6 +297,12 @@ This flag can only be used in conjunction with .It Fl v , -verbose Print verbose information about the stream package generated. This information includes a per-second report of how much data has been sent. +The same report can be requested by sending +.Dv SIGINFO +or +.Dv SIGUSR1 , +regardless of +.Fl v . .Pp The format of the stream is committed. You will be able to receive your streams on future versions of ZFS. @@ -433,6 +439,12 @@ and the verbose output goes to standard error .It Fl v , -verbose Print verbose information about the stream package generated. This information includes a per-second report of how much data has been sent. +The same report can be requested by sending +.Dv SIGINFO +or +.Dv SIGUSR1 , +regardless of +.Fl v . .El .It Xo .Nm zfs @@ -669,6 +681,10 @@ ones on the source, and are ready to be used, while the parent snapshot on the target contains none of the username and password data present on the source, because it was removed by the redacted send operation. . +.Sh SIGNALS +See +.Fl v . +. .Sh EXAMPLES .\" These are, respectively, examples 12, 13 from zfs.8 .\" Make sure to update them bidirectionally