PERFORCE change 85236 for review

soc-chenk soc-chenk at FreeBSD.org
Thu Oct 13 15:00:55 PDT 2005


http://perforce.freebsd.org/chv.cgi?CH=85236

Change 85236 by soc-chenk at soc-chenk_leavemealone on 2005/10/13 22:00:13

	fixed panics related to stale vnodes
	Submitted by:	soc-chenk

Affected files ...

.. //depot/projects/soc2005/fuse4bsd2/fuse_module/fuse.c#15 edit
.. //depot/projects/soc2005/fuse4bsd2/fuse_module/fuse.h#8 edit

Differences ...

==== //depot/projects/soc2005/fuse4bsd2/fuse_module/fuse.c#15 (text+ko) ====

@@ -1514,7 +1514,7 @@
 static void fuse_filehandle_gc(struct vnode *vp, struct thread *td, struct ucred *cred);
 static vop_reclaim_t fuse_reclaim;
 static vop_inactive_t fuse_inactive;
-static __inline void fuse_vnode_kick(struct vnode *vp);
+static __inline void fuse_vnode_kick(struct vnode *vp, struct thread *td);
 static vop_access_t fuse_access;
 static __inline int fuse_access_by_attr(struct mount *mp, struct vattr *vap, mode_t mode, struct ucred *cred);
 /* static vop_cachedlookup_t fuse_lookup; */
@@ -1844,6 +1844,7 @@
 	 * without resorting to the vfs hashing mechanism, thus it also
 	 * can be inserted directly to the v_hash slot.
 	 */
+	rvp->v_hash = FUSE_ROOT_INODE;
 	fmnt->rvp = rvp; 	
 	fuse_vnode_init(rvp, fvdat, FUSE_ROOT_INODE, VDIR);
 	rvp->v_vflag |= VV_ROOT;
@@ -2113,7 +2114,7 @@
 
 	DEBUG2G("mp %p: %s\n", mp, mp->mnt_stat.f_mntfromname);
 
-	if ((err = vfs_hash_get(mp, 0, /*flags*/ myflags, td, vpp, fuse_vnode_cmp, &nodeid)))
+	if ((err = vfs_hash_get(mp, nodeid, /*flags*/ myflags, td, vpp, fuse_vnode_cmp, &nodeid)))
 		return (err);
 
 audit:
@@ -2122,7 +2123,7 @@
 		if ((*vpp)->v_type == vtyp) {
 			return (0);
 		} else
-			fuse_vnode_kick(*vpp);
+			fuse_vnode_kick(*vpp, td);
 	}
 
 	/* as the big guys say, malloc for your data before getnewvnode() */
@@ -2142,8 +2143,7 @@
 	        return (err);
 	}
 
-	/* XXX nodeid: cast from 64 bytes to 32 */
-	err = vfs_hash_insert(*vpp, 0, /*flags*/ myflags, td, &vp2, fuse_vnode_cmp, &nodeid);
+	err = vfs_hash_insert(*vpp, nodeid, /*flags*/ myflags, td, &vp2, fuse_vnode_cmp, &nodeid);
 
 	if (err) {
 		FREE(fvdat, M_FUSEFS);
@@ -2204,7 +2204,7 @@
 		return (0);
 	}
 
-	DEBUG("getting at vnode of ino %llu\n", VTOI(vp));
+	DEBUG("getting at vnode of ino %llu\n", VTOI32(vp));
 
 	fvdat = vp->v_data;
 
@@ -2247,7 +2247,7 @@
 	KASSERT(fufh->useco >= 0, ("negative use count for fuse filehandle"));
 	KASSERT(! fufh->fp || fufh->useco > 0,
 	        ("filehandle bound with 0 use counter"));
