aboutsummaryrefslogtreecommitdiff
path: root/sbin/umount/umount.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/umount/umount.c')
-rw-r--r--sbin/umount/umount.c86
1 files changed, 67 insertions, 19 deletions
diff --git a/sbin/umount/umount.c b/sbin/umount/umount.c
index 9119c5be0da1..c15fd13d065a 100644
--- a/sbin/umount/umount.c
+++ b/sbin/umount/umount.c
@@ -29,20 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1980, 1989, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)umount.c 8.8 (Berkeley) 5/8/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/socket.h>
@@ -64,10 +50,20 @@ static const char rcsid[] =
#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 *);
@@ -84,17 +80,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;
@@ -102,6 +99,9 @@ main(int argc, char *argv[])
case 'a':
all = 1;
break;
+ case 'd':
+ dflag = 1;
+ break;
case 'F':
setfstab(optarg);
break;
@@ -469,6 +469,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);
}
@@ -651,7 +661,45 @@ 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;
+
+ if (strncmp(device, DEV_MD, sizeof(DEV_MD) - 1)) {
+ if (!all)
+ warnx("invalid md device: %s", device);
+ return (-1);
+ }
+
+ memset(&mdio, 0, sizeof(mdio));
+ mdio.md_version = MDIOVERSION;
+ mdio.md_options = fflag ? MD_FORCE : 0;
+ mdio.md_unit = strtoul(device + sizeof(DEV_MD) - 1, &eptr, 0);
+ if (mdio.md_unit == (unsigned)ULONG_MAX || eptr - device == sizeof(DEV_MD) - 1) {
+ 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);
+}