Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 13 Jun 2011 15:33:42 GMT
From:      Ilya Putsikau <ilya@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 194682 for review
Message-ID:  <201106131533.p5DFXgkM074432@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@194682?ac=10

Change 194682 by ilya@ilya_triton2011 on 2011/06/13 15:33:26

	Restore vfs_hash and original node creations on FreeBSD

Affected files ...

.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.c#2 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.h#4 edit

Differences ...

==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.c#2 (text+ko) ====

@@ -3,173 +3,165 @@
  * Amit Singh <singh@>
  */
 
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/lock.h>
+#include <sys/sx.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/namei.h>
+#include <sys/mount.h>
+#include <sys/sysctl.h>
+#include <sys/fcntl.h>
+#include <sys/fnv_hash.h>
+
 #include "fuse.h"
+#include "fuse_node.h"
+#include "fuse_internal.h"
 #include "fuse_ipc.h"
-#include "fuse_locking.h"
-#include "fuse_node.h"
+
+#include <sys/priv.h>
+#include <security/mac/mac_framework.h>
+
+static void
+fuse_vnode_init(struct vnode *vp, struct fuse_vnode_data *fvdat,
+    uint64_t nodeid, enum vtype vtyp)
+{
+    fvdat->nid = nodeid;
+    if (nodeid == FUSE_ROOT_ID) {
+        vp->v_vflag |= VV_ROOT;
+    }
+    vp->v_type = vtyp;
+    vp->v_data = fvdat;
+    mtx_init(&fvdat->createlock, "fuse node create mutex", NULL, MTX_DEF);
+    sx_init(&fvdat->nodelock, "fuse node sx lock");
+    sx_init(&fvdat->truncatelock, "fuse node truncate sx lock");
+}
 
 void
-FSNodeScrub(struct fuse_vnode_data *fvdat)
+fuse_vnode_destroy(struct vnode *vp)
 {
-    lck_mtx_destroy(fvdat->createlock, fuse_lock_group);
-    lck_rw_destroy(fvdat->nodelock, fuse_lock_group);
-    lck_rw_destroy(fvdat->truncatelock, fuse_lock_group);
-    fvdat->fMagic = kFSNodeBadMagic;
-}       
+    struct fuse_vnode_data *fvdat = vp->v_data;
+
+    vp->v_data = NULL;
+    mtx_destroy(&fvdat->createlock);
+    sx_destroy(&fvdat->nodelock);
+    sx_destroy(&fvdat->truncatelock);
+    free(fvdat, M_FUSEVN);
+}
 
-errno_t
-FSNodeGetOrCreateFileVNodeByID(mount_t    mp,
-                               uint64_t   nodeid,
-                               vnode_t    dvp,
-                               enum vtype vtyp,
-                               uint64_t   insize,
-                               vnode_t   *vnPtr,
-                               int        flags)
+static int
+fuse_vnode_cmp(struct vnode *vp, void *nidp)
 {
-    int      err;
-    int      junk;
-    vnode_t  vn;
-    HNodeRef hn;
-    vnode_t  dirVN;
-    dev_t    dummy_device;
-    struct fuse_vnode_data *fvdat = NULL;
-    struct fuse_data *mntdata;
-    int markroot = FALSE;
-    uint64_t size = 0;
+    return (VTOI(vp) != *((uint64_t *)nidp));
+}
 
-    if (insize == 0xffffffff) {
-        markroot = TRUE;
-    } else {
-        size = insize;
-    }
+static uint32_t __inline
+fuse_vnode_hash(uint64_t id)
+{
+    return (fnv_32_buf(&id, sizeof(id), FNV1_32_INIT));
+}
 
