Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 9 Jul 2011 09:02:46 GMT
From:      Ilya Putsikau <ilya@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 195926 for review
Message-ID:  <201107090902.p6992kqQ044935@skunkworks.freebsd.org>

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

Change 195926 by ilya@ilya_triton2011 on 2011/07/09 09:02:07

	Truncate vnode buffers in fuse_vnode_setsize
	Set new size before extending file
	Flush vnode buffers before close

Affected files ...

.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.c#17 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_io.h#10 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.c#16 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_node.h#16 edit
.. //depot/projects/soc2011/ilya_fuse/fuse_module/fuse_vnops.c#38 edit

Differences ...

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

@@ -298,7 +298,7 @@
         uio->uio_resid += diff;
         uio->uio_offset -= diff; 
         if (uio->uio_offset > fvdat->filesize)
-            fuse_vnode_setsize(vp, uio->uio_offset);
+            fuse_vnode_setsize(vp, cred, uio->uio_offset);
     }
 
     fuse_ticket_drop(fdi.tick);
@@ -363,7 +363,7 @@
             if (bp != NULL) {
                 long save;
 
-		fuse_vnode_setsize(vp, uio->uio_offset + n);
+		fuse_vnode_extend(vp, cred, uio->uio_offset + n);
 
                 save = bp->b_flags & B_CACHE;
                 bcount += n;
@@ -385,7 +385,7 @@
             DEBUG("getting block from OS, bcount %d\n", bcount);
             bp = getblk(vp, lbn, bcount, PCATCH, 0, 0);
             if (uio->uio_offset + n > fvdat->filesize) {
-                fuse_vnode_setsize(vp, uio->uio_offset + n);
+		fuse_vnode_extend(vp, cred, uio->uio_offset + n);
             }
         }
 
@@ -649,3 +649,63 @@
     bufdone(bp);
     return (error);
 }
+
+/*
+ * Flush and invalidate all dirty buffers. If another process is already
+ * doing the flush, just wait for completion.
+ */
+int
+fuse_io_invalbuf(struct vnode *vp, struct thread *td)
+{
+	struct fuse_vnode_data *fvdat = VTOFUD(vp);
+	int error = 0;
+
+	if (vp->v_iflag & VI_DOOMED)
+		return 0;
+
+	ASSERT_VOP_ELOCKED(vp, "fuse_io_invalbuf");
+
+	while (fvdat->flag & FN_FLUSHINPROG) {
+		struct proc *p = td->td_proc;
+		if (vp->v_mount->mnt_kern_flag & MNTK_UNMOUNTF)
+			return EIO;
+		fvdat->flag |= FN_FLUSHWANT;
+		tsleep(&fvdat->flag, PRIBIO + 2, "fusevinv", 2 * hz);
+		error = 0;
+		if (p != NULL) {
+			PROC_LOCK(p);
+			if (SIGNOTEMPTY(p->p_siglist) ||
+			    SIGNOTEMPTY(td->td_siglist))
+			    error = EINTR;
+			PROC_UNLOCK(p);
+		}
+		if (error == EINTR)
+			return EINTR;
+	}
+	fvdat->flag |= FN_FLUSHINPROG;
+
+	if (vp->v_bufobj.bo_object != NULL) {
+		VM_OBJECT_LOCK(vp->v_bufobj.bo_object);
+		vm_object_page_clean(vp->v_bufobj.bo_object, 0, 0, OBJPC_SYNC);
+		VM_OBJECT_UNLOCK(vp->v_bufobj.bo_object);
+	}
+
+	error = vinvalbuf(vp, V_SAVE, PCATCH, 0);
+	while (error) {
+		if (error == ERESTART || error == EINTR) {
+			fvdat->flag &= ~FN_FLUSHINPROG;
+			if (fvdat->flag & FN_FLUSHWANT) {
+				fvdat->flag &= ~FN_FLUSHWANT;
+				wakeup(&fvdat->flag);
+			}
+			return EINTR;
+		}
+		error = vinvalbuf(vp, V_SAVE, PCATCH, 0);
+	}
+	fvdat->flag &= ~FN_FLUSHINPROG;
+	if (fvdat->flag & FN_FLUSHWANT) {
+		fvdat->flag &= ~FN_FLUSHWANT;
+		wakeup(&fvdat->flag);
+	}
+	return (error);
+}

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

@@ -4,5 +4,6 @@
 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);
+int fuse_io_invalbuf(struct vnode *vp, struct thread *td);
 
 #endif /* _FUSE_IO_H_ */

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

@@ -228,6 +228,68 @@
     return fuse_timespec_cmp(&uptsp, &fvdat->cached_attrs_valid, <=);
 }
 
