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