diff options
Diffstat (limited to 'sys/fs/devfs/devfs_vfsops.c')
-rw-r--r-- | sys/fs/devfs/devfs_vfsops.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/sys/fs/devfs/devfs_vfsops.c b/sys/fs/devfs/devfs_vfsops.c index 17db07a..8c1069a 100644 --- a/sys/fs/devfs/devfs_vfsops.c +++ b/sys/fs/devfs/devfs_vfsops.c @@ -77,6 +77,7 @@ devfs_mount(struct mount *mp, struct thread *td) fmp = malloc(sizeof *fmp, M_DEVFS, M_WAITOK | M_ZERO); fmp->dm_idx = alloc_unr(devfs_unr); sx_init(&fmp->dm_lock, "devfsmount"); + fmp->dm_holdcnt = 1; mp->mnt_flag |= MNT_LOCAL; mp->mnt_kern_flag |= MNTK_MPSAFE; @@ -104,14 +105,25 @@ devfs_mount(struct mount *mp, struct thread *td) return (0); } +void +devfs_unmount_final(struct devfs_mount *fmp) +{ + sx_destroy(&fmp->dm_lock); + free(fmp, M_DEVFS); +} + static int devfs_unmount(struct mount *mp, int mntflags, struct thread *td) { int error; int flags = 0; struct devfs_mount *fmp; + int hold; + u_int idx; fmp = VFSTODEVFS(mp); + KASSERT(fmp->dm_mount != NULL, + ("devfs_unmount unmounted devfs_mount")); /* There is 1 extra root vnode reference from devfs_mount(). */ error = vflush(mp, 1, flags, td); if (error) @@ -119,11 +131,14 @@ devfs_unmount(struct mount *mp, int mntflags, struct thread *td) sx_xlock(&fmp->dm_lock); devfs_cleanup(fmp); devfs_rules_cleanup(fmp); - sx_xunlock(&fmp->dm_lock); + fmp->dm_mount = NULL; + hold = --fmp->dm_holdcnt; mp->mnt_data = NULL; - sx_destroy(&fmp->dm_lock); - free_unr(devfs_unr, fmp->dm_idx); - free(fmp, M_DEVFS); + idx = fmp->dm_idx; + sx_xunlock(&fmp->dm_lock); + free_unr(devfs_unr, idx); + if (hold == 0) + devfs_unmount_final(fmp); return 0; } @@ -137,6 +152,7 @@ devfs_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td) struct devfs_mount *dmp; dmp = VFSTODEVFS(mp); + sx_xlock(&dmp->dm_lock); error = devfs_allocv(dmp->dm_rootdir, mp, &vp, td); if (error) return (error); |