PERFORCE change 194687 for review

Ilya Putsikau ilya at FreeBSD.org
Mon Jun 13 15:40:20 UTC 2011


http://p4web.freebsd.org/@@194687?ac=10

Change 194687 by ilya at ilya_triton2011 on 2011/06/13 15:39:55

	Vnode operations merge.

Affected files ...

.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#12 edit

Differences ...

==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#12 (text+ko) ====

@@ -74,7 +74,7 @@
 static vop_print_t    fuse_vnop_print;
 static vop_unlock_t   fuse_vnop_unlock;
 
-static struct vop_vector fuse_vnops = {
+struct vop_vector fuse_vnops = {
 	.vop_default       = &default_vnodeops,
 	.vop_access        = fuse_vnop_access,
 	.vop_close         = fuse_vnop_close,
@@ -289,12 +289,11 @@
         goto undo;
     }
 
-    err = FSNodeGetOrCreateFileVNodeByID(mp,
-                                         feo->nodeid,
-                                         dvp,
-                                         VREG, /*size*/0,
-                                         vpp,
-                                         (gone_good_old) ? 0 : FN_CREATING);
+    err = fuse_vnode_get(mp, feo->nodeid, dvp, vpp, cnp, VREG,
+	/*size*/0);
+    if (!err && !gone_good_old) {
+	    VTOFUD(*vpp)->flag |= FN_CREATING;
+    }
     if (err) {
        if (gone_good_old) {
            fuse_internal_forget_send(mp, td, cred, feo->nodeid, 1, fdip);
@@ -416,7 +415,11 @@
     return 0;
 }
 
-#ifdef XXXVP
+#define fusetimespeccmp(tvp, uvp, cmp)           \
+        (((tvp)->tv_sec == (uvp)->tv_sec) ?     \
+         ((tvp)->tv_nsec cmp (uvp)->tv_nsec) :  \
+         ((tvp)->tv_sec cmp (uvp)->tv_sec))
+
 /*
     struct vnop_getattr_args {
 	struct vnode *a_vp;
@@ -428,68 +431,72 @@
 static int
 fuse_vnop_getattr(struct vop_getattr_args *ap)
 {
-	struct vnode *vp = ap->a_vp;
-	struct vattr *vap = ap->a_vap;
-	struct ucred *cred = ap->a_cred;
-	struct thread *td = curthread;
-	struct fuse_dispatcher fdi;
-	struct timespec uptsp;
-	int err = 0;
+    int err = 0;
+    int dataflag;
+    struct vnode *vp = ap->a_vp;
+    struct vattr *vap = ap->a_vap;
+    struct ucred *cred = ap->a_cred;
+    struct thread *td = curthread;
+    struct fuse_dispatcher fdi;
+    struct timespec uptsp;
 
-	/* look for cached attributes */
-	nanouptime(&uptsp);
-	if (timespeccmp(&uptsp, &VTOFUD(vp)->cached_attrs_valid, <=)) {
-		DEBUG("found valid cached attrs for vp #%llu\n", VTOILLU(vp));
+    fuse_trace_printf_vnop();
 
-		if (vap != VTOVA(vp))
-			memcpy(vap, VTOVA(vp), sizeof(*vap));
+    dataflag = fusefs_get_data(vnode_mount(vp))->dataflag;
 
-		return (0);
-	}
+    /* Note that we are not bailing out on a dead file system just yet. */
 
-	if (! (fusefs_get_data(vp->v_mount)->dataflag & FSESS_INITED)) {
-		if (! (vp->v_vflag & VV_ROOT)) {
-			fdata_kick_set(fusefs_get_data(vp->v_mount));
-			err = ENOTCONN;
+    /* look for cached attributes */
+    nanouptime(&uptsp);
+    if (fusetimespeccmp(&uptsp, &VTOFUD(vp)->cached_attrs_valid, <=)) {
+        if (vap != VTOVA(vp)) {
+            memcpy(vap, VTOVA(vp), sizeof(*vap));
+        }
+        debug_printf("fuse_getattr a: returning 0\n");
+        return (0);
+    }
 
-			return (err);
-		} else
-			goto fake;
-	}
+    if (!(dataflag & FSESS_INITED)) {
+        if (!vnode_isvroot(vp)) {
+            fdata_kick_set(fusefs_get_data(vnode_mount(vp)));
+            err = ENOTCONN;
+            debug_printf("fuse_getattr b: returning ENOTCONN\n");
+            return (err);
+        } else {
+            goto fake;
+        }
+    }
 
-	if ((err = fdisp_simple_putget(&fdi, FUSE_GETATTR, vp, td, cred))) {
-		if (err == ENOTCONN && vp->v_vflag & VV_ROOT)
-			/* see comment at similar place in fuse_statfs() */
-			goto fake;
+    if ((err = fdisp_simple_putget_vp(&fdi, FUSE_GETATTR, vp, td, cred))) {
+        if (err == ENOTCONN && vnode_isvroot(vp)) {
+            /* see comment at similar place in fuse_statfs() */
+            goto fake;
+        }
+        debug_printf("fuse_getattr c: returning ENOTCONN\n");
+        return (err);
+    }
 
-		return (err);
-	}
+    cache_attrs(vp, (struct fuse_attr_out *)fdi.answ);
+    if (vap != VTOVA(vp)) {
+        memcpy(vap, VTOVA(vp), sizeof(*vap));
+    }
 
-	cache_attrs(vp, (struct fuse_attr_out *)fdi.answ);
-	if (vap != VTOVA(vp))
-		memcpy(vap, VTOVA(vp), sizeof(*vap));
+    fuse_ticket_drop(fdi.tick);
 
-	fuse_ticket_drop(fdi.tick);
+    if (vnode_vtype(vp) != vap->va_type) {
+        if (vnode_vtype(vp) == VNON && vap->va_type != VNON) {
+            // vp->v_type = vap->va_type;
+        } else {
+            /* stale vnode */
+            // XXX: vnode should be ditched.
+            debug_printf("fuse_getattr d: returning ENOTCONN\n");
+            return (ENOTCONN);
+        }
+    }
 
-	if (vp->v_type != vap->va_type) {
-		if (vp->v_type == VNON && vap->va_type != VNON) {
-			DEBUG2G("vnode #%llu with no type\n", VTOILLU(vp));
-			vp->v_type = vap->va_type;
-		} else {
-			/* stale vnode */
-			DEBUG2G("node #%lu got stale (old type %#x, new type %#x), kicking...\n",
-		                vap->va_fileid, vp->v_type, vap->va_type);
-			fuse_vnode_ditch(vp, td);
-			return (ENOTCONN);
-		}
-	}
+    debug_printf("fuse_getattr e: returning 0\n");
 
-	DEBUG("node #%llu, type %d\n", VTOILLU(vp), vap->va_type);
-#if _DEBUG
-	DEBUG2G("\n");	
-	vn_printf(vp, " * ");
-#endif
-	return (0);
+    return (0);
 
 fake:
     bzero(vap, sizeof(*vap));
@@ -497,7 +504,6 @@
 
     return (0);
 }
-#endif
 
 /*
     struct vnop_inactive_args {
@@ -584,47 +590,44 @@
 	struct componentname *a_cnp;
     };
 */
-#ifdef XXXIP
 int
 fuse_vnop_lookup(struct vop_lookup_args *ap)
 {
     struct componentname *cnp = ap->a_cnp;
     int nameiop               = cnp->cn_nameiop;
     int flags                 = cnp->cn_flags;
-    int wantparent            = flags & WANTPARENT;
+    int wantparent            = flags & (LOCKPARENT|WANTPARENT);
     int islastcn              = flags & ISLASTCN;
     struct vnode *dvp         = ap->a_dvp;
     struct vnode **vpp        = ap->a_vpp;
     struct thread *td         = cnp->cn_thread;
     struct ucred *cred        = cnp->cn_cred;
+    struct mount *mp          = vnode_mount(dvp);
 
     fuse_trace_printf_vnop();
 
     int err                   = 0;
     int lookup_err            = 0;
     struct vnode *vp          = NULL;
+    struct vnode *pdp         = NULL;
     struct fuse_attr *fattr   = NULL;
     struct fuse_dispatcher fdi;
     enum fuse_opcode op;
-    uint64_t nid, parentid;
+    uint64_t nid, parent_nid;
     struct fuse_access_param facp;
-#ifdef INVARIANTS
-    int cache_attrs_hit = 0;
-#endif
+    uint64_t size = 0;
 
-    /* general stuff, based on vfs_cache_lookup */
+    if (fuse_isdeadfs(dvp)) {
+        *vpp = NULL;
+        return ENXIO;
+    }
 
-#if _DEBUG
-    DEBUG2G("root node:\n");
-    vn_printf(fusefs_get_data(dvp->v_mount)->rvp, " * ");
-#endif
-
-    if (dvp->v_type != VDIR) {
+    if (vnode_vtype(dvp) != VDIR) {
         return ENOTDIR;
     }
 
-    if (islastcn && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
-        (nameiop == DELETE || nameiop == RENAME)) {
+    if (islastcn && vfs_isrdonly(mp) &&
+        ((nameiop == DELETE) || (nameiop == RENAME) || (nameiop == CREATE))) {
         return (EROFS);
     }
 
@@ -636,122 +639,121 @@
      */
 
     bzero(&facp, sizeof(facp));
-    if (
-#ifdef NO_EARLY_PERM_CHECK_HACK
-        1
-#else
-        dvp->v_vflag & VV_ROOT
-#endif
-       ) {
-            if ((err = fuse_internal_access(dvp, VEXEC, cred, td, &facp)))
-                return err;
+    if (vnode_isvroot(dvp)) { /* early permission check hack */
+        if ((err = fuse_internal_access(dvp, VEXEC, cred, td, &facp))) {
+            return err;
+        }
     }
 
-    DEBUG2G("lookup in #%llu, nameiop %lu, with flags %#x\n",
-            VTOILLU(dvp), cnp->cn_nameiop, flags);
-
-    /* fetching data from "storage" */
-
     if (flags & ISDOTDOT) {
-        DEBUG2G("dotdot lookup!\n");
-        nid = VTOFUD(dvp)->parent_nid;
-        parentid = FUSE_NULL_ID;
+        pdp = VTOFUD(dvp)->parent;
+        nid = VTOI(pdp);
+        parent_nid = VTOFUD(dvp)->parent_nid;
         fdisp_init(&fdi, 0);
         op = FUSE_GETATTR;
+        goto calldaemon;
     } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') {
-        DEBUG2G("dot lookup!\n");
         nid = VTOI(dvp);
-        parentid = VTOFUD(dvp)->parent_nid; /* irrelevant */
+        parent_nid = VTOFUD(dvp)->parent_nid;
         fdisp_init(&fdi, 0);
         op = FUSE_GETATTR;
+        goto calldaemon;
     } else {
-        nid = VTOI(dvp);
-        parentid = VTOI(dvp);
-        fdisp_init(&fdi, cnp->cn_namelen + 1);
-        op = FUSE_LOOKUP;
+        err = cache_lookup(dvp, vpp, cnp);
+        switch (err) {
+
+        case -1: /* positive match */
+#ifdef XXXIP
+            fuse_lookup_cache_hits++;
+#endif
+            return 0;
+
+        case 0: /* no match in cache */
+#ifdef XXXIP
+            fuse_lookup_cache_misses++;
+#endif
+            break;
+
+        case ENOENT: /* negative match */
+             /* fall through */
+        default:
+             return err;
+        }
     }
 
-    fdisp_make(&fdi, dvp->v_mount, op, nid, td, cred);
+    nid = VTOI(dvp);
+    parent_nid = VTOI(dvp);
+    fdisp_init(&fdi, cnp->cn_namelen + 1);
+    op = FUSE_LOOKUP;
+
+calldaemon:
+    fdisp_make(&fdi, vnode_mount(dvp), op, nid, td, cred);
 
     if (op == FUSE_LOOKUP) {
         memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen);
         ((char *)fdi.indata)[cnp->cn_namelen] = '\0';
-        DEBUG2G("standard lookup, looking up %s\n", (char *)fdi.indata);
     }
 
     lookup_err = fdisp_wait_answ(&fdi);
 
     if (op == FUSE_LOOKUP && !lookup_err) {
         nid = ((struct fuse_entry_out *)fdi.answ)->nodeid;
+        size = ((struct fuse_entry_out *)fdi.answ)->attr.size;
         if (!nid) {
             /*
              * zero nodeid is the same as "not found",
              * but it's also cacheable (which we keep
              * keep on doing not as of writing this)
              */
-            DEBUG2G("zero nid, ie ENOENT\n");
             lookup_err = ENOENT;
         } else if (nid == FUSE_ROOT_ID) {
-            DEBUG2G("root inode found on lookup?!!\n");
             lookup_err = EINVAL;
         }
     }
 
-    if (lookup_err && (
-         (!fdi.answ_stat) || /* this means messaging error */
-         lookup_err != ENOENT || /* daemon reported other error than "legal" ENOENT */
-         op != FUSE_LOOKUP /* we tolerate ENOENT only when we sent a LOOKUP */  
-        )) {
+    if (lookup_err &&
+        ((!fdi.answ_stat) || lookup_err != ENOENT || op != FUSE_LOOKUP)) {
         /*
          * There is error but not lookup related actually
          * (messaging error)
          */
-        DEBUG("lookup failed b/c messaging crap\n");
         return (lookup_err);
     }
 
-    /* analyzing answer */
-
     /*
      * Now we got the answer and filtered out the crap, too, so we know that
      * "found" iff lookup_err == 0
      */
 
     if (lookup_err) {
-        DEBUG("looked up thingy not found\n");
-        if ((nameiop == CREATE || nameiop == RENAME)
-         && islastcn
-         /* && directory dvp has not been removed */) {
+        if ((nameiop == CREATE || nameiop == RENAME) &&
+            islastcn /* && directory dvp has not been removed */) {
 
-                if (dvp->v_mount->mnt_flag & MNT_RDONLY) {
-                        err = EROFS;
-                        goto out;
-                }
+            if (vfs_isrdonly(mp)) {
+                err = EROFS;
+                goto out;
+            }
 
-                DEBUG("create/rename -- we have to make it\n");
-                /*
-                 * Check for write access on directory.
-                 */
-                
-                if ((err = fuse_internal_access(dvp, VWRITE, cred, td, &facp)))
-                        goto out;
+#if 0 // THINK_ABOUT_THIS
+            if ((err = fuse_internal_access(dvp, VWRITE, cred, td, &facp))) {
+                goto out;
+            }
+#endif
 
-                /*
-                 * Possibly record the position of a slot in the
-                 * directory large enough for the new component name.
-                 * This can be recorded in the vnode private data for
-                 * dvp. Set the SAVENAME flag to hold onto the
-                 * pathname for use later in VOP_CREATE or VOP_RENAME.
-                 */
-                cnp->cn_flags |= SAVENAME;
-                
-                err = EJUSTRETURN;
-                goto out;
+            /*
+             * Possibly record the position of a slot in the
+             * directory large enough for the new component name.
+             * This can be recorded in the vnode private data for
+             * dvp. Set the SAVENAME flag to hold onto the
+             * pathname for use later in VOP_CREATE or VOP_RENAME.
+             */
+            cnp->cn_flags |= SAVENAME;
+            
+            err = EJUSTRETURN;
+            goto out;
         }
 
-        /*
-         * Consider inserting name into cache.
-         */
+        /* Consider inserting name into cache. */
 
         /*
          * No we can't use negative caching, as the fs
@@ -772,13 +774,13 @@
         goto out;
 
     } else {
+
         if (op == FUSE_GETATTR) {
             fattr = &((struct fuse_attr_out *)fdi.answ)->attr;
         } else {
             fattr = &((struct fuse_entry_out *)fdi.answ)->attr;
         }
 
-        DEBUG("we found something...\n");
         /*
          * If deleting, and at end of pathname, return parameters
          * which can be used to remove file.  If the wantparent flag
@@ -786,11 +788,9 @@
          * and lock the inode, being careful with ".".
          */
         if (nameiop == DELETE && islastcn) {
-            DEBUG("something to delete\n");
             /*
              * Check for write access on directory.
              */
-
             facp.xuid = fattr->uid;
             facp.facc_flags |= FACCESS_STICKY;
             err = fuse_internal_access(dvp, VWRITE, cred, td, &facp);
@@ -801,95 +801,112 @@
             }
 
             if (nid == VTOI(dvp)) {
-                VREF(dvp);
+                vref(dvp);
                 *vpp = dvp;
                 goto out;
             }
 
-            if ((err = fuse_vget_i(dvp->v_mount, td,
-                                   nid,
-                                   IFTOVT(fattr->mode),
-                                   &vp,
-                                   VG_NORMAL,
-                                   parentid))) {
-                    goto out;
+            /*
+             * XXX We discard generation, also brought to us by
+             * LOOKUP. It's purpose is unclear... it seems to be
+             * simply just yet another 32/64 bit extension for the
+             * inode number, but I'm not sure (hmm, it seems to
+             * have something to do with NFS exportability, too).
+             *
+             * (Linux has such a 32 bit value in its inode struct,
+             * and it really might just be a backward compatible
+             * extension for the inode space [but might as well
+             * be more into it, dunno]. The FUSE protocol uses
+             * a 64 bit generation value; FUSE/Linux uses it for
+             * filling the inode's i_generation field.)
+             */   
+            err = fuse_vnode_get(dvp->v_mount,
+                                 nid,
+                                 dvp,
+                                 &vp,
+                                 cnp,
+                                 IFTOVT(fattr->mode),
+                                 size);
+            if (err) {
+                goto out;
             }
 
             *vpp = vp;
         
             goto out;
+        }
+
+        /*
+         * If rewriting (RENAME), return the inode and the
+         * information required to rewrite the present directory
+         * Must get inode of directory entry to verify it's a
+         * regular file, or empty directory.
+         */
+        if (nameiop == RENAME && wantparent && islastcn) {
+
+#if 0 // THINK_ABOUT_THIS
+            if ((err = fuse_internal_access(dvp, VWRITE, cred, td, &facp))) {
+                goto out;
             }
+#endif
 
             /*
-             * If rewriting (RENAME), return the inode and the
-             * information required to rewrite the present directory
-             * Must get inode of directory entry to verify it's a
-             * regular file, or empty directory.
+             * Check for "."
              */
-            if (nameiop == RENAME && wantparent && islastcn) {
-                    DEBUG("something to rename...\n");
+            if (nid == VTOI(dvp)) {
+                err = EISDIR;
+                goto out;
+            }
 
-                    facp.xuid = fattr->uid;
-                    facp.facc_flags |= FACCESS_STICKY;
-                    err = fuse_internal_access(dvp, VWRITE, cred, td, &facp);
-                    facp.facc_flags &= ~FACCESS_XQUERIES;
+            err = fuse_vnode_get(vnode_mount(dvp),
+                                 nid,
+                                 dvp,
+                                 &vp,
+                                 cnp,
+                                 IFTOVT(fattr->mode),
+                                 size);
+            if (err) {
+                goto out;
+            }
 
-                    if (err)
-                            goto out;
+            *vpp = vp;
+            /*
+             * Save the name for use in VOP_RENAME later.
+             */
+            cnp->cn_flags |= SAVENAME;
 
-                    /*
-                     * Check for "."
-                     */
-                    if (nid == VTOI(dvp)) {
-                            err = EISDIR;
-                            goto out;
-                    }
+            goto out;
+        }
 
-                    err = fuse_vget_i(dvp->v_mount, td, nid,
-                                      IFTOVT(fattr->mode), &vp, VG_NORMAL,
-                                      parentid);
-                    if (err)
-                            goto out;
-                    *vpp = vp;
-                    /*
-                     * Save the name for use in VOP_RENAME later.
-                     */
-                    cnp->cn_flags |= SAVENAME;
-
-                    goto out;
+        if (flags & ISDOTDOT) {
+            vref(pdp);
+            *vpp = pdp;
+        } else if (nid == VTOI(dvp)) {
+            vref(dvp);
+            *vpp = dvp;
+        } else {
+            err = fuse_vnode_get(vnode_mount(dvp),
+                                 nid,
+                                 dvp,
+                                 &vp,
+                                 cnp,
+                                 IFTOVT(fattr->mode),
+                                 size);
+            if (err) {
+                goto out;
             }
-
-            DEBUG("we peacefully found that file\n");
-
-            if (nid == VTOI(dvp)) {
-                    VREF(dvp); /* We want ourself, ie "." */
-                    *vpp = dvp;
-            } else {
-                    if (flags & ISDOTDOT)
-                            /*
-                             * If doing dotdot, we unlock dvp for vget time
-                             * to conform lock order regulations.
-                             */
-                            VOP_UNLOCK(dvp, 0);
-                    err = fuse_vget_i(dvp->v_mount, td, nid,
-                                      IFTOVT(fattr->mode), &vp, VG_NORMAL,
-                                      parentid);
-                    if (flags & ISDOTDOT)
-                            vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
-                    if (err)
-                            goto out;
-                    *vpp = vp;
+            if (vnode_vtype(vp) == VDIR) {
+                VTOFUD(vp)->parent = dvp;
+                //SETPARENT(vp, dvp);
             }
+            *vpp = vp;
+        }
 
         if (op == FUSE_GETATTR)
             cache_attrs(*vpp, (struct fuse_attr_out *)fdi.answ);
         else
             cache_attrs(*vpp, (struct fuse_entry_out *)fdi.answ);
 
-#ifdef INVARIANTS
-            cache_attrs_hit = 1;
-#endif
-
         /* Insert name into cache if appropriate. */
 
         /*
@@ -915,27 +932,19 @@
          */    
 #if 0
         if (cnp->cn_flags & MAKEENTRY) {
-            DEBUG("...caching\n");
             cache_enter(dvp, *vpp, cnp);
         }
 #endif
     }
 out:
     if (!lookup_err) {
-        DEBUG("as the looked up thing was simply found, the cleanup is left for us\n");
-
+        // as the looked up thing was simply found, the cleanup is left for us
         if (err) {
-            DEBUG("though inode found, err exit with no vnode\n");
+            // though inode found, err exit with no vnode
             if (op == FUSE_LOOKUP)
-                fuse_internal_forget_send(dvp->v_mount, td, cred, nid, 1, &fdi);
+                fuse_internal_forget_send(vnode_mount(dvp), td, cred, nid, 1, &fdi);
             return (err);
         } else {
-            if (op == FUSE_LOOKUP)
-                VTOFUD(*vpp)->nlookup++;
-
-            if (islastcn && flags & ISOPEN)
-                VTOFUD(*vpp)->flags |= FVP_ACCESS_NOOP;
-
 #ifndef NO_EARLY_PERM_CHECK_HACK
             if (!islastcn) {
                 /* We have the attributes of the next item
@@ -966,18 +975,21 @@
                  * dir in question. But that can be known only
                  * by having the vnode...
                  */
+                int tmpvtype = vnode_vtype(*vpp);
+
                 bzero(&facp, sizeof(facp));
-                DEBUG("the early perm check hack\n");
+                // the early perm check hack
                 facp.facc_flags |= FACCESS_VA_VALID;
 
-                KASSERT(cache_attrs_hit,
-                        (("invalid reference to cached attrs")));
-                if ((*vpp)->v_type != VDIR && (*vpp)->v_type != VLNK)
+                if (tmpvtype != VDIR && tmpvtype != VLNK)
                     err = ENOTDIR;
-                if (!err && !(*vpp)->v_mountedhere)
+
+                if (!err && !vnode_mountedhere(*vpp)) {
                     err = fuse_internal_access(*vpp, VEXEC, cred, td, &facp);
+                }
+
                 if (err) {
-                    if ((*vpp)->v_type == VLNK)
+                    if (tmpvtype == VLNK)
                         DEBUG("weird, permission error with a symlink?\n");
                     vput(*vpp);
                     *vpp = NULL;
@@ -991,9 +1003,7 @@
 
     return (err);
 }
-#endif
 
-
 /*
     struct vnop_mkdir_args {
 	struct vnode *a_dvp;
@@ -1199,17 +1209,68 @@
 static int
 fuse_vnop_read(struct vop_read_args *ap)
 {
+    int             err;
     struct vnode *vp = ap->a_vp;
-    struct ucred *cred = ap->a_cred;
     struct uio *uio = ap->a_uio;
+#ifdef XXXIP
     int ioflag = ap->a_ioflag;
+    struct ucred *cred = ap->a_cred;
+#endif
+    off_t           orig_resid;
+    off_t           orig_offset;
 
-    DEBUG2G("vnode #%llu\n", VTOILLU(vp));
-    return fuse_io_vnode(vp, cred, uio, ioflag);
+    struct fuse_vnode_data *fvdat;
+
+    fuse_trace_printf_vnop();
+
+    if (fuse_isdeadfs_nop(vp)) {
+        if (vnode_vtype(vp) != VCHR) {
+            return EIO;
+        } else {
+            return 0;
+        }
+    }
+
+    if (uio_offset(uio) < 0) {
+        return EINVAL;
+    }
+
+    /*
+     * if (uio_offset(uio) > SOME_MAXIMUM_SIZE) {
+     *     return 0;
+     * }
+     */
+
+    orig_resid = uio_resid(uio);
+    if (orig_resid == 0) {
+        return 0;
+    }
+
+    orig_offset = uio_offset(uio);
+    if (orig_offset < 0) {
+        return EINVAL;
+    }
+
+    fvdat = VTOFUD(vp);
+    if (!fvdat) {
+        return EINVAL;
+    }
+
+    /* Protect against size change here. */
+
+    if (vnode_isreg(vp)) {
+#ifdef XXXIP
+        err = cluster_read(vp, uio, fvdat->filesize, 0);
+#endif
+    } else if (vnode_isdir(vp)) {
+        err = EISDIR;
+    } else {
+        err = EPERM;
+    }
+
+    return err;
 }
 
-#define DIRCOOKEDSIZE FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + MAXNAMLEN + 1)
-
 /*
     struct vnop_readdir_args {
 	struct vnode *a_vp;
@@ -1226,48 +1287,47 @@
     struct vnode *vp = ap->a_vp;
     struct ucred *cred = ap->a_cred;
     struct uio *uio = ap->a_uio;
-
-    struct thread *td = curthread;
+    int freefufh = 0;
     int err = 0;
     struct fuse_iov cookediov;
     struct fuse_filehandle *fufh;
-    struct fuse_io_data fioda;
-    struct get_filehandle_param gefhp;
+    struct fuse_vnode_data *fvdat;
+
+    fuse_trace_printf_vnop();
+
+    if (fuse_isdeadfs_nop(vp)) {
+        return EBADF;
+    }
+
+#ifdef XXXIP
+    /* Sanity check the uio data. */
+    if ((uio_iovcnt(uio) > 1) ||
+        (uio_resid(uio) < (int)sizeof(struct dirent))) {
+        return (EINVAL);
+    }
+#endif
+
+    fvdat = VTOFUD(vp);
 
-    bzero(&gefhp, sizeof(gefhp));
-    gefhp.opcode = FUSE_OPENDIR;
-    if ((err = fuse_get_filehandle(vp, td, cred, FREAD, &fufh, &gefhp))) {
-            DEBUG2G("fetching filehandle failed\n");
-            return (err);
+    fufh = &(fvdat->fufh[FUFH_RDONLY]);
+    if (!(fufh->fufh_flags & FUFH_VALID)) {
+        err = fuse_filehandle_get(vp, NULL, cred, FUFH_RDONLY);
+        if (err) {
+            return err;
+        }
+        freefufh = 1;
     }
 
-    /*
-     * In "most cases" this will do and won't have to resize the buffer
-     * (that is, if the daemon has a "tight" view of the dir entries,
-     * which is the case if userspace uses the old API or the new one
-     * in the analogous way; by our terminology, this means
-     * freclen == bytesavail)
-     * (See fuse_internal_readdir_processdata).
-     */
+#define DIRCOOKEDSIZE FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + MAXNAMLEN + 1)
     fiov_init(&cookediov, DIRCOOKEDSIZE);
 
-    bzero(&fioda, sizeof(fioda));
-    fioda.vp = vp;
-    fioda.fufh = fufh;
-    fioda.uio = uio;
-    fioda.cred = cred;
-    fioda.opcode = FUSE_READDIR;
-    fioda.buffeater = fuse_internal_readdir_processdata;
-    fioda.param = &cookediov;
-    /*
-     * We tried hard to use bio, but offsety readdir can't be handled
-     * properly that way -- the offset field of fuse_dirents can't be
-     * mapped to an offset of a bio buffer
-     */
-    err = fuse_read_directbackend(&fioda);
+    err = fuse_internal_readdir(vp, uio, fufh, &cookediov);
 
     fiov_teardown(&cookediov);
-    fufh->useco--;
+    if (freefufh) {
+        fufh->open_count--;
+        (void)fuse_filehandle_put(vp, NULL, NULL, FUFH_RDONLY, 0);
+    }
     fuse_invalidate_attr(vp);
 
     return err;
@@ -1286,19 +1346,27 @@
     int err;
     struct vnode *vp = ap->a_vp;
     struct uio *uio = ap->a_uio;
+    struct ucred *cred = ap->a_cred;
     struct fuse_dispatcher fdi;
 
     fuse_trace_printf_vnop();
 
-    if ((err = fdisp_simple_putget(&fdi, FUSE_READLINK, vp, curthread,
-        ap->a_cred)))
-            return (err);
+    if (fuse_isdeadfs_nop(vp)) {
+        return EBADF;
+    }
+
+    if (vnode_vtype(vp) != VLNK) {
+        return EINVAL;
+    }
+
+    if ((err = fdisp_simple_putget_vp(&fdi, FUSE_READLINK, vp, curthread, cred))) {
+        return err;
+    }
 
     if (((char *)fdi.answ)[0] == '/' &&
-        fusefs_get_data(vp->v_mount)->dataflag & FSESS_PUSH_SYMLINKS_IN) {
-        char *mpth = vp->v_mount->mnt_stat.f_mntonname;
-
-        err = uiomove(mpth, strlen(mpth), uio);
+        fusefs_get_data(vnode_mount(vp))->dataflag & FSESS_PUSH_SYMLINKS_IN) {
+            char *mpth = vnode_mount(vp)->mnt_stat.f_mntonname;
+            err = uiomove(mpth, strlen(mpth), uio);
     }
 
     if (!err) {
@@ -1320,18 +1388,46 @@
 static int
 fuse_vnop_reclaim(struct vop_reclaim_args *ap)
 {
+    int type;
     struct vnode *vp = ap->a_vp;
     struct thread *td = ap->a_td;
+    struct fuse_vnode_data *fvdat = VTOFUD(vp);
+    struct fuse_filehandle *fufh = NULL;
+
+    fuse_trace_printf_vnop();
+
+    if (!fvdat) {
+        panic("FUSE: no vnode data during recycling");
+    }
+
+    for (type = 0; type < FUFH_MAXTYPE; type++) {
+        fufh = &(fvdat->fufh[type]);
+        if (fufh->fufh_flags & FUFH_VALID) {
+            if (fufh->fufh_flags & FUFH_STRATEGY) {
+                fufh->fufh_flags &= ~FUFH_MAPPED;
+                fufh->open_count = 0;
+                (void)fuse_filehandle_put(vp, td, NULL, type, 0);
+            } else {
+                panic("vnode being reclaimed but fufh (type=%d) is valid",
+                      type);
+            }
+        }
+    }
 
-    DEBUG("pfft...\n");
-#if _DEBUG
-    DEBUG2G("=============>\n");
-    kdb_backtrace();
-    vn_printf(vp, " ");
-    DEBUG2G("<=============\n");
-#endif
+    if ((!fuse_isdeadfs(vp)) && (fvdat->nlookup)) {
+        struct fuse_dispatcher fdi;
+        fdi.tick = NULL;
+        fuse_internal_forget_send(vnode_mount(vp), td, NULL, VTOI(vp),
+                                  fvdat->nlookup, &fdi);
+    }
+
+    cache_purge(vp);
+    /* XXXIP TODO */
+    vfs_hash_remove(vp);
     vnode_destroy_vobject(vp);
-    return (fuse_recyc_backend(vp, td));
+    fuse_vnode_destroy(vp);
+
+    return 0;
 }
 
 /*
@@ -1348,6 +1444,18 @@
     struct vnode *vp = ap->a_vp;
     struct componentname *cnp = ap->a_cnp;
 
+    fuse_trace_printf_vnop();
+
+    if (fuse_isdeadfs_nop(vp)) {
+        panic("fuse_vnop_remove(): called on a dead file system");
+    }
+
+    if (vnode_isdir(vp)) {
+        return EPERM;
+    }
+
+    cache_purge(vp);
+
     return (fuse_internal_remove(dvp, vp, cnp, FUSE_UNLINK));
 }
 
@@ -1364,252 +1472,34 @@
 static int
 fuse_vnop_rename(struct vop_rename_args *ap)
 {
-	struct vnode *tvp = ap->a_tvp;
-	struct vnode *tdvp = ap->a_tdvp;
-	struct vnode *fvp = ap->a_fvp;
-	struct vnode *fdvp = ap->a_fdvp;
-	struct componentname *tcnp = ap->a_tcnp;
-	struct componentname *fcnp = ap->a_fcnp;
+    int err = 0;
+    struct vnode *fdvp = ap->a_fdvp;
+    struct vnode *fvp = ap->a_fvp;
+    struct componentname *tcnp = ap->a_tcnp;
+    struct vnode *tdvp = ap->a_tdvp;
+    struct vnode *tvp = ap->a_tvp;
+    struct componentname *fcnp = ap->a_fcnp;
 
-	int doingdirectory = 0;
-	int err = 0;
-	struct thread *td;
-	struct fuse_access_param facp;
-	uint64_t fnid, tdnid;
-	struct fuse_data *data = NULL;
-	struct parentmanager_param pmp;
-	struct vnode *xvp;
+    fuse_trace_printf_vnop();
 
-	td = curthread;
-	bzero(&facp, sizeof(facp));
+    if (fuse_isdeadfs_nop(fdvp)) {
+        panic("fuse_vnop_rename(): called on a dead file system");
+    }
 

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list