@@ -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=' '
@@ -77,6 +78,7 @@ print_usage ()
7778 -q, --quiet Suppress warnings and notices at the console.
7879 --send-full=F Send zfs full backup.
7980 --send-incr=F Send zfs incremental backup.
81+ --send-fallback Fallback from incremental to full if needed.
8082 --send-opts=F Option(s) passed to 'zfs send'.
8183 --recv-opts=F Option(s) passed to 'zfs receive'.
8284 --send-ssh-opts Option(s) passed to 'ssh'.
@@ -231,8 +233,8 @@ do_send () # snapname, oldglob
231233 local jj
232234
233235 [ -n " $opt_send_mbuf_opts " ] && remote=" mbuffer $opt_send_mbuf_opts |"
234- remote=" $remote ssh $opt_send_ssh_opts $opt_send_host "
235- remote=" $remote zfs receive $opt_recv_opts $opt_recv_pool "
236+ remote=" $remote ssh $opt_send_ssh_opts $opt_send_host "
237+ remote=" $remote zfs receive $opt_recv_opts "
236238
237239 # STEP 1: Go throug all snapshots we've created
238240 for ii in $SNAPS_DONE
@@ -263,22 +265,33 @@ do_send () # snapname, oldglob
263265 # 1: We change from incremental to full.
264266 # 2: We accept that the user have said INCR, and stick with
265267 # it.
266- if [ " $opt_send_type " = " incr" -a -z " $last_snap " ]; then
268+ # Normally we do point 2, but if --send-fallback is specified,
269+ # we allow it and convert to a full send instead.
270+ if [ " $opt_send_type " = " incr" -a -z " $last_snap " -a -z " $opt_send_fallback " ]; then
267271 if [ -n " $opt_verbose " ]; then
268272 echo " WARNING: No previous snapshots exist but we where called"
269273 echo " with --send-incr. Can not continue."
270274 echo " Please rerun with --send-full."
275+ echo " Or use --send-fallback."
271276 fi
272277 return 1
273278 fi
274279
275- if [ -n " $opt_recursive " -a -n " $last_snap " ]; then
280+ if [ -n " $opt_recursive " ]; then
276281 # STEP 3: Again, go through ALL snapshots that exists, but this
277282 # time only look for the snapshots that 'starts with'
278283 # the dataset/volume in question AND 'ends with'
279284 # the exact snapshot name/date in step 2.
280285 for jj in $SNAPSHOTS_OLD
281286 do
287+ # When trying to find snapshots recurively, we MUST have a 'last_snap'
288+ # value. Othervise, it will match ALL snapshots for dset (if we had
289+ # used '"^$dset.*@$GLOB" only).
290+ if [ -z " $last_snap " ] && echo " $jj " | grep -qE " ^$dset .*@$GLOB " ; then
291+ # Use this as last snapshot name
292+ last_snap=" ${jj#*@ } "
293+ fi
294+
282295 if echo " $jj " | grep -qE " ^$dset .*@$last_snap " ; then
283296 SNAPS_SEND=" $SNAPS_SEND
284297$jj "
@@ -297,9 +310,15 @@ $jj"
297310
298311 if [ $RUNSEND -eq 1 ]; then
299312 if [ " $opt_send_type " = " incr" ]; then
300- do_run " zfs send $opt_send_opts -i $jj $ii | $remote " || RUNSEND=0
313+ if [ " $jj " = " $ii " -a -n " $opt_send_fallback " ]; then
314+ do_run " zfs send $opt_send_opts -R $ii | $remote -F $opt_recv_pool " \
315+ || RUNSEND=0
316+ else
317+ do_run " zfs send $opt_send_opts -i $jj $ii | $remote $opt_recv_pool " \
318+ || RUNSEND=0
319+ fi
301320 else
302- do_run " zfs send $opt_send_opts -R $jj | $remote " || RUNSEND=0
321+ do_run " zfs send $opt_send_opts -R $jj | $remote $opt_recv_pool " || RUNSEND=0
303322 fi
304323
305324 if [ $RUNSEND = 1 -a -n " $opt_post_send " ]; then
@@ -320,6 +339,7 @@ GETOPT=$(getopt \
320339 --longoptions=pre-snapshot:,post-snapshot:,destroy-only \
321340 --longoptions=send-full:,send-incr:,send-opts:,recv-opts: \
322341 --longoptions=send-ssh-opts:,send-mbuf-opts:,pre-send:,post-send: \
342+ --longoptions=send-fallback \
323343 --options=dnshe:l:k:p:rs:qgv \
324344 -- " $@ " ) \
325345 || exit 128
420440 opt_recv_pool=$( echo " $2 " | sed ' s,.*:,,' )
421441 shift 2
422442 ;;
443+ (--send-fallback)
444+ opt_send_fallback=1
445+ shift 1
446+ ;;
423447 (--send-opts)
424448 opt_send_opts=" $2 "
425449 shift 2
0 commit comments