changeset 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 210695c732dd
files docs/man/man8/fzfs-clone-tree.rst docs/man/man8/fzfs-mount.rst sbin/fzfs
diffstat 3 files changed, 46 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/docs/man/man8/fzfs-clone-tree.rst	Sun Sep 01 21:34:27 2024 +0200
+++ b/docs/man/man8/fzfs-clone-tree.rst	Sun Sep 01 21:52:01 2024 +0200
@@ -9,7 +9,7 @@
 Synopsis
 --------
 
-**fzfs clone-tree** [**-n**] `source-dataset` `dest-dataset`
+**fzfs clone-tree** [**-k**] [**-n**] `source-dataset` `dest-dataset`
 
 
 Description
@@ -36,6 +36,11 @@
 Options
 -------
 
+.. option:: -k
+
+   Do not try to destroy intermediately cloned datasets on errors but
+   keep them.
+
 .. option:: -n
 
    Dry-run. Do not really clone datasets but show what would be done.
--- a/docs/man/man8/fzfs-mount.rst	Sun Sep 01 21:34:27 2024 +0200
+++ b/docs/man/man8/fzfs-mount.rst	Sun Sep 01 21:52:01 2024 +0200
@@ -6,7 +6,7 @@
 Synopsis
 --------
 
-**fzfs mount** [**-O**] [**-N**] [**-P**] [**-n**] [**-u**] `dataset` [`mountpoint`]
+**fzfs mount** [**-O**] [**-N**] [**-P**] [**-k**] [**-n**] [**-u**] `dataset` [`mountpoint`]
 
 
 Description
@@ -38,6 +38,11 @@
 
    Do not mount the given parent `dataset` but only its children.
 
+.. option:: -k
+
+   Do not try to unmount intermediately mounted datasets on errors but
+   keep them mounted.
+
 .. option:: -n
 
    Do not really mount anything but show what would be mounted where.
--- 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
 }