-	DEBUG2G("vnode #%llu, fufh owner %p, useco %d\n", VTOI(vp), fufh->fp, fufh->useco);
+	DEBUG2G("vnode #%llu, fufh owner %p, useco %d\n", VTOI32(vp), fufh->fp, fufh->useco);
 	if (! fufh->fp && fufh->useco == 0) {
 		LIST_REMOVE(fufh, fh_link);
 		fuse_send_release(vp, td, cred, fufh, fufh->mode);
@@ -2292,7 +2292,7 @@
 
 	int err;
 
-	DEBUG("getting at vnode of ino %llu\n", VTOI(vp));
+	DEBUG("getting at vnode of ino %llu\n", VTOI32(vp));
 #if _DEBUG
 	DEBUG2G("=============>\n");
 	kdb_backtrace();
@@ -2342,12 +2342,22 @@
 }
 
 static __inline void
-fuse_vnode_kick(struct vnode *vp)
+fuse_vnode_kick(struct vnode *vp, struct thread *td)
 {
 	struct fuse_vnode_data *fvdat;
 
+	if (! td)
+		td = curthread;
+
+	if (vp->v_vflag & VV_ROOT) {
+		fdata_kick_set(fusedev_get_data(((struct fuse_mnt_data *)vp->v_mount->mnt_data)->fdev));
+		return;
+	}
 	fvdat = vp->v_data;
 	fvdat->nlookup = 0;
+	DEBUG("pfft...\n"); 
+	fuse_filehandle_gc(vp, td, NULL);		
+	vnode_destroy_vobject(vp);
 	/*
 	 * this implies we won't get feedback on recycling
 	 * (other than panicking, or the lack of that)
@@ -2355,8 +2365,7 @@
 	 * would be too much hassle...
 	 */
 	vp->v_op = &dead_vnodeops;
-	DEBUG("pfft...\n"); 
-	fuse_recyc_backend(vp, curthread);
+	fuse_recyc_backend(vp, td);
 	vput(vp);
 }
 
@@ -2458,12 +2467,13 @@
 
 	if (vp->v_type != vap->va_type) {
 		/* stale vnode */
-		DEBUG("node #%lu got stale, kicking...\n", vap->va_fileid);
-		fuse_vnode_kick(vp);
+		DEBUG("node #%lu got stale (old type 0x%x, new type 0x%x), kicking...\n",
+	        vap->va_fileid, vp->v_type, vap->va_type);
+		fuse_vnode_kick(vp, td);
 		return (EIO);
 	}
 
-	DEBUG("node #%llu, type %d\n", VTOI(vp), vap->va_type);
+	DEBUG("node #%llu, type %d\n", VTOI32(vp), vap->va_type);
 #if _DEBUG
 	DEBUG2G("\n");	
 	vn_printf(vp, " * ");
@@ -2567,7 +2577,7 @@
 #endif
 
 	if (dvp->v_type != VDIR) {
-		DEBUG("vnode #%llu of vtype %d is not a dir\n", VTOI(dvp),
+		DEBUG("vnode #%llu of vtype %d is not a dir\n", VTOI32(dvp),
 		      dvp->v_type); 
 		return (ENOTDIR);
 	}
@@ -2594,7 +2604,7 @@
 			return (err);
 	}
 
-	DEBUG2G("lookup in #%llu, with flags 0x%x\n", VTOI(dvp), flags);
+	DEBUG2G("lookup in #%llu, with flags 0x%x\n", VTOI32(dvp), flags);
 
 	/* fetching data from "storage" */
 
@@ -2978,13 +2988,13 @@
 	sx_sunlock(&fvdat->fh_lock);
 
 	if (err == -1) {
-		DEBUG2G("suitable fh of vnode #%llu found\n", VTOI(vp));
+		DEBUG2G("suitable fh of vnode #%llu found\n", VTOI32(vp));
 		return (fufh);
 	}
 	else if (err)
 		return (NULL);
 
