Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 9 Jul 2011 08:59:30 GMT
From:      Ilya Putsikau <ilya@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 195925 for review
Message-ID:  <201107090859.p698xUsI043254@skunkworks.freebsd.org>

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

Change 195925 by ilya@ilya_triton2011 on 2011/07/09 08:59:09

	Rewrite fuse_io_strategy to be similar to NFS.
	Set iosize to PAGE_SIZE (was MAXBSIZE)
	Set file size in fuse_write_directbackend
	Refresh file size before write
	Remove fuse_std_buffeater

Affected files ...

.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_internal.h#17 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.c#16 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.h#9 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.c#15 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.h#15 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vfsops.c#20 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#37 edit

Differences ...

==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_internal.h#17 (text+ko) ====

@@ -130,6 +130,13 @@
     return fuse_isdeadfs_mp(vnode_mount(vp));
 }
 
+static __inline__
+int
+fuse_iosize(struct vnode *vp)
+{
+    return vp->v_mount->mnt_stat.f_iosize;
+}
+
 /* access */
 
 #define FVP_ACCESS_NOOP   0x01

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

@@ -38,27 +38,32 @@
 #include "fuse.h"
 #include "fuse_file.h"
 #include "fuse_node.h"
+#include "fuse_internal.h"
 #include "fuse_ipc.h"
 #include "fuse_io.h"
 
 #define FUSE_DEBUG_MODULE IO
 #include "fuse_debug.h"
 
-static int fuse_read_directbackend(struct fuse_io_data *fioda);
-static int fuse_read_biobackend(struct fuse_io_data *fioda);
-static int fuse_write_directbackend(struct fuse_io_data *fioda);
-static int fuse_write_biobackend(struct fuse_io_data *fioda);
 
