PERFORCE change 195926 for review
Ilya Putsikau
ilya at FreeBSD.org
Sat Jul 9 09:02:47 UTC 2011
http://p4web.freebsd.org/@@195926?ac=10
Change 195926 by ilya at 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;
More information about the p4-projects
mailing list