From owner-p4-projects@FreeBSD.ORG Mon Jun 13 15:41:25 2011 Return-Path: <owner-p4-projects@FreeBSD.ORG> Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 2A9CE1065680; Mon, 13 Jun 2011 15:41:25 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E0D3E106567B for <perforce@FreeBSD.org>; Mon, 13 Jun 2011 15:41:24 +0000 (UTC) (envelope-from ilya@FreeBSD.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id CBA558FC14 for <perforce@FreeBSD.org>; Mon, 13 Jun 2011 15:41:24 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id p5DFfOoB076351 for <perforce@FreeBSD.org>; Mon, 13 Jun 2011 15:41:24 GMT (envelope-from ilya@FreeBSD.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id p5DFfOQ1076347 for perforce@freebsd.org; Mon, 13 Jun 2011 15:41:24 GMT (envelope-from ilya@FreeBSD.org) Date: Mon, 13 Jun 2011 15:41:24 GMT Message-Id: <201106131541.p5DFfOQ1076347@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to ilya@FreeBSD.org using -f From: Ilya Putsikau <ilya@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Precedence: bulk Cc: Subject: PERFORCE change 194689 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes <p4-projects.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/listinfo/p4-projects>, <mailto:p4-projects-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/p4-projects> List-Post: <mailto:p4-projects@freebsd.org> List-Help: <mailto:p4-projects-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/p4-projects>, <mailto:p4-projects-request@freebsd.org?subject=subscribe> X-List-Received-Date: Mon, 13 Jun 2011 15:41:25 -0000 http://p4web.freebsd.org/@@194689?ac=10 Change 194689 by ilya@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 {