git: d6fbae084a2a - main - libbe: attempt to remove autocreated mountpoints at unmount time

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Mon, 21 Apr 2025 03:49:51 UTC
The branch main has been updated by kevans:

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

commit d6fbae084a2a0e07805633ca46935963357f1efa
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-04-21 03:47:59 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-04-21 03:47:59 +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
    Differential Revision:  https://reviews.freebsd.org/D42243
---
 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 4d9439206b7b..113763311796 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