From abf3d458ff20444c40acac1997d2e380367c9487 Mon Sep 17 00:00:00 2001 From: Christoph Klaffl Date: Thu, 26 Jul 2018 21:43:09 +0200 Subject: [PATCH 1/2] check for partial resume state for non resume style transfers, if so reset state and retry --- syncoid | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/syncoid b/syncoid index f53aee4..0e60680 100755 --- a/syncoid +++ b/syncoid @@ -391,8 +391,20 @@ sub syncdataset { if (!$quiet) { print "Sending incremental $sourcefs\@$matchingsnap ... $newsyncsnap (~ $disp_pvsize):\n"; } if ($debug) { print "DEBUG: $synccmd\n"; } - system("$synccmd") == 0 - or die "CRITICAL ERROR: $synccmd failed: $?"; + + my $output = `$synccmd 2>&1`; + my $exitcode = $?; + + if ($exitcode != 0) { + if (!$resume && $output =~ /\Qcontains partially-complete state\E/) { + if (!$quiet) { print "Resetting partially receive state\n"; } + resetreceivestate($targethost,$targetfs,$targetisroot); + system($synccmd) == 0 + or die "CRITICAL ERROR: $synccmd failed: $?"; + } else { + die "CRITICAL ERROR: $synccmd failed: $exitcode"; + } + } # restore original readonly value to target after sync complete # dyking this functionality out for the time being due to buggy mount/unmount behavior @@ -1143,6 +1155,26 @@ sub getreceivetoken() { return } +sub resetreceivestate { + my ($rhost,$fs,$isroot) = @_; + + my $fsescaped = escapeshellparam($fs); + + if ($rhost ne '') { + $rhost = "$sshcmd $rhost"; + # double escaping needed + $fsescaped = escapeshellparam($fsescaped); + } + + if ($debug) { print "DEBUG: reset partial receive state of $fs...\n"; } + my $mysudocmd; + if ($isroot) { $mysudocmd = ''; } else { $mysudocmd = $sudocmd; } + my $resetcmd = "$rhost $mysudocmd $zfscmd receive -A $fsescaped"; + if ($debug) { print "$resetcmd\n"; } + system("$resetcmd") == 0 + or die "CRITICAL ERROR: $resetcmd failed: $?"; +} + __END__ =head1 NAME From 1046f7f58e23128bf798aaf301048714ad333844 Mon Sep 17 00:00:00 2001 From: Christoph Klaffl Date: Thu, 16 May 2019 18:42:26 +0200 Subject: [PATCH 2/2] use capture::tiny for teeing commands --- syncoid | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/syncoid b/syncoid index 51002b7..389f1a9 100755 --- a/syncoid +++ b/syncoid @@ -13,6 +13,7 @@ use Getopt::Long qw(:config auto_version auto_help); use Pod::Usage; use Time::Local; use Sys::Hostname; +use Capture::Tiny ':all'; my $mbuffer_size = "16M"; @@ -672,10 +673,15 @@ sub syncdataset { if (!$quiet) { print "Sending incremental $sourcefs#$bookmarkescaped ... $nextsnapshot (~ $disp_pvsize):\n"; } if ($debug) { print "DEBUG: $synccmd\n"; } - my $output = `$synccmd 2>&1`; + my $stdout; + my $stderr; + my $exit; + ($stdout, $stderr, $exit) = tee { + system("$synccmd") + }; - $? == 0 or do { - if (!$resume && $output =~ /\Qcontains partially-complete state\E/) { + $exit == 0 or do { + if (!$resume && $stderr =~ /\Qcontains partially-complete state\E/) { if (!$quiet) { print "WARN: resetting partially receive state\n"; } resetreceivestate($targethost,$targetfs,$targetisroot); system("$synccmd") == 0 or do { @@ -700,10 +706,15 @@ sub syncdataset { if (!$quiet) { print "Sending incremental $sourcefs#$bookmarkescaped ... $newsyncsnap (~ $disp_pvsize):\n"; } if ($debug) { print "DEBUG: $synccmd\n"; } - my $output = `$synccmd 2>&1`; + my $stdout; + my $stderr; + my $exit; + ($stdout, $stderr, $exit) = tee { + system("$synccmd") + }; - $? == 0 or do { - if (!$resume && $output =~ /\Qcontains partially-complete state\E/) { + $exit == 0 or do { + if (!$resume && $stderr =~ /\Qcontains partially-complete state\E/) { if (!$quiet) { print "WARN: resetting partially receive state\n"; } resetreceivestate($targethost,$targetfs,$targetisroot); system("$synccmd") == 0 or do { @@ -739,10 +750,15 @@ sub syncdataset { if (!$quiet) { print "Sending incremental $sourcefs\@$matchingsnap ... $newsyncsnap (~ $disp_pvsize):\n"; } if ($debug) { print "DEBUG: $synccmd\n"; } - my $output = `$synccmd 2>&1`; + my $stdout; + my $stderr; + my $exit; + ($stdout, $stderr, $exit) = tee { + system("$synccmd") + }; - $? == 0 or do { - if (!$resume && $output =~ /\Qcontains partially-complete state\E/) { + $exit == 0 or do { + if (!$resume && $stderr =~ /\Qcontains partially-complete state\E/) { if (!$quiet) { print "WARN: resetting partially receive state\n"; } resetreceivestate($targethost,$targetfs,$targetisroot); system("$synccmd") == 0 or do {