diff --git a/src/zfs-auto-snapshot.sh b/src/zfs-auto-snapshot.sh index c34a87a..4d2d49b 100755 --- a/src/zfs-auto-snapshot.sh +++ b/src/zfs-auto-snapshot.sh @@ -107,7 +107,7 @@ print_usage () -R, --replication Use zfs's replication (zfs send -R) instead of simple send over newly created snapshots (check man zfs for details). -f is used automatically. -v, --verbose Print info messages. - -f, --force Passes -F argument to zfs receive + -f, --force Passes -F argument to zfs receive (e.g. makes possible to overwrite remote filesystem during --send-full) name Filesystem and volume names, or '//' for all ZFS datasets. " } @@ -282,15 +282,13 @@ do_send () local list_child=('') if [ "$SENDFLAGS" = "-R" -a "$SENDTYPE" = "full" ]; then - # for full send with -R, target filesystem must be without snapshots including chilren as well - list_child=($(printf "%s\n" "${SNAPSHOTS_OLD_REM[@]}" | grep ^"$REMOTEFS" | grep @)) - if [ "$SENDTYPE" = "full" ]; then - list_child=( "${list_child[@]}" $(printf "%s\n" "${ZFS_REMOTE_LIST[@]}" | grep ^"$REMOTEFS" | sort -r )) - fi - elif [ "$SENDTYPE" = "full" ]; then - list_child=( $(printf "%s\n" "${SNAPSHOTS_OLD_REM[@]}" | grep ^"$REMOTEFS@" ) ) + # for full send with -R, target filesystem must be with no snapshots (including snapshots on child filesystems) + list_child=( $(printf "%s\n" "${SNAPSHOTS_OLD_REM[@]}" | grep ^"$REMOTEFS/" ) ) fi - + if [ "$SENDTYPE" = "full" ]; then + list_child=( ${list_child[@]} $(printf "%s\n" "${SNAPSHOTS_OLD_REM[@]}" | grep ^"$REMOTEFS@" ) ) + fi + for ll in ${list_child[@]}; do if do_delete "remote" "$ll" ""; then continue @@ -341,7 +339,14 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...] LAST_REMOTE=$(printf "%s\n" ${SNAPSHOTS_OLD_REM[@]} | grep ^$opt_sendprefix/$ii@ | grep -m1 . | awk -F'@' '{print $2}') - # remote filesystem just created. if -R run + # in case of -R and incremental send, receiving side needs to have $LAST_REMOTE snapshot for each replicated filesystem + if [ "$FLAGS" = "-r" ]; then + snaps_needed=$(( $(printf "%s\n" ${ZFS_LIST_LOC[@]} | grep ^"$ii/") + 1 )) + else + snaps_needed='1' + fi + + # remote filesystem just created. if -R run if ! is_member "${CREATED_TARGETS[*]}" "$opt_sendprefix/$ii" then FALLBACK='2' @@ -349,8 +354,8 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...] then # no snapshot on remote FALLBACK='1' - # last snapshot on remote is no more available on local, this applies both for -r and non -r runs - elif [ $(printf "%s\n" "${SNAPSHOTS_OLD_REM[@]}" | grep -c -e ^$opt_sendprefix/$ii$SNexp@$LAST_REMOTE ) -ne $(printf "%s\n" "${SNAPSHOTS_OLD_LOC[@]}" | grep -c -e ^$ii$SNexp@$LAST_REMOTE ) ] + elif [ "$snaps_needed" -ne $(printf "%s\n" ${SNAPSHOTS_OLD_REM[@]} | grep -c -e ^"$opt_sendprefix/$ii$SNexp@$LAST_REMOTE" ) -o \ + "$snaps_needed" -ne $(printf "%s\n" ${SNAPSHOTS_OLD_LOC[@]} | grep -c -e ^"$ii$SNexp@$LAST_REMOTE" ) ] then FALLBACK='3' else @@ -365,10 +370,14 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...] print_log info "Going back to full send, remote filesystem was just created: $ii" ;; (3) - print_log info "Going back to full send, last snapshot on remote is not available on local: $opt_sendprefix/$ii@$LAST_REMOTE" - ;; + if [ "$FLAGS" = "-r" ]; then + print_log info "Going back to full send, last snapshot on remote is not the last one for whole recursion: $opt_sendprefix/$ii@$LAST_REMOTE" + else + print_log info "Going back to full send, last snapshot on remote is not available on local: $opt_sendprefix/$ii@$LAST_REMOTE" + fi + ;; (0) - do_send "incr" "$ii@$LAST_REMOTE" "$ii@$NAME" "$sFLAGS" "$opt_sendprefix/$ii" + do_send "incr" "$ii@$LAST_REMOTE" "$ii@$NAME" "$sFLAGS" "$opt_sendprefix/$ii" SND_RC="$?" ;; esac @@ -412,7 +421,7 @@ do_snapshots () # properties, flags, snapname, oldglob, [targets...] continue elif [ "$sFLAGS" = "-R" ] then - print_log debug "Replication specified, snapshots were removed while sending." + print_log debug "Replication specified, remote snapshots were removed while sending." continue elif [ "$opt_destroy" -eq '1' -a "$FALLBACK" -ne '0' -o "$opt_send" = "full" ] then