PERFORCE change 194689 for review

Ilya Putsikau ilya at FreeBSD.org
Mon Jun 13 15:41:25 UTC 2011


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

Change 194689 by ilya at ilya_triton2011 on 2011/06/13 15:40:31

	Use fuse4bsd io

Affected files ...

.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.c#7 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.h#4 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#13 edit

Differences ...

==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.c#7 (text+ko) ====

@@ -35,17 +35,13 @@
 #include <vm/vnode_pager.h>
 #include <vm/vm_object.h>
 
-#if (__FreeBSD__ >= 8)
-#define vfs_bio_set_validclean vfs_bio_set_valid
-#endif
-
 #include "fuse.h"
 #include "fuse_file.h"
 #include "fuse_node.h"
 #include "fuse_ipc.h"
 #include "fuse_io.h"
 
-int fuse_read_directbackend(struct fuse_io_data *fioda);
+static int fuse_read_directbackend(struct fuse_io_data *fioda);
 static int fuse_io_p2p(struct fuse_io_data *fioda, struct fuse_dispatcher *fdip);
 static int fuse_read_biobackend(struct fuse_io_data *fioda);
 static int fuse_write_directbackend(struct fuse_io_data *fioda);
@@ -53,6 +49,52 @@
 
 static fuse_buffeater_t fuse_std_buffeater; 
 
+static int
+fuse_io_filehandle_get(struct vnode *vp, int rdonly,
+    struct ucred *cred, struct fuse_filehandle **fufhp)
+{
+	struct fuse_vnode_data *fvdat = VTOFUD(vp);
+	struct fuse_filehandle *fufh;
+	fufh_type_t fufh_type;
+	int err = 0;
+
+	if (rdonly) {
+		fufh_type = FUFH_RDONLY; // FUFH_RDWR will also do
+	} else {
+		fufh_type = FUFH_WRONLY; // FUFH_RDWR will also do
+	}
+
+	fufh = &(fvdat->fufh[fufh_type]);
+	if (!(fufh->fufh_flags & FUFH_VALID)) {
+		fufh_type = FUFH_RDWR;
+		fufh = &(fvdat->fufh[fufh_type]);
+		if (!(fufh->fufh_flags & FUFH_VALID)) {
+			fufh = NULL;
+		} else {
+			debug_printf("strategy falling back to FUFH_RDWR ... OK\n");
+		}
+	}
+
+	if (fufh == NULL) {
+		if (rdonly) {
+			fufh_type = FUFH_RDONLY;
+		} else {
+			fufh_type = FUFH_RDWR;
+		}
+		err = fuse_filehandle_get(vp, NULL, cred, fufh_type);
+		if (!err) {
+			fufh = &(fvdat->fufh[fufh_type]);
+			debug_printf("STRATEGY: created *new* fufh of type %d\n",
+			    fufh_type);
+		}
+	} else {
+		debug_printf("STRATEGY: using existing fufh of type %d\n", fufh_type);
+	}
+
+	*fufhp = fufh;
+	return (err);
+}
+
 /****************
  *
  * >>> Low level I/O routines and interface to them
@@ -61,29 +103,24 @@
 
 /* main I/O dispatch routine */
 int
-fuse_io_dispatch(struct vnode *vp, struct fuse_filehandle *fufh, struct uio *uio,
-                 struct ucred *cred, int flag, struct thread *td)
+fuse_io_dispatch(struct vnode *vp, struct uio *uio, int flag,
+    struct ucred *cred)
 {
-	int err;
+	struct fuse_filehandle *fufh;
 	struct fuse_io_data fioda;
-	int directio;
+	int err, directio;
 
-	RECTIFY_TDCR(td, cred);
-	ASSERT_VOP_LOCKED__FH(vp);
-
-	if (fufh)
-		fufh->useco++;
-	else if ((err = fuse_get_filehandle(vp, NULL, cred, flag, &fufh, NULL))) {
-		DEBUG2G("no filehandle for vnode #%llu\n", VTOILLU(vp));
+	err = fuse_io_filehandle_get(vp, (uio->uio_rw == UIO_READ),
+	    cred, &fufh);
+	if (!err)
 		return (err);
-	}
 
 	bzero(&fioda, sizeof(fioda));
 	fioda.vp = vp;
 	fioda.fufh = fufh;
 	fioda.uio = uio;
 	fioda.cred = cred;
-	fioda.td = td;
+	fioda.td = curthread;
 
 	/*
 	 * Ideally, when the daemon asks for direct io at open time, the
@@ -95,7 +132,7 @@
 	 * we hardwire it into the file's private data (similarly to Linux,
 	 * btw.).
 	 */
-	directio = (flag & O_DIRECT) || (fufh->flags & FOPEN_DIRECT_IO);
+	directio = (flag & O_DIRECT);
 
 	switch (uio->uio_rw) {
 	case UIO_READ:
@@ -125,62 +162,15 @@
 		panic("uninterpreted mode passed to fuse_io_dispatch");
 	}
 
-	if (VTOFUD(vp))
-		fufh->useco--;
-	else
-		DEBUG2G("poor nasty nasty vnode %p...\n", vp);
 	fuse_invalidate_attr(vp);
 
 	return (err);
 }
 
