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 @@ -84,6 +84,8 @@ { "automounted", 0, ALTF_AUTOMOUNTED, 1 }, #define ALTF_INTR 0x200 { "intr", 0, ALTF_INTR, 1 }, + #define ALTF_AUTOUNMOUNT 0x400 + { "auto_unmount", 0, ALTF_AUTOUNMOUNT, 1 }, /* Linux specific options, we silently ignore them */ { "fd=", 0, 0x00, 1 }, { "rootmode=", 0, 0x00, 1 }, diff --git a/sys/fs/fuse/fuse_device.c b/sys/fs/fuse/fuse_device.c --- a/sys/fs/fuse/fuse_device.c +++ b/sys/fs/fuse/fuse_device.c @@ -65,7 +65,6 @@ #include #include #include -#include #include #include #include @@ -104,6 +103,7 @@ static d_kqfilter_t fuse_device_filter; static d_open_t fuse_device_open; +static d_close_t fuse_device_close; static d_poll_t fuse_device_poll; static d_read_t fuse_device_read; static d_write_t fuse_device_write; @@ -111,6 +111,7 @@ static struct cdevsw fuse_device_cdevsw = { .d_kqfilter = fuse_device_filter, .d_open = fuse_device_open, + .d_close = fuse_device_close, .d_name = "fuse", .d_poll = fuse_device_poll, .d_read = fuse_device_read, @@ -269,6 +270,31 @@ return (error); } +static int +fuse_device_close(struct cdev *dev, int fflag, int devtype, struct thread *td) +{ + struct fuse_data *data; + struct mount *mp; + int err; +printf("=======> begin\n"); + err = devfs_get_cdevpriv((void **)&data); + if (err != 0) + return (err); + + if (!(data->dataflags & FSESS_AUTO_UNMOUNT)) + return (0); + + if (fdata_get_dead(data)) + return (0); + + mp = data->mp; + + printf("=======> before\n"); + err = VFS_UNMOUNT(mp, MNT_FORCE); + printf("=======> after %d\n", err); + return (err); +} + int fuse_device_poll(struct cdev *dev, int events, struct thread *td) { diff --git a/sys/fs/fuse/fuse_ipc.h b/sys/fs/fuse/fuse_ipc.h --- a/sys/fs/fuse/fuse_ipc.h +++ b/sys/fs/fuse/fuse_ipc.h @@ -240,9 +240,10 @@ #define FSESS_WARN_READLINK_EMBEDDED_NUL 0x1000000 /* corrupt READLINK output */ #define FSESS_WARN_DOT_LOOKUP 0x2000000 /* Inconsistent . LOOKUP response */ #define FSESS_WARN_INODE_MISMATCH 0x4000000 /* ino != nodeid */ +#define FSESS_AUTO_UNMOUNT 0x8000000 /* perform unmount when server dies */ #define FSESS_MNTOPTS_MASK ( \ FSESS_DAEMON_CAN_SPY | FSESS_PUSH_SYMLINKS_IN | \ - FSESS_DEFAULT_PERMISSIONS | FSESS_INTR) + FSESS_DEFAULT_PERMISSIONS | FSESS_INTR | FSESS_AUTO_UNMOUNT) extern int fuse_data_cache_mode; diff --git a/sys/fs/fuse/fuse_vfsops.c b/sys/fs/fuse/fuse_vfsops.c --- a/sys/fs/fuse/fuse_vfsops.c +++ b/sys/fs/fuse/fuse_vfsops.c @@ -337,6 +337,7 @@ FUSE_FLAGOPT(push_symlinks_in, FSESS_PUSH_SYMLINKS_IN); FUSE_FLAGOPT(default_permissions, FSESS_DEFAULT_PERMISSIONS); FUSE_FLAGOPT(intr, FSESS_INTR); + FUSE_FLAGOPT(auto_unmount, FSESS_AUTO_UNMOUNT); (void)vfs_scanopt(opts, "max_read=", "%u", &max_read); (void)vfs_scanopt(opts, "linux_errnos", "%d", &linux_errnos); @@ -416,6 +417,9 @@ FUSE_UNLOCK(); goto out; } + if (mntopts & FSESS_AUTO_UNMOUNT) { + mp->mnt_flag |= MNT_NOCOVER; + } data->ref++; data->mp = mp; data->dataflags |= mntopts;