Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern Switch vfs_getvfs(), dounmount() and vfs_mountroot(...



details:   https://anonhg.NetBSD.org/src/rev/285d2994ccd2
branches:  trunk
changeset: 352847:285d2994ccd2
user:      hannken <hannken%NetBSD.org@localhost>
date:      Wed Apr 12 10:35:10 2017 +0000

description:
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().

diffstat:

 sys/kern/vfs_mount.c |  100 +++++++++++++++++++++++++++++++++-----------------
 1 files changed, 65 insertions(+), 35 deletions(-)

diffs (201 lines):

diff -r 3b9e62d07116 -r 285d2994ccd2 sys/kern/vfs_mount.c
--- a/sys/kern/vfs_mount.c      Wed Apr 12 10:30:02 2017 +0000
+++ b/sys/kern/vfs_mount.c      Wed Apr 12 10:35:10 2017 +0000
@@ -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 @@
                ++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 @@
 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 @@
 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 @@
        /*
         * 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 @@
            mp->mnt_stat.f_fstypename);
 }
 
+/*
+ * 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;
+
+       nmp = NULL;
+
+       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);
+               }
+       }
+       mountlist_iterator_destroy(iter);
+
+       return nmp;
+}
+
 bool
 vfs_unmount_forceone(struct lwp *l)
 {
-       struct mount *mp, *nmp;
+       struct mount *mp;
        int error;
 
-       nmp = NULL;
-
-       TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
-               if (nmp == NULL || mp->mnt_gen > nmp->mnt_gen) {
-                       nmp = mp;
-               }
-       }
-       if (nmp == NULL) {
+       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 @@
 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 @@
                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);



Home | Main Index | Thread Index | Old Index