From 8aa7625b56364a334d7c4038061d23aac9b58218 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 21 Aug 2007 17:26:48 +0000 Subject: [PATCH] getpages/putpages fixup part 1 - Add support for UIO_NOCOPY VOP_WRITEs to filesystems which use the buffer cache and assert that UIO_NOCOPY is not being used for filesystems which do not. For filesystems using the buffer cache all we have to do is force a read-before-write to fill in any missing pieces of the buffer. UIO_NOCOPY writes are used for buffer-cache-backed filesystems which do not implement their own vop_putpages code. At the moment this is only the msdosfs. --- sys/kern/kern_physio.c | 5 ++++- sys/netproto/ncp/ncp_subr.c | 3 ++- sys/netproto/smb/smb_smb.c | 5 ++++- sys/vfs/gnu/ext2fs/ext2_readwrite.c | 14 ++++++-------- sys/vfs/hpfs/hpfs_vnops.c | 13 +++++++++++-- sys/vfs/msdosfs/msdosfs_vnops.c | 17 +++++++++++------ sys/vfs/nfs/nfs_bio.c | 8 ++++++-- sys/vfs/ntfs/ntfs_subr.c | 6 +++--- sys/vfs/specfs/spec_vnops.c | 4 +++- sys/vfs/ufs/ufs_readwrite.c | 9 +++++---- sys/vfs/userfs/userfs_vnops.c | 4 ++-- 11 files changed, 57 insertions(+), 31 deletions(-) diff --git a/sys/kern/kern_physio.c b/sys/kern/kern_physio.c index aa9b9607d8..d8aed754e8 100644 --- a/sys/kern/kern_physio.c +++ b/sys/kern/kern_physio.c @@ -17,7 +17,7 @@ * are met. * * $FreeBSD: src/sys/kern/kern_physio.c,v 1.46.2.4 2003/11/14 09:51:47 simokawa Exp $ - * $DragonFly: src/sys/kern/kern_physio.c,v 1.24 2006/12/23 00:35:04 swildner Exp $ + * $DragonFly: src/sys/kern/kern_physio.c,v 1.25 2007/08/21 17:26:45 dillon Exp $ */ #include @@ -61,6 +61,9 @@ physio(cdev_t dev, struct uio *uio, int ioflag) dev->si_iosize_max = DFLTPHYS; } + /* Must be a real uio */ + KKASSERT(uio->uio_segflg != UIO_NOCOPY); + /* Don't check block number overflow for D_MEM */ if ((dev_dflags(dev) & D_TYPEMASK) == D_MEM) chk_blockno = 0; diff --git a/sys/netproto/ncp/ncp_subr.c b/sys/netproto/ncp/ncp_subr.c index 081b996643..b244afecae 100644 --- a/sys/netproto/ncp/ncp_subr.c +++ b/sys/netproto/ncp/ncp_subr.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netncp/ncp_subr.c,v 1.2.2.1 2001/02/22 08:54:11 bp Exp $ - * $DragonFly: src/sys/netproto/ncp/ncp_subr.c,v 1.10 2006/12/22 23:57:54 swildner Exp $ + * $DragonFly: src/sys/netproto/ncp/ncp_subr.c,v 1.11 2007/08/21 17:26:46 dillon Exp $ */ #include #include @@ -231,6 +231,7 @@ ncp_write(struct ncp_conn *conn, ncp_fh *file, struct uio *uiop, struct ucred *c kprintf("%s: can't handle iovcnt>1 !!!\n", __func__); return EIO; } + KKASSERT(uiop->uio_segflg != UIO_NOCOPY); tsiz = uiop->uio_resid; while (tsiz > 0) { len = min(4096 - (uiop->uio_offset % 4096), tsiz); diff --git a/sys/netproto/smb/smb_smb.c b/sys/netproto/smb/smb_smb.c index 52bd0bbb87..e41518bc5e 100644 --- a/sys/netproto/smb/smb_smb.c +++ b/sys/netproto/smb/smb_smb.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netsmb/smb_smb.c,v 1.1.2.3 2002/12/14 14:44:19 fjoe Exp $ - * $DragonFly: src/sys/netproto/smb/smb_smb.c,v 1.6 2006/09/05 00:55:49 dillon Exp $ + * $DragonFly: src/sys/netproto/smb/smb_smb.c,v 1.7 2007/08/21 17:26:47 dillon Exp $ */ /* * various SMB requests. Most of the routines merely packs data into mbufs. @@ -572,6 +572,9 @@ smb_smb_write(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid, u_int8_t wc; int error, blksz; + /* write data must be real */ + KKASSERT(uio->uio_segflg != UIO_NOCOPY); + blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 16; if (blksz > 0xffff) blksz = 0xffff; diff --git a/sys/vfs/gnu/ext2fs/ext2_readwrite.c b/sys/vfs/gnu/ext2fs/ext2_readwrite.c index f424c8e0ec..7a5553aec6 100644 --- a/sys/vfs/gnu/ext2fs/ext2_readwrite.c +++ b/sys/vfs/gnu/ext2fs/ext2_readwrite.c @@ -38,7 +38,7 @@ * * @(#)ufs_readwrite.c 8.7 (Berkeley) 1/21/94 * $FreeBSD: src/sys/gnu/ext2fs/ext2_readwrite.c,v 1.18.2.2 2000/12/22 18:44:33 dillon Exp $ - * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_readwrite.c,v 1.13 2007/02/22 15:50:49 corecode Exp $ + * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_readwrite.c,v 1.14 2007/08/21 17:26:48 dillon Exp $ */ #define BLKSIZE(a, b, c) blksize(a, b, c) @@ -238,15 +238,13 @@ ext2_write(struct vop_write_args *ap) * by ensuring that newly allocated blocks are zerod. The * race can occur even in the case where the write covers * the entire block. + * + * Just set B_CLRBUF unconditionally, even if the write + * covers the whole block. This also handles the UIO_NOCOPY + * case. See ffs_write() in ufs for a more sophisticated + * version. */ flags |= B_CLRBUF; -#if 0 - if (fs->s_frag_size > xfersize) - flags |= B_CLRBUF; - else - flags &= ~B_CLRBUF; -#endif - error = ext2_balloc(ip, lbn, blkoffset + xfersize, ap->a_cred, &bp, flags); if (error) diff --git a/sys/vfs/hpfs/hpfs_vnops.c b/sys/vfs/hpfs/hpfs_vnops.c index 1efab42166..84b6b7869c 100644 --- a/sys/vfs/hpfs/hpfs_vnops.c +++ b/sys/vfs/hpfs/hpfs_vnops.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/hpfs/hpfs_vnops.c,v 1.2.2.2 2002/01/15 18:35:09 semenu Exp $ - * $DragonFly: src/sys/vfs/hpfs/hpfs_vnops.c,v 1.43 2007/08/13 17:31:56 dillon Exp $ + * $DragonFly: src/sys/vfs/hpfs/hpfs_vnops.c,v 1.44 2007/08/21 17:26:48 dillon Exp $ */ #include @@ -404,7 +404,16 @@ hpfs_write(struct vop_write_args *ap) dprintf(("hpfs_write: bn: 0x%x (0x%x) towrite: 0x%x (0x%x)\n", bn, runl, towrite, xfersz)); - if ((off == 0) && (towrite == xfersz)) { + /* + * We do not have to issue a read-before-write if the xfer + * size does not cover the whole block. + * + * In the UIO_NOCOPY case, however, we are not overwriting + * anything and must do a read-before-write to fill in + * any missing pieces. + */ + if (off == 0 && towrite == xfersz && + uio->uio_segflg != UIO_NOCOPY) { bp = getblk(hp->h_devvp, dbtodoff(bn), xfersz, 0, 0); clrbuf(bp); } else { diff --git a/sys/vfs/msdosfs/msdosfs_vnops.c b/sys/vfs/msdosfs/msdosfs_vnops.c index 8ad3ff5aee..ce77d82ca8 100644 --- a/sys/vfs/msdosfs/msdosfs_vnops.c +++ b/sys/vfs/msdosfs/msdosfs_vnops.c @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/msdosfs/msdosfs_vnops.c,v 1.95.2.4 2003/06/13 15:05:47 trhodes Exp $ */ -/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vnops.c,v 1.50 2007/08/13 17:31:56 dillon Exp $ */ +/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vnops.c,v 1.51 2007/08/21 17:26:48 dillon Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.68 1998/02/10 14:10:04 mrg Exp $ */ /*- @@ -749,16 +749,21 @@ msdosfs_write(struct vop_write_args *ap) vnode_pager_setsize(vp, dep->de_FileSize); } + /* + * If either the whole cluster gets written, or we write + * the cluster from its start beyond EOF, then no need to + * read data from disk. + * + * If UIO_NOCOPY is set we have to do a read-before-write + * to fill in any missing pieces of the buffer since no + * actual overwrite will occur. + */ cn = de_off2cn(pmp, uio->uio_offset); if ((uio->uio_offset & pmp->pm_crbomask) == 0 + && uio->uio_segflg != UIO_NOCOPY && (de_off2cn(pmp, uio->uio_offset + uio->uio_resid) > de_off2cn(pmp, uio->uio_offset) || uio->uio_offset + uio->uio_resid >= dep->de_FileSize)) { - /* - * If either the whole cluster gets written, - * or we write the cluster from its start beyond EOF, - * then no need to read data from disk. - */ bp = getblk(thisvp, de_cn2doff(pmp, cn), pmp->pm_bpcluster, 0, 0); clrbuf(bp); diff --git a/sys/vfs/nfs/nfs_bio.c b/sys/vfs/nfs/nfs_bio.c index 9a9a5b236e..5ecd03276d 100644 --- a/sys/vfs/nfs/nfs_bio.c +++ b/sys/vfs/nfs/nfs_bio.c @@ -35,7 +35,7 @@ * * @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95 * $FreeBSD: /repoman/r/ncvs/src/sys/nfsclient/nfs_bio.c,v 1.130 2004/04/14 23:23:55 peadar Exp $ - * $DragonFly: src/sys/vfs/nfs/nfs_bio.c,v 1.40 2007/02/22 15:50:50 corecode Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_bio.c,v 1.41 2007/08/21 17:26:48 dillon Exp $ */ @@ -938,9 +938,13 @@ again: * * B_CACHE may also be set due to the buffer being cached * normally. + * + * When doing a UIO_NOCOPY write the buffer is not + * overwritten and we cannot just set B_CACHE unconditionally + * for full-block writes. */ - if (on == 0 && n == bcount) { + if (on == 0 && n == bcount && uio->uio_segflg != UIO_NOCOPY) { bp->b_flags |= B_CACHE; bp->b_flags &= ~(B_ERROR | B_INVAL); } diff --git a/sys/vfs/ntfs/ntfs_subr.c b/sys/vfs/ntfs/ntfs_subr.c index 1d5b39dd06..eec2c03fd3 100644 --- a/sys/vfs/ntfs/ntfs_subr.c +++ b/sys/vfs/ntfs/ntfs_subr.c @@ -26,7 +26,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/ntfs/ntfs_subr.c,v 1.7.2.4 2001/10/12 22:08:49 semenu Exp $ - * $DragonFly: src/sys/vfs/ntfs/ntfs_subr.c,v 1.25 2006/12/23 00:41:30 swildner Exp $ + * $DragonFly: src/sys/vfs/ntfs/ntfs_subr.c,v 1.26 2007/08/21 17:26:48 dillon Exp $ */ #include @@ -1404,8 +1404,8 @@ ntfs_writentvattr_plain(struct ntfsmount *ntmp, struct ntnode *ip, (u_int32_t) cn, (u_int32_t) cl, (u_int32_t) off, (u_int32_t) tocopy, (u_int32_t) left)); - if ((off == 0) && (tocopy == ntfs_cntob(cl))) - { + if (off == 0 && tocopy == ntfs_cntob(cl) && + uio->uio_segflg != UIO_NOCOPY) { bp = getblk(ntmp->ntm_devvp, ntfs_cntodoff(cn), ntfs_cntob(cl), 0, 0); clrbuf(bp); diff --git a/sys/vfs/specfs/spec_vnops.c b/sys/vfs/specfs/spec_vnops.c index 10c56ed0c4..45c3d4f2c0 100644 --- a/sys/vfs/specfs/spec_vnops.c +++ b/sys/vfs/specfs/spec_vnops.c @@ -32,7 +32,7 @@ * * @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95 * $FreeBSD: src/sys/miscfs/specfs/spec_vnops.c,v 1.131.2.4 2001/02/26 04:23:20 jlemon Exp $ - * $DragonFly: src/sys/vfs/specfs/spec_vnops.c,v 1.55 2007/08/13 17:31:56 dillon Exp $ + * $DragonFly: src/sys/vfs/specfs/spec_vnops.c,v 1.56 2007/08/21 17:26:48 dillon Exp $ */ #include @@ -360,6 +360,8 @@ spec_write(struct vop_write_args *ap) uio = ap->a_uio; td = uio->uio_td; + KKASSERT(uio->uio_segflg != UIO_NOCOPY); + if (dev == NULL) /* device was revoked */ return (EBADF); diff --git a/sys/vfs/ufs/ufs_readwrite.c b/sys/vfs/ufs/ufs_readwrite.c index c9f8d251f5..1a73c33a78 100644 --- a/sys/vfs/ufs/ufs_readwrite.c +++ b/sys/vfs/ufs/ufs_readwrite.c @@ -32,7 +32,7 @@ * * @(#)ufs_readwrite.c 8.11 (Berkeley) 5/8/95 * $FreeBSD: src/sys/ufs/ufs/ufs_readwrite.c,v 1.65.2.14 2003/04/04 22:21:29 tegge Exp $ - * $DragonFly: src/sys/vfs/ufs/ufs_readwrite.c,v 1.22 2007/08/13 17:31:57 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ufs_readwrite.c,v 1.23 2007/08/21 17:26:48 dillon Exp $ */ #define BLKSIZE(a, b, c) blksize(a, b, c) @@ -315,9 +315,10 @@ ffs_write(struct vop_write_args *ap) /* * We must perform a read-before-write if the transfer - * size does not cover the entire buffer. + * size does not cover the entire buffer, or if doing + * a dummy write to flush the buffer. */ - if (fs->fs_bsize > xfersize) + if (xfersize < fs->fs_bsize || uio->uio_segflg == UIO_NOCOPY) flags |= B_CLRBUF; else flags &= ~B_CLRBUF; @@ -333,7 +334,7 @@ ffs_write(struct vop_write_args *ap) * race where another process may see the garbage prior to * the uiomove() for a write replacing it. */ - if ((bp->b_flags & B_CACHE) == 0 && fs->fs_bsize <= xfersize) + if ((bp->b_flags & B_CACHE) == 0 && (flags & B_CLRBUF) == 0) vfs_bio_clrbuf(bp); if (ioflag & IO_DIRECT) bp->b_flags |= B_DIRECT; diff --git a/sys/vfs/userfs/userfs_vnops.c b/sys/vfs/userfs/userfs_vnops.c index 9fe9fe4971..4c92a989d3 100644 --- a/sys/vfs/userfs/userfs_vnops.c +++ b/sys/vfs/userfs/userfs_vnops.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/userfs/userfs_vnops.c,v 1.1 2007/08/13 17:49:17 dillon Exp $ + * $DragonFly: src/sys/vfs/userfs/userfs_vnops.c,v 1.2 2007/08/21 17:26:48 dillon Exp $ */ #include @@ -282,7 +282,7 @@ user_vop_write (struct vop_write_args *ap) * on USERFS_BSIZE boundaries. * * XXX not optimized for complete write-overs or file - * extensions. + * extensions. Note: must bread on UIO_NOCOPY writes. */ offset = (int)uio->uio_offset & USERFS_BMASK; error = bread(vp, uio->uio_offset - offset, USERFS_BSIZE, &bp); -- 2.41.0