git: f9b66c0040bf - stable/14 - umount: Add -d option to detach md devices

From: Warner Losh <imp_at_FreeBSD.org>
Date: Tue, 21 May 2024 22:50:21 UTC
The branch stable/14 has been updated by imp:

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

commit f9b66c0040bf03e5abe96df21690c51e881d72ed
Author:     Ricardo Branco <rbranco@suse.de>
AuthorDate: 2024-02-03 00:29:48 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2024-05-21 22:49:52 +0000

    umount: Add -d option to detach md devices
    
    Reviewed by: imp
    Pull Request: https://github.com/freebsd/freebsd-src/pull/972
    
    (cherry picked from commit 840a802750a464355c52b314c17fb067b317da8c)
---
 sbin/umount/umount.8 | 14 ++++++----
 sbin/umount/umount.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/sbin/umount/umount.8 b/sbin/umount/umount.8
index b5a7d7230269..086980151d60 100644
--- a/sbin/umount/umount.8
+++ b/sbin/umount/umount.8
@@ -25,9 +25,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"     @(#)umount.8	8.2 (Berkeley) 5/8/95
-.\"
-.Dd June 19, 2020
+.Dd January 16, 2024
 .Dt UMOUNT 8
 .Os
 .Sh NAME
@@ -35,7 +33,7 @@
 .Nd unmount file systems
 .Sh SYNOPSIS
 .Nm
-.Op Fl fNnv
+.Op Fl dfNnv
 .Ar special ... | node ... | fsid ...
 .Nm
 .Fl a | A
@@ -73,6 +71,11 @@ except for those mounted at
 .Pa /
 or
 .Pa /dev .
+.It Fl d
+If the filesystem is mounted on an
+.Xr md 4
+device (a memory disk), detach it after
+.Xr unmount 2 .
 .It Fl F Ar fstab
 Specify the
 .Pa fstab
@@ -184,7 +187,8 @@ file system table
 .Xr unmount 2 ,
 .Xr fstab 5 ,
 .Xr autounmountd 8 ,
-.Xr mount 8
+.Xr mount 8 ,
+.Xr mdconfig 8
 .Sh HISTORY
 A
 .Nm
diff --git a/sbin/umount/umount.c b/sbin/umount/umount.c
index aca7c201bc9b..d1471076359c 100644
--- a/sbin/umount/umount.c
+++ b/sbin/umount/umount.c
@@ -62,10 +62,20 @@ static char sccsid[] = "@(#)umount.c	8.8 (Berkeley) 5/8/95";
 
 #include "mounttab.h"
 
+/* used by md_detach() */
+#include <sys/ioctl.h>
+#include <sys/mdioctl.h>
+#include <fcntl.h>
+#include <paths.h>
+
+#define DEV_MD     _PATH_DEV   MD_NAME
+#define DEV_MDCTL   _PATH_DEV  MDCTL_NAME
+
 typedef enum { FIND, REMOVE, CHECKUNIQUE } dowhat;
 
 static struct addrinfo *nfshost_ai = NULL;
-static int	fflag, vflag;
+static int	dflag, fflag, vflag;
+static int	all;
 static char	*nfshost;
 
 struct statfs *checkmntlist(char *);
@@ -82,17 +92,18 @@ int	 checkname (char *, char **);
 int	 umountfs(struct statfs *sfs);
 void	 usage (void);
 int	 xdr_dir (XDR *, char *);
+int	 md_detach(const char *);
 
 int
 main(int argc, char *argv[])
 {
-	int all, errs, ch, mntsize, error, nfsforce, ret;
+	int errs, ch, mntsize, error, nfsforce, ret;
 	char **typelist = NULL;
 	struct statfs *mntbuf, *sfs;
 	struct addrinfo hints;
 
 	nfsforce = all = errs = 0;
-	while ((ch = getopt(argc, argv, "AaF:fh:Nnt:v")) != -1)
+	while ((ch = getopt(argc, argv, "AadF:fh:Nnt:v")) != -1)
 		switch (ch) {
 		case 'A':
 			all = 2;
@@ -100,6 +111,9 @@ main(int argc, char *argv[])
 		case 'a':
 			all = 1;
 			break;
+		case 'd':
+			dflag = 1;
+			break;
 		case 'F':
 			setfstab(optarg);
 			break;
@@ -467,6 +481,16 @@ umountfs(struct statfs *sfs)
 		clnt_destroy(clp);
 	}
 	free(orignfsdirname);
+
+	if (dflag) {
+		if (md_detach(sfs->f_mntfromname) == 0) {
+			if (vflag)
+				(void)printf("%s: detached\n",
+				    sfs->f_mntfromname);
+		} else if (!all)
+			return (-1);
+	}
+
 	return (0);
 }
 
@@ -649,7 +673,47 @@ usage(void)
 {
 
 	(void)fprintf(stderr, "%s\n%s\n",
-	    "usage: umount [-fNnv] special ... | node ... | fsid ...",
-	    "       umount -a | -A [-F fstab] [-fnv] [-h host] [-t type]");
+	    "usage: umount [-dfNnv] special ... | node ... | fsid ...",
+	    "       umount -a | -A [-F fstab] [-dfnv] [-h host] [-t type]");
 	exit(1);
 }
+
+int
+md_detach(const char *device)
+{
+	struct md_ioctl mdio;
+	char *eptr;
+	int fd;
+
+	memset(&mdio, 0, sizeof(mdio));
+
+	mdio.md_version = MDIOVERSION;
+	mdio.md_options = fflag ? MD_FORCE : 0;
+
+	if (strncmp(device, DEV_MD, sizeof(DEV_MD) - 1)) {
+		if (!all)
+			warnx("invalid md device: %s", device);
+		return (-1);
+	}
+
+	mdio.md_unit = strtoul(device + sizeof(DEV_MD) - 1, &eptr, 0);
+	if (mdio.md_unit == (unsigned)ULONG_MAX || *eptr != '\0') {
+		warnx("invalid md device: %s", device);
+		return (-1);
+	}
+
+	fd = open(DEV_MDCTL, O_RDWR, 0);
+	if (fd < 0) {
+		warn("%s", DEV_MDCTL);
+		return (-1);
+	}
+
+	if (ioctl(fd, MDIOCDETACH, &mdio) < 0) {
+		warn("%s", DEV_MD);
+		close(fd);
+		return (-1);
+	}
+
+	close(fd);
+	return (0);
+}