@@ -41,6 +41,7 @@ opt_send_opts=''
4141opt_recv_opts=' '
4242opt_send_ssh_opts=' '
4343opt_send_mbuf_opts=' '
44+ opt_send_fallback=' '
4445opt_sep=' _'
4546opt_setauto=' '
4647opt_syslog=' '
@@ -78,6 +79,7 @@ print_usage ()
7879 -q, --quiet Suppress warnings and notices at the console.
7980 --send-full=F Send zfs full backup.
8081 --send-incr=F Send zfs incremental backup.
82+ --send-fallback Fallback from incremental to full if needed.
8183 --send-opts=F Option(s) passed to 'zfs send'.
8284 --recv-opts=F Option(s) passed to 'zfs receive'.
8385 --send-ssh-opts Option(s) passed to 'ssh'.
@@ -189,22 +191,33 @@ find_last_snap () # dset, GLOB
189191 # 1: We change from incremental to full.
190192 # 2: We accept that the user have said INCR, and stick with
191193 # it.
192- if [ " $opt_send_type " = " incr" -a -z " $last_snap " ]; then
194+ # Normally we do point 2, but if --send-fallback is specified,
195+ # we allow it and convert to a full send instead.
196+ if [ " $opt_send_type " = " incr" -a -z " $last_snap " -a -z " $opt_send_fallback " ]; then
193197 if [ -n " $opt_verbose " ]; then
194198 echo > /dev/stderr " WARNING: No previous snapshots exist but we where called"
195199 echo > /dev/stderr " with --send-incr. Can not continue."
196200 echo > /dev/stderr " Please rerun with --send-full."
201+ echo > /dev/stderr " Or use --send-fallback."
197202 fi
198203 return 1
199204 fi
200205
201- if [ -n " $opt_recursive " -a -n " $last_snap " ]; then
206+ if [ -n " $opt_recursive " ]; then
202207 # STEP 2: Again, go through ALL snapshots that exists, but this
203208 # time only look for the snapshots that 'starts with'
204209 # the dataset/volume in question AND 'ends with'
205210 # the exact snapshot name/date in step 2.
206211 for jj in $SNAPSHOTS_OLD
207212 do
213+ # When trying to find snapshots recurively, we MUST have a 'last_snap'
214+ # value. Othervise, it will match ALL snapshots for dset (if we had
215+ # used '"^$dset.*@$GLOB" only).
216+ if [ -z " $last_snap " ] && echo " $jj " | grep -qE " ^$dset .*@$GLOB " ; then
217+ # Use this as last snapshot name
218+ last_snap=" ${jj#*@ } "
219+ fi
220+
208221 if echo " $jj " | grep -qE " ^$dset .*@$last_snap " ; then
209222 echo $jj
210223 fi
@@ -288,8 +301,8 @@ do_send () # snapname, oldglob
288301 local jj
289302
290303 [ -n " $opt_send_mbuf_opts " ] && remote=" mbuffer $opt_send_mbuf_opts |"
291- remote=" $remote ssh $opt_send_ssh_opts $opt_send_host "
292- remote=" $remote zfs receive $opt_recv_opts $opt_recv_pool "
304+ remote=" $remote ssh $opt_send_ssh_opts $opt_send_host "
305+ remote=" $remote zfs receive $opt_recv_opts "
293306
294307 # STEP 1: Go throug all snapshots we've created
295308 for ii in $SNAPS_DONE
@@ -309,9 +322,15 @@ do_send () # snapname, oldglob
309322
310323 if [ $RUNSEND -eq 1 ]; then
311324 if [ " $opt_send_type " = " incr" ]; then
312- do_run " zfs send $opt_send_opts -i $jj $ii | $remote " || RUNSEND=0
325+ if [ " $jj " = " $ii " -a -n " $opt_send_fallback " ]; then
326+ do_run " zfs send $opt_send_opts -R $ii | $remote -F $opt_recv_pool " \
327+ || RUNSEND=0
328+ else
329+ do_run " zfs send $opt_send_opts -i $jj $ii | $remote $opt_recv_pool " \
330+ || RUNSEND=0
331+ fi
313332 else
314- do_run " zfs send $opt_send_opts -R $jj | $remote " || RUNSEND=0
333+ do_run " zfs send $opt_send_opts -R $jj | $remote $opt_recv_pool " || RUNSEND=0
315334 fi
316335
317336 if [ $RUNSEND = 1 -a -n " $opt_post_send " ]; then
@@ -332,6 +351,7 @@ GETOPT=$(getopt \
332351 --longoptions=pre-snapshot:,post-snapshot:,destroy-only \
333352 --longoptions=send-full:,send-incr:,send-opts:,recv-opts: \
334353 --longoptions=send-ssh-opts:,send-mbuf-opts:,pre-send:,post-send: \
354+ --longoptions=send-fallback \
335355 --options=dnshe:l:k:p:rs:qgv \
336356 -- " $@ " ) \
337357 || exit 128
432452 opt_recv_pool=$( echo " $2 " | sed ' s,.*:,,' )
433453 shift 2
434454 ;;
455+ (--send-fallback)
456+ opt_send_fallback=1
457+ shift 1
458+ ;;
435459 (--send-opts)
436460 opt_send_opts=" $2 "
437461 shift 2
0 commit comments