-	DEBUG2G("we need to fetch a new filehandle for vnode #%llu\n", VTOI(vp));
+	DEBUG2G("we need to fetch a new filehandle for vnode #%llu\n", VTOI32(vp));
 
 	fdi.iosize = sizeof(*foi);
 	if ((err = fdisp_prepare_all(&fdi,
@@ -3241,7 +3251,7 @@
 
 	fvdat->fh_counter--;
 	DEBUG2G("filehandle of vnode #%llu being released, fh counter now is %d\n",
-	         VTOI(vp), fvdat->fh_counter); 
+	         VTOI32(vp), fvdat->fh_counter); 
 	fdi.iosize = sizeof(*fri);
 
 	if ((err = fdisp_prepare_all(&fdi,
@@ -3272,7 +3282,7 @@
  */
 #define BREAK_IF_BAD(fp)						\
 if (! (fp)->f_vnode->v_data) {						\
-	DEBUG("bad fileop on vnode no. %llu\n", VTOI((fp)->f_vnode));	\
+	DEBUG("bad fileop on vnode no. %llu\n", VTOI32((fp)->f_vnode));	\
 	return (EBADF);							\
 }
 
@@ -3305,7 +3315,7 @@
 	fufh = fp->f_data;
 	KASSERT(fufh->fp == fp, ("file's filehandle is stolen"));
 	DEBUG2G("vnode #%llu, fufh owner %p, useco %d\n",
-	        VTOI(fp->f_vnode), fp, fufh->useco);
+	        VTOI32(fp->f_vnode), fp, fufh->useco);
 
 	fufh->useco--;
 	sx_xlock(&fvdat->fh_lock);
@@ -3504,6 +3514,7 @@
 	if (! FILE_IS_FAT(fp))
 		panic("non-fat file passed to read routine");
 
+	vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
 	if ((flags & FOF_OFFSET) == 0)
 		uio->uio_offset = fp->f_offset;
 
@@ -3522,12 +3533,12 @@
 	if (fp->f_flag & O_DIRECT ||
 	    fufh->flags & FUSEFH_DIRECTIO) {
 		DEBUG2G("direct read of vnode %llu via file handle %llu\n",
-		         VTOI(fp->f_vnode), fufh->fh_id);
+		         VTOI32(fp->f_vnode), fufh->fh_id);
 		err = fuse_read_directbackend(fp->f_vnode, fufh, uio, cred, td,
 		                              FUSE_READ, fuse_std_buffeater,
 		                              NULL);
 	} else {
-		DEBUG2G("buffered read of vnode %llu\n", VTOI(fp->f_vnode));
+		DEBUG2G("buffered read of vnode %llu\n", VTOI32(fp->f_vnode));
 		err = fuse_read_biobackend(fp->f_vnode, fufh, uio, cred, td,
 		                           FUSE_READ, fuse_std_buffeater, NULL);
 	}
@@ -3535,6 +3546,7 @@
 	if ((flags & FOF_OFFSET) == 0)
 		fp->f_offset = uio->uio_offset;
 	fp->f_nextoff = uio->uio_offset;
+	VOP_UNLOCK(fp->f_vnode, 0, td);
 
 	return (err);
 }
@@ -3974,7 +3986,7 @@
 		 * XXX: handling of this case is untested.
 		 */
 		DEBUG("weird, file changed type during linking\n"); 
-		fuse_vnode_kick(vp);
+		fuse_vnode_kick(vp, NULL);
 		err = EBADF;
 	}
 
@@ -4199,7 +4211,7 @@
 			struct vnode *pdp2;
 			DEBUG("trying at chenkpath\n");
 			do {
-				DEBUG("checkpath bumped into node %llu\n", VTOI(pdp));
+				DEBUG("checkpath bumped into node %llu\n", VTOI32(pdp));
 				if (pdp->v_vflag & VV_ROOT)
 					err = -1;
 				if (pdp == fvp) {
@@ -4421,7 +4433,7 @@
 		return (err);
 
 	if (vp->v_type != IFTOVT(((struct fuse_attr_out *)fdi.answ)->attr.mode)) {
-		fuse_vnode_kick(vp);
+		fuse_vnode_kick(vp, td);
 		err = EIO;
 	}
 
@@ -4827,6 +4839,7 @@
 	if (uio->uio_resid == 0)
 		return (0);
 
+	vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
 	if (fp->f_flag & O_APPEND) {
 		VOP_GETATTR(fp->f_vnode, &va, cred, td);
 		uio->uio_offset = va.va_size;
@@ -4836,17 +4849,18 @@
 	if (fp->f_flag & O_DIRECT ||
 	    fufh->flags & FUSEFH_DIRECTIO) {
 		DEBUG2G("direct write of vnode %llu via file handle %llu\n",
-		        VTOI(fp->f_vnode), fufh->fh_id);
+		        VTOI32(fp->f_vnode), fufh->fh_id);
 		err = fuse_write_directbackend(fp->f_vnode, fufh->fh_id, uio,
 		                               cred, td);
 	} else {
-		DEBUG2G("buffered write of vnode %llu\n", VTOI(fp->f_vnode));
+		DEBUG2G("buffered write of vnode %llu\n", VTOI32(fp->f_vnode));
 		err = fuse_write_biobackend(fp->f_vnode, uio, cred, td);
 	}
 
 	if ((flags & FOF_OFFSET) == 0)
 		fp->f_offset = uio->uio_offset;
 	fp->f_nextoff = uio->uio_offset;
+	VOP_UNLOCK(fp->f_vnode, 0, td);
 
 	DEBUG("leaving with %d\n", err);
 	return (err);
@@ -4879,13 +4893,13 @@
 
 	if (! (vp->v_type == VREG || vp->v_type == VDIR)) {
 		DEBUG("for vnode #%llu v_type is %d, dropping\n",
-		      VTOI(vp), vp->v_type);
+		      VTOI32(vp), vp->v_type);
 		return (EOPNOTSUPP);
 	}
 
 	if (bp->b_iocmd != BIO_READ && bp->b_iocmd != BIO_WRITE) {
 		DEBUG("for vnode #%llu bio tried with biocmd 0x%x, dropping\n",
-		       VTOI(vp), bp->b_iocmd);
+		       VTOI32(vp), bp->b_iocmd);
 		return (EOPNOTSUPP);
 	}
 
@@ -4924,7 +4938,7 @@
 	if (err)
 		goto out;
 
-	DEBUG2G("vp #%llu, fufh #%llu\n", VTOI(vp), fufh->fh_id);
+	DEBUG2G("vp #%llu, fufh #%llu\n", VTOI32(vp), fufh->fh_id);
 
 	if (bp->b_iocmd == BIO_READ) {
 		struct fuse_read_in *fri;
@@ -5077,7 +5091,7 @@
 	struct fuse_vnode_data *fvdat = ap->a_vp->v_data;
 
 	printf("nodeid: %llu, fh_counter: %d, nlookup: %llu\n",
-	       VTOI(ap->a_vp), fvdat->fh_counter, fvdat->nlookup);
+	       VTOI32(ap->a_vp), fvdat->fh_counter, fvdat->nlookup);
 	return (0);
 }
 
