Source-Changes-HG archive

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

[src/trunk]: src/sys/fs/msdosfs Change msdosfs from hashlist to vcache:



details:   https://anonhg.NetBSD.org/src/rev/7456524a92b9
branches:  trunk
changeset: 330419:7456524a92b9
user:      hannken <hannken%NetBSD.org@localhost>
date:      Tue Jul 08 09:21:52 2014 +0000

description:
Change msdosfs from hashlist to vcache:
- Use (dir_cluster, dir_offset, dir_generation) as key, where
  dir_generation is non-zero and unique for unlinked but open nodes.
- Change deget() to return a vnode as it is unsafe to return a
  referenced but unlocked denode.

diffstat:

 sys/fs/msdosfs/denode.h         |   19 +-
 sys/fs/msdosfs/msdosfs_denode.c |  288 ++++++++++-----------------------------
 sys/fs/msdosfs/msdosfs_lookup.c |  103 ++++++-------
 sys/fs/msdosfs/msdosfs_vfsops.c |   35 ++-
 sys/fs/msdosfs/msdosfs_vnops.c  |   21 +-
 sys/fs/msdosfs/msdosfsmount.h   |    6 +-
 6 files changed, 180 insertions(+), 292 deletions(-)

diffs (truncated from 849 to 300 lines):

diff -r c700a490f947 -r 7456524a92b9 sys/fs/msdosfs/denode.h
--- a/sys/fs/msdosfs/denode.h   Tue Jul 08 09:08:05 2014 +0000
+++ b/sys/fs/msdosfs/denode.h   Tue Jul 08 09:21:52 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: denode.h,v 1.23 2013/01/26 19:45:02 christos Exp $     */
+/*     $NetBSD: denode.h,v 1.24 2014/07/08 09:21:52 hannken Exp $      */
 
 /*-
  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -153,15 +153,21 @@
  * This is the in memory variant of a dos directory entry.  It is usually
  * contained within a vnode.
  */
+struct denode_key {
+       u_long dk_dirclust;     /* cluster of the directory file containing this entry */
+       u_long dk_diroffset;    /* offset of this entry in the directory cluster */
+       void *dk_dirgen;        /* non zero and unique for unlinked nodes */
+};
 struct denode {
        struct genfs_node de_gnode;
-       LIST_ENTRY(denode) de_hash;
        struct vnode *de_vnode; /* addr of vnode we are part of */
        struct vnode *de_devvp; /* vnode of blk dev we live on */
        u_long de_flag;         /* flag bits */
        dev_t de_dev;           /* device where direntry lives */
-       u_long de_dirclust;     /* cluster of the directory file containing this entry */
-       u_long de_diroffset;    /* offset of this entry in the directory cluster */
+       struct denode_key de_key;
+#define de_dirclust de_key.dk_dirclust
+#define de_diroffset de_key.dk_diroffset
+#define de_dirgen de_key.dk_dirgen
        u_long de_fndoffset;    /* offset of found dir entry */
        int de_fndcnt;          /* number of slots before de_fndoffset */
        long de_refcnt;         /* reference count */
@@ -303,7 +309,11 @@
 int createde(struct denode *, struct denode *,
                struct denode **, struct componentname *);
 int deextend(struct denode *, u_long, struct kauth_cred *);
+#ifdef MAKEFS
 int deget(struct msdosfsmount *, u_long, u_long, struct denode **);
+#else
+int deget(struct msdosfsmount *, u_long, u_long, struct vnode **);
+#endif
 int detrunc(struct denode *, u_long, int, struct kauth_cred *);
 int deupdat(struct denode *, int);
 int doscheckpath(struct denode *, struct denode *);
@@ -311,7 +321,6 @@
 int readde(struct denode *, struct buf **, struct direntry **);
 int readep(struct msdosfsmount *, u_long, u_long,
                struct buf **, struct direntry **);
-void reinsert(struct denode *);
 int removede(struct denode *, struct denode *);
 int uniqdosname(struct denode *, struct componentname *, u_char *);
 int findwin95(struct denode *);
diff -r c700a490f947 -r 7456524a92b9 sys/fs/msdosfs/msdosfs_denode.c
--- a/sys/fs/msdosfs/msdosfs_denode.c   Tue Jul 08 09:08:05 2014 +0000
+++ b/sys/fs/msdosfs/msdosfs_denode.c   Tue Jul 08 09:21:52 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: msdosfs_denode.c,v 1.49 2014/05/30 08:42:35 hannken Exp $      */
+/*     $NetBSD: msdosfs_denode.c,v 1.50 2014/07/08 09:21:52 hannken Exp $      */
 
 /*-
  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: msdosfs_denode.c,v 1.49 2014/05/30 08:42:35 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: msdosfs_denode.c,v 1.50 2014/07/08 09:21:52 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -72,14 +72,6 @@
 #include <fs/msdosfs/denode.h>
 #include <fs/msdosfs/fat.h>
 
-LIST_HEAD(ihashhead, denode) *dehashtbl;
-u_long dehash;                 /* size of hash table - 1 */
-#define        DEHASH(dev, dcl, doff) \
-    (((dev) + (dcl) + (doff) / sizeof(struct direntry)) & dehash)
-
-kmutex_t msdosfs_ihash_lock;
-kmutex_t msdosfs_hashlock;
-
 struct pool msdosfs_denode_pool;
 
 extern int prtactive;
@@ -138,10 +130,6 @@
        .gop_markupdate = msdosfs_gop_markupdate,
 };
 