-/* dispatch routine for file based I/O */
-int
-fuse_io_file(struct file *fp, struct uio *uio, struct ucred *cred, int flags,
-	     struct thread *td)
-{
-	struct fuse_filehandle *fufh;
-	struct vattr va;
-	struct vnode *vp, *ovl_vp = fp->f_vnode;
-	int err = 0;
-
-	vn_lock(ovl_vp, LK_EXCLUSIVE | LK_RETRY);
-
-	if (_file_is_bad(fp) || ! _file_is_fat(fp)) {
-		err = EBADF;
-		goto out;
-	}
-	fufh = FTOFH(fp);
-	vp = fufh->fh_vp;
-	ASSERT_VOP_LOCKED__FH(vp);
-
-	if (uio->uio_resid == 0)
-		goto out;
-
-	if (uio->uio_rw == UIO_WRITE && fp->f_flag & O_APPEND) {
-		if ((err = VOP_GETATTR(vp, &va, cred)))
-			goto out;
-		uio->uio_offset = va.va_size;
-	} else if ((flags & FOF_OFFSET) == 0)
-		uio->uio_offset = fp->f_offset;
-
-	err = fuse_io_dispatch(vp, fufh->op == FUSE_OPEN ? fufh : NULL, uio,
-	                       cred, fp->f_flag, td);
-
-	if ((flags & FOF_OFFSET) == 0)
-		fp->f_offset = uio->uio_offset;
-	fp->f_nextoff = uio->uio_offset;
-
-out:
-	VOP_UNLOCK(ovl_vp, 0);
-	DEBUG("leaving with %d\n", err);
-	return (err);
-}
-
 /* dispatch routine for vnode based I/O */
 int
