Source-Changes-HG archive

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

[src/trunk]: src/sys/fs/union Change union to vcache. Use address of the uni...



details:   https://anonhg.NetBSD.org/src/rev/36e577976c5a
branches:  trunk
changeset: 806326:36e577976c5a
user:      hannken <hannken%NetBSD.org@localhost>
date:      Mon Feb 16 10:22:00 2015 +0000

description:
Change union to vcache.  Use address of the union node as key.

It would be better to use (uppervp, lowervp) as key, but either
may be NULL and may change any time.

diffstat:

 sys/fs/union/union.h        |    5 +-
 sys/fs/union/union_subr.c   |  225 ++++++++++++++++++++++---------------------
 sys/fs/union/union_vfsops.c |    7 +-
 3 files changed, 120 insertions(+), 117 deletions(-)

diffs (truncated from 384 to 300 lines):

diff -r b3ad6765fab1 -r 36e577976c5a sys/fs/union/union.h
--- a/sys/fs/union/union.h      Mon Feb 16 10:21:25 2015 +0000
+++ b/sys/fs/union/union.h      Mon Feb 16 10:22:00 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: union.h,v 1.27 2015/02/16 10:21:25 hannken Exp $       */
+/*     $NetBSD: union.h,v 1.28 2015/02/16 10:22:00 hannken Exp $       */
 
 /*
  * Copyright (c) 1994 The Regents of the University of California.
@@ -121,6 +121,7 @@
        kmutex_t                un_lock;
        LIST_ENTRY(union_node)  un_cache;       /* c: Hash chain */
        int                     un_refs;        /* c: Reference counter */
+       struct mount            *un_mount;      /* c: union mount */
        struct vnode            *un_vnode;      /* :: Back pointer */
        struct vnode            *un_uppervp;    /* m: overlaying object */
        struct vnode            *un_lowervp;    /* v: underlying object */
@@ -162,6 +163,8 @@
 extern void union_newsize(struct vnode *, off_t, off_t);
 int union_readdirhook(struct vnode **, struct file *, struct lwp *);
 
+VFS_PROTOS(union);
+
 #define        MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data))
 #define        VTOUNION(vp) ((struct union_node *)(vp)->v_data)
 #define        UNIONTOV(un) ((un)->un_vnode)
diff -r b3ad6765fab1 -r 36e577976c5a sys/fs/union/union_subr.c
--- a/sys/fs/union/union_subr.c Mon Feb 16 10:21:25 2015 +0000
+++ b/sys/fs/union/union_subr.c Mon Feb 16 10:22:00 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: union_subr.c,v 1.69 2015/02/16 10:21:25 hannken Exp $  */
+/*     $NetBSD: union_subr.c,v 1.70 2015/02/16 10:22:00 hannken Exp $  */
 
 /*
  * Copyright (c) 1994
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.69 2015/02/16 10:21:25 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.70 2015/02/16 10:22:00 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -344,22 +344,12 @@
  * the reference is either maintained in the new union_node
  * object which is allocated, or they are vrele'd.
  *
- * all union_nodes are maintained on a singly-linked
+ * all union_nodes are maintained on a hash
  * list.  new nodes are only allocated when they cannot
  * be found on this list.  entries on the list are
  * removed when the vfs reclaim entry is called.
  *
- * a single lock is kept for the entire list.  this is
- * needed because the getnewvnode() function can block
- * waiting for a vnode to become free, in which case there
- * may be more than one process trying to get the same
- * vnode.  this lock is only taken if we are going to
- * call getnewvnode, since the kernel itself is single-threaded.
- *
- * if an entry is found on the list, then call vget() to
- * take a reference.  this is done because there may be
- * zero references to it and so it needs to removed from
- * the vnode free list.
+ * the vnode gets attached or referenced with vcache_get().
  */
 int
 union_allocvp(
@@ -373,14 +363,9 @@
        int docache)
 {
        int error;
-       struct vattr va;
        struct union_node *un = NULL, *un1;
        struct vnode *vp, *xlowervp = NULLVP;
-       struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
-       voff_t uppersz, lowersz;
-       dev_t rdev;
        u_long hash[3];
-       int vflag, iflag;
        int try;
        bool is_dotdot;
 
@@ -394,20 +379,6 @@
                lowervp = NULLVP;
        }
 
