diff sbin/fzfs @ 521:c05ef1c86c9c

fzfs: Implement option "-k" for clone-tree and mount to keep cloned datasets or keep datasets mounted on errors
author Franz Glasner <fzglas.hg@dom66.de>
date Sun, 01 Sep 2024 21:52:01 +0200
parents 7d08fd78775c
children b7d60802b25f
line wrap: on
line diff
--- a/sbin/fzfs	Sun Sep 01 21:34:27 2024 +0200
+++ b/sbin/fzfs	Sun Sep 01 21:52:01 2024 +0200
@@ -28,13 +28,13 @@
 
 COMMANDS:
 
-  clone-tree [-n] SOUECE-DATASET DEST-DATASET
+  clone-tree [-k] [-n] SOUECE-DATASET DEST-DATASET
 
   copy-tree [-A] [-M MOUNTPOINT] [-n] [-u] SOURCE-DATASET DEST-DATASET
 
   create-tree [-A] [-M MOUNTPOINT] [-n] [-p] [-u] SOURCE-DATASET DEST-DATASET
 
-  mount [-O] [-N] [-P] [-u] [-n] DATASET [MOUNTPOINT]
+  mount [-O] [-N] [-P] [-k] [-u] [-n] DATASET [MOUNTPOINT]
 
   umount DATASET
 
@@ -56,15 +56,16 @@
 command_mount() {
     local _dsname _mountpoint
     local _opt_dry_run _opt_mount_outside _opt_mount_natural
-    local _opt_mount_children_only
+    local _opt_mount_children_only _opt_keep
 
     local _name _mp _canmount _mounted _rootds_mountpoint _rootds_mountpoint_prefix _relative_mp _real_mp
 
     _opt_dry_run=""
+    _opt_keep=""
     _opt_mount_outside=""
     _opt_mount_natural=""
     _opt_mount_children_only=""
-    while getopts "ONPnu" _opt ; do
+    while getopts "ONPknu" _opt ; do
         case ${_opt} in
             O)
                 _opt_mount_outside="yes"
@@ -75,6 +76,9 @@
             P)
                 _opt_mount_children_only="yes"
                 ;;
+            k)
+                _opt_keep="yes"
+                ;;
             n|u)
                 _opt_dry_run="yes"
                 ;;
@@ -162,7 +166,9 @@
                     if [ "${_mp}" = "${_rootds_mountpoint}" ]; then
                         if [ "${_name}" != "${_dsname}" ]; then
                             echo "ERROR: child dataset mounts over root dataset" >&2
-                            _umount_datasets _mounted_datasets || true
+                            if ! checkyes _opt_keep; then
+                                _umount_datasets _mounted_datasets || true
+                            fi
                             return 1
                         fi
                         _relative_mp=""
@@ -173,7 +179,9 @@
                         _relative_mp="${_relative_mp%/}"
                         if [ -z "${_relative_mp}" ]; then
                             echo "ERROR: got an empty relative mountpoint in child" >&2
-                            _umount_datasets _mounted_datasets || true
+                            if ! checkyes _opt_keep; then
+                                _umount_datasets _mounted_datasets || true
+                            fi
                             return 1
                         fi
                         # The real effective full mountpoint
@@ -188,7 +196,9 @@
                     if [ "${_opt_mount_natural}" = "yes" ]; then
                         if [ "${_real_mp}" != "${_mp}" ]; then
                             echo "ERROR: mountpoint mismatch" >&2
-                            _umount_datasets _mounted_datasets || true
+                            if ! checkyes _opt_keep; then
+                                _umount_datasets _mounted_datasets || true
+                            fi
                             return 1
                         fi
                     fi
@@ -202,7 +212,9 @@
                         if mount -t zfs "${_name}" "${_real_mp}"; then
                             array_append _mounted_datasets "${_name}"
                         else
-                            _umount_datasets _mounted_datasets || true
+                            if ! checkyes _opt_keep; then
+                                _umount_datasets _mounted_datasets || true
+                            fi
                             return 1
                         fi
                     fi
@@ -216,7 +228,9 @@
                             if zfs mount "${_name}"; then
                                 array_append _mounted_datasets "${_name}"
                             else
-                                _umount_datasets _mounted_datasets || true
+                                if ! checkyes _opt_keep; then
+                                    _umount_datasets _mounted_datasets || true
+                                fi
                                 return 1
                             fi
                         fi
@@ -436,7 +450,7 @@
 #:
 command_clone_tree() {
     local _ds_source _ds_dest
-    local _opt_dry_run
+    local _opt_keep _opt_dry_run
 
     local _ds snapshot_name _ds_source_base _ds_relname
     local _ds_canmount _ds_mountpoint
@@ -444,9 +458,13 @@
     local _opt _idx _idx_lp _prop _propval
 
     _opt_dry_run=""
+    _opt_keep=""
 
-    while getopts "n" _opt ; do
+    while getopts "kn" _opt ; do
         case ${_opt} in
+            k)
+                _opt_keep="yes"
+                ;;
             n)
                 _opt_dry_run="yes"
                 ;;
@@ -493,8 +511,7 @@
     _idx=1
     while array_tryget _ds _ds_tree ${_idx}; do
         if  ! zfs get -H name "${_ds}@${_snapshot_name}" >/dev/null 2>&1; then
-            err "child dataset does not exist: ${_ds}@${_snapshot_name}" 1>&2
-            array_destroy _ds_tree
+            err "child dataset (snapshot) does not exist: ${_ds}@${_snapshot_name}" 1>&2
             return 1
         fi
         _idx=$((${_idx} + 1))
@@ -556,7 +573,9 @@
             if zfs clone ${_arg_canmount} ${_arg_other_clone_props} "${_ds}@${_snapshot_name}" "${_ds_dest}${_ds_relname}"; then
                 array_append _cloned_datasets "${_ds_dest}${_ds_relname}"
             else
-                _destroy_datasets _cloned_datasets  || true
+                if ! checkyes _opt_keep; then
+                    _destroy_datasets _cloned_datasets || true
+                fi
                 return 1
             fi
         else
@@ -610,7 +629,7 @@
         fi
         _idx=$((${_idx} + 1))
     done
-
+    array_destroy _cloned_datasets
     return 0
 }