-static fuse_buffeater_t fuse_std_buffeater; 
+static int fuse_read_directbackend(struct vnode *vp, struct uio *uio,
+    struct ucred *cred, struct fuse_filehandle *fufh);
+static int fuse_read_biobackend(struct vnode *vp, struct uio *uio,
+    struct ucred *cred, struct fuse_filehandle *fufh);
+static int fuse_write_directbackend(struct vnode *vp, struct uio *uio,
+    struct ucred *cred, struct fuse_filehandle *fufh);
+static int fuse_write_biobackend(struct vnode *vp, struct uio *uio,
+    struct ucred *cred, struct fuse_filehandle *fufh);
 
 int
 fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag,
     struct ucred *cred)
 {
     struct fuse_filehandle *fufh;
-    struct fuse_io_data fioda;
     int err, directio;
 
+    MPASS(vp->v_type == VREG);
+
     err = fuse_filehandle_getrw(vp,
         (uio->uio_rw == UIO_READ) ? FUFH_RDONLY : FUFH_WRONLY, &fufh);
     if (err) {
@@ -66,13 +71,6 @@
         return err;
     }
 
-    bzero(&fioda, sizeof(fioda));
-    fioda.vp = vp;
-    fioda.fufh = fufh;
-    fioda.uio = uio;
-    fioda.cred = cred;
-    fioda.td = curthread;
-
     /*
      * Ideally, when the daemon asks for direct io at open time, the
      * standard file flag should be set according to this, so that would
@@ -87,26 +85,23 @@
 
     switch (uio->uio_rw) {
     case UIO_READ:
-        fioda.opcode = FUSE_READ;
-        fioda.buffeater = fuse_std_buffeater;
-
         if (directio) {
             DEBUG("direct read of vnode %ju via file handle %ju\n",
                 (uintmax_t)VTOILLU(vp), (uintmax_t)fufh->fh_id);
-            err = fuse_read_directbackend(&fioda);
+            err = fuse_read_directbackend(vp, uio, cred, fufh);
         } else {
             DEBUG("buffered read of vnode %ju\n", (uintmax_t)VTOILLU(vp));
-            err = fuse_read_biobackend(&fioda);
+            err = fuse_read_biobackend(vp, uio, cred, fufh);
         }
         break;
     case UIO_WRITE:
         if (directio) {
             DEBUG("direct write of vnode %ju via file handle %ju\n",
                 (uintmax_t)VTOILLU(vp), (uintmax_t)fufh->fh_id);
-            err = fuse_write_directbackend(&fioda);
+            err = fuse_write_directbackend(vp, uio, cred, fufh);
         } else {
             DEBUG("buffered write of vnode %ju\n", (uintmax_t)VTOILLU(vp));
-            err = fuse_write_biobackend(&fioda);
+            err = fuse_write_biobackend(vp, uio, cred, fufh);
         }
         break;
     default:
@@ -119,30 +114,28 @@
 }
 
 static int
-fuse_read_biobackend(struct fuse_io_data *fioda)
+fuse_read_biobackend(struct vnode *vp, struct uio *uio,
+    struct ucred *cred, struct fuse_filehandle *fufh)
 {
-
-    struct vnode *vp = fioda->vp;
-    struct fuse_filehandle *fufh = fioda->fufh;
-    struct uio *uio = fioda->uio;
-    enum fuse_opcode op = fioda->opcode;
-    fuse_buffeater_t *buffe = fioda->buffeater;
-    void *param = fioda->param;
-
-    int biosize;
     struct buf *bp;
     daddr_t lbn;
     int bcount;
-    int bbcount;
     int err = 0, n = 0, on = 0;
+    off_t filesize;
+
+    const int biosize = fuse_iosize(vp);
+
+    DEBUG("resid=%zx offset=%jx fsize=%jx\n",
+        uio->uio_resid, uio->uio_offset, VTOFUD(vp)->filesize);
 
     if (uio->uio_resid == 0)
         return (0);
+    if (uio->uio_offset < 0)
+        return (EINVAL);
 
-    biosize = vp->v_mount->mnt_stat.f_iosize;
     bcount = MIN(MAXBSIZE, biosize);
+    filesize = VTOFUD(vp)->filesize;
 
-    DEBUG2G("entering loop\n");
     do {
         lbn = uio->uio_offset / biosize;
         on = uio->uio_offset & (biosize - 1);
@@ -160,6 +153,11 @@
          *
          * Note that bcount is *not* DEV_BSIZE aligned.
          */
+        if ((off_t)lbn * biosize >= filesize) {
+            bcount = 0;
+        } else if ((off_t)(lbn + 1) * biosize > filesize) {
+            bcount = filesize - (off_t)lbn * biosize;
+        }
 
         bp = getblk(vp, lbn, bcount, PCATCH, 0, 0);
 
@@ -174,7 +172,7 @@
         if ((bp->b_flags & B_CACHE) == 0) {
             bp->b_iocmd = BIO_READ;
             vfs_busy_pages(bp, 0);
-            err = fuse_io_strategy(vp, bp, fufh, op);
+            err = fuse_io_strategy(vp, bp);
             if (err) {
                 brelse(bp);
                 return (err);
@@ -190,43 +188,25 @@
          */
 
         n = 0;
-        /*
-         * If we zero pad the buf, bp->b_resid will be 0, so then
-         * just ignore it
-         */
-        bbcount = bcount - bp->b_resid;
-        if (on < bbcount)
-            n = bbcount - on;
+        if (on < bcount)
+            n = MIN((unsigned)(bcount - on), uio->uio_resid);
         if (n > 0) {
             DEBUG2G("feeding buffeater with %d bytes of buffer %p, saying %d was asked for\n",
                 n, bp->b_data + on, n + (int)bp->b_resid);
-#if 0 && _DEBUG
-            prettyprint(bp->b_data + on, n);
-            printf("\n");
-#endif
-            err = buffe(uio, n + bp->b_resid, bp->b_data + on, n,
-                param);
+	    err = uiomove(bp->b_data + on, n, uio);
         }
         brelse(bp);
         DEBUG2G("end of turn, err %d, uio->uio_resid %zd, n %d\n",
             err, uio->uio_resid, n);
     } while (err == 0 && uio->uio_resid > 0 && n > 0);
 
-    return ((err == -1) ? 0 : err);
+    return (err);
 }
 
 static int
-fuse_read_directbackend(struct fuse_io_data *fioda)
+fuse_read_directbackend(struct vnode *vp, struct uio *uio,
+    struct ucred *cred, struct fuse_filehandle *fufh)
 {
-    struct vnode *vp = fioda->vp;
-    struct fuse_filehandle *fufh = fioda->fufh;
-    struct uio *uio = fioda->uio;
-    struct ucred *cred = fioda->cred;
-    struct thread *td = fioda->td;
-    enum fuse_opcode op = fioda->opcode;
-    fuse_buffeater_t *buffe = fioda->buffeater;
-    void *param = fioda->param;
-
     struct fuse_dispatcher fdi;
     struct fuse_read_in *fri;
     int err = 0;
@@ -234,8 +214,6 @@
     if (uio->uio_resid == 0)
         return (0);
 
-    DEBUG("bug daemon for food\n");
-
     fdisp_init(&fdi, 0);
 
     /*
@@ -248,7 +226,7 @@
      */
     while (uio->uio_resid > 0) {
         fdi.iosize = sizeof(*fri);
-        fdisp_make_vp(&fdi, op, vp, td, cred);
+        fdisp_make_vp(&fdi, FUSE_READ, vp, uio->uio_td, cred);
         fri = fdi.indata;
         fri->fh = fufh->fh_id;
         fri->offset = uio->uio_offset;
@@ -260,48 +238,31 @@
         if ((err = fdisp_wait_answ(&fdi)))
             goto out;
 
-        DEBUG2G("%zd bytes asked for from offset %ju, passing on the %jd we got\n",
-            uio->uio_resid, (uintmax_t)uio->uio_offset, (uintmax_t)fdi.iosize);
+        DEBUG2G("complete: got iosize=%d, requested fri.size=%zd; "
+            "resid=%zd offset=%ju\n",
+            fri->size, fdi.iosize, uio->uio_resid, (uintmax_t)uio->uio_offset);
 
-        if ((err = buffe(uio, fri->size, fdi.answ, fdi.iosize, param)))
+        if ((err = uiomove(fdi.answ, MIN(fri->size, fdi.iosize), uio)))
             break;
+	if (fdi.iosize < fri->size)
+		break;
     }
 
     fuse_ticket_drop(fdi.tick);
 
 out:
-    return ((err == -1) ? 0 : err);
+    return (err);
 }
 
-/* Simple standard way for transmitting input */
 static int
-fuse_std_buffeater(struct uio *uio, size_t reqsize, void *buf, size_t bufsize, void *param)
-{
-    int err;
-
-    if ((err = uiomove(buf, MIN(reqsize, bufsize), uio)))
-        return (err);
-
-    if (bufsize < reqsize)
-        return (-1);
-
-    return (0);
-}
-
-
-static int
-fuse_write_directbackend(struct fuse_io_data *fioda)
+fuse_write_directbackend(struct vnode *vp, struct uio *uio,
+    struct ucred *cred, struct fuse_filehandle *fufh)
 {	
-    struct vnode *vp = fioda->vp;
-    uint64_t fh_id = fioda->fufh->fh_id;
-    struct uio *uio = fioda->uio;
-    struct ucred *cred = fioda->cred;
-    struct thread *td = fioda->td;
-
+    struct fuse_vnode_data *fvdat = VTOFUD(vp);
+    struct fuse_write_in *fwi;
+    struct fuse_dispatcher fdi;
     size_t chunksize;
     int diff;
-    struct fuse_write_in *fwi;
-    struct fuse_dispatcher fdi;
     int err = 0;
 
     if (! uio->uio_resid)
@@ -314,10 +275,10 @@
             fuse_get_mpdata(vp->v_mount)->max_write);
 
         fdi.iosize = sizeof(*fwi) + chunksize;
-        fdisp_make_vp(&fdi, FUSE_WRITE, vp, td, cred);
+        fdisp_make_vp(&fdi, FUSE_WRITE, vp, uio->uio_td, cred);
 
         fwi = fdi.indata;
-        fwi->fh = fh_id;
+        fwi->fh = fufh->fh_id;
         fwi->offset = uio->uio_offset;
         fwi->size = chunksize;
 
@@ -336,6 +297,8 @@
 
         uio->uio_resid += diff;
         uio->uio_offset -= diff; 
+        if (uio->uio_offset > fvdat->filesize)
+            fuse_vnode_setsize(vp, uio->uio_offset);
     }
 
     fuse_ticket_drop(fdi.tick);