-       /* detect the root vnode (and aliases) */
-       iflag = VI_LAYER;
-       vflag = 0;
-       if ((uppervp == um->um_uppervp) &&
-           ((lowervp == NULLVP) || lowervp == um->um_lowervp)) {
-               if (lowervp == NULLVP) {
-                       lowervp = um->um_lowervp;
-                       if (lowervp != NULLVP)
-                               vref(lowervp);
-               }
-               iflag = 0;
-               vflag = VV_ROOT;
-       }
-
        if (!docache) {
                un = NULL;
                goto found;
@@ -434,17 +405,18 @@
                LIST_FOREACH(un, &uhashtbl[hash[try]], un_cache) {
                        if ((un->un_lowervp && un->un_lowervp != lowervp) ||
                            (un->un_uppervp && un->un_uppervp != uppervp) ||
-                           UNIONTOV(un)->v_mount != mp)
+                           un->un_mount != mp)
                                continue;
 
-                       vp = UNIONTOV(un);
                        union_ref(un);
-                       mutex_enter(vp->v_interlock);
                        mutex_exit(&uhash_lock);
-                       error = vget(vp, 0);
+                       error = vcache_get(mp, &un, sizeof(un), &vp);
+                       KASSERT(error != 0 || UNIONTOV(un) == vp);
                        union_rele(un);
-                       if (error)
+                       if (error == ENOENT)
                                goto loop;
+                       else if (error)
+                               goto out;
                        goto found;
                }
        }
@@ -492,77 +464,15 @@
                *vpp = UNIONTOV(un);
                if (uppervp != dvp)
                        VOP_UNLOCK(*vpp);
-               return (0);
-       }
-
-       uppersz = lowersz = VNOVAL;
-       if (uppervp != NULLVP) {
-               vn_lock(uppervp, LK_SHARED | LK_RETRY);
-               if (VOP_GETATTR(uppervp, &va, FSCRED) == 0)
-                       uppersz = va.va_size;
-               VOP_UNLOCK(uppervp);
-       }
-       if (lowervp != NULLVP) {
-               vn_lock(lowervp, LK_SHARED | LK_RETRY);
-               if (VOP_GETATTR(lowervp, &va, FSCRED) == 0)
-                       lowersz = va.va_size;
-               VOP_UNLOCK(lowervp);
-       }
-
-       /*
-        * Get a new vnode and share the lock with upper layer vnode,
-        * unless layers are inverted.
-        */
-       vnode_t *svp = (uppervp != NULLVP) ? uppervp : lowervp;
-       error = getnewvnode(VT_UNION, mp, union_vnodeop_p,
-           svp->v_interlock, vpp);
-       if (error) {
-               if (uppervp)
-                       vrele(uppervp);
-               if (lowervp)
-                       vrele(lowervp);
-
-               return error;
+               error = 0;
+               goto out;
        }
 