-static struct denode *msdosfs_hashget(dev_t, u_long, u_long, int);
-static void msdosfs_hashins(struct denode *);
-static void msdosfs_hashrem(struct denode *);
-
 MALLOC_DECLARE(M_MSDOSFSFAT);
 
 void
@@ -155,112 +143,33 @@
            "msdosnopl", &pool_allocator_nointr, IPL_NONE);
        pool_init(&fh_pool, sizeof(struct fh_node), 0, 0, 0,
            "msdosfhpl", &pool_allocator_nointr, IPL_NONE);
-       dehashtbl = hashinit(desiredvnodes / 2, HASH_LIST, true, &dehash);
        rb_tree_init(&fh_rbtree, &fh_rbtree_ops);
-       mutex_init(&msdosfs_ihash_lock, MUTEX_DEFAULT, IPL_NONE);
        mutex_init(&fh_lock, MUTEX_DEFAULT, IPL_NONE);
-       mutex_init(&msdosfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
 }
 
 /*
- * Reinitialize inode hash table.
+ * Reinitialize.
  */
 
 void
 msdosfs_reinit(void)
 {
-       struct denode *dep;
-       struct ihashhead *oldhash, *hash;
-       u_long oldmask, mask, val;
-       int i;
 
-       hash = hashinit(desiredvnodes / 2, HASH_LIST, true, &mask);
-
-       mutex_enter(&msdosfs_ihash_lock);
-       oldhash = dehashtbl;
-       oldmask = dehash;
-       dehashtbl = hash;
-       dehash = mask;
-       for (i = 0; i <= oldmask; i++) {
-               while ((dep = LIST_FIRST(&oldhash[i])) != NULL) {
-                       LIST_REMOVE(dep, de_hash);
-                       val = DEHASH(dep->de_dev, dep->de_dirclust,
-                           dep->de_diroffset);
-                       LIST_INSERT_HEAD(&hash[val], dep, de_hash);
-               }
-       }
-       mutex_exit(&msdosfs_ihash_lock);
-       hashdone(oldhash, HASH_LIST, oldmask);
 }
 
 void
 msdosfs_done(void)
 {
-       hashdone(dehashtbl, HASH_LIST, dehash);
        pool_destroy(&msdosfs_denode_pool);
        pool_destroy(&fh_pool);
-       mutex_destroy(&msdosfs_ihash_lock);
        mutex_destroy(&fh_lock);
-       mutex_destroy(&msdosfs_hashlock);
        malloc_type_detach(M_MSDOSFSTMP);
        malloc_type_detach(M_MSDOSFSFAT);
        malloc_type_detach(M_MSDOSFSMNT);
 }
 