+int
+fuse_vnode_extend(struct vnode *vp, struct ucred *cred, off_t newsize)
+{
+    struct thread *td = curthread;
+    struct fuse_filehandle *fufh = NULL;
+    struct fuse_dispatcher  fdi;
+    struct fuse_setattr_in *fsai;
+    struct fuse_access_param facp;
+    int err = 0;
+
+    DEBUG("inode=%jd oldsize=%jd newsize=%jd\n",
+        VTOI(vp), VTOFUD(vp)->filesize, newsize);
+    ASSERT_VOP_ELOCKED(vp, "fuse_io_extend");
+    MPASS(newsize > VTOFUD(vp)->filesize);
+
+    if (fuse_isdeadfs(vp)) {
+        return EBADF;
+    }
+
+    if (vnode_vtype(vp) == VDIR) {
+        return EISDIR;
+    }
+
+    if (vfs_isrdonly(vnode_mount(vp))) {
+        return EROFS;
+    }
+
+    if (cred == NULL) {
+        cred = td->td_ucred;
+    }
+
+    fdisp_init(&fdi, sizeof(*fsai));
+    fdisp_make_vp(&fdi, FUSE_SETATTR, vp, td, cred);
+    fsai = fdi.indata;
+    fsai->valid = 0;
+
+    bzero(&facp, sizeof(facp));
+    facp.xuid = cred->cr_uid;
+    facp.xgid = cred->cr_gid;
+
+    // Truncate to a new value.
+    fsai->size = newsize;
+    fsai->valid |= FATTR_SIZE;
+
+    fuse_filehandle_getrw(vp, FUFH_WRONLY, &fufh);
+    if (fufh) {
+        fsai->fh = fufh->fh_id;
+        fsai->valid |= FATTR_FH;
+    }
+
+    err = fdisp_wait_answ(&fdi);
+
+    fuse_ticket_drop(fdi.tick);
+
+    fuse_invalidate_attr(vp);
+    if (!err) {
+        fuse_vnode_setsize(vp, cred, newsize);
+    }
+
+    return err;
+}
+
 void
 fuse_vnode_refreshsize(struct vnode *vp, struct ucred *cred)
 {
@@ -241,10 +303,22 @@
 }
 
 void
-fuse_vnode_setsize(struct vnode *vp, off_t newsize)
+fuse_vnode_setsize(struct vnode *vp, struct ucred *cred, off_t newsize)
 {
     struct fuse_vnode_data *fvdat = VTOFUD(vp);
+    off_t oldsize;
+
+    DEBUG("inode=%jd oldsize=%jd newsize=%jd\n",
+        VTOI(vp), fvdat->filesize, newsize);
+    ASSERT_VOP_ELOCKED(vp, "fuse_vnode_setsize");
 
+    oldsize = fvdat->filesize;
+    fvdat->filesize = newsize;
+
+    if (newsize < oldsize) {
+        vtruncbuf(vp, cred, curthread, newsize, fuse_iosize(vp));
+    }
+
     vnode_pager_setsize(vp, newsize);
-    fvdat->filesize = newsize;
+    fuse_invalidate_attr(vp);
 }

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

@@ -13,6 +13,8 @@
 
 #define FN_CREATING          0x00000002
 #define FN_REVOKED           0x00000020
+#define FN_FLUSHINPROG       0x00000040
+#define FN_FLUSHWANT         0x00000080
 
 struct fuse_vnode_data {
     /** self **/
@@ -103,8 +105,10 @@
                      int32_t fuse_open_flags,
                      struct thread *td);
 
+int fuse_vnode_extend(struct vnode *vp, struct ucred *cred, off_t newsize);
+
 void fuse_vnode_refreshsize(struct vnode *vp, struct ucred *cred);
 
-void fuse_vnode_setsize(struct vnode *vp, off_t newsize);
+void fuse_vnode_setsize(struct vnode *vp, struct ucred *cred, off_t newsize);
 
 #endif /* _FUSE_NODE_H_ */

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

@@ -522,7 +522,7 @@
         off_t new_filesize = ((struct fuse_attr_out *)fdi.answ)->attr.size;
 
         if (fvdat->filesize != new_filesize) {
-            fuse_vnode_setsize(vp, new_filesize);
+            fuse_vnode_setsize(vp, cred, new_filesize);
         }
     }
 
@@ -574,13 +574,17 @@
     struct fuse_vnode_data *fvdat = VTOFUD(vp);
     struct fuse_filehandle *fufh = NULL;
 
-    int type;
+    int type, need_invalbuf = 1;
 
     DEBUG("inode=%jd\n", (uintmax_t)VTOI(vp));
 
     for (type = 0; type < FUFH_MAXTYPE; type++) {
         fufh = &(fvdat->fufh[type]);
         if (FUFH_IS_VALID(fufh)) {
+            if (need_invalbuf) {
+                fuse_io_invalbuf(vp, td);
+                need_invalbuf = 0;
+            }
             fuse_filehandle_close(vp, type, td, NULL, FUSE_OP_BACKGROUNDED);
         }
     }
@@ -1710,7 +1714,7 @@
     fuse_ticket_drop(fdi.tick);
     if (!err && sizechanged) {
         fuse_invalidate_attr(vp);
-        fuse_vnode_setsize(vp, newsize);
+        fuse_vnode_setsize(vp, cred, newsize);
     }
 
     return err;



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