improve post-ubc file overwrite performance in common cases.
ie. when it's safe, actually overwrite blocks rather than doing read-modify-write. also fixes PR/33152 and PR/36303.
This commit is contained in:
parent
ae34899ec3
commit
da51d139a4
|
@ -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 <sys/cdefs.h>
|
||||
__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 <sys/param.h>
|
||||
#include <sys/fstrans.h>
|
||||
|
@ -1552,7 +1552,6 @@ puffs_write(void *v)
|
|||
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 @@ puffs_write(void *v)
|
|||
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 @@ puffs_write(void *v)
|
|||
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;
|
||||
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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 @@ getnewvnode(enum vtagtype tag, struct mount *mp, int (**vops)(void *),
|
|||
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 @@ vfs_vnode_print(struct vnode *vp, int full, void (*pr)(const char *, ...))
|
|||
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,
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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 <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -425,7 +425,7 @@ genfs_getpages(void *v)
|
|||
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 @@ startover:
|
|||
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 @@ startover:
|
|||
|
||||
/*
|
||||
* 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;
|
||||
tailstart = bytes;
|
||||
while (tailbytes > 0) {
|
||||
const int len = PAGE_SIZE - (tailstart & PAGE_MASK);
|
||||
|
||||
if ((pgs[bytes >> PAGE_SHIFT]->flags & PG_FAKE) == 0) {
|
||||
tailstart = round_page(tailstart);
|
||||
tailbytes -= tailstart - bytes;
|
||||
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 @@ genfs_do_io(struct vnode *vp, off_t off, vaddr_t kva, size_t len, int flags,
|
|||
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;
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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 <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
|
@ -245,7 +245,8 @@ spec_open(v)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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 @@ nfs_write(v)
|
|||
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 @@ nfs_write(v)
|
|||
|
||||
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 @@ nfs_write(v)
|
|||
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.
|
||||
*/
|
||||
|
|
|
@ -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 @@ struct vnode {
|
|||
#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 */
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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 <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -290,6 +290,7 @@ ext2fs_truncate(struct vnode *ovp, off_t length, int ioflag,
|
|||
* 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) {
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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 <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -305,6 +305,9 @@ ext2fs_write(void *v)
|
|||
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)
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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 @@ ext2fs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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 @@ ffs_truncate(struct vnode *ovp, off_t length, int ioflag, kauth_cred_t cred,
|
|||
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,
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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 <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -110,7 +110,7 @@ const struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
|
|||
{ &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 @@ ffs_reclaim(void *v)
|
|||
return (0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
int
|
||||
ffs_getpages(void *v)
|
||||
{
|
||||
|
@ -548,6 +549,7 @@ ffs_getpages(void *v)
|
|||
}
|
||||
return genfs_getpages(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return the last logical file offset that should be written for this file
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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 @@ lfs_truncate(struct vnode *ovp, off_t length, int ioflag,
|
|||
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 @@ lfs_truncate(struct vnode *ovp, off_t length, int ioflag,
|
|||
PGO_CLEANIT | PGO_SYNCIO);
|
||||
}
|
||||
}
|
||||
uvm_vnp_setwritesize(ovp, length);
|
||||
error = ufs_balloc_range(ovp, length - 1, 1, cred,
|
||||
aflags);
|
||||
if (error) {
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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 @@ WRITE(void *v)
|
|||
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 @@ WRITE(void *v)
|
|||
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 @@ WRITE(void *v)
|
|||
* 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;
|
||||
|
||||
if (!extending) {
|
||||
len = trunc_page(bytelen);
|
||||
len -= blkoff(fs, len);
|
||||
if (len > 0) {
|
||||
overwrite = true;
|
||||
bytelen = len;
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ WRITE(void *v)
|
|||
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 @@ WRITE(void *v)
|
|||
* otherwise ffs_truncate can't flush soft update states.
|
||||
*/
|
||||
|
||||
newoff = oldoff + bytelen;
|
||||
if (vp->v_size < newoff) {
|
||||
uvm_vnp_setsize(vp, newoff);
|
||||
extended = 1;
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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 @@ ubc_release(void *va, int flags)
|
|||
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 */
|
||||
/*
|
||||
|
|
|
@ -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 @@ typedef voff_t pgoff_t; /* XXX: number of pages within a uvm object */
|
|||
/*
|
||||
* 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 @@ void * ubc_alloc(struct uvm_object *, voff_t, vsize_t *, int,
|
|||
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 @@ void uvm_deallocate(struct vm_map *, vaddr_t, vsize_t);
|
|||
|
||||
/* 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,
|
||||
|
|
|
@ -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 <sys/cdefs.h>
|
||||
__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 @@ uvn_attach(void *arg, vm_prot_t accessprot)
|
|||
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 @@ uvm_vnp_setsize(struct vnode *vp, voff_t newsize)
|
|||
* 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.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue