diff sbin/fzfs @ 492:312aebce590c

FIX: Handle severe error in "fzfs mount" when the root dataset naturally mounts at root filesystem
author Franz Glasner <fzglas.hg@dom66.de>
date Fri, 30 Aug 2024 14:17:45 +0200
parents a2011285f054
children eb42828c0cbf
line wrap: on
line diff
--- a/sbin/fzfs	Fri Aug 30 10:49:36 2024 +0200
+++ b/sbin/fzfs	Fri Aug 30 14:17:45 2024 +0200
@@ -55,7 +55,7 @@
     local _opt_dry_run _opt_mount_outside _opt_mount_natural
     local _opt_mount_children_only
 
-    local _name _mp _canmount _mounted _rootds_mountpoint _relative_mp _real_mp
+    local _name _mp _canmount _mounted _rootds_mountpoint _rootds_mountpoint_prefix _relative_mp _real_mp
 
     _opt_dry_run=""
     _opt_mount_outside=""
@@ -115,6 +115,12 @@
         return 1
     fi
 
+    if [ "${_rootds_mountpoint}" = "/" ]; then
+        _rootds_mountpoint_prefix="/"
+    else
+        _rootds_mountpoint_prefix="${_rootds_mountpoint}/"
+    fi
+
     zfs list -H -o name,mountpoint,canmount,mounted -s mountpoint -t filesystem -r "${_dsname}" \
     | {
         while IFS=$'\t' read -r _name _mp _canmount _mounted ; do
@@ -131,18 +137,35 @@
                 "none"|"legacy")
                     # Do nothing for filesystem with unset or legacy mountpoints
                     ;;
-                "${_rootds_mountpoint}"|"${_rootds_mountpoint}/"*)
+                "${_rootds_mountpoint}"|"${_rootds_mountpoint_prefix}"*)
                     #
                     # Handle only mountpoints that have a mountpoint below
-                    # the parent datasets mountpoint
+                    # or exactly at the parent datasets mountpoint
                     #
 
-                    # Determine the mountpoint relative to the parent mountpoint
-                    _relative_mp="${_mp#${_rootds_mountpoint}}"
-                    # Eventually remove a trailing slash
-                    _relative_mp="${_relative_mp%/}"
-                    # The real effective full mountpoint
-                    _real_mp="${_mountpoint}${_relative_mp}"
+                    #
+                    # Determine the mountpoint relative to the parent
+                    # mountpoint. Extra effort is needed because the root
+                    # filesystem mount is just a single slash.
+                    #
+                    if [ "${_mp}" = "${_rootds_mountpoint}" ]; then
+                        if [ "${_name}" != "${_dsname}" ]; then
+                            echo "ERRROR: child dataset mounts over root dataset" >&2
+                            return 1
+                        fi                            
+                        _relative_mp=""
+                        _real_mp="${_mountpoint}"
+                    else
+                        _relative_mp="${_mp#${_rootds_mountpoint_prefix}}"
+                        # Eventually remove a trailing slash
+                        _relative_mp="${_relative_mp%/}"
+                        if [ -z "${_relative_mp}" ]; then
+                            echo "ERROR: got an empty relative mountpoint in child" >&2
+                            return 1
+                        fi
+                        # The real effective full mountpoint
+                        _real_mp="${_mountpoint}/${_relative_mp}"
+                    fi
 
                     #
                     # Consistency and sanity check: computed real mountpoint must