@@ -344,23 +307,26 @@
 }
 
 static int
-fuse_write_biobackend(struct fuse_io_data *fioda)
+fuse_write_biobackend(struct vnode *vp, struct uio *uio,
+    struct ucred *cred, struct fuse_filehandle *fufh)
 {
-    struct vnode *vp = fioda->vp;
-    struct uio *uio = fioda->uio;
-    struct ucred *cred = fioda->cred;
     struct fuse_vnode_data *fvdat = VTOFUD(vp);
-
-    int biosize;
-
     struct buf *bp;
     daddr_t lbn;
     int bcount;
     int n, on, err = 0;
 
-    DEBUG2G("fsize %ju\n", (uintmax_t)fvdat->filesize);
+    const int biosize = fuse_iosize(vp);
 
-    biosize = vp->v_mount->mnt_stat.f_iosize;
+    KASSERT(uio->uio_rw == UIO_WRITE, ("ncl_write mode"));
+    DEBUG("resid=%zx offset=%jx fsize=%jx\n",
+        uio->uio_resid, uio->uio_offset, fvdat->filesize);
+    if (vp->v_type != VREG)
+        return (EIO);
+    if (uio->uio_offset < 0)
+        return (EINVAL);
+    if (uio->uio_resid == 0)
+        return (0);
 
     /*
      * Find all of this file's B_NEEDCOMMIT buffers.  If our writes
@@ -383,7 +349,6 @@
          * Handle direct append and file extension cases, calculate
          * unaligned buffer size.
          */
-
         if (uio->uio_offset == fvdat->filesize && n) {
             /*
              * Get the buffer (in its pre-append state to maintain
@@ -457,7 +422,7 @@
         if ((bp->b_flags & B_CACHE) == 0) {
             bp->b_iocmd = BIO_READ;
             vfs_busy_pages(bp, 0);
-            fuse_io_strategy(vp, bp, NULL, 0);
+            fuse_io_strategy(vp, bp);
             if ((err = bp->b_error)) {
                 brelse(bp);
                 break;
@@ -476,7 +441,7 @@
          */
 
         if (bp->b_dirtyend > bcount) {
-            DEBUG("Fuse append race @%lx:%d\n",
+            DEBUG("FUSE append race @%lx:%d\n",
                 (long)bp->b_blkno * biosize,
                 bp->b_dirtyend - bcount);
             bp->b_dirtyend = bcount;
@@ -550,8 +515,8 @@
             vfs_bio_set_valid(bp, on, n);
         }
 
-        bwrite(bp);
-        if ((err =  bp->b_error))
+        err = bwrite(bp);
+        if (err)
             break;
     } while (uio->uio_resid > 0 && n > 0);
 
@@ -559,31 +524,42 @@
 }
 
 int
-fuse_io_strategy(struct vnode *vp, struct buf *bp, struct fuse_filehandle *fufh,
-    enum fuse_opcode op)
+fuse_io_strategy(struct vnode *vp, struct buf *bp)
 {
+    struct fuse_filehandle *fufh;
     struct fuse_vnode_data *fvdat = VTOFUD(vp);
-    struct fuse_dispatcher fdi;
-    struct ucred *cred; 
-    int err = 0;
-    int chunksize, respsize;
-    caddr_t bufdat;
-    int biosize = vp->v_mount->mnt_stat.f_iosize;
+    struct ucred *cred;
+    struct uio *uiop;
+    struct uio uio;
+    struct iovec io;
+    int error = 0;
+
+    const int biosize = fuse_iosize(vp);
+
+    MPASS(vp->v_type == VREG);
+    MPASS(bp->b_iocmd == BIO_READ || bp->b_iocmd == BIO_WRITE);
+    DEBUG("inode=%jd offset=%jd resid=%jd\n",
+        VTOI(vp), ((off_t)bp->b_blkno) * biosize, bp->b_bcount);
 
-    if (! (vp->v_type == VREG || vp->v_type == VDIR)) {
-        DEBUG("for vnode #%ju v_type is %d, dropping\n",
-            (uintmax_t)VTOILLU(vp), vp->v_type);
-        return (EOPNOTSUPP);
+    error = fuse_filehandle_getrw(vp,
+	(bp->b_iocmd == BIO_READ) ? FUFH_RDONLY : FUFH_WRONLY, &fufh);
+    if (error) {
+        DEBUG("fetching filehandle failed\n");
+        bp->b_ioflags |= BIO_ERROR;
+        bp->b_error = error;
+        return (error);
     }
 
-    if (bp->b_iocmd != BIO_READ && bp->b_iocmd != BIO_WRITE) {
-        DEBUG("for vnode #%ju bio tried with biocmd %#x, dropping\n",
-            (uintmax_t)VTOILLU(vp), bp->b_iocmd);
-        return (EOPNOTSUPP);
-    }
+    cred = bp->b_iocmd == BIO_READ ? bp->b_rcred : bp->b_wcred;
+
+    uiop = &uio;
+    uiop->uio_iov = &io;
+    uiop->uio_iovcnt = 1;
+    uiop->uio_segflg = UIO_SYSSPACE;
+    uiop->uio_td = curthread;
 
     /*
-     * clear BIO_ERROR and B_INVAL state prior to initiating the I/O. We
+     * clear BIO_ERROR and B_INVAL state prior to initiating the I/O.  We
      * do this here so we do not have to do it in all the code that
      * calls us.
      */
@@ -591,157 +567,85 @@
     bp->b_ioflags &= ~BIO_ERROR;
 
     KASSERT(!(bp->b_flags & B_DONE),
-        ("fuse_strategy: bp %p already marked done", bp));
-
-    if (bp->b_bcount == 0)
-        return (0);
-
-    cred = bp->b_iocmd == BIO_READ ? bp->b_rcred : bp->b_wcred;
-
-    err = fuse_filehandle_getrw(vp,
-	(bp->b_iocmd == BIO_READ) ? FUFH_RDONLY : FUFH_WRONLY, &fufh);
-    if (err) {
-        DEBUG("fetching filehandle failed\n");
-        goto out;
-    }
-
-    DEBUG2G("vp #%ju, fufh #%ju\n",
-	(uintmax_t)VTOILLU(vp), (uintmax_t)fufh->fh_id);
-
-    fdisp_init(&fdi, 0);
-
+        ("fuse_io_strategy: bp %p already marked done", bp));
     if (bp->b_iocmd == BIO_READ) {
-        struct fuse_read_in *fri;
-        int ioff = 0;
+        io.iov_len = uiop->uio_resid = bp->b_bcount;
+        io.iov_base = bp->b_data;
+        uiop->uio_rw = UIO_READ;
 
-        bufdat = bp->b_data;
-        bp->b_resid = bp->b_bcount;
-        while (bp->b_resid > 0) {
-            DEBUG2G("starting bio with resid %ld\n", bp->b_resid);	
-            chunksize = MIN(bp->b_resid,
-                fuse_get_mpdata(vp->v_mount)->max_read);
-            fdi.iosize = sizeof(*fri);
-            if (! op)
-                op = vp->v_type == VDIR ? FUSE_READDIR : FUSE_READ;
-            fdisp_make_vp(&fdi, op, vp, curthread, cred);
+        uiop->uio_offset = ((off_t)bp->b_blkno) * biosize;
+        error = fuse_read_directbackend(vp, uiop, cred, fufh);
 
-            fri = fdi.indata;
-            fri->fh = fufh->fh_id;
-            fri->offset = ((off_t)bp->b_blkno) * biosize + ioff;
-            chunksize = MIN(chunksize,
-                MIN(fri->offset + bp->b_resid,
-                fvdat->filesize) - fri->offset);
-            if (chunksize == 0) {
-                respsize = -1;
-                goto eval;
-            }
-            fri->size = chunksize;
-            fdi.tick->tk_aw_type = FT_A_BUF;
-            fdi.tick->tk_aw_bufdata = bufdat;
+        if (!error && uiop->uio_resid) {
+            /*
+             * If we had a short read with no error, we must have
+             * hit a file hole.  We should zero-fill the remainder.
+             * This can also occur if the server hits the file EOF.
+             *
+             * Holes used to be able to occur due to pending
+             * writes, but that is not possible any longer.
+             */
+            int nread = bp->b_bcount - uiop->uio_resid;
+            int left  = uiop->uio_resid;
 
-            DEBUG("waiting for answer\n");
-            if ((err = fdisp_wait_answ(&fdi)))
-                goto out;
-
-            respsize = fdi.tick->tk_aw_bufsize;
-            DEBUG2G("chunksize %d, respsize %d, bp->b_resid %ld, bp->b_bcount %ld\n",
-                chunksize, respsize, bp->b_resid, bp->b_bcount);
-            bp->b_resid -= respsize;
-            bufdat += respsize;
-            ioff += respsize;
-
-eval:
-            DEBUG2G("%d bytes asked for from offset %llu, passing on the %d we got\n",
-                chunksize, (long long unsigned)fri->offset, respsize);
-
-            if (respsize < chunksize) {
-                /*
-                 * if we don't get enough data, just fill the
-                 * rest with zeros.
-                 */ 
-                DEBUG("zeroing tail of %ld bytes\n",
-                    bp->b_resid);
-                bzero((char *)bp->b_data + bp->b_bcount - bp->b_resid,
-                    bp->b_resid);
-                if (chunksize)
-                    bp->b_resid = 0;
-                break;
-            }
-            if (respsize > chunksize) {
-                fuse_ticket_drop(fdi.tick);
-                err = EINVAL;
-                goto out;
-            }
-            DEBUG("bp->b_data %p\n", bp->b_data);
+            if (left > 0)
+                bzero((char *)bp->b_data + nread, left);
+            uiop->uio_resid = 0;
+        }
+        if (error) {
+            bp->b_ioflags |= BIO_ERROR;
+            bp->b_error = error;
         }
     } else {
-        struct fuse_write_in *fwi;
-        struct fuse_write_out *fwo;
-        int diff;
-        int merr = 0;
+        /*
+         * If we only need to commit, try to commit
+         */
+        if (bp->b_flags & B_NEEDCOMMIT) {
+            DEBUG("write: B_NEEDCOMMIT flags set\n");
+        }
 
-        bufdat = bp->b_data + bp->b_dirtyoff;
-        while (bp->b_dirtyend > bp->b_dirtyoff) {
-            chunksize = MIN(bp->b_dirtyend - bp->b_dirtyoff,
-                fuse_get_mpdata(vp->v_mount)->max_write);
+        /*
+         * Setup for actual write
+         */
+        if ((off_t)bp->b_blkno * biosize + bp->b_dirtyend > fvdat->filesize)
+            bp->b_dirtyend = fvdat->filesize - (off_t)bp->b_blkno * biosize;
 
-            fdi.iosize = sizeof(*fwi);
-            op = op ?: FUSE_WRITE;
-            fdisp_make_vp(&fdi, op, vp, NULL, cred);
+        if (bp->b_dirtyend > bp->b_dirtyoff) {
+            io.iov_len = uiop->uio_resid = bp->b_dirtyend
+              - bp->b_dirtyoff;
+            uiop->uio_offset = (off_t)bp->b_blkno * biosize
+              + bp->b_dirtyoff;
+            io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
+            uiop->uio_rw = UIO_WRITE;
 
-            fwi = fdi.indata;
-            fwi->fh = fufh->fh_id;
-            fwi->offset = (off_t)bp->b_blkno * biosize + bp->b_dirtyoff;
-            fwi->size = chunksize;
-            fdi.tick->tk_ms_type = FT_M_BUF;
-            fdi.tick->tk_ms_bufdata = bufdat;
-            fdi.tick->tk_ms_bufsize = chunksize;
+            error = fuse_write_directbackend(vp, uiop, cred, fufh);
 
-            if ((err = fdisp_wait_answ(&fdi))) {
-                merr = 1;
-                break;
-            }
+            if (error == EINTR || error == ETIMEDOUT
+                || (!error && (bp->b_flags & B_NEEDCOMMIT))) {
 
-            fwo = fdi.answ;
-            diff = chunksize - fwo->size;
-            if (diff < 0) {
-                err = EINVAL;
-                break;
+                bp->b_flags &= ~(B_INVAL|B_NOCACHE);
+                if ((bp->b_flags & B_PAGING) == 0) {
+                    bdirty(bp);
+                    bp->b_flags &= ~B_DONE;
+                }
+                if ((error == EINTR || error == ETIMEDOUT) &&
+                    (bp->b_flags & B_ASYNC) == 0)
+                    bp->b_flags |= B_EINTR;
+            } else {
+                if (error) {
+                    bp->b_ioflags |= BIO_ERROR;
+                    bp->b_flags |= B_INVAL;
+                    bp->b_error = error;
+                }
+                bp->b_dirtyoff = bp->b_dirtyend = 0;
             }
-            if (diff > 0) {
-                /*
-                 * Tolerating a short read would mean
-                 * keeping dirty data around and we
-                 * don't do that.
-                 */
-                err = EIO;
-                break;
-            }
-
-            bp->b_dirtyoff += fwo->size; 
+        } else {
+            bp->b_resid = 0;
+            bufdone(bp);
+            return (0);
         }
-
-        if (bp->b_dirtyend == bp->b_dirtyoff)
-            bp->b_dirtyend = bp->b_dirtyoff = 0;
-
-        bp->b_resid = bp->b_dirtyend - bp->b_dirtyoff;
-
-        if (merr)
-            goto out;
     }
-
-    if (fdi.tick)
-        fuse_ticket_drop(fdi.tick);
-    else
-        DEBUG("no ticket on leave\n");
-
-out:
-    if (err) {
-        bp->b_ioflags |= BIO_ERROR;
-        bp->b_error = err;
-    }
-    DEBUG("calling bufdone\n");      
+    bp->b_resid = uiop->uio_resid;
     bufdone(bp);
-
-    return (err);
-}	
+    return (error);
+}

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

@@ -1,26 +1,8 @@
 #ifndef _FUSE_IO_H_
 #define _FUSE_IO_H_
 
-/* prototype for processing an input data buffer and an uio
-   for reading related acivities */
-typedef	int fuse_buffeater_t(struct uio *uio, size_t reqsize,
-    void *buf, size_t bufsize, void *param);
-
-/* data used through an I/O operation */
-struct fuse_io_data {
-    struct vnode *vp;
-    struct fuse_filehandle *fufh;
-    struct uio *uio;
-    struct ucred *cred;
-    struct thread *td;
-    enum fuse_opcode opcode;
-    fuse_buffeater_t *buffeater;
-    void *param;
-};
-
 int fuse_io_dispatch(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);
+int fuse_io_strategy(struct vnode *vp, struct buf *bp);
 
 #endif /* _FUSE_IO_H_ */

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

@@ -33,6 +33,7 @@
 #include "fuse.h"
 #include "fuse_node.h"
 #include "fuse_internal.h"
+#include "fuse_io.h"
 #include "fuse_ipc.h"
 
 #define FUSE_DEBUG_MODULE VNOPS
@@ -228,6 +229,18 @@
 }
 
 void
+fuse_vnode_refreshsize(struct vnode *vp, struct ucred *cred)
+{
+    struct vattr va;
+
+    if (fuse_isvalid_attr(vp))
+        return;
+
+    VOP_GETATTR(vp, &va, cred);
+    DEBUG("refreshed file size: %jd\n", VTOFUD(vp)->filesize);
+}
+
+void
 fuse_vnode_setsize(struct vnode *vp, off_t newsize)
 {
     struct fuse_vnode_data *fvdat = VTOFUD(vp);

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

@@ -103,6 +103,8 @@
                      int32_t fuse_open_flags,
                      struct thread *td);
 
+void fuse_vnode_refreshsize(struct vnode *vp, struct ucred *cred);
+
 void fuse_vnode_setsize(struct vnode *vp, off_t newsize);
 
 #endif /* _FUSE_NODE_H_ */

==== //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vfsops.c#20 (text+ko) ====

@@ -241,7 +241,7 @@
     }
 
     /* We need this here as this slot is used by getnewvnode() */
-    mp->mnt_stat.f_iosize = MAXBSIZE;
+    mp->mnt_stat.f_iosize = PAGE_SIZE;
 
     mp->mnt_data = data;
 

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

@@ -1737,7 +1737,10 @@
         return EIO;
     }
 
-    (void)fuse_io_strategy(vp, bp, NULL, 0);
+    if (bp->b_iocmd == BIO_WRITE)
+	    fuse_vnode_refreshsize(vp, NOCRED);
+
+    (void)fuse_io_strategy(vp, bp);
 
     /* 
      * This is a dangerous function. If returns error, that might mean a
@@ -1827,6 +1830,8 @@
         return EIO;
     }
 
+    fuse_vnode_refreshsize(vp, cred);
+
     return fuse_io_dispatch(vp, uio, ioflag, cred);
 }
 



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