-       if (docache) {
-               mutex_enter(&uhash_lock);
-               LIST_FOREACH(un1, &uhashtbl[hash[0]], un_cache) {
-                       if (un1->un_lowervp == lowervp &&
-                           un1->un_uppervp == uppervp &&
-                           UNIONTOV(un1)->v_mount == mp) {
-                               /*
-                                * Another thread beat us, push back freshly
-                                * allocated vnode and retry.
-                                */
-                               mutex_exit(&uhash_lock);
-                               ungetnewvnode(*vpp);
-                               goto loop;
-                       }
-               }
-       }
-
-       (*vpp)->v_data = malloc(sizeof(struct union_node), M_TEMP, M_WAITOK);
-
-       (*vpp)->v_vflag |= vflag;
-       (*vpp)->v_iflag |= iflag;
-       rdev = NODEV;
-       if (uppervp) {
-               (*vpp)->v_type = uppervp->v_type;
-               if (uppervp->v_type == VCHR || uppervp->v_type == VBLK)
-                       rdev = uppervp->v_rdev;
-       } else {
-               (*vpp)->v_type = lowervp->v_type;
-               if (lowervp->v_type == VCHR || lowervp->v_type == VBLK)
-                       rdev = lowervp->v_rdev;
-       }
-       if (rdev != NODEV)
-               spec_node_init(*vpp, rdev);
-
-       un = VTOUNION(*vpp);
+       un = malloc(sizeof(struct union_node), M_TEMP, M_WAITOK);
        mutex_init(&un->un_lock, MUTEX_DEFAULT, IPL_NONE);
        un->un_refs = 1;
-       un->un_vnode = *vpp;
+       un->un_mount = mp;
+       un->un_vnode = NULL;
        un->un_uppervp = uppervp;
        un->un_lowervp = lowervp;
        un->un_pvp = undvp;
@@ -572,10 +482,8 @@
        un->un_openl = 0;
        un->un_cflags = 0;
 
-       mutex_enter(&un->un_lock);
        un->un_uppersz = VNOVAL;
        un->un_lowersz = VNOVAL;
-       union_newsize(*vpp, uppersz, lowersz);
 
        if (dvp && cnp && (lowervp != NULLVP)) {
                un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
@@ -589,17 +497,36 @@
        }
 
        if (docache) {
+               mutex_enter(&uhash_lock);
+               LIST_FOREACH(un1, &uhashtbl[hash[0]], un_cache) {
+                       if (un1->un_lowervp == lowervp &&
+                           un1->un_uppervp == uppervp &&
+                           un1->un_mount == mp) {
+                               /*
+                                * Another thread beat us, push back freshly
+                                * allocated node and retry.
+                                */
+                               mutex_exit(&uhash_lock);
+                               union_rele(un);
+                               goto loop;
+                       }
+               }
                LIST_INSERT_HEAD(&uhashtbl[hash[0]], un, un_cache);
                un->un_cflags |= UN_CACHED;
+               mutex_exit(&uhash_lock);
        }
 
+       error = vcache_get(mp, &un, sizeof(un), vpp);
+       KASSERT(error != 0 || UNIONTOV(un) == *vpp);
+       union_rele(un);
+       if (error == ENOENT)
+               goto loop;
+
+out:
        if (xlowervp)
                vrele(xlowervp);
 
-       if (docache)
-               mutex_exit(&uhash_lock);
-
-       return (error);
+       return error;
 }
 
 int
@@ -607,9 +534,83 @@
 {
        struct union_node *un = VTOUNION(vp);
 
+       vcache_remove(vp->v_mount, &un, sizeof(un));
+
+       mutex_enter(vp->v_interlock);
+       vp->v_data = NULL;
+       mutex_exit(vp->v_interlock);
+
        union_rele(un);
 
-       vp->v_data = NULL;
+       return 0;
+}
+
+int
+union_loadvnode(struct mount *mp, struct vnode *vp,
+    const void *key, size_t key_len, const void **new_key)
+{
+       struct vattr va;
+       struct vnode *svp;
+       struct union_node *un;
+       struct union_mount *um;
+       voff_t uppersz, lowersz;
+
+       KASSERT(key_len == sizeof(un));
+       memcpy(&un, key, key_len);
+
+       um = MOUNTTOUNIONMOUNT(mp);
+       svp = (un->un_uppervp != NULLVP) ? un->un_uppervp : un->un_lowervp;
+
+       vp->v_tag = VT_UNION;
+       vp->v_op = union_vnodeop_p;
+       vp->v_data = un;
+       un->un_vnode = vp;



Home | Main Index | Thread Index | Old Index