@@ -5087,13 +5101,14 @@
 	struct vnode *vp;
 	int rc;
 
-	DEBUG("vnode #%llu\n", VTOI((struct vnode *)bo->bo_private));
+	DEBUG("vnode #%llu\n", VTOI32((struct vnode *)bo->bo_private));
 	vp = bo->bo_private;
 	KASSERT(bo == &vp->v_bufobj, ("BO/VP mismatch: vp %p (#%llu) bo %p != %p",
-	    vp, VTOI(vp), &vp->v_bufobj, bo));
+	    vp, VTOI32(vp), &vp->v_bufobj, bo));
 	rc = VOP_STRATEGY(vp, bp);
-	KASSERT(rc == 0, ("Fuse VOP_STRATEGY failed: bp=%p, "
-	    "vp=%p, rc=%d", bp, vp, rc));
+	KASSERT(vp->v_op == &dead_vnodeops || rc == 0,
+	        ("Fuse VOP_STRATEGY failed: bp=%p, "
+	        "vp=%p, rc=%d", bp, vp, rc));
 }
 
 

==== //depot/projects/soc2005/fuse4bsd2/fuse_module/fuse.h#8 (text+ko) ====

@@ -137,6 +137,7 @@
 #define FUSE_ROOT_INODE 1   /* Fuse convention: node id of root node is 1 */
 
 #define VTOI(vp) ((struct fuse_vnode_data *)(vp)->v_data)->nid
+#define VTOI32(vp) (uint64_t)(vp)->v_hash
 
 /** Max number of pages that can be used in a single read request */
 /* (taken from Linux Fuse) */


More information about the p4-projects mailing list