@@ -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'.
@@ -230,8 +232,8 @@ do_send () # snapname, oldglob
230232 local jj
231233
232234 [ -n " $opt_send_mbuf_opts " ] && remote=" mbuffer $opt_send_mbuf_opts |"
233- remote=" $remote ssh $opt_send_ssh_opts $opt_send_host "
234- remote=" $remote zfs receive $opt_recv_opts $opt_recv_pool "
235+ remote=" $remote ssh $opt_send_ssh_opts $opt_send_host "
236+ remote=" $remote zfs receive $opt_recv_opts "
235237
236238 # STEP 1: Go throug all snapshots we've created
237239 for ii in $SNAPS_DONE
@@ -262,22 +264,33 @@ do_send () # snapname, oldglob
262264 # 1: We change from incremental to full.
263265 # 2: We accept that the user have said INCR, and stick with
264266 # it.
265- if [ " $opt_send_type " = " incr" -a -z " $last_snap " ]; then
267+ # Normally we do point 2, but if --send-fallback is specified,
268+ # we allow it and convert to a full send instead.
269+ if [ " $opt_send_type " = " incr" -a -z " $last_snap " -a -z " $opt_send_fallback " ]; then
266270 if [ -n " $opt_verbose " ]; then
267271 echo " WARNING: No previous snapshots exist but we where called"
268272 echo " with --send-incr. Can not continue."
269273 echo " Please rerun with --send-full."
274+ echo " Or use --send-fallback."
270275 fi
271276 return 1
272277 fi
273278
274- if [ -n " $opt_recursive " -a -n " $last_snap " ]; then
279+ if [ -n " $opt_recursive " ]; then
275280 # STEP 3: Again, go through ALL snapshots that exists, but this
276281 # time only look for the snapshots that 'starts with'
277282 # the dataset/volume in question AND 'ends with'
278283 # the exact snapshot name/date in step 2.
279284 for jj in $SNAPSHOTS_OLD
280285 do
286+ # When trying to find snapshots recurively, we MUST have a 'last_snap'
287+ # value. Othervise, it will match ALL snapshots for dset (if we had
288+ # used '"^$dset.*@$GLOB" only).
289+ if [ -z " $last_snap " ] && echo " $jj " | grep -qE " ^$dset .*@$GLOB " ; then
290+ # Use this as last snapshot name
291+ last_snap=" ${jj#*@ } "
292+ fi
293+
281294 if echo " $jj " | grep -qE " ^$dset .*@$last_snap " ; then
282295 SNAPS_SEND=" $SNAPS_SEND
283296$jj "
@@ -296,9 +309,15 @@ $jj"
296309
297310 if [ $RUNSEND -eq 1 ]; then
298311 if [ " $opt_send_type " = " incr" ]; then
299- do_run " zfs send $opt_send_opts -i $jj $ii | $remote " || RUNSEND=0
312+ if [ " $jj " = " $ii " -a -n " $opt_send_fallback " ]; then
313+ do_run " zfs send $opt_send_opts -R $ii | $remote -F $opt_recv_pool " \
314+ || RUNSEND=0
315+ else
316+ do_run " zfs send $opt_send_opts -i $jj $ii | $remote $opt_recv_pool " \
317+ || RUNSEND=0
318+ fi
300319 else
301- do_run " zfs send $opt_send_opts -R $jj | $remote " || RUNSEND=0
320+ do_run " zfs send $opt_send_opts -R $jj | $remote $opt_recv_pool " || RUNSEND=0
302321 fi
303322
304323 if [ $RUNSEND = 1 -a -n " $opt_post_send " ]; then
@@ -319,6 +338,7 @@ GETOPT=$(getopt \
319338 --longoptions=pre-snapshot:,post-snapshot:,destroy-only \
320339 --longoptions=send-full:,send-incr:,send-opts:,recv-opts: \
321340 --longoptions=send-ssh-opts:,send-mbuf-opts:,pre-send:,post-send: \
341+ --longoptions=send-fallback \
322342 --options=dnshe:l:k:p:rs:qgv \
323343 -- " $@ " ) \
324344 || exit 128
419439 opt_recv_pool=$( echo " $2 " | sed ' s,.*:,,' )
420440 shift 2
421441 ;;
442+ (--send-fallback)
443+ opt_send_fallback=1
444+ shift 1
445+ ;;
422446 (--send-opts)
423447 opt_send_opts=" $2 "
424448 shift 2
0 commit comments