Source-Changes-HG archive

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

[src/trunk]: src/sys/miscfs/fdesc Use a kmutex to protect the hash chains and...



details:   https://anonhg.NetBSD.org/src/rev/d6db1d5b0047
branches:  trunk
changeset: 756394:d6db1d5b0047
user:      hannken <hannken%NetBSD.org@localhost>
date:      Fri Jul 16 10:41:12 2010 +0000

description:
Use a kmutex to protect the hash chains and always take this mutex
before removing a node from the hash chain.

Release the hash list lock before calling getnewvnode() and check the
hash list again like other file systems do.

Take v_interlock before calling vget().

diffstat:

 sys/miscfs/fdesc/fdesc_vnops.c |  64 +++++++++++++++++++++--------------------
 1 files changed, 33 insertions(+), 31 deletions(-)

diffs (130 lines):

diff -r 3e7a47526880 -r d6db1d5b0047 sys/miscfs/fdesc/fdesc_vnops.c
--- a/sys/miscfs/fdesc/fdesc_vnops.c    Fri Jul 16 08:23:28 2010 +0000
+++ b/sys/miscfs/fdesc/fdesc_vnops.c    Fri Jul 16 10:41:12 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fdesc_vnops.c,v 1.110 2010/06/24 13:03:12 hannken Exp $        */
+/*     $NetBSD: fdesc_vnops.c,v 1.111 2010/07/16 10:41:12 hannken Exp $        */
 
 /*
  * Copyright (c) 1992, 1993
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.110 2010/06/24 13:03:12 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.111 2010/07/16 10:41:12 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -69,9 +69,7 @@
 
 #define cttyvp(p) ((p)->p_lflag & PL_CONTROLT ? (p)->p_session->s_ttyvp : NULL)
 
-#define FDL_WANT       0x01
-#define FDL_LOCKED     0x02
-static int fdcache_lock;
+static kmutex_t fdcache_lock;
 
 dev_t devctty;
 
@@ -187,6 +185,7 @@
        /* locate the major number */
        cttymajor = devsw_name2chr("ctty", NULL, 0);
        devctty = makedev(cttymajor, 0);
+       mutex_init(&fdcache_lock, MUTEX_DEFAULT, IPL_NONE);
        fdhashtbl = hashinit(NFDCACHE, HASH_LIST, true, &fdhash);
 }
 
@@ -197,6 +196,7 @@
 fdesc_done(void)
 {
        hashdone(fdhashtbl, HASH_LIST, fdhash);
+       mutex_destroy(&fdcache_lock);
 }
 
 /*
@@ -211,29 +211,36 @@
 
        fc = FD_NHASH(ix);
 loop:
-       for (fd = fc->lh_first; fd != 0; fd = fd->fd_hash.le_next) {
+       mutex_enter(&fdcache_lock);
+       LIST_FOREACH(fd, fc, fd_hash) {
                if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
-                       if (vget(fd->fd_vnode, LK_EXCLUSIVE))
+                       mutex_enter(&fd->fd_vnode->v_interlock);
+                       mutex_exit(&fdcache_lock);
+                       if (vget(fd->fd_vnode, LK_INTERLOCK | LK_EXCLUSIVE))
                                goto loop;
                        *vpp = fd->fd_vnode;
-                       return (error);
+                       return 0;
+               }
+       }
+       mutex_exit(&fdcache_lock);
+
+       error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp);
+       if (error)
+               return error;
+
+       mutex_enter(&fdcache_lock);
+       LIST_FOREACH(fd, fc, fd_hash) {
+               if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
+                       /*
+                        * Another thread beat us, push back freshly
+                        * allocated vnode and retry.
+                        */
+                       mutex_exit(&fdcache_lock);
+                       ungetnewvnode(*vpp);
+                       goto loop;
                }
        }
 
-       /*
-        * otherwise lock the array while we call getnewvnode
-        * since that can block.
-        */
-       if (fdcache_lock & FDL_LOCKED) {
-               fdcache_lock |= FDL_WANT;
-               (void) tsleep(&fdcache_lock, PINOD, "fdcache", 0);
-               goto loop;
-       }
-       fdcache_lock |= FDL_LOCKED;
-
-       error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp);
-       if (error)
-               goto out;
        fd = malloc(sizeof(struct fdescnode), M_TEMP, M_WAITOK);
        (*vpp)->v_data = fd;
        fd->fd_vnode = *vpp;
@@ -244,16 +251,9 @@
        uvm_vnp_setsize(*vpp, 0);
        VOP_LOCK(*vpp, LK_EXCLUSIVE);
        LIST_INSERT_HEAD(fc, fd, fd_hash);
-
-out:;
-       fdcache_lock &= ~FDL_LOCKED;
+       mutex_exit(&fdcache_lock);
 
-       if (fdcache_lock & FDL_WANT) {
-               fdcache_lock &= ~FDL_WANT;
-               wakeup(&fdcache_lock);
-       }
-
-       return (error);
+       return 0;
 }
 
 /*
@@ -956,9 +956,11 @@
        struct vnode *vp = ap->a_vp;
        struct fdescnode *fd = VTOFDESC(vp);
 
+       mutex_enter(&fdcache_lock);
        LIST_REMOVE(fd, fd_hash);
        free(vp->v_data, M_TEMP);
        vp->v_data = 0;
+       mutex_exit(&fdcache_lock);
 
        return (0);
 }



Home | Main Index | Thread Index | Old Index