-static struct denode *
-msdosfs_hashget(dev_t dev, u_long dirclust, u_long diroff, int flags)
-{
-       struct denode *dep;
-       struct vnode *vp;
-
-loop:
-       mutex_enter(&msdosfs_ihash_lock);
-       LIST_FOREACH(dep, &dehashtbl[DEHASH(dev, dirclust, diroff)], de_hash) {
-               if (dirclust == dep->de_dirclust &&
-                   diroff == dep->de_diroffset &&
-                   dev == dep->de_dev &&
-                   dep->de_refcnt != 0) {
-                       vp = DETOV(dep);
-                       if (flags == 0) {
-                               mutex_exit(&msdosfs_ihash_lock);
-                       } else {
-                               mutex_enter(vp->v_interlock);
-                               mutex_exit(&msdosfs_ihash_lock);
-                               if (vget(vp, flags))
-                                       goto loop;
-                       }
-                       return (dep);
-               }
-       }
-       mutex_exit(&msdosfs_ihash_lock);
-       return (NULL);
-}
-
-static void
-msdosfs_hashins(struct denode *dep)
-{
-       struct ihashhead *depp;
-       int val;
-
-       KASSERT(mutex_owned(&msdosfs_hashlock));
-
-       mutex_enter(&msdosfs_ihash_lock);
-       val = DEHASH(dep->de_dev, dep->de_dirclust, dep->de_diroffset);
-       depp = &dehashtbl[val];
-       LIST_INSERT_HEAD(depp, dep, de_hash);
-       mutex_exit(&msdosfs_ihash_lock);
-}
-
-static void
-msdosfs_hashrem(struct denode *dep)
-{
-       mutex_enter(&msdosfs_ihash_lock);
-       LIST_REMOVE(dep, de_hash);
-       mutex_exit(&msdosfs_ihash_lock);
-}
-
 /*
- * If deget() succeeds it returns with the gotten denode locked().
+ * If deget() succeeds it returns with the gotten denode unlocked.
  *
  * pmp      - address of msdosfsmount structure of the filesystem containing
  *            the denode of interest.  The pm_dev field and the address of
@@ -269,26 +178,18 @@
  *            diroffset is relative to the beginning of the root directory,
  *            otherwise it is cluster relative.
  * diroffset - offset past begin of cluster of denode we want
- * depp             - returns the address of the gotten denode.
+ * vpp      - returns the address of the gotten vnode.
  */
 int
-deget(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset, struct denode **depp)
+deget(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset,
+    struct vnode **vpp)
        /* pmp:  so we know the maj/min number */
        /* dirclust:             cluster this dir entry came from */
        /* diroffset:            index of entry within the cluster */
-       /* depp:                 returns the addr of the gotten denode */
+       /* vpp:                  returns the addr of the gotten vnode */
 {
        int error;
-       extern int (**msdosfs_vnodeop_p)(void *);
-       struct direntry *direntptr;
-       struct denode *ldep;
-       struct vnode *nvp;
-       struct buf *bp;
-
-#ifdef MSDOSFS_DEBUG
-       printf("deget(pmp %p, dirclust %lu, diroffset %lx, depp %p)\n",
-           pmp, dirclust, diroffset, depp);
-#endif
+       struct denode_key key;
 
        /*
         * On FAT32 filesystems, root is a (more or less) normal
@@ -297,78 +198,59 @@
        if (FAT32(pmp) && dirclust == MSDOSFSROOT)
                dirclust = pmp->pm_rootdirblk;
 
-       /*
-        * See if the denode is in the denode cache. Use the location of
-        * the directory entry to compute the hash value. For subdir use
-        * address of "." entry. For root dir (if not FAT32) use cluster
-        * MSDOSFSROOT, offset MSDOSFSROOT_OFS
-        *
-        * NOTE: The check for de_refcnt > 0 below insures the denode being
-        * examined does not represent an unlinked but still open file.
-        * These files are not to be accessible even when the directory
-        * entry that represented the file happens to be reused while the
-        * deleted file is still open.
-        */
- retry:
-       ldep = msdosfs_hashget(pmp->pm_dev, dirclust, diroffset, LK_EXCLUSIVE);
-       if (ldep) {
-               *depp = ldep;
-               return (0);
-       }
+       memset(&key, 0, sizeof(key));
+       key.dk_dirclust = dirclust;
+       key.dk_diroffset = diroffset;
+       /* key.dk_dirgen = NULL; */
+
+       error = vcache_get(pmp->pm_mountp, &key, sizeof(key), vpp);
+       return error;
+}
+
+int
+msdosfs_loadvnode(struct mount *mp, struct vnode *vp,
+    const void *key, size_t key_len, const void **new_key)
+{
+       bool is_root;
+       int error;
+       extern int (**msdosfs_vnodeop_p)(void *);
+       struct msdosfsmount *pmp;
+       struct direntry *direntptr;
+       struct denode *ldep;
+       struct buf *bp;
+       struct denode_key dkey;
 
-       /*
-        * Directory entry was not in cache, have to create a vnode and
-        * copy it from the passed disk buffer.
-        */
-       error = getnewvnode(VT_MSDOSFS, pmp->pm_mountp, msdosfs_vnodeop_p,
-           NULL, &nvp);
-       if (error) {
-               *depp = 0;
-               return (error);
-       }
-       ldep = pool_get(&msdosfs_denode_pool, PR_WAITOK);



Home | Main Index | Thread Index | Old Index