-    hn = NULL;
-    vn = NULL;
-    dirVN = NULL;
+static int
+fuse_vnode_alloc(struct mount *mp,
+            struct thread *td,
+            uint64_t nodeid,
+            enum vtype vtyp,
+	    int lkflags,
+            struct vnode **vpp)
+{
+    struct fuse_vnode_data *fvdat;
+    struct vnode *vp2;
+    int err = 0;
 
-    mntdata = vfs_fsprivate(mp);
-    dummy_device = (dev_t)mntdata->fdev;
+    DEBUG("been asked for vno #%ju\n", (uintmax_t)nodeid);
 
-    err = HNodeLookupCreatingIfNecessary(dummy_device,
-                                         (ino_t)nodeid, // XXXXXXXX
-                                         0 /* fork index */,
-                                         &hn,
-                                         &vn);
-    if ((err == 0) && (vn == NULL)) {
+    if (vtyp == VNON) {
+        return EINVAL;
+    }
 
-        struct vnode_fsparam params;
-        fvdat = (struct fuse_vnode_data *)FSNodeGenericFromHNode(hn);
-        if (!fvdat->fInitialised) {
-            int k;
-            fvdat->fMagic = kFSNodeMagic;
-            fvdat->fInitialised = TRUE;
-            fvdat->nid = nodeid;
-            fvdat->vtype = vtyp;
-            fvdat->parent = NULL;
-            fvdat->filesize = size;
-            fvdat->newfilesize = 0;
-            fvdat->nlookup = 0;
-            if (dvp) {
-                fvdat->parent_nid = VTOFUD(dvp)->nid;
-            } else {
-                fvdat->parent_nid = 0;
-            }
-            for (k = 0; k < FUFH_MAXTYPE; k++) {
-                fvdat->fufh[k].fufh_flags = 0;
-            }
-            fvdat->createlock = lck_mtx_alloc_init(fuse_lock_group, fuse_lock_attr);
-            fvdat->nodelock = lck_rw_alloc_init(fuse_lock_group, fuse_lock_attr);
-            fvdat->truncatelock = lck_rw_alloc_init(fuse_lock_group, fuse_lock_attr);
-            fvdat->creator = current_thread();
-            fvdat->flag = flags;
-            //LIST_INIT(&fvdat->fh_head);
-        }
+    *vpp = NULL;
+    err = vfs_hash_get(mp, fuse_vnode_hash(nodeid), lkflags, td, vpp,
+        fuse_vnode_cmp, &nodeid);
+    if (err)
+        return (err);
 
-        if (err == 0) {
-            params.vnfs_mp         = mp;
-            params.vnfs_vtype      = vtyp;
-            params.vnfs_str        = NULL;
-            params.vnfs_dvp        = NULL; // dvp; XXXXXXXXXXXXXXXXXXXXXXXXXX
-            params.vnfs_fsnode     = hn;
-            params.vnfs_vops       = fuse_vnode_operations;
-            params.vnfs_marksystem = FALSE;
-            params.vnfs_rdev       = 0;
-            params.vnfs_cnp        = NULL;
-            params.vnfs_flags      = VNFS_NOCACHE | VNFS_CANTCACHE;
-            params.vnfs_filesize   = size;
-            params.vnfs_markroot   = markroot;
+    if (*vpp) {
+        MPASS((*vpp)->v_type == vtyp && (*vpp)->v_data != NULL);
+        DEBUG("vnode taken from hash\n");
+        return (0);
+    }
 
-            err = vnode_create(VNCREATE_FLAVOR, sizeof(params), &params, &vn);
-        }
+    lkflags = LK_EXCLUSIVE | LK_RETRY; /* XXXIP don't loose other flags */
 
-        if (err == 0) {
-            HNodeAttachVNodeSucceeded(hn, 0 /* forkIndex */, vn);
-            if (markroot == TRUE) {
-                fvdat->parent = vn;
-            }
-        } else {
-            if (HNodeAttachVNodeFailed(hn, 0 /* forkIndex */)) {
-                FSNodeScrub(fvdat);
-                HNodeScrubDone(hn);
-            }
-        }
+    fvdat = malloc(sizeof(*fvdat), M_FUSEVN, M_WAITOK | M_ZERO);
+    err = getnewvnode("fuse", mp, &fuse_vnops, vpp);
+    if (err) {
+        free(fvdat, M_FUSEVN);
+        return (err);
     }
 
-    if (err == 0) {
-        *vnPtr = vn;
-        vnode_settag(vn, VT_KERNFS);
+    vn_lock(*vpp, lkflags);
+    err = insmntque(*vpp, mp);
+    if (err) {
+        free(fvdat, M_FUSEVN);
+        return (err);
     }
 
-    if (dirVN != NULL) {
-        junk = vnode_put(dirVN);
-        /* assert(junk == 0); */
+    fuse_vnode_init(*vpp, fvdat, nodeid, vtyp);
+    err = vfs_hash_insert(*vpp, fuse_vnode_hash(nodeid), lkflags,
+        td, &vp2, fuse_vnode_cmp, &nodeid);
+
+    if (err) {
+        fuse_vnode_destroy(*vpp);
+	*vpp = NULL;
+        return (err);
     }
 
-    /* assert((err == 0) == (*vnPtr != NULL); */
+    /*
+     * XXXIP: Prevent silent vnode reuse. It may happen because several fuse
+     * filesystems ignore inode numbers
+     */
+    KASSERT(vp2 == NULL,
+        ("vfs hash collision for node #%ju\n", (uintmax_t)nodeid));
 
-    return err;
+    return (0);
 }
 
 int
-fuse_vget_i(mount_t               mp,
-            uint64_t              nodeid,
-            vfs_context_t         context,
-            vnode_t               dvp,
-            vnode_t              *vpp,
-            struct componentname *cnp,
-            enum vtype            vtyp,
-            uint64_t              size,
-            enum vget_mode        mode,
-            uint64_t              parentid)
+fuse_vnode_get(struct mount         *mp,
+               uint64_t              nodeid,
+               struct vnode         *dvp,
+               struct vnode         **vpp,
+               struct componentname *cnp,
+               enum vtype            vtyp,
+               uint64_t              size)
 {
+    struct thread *td = (cnp != NULL ? cnp->cn_thread : curthread);
     int err = 0;
 
     debug_printf("dvp=%p\n", dvp);
 
-    if (vtyp == VNON) {
-        return EINVAL;
-    }
-
-#if 0 //XROOT
-    if (nodeid == FUSE_ROOT_ID) {
-        *vpp = fusefs_get_data(mp)->rvp; //XROOT
-        err = vnode_get(*vpp);
-        if (err) {
-            *vpp = NULLVP;
-            return err;
-        }
-        goto found;
-    }
-#endif
-
-    err = FSNodeGetOrCreateFileVNodeByID(mp, nodeid, dvp, vtyp, size, vpp, 0);
+    err = fuse_vnode_alloc(mp, td, nodeid, vtyp, LK_EXCLUSIVE | LK_RETRY, vpp);
     if (err) {
         return err;
     }
 
-    cache_enter(dvp, *vpp, cnp);
+    if (cnp != NULL) {
+        cache_enter(dvp, *vpp, cnp);
+    }
 
-found:
     VTOFUD(*vpp)->nlookup++;
 
     return 0;

==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.h#4 (text+ko) ====

@@ -10,22 +10,14 @@
 #include <sys/mutex.h>
 
 #include "fuse_file.h"
-#include "fuse_nodehash.h"
 
-enum {
-    kFSNodeMagic    = 1,
-    kFSNodeBadMagic = 2,
-    kHNodeMagic     = 3,
-};
-
 #define FN_CREATING      0x00000001
 
 struct fuse_vnode_data {
-    uint32_t   fMagic;
-    boolean_t  fInitialised;
     uint64_t   nid;
     uint64_t   nlookup;
     enum vtype vtype;
+    /* XXXIP very likely to be stale, it's not updated in rename() */
     uint64_t   parent_nid;
 
     struct mtx createlock;
@@ -40,16 +32,17 @@
      * modified. Typically, we would take this lock at the beginning of a
      * vnop and drop it at the end of the vnop.
      */
-    struct sx *nodelock;
+    struct sx nodelock;
     void      *nodelockowner;
 
     /*
      * The truncatelock guards against the EOF changing on us (that is, a
      * file resize) unexpectedly.
      */
-    struct sx  *truncatelock;
+    struct sx  truncatelock;
 
     struct vnode *c_vp;
+    /* XXXIP reference is very likely to be stale, it's not updated in rename() */
     struct vnode *parent;
     off_t      filesize; 
     off_t      newfilesize;
@@ -59,13 +52,11 @@
     struct vattr      cached_attrs;
     struct timespec   cached_attrs_valid;
 };
-typedef struct fuse_vnode_data * fusenode_t;
 
-#define VTOFUD(vp) \
-    ((struct fuse_vnode_data *)FSNodeGenericFromHNode((vp)->v_data))
+#define VTOFUD(vp)  ((struct fuse_vnode_data *)((vp)->v_data))
 #define VTOI(vp)    (VTOFUD(vp)->nid)
 #define VTOVA(vp)   (&(VTOFUD(vp)->cached_attrs))
-#define VTOILLU(vp) ((unsigned long long)(VTOFUD(vp) ? VTOI(vp) : 0))
+#define VTOILLU(vp) ((uint64_t)(VTOFUD(vp) ? VTOI(vp) : 0))
 
 #define FUSE_NULL_ID 0
 
@@ -79,17 +70,6 @@
 
 MALLOC_DECLARE(M_FUSEVN);
 
-vfs_hash_cmp_t fuse_vnode_cmp;
-vfs_hash_cmp_t fuse_vnode_setparent_cmp;
-
-void fuse_vnode_init(struct vnode *vp, struct fuse_vnode_data *fvdat,
-                     uint64_t nodeid, enum vtype vtyp, uint64_t parentid);
-void fuse_vnode_ditch(struct vnode *vp, struct thread *td);
-void fuse_vnode_teardown(struct vnode *vp, struct thread *td,
-                         struct ucred *cred, enum vtype vtyp);
-
-enum vget_mode { VG_NORMAL, VG_WANTNEW, VG_FORCENEW };
-
 struct get_filehandle_param {
     enum fuse_opcode opcode;
     uint8_t          do_gc:1;
@@ -116,37 +96,17 @@
 #define C_CREATING           0x04000
 #define C_ACCESS_NOOP        0x08000
 
-int
-FSNodeGetOrCreateFileVNodeByID(struct mount *mp,
-                               uint64_t   nodeid,
-                               struct vnode *dvp,
-                               enum vtype vtyp,
-                               uint64_t   insize,
-                               struct vnode **vnPtr,
-                               int        flags);
+extern struct vop_vector fuse_vnops;
 
-void FSNodeScrub(struct fuse_vnode_data *fvdat);
+void fuse_vnode_destroy(struct vnode *vp);
 
 int
-fuse_vget_i(struct mount *mp,
-            struct thread *td,
-            uint64_t nodeid,
-            enum vtype vtyp,
-            struct vnode **vpp,
-            enum vget_mode vmod,
-            uint64_t parentid);
-#ifdef XXXIP
-int
-fuse_vget_i(struct mount         *mp,
-            uint64_t              nodeid,
-            vfs_context_t         context,
-            struct vnode         *dvp,
-            struct vnode         *vpp,
-            struct componentname *cnp,
-            enum vtype            vtyp,
-            uint64_t              size,
-            enum vget_mode        mode,
-            uint64_t              parentid);
-#endif
+fuse_vnode_get(struct mount         *mp,
+               uint64_t              nodeid,
+               struct vnode         *dvp,
+               struct vnode        **vpp,
+               struct componentname *cnp,
+               enum vtype            vtyp,
+               uint64_t              size);
 
 #endif /* _FUSE_NODE_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201106131533.p5DFXgkM074432>