Index: sys/fs/puffs/puffs_vnops.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/fs/puffs/puffs_vnops.c,v retrieving revision 1.73 retrieving revision 1.74 diff -u -r1.73 -r1.74 --- sys/fs/puffs/puffs_vnops.c 1 Jun 2007 15:59:37 -0000 1.73 +++ sys/fs/puffs/puffs_vnops.c 5 Jun 2007 12:31:30 -0000 1.74 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_vnops.c,v 1.73 2007/06/01 15:59:37 yamt Exp $ */ +/* $NetBSD: puffs_vnops.c,v 1.74 2007/06/05 12:31:30 yamt Exp $ */ /* * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved. @@ -33,7 +33,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.73 2007/06/01 15:59:37 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.74 2007/06/05 12:31:30 yamt Exp $"); #include #include @@ -1552,7 +1552,6 @@ struct puffs_mount *pmp; struct uio *uio; struct vnode *vp; - void *win; size_t tomove, argsize; off_t oldoff, newoff, origoff; vsize_t bytelen; @@ -1566,7 +1565,7 @@ pmp = MPTOPUFFSMP(ap->a_vp->v_mount); if (vp->v_type == VREG && PUFFS_DOCACHE(pmp)) { - ubcflags = 0; + ubcflags = UBC_WRITE | UBC_PARTIALOK; if (UBC_WANT_UNMAP(vp)) ubcflags = UBC_UNMAP; @@ -1584,26 +1583,28 @@ oldoff = uio->uio_offset; bytelen = uio->uio_resid; - win = ubc_alloc(&vp->v_uobj, oldoff, &bytelen, - UVM_ADV_NORMAL, UBC_WRITE); - error = uiomove(win, bytelen, uio); + newoff = oldoff + bytelen; + if (vp->v_size < newoff) { + uvm_vnp_setwritesize(vp, newoff); + } + error = ubc_uiomove(&vp->v_uobj, uio, bytelen, + ubcflags); /* - * There is no guarantee that the faults - * generated by uiomove() succeed at all. - * Therefore, in case of an uiomove() error, + * In case of a ubc_uiomove() error, * opt to not extend the file at all and * return an error. Otherwise, if we attempt * to clear the memory we couldn't fault to, * we might generate a kernel page fault. */ - newoff = oldoff + bytelen; - if (vp->v_size < newoff && error == 0) { - uflags |= PUFFS_UPDATESIZE; - uvm_vnp_setsize(vp, newoff); + if (vp->v_size < newoff) { + if (error == 0) { + uflags |= PUFFS_UPDATESIZE; + uvm_vnp_setsize(vp, newoff); + } else { + uvm_vnp_setwritesize(vp, vp->v_size); + } } - - ubc_release(win, ubcflags); if (error) break; Index: sys/kern/vfs_subr.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/kern/vfs_subr.c,v retrieving revision 1.287 retrieving revision 1.288 diff -u -r1.287 -r1.288 --- sys/kern/vfs_subr.c 16 Apr 2007 05:14:54 -0000 1.287 +++ sys/kern/vfs_subr.c 5 Jun 2007 12:31:31 -0000 1.288 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_subr.c,v 1.287 2007/04/16 05:14:54 chs Exp $ */ +/* $NetBSD: vfs_subr.c,v 1.288 2007/06/05 12:31:31 yamt Exp $ */ /*- * Copyright (c) 1997, 1998, 2004, 2005 The NetBSD Foundation, Inc. @@ -80,7 +80,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.287 2007/04/16 05:14:54 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.288 2007/06/05 12:31:31 yamt Exp $"); #include "opt_inet.h" #include "opt_ddb.h" @@ -594,7 +594,7 @@ KASSERT(uobj->pgops == &uvm_vnodeops); KASSERT(uobj->uo_npages == 0); KASSERT(TAILQ_FIRST(&uobj->memq) == NULL); - vp->v_size = VSIZENOTSET; + vp->v_size = vp->v_writesize = VSIZENOTSET; if (mp && error != EDEADLK) vfs_unbusy(mp); @@ -2638,8 +2638,8 @@ uvm_object_printit(&vp->v_uobj, full, pr); bitmask_snprintf(vp->v_flag, vnode_flagbits, bf, sizeof(bf)); (*pr)("\nVNODE flags %s\n", bf); - (*pr)("mp %p numoutput %d size 0x%llx\n", - vp->v_mount, vp->v_numoutput, vp->v_size); + (*pr)("mp %p numoutput %d size 0x%llx writesize 0x%llx\n", + vp->v_mount, vp->v_numoutput, vp->v_size, vp->v_writesize); (*pr)("data %p usecount %d writecount %ld holdcnt %ld numoutput %d\n", vp->v_data, vp->v_usecount, vp->v_writecount, Index: sys/miscfs/genfs/genfs_vnops.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/miscfs/genfs/genfs_vnops.c,v retrieving revision 1.153 retrieving revision 1.154 diff -u -r1.153 -r1.154 --- sys/miscfs/genfs/genfs_vnops.c 17 May 2007 07:26:22 -0000 1.153 +++ sys/miscfs/genfs/genfs_vnops.c 5 Jun 2007 12:31:31 -0000 1.154 @@ -1,4 +1,4 @@ -/* $NetBSD: genfs_vnops.c,v 1.153 2007/05/17 07:26:22 hannken Exp $ */ +/* $NetBSD: genfs_vnops.c,v 1.154 2007/06/05 12:31:31 yamt Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -31,7 +31,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.153 2007/05/17 07:26:22 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.154 2007/06/05 12:31:31 yamt Exp $"); #include #include @@ -425,7 +425,7 @@ int i, error, npages, orignpages, npgs, run, ridx, pidx, pcount; int fs_bshift, fs_bsize, dev_bshift; int flags = ap->a_flags; - size_t bytes, iobytes, tailbytes, totalbytes, skipbytes; + size_t bytes, iobytes, tailstart, tailbytes, totalbytes, skipbytes; vaddr_t kva; struct buf *bp, *mbp; struct vnode *vp = ap->a_vp; @@ -465,9 +465,19 @@ orignpages = *ap->a_count; GOP_SIZE(vp, origvsize, &diskeof, 0); if (flags & PGO_PASTEOF) { +#if defined(DIAGNOSTIC) + off_t writeeof; +#endif /* defined(DIAGNOSTIC) */ + newsize = MAX(origvsize, origoffset + (orignpages << PAGE_SHIFT)); GOP_SIZE(vp, newsize, &memeof, GOP_SIZE_MEM); +#if defined(DIAGNOSTIC) + GOP_SIZE(vp, vp->v_writesize, &writeeof, GOP_SIZE_MEM); + if (newsize > round_page(writeeof)) { + panic("%s: past eof", __func__); + } +#endif /* defined(DIAGNOSTIC) */ } else { GOP_SIZE(vp, origvsize, &memeof, GOP_SIZE_MEM); } @@ -728,20 +738,22 @@ /* * if EOF is in the middle of the range, zero the part past EOF. - * if the page including EOF is not PG_FAKE, skip over it since - * in that case it has valid data that we need to preserve. + * skip over pages which are not PG_FAKE since in that case they have + * valid data that we need to preserve. */ - if (tailbytes > 0) { - size_t tailstart = bytes; - - if ((pgs[bytes >> PAGE_SHIFT]->flags & PG_FAKE) == 0) { - tailstart = round_page(tailstart); - tailbytes -= tailstart - bytes; + tailstart = bytes; + while (tailbytes > 0) { + const int len = PAGE_SIZE - (tailstart & PAGE_MASK); + + KASSERT(len <= tailbytes); + if ((pgs[tailstart >> PAGE_SHIFT]->flags & PG_FAKE) != 0) { + memset((void *)(kva + tailstart), 0, len); + UVMHIST_LOG(ubchist, "tailbytes %p 0x%x 0x%x", + kva, tailstart, len, 0); } - UVMHIST_LOG(ubchist, "tailbytes %p 0x%x 0x%x", - kva, tailstart, tailbytes,0); - memset((void *)(kva + tailstart), 0, tailbytes); + tailstart += len; + tailbytes -= len; } /* @@ -1514,7 +1526,8 @@ UVMHIST_LOG(ubchist, "vp %p kva %p len 0x%x flags 0x%x", vp, kva, len, flags); - GOP_SIZE(vp, vp->v_size, &eof, 0); + KASSERT(vp->v_size <= vp->v_writesize); + GOP_SIZE(vp, vp->v_writesize, &eof, 0); if (vp->v_type != VBLK) { fs_bshift = vp->v_mount->mnt_fs_bshift; dev_bshift = vp->v_mount->mnt_dev_bshift; Index: sys/miscfs/specfs/spec_vnops.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/miscfs/specfs/spec_vnops.c,v retrieving revision 1.98 retrieving revision 1.99 diff -u -r1.98 -r1.99 --- sys/miscfs/specfs/spec_vnops.c 4 Mar 2007 06:03:14 -0000 1.98 +++ sys/miscfs/specfs/spec_vnops.c 5 Jun 2007 12:31:32 -0000 1.99 @@ -1,4 +1,4 @@ -/* $NetBSD: spec_vnops.c,v 1.98 2007/03/04 06:03:14 christos Exp $ */ +/* $NetBSD: spec_vnops.c,v 1.99 2007/06/05 12:31:32 yamt Exp $ */ /* * Copyright (c) 1989, 1993 @@ -32,7 +32,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.98 2007/03/04 06:03:14 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.99 2007/06/05 12:31:32 yamt Exp $"); #include #include @@ -245,7 +245,8 @@ if (error) return error; if (!(*d_ioctl)(vp->v_rdev, DIOCGPART, (void *)&pi, FREAD, curlwp)) - vp->v_size = (voff_t)pi.disklab->d_secsize * pi.part->p_size; + uvm_vnp_setsize(vp, + (voff_t)pi.disklab->d_secsize * pi.part->p_size); return 0; } Index: sys/nfs/nfs_bio.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/nfs/nfs_bio.c,v retrieving revision 1.154 retrieving revision 1.155 diff -u -r1.154 -r1.155 --- sys/nfs/nfs_bio.c 9 May 2007 23:17:45 -0000 1.154 +++ sys/nfs/nfs_bio.c 5 Jun 2007 12:31:32 -0000 1.155 @@ -1,4 +1,4 @@ -/* $NetBSD: nfs_bio.c,v 1.154 2007/05/09 23:17:45 yamt Exp $ */ +/* $NetBSD: nfs_bio.c,v 1.155 2007/06/05 12:31:32 yamt Exp $ */ /* * Copyright (c) 1989, 1993 @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.154 2007/05/09 23:17:45 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.155 2007/06/05 12:31:32 yamt Exp $"); #include "opt_nfs.h" #include "opt_ddb.h" @@ -462,10 +462,9 @@ kauth_cred_t cred = ap->a_cred; struct vattr vattr; struct nfsmount *nmp = VFSTONFS(vp->v_mount); - void *win; voff_t oldoff, origoff; vsize_t bytelen; - int flags, error = 0; + int error = 0; int ioflag = ap->a_ioflag; int extended = 0, wrotedata = 0; @@ -519,7 +518,7 @@ origoff = uio->uio_offset; do { - bool extending; /* if we are extending whole pages */ + bool overwrite; /* if we are overwriting whole pages */ u_quad_t oldsize; oldoff = uio->uio_offset; bytelen = uio->uio_resid; @@ -531,17 +530,27 @@ if (np->n_size < uio->uio_offset + bytelen) { np->n_size = uio->uio_offset + bytelen; } - extending = ((uio->uio_offset & PAGE_MASK) == 0 && - (bytelen & PAGE_MASK) == 0 && - uio->uio_offset >= vp->v_size); - win = ubc_alloc(&vp->v_uobj, uio->uio_offset, &bytelen, - UVM_ADV_NORMAL, - UBC_WRITE | (extending ? UBC_FAULTBUSY : 0)); - error = uiomove(win, bytelen, uio); - flags = UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0; - ubc_release(win, flags); + overwrite = false; + if ((uio->uio_offset & PAGE_MASK) == 0) { + if ((vp->v_flag & VMAPPED) == 0 && + bytelen > PAGE_SIZE) { + bytelen = trunc_page(bytelen); + overwrite = true; + } else if ((bytelen & PAGE_MASK) == 0 && + uio->uio_offset >= vp->v_size) { + overwrite = true; + } + } + if (vp->v_size < uio->uio_offset + bytelen) { + uvm_vnp_setwritesize(vp, uio->uio_offset + bytelen); + } + error = ubc_uiomove(&vp->v_uobj, uio, bytelen, + UBC_WRITE | UBC_PARTIALOK | + (overwrite ? UBC_FAULTBUSY : 0) | + (UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0)); if (error) { - if (extending) { + uvm_vnp_setwritesize(vp, vp->v_size); + if (overwrite && np->n_size != oldsize) { /* * backout size and free pages past eof. */ Index: sys/sys/vnode.h =================================================================== RCS file: /e/cvsync/cvsync/src/sys/sys/vnode.h,v retrieving revision 1.168 retrieving revision 1.169 diff -u -r1.168 -r1.169 --- sys/sys/vnode.h 8 Apr 2007 11:20:50 -0000 1.168 +++ sys/sys/vnode.h 5 Jun 2007 12:31:33 -0000 1.169 @@ -1,4 +1,4 @@ -/* $NetBSD: vnode.h,v 1.168 2007/04/08 11:20:50 hannken Exp $ */ +/* $NetBSD: vnode.h,v 1.169 2007/06/05 12:31:33 yamt Exp $ */ /* * Copyright (c) 1989, 1993 @@ -98,6 +98,7 @@ #define v_usecount v_uobj.uo_refs #define v_interlock v_uobj.vmobjlock voff_t v_size; /* size of file */ + voff_t v_writesize; /* new size after write */ int v_flag; /* flags */ int v_numoutput; /* number of pending writes */ long v_writecount; /* reference count of writers */ Index: sys/ufs/ext2fs/ext2fs_inode.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/ufs/ext2fs/ext2fs_inode.c,v retrieving revision 1.58 retrieving revision 1.59 diff -u -r1.58 -r1.59 --- sys/ufs/ext2fs/ext2fs_inode.c 7 Apr 2007 14:21:52 -0000 1.58 +++ sys/ufs/ext2fs/ext2fs_inode.c 5 Jun 2007 12:31:33 -0000 1.59 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_inode.c,v 1.58 2007/04/07 14:21:52 hannken Exp $ */ +/* $NetBSD: ext2fs_inode.c,v 1.59 2007/06/05 12:31:33 yamt Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -65,7 +65,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.58 2007/04/07 14:21:52 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.59 2007/06/05 12:31:33 yamt Exp $"); #include #include @@ -290,6 +290,7 @@ * value of osize is 0, length will be at least 1. */ if (osize < length) { + uvm_vnp_setwritesize(ovp, length); error = ufs_balloc_range(ovp, length - 1, 1, cred, ioflag & IO_SYNC ? B_SYNC : 0); if (error) { Index: sys/ufs/ext2fs/ext2fs_readwrite.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/ufs/ext2fs/ext2fs_readwrite.c,v retrieving revision 1.46 retrieving revision 1.47 diff -u -r1.46 -r1.47 --- sys/ufs/ext2fs/ext2fs_readwrite.c 19 Apr 2007 11:05:14 -0000 1.46 +++ sys/ufs/ext2fs/ext2fs_readwrite.c 5 Jun 2007 12:31:33 -0000 1.47 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_readwrite.c,v 1.46 2007/04/19 11:05:14 yamt Exp $ */ +/* $NetBSD: ext2fs_readwrite.c,v 1.47 2007/06/05 12:31:33 yamt Exp $ */ /*- * Copyright (c) 1993 @@ -65,7 +65,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ext2fs_readwrite.c,v 1.46 2007/04/19 11:05:14 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_readwrite.c,v 1.47 2007/06/05 12:31:33 yamt Exp $"); #include #include @@ -305,6 +305,9 @@ bytelen = MIN(fs->e2fs_bsize - blkoffset, uio->uio_resid); + if (vp->v_size < oldoff + bytelen) { + uvm_vnp_setwritesize(vp, oldoff + bytelen); + } error = ufs_balloc_range(vp, uio->uio_offset, bytelen, ap->a_cred, 0); if (error) Index: sys/ufs/ext2fs/ext2fs_vfsops.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/ufs/ext2fs/ext2fs_vfsops.c,v retrieving revision 1.110 retrieving revision 1.111 diff -u -r1.110 -r1.111 --- sys/ufs/ext2fs/ext2fs_vfsops.c 12 Mar 2007 18:18:37 -0000 1.110 +++ sys/ufs/ext2fs/ext2fs_vfsops.c 5 Jun 2007 12:31:33 -0000 1.111 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_vfsops.c,v 1.110 2007/03/12 18:18:37 ad Exp $ */ +/* $NetBSD: ext2fs_vfsops.c,v 1.111 2007/06/05 12:31:33 yamt Exp $ */ /* * Copyright (c) 1989, 1991, 1993, 1994 @@ -65,7 +65,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.110 2007/03/12 18:18:37 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.111 2007/06/05 12:31:33 yamt Exp $"); #if defined(_KERNEL_OPT) #include "opt_compat_netbsd.h" @@ -1038,7 +1038,7 @@ if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) ip->i_flag |= IN_MODIFIED; } - vp->v_size = ext2fs_size(ip); + uvm_vnp_setsize(vp, ext2fs_size(ip)); *vpp = vp; return (0); } Index: sys/ufs/ffs/ffs_inode.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/ufs/ffs/ffs_inode.c,v retrieving revision 1.86 retrieving revision 1.87 diff -u -r1.86 -r1.87 --- sys/ufs/ffs/ffs_inode.c 4 Mar 2007 06:03:43 -0000 1.86 +++ sys/ufs/ffs/ffs_inode.c 5 Jun 2007 12:31:34 -0000 1.87 @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_inode.c,v 1.86 2007/03/04 06:03:43 christos Exp $ */ +/* $NetBSD: ffs_inode.c,v 1.87 2007/06/05 12:31:34 yamt Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -32,7 +32,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ffs_inode.c,v 1.86 2007/03/04 06:03:43 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ffs_inode.c,v 1.87 2007/06/05 12:31:34 yamt Exp $"); #if defined(_KERNEL_OPT) #include "opt_ffs.h" @@ -230,18 +230,19 @@ off_t eob; eob = blkroundup(fs, osize); + uvm_vnp_setwritesize(ovp, eob); error = ufs_balloc_range(ovp, osize, eob - osize, cred, aflag); if (error) return error; if (ioflag & IO_SYNC) { - ovp->v_size = eob; simple_lock(&ovp->v_interlock); VOP_PUTPAGES(ovp, trunc_page(osize & fs->fs_bmask), round_page(eob), PGO_CLEANIT | PGO_SYNCIO); } } + uvm_vnp_setwritesize(ovp, length); error = ufs_balloc_range(ovp, length - 1, 1, cred, aflag); if (error) { (void) ffs_truncate(ovp, osize, ioflag & IO_SYNC, Index: sys/ufs/ffs/ffs_vnops.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/ufs/ffs/ffs_vnops.c,v retrieving revision 1.87 retrieving revision 1.88 diff -u -r1.87 -r1.88 --- sys/ufs/ffs/ffs_vnops.c 17 May 2007 07:26:23 -0000 1.87 +++ sys/ufs/ffs/ffs_vnops.c 5 Jun 2007 12:31:34 -0000 1.88 @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_vnops.c,v 1.87 2007/05/17 07:26:23 hannken Exp $ */ +/* $NetBSD: ffs_vnops.c,v 1.88 2007/06/05 12:31:34 yamt Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -32,7 +32,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.87 2007/05/17 07:26:23 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.88 2007/06/05 12:31:34 yamt Exp $"); #include #include @@ -110,7 +110,7 @@ { &vop_pathconf_desc, ufs_pathconf }, /* pathconf */ { &vop_advlock_desc, ufs_advlock }, /* advlock */ { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ - { &vop_getpages_desc, ffs_getpages }, /* getpages */ + { &vop_getpages_desc, genfs_getpages }, /* getpages */ { &vop_putpages_desc, genfs_putpages }, /* putpages */ { &vop_openextattr_desc, ffs_openextattr }, /* openextattr */ { &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */ @@ -514,6 +514,7 @@ return (0); } +#if 0 int ffs_getpages(void *v) { @@ -548,6 +549,7 @@ } return genfs_getpages(v); } +#endif /* * Return the last logical file offset that should be written for this file Index: sys/ufs/lfs/lfs_inode.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/ufs/lfs/lfs_inode.c,v retrieving revision 1.109 retrieving revision 1.110 diff -u -r1.109 -r1.110 --- sys/ufs/lfs/lfs_inode.c 16 May 2007 19:11:37 -0000 1.109 +++ sys/ufs/lfs/lfs_inode.c 5 Jun 2007 12:31:34 -0000 1.110 @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_inode.c,v 1.109 2007/05/16 19:11:37 perseant Exp $ */ +/* $NetBSD: lfs_inode.c,v 1.110 2007/06/05 12:31:34 yamt Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -67,7 +67,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: lfs_inode.c,v 1.109 2007/05/16 19:11:37 perseant Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_inode.c,v 1.110 2007/06/05 12:31:34 yamt Exp $"); #if defined(_KERNEL_OPT) #include "opt_quota.h" @@ -284,12 +284,12 @@ off_t eob; eob = blkroundup(fs, osize); + uvm_vnp_setwritesize(ovp, eob); error = ufs_balloc_range(ovp, osize, eob - osize, cred, aflags); if (error) return error; if (ioflag & IO_SYNC) { - ovp->v_size = eob; simple_lock(&ovp->v_interlock); VOP_PUTPAGES(ovp, trunc_page(osize & fs->lfs_bmask), @@ -297,6 +297,7 @@ PGO_CLEANIT | PGO_SYNCIO); } } + uvm_vnp_setwritesize(ovp, length); error = ufs_balloc_range(ovp, length - 1, 1, cred, aflags); if (error) { Index: sys/ufs/ufs/ufs_readwrite.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/ufs/ufs/ufs_readwrite.c,v retrieving revision 1.78 retrieving revision 1.79 diff -u -r1.78 -r1.79 --- sys/ufs/ufs/ufs_readwrite.c 17 May 2007 07:26:23 -0000 1.78 +++ sys/ufs/ufs/ufs_readwrite.c 5 Jun 2007 12:31:35 -0000 1.79 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_readwrite.c,v 1.78 2007/05/17 07:26:23 hannken Exp $ */ +/* $NetBSD: ufs_readwrite.c,v 1.79 2007/06/05 12:31:35 yamt Exp $ */ /*- * Copyright (c) 1993 @@ -32,7 +32,7 @@ */ #include -__KERNEL_RCSID(1, "$NetBSD: ufs_readwrite.c,v 1.78 2007/05/17 07:26:23 hannken Exp $"); +__KERNEL_RCSID(1, "$NetBSD: ufs_readwrite.c,v 1.79 2007/06/05 12:31:35 yamt Exp $"); #ifdef LFS_READWRITE #define BLKSIZE(a, b, c) blksize(a, b, c) @@ -214,9 +214,7 @@ off_t osize, origoff, oldoff, preallocoff, endallocoff, nsize; int blkoffset, error, flags, ioflag, resid, size, xfersize; int aflag; - int ubc_alloc_flags, ubc_release_flags; int extended=0; - void *win; vsize_t bytelen; bool async; bool usepc = false; @@ -314,20 +312,20 @@ off_t eob; eob = blkroundup(fs, osize); + uvm_vnp_setwritesize(vp, eob); error = ufs_balloc_range(vp, osize, eob - osize, cred, aflag); if (error) goto out; if (flags & B_SYNC) { - vp->v_size = eob; simple_lock(&vp->v_interlock); VOP_PUTPAGES(vp, trunc_page(osize & fs->fs_bmask), round_page(eob), PGO_CLEANIT | PGO_SYNCIO); } } - ubc_alloc_flags = UBC_WRITE; while (uio->uio_resid > 0) { - bool extending; /* if we're extending a whole block */ + int ubc_flags = UBC_WRITE; + bool overwrite; /* if we're overwrite a whole block */ off_t newoff; if (ioflag & IO_DIRECT) { @@ -348,15 +346,31 @@ * since the new blocks will be inaccessible until the write * is complete. */ - extending = uio->uio_offset >= preallocoff && + overwrite = uio->uio_offset >= preallocoff && uio->uio_offset < endallocoff; + if (!overwrite && (vp->v_flag & VMAPPED) == 0 && + blkoff(fs, uio->uio_offset) == 0 && + (uio->uio_offset & PAGE_MASK) == 0) { + vsize_t len; + + len = trunc_page(bytelen); + len -= blkoff(fs, len); + if (len > 0) { + overwrite = true; + bytelen = len; + } + } - if (!extending) { + newoff = oldoff + bytelen; + if (vp->v_size < newoff) { + uvm_vnp_setwritesize(vp, newoff); + } + + if (!overwrite) { error = ufs_balloc_range(vp, uio->uio_offset, bytelen, cred, aflag); if (error) break; - ubc_alloc_flags &= ~UBC_FAULTBUSY; } else { genfs_node_wrlock(vp); error = GOP_ALLOC(vp, uio->uio_offset, bytelen, @@ -364,26 +378,15 @@ genfs_node_unlock(vp); if (error) break; - ubc_alloc_flags |= UBC_FAULTBUSY; + ubc_flags |= UBC_FAULTBUSY; } /* * copy the data. */ - win = ubc_alloc(&vp->v_uobj, uio->uio_offset, &bytelen, - UVM_ADV_NORMAL, ubc_alloc_flags); - error = uiomove(win, bytelen, uio); - if (error && extending) { - /* - * if we haven't initialized the pages yet, - * do it now. it's safe to use memset here - * because we just mapped the pages above. - */ - memset(win, 0, bytelen); - } - ubc_release_flags = UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0; - ubc_release(win, ubc_release_flags); + ubc_flags |= UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0; + error = ubc_uiomove(&vp->v_uobj, uio, bytelen, ubc_flags); /* * update UVM's notion of the size now that we've @@ -393,7 +396,6 @@ * otherwise ffs_truncate can't flush soft update states. */ - newoff = oldoff + bytelen; if (vp->v_size < newoff) { uvm_vnp_setsize(vp, newoff); extended = 1; Index: sys/uvm/uvm_bio.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/uvm/uvm_bio.c,v retrieving revision 1.57 retrieving revision 1.58 diff -u -r1.57 -r1.58 --- sys/uvm/uvm_bio.c 7 May 2007 12:39:45 -0000 1.57 +++ sys/uvm/uvm_bio.c 5 Jun 2007 12:31:35 -0000 1.58 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_bio.c,v 1.57 2007/05/07 12:39:45 yamt Exp $ */ +/* $NetBSD: uvm_bio.c,v 1.58 2007/06/05 12:31:35 yamt Exp $ */ /* * Copyright (c) 1998 Chuck Silvers. @@ -34,7 +34,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.57 2007/05/07 12:39:45 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.58 2007/06/05 12:31:35 yamt Exp $"); #include "opt_uvmhist.h" #include "opt_ubc.h" @@ -632,6 +632,50 @@ simple_unlock(&ubc_object.uobj.vmobjlock); } +/* + * ubc_uiomove: move data to/from an object. + */ + +int +ubc_uiomove(struct uvm_object *uobj, struct uio *uio, vsize_t todo, int flags) +{ + voff_t off; + const bool overwrite = (flags & UBC_FAULTBUSY) != 0; + int error; + + KASSERT(todo <= uio->uio_resid); + KASSERT(((flags & UBC_WRITE) != 0 && uio->uio_rw == UIO_WRITE) || + ((flags & UBC_READ) != 0 && uio->uio_rw == UIO_READ)); + + off = uio->uio_offset; + error = 0; + while (todo > 0) { + vsize_t bytelen = todo; + void *win; + + win = ubc_alloc(uobj, off, &bytelen, UVM_ADV_NORMAL, flags); + if (error == 0) { + error = uiomove(win, bytelen, uio); + } + if (error != 0 && overwrite) { + /* + * if we haven't initialized the pages yet, + * do it now. it's safe to use memset here + * because we just mapped the pages above. + */ + printf("%s: error=%d\n", __func__, error); + memset(win, 0, bytelen); + } + ubc_release(win, flags); + off += bytelen; + todo -= bytelen; + if (error != 0 && (flags & UBC_PARTIALOK) != 0) { + break; + } + } + + return error; +} #if 0 /* notused */ /* Index: sys/uvm/uvm_extern.h =================================================================== RCS file: /e/cvsync/cvsync/src/sys/uvm/uvm_extern.h,v retrieving revision 1.129 retrieving revision 1.130 diff -u -r1.129 -r1.130 --- sys/uvm/uvm_extern.h 24 Mar 2007 21:15:39 -0000 1.129 +++ sys/uvm/uvm_extern.h 5 Jun 2007 12:31:35 -0000 1.130 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_extern.h,v 1.129 2007/03/24 21:15:39 rmind Exp $ */ +/* $NetBSD: uvm_extern.h,v 1.130 2007/06/05 12:31:35 yamt Exp $ */ /* * @@ -189,14 +189,19 @@ /* * flags for ubc_alloc() */ -#define UBC_READ 0x01 -#define UBC_WRITE 0x02 -#define UBC_FAULTBUSY 0x04 +#define UBC_READ 0x001 +#define UBC_WRITE 0x002 +#define UBC_FAULTBUSY 0x004 /* * flags for ubc_release() */ -#define UBC_UNMAP 0x01 +#define UBC_UNMAP 0x010 + +/* + * flags for ubc_uiomve() + */ +#define UBC_PARTIALOK 0x100 /* * helpers for calling ubc_release() @@ -556,6 +561,8 @@ int); void ubc_release(void *, int); void ubc_flush(struct uvm_object *, voff_t, voff_t); +int ubc_uiomove(struct uvm_object *, struct uio *, vsize_t, + int); /* uvm_fault.c */ #define uvm_fault(m, a, p) uvm_fault_internal(m, a, p, 0) @@ -703,6 +710,7 @@ /* uvm_vnode.c */ void uvm_vnp_setsize(struct vnode *, voff_t); +void uvm_vnp_setwritesize(struct vnode *, voff_t); void uvm_vnp_sync(struct mount *); struct uvm_object *uvn_attach(void *, vm_prot_t); int uvn_findpages(struct uvm_object *, voff_t, Index: sys/uvm/uvm_vnode.c =================================================================== RCS file: /e/cvsync/cvsync/src/sys/uvm/uvm_vnode.c,v retrieving revision 1.81 retrieving revision 1.82 diff -u -r1.81 -r1.82 --- sys/uvm/uvm_vnode.c 4 Mar 2007 06:03:49 -0000 1.81 +++ sys/uvm/uvm_vnode.c 5 Jun 2007 12:31:36 -0000 1.82 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_vnode.c,v 1.81 2007/03/04 06:03:49 christos Exp $ */ +/* $NetBSD: uvm_vnode.c,v 1.82 2007/06/05 12:31:36 yamt Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -50,7 +50,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uvm_vnode.c,v 1.81 2007/03/04 06:03:49 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_vnode.c,v 1.82 2007/06/05 12:31:36 yamt Exp $"); #include "fs_nfs.h" #include "opt_uvmhist.h" @@ -212,7 +212,7 @@ UVMHIST_LOG(maphist,"<- done (VOP_GETATTR FAILED!)", 0,0,0,0); return(NULL); } - vp->v_size = used_vnode_size; + vp->v_size = vp->v_writesize = used_vnode_size; } @@ -469,15 +469,35 @@ * toss some pages... */ - oldsize = vp->v_size; + if (vp->v_writesize != VSIZENOTSET) { + KASSERT(vp->v_size <= vp->v_writesize); + KASSERT(vp->v_size == vp->v_writesize || + newsize == vp->v_writesize || newsize <= vp->v_size); + oldsize = vp->v_writesize; + } else { + oldsize = vp->v_size; + } if (oldsize > pgend && oldsize != VSIZENOTSET) { (void) uvn_put(uobj, pgend, 0, PGO_FREE | PGO_SYNCIO); simple_lock(&uobj->vmobjlock); } - vp->v_size = newsize; + vp->v_size = vp->v_writesize = newsize; simple_unlock(&uobj->vmobjlock); } +void +uvm_vnp_setwritesize(struct vnode *vp, voff_t newsize) +{ + + simple_lock(&vp->v_interlock); + KASSERT(vp->v_size != VSIZENOTSET); + KASSERT(vp->v_writesize != VSIZENOTSET); + KASSERT(vp->v_size <= vp->v_writesize); + KASSERT(vp->v_size <= newsize); + vp->v_writesize = newsize; + simple_unlock(&vp->v_interlock); +} + /* * uvm_vnp_zerorange: set a range of bytes in a file to zero. */