xref: /dflybsd-src/sys/vfs/fuse/fuse_io.c (revision 5d0d0bafbc717a20af3abdbf6366fee0ae276685)
15812c3ccSTomohiro Kusumi /*-
25812c3ccSTomohiro Kusumi  * Copyright (c) 2019 Tomohiro Kusumi <tkusumi@netbsd.org>
35812c3ccSTomohiro Kusumi  * Copyright (c) 2019 The DragonFly Project
45812c3ccSTomohiro Kusumi  * All rights reserved.
55812c3ccSTomohiro Kusumi  *
65812c3ccSTomohiro Kusumi  * Redistribution and use in source and binary forms, with or without
75812c3ccSTomohiro Kusumi  * modification, are permitted provided that the following conditions
85812c3ccSTomohiro Kusumi  * are met:
95812c3ccSTomohiro Kusumi  * 1. Redistributions of source code must retain the above copyright
105812c3ccSTomohiro Kusumi  *    notice, this list of conditions and the following disclaimer.
115812c3ccSTomohiro Kusumi  * 2. Redistributions in binary form must reproduce the above copyright
125812c3ccSTomohiro Kusumi  *    notice, this list of conditions and the following disclaimer in the
135812c3ccSTomohiro Kusumi  *    documentation and/or other materials provided with the distribution.
145812c3ccSTomohiro Kusumi  *
155812c3ccSTomohiro Kusumi  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
165812c3ccSTomohiro Kusumi  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
175812c3ccSTomohiro Kusumi  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
185812c3ccSTomohiro Kusumi  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
195812c3ccSTomohiro Kusumi  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
205812c3ccSTomohiro Kusumi  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
215812c3ccSTomohiro Kusumi  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
225812c3ccSTomohiro Kusumi  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
235812c3ccSTomohiro Kusumi  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
245812c3ccSTomohiro Kusumi  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
255812c3ccSTomohiro Kusumi  * SUCH DAMAGE.
265812c3ccSTomohiro Kusumi  */
275812c3ccSTomohiro Kusumi 
285812c3ccSTomohiro Kusumi #include "fuse.h"
295812c3ccSTomohiro Kusumi 
305812c3ccSTomohiro Kusumi #include <sys/uio.h>
315812c3ccSTomohiro Kusumi #include <sys/buf2.h>
325812c3ccSTomohiro Kusumi 
33*5d0d0bafSMatthew Dillon #if 0
345812c3ccSTomohiro Kusumi static void
355812c3ccSTomohiro Kusumi fuse_fix_size(struct fuse_node *fnp, bool fixsize, size_t oldsize)
365812c3ccSTomohiro Kusumi {
375812c3ccSTomohiro Kusumi 	if (fixsize)
385812c3ccSTomohiro Kusumi 		fuse_node_truncate(fnp, fnp->size, oldsize);
395812c3ccSTomohiro Kusumi }
40*5d0d0bafSMatthew Dillon #endif
415812c3ccSTomohiro Kusumi 
42*5d0d0bafSMatthew Dillon #if 0
435812c3ccSTomohiro Kusumi int
445812c3ccSTomohiro Kusumi fuse_read(struct vop_read_args *ap)
455812c3ccSTomohiro Kusumi {
465812c3ccSTomohiro Kusumi 	struct vnode *vp = ap->a_vp;
475812c3ccSTomohiro Kusumi 	struct uio *uio = ap->a_uio;
485812c3ccSTomohiro Kusumi 	struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
495812c3ccSTomohiro Kusumi 	struct fuse_node *fnp = VTOI(vp);
505812c3ccSTomohiro Kusumi 	bool need_reopen = !curproc || fnp->closed; /* XXX */
515812c3ccSTomohiro Kusumi 	int error = 0;
525812c3ccSTomohiro Kusumi 
535812c3ccSTomohiro Kusumi 	while (uio->uio_resid > 0 && uio->uio_offset < fnp->size) {
545812c3ccSTomohiro Kusumi 		struct file *fp;
555812c3ccSTomohiro Kusumi 		struct buf *bp;
565812c3ccSTomohiro Kusumi 		struct fuse_ipc *fip;
575812c3ccSTomohiro Kusumi 		struct fuse_read_in *fri;
585812c3ccSTomohiro Kusumi 		off_t base_offset, buf_offset;
595812c3ccSTomohiro Kusumi 		size_t len;
605812c3ccSTomohiro Kusumi 		uint64_t fh;
615812c3ccSTomohiro Kusumi 
625812c3ccSTomohiro Kusumi 		fh = fuse_nfh(VTOI(vp));
635812c3ccSTomohiro Kusumi 		if (ap->a_fp)
645812c3ccSTomohiro Kusumi 			fh = fuse_fh(ap->a_fp);
655812c3ccSTomohiro Kusumi 
665812c3ccSTomohiro Kusumi 		buf_offset = (off_t)uio->uio_offset & FUSE_BLKMASK64;
675812c3ccSTomohiro Kusumi 		base_offset = (off_t)uio->uio_offset - buf_offset;
685812c3ccSTomohiro Kusumi 
695812c3ccSTomohiro Kusumi 		fuse_dbg("uio_offset=%ju uio_resid=%ju base_offset=%ju "
705812c3ccSTomohiro Kusumi 		    "buf_offset=%ju\n",
715812c3ccSTomohiro Kusumi 		    uio->uio_offset, uio->uio_resid, base_offset, buf_offset);
725812c3ccSTomohiro Kusumi 
735812c3ccSTomohiro Kusumi 		bp = getblk(vp, base_offset, FUSE_BLKSIZE, 0, 0);
745812c3ccSTomohiro Kusumi 		KKASSERT(bp);
755812c3ccSTomohiro Kusumi 		if ((bp->b_flags & (B_INVAL | B_CACHE | B_RAM)) == B_CACHE) {
765812c3ccSTomohiro Kusumi 			bp->b_flags &= ~B_AGE;
775812c3ccSTomohiro Kusumi 			goto skip;
785812c3ccSTomohiro Kusumi 		}
795812c3ccSTomohiro Kusumi 		if (ap->a_ioflag & IO_NRDELAY) {
805812c3ccSTomohiro Kusumi 			bqrelse(bp);
815812c3ccSTomohiro Kusumi 			return EWOULDBLOCK;
825812c3ccSTomohiro Kusumi 		}
835812c3ccSTomohiro Kusumi 
845812c3ccSTomohiro Kusumi 		error = breadnx(vp, base_offset, FUSE_BLKSIZE, B_NOTMETA, NULL,
855812c3ccSTomohiro Kusumi 				NULL, 0, &bp);
865812c3ccSTomohiro Kusumi 		KKASSERT(!error);
875812c3ccSTomohiro Kusumi 
885812c3ccSTomohiro Kusumi 		fuse_dbg("b_loffset=%ju b_bcount=%d b_flags=%x\n",
895812c3ccSTomohiro Kusumi 		    bp->b_loffset, bp->b_bcount, bp->b_flags);
905812c3ccSTomohiro Kusumi 
915812c3ccSTomohiro Kusumi 		if (need_reopen) {
925812c3ccSTomohiro Kusumi 			error = falloc(NULL, &fp, NULL);
935812c3ccSTomohiro Kusumi 			if (error) {
945812c3ccSTomohiro Kusumi 				fuse_brelse(bp);
955812c3ccSTomohiro Kusumi 				break;
965812c3ccSTomohiro Kusumi 			}
975bd45597SMatthew Dillon 			error = VOP_OPEN(vp, FREAD | FWRITE, ap->a_cred, &fp);
985812c3ccSTomohiro Kusumi 			if (error) {
995812c3ccSTomohiro Kusumi 				fuse_brelse(bp);
1005812c3ccSTomohiro Kusumi 				break;
1015812c3ccSTomohiro Kusumi 			}
1025812c3ccSTomohiro Kusumi 		}
1035812c3ccSTomohiro Kusumi 
1045812c3ccSTomohiro Kusumi 		fip = fuse_ipc_get(fmp, sizeof(*fri));
1055812c3ccSTomohiro Kusumi 		fri = fuse_ipc_fill(fip, FUSE_READ, fnp->ino, ap->a_cred);
1065812c3ccSTomohiro Kusumi 		fri->offset = bp->b_loffset;
1075812c3ccSTomohiro Kusumi 		fri->size = bp->b_bcount;
1085812c3ccSTomohiro Kusumi 		if (need_reopen)
1095812c3ccSTomohiro Kusumi 			fri->fh = fuse_nfh(VTOI(vp));
1105812c3ccSTomohiro Kusumi 		else
1115812c3ccSTomohiro Kusumi 			fri->fh = fh;
1125812c3ccSTomohiro Kusumi 
1135812c3ccSTomohiro Kusumi 		fuse_dbg("fuse_read_in offset=%ju size=%u fh=%jx\n",
1145812c3ccSTomohiro Kusumi 		    fri->offset, fri->size, fri->fh);
1155812c3ccSTomohiro Kusumi 
1165812c3ccSTomohiro Kusumi 		error = fuse_ipc_tx(fip);
1175812c3ccSTomohiro Kusumi 		if (error) {
1185812c3ccSTomohiro Kusumi 			fuse_brelse(bp);
1195812c3ccSTomohiro Kusumi 			break;
1205812c3ccSTomohiro Kusumi 		}
1215812c3ccSTomohiro Kusumi 		memcpy(bp->b_data, fuse_out_data(fip), fuse_out_data_size(fip));
1225812c3ccSTomohiro Kusumi 		fuse_ipc_put(fip);
1235812c3ccSTomohiro Kusumi 
1245812c3ccSTomohiro Kusumi 		if (need_reopen) {
1255812c3ccSTomohiro Kusumi 			error = fdrop(fp); /* calls VOP_CLOSE() */
1265812c3ccSTomohiro Kusumi 			if (error) {
1275812c3ccSTomohiro Kusumi 				fuse_brelse(bp);
1285812c3ccSTomohiro Kusumi 				break;
1295812c3ccSTomohiro Kusumi 			}
1305812c3ccSTomohiro Kusumi 		}
1315812c3ccSTomohiro Kusumi skip:
1325812c3ccSTomohiro Kusumi 		len = FUSE_BLKSIZE - buf_offset;
1335812c3ccSTomohiro Kusumi 		if (len > uio->uio_resid)
1345812c3ccSTomohiro Kusumi 			len = uio->uio_resid;
1355812c3ccSTomohiro Kusumi 		if (uio->uio_offset + len > fnp->size)
1365812c3ccSTomohiro Kusumi 			len = (size_t)(fnp->size - uio->uio_offset);
1375812c3ccSTomohiro Kusumi 		fuse_dbg("size=%ju len=%ju\n", fnp->size, len);
1385812c3ccSTomohiro Kusumi 
1395812c3ccSTomohiro Kusumi 		error = uiomovebp(bp, bp->b_data + buf_offset, len, uio);
1405812c3ccSTomohiro Kusumi 		bqrelse(bp);
1415812c3ccSTomohiro Kusumi 		if (error)
1425812c3ccSTomohiro Kusumi 			break;
1435812c3ccSTomohiro Kusumi 	}
1445812c3ccSTomohiro Kusumi 
1455812c3ccSTomohiro Kusumi 	fuse_dbg("uio_offset=%ju uio_resid=%ju error=%d done\n",
1465812c3ccSTomohiro Kusumi 	    uio->uio_offset, uio->uio_resid, error);
1475812c3ccSTomohiro Kusumi 
1485812c3ccSTomohiro Kusumi 	return error;
1495812c3ccSTomohiro Kusumi }
1505812c3ccSTomohiro Kusumi 
1515812c3ccSTomohiro Kusumi int
1525812c3ccSTomohiro Kusumi fuse_write(struct vop_write_args *ap)
1535812c3ccSTomohiro Kusumi {
1545812c3ccSTomohiro Kusumi 	return fuse_dio_write(ap);
1555812c3ccSTomohiro Kusumi }
1565812c3ccSTomohiro Kusumi 
1575812c3ccSTomohiro Kusumi int
1585812c3ccSTomohiro Kusumi fuse_dio_write(struct vop_write_args *ap)
1595812c3ccSTomohiro Kusumi {
1605812c3ccSTomohiro Kusumi 	struct vnode *vp = ap->a_vp;
1615812c3ccSTomohiro Kusumi 	struct uio *uio = ap->a_uio;
1625812c3ccSTomohiro Kusumi 	struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount);
1635812c3ccSTomohiro Kusumi 	struct fuse_node *fnp = VTOI(vp);
1645812c3ccSTomohiro Kusumi 	bool need_reopen = !curproc || fnp->closed; /* XXX */
1655812c3ccSTomohiro Kusumi 	int kflags = 0;
1665812c3ccSTomohiro Kusumi 	int error = 0;
1675812c3ccSTomohiro Kusumi 
1685812c3ccSTomohiro Kusumi 	if (ap->a_ioflag & IO_APPEND)
1695812c3ccSTomohiro Kusumi 		uio->uio_offset = fnp->size;
1705812c3ccSTomohiro Kusumi 
1715812c3ccSTomohiro Kusumi 	while (uio->uio_resid > 0) {
1725812c3ccSTomohiro Kusumi 		struct file *fp;
1735812c3ccSTomohiro Kusumi 		struct buf *bp;
1745812c3ccSTomohiro Kusumi 		struct fuse_ipc *fip;
1755812c3ccSTomohiro Kusumi 		struct fuse_read_in *fri;
1765812c3ccSTomohiro Kusumi 		struct fuse_write_in *fwi;
1775812c3ccSTomohiro Kusumi 		struct fuse_write_out *fwo;
1785812c3ccSTomohiro Kusumi 		off_t base_offset, buf_offset;
1795812c3ccSTomohiro Kusumi 		size_t len, oldsize;
1805812c3ccSTomohiro Kusumi 		uint64_t fh;
1815812c3ccSTomohiro Kusumi 		bool fixsize = false;
1825812c3ccSTomohiro Kusumi 		bool need_read = false;
1835812c3ccSTomohiro Kusumi 
1845812c3ccSTomohiro Kusumi 		fh = fuse_nfh(VTOI(vp));
1855812c3ccSTomohiro Kusumi 		if (ap->a_fp)
1865812c3ccSTomohiro Kusumi 			fh = fuse_fh(ap->a_fp);
1875812c3ccSTomohiro Kusumi 
1885812c3ccSTomohiro Kusumi 		buf_offset = (off_t)uio->uio_offset & FUSE_BLKMASK64;
1895812c3ccSTomohiro Kusumi 		base_offset = (off_t)uio->uio_offset - buf_offset;
1905812c3ccSTomohiro Kusumi 
1915812c3ccSTomohiro Kusumi 		fuse_dbg("uio_offset=%ju uio_resid=%ju base_offset=%ju "
1925812c3ccSTomohiro Kusumi 		    "buf_offset=%ju\n",
1935812c3ccSTomohiro Kusumi 		    uio->uio_offset, uio->uio_resid, base_offset, buf_offset);
1945812c3ccSTomohiro Kusumi 
1955812c3ccSTomohiro Kusumi 		oldsize = fnp->size;
1965812c3ccSTomohiro Kusumi 		len = FUSE_BLKSIZE - buf_offset;
1975812c3ccSTomohiro Kusumi 		if (len > uio->uio_resid)
1985812c3ccSTomohiro Kusumi 			len = uio->uio_resid;
1995812c3ccSTomohiro Kusumi 		if (uio->uio_offset + len > fnp->size) {
2005812c3ccSTomohiro Kusumi 			/* XXX trivial flag */
2015812c3ccSTomohiro Kusumi 			error = fuse_node_truncate(fnp, fnp->size,
2025812c3ccSTomohiro Kusumi 			    uio->uio_offset + len);
2035812c3ccSTomohiro Kusumi 			if (error)
2045812c3ccSTomohiro Kusumi 				break;
2055812c3ccSTomohiro Kusumi 			fixsize = true;
2065812c3ccSTomohiro Kusumi 			kflags |= NOTE_EXTEND;
2075812c3ccSTomohiro Kusumi 		}
2085812c3ccSTomohiro Kusumi 		fuse_dbg("size=%ju len=%ju\n", fnp->size, len);
2095812c3ccSTomohiro Kusumi 
2105812c3ccSTomohiro Kusumi 		bp = NULL;
2115812c3ccSTomohiro Kusumi 		if (uio->uio_segflg == UIO_NOCOPY) {
2125812c3ccSTomohiro Kusumi 			bp = getblk(ap->a_vp, base_offset, FUSE_BLKSIZE,
2135812c3ccSTomohiro Kusumi 			    GETBLK_BHEAVY, 0);
2145812c3ccSTomohiro Kusumi 			if (!(bp->b_flags & B_CACHE)) {
2155812c3ccSTomohiro Kusumi 				bqrelse(bp);
2165812c3ccSTomohiro Kusumi 				need_read = true;
2175812c3ccSTomohiro Kusumi 			}
2185812c3ccSTomohiro Kusumi 		} else if (!buf_offset && uio->uio_resid >= FUSE_BLKSIZE) {
2195812c3ccSTomohiro Kusumi 			bp = getblk(ap->a_vp, base_offset, FUSE_BLKSIZE,
2205812c3ccSTomohiro Kusumi 			    GETBLK_BHEAVY, 0);
2215812c3ccSTomohiro Kusumi 			if (!(bp->b_flags & B_CACHE))
2225812c3ccSTomohiro Kusumi 				vfs_bio_clrbuf(bp);
2235812c3ccSTomohiro Kusumi 		} else if (base_offset >= fnp->size) {
2245812c3ccSTomohiro Kusumi 			bp = getblk(ap->a_vp, base_offset, FUSE_BLKSIZE,
2255812c3ccSTomohiro Kusumi 			    GETBLK_BHEAVY, 0);
2265812c3ccSTomohiro Kusumi 			vfs_bio_clrbuf(bp);
2275812c3ccSTomohiro Kusumi 		} else {
2285812c3ccSTomohiro Kusumi 			need_read = true;
2295812c3ccSTomohiro Kusumi 		}
2305812c3ccSTomohiro Kusumi 
2315812c3ccSTomohiro Kusumi 		if (bp)
2325812c3ccSTomohiro Kusumi 			fuse_dbg("b_loffset=%ju b_bcount=%d b_flags=%x\n",
2335812c3ccSTomohiro Kusumi 			    bp->b_loffset, bp->b_bcount, bp->b_flags);
2345812c3ccSTomohiro Kusumi 
2355812c3ccSTomohiro Kusumi 		if (need_reopen) {
2365812c3ccSTomohiro Kusumi 			error = falloc(NULL, &fp, NULL);
2375812c3ccSTomohiro Kusumi 			if (error) {
2385812c3ccSTomohiro Kusumi 				fuse_brelse(bp);
2395812c3ccSTomohiro Kusumi 				fuse_fix_size(fnp, fixsize, oldsize);
2405812c3ccSTomohiro Kusumi 				break;
2415812c3ccSTomohiro Kusumi 			}
2425812c3ccSTomohiro Kusumi 			/* XXX can panic at vref() in vop_stdopen() */
2435bd45597SMatthew Dillon 			error = VOP_OPEN(vp, FREAD | FWRITE, ap->a_cred, &fp);
2445812c3ccSTomohiro Kusumi 			if (error) {
2455812c3ccSTomohiro Kusumi 				fuse_brelse(bp);
2465812c3ccSTomohiro Kusumi 				fuse_fix_size(fnp, fixsize, oldsize);
2475812c3ccSTomohiro Kusumi 				break;
2485812c3ccSTomohiro Kusumi 			}
2495812c3ccSTomohiro Kusumi 		}
2505812c3ccSTomohiro Kusumi 
2515812c3ccSTomohiro Kusumi 		if (need_read) {
2525812c3ccSTomohiro Kusumi 			error = bread(ap->a_vp, base_offset, FUSE_BLKSIZE, &bp);
2535812c3ccSTomohiro Kusumi 			KKASSERT(!error);
2545812c3ccSTomohiro Kusumi 
2555812c3ccSTomohiro Kusumi 			fuse_dbg("b_loffset=%ju b_bcount=%d b_flags=%x\n",
2565812c3ccSTomohiro Kusumi 			    bp->b_loffset, bp->b_bcount, bp->b_flags);
2575812c3ccSTomohiro Kusumi 
2585812c3ccSTomohiro Kusumi 			if (bp->b_loffset + (buf_offset + len) > oldsize) {
2595812c3ccSTomohiro Kusumi 				memset(bp->b_data, 0, FUSE_BLKSIZE); /* XXX */
2605812c3ccSTomohiro Kusumi 				goto skip; /* prevent EBADF */
2615812c3ccSTomohiro Kusumi 			}
2625812c3ccSTomohiro Kusumi 
2635812c3ccSTomohiro Kusumi 			fip = fuse_ipc_get(fmp, sizeof(*fri));
2645812c3ccSTomohiro Kusumi 			fri = fuse_ipc_fill(fip, FUSE_READ, fnp->ino,
2655812c3ccSTomohiro Kusumi 			    ap->a_cred);
2665812c3ccSTomohiro Kusumi 			fri->offset = bp->b_loffset;
2675812c3ccSTomohiro Kusumi 			fri->size = buf_offset + len;
2685812c3ccSTomohiro Kusumi 			if (need_reopen)
2695812c3ccSTomohiro Kusumi 				fri->fh = fuse_nfh(VTOI(vp));
2705812c3ccSTomohiro Kusumi 			else
2715812c3ccSTomohiro Kusumi 				fri->fh = fh;
2725812c3ccSTomohiro Kusumi 
2735812c3ccSTomohiro Kusumi 			fuse_dbg("fuse_read_in offset=%ju size=%u fh=%jx\n",
2745812c3ccSTomohiro Kusumi 			    fri->offset, fri->size, fri->fh);
2755812c3ccSTomohiro Kusumi 
2765812c3ccSTomohiro Kusumi 			error = fuse_ipc_tx(fip);
2775812c3ccSTomohiro Kusumi 			if (error) {
2785812c3ccSTomohiro Kusumi 				fuse_brelse(bp);
2795812c3ccSTomohiro Kusumi 				fuse_fix_size(fnp, fixsize, oldsize);
2805812c3ccSTomohiro Kusumi 				break;
2815812c3ccSTomohiro Kusumi 			}
2825812c3ccSTomohiro Kusumi 			memcpy(bp->b_data, fuse_out_data(fip),
2835812c3ccSTomohiro Kusumi 			    fuse_out_data_size(fip));
2845812c3ccSTomohiro Kusumi 			fuse_ipc_put(fip);
2855812c3ccSTomohiro Kusumi 		}
2865812c3ccSTomohiro Kusumi skip:
2875812c3ccSTomohiro Kusumi 		error = uiomovebp(bp, bp->b_data + buf_offset, len, uio);
2885812c3ccSTomohiro Kusumi 		if (error) {
2895812c3ccSTomohiro Kusumi 			bqrelse(bp);
2905812c3ccSTomohiro Kusumi 			fuse_fix_size(fnp, fixsize, oldsize);
2915812c3ccSTomohiro Kusumi 			break;
2925812c3ccSTomohiro Kusumi 		}
2935812c3ccSTomohiro Kusumi 		kflags |= NOTE_WRITE;
2945812c3ccSTomohiro Kusumi 
2955812c3ccSTomohiro Kusumi 		fip = fuse_ipc_get(fmp, sizeof(*fwi) + len);
2965812c3ccSTomohiro Kusumi 		fwi = fuse_ipc_fill(fip, FUSE_WRITE, fnp->ino, ap->a_cred);
2975812c3ccSTomohiro Kusumi 		fwi->offset = bp->b_loffset + buf_offset;
2985812c3ccSTomohiro Kusumi 		fwi->size = len;
2995812c3ccSTomohiro Kusumi 		if (need_reopen)
3005812c3ccSTomohiro Kusumi 			fwi->fh = fuse_nfh(VTOI(vp));
3015812c3ccSTomohiro Kusumi 		else
3025812c3ccSTomohiro Kusumi 			fwi->fh = fh;
3035812c3ccSTomohiro Kusumi 		memcpy((void*)(fwi + 1), bp->b_data + buf_offset, len);
3045812c3ccSTomohiro Kusumi 
3055812c3ccSTomohiro Kusumi 		fuse_dbg("fuse_write_in offset=%ju size=%u fh=%jx\n",
3065812c3ccSTomohiro Kusumi 		    fwi->offset, fwi->size, fwi->fh);
3075812c3ccSTomohiro Kusumi 
3085812c3ccSTomohiro Kusumi 		error = fuse_ipc_tx(fip);
3095812c3ccSTomohiro Kusumi 		if (error) {
3105812c3ccSTomohiro Kusumi 			fuse_brelse(bp);
3115812c3ccSTomohiro Kusumi 			fuse_fix_size(fnp, fixsize, oldsize);
3125812c3ccSTomohiro Kusumi 			break;
3135812c3ccSTomohiro Kusumi 		}
3145812c3ccSTomohiro Kusumi 		fwo = fuse_out_data(fip);
3155812c3ccSTomohiro Kusumi 		if (fwo->size != len) {
3165812c3ccSTomohiro Kusumi 			fuse_ipc_put(fip);
3175812c3ccSTomohiro Kusumi 			fuse_brelse(bp);
3185812c3ccSTomohiro Kusumi 			fuse_fix_size(fnp, fixsize, oldsize);
3195812c3ccSTomohiro Kusumi 			break;
3205812c3ccSTomohiro Kusumi 		}
3215812c3ccSTomohiro Kusumi 		fuse_ipc_put(fip);
3225812c3ccSTomohiro Kusumi 
3235812c3ccSTomohiro Kusumi 		if (need_reopen) {
3245812c3ccSTomohiro Kusumi 			error = fdrop(fp); /* calls VOP_CLOSE() */
3255812c3ccSTomohiro Kusumi 			if (error) {
3265812c3ccSTomohiro Kusumi 				fuse_brelse(bp);
3275812c3ccSTomohiro Kusumi 				fuse_fix_size(fnp, fixsize, oldsize);
3285812c3ccSTomohiro Kusumi 				break;
3295812c3ccSTomohiro Kusumi 			}
3305812c3ccSTomohiro Kusumi 		}
3315812c3ccSTomohiro Kusumi 
3325812c3ccSTomohiro Kusumi 		error = bwrite(bp);
3335812c3ccSTomohiro Kusumi 		KKASSERT(!error);
3345812c3ccSTomohiro Kusumi 	}
3355812c3ccSTomohiro Kusumi 
3365812c3ccSTomohiro Kusumi 	fuse_knote(ap->a_vp, kflags);
3375812c3ccSTomohiro Kusumi 
3385812c3ccSTomohiro Kusumi 	fuse_dbg("uio_offset=%ju uio_resid=%ju error=%d done\n",
3395812c3ccSTomohiro Kusumi 	    uio->uio_offset, uio->uio_resid, error);
3405812c3ccSTomohiro Kusumi 
3415812c3ccSTomohiro Kusumi 	return error;
3425812c3ccSTomohiro Kusumi }
343*5d0d0bafSMatthew Dillon #endif
344