Module Name: src Committed By: hannken Date: Wed Apr 12 10:35:10 UTC 2017
Modified Files: src/sys/kern: vfs_mount.c Log Message: Switch vfs_getvfs(), dounmount() and vfs_mountroot() to mountlist iterator. Add a helper to retrieve a mount with "highest generation < arg" and use it from vfs_unmount_forceone() and vfs_unmountall1(). To generate a diff of this commit: cvs rdiff -u -r1.52 -r1.53 src/sys/kern/vfs_mount.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/vfs_mount.c diff -u src/sys/kern/vfs_mount.c:1.52 src/sys/kern/vfs_mount.c:1.53 --- src/sys/kern/vfs_mount.c:1.52 Tue Apr 11 07:46:37 2017 +++ src/sys/kern/vfs_mount.c Wed Apr 12 10:35:10 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_mount.c,v 1.52 2017/04/11 07:46:37 hannken Exp $ */ +/* $NetBSD: vfs_mount.c,v 1.53 2017/04/12 10:35:10 hannken Exp $ */ /*- * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. @@ -67,7 +67,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.52 2017/04/11 07:46:37 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.53 2017/04/12 10:35:10 hannken Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -234,11 +234,9 @@ vfs_getnewfsid(struct mount *mp) ++xxxfs_mntid; tfsid.__fsid_val[0] = makedev(mtype & 0xff, xxxfs_mntid); tfsid.__fsid_val[1] = mtype; - if (!TAILQ_EMPTY(&mountlist)) { - while (vfs_getvfs(&tfsid)) { - tfsid.__fsid_val[0]++; - xxxfs_mntid++; - } + while (vfs_getvfs(&tfsid)) { + tfsid.__fsid_val[0]++; + xxxfs_mntid++; } mp->mnt_stat.f_fsidx.__fsid_val[0] = tfsid.__fsid_val[0]; mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0]; @@ -253,17 +251,18 @@ vfs_getnewfsid(struct mount *mp) struct mount * vfs_getvfs(fsid_t *fsid) { + mount_iterator_t *iter; struct mount *mp; - mutex_enter(&mountlist_lock); - TAILQ_FOREACH(mp, &mountlist, mnt_list) { + mountlist_iterator_init(&iter); + while ((mp = mountlist_iterator_next(iter)) != NULL) { if (mp->mnt_stat.f_fsidx.__fsid_val[0] == fsid->__fsid_val[0] && mp->mnt_stat.f_fsidx.__fsid_val[1] == fsid->__fsid_val[1]) { - mutex_exit(&mountlist_lock); - return (mp); + mountlist_iterator_destroy(iter); + return mp; } } - mutex_exit(&mountlist_lock); + mountlist_iterator_destroy(iter); return NULL; } @@ -832,6 +831,7 @@ err_unmounted: int dounmount(struct mount *mp, int flags, struct lwp *l) { + mount_iterator_t *iter; struct mount *cmp; vnode_t *coveredvp; int error, async, used_syncer, used_extattr; @@ -845,14 +845,14 @@ dounmount(struct mount *mp, int flags, s /* * No unmount below layered mounts. */ - mutex_enter(&mountlist_lock); - TAILQ_FOREACH(cmp, &mountlist, mnt_list) { + mountlist_iterator_init(&iter); + while ((cmp = mountlist_iterator_next(iter)) != NULL) { if (cmp->mnt_lower == mp) { - mutex_exit(&mountlist_lock); + mountlist_iterator_destroy(iter); return EBUSY; } } - mutex_exit(&mountlist_lock); + mountlist_iterator_destroy(iter); /* * XXX Freeze syncer. Must do this before locking the @@ -983,38 +983,57 @@ vfs_unmount_print(struct mount *mp, cons mp->mnt_stat.f_fstypename); } -bool -vfs_unmount_forceone(struct lwp *l) +/* + * Return the mount with the highest generation less than "gen". + */ +static struct mount * +vfs_unmount_next(uint64_t gen) { + mount_iterator_t *iter; struct mount *mp, *nmp; - int error; nmp = NULL; - TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) { - if (nmp == NULL || mp->mnt_gen > nmp->mnt_gen) { + mountlist_iterator_init(&iter); + while ((mp = mountlist_iterator_next(iter)) != NULL) { + if ((nmp == NULL || mp->mnt_gen > nmp->mnt_gen) && + mp->mnt_gen < gen) { + if (nmp != NULL) + vfs_destroy(nmp); nmp = mp; + atomic_inc_uint(&nmp->mnt_refcnt); } } - if (nmp == NULL) { + mountlist_iterator_destroy(iter); + + return nmp; +} + +bool +vfs_unmount_forceone(struct lwp *l) +{ + struct mount *mp; + int error; + + mp = vfs_unmount_next(mountgen); + if (mp == NULL) { return false; } #ifdef DEBUG printf("forcefully unmounting %s (%s)...\n", - nmp->mnt_stat.f_mntonname, nmp->mnt_stat.f_mntfromname); + mp->mnt_stat.f_mntonname, mp->mnt_stat.f_mntfromname); #endif - atomic_inc_uint(&nmp->mnt_refcnt); - if ((error = dounmount(nmp, MNT_FORCE, l)) == 0) { - vfs_unmount_print(nmp, "forcefully "); + if ((error = dounmount(mp, MNT_FORCE, l)) == 0) { + vfs_unmount_print(mp, "forcefully "); return true; } else { - vfs_destroy(nmp); + vfs_destroy(mp); } #ifdef DEBUG printf("forceful unmount of %s failed with error %d\n", - nmp->mnt_stat.f_mntonname, error); + mp->mnt_stat.f_mntonname, error); #endif return false; @@ -1023,17 +1042,23 @@ vfs_unmount_forceone(struct lwp *l) bool vfs_unmountall1(struct lwp *l, bool force, bool verbose) { - struct mount *mp, *nmp; + struct mount *mp; bool any_error = false, progress = false; + uint64_t gen; int error; - TAILQ_FOREACH_REVERSE_SAFE(mp, &mountlist, mntlist, mnt_list, nmp) { + gen = mountgen; + for (;;) { + mp = vfs_unmount_next(gen); + if (mp == NULL) + break; + gen = mp->mnt_gen; + #ifdef DEBUG printf("unmounting %p %s (%s)...\n", (void *)mp, mp->mnt_stat.f_mntonname, mp->mnt_stat.f_mntfromname); #endif - atomic_inc_uint(&mp->mnt_refcnt); if ((error = dounmount(mp, force ? MNT_FORCE : 0, l)) == 0) { vfs_unmount_print(mp, ""); progress = true; @@ -1229,10 +1254,15 @@ done: vrele(rootvp); } if (error == 0) { + mount_iterator_t *iter; struct mount *mp; extern struct cwdinfo cwdi0; - mp = TAILQ_FIRST(&mountlist); + mountlist_iterator_init(&iter); + mp = mountlist_iterator_next(iter); + KASSERT(mp != NULL); + mountlist_iterator_destroy(iter); + mp->mnt_flag |= MNT_ROOTFS; mp->mnt_op->vfs_refcount++; error = fstrans_mount(mp);