-fuse_io_vnode(struct vnode *vp, struct ucred *cred, struct uio *uio,
-              int ioflag)
+fuse_io_vnode(struct vnode *vp, struct uio *uio,
+              int ioflag, struct ucred *cred)
 {
 	int fflag = (uio->uio_rw == UIO_READ) ? FREAD : FWRITE;
 	int err;
@@ -196,7 +186,7 @@
 	if (ioflag & IO_SYNC)
 		fflag |= O_SYNC;
 
-	err = fuse_io_dispatch(vp, NULL, uio, cred, fflag, NULL);
+	err = fuse_io_dispatch(vp, uio, fflag, cred);
 
 	DEBUG("return with %d\n", err);
 	return (err);
@@ -258,7 +248,7 @@
 		if ((bp->b_flags & B_CACHE) == 0) {
 			bp->b_iocmd = BIO_READ;
 			vfs_busy_pages(bp, 0);
-			err = fuse_strategy_i(vp, bp, fufh, op);
+			err = fuse_io_strategy(vp, bp, fufh, op);
 #if _DEBUG
 			prettyprint(bp->b_data, 48);
 			printf("\n");
@@ -305,7 +295,7 @@
 	return ((err == -1) ? 0 : err);
 }
 
-int
+static int
 fuse_read_directbackend(struct fuse_io_data *fioda)
 {
 	struct vnode *vp = fioda->vp;
@@ -652,7 +642,7 @@
 		if ((bp->b_flags & B_CACHE) == 0) {
 			bp->b_iocmd = BIO_READ;
 			vfs_busy_pages(bp, 0);
-			fuse_strategy_i(vp, bp, NULL, 0);
+			fuse_io_strategy(vp, bp, NULL, 0);
 			if ((err =  bp->b_error)) {
 				brelse(bp);
 				break;
@@ -742,7 +732,7 @@
 				bp->b_dirtyoff = on;
 				bp->b_dirtyend = on + n;
 			}
-			vfs_bio_set_validclean(bp, on, n);
+			vfs_bio_set_valid(bp, on, n);
 		}
 
 		bwrite(bp);
@@ -755,7 +745,7 @@
 
 /* core strategy like routine */
 int
-fuse_strategy_i(struct vnode *vp, struct buf *bp, struct fuse_filehandle *fufh,
+fuse_io_strategy(struct vnode *vp, struct buf *bp, struct fuse_filehandle *fufh,
                 enum fuse_opcode op)
 {
 	struct fuse_dispatcher fdi;
@@ -793,22 +783,13 @@
 
 	cred = bp->b_iocmd == BIO_READ ? bp->b_rcred : bp->b_wcred;
 
-#if _DEBUG
-	DEBUG2G("reading from block #%d at vnode:\n", (int)bp->b_blkno);
-	vn_printf(vp, " * ");
-#endif
-	if (fufh) {
-		DEBUG2G("we have a useable filehandle passed on\n");
-		fufh->useco++;
-	} else
-		err = fuse_get_filehandle(vp, NULL, cred,
-	                             bp->b_iocmd == BIO_READ ? FREAD : FWRITE,
-		                     &fufh, NULL);
-
+	err = fuse_io_filehandle_get(vp, (bp->b_iocmd == BIO_READ),
+	    cred, &fufh);
 	if (err) {
 		DEBUG2G("fetching filehandle failed\n");
 		goto out;
 	}
+	fufh->fufh_flags |= FUFH_STRATEGY;
 
 	DEBUG2G("vp #%llu, fufh #%llu\n", VTOILLU(vp), (unsigned long long)fufh->fh_id);
 
@@ -952,9 +933,6 @@
 		DEBUG("no ticket on leave\n");
 
 out:
-	if (fufh)
-		fufh->useco--;
-
 	if (err) {
 		bp->b_ioflags |= BIO_ERROR;
 		bp->b_error = err;

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

@@ -1,3 +1,5 @@
+#ifndef _FUSE_IO_H_
+#define _FUSE_IO_H_
 
 /* prototype for processing an input data buffer and an uio
    for reading related acivities */
@@ -15,15 +17,12 @@
 	void *param;
 };
 
-int fuse_io_dispatch(struct vnode *vp, struct fuse_filehandle *fufh,
-                     struct uio *uio, struct ucred *cred, int flag,
-                     struct thread *td);
-int fuse_io_file(struct file *fp, struct uio *uio, struct ucred *cred,
-                 int flags, struct thread *td);
-int fuse_io_vnode(struct vnode *vp, struct ucred *cred, struct uio *uio,
-                  int ioflag);
-int fuse_strategy_i(struct vnode *vp, struct buf *bp,
-                    struct fuse_filehandle *fufh, enum fuse_opcode op);
+int fuse_io_dispatch(struct vnode *vp, struct uio *uio, int flag,
+    struct ucred *cred);
+int fuse_io_vnode(struct vnode *vp, struct uio *uio, int ioflag,
+    struct ucred *cred);
+int fuse_io_strategy(struct vnode *vp, struct buf *bp,
+    struct fuse_filehandle *fufh, enum fuse_opcode op);
 
 /*
  * XXX for blocking vnode usage, it seems that changing vnops to dead ones
@@ -60,3 +59,5 @@
 {
 	return (fp->f_vnode && fp->f_data != fp->f_vnode);
 }
+
+#endif /* _FUSE_IO_H_ */

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

@@ -374,30 +374,17 @@
     struct fuse_dispatcher fdi;
     struct fuse_filehandle *fufh;
     struct fuse_vnode_data *fvdat = VTOFUD(vp);
-    int type;
-#if 0
-    int err = 0;
-    int waitfor = ap->a_waitfor;
-    struct timeval tv;
-    int wait = (waitfor == MNT_WAIT);
-#endif
+    int err, type;
+
     fuse_trace_printf_vnop();
 
     if (fuse_isdeadfs_nop(vp)) {
         return 0;
     }
 
-    cluster_push(vp, 0);
+    if ((err = vop_stdfsync(ap)))
+        return (err); 
 
-#if 0
-    buf_flushdirtyblks(vp, wait, 0, (char *)"fuse_fsync");
-    microtime(&tv);
-#endif
-
-    // vnode and ubc are in lock-step.
-    // can call vnode_isinuse().
-    // can call ubc_sync_range().
-
     if (!(fusefs_get_data(vnode_mount(vp))->dataflag &
         (vnode_vtype(vp) == VDIR ? FSESS_NOFSYNCDIR : FSESS_NOFSYNC))) {
         goto out;
@@ -1186,6 +1173,7 @@
          * Doing this here because when a vnode goes inactive, no-cache and
          * no-readahead are cleared by the kernel.
          */
+#ifdef XXXIP
         int dataflag = fusefs_get_data(vnode_mount(vp))->dataflag;
         if (dataflag & FSESS_NO_READAHEAD) {
             vnode_setnoreadahead(vp);
@@ -1193,6 +1181,7 @@
         if (dataflag & FSESS_NO_UBC) {
             vnode_setnocache(vp);
         }
+#endif
     }
 
     return 0;
@@ -1209,66 +1198,18 @@
 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;
-
-    struct fuse_vnode_data *fvdat;
 
     fuse_trace_printf_vnop();
 
     if (fuse_isdeadfs_nop(vp)) {
-        if (vnode_vtype(vp) != VCHR) {
-            return EIO;
-        } else {
-            return 0;
-        }
+        return EIO;
     }
 
-    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;
+    return fuse_io_vnode(vp, uio, ioflag, cred);
 }
 
 /*
@@ -1727,17 +1668,29 @@
 static int
 fuse_vnop_strategy(struct vop_strategy_args *ap)
 {
-	(void)fuse_strategy_i(ap->a_vp, ap->a_bp, NULL, 0);
+    struct vnode *vp = ap->a_vp;
+    struct buf *bp = ap->a_bp;
+
+    fuse_trace_printf_vnop();
+
+    if ((vp == NULL) || (fuse_isdeadfs(vp))) {
+        bp->b_ioflags |= BIO_ERROR;
+        bp->b_error = EIO;
+        bufdone(bp);
+        return EIO;
+    }
+
+    (void)fuse_io_strategy(vp, bp, NULL, 0);
 
-	/* 
-	 * This is a dangerous function. If returns error, that might mean a
-	 * panic. We prefer pretty much anything over being forced to panic by
-	 * a malicious daemon (a demon?). So we just return 0 anyway. You
-	 * should never mind this: this function has its own error propagation
-	 * mechanism via the argument buffer, so not-that-melodramatic
-	 * residents of the call chain still will be able to know what to do.
-	 */
-	return (0);
+    /* 
+     * This is a dangerous function. If returns error, that might mean a
+     * panic. We prefer pretty much anything over being forced to panic by
+     * a malicious daemon (a demon?). So we just return 0 anyway. You
+     * should never mind this: this function has its own error propagation
+     * mechanism via the argument buffer, so not-that-melodramatic
+     * residents of the call chain still will be able to know what to do.
+     */
+    return 0;
 }
 
 
@@ -1798,166 +1751,14 @@
     struct ucred *cred = ap->a_cred;
     struct uio *uio = ap->a_uio;
     int ioflag = ap->a_ioflag;
-    struct fuse_vnode_data *fvdat;
 
-    int          error;
-    int          lflag;
-    off_t        offset;
-    off_t        zero_off;
-    off_t        filesize;
-    off_t        original_offset;
-    off_t        original_size;
-    ssize_t      original_resid;
-
-    /*
-     * XXX: Locking
-     *
-     * lock_shared(truncatelock)
-     * lock(nodelock)
-     * if (file is being extended) {
-     *     unlock(nodelock)
-     *     unlock(truncatelock)
-     *     lock_exclusive(truncatelock)
-     *     lock(nodelock)
-     *     current_size = the file's current size
-     * }
-     * if (file is being extended) { // check again
-     *     // do whatever needs to be done to allocate storage
-     * }
-     * // We are always block-aligned
-     * unlock(nodelock)
-     * call the cluster layer
-     * adjust ubc
-     * lock(nodelock)
-     * do cleanup 
-     * unlock(nodelock)
-     * unlock(truncatelock)
-     */
-
     fuse_trace_printf_vnop();
 
     if (fuse_isdeadfs_nop(vp)) {
         return EIO;
     }
 
-    fvdat = VTOFUD(vp);
-
-    switch (vnode_vtype(vp)) {
-    case VREG:
-        break;
-
-    case VDIR:
-        return EISDIR;
-
-    default:
-        // Wanna panic here?
-        return EPERM; // or EINVAL?
-    }
-
-    original_resid = uio_resid(uio);
-    original_size = fvdat->filesize;
-    original_offset = uio_offset(uio);
-    offset = original_offset;
-
-    if (original_resid == 0) {
-        return 0;
-    }
-
-    if (original_offset < 0) {
-        return EINVAL;
-    }
-
-    // Be wary of a size change here.
-
-    if (ioflag & IO_APPEND) {
-        debug_printf("WRITE: arranging for append\n");
-        uio_setoffset(uio, fvdat->filesize);
-        offset = fvdat->filesize;
-    }
-
-    if (offset < 0)
-        return EFBIG;
-
-#if 0
-    if (original_resid == 0) {
-        return 0;
-    }
-
-    if (offset + original_resid > /* some maximum file size */) {
-        return EFBIG;
-    }
-#endif
-
-    if (offset + original_resid > original_size) {
-        /* Need to extend the file. */
-        debug_printf("WRITE: need to extend the file\n");
-        filesize = offset + original_resid;
-        fvdat->newfilesize = filesize;
-    } else {
-        debug_printf("WRITE: original size OK\n");
-        filesize = original_size;
-        fvdat->newfilesize = filesize;
-    }
-        
-    lflag = (ioflag & IO_SYNC);
-
-    if (offset > original_size) {
-        zero_off = original_size;
-#ifdef XXXIP
-        lflag   |= IO_HEADZEROFILL;
-#endif
-        debug_printf("WRITE: zero filling enabled\n");
-    } else
-        zero_off = 0;
-
-#ifdef XXXIP
-    error = cluster_write(vp, uio, original_size, filesize,
-                          zero_off, 0, lflag);
-#endif
-        
-    if (uio_offset(uio) > fvdat->filesize) {
-        debug_printf("WRITE: updating to new size\n");
-        fvdat->filesize = uio_offset(uio);
-        vnode_pager_setsize(vp, fvdat->filesize);
-        fuse_invalidate_attr(vp);
-    }
-    fvdat->newfilesize = fvdat->filesize;
-
-#if 0
-     if (original_resid > uio_resid(uio)) {
-         dep->de_flag |= DE_UPDATE;
-     }
-#endif
-        
-    /*
-     * If the write failed and they want us to, truncate the file back
-     * to the size it was before the write was attempted.
-     */
-errexit:
-    if (error) {
-        debug_printf("WRITE: we had a failed write (%d)\n", error);
-        if (ioflag & IO_UNIT) {
-#if 0
-            detrunc(dep, original_size, ioflag & IO_SYNC, context);
-#endif
-            uio_setoffset(uio, original_offset);
-            uio_setresid(uio, original_resid);
-        } else {
-#if 0
-            detrunc(dep, dep->de_FileSize, ioflag & IO_SYNC, context);
-#endif
-            if (uio_resid(uio) != original_resid) {
-                error = 0;
-            }
-        }
-    } else if (ioflag & IO_SYNC) {
-#if 0
-        error = deupdat(dep, 1, context);
-#endif
-        ;
-    }
-
-    return error;
+    return fuse_io_vnode(vp, uio, ioflag, cred);
 }
 
 /*
@@ -1973,7 +1774,6 @@
 #define FUSE_PAGEOPS_RESID bp->b_resid
 #endif
 
-#ifdef XXXIP
 /*
     struct vnop_getpages_args {
         struct vnode *a_vp;
@@ -2057,9 +1857,9 @@
 	uio.uio_rw = UIO_READ;
 	uio.uio_td = td;
 
-	error = fuse_io_dispatch(vp, NULL, &uio, cred, FREAD | O_DIRECT, td);
+	error = fuse_io_dispatch(vp, &uio, FREAD | O_DIRECT, cred);
 #else
-	error = fuse_strategy_i(vp, bp, NULL, 0);
+	error = fuse_io_strategy(vp, bp);
 #endif
 	pmap_qremove(kva, npages);
 
@@ -2223,9 +2023,9 @@
 	uio.uio_rw = UIO_WRITE;
 	uio.uio_td = td;
 
-	error = fuse_io_dispatch(vp, NULL, &uio, cred, FWRITE | O_DIRECT, td);
+	error = fuse_io_dispatch(vp, &uio, FWRITE | O_DIRECT, cred);
 #else
-	error = fuse_strategy_i(vp, bp, NULL, 0);
+	error = fuse_io_strategy(vp, bp);
 #endif
 
 	pmap_qremove(kva, npages);
@@ -2241,7 +2041,6 @@
 	return rtvals[0];
 }
 #undef FUSE_PAGEOPS_RESID
-#endif
 
 /*
     struct vnop_print_args {


More information about the p4-projects mailing list