Page MenuHomeFreeBSD

D51549.id163336.diff
No OneTemporary

D51549.id163336.diff

diff --git a/sbin/mount_fusefs/mount_fusefs.c b/sbin/mount_fusefs/mount_fusefs.c
--- a/sbin/mount_fusefs/mount_fusefs.c
+++ b/sbin/mount_fusefs/mount_fusefs.c
@@ -38,6 +38,8 @@
#include <sys/uio.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
+#include <sys/event.h>
+#include <sys/user.h>
#include <err.h>
#include <stdio.h>
@@ -112,6 +114,102 @@
};
#define DEFAULT_MOUNT_FLAGS ALTF_PRIVATE
+#define AUTO_UNMOUNT_OPTION 128
+
+static int
+resolve_pid(pid_t pid, struct kinfo_proc *out)
+{
+ int mib[4];
+ size_t size = sizeof(struct kinfo_proc);
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = pid;
+ return sysctl(mib, 4, out, &size, NULL, 0);
+}
+
+static int
+auto_unmount_main(const char *mountpoint, const char *args)
+{
+ pid_t parent_pid;
+ struct timeval parent_start;
+ fsid_t fsid;
+ int parsed;
+ struct kinfo_proc proc_info;
+ struct statfs stat_buf;
+ int kq;
+ struct kevent kev;
+
+ /* the caller should pass the following info for auto unmount to work:
+ * parent PID to monitor
+ * parent PID's starting time to avoid races
+ * fsid values to be sure we're unmounting the right FS
+ */
+ parsed = sscanf(args, "%d,%ld,%ld,%d,%d", &parent_pid,
+ &parent_start.tv_sec, &parent_start.tv_usec,
+ &fsid.val[0], &fsid.val[1]);
+ if (parsed != 5) {
+ warnx("fail to parse auto-unmount args");
+ return 1;
+ }
+
+ kq = kqueue();
+ if (kq == -1) {
+ warn("fail to create kqueue");
+ return 1;
+ }
+
+ EV_SET(&kev, parent_pid, EVFILT_PROC, EV_ADD | EV_ENABLE, NOTE_EXIT,
+ 0, NULL);
+ if (kevent(kq, &kev, 1, NULL, 0, NULL) == -1) {
+ warn("fail to setup process monitor");
+ return 1;
+ }
+
+ /* if the process is already gone, unmount right now */
+ if (resolve_pid(parent_pid, &proc_info) != 0)
+ goto unmount;
+
+ /* it might be a different process with the same PID */
+ if (proc_info.ki_start.tv_sec != parent_start.tv_sec ||
+ proc_info.ki_start.tv_usec != parent_start.tv_usec)
+ goto unmount;
+
+ /* wait for the parent process to die */
+ if (kevent(kq, NULL, 0, &kev, 1, NULL) == -1) {
+ warn("failure while waiting for process to die");
+ return 1;
+ }
+ if ((kev.fflags & NOTE_EXIT) == 0) {
+ warnx("unknown event while waiting for process to die");
+ return 1;
+ }
+
+unmount:
+ close(kq);
+
+ if (statfs(mountpoint, &stat_buf) != 0) {
+ warn("fail to statfs the mountpoint");
+ return 1;
+ }
+ /*
+ * do not unmount if fsids differ - otherwise we'll unmount
+ * someone's else FS
+ */
+ if (stat_buf.f_fsid.val[0] != fsid.val[0] ||
+ stat_buf.f_fsid.val[1] != fsid.val[1])
+ return 1;
+ /* refuse to unmount anything other than fuse */
+ if (strncmp(stat_buf.f_fstypename, "fusefs", 6))
+ return 1;
+ /* for usermount case we should only unmount FSs mounted by the same user */
+ if (stat_buf.f_owner != proc_info.ki_ruid)
+ return 1;
+
+ unmount(mountpoint, 0);
+ return 0;
+}
int
main(int argc, char *argv[])
@@ -136,12 +234,14 @@
{"mountpath", required_argument, NULL, 'm'},
{"version", no_argument, NULL, 'V'},
{"help", no_argument, NULL, 'h'},
+ {"auto-unmount", required_argument, NULL, AUTO_UNMOUNT_OPTION},
{0,0,0,0}
};
- int pid = 0;
+ pid_t pid = 0;
int fd = -1, fdx;
char *ep;
char *daemon_str = NULL, *daemon_opts = NULL;
+ char *auto_unmount_args = NULL;
/*
* We want a parsing routine which is not sensitive to
@@ -238,6 +338,11 @@
case 'V':
showversion();
break;
+ case AUTO_UNMOUNT_OPTION:
+ if (auto_unmount_args)
+ errx(1, "auto-unmount args specified inconsistently");
+ auto_unmount_args = optarg;
+ break;
case '\0':
break;
case '?':
@@ -277,6 +382,9 @@
if (! (dev && dir))
errx(1, "missing special and/or mountpoint");
+ if (auto_unmount_args)
+ return (auto_unmount_main(dir, auto_unmount_args));
+
for (mo = mopts; mo->m_flag; ++mo) {
if (altflags & mo->m_flag) {
int iov_done = 0;

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 4, 1:14 PM (17 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29244012
Default Alt Text
D51549.id163336.diff (3 KB)

Event Timeline