git: 0635fe29225b - stable/14 - libbe: attempt to remove autocreated mountpoints at unmount time

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Sat, 26 Apr 2025 03:24:57 UTC
The branch stable/14 has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=0635fe29225b5a4ecac63fc9d95dff63517d0003

commit 0635fe29225b5a4ecac63fc9d95dff63517d0003
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-04-21 03:47:59 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-04-26 03:23:55 +0000

    libbe: attempt to remove autocreated mountpoints at unmount time
    
    We use a be_mount.XXXX pattern to mkdtemp(3) when creating these, which
    seems reasonably unique enough to just continue using that.  Record the
    mountpoint of the root dataset and check the dirname of that for the
    auto-creation trait.  There's no sense in this bubbling up an error to
    callers, so we'll just ignore an error for now.
    
    Requested by:   manu
    
    (cherry picked from commit d6fbae084a2a0e07805633ca46935963357f1efa)
---
 lib/libbe/be_access.c | 30 +++++++++++++++++++++++++++++-
 lib/libbe/libbe.3     |  7 +++++++
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/lib/libbe/be_access.c b/lib/libbe/be_access.c
index 67b30d3fb4fb..51f5a75e957d 100644
--- a/lib/libbe/be_access.c
+++ b/lib/libbe/be_access.c
@@ -33,6 +33,8 @@
 #include "be.h"
 #include "be_impl.h"
 
+#define	LIBBE_MOUNT_PREFIX	"be_mount."	/* XXX */
+
 struct be_mountcheck_info {
 	const char *path;
 	char *name;
@@ -164,7 +166,11 @@ be_umount_iter(zfs_handle_t *zfs_hdl, void *data)
 	if (!zfs_is_mounted(zfs_hdl, &mountpoint)) {
 		return (0);
 	}
-	free(mountpoint);
+
+	if (info->depth == 0 && info->mountpoint == NULL)
+		info->mountpoint = mountpoint;
+	else
+		free(mountpoint);
 
 	if (zfs_unmount(zfs_hdl, NULL, info->mntflags) != 0) {
 		switch (errno) {
@@ -307,10 +313,32 @@ be_unmount(libbe_handle_t *lbh, const char *bootenv, int flags)
 	info.depth = 0;
 
 	if ((err = be_umount_iter(root_hdl, &info)) != 0) {
+		free(__DECONST(char *, info.mountpoint));
 		zfs_close(root_hdl);
 		return (err);
 	}
 
+	/*
+	 * We'll attempt to remove the directory if we created it on a
+	 * best-effort basis.  rmdir(2) failure will not be reported.
+	 */
+	if (info.mountpoint != NULL) {
+		const char *mdir;
+
+		mdir = strrchr(info.mountpoint, '/');
+		if (mdir == NULL)
+			mdir = info.mountpoint;
+		else
+			mdir++;
+
+		if (strncmp(mdir, LIBBE_MOUNT_PREFIX,
+		    sizeof(LIBBE_MOUNT_PREFIX) - 1) == 0) {
+			(void)rmdir(info.mountpoint);
+		}
+	}
+
+	free(__DECONST(char *, info.mountpoint));
+
 	zfs_close(root_hdl);
 	return (BE_ERR_SUCCESS);
 }
diff --git a/lib/libbe/libbe.3 b/lib/libbe/libbe.3
index 644b1d71ccd3..743922a76391 100644
--- a/lib/libbe/libbe.3
+++ b/lib/libbe/libbe.3
@@ -392,6 +392,13 @@ This list of properties matches the properties collected by
 The
 .Fn be_unmount
 function will unmount the given boot environment.
+If the mount point looks like it was created by
+.Fn be_mount ,
+then
+.Fn be_unmount
+will attempt to
+.Xr rmdir 2
+the mountpoint after a successful unmount.
 Setting the
 .Dv BE_MNT_FORCE
 flag will pass