@@ -928,6 +928,39 @@ zfs_send_progress(zfs_handle_t *zhp, int fd, uint64_t *bytes_written,
928
928
return (0 );
929
929
}
930
930
931
+ static volatile boolean_t send_progress_thread_signal_duetotimer ;
932
+ static void
933
+ send_progress_thread_act (int sig , siginfo_t * info , void * ucontext )
934
+ {
935
+ (void ) sig , (void ) ucontext ;
936
+ send_progress_thread_signal_duetotimer = info -> si_code == SI_TIMER ;
937
+ }
938
+
939
+ struct timer_desirability {
940
+ timer_t timer ;
941
+ boolean_t desired ;
942
+ };
943
+ static void
944
+ timer_delete_cleanup (void * timer )
945
+ {
946
+ struct timer_desirability * td = timer ;
947
+ if (td -> desired )
948
+ timer_delete (td -> timer );
949
+ }
950
+
951
+ #ifdef SIGINFO
952
+ #define SEND_PROGRESS_THREAD_PARENT_BLOCK_SIGINFO sigaddset(&new, SIGINFO)
953
+ #else
954
+ #define SEND_PROGRESS_THREAD_PARENT_BLOCK_SIGINFO
955
+ #endif
956
+ #define SEND_PROGRESS_THREAD_PARENT_BLOCK (old ) { \
957
+ sigset_t new; \
958
+ sigemptyset(&new); \
959
+ sigaddset(&new, SIGUSR1); \
960
+ SEND_PROGRESS_THREAD_PARENT_BLOCK_SIGINFO; \
961
+ pthread_sigmask(SIG_BLOCK, &new, old); \
962
+ }
963
+
931
964
static void *
932
965
send_progress_thread (void * arg )
933
966
{
@@ -941,6 +974,26 @@ send_progress_thread(void *arg)
941
974
struct tm tm ;
942
975
int err ;
943
976
977
+ const struct sigaction signal_action =
978
+ {.sa_sigaction = send_progress_thread_act , .sa_flags = SA_SIGINFO };
979
+ struct sigevent timer_cfg =
980
+ {.sigev_notify = SIGEV_SIGNAL , .sigev_signo = SIGUSR1 };
981
+ const struct itimerspec timer_time =
982
+ {.it_value = {.tv_sec = 1 }, .it_interval = {.tv_sec = 1 }};
983
+ struct timer_desirability timer = {};
984
+
985
+ sigaction (SIGUSR1 , & signal_action , NULL );
986
+ #ifdef SIGINFO
987
+ sigaction (SIGINFO , & signal_action , NULL );
988
+ #endif
989
+
990
+ if ((timer .desired = pa -> pa_progress || pa -> pa_astitle )) {
991
+ if (timer_create (CLOCK_MONOTONIC , & timer_cfg , & timer .timer ))
992
+ return ((void * )(uintptr_t )errno );
993
+ (void ) timer_settime (timer .timer , 0 , & timer_time , NULL );
994
+ }
995
+ pthread_cleanup_push (timer_delete_cleanup , & timer );
996
+
944
997
if (!pa -> pa_parsable && pa -> pa_progress ) {
945
998
(void ) fprintf (stderr ,
946
999
"TIME %s %sSNAPSHOT %s\n" ,
@@ -953,12 +1006,12 @@ send_progress_thread(void *arg)
953
1006
* Print the progress from ZFS_IOC_SEND_PROGRESS every second.
954
1007
*/
955
1008
for (;;) {
956
- ( void ) sleep ( 1 );
1009
+ pause ( );
957
1010
if ((err = zfs_send_progress (zhp , pa -> pa_fd , & bytes ,
958
1011
& blocks )) != 0 ) {
959
1012
if (err == EINTR || err == ENOENT )
960
- return (( void * ) 0 ) ;
961
- return (( void * )(uintptr_t )err );
1013
+ err = 0 ;
1014
+ pthread_exit ((( void * )(uintptr_t )err ) );
962
1015
}
963
1016
964
1017
(void ) time (& t );
@@ -991,21 +1044,25 @@ send_progress_thread(void *arg)
991
1044
(void ) fprintf (stderr , "%02d:%02d:%02d\t%llu\t%s\n" ,
992
1045
tm .tm_hour , tm .tm_min , tm .tm_sec ,
993
1046
(u_longlong_t )bytes , zhp -> zfs_name );
994
- } else if (pa -> pa_progress ) {
1047
+ } else if (pa -> pa_progress ||
1048
+ !send_progress_thread_signal_duetotimer ) {
995
1049
zfs_nicebytes (bytes , buf , sizeof (buf ));
996
1050
(void ) fprintf (stderr , "%02d:%02d:%02d %5s %s\n" ,
997
1051
tm .tm_hour , tm .tm_min , tm .tm_sec ,
998
1052
buf , zhp -> zfs_name );
999
1053
}
1000
1054
}
1055
+ pthread_cleanup_pop (B_TRUE );
1001
1056
}
1002
1057
1003
1058
static boolean_t
1004
- send_progress_thread_exit (libzfs_handle_t * hdl , pthread_t ptid )
1059
+ send_progress_thread_exit (
1060
+ libzfs_handle_t * hdl , pthread_t ptid , sigset_t * oldmask )
1005
1061
{
1006
1062
void * status = NULL ;
1007
1063
(void ) pthread_cancel (ptid );
1008
1064
(void ) pthread_join (ptid , & status );
1065
+ pthread_sigmask (SIG_SETMASK , oldmask , NULL );
1009
1066
int error = (int )(uintptr_t )status ;
1010
1067
if (error != 0 && status != PTHREAD_CANCELED )
1011
1068
return (zfs_standard_error (hdl , error ,
@@ -1199,7 +1256,8 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
1199
1256
* If progress reporting is requested, spawn a new thread to
1200
1257
* poll ZFS_IOC_SEND_PROGRESS at a regular interval.
1201
1258
*/
1202
- if (sdd -> progress || sdd -> progressastitle ) {
1259
+ sigset_t oldmask ;
1260
+ {
1203
1261
pa .pa_zhp = zhp ;
1204
1262
pa .pa_fd = sdd -> outfd ;
1205
1263
pa .pa_parsable = sdd -> parsable ;
@@ -1214,13 +1272,13 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
1214
1272
zfs_close (zhp );
1215
1273
return (err );
1216
1274
}
1275
+ SEND_PROGRESS_THREAD_PARENT_BLOCK (& oldmask );
1217
1276
}
1218
1277
1219
1278
err = dump_ioctl (zhp , sdd -> prevsnap , sdd -> prevsnap_obj ,
1220
1279
fromorigin , sdd -> outfd , flags , sdd -> debugnv );
1221
1280
1222
- if ((sdd -> progress || sdd -> progressastitle ) &&
1223
- send_progress_thread_exit (zhp -> zfs_hdl , tid ))
1281
+ if (send_progress_thread_exit (zhp -> zfs_hdl , tid , & oldmask ))
1224
1282
return (-1 );
1225
1283
}
1226
1284
@@ -1562,8 +1620,9 @@ estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
1562
1620
progress_arg_t pa = { 0 };
1563
1621
int err = 0 ;
1564
1622
pthread_t ptid ;
1623
+ sigset_t oldmask ;
1565
1624
1566
- if ( flags -> progress || flags -> progressastitle ) {
1625
+ {
1567
1626
pa .pa_zhp = zhp ;
1568
1627
pa .pa_fd = fd ;
1569
1628
pa .pa_parsable = flags -> parsable ;
@@ -1577,15 +1636,15 @@ estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
1577
1636
return (zfs_error (zhp -> zfs_hdl ,
1578
1637
EZFS_THREADCREATEFAILED , errbuf ));
1579
1638
}
1639
+ SEND_PROGRESS_THREAD_PARENT_BLOCK (& oldmask );
1580
1640
}
1581
1641
1582
1642
err = lzc_send_space_resume_redacted (zhp -> zfs_name , from ,
1583
1643
lzc_flags_from_sendflags (flags ), resumeobj , resumeoff , bytes ,
1584
1644
redactbook , fd , & size );
1585
1645
* sizep = size ;
1586
1646
1587
- if ((flags -> progress || flags -> progressastitle ) &&
1588
- send_progress_thread_exit (zhp -> zfs_hdl , ptid ))
1647
+ if (send_progress_thread_exit (zhp -> zfs_hdl , ptid , & oldmask ))
1589
1648
return (-1 );
1590
1649
1591
1650
if (!flags -> progress && !flags -> parsable )
@@ -1876,11 +1935,12 @@ zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags,
1876
1935
if (!flags -> dryrun ) {
1877
1936
progress_arg_t pa = { 0 };
1878
1937
pthread_t tid ;
1938
+ sigset_t oldmask ;
1879
1939
/*
1880
1940
* If progress reporting is requested, spawn a new thread to
1881
1941
* poll ZFS_IOC_SEND_PROGRESS at a regular interval.
1882
1942
*/
1883
- if ( flags -> progress || flags -> progressastitle ) {
1943
+ {
1884
1944
pa .pa_zhp = zhp ;
1885
1945
pa .pa_fd = outfd ;
1886
1946
pa .pa_parsable = flags -> parsable ;
@@ -1898,15 +1958,15 @@ zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags,
1898
1958
zfs_close (zhp );
1899
1959
return (error );
1900
1960
}
1961
+ SEND_PROGRESS_THREAD_PARENT_BLOCK (& oldmask );
1901
1962
}
1902
1963
1903
1964
error = lzc_send_resume_redacted (zhp -> zfs_name , fromname , outfd ,
1904
1965
lzc_flags , resumeobj , resumeoff , redact_book );
1905
1966
if (redact_book != NULL )
1906
1967
free (redact_book );
1907
1968
1908
- if ((flags -> progressastitle || flags -> progress ) &&
1909
- send_progress_thread_exit (hdl , tid )) {
1969
+ if (send_progress_thread_exit (hdl , tid , & oldmask )) {
1910
1970
zfs_close (zhp );
1911
1971
return (-1 );
1912
1972
}
@@ -2691,7 +2751,8 @@ zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd,
2691
2751
* If progress reporting is requested, spawn a new thread to poll
2692
2752
* ZFS_IOC_SEND_PROGRESS at a regular interval.
2693
2753
*/
2694
- if (flags -> progress || flags -> progressastitle ) {
2754
+ sigset_t oldmask ;
2755
+ {
2695
2756
pa .pa_zhp = zhp ;
2696
2757
pa .pa_fd = fd ;
2697
2758
pa .pa_parsable = flags -> parsable ;
@@ -2708,13 +2769,13 @@ zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd,
2708
2769
return (zfs_error (zhp -> zfs_hdl ,
2709
2770
EZFS_THREADCREATEFAILED , errbuf ));
2710
2771
}
2772
+ SEND_PROGRESS_THREAD_PARENT_BLOCK (& oldmask );
2711
2773
}
2712
2774
2713
2775
err = lzc_send_redacted (name , from , fd ,
2714
2776
lzc_flags_from_sendflags (flags ), redactbook );
2715
2777
2716
- if ((flags -> progress || flags -> progressastitle ) &&
2717
- send_progress_thread_exit (hdl , ptid ))
2778
+ if (send_progress_thread_exit (hdl , ptid , & oldmask ))
2718
2779
return (-1 );
2719
2780
2720
2781
if (err == 0 && (flags -> props || flags -> holds || flags -> backup )) {
0 commit comments