Keep track of the maximum size we have supplied the file server (or

it has supplied us).  If we fault pages which are at offset >= server
size, but less than the in-kernel vnode size, inform the file server
of the latest developments in file size before issueing the fault.
The avoids confusion with files which are not written start to finish.

fixes kern/36429 by yamt
This commit is contained in:
pooka 2007-07-22 18:22:49 +00:00
parent 666d15456c
commit 9a0aaa5422
3 changed files with 63 additions and 23 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs_subr.c,v 1.41 2007/07/19 19:04:47 pooka Exp $ */
/* $NetBSD: puffs_subr.c,v 1.42 2007/07/22 18:22:49 pooka Exp $ */
/*
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: puffs_subr.c,v 1.41 2007/07/19 19:04:47 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: puffs_subr.c,v 1.42 2007/07/22 18:22:49 pooka Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@ -200,6 +200,7 @@ puffs_getvnode(struct mount *mp, void *cookie, enum vtype type,
vp->v_data = pnode;
vp->v_type = type;
pnode->pn_vp = vp;
pnode->pn_serversize = vsize;
genfs_node_init(vp, &puffs_genfsops);
*vpp = vp;

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs_sys.h,v 1.46 2007/07/17 11:29:43 pooka Exp $ */
/* $NetBSD: puffs_sys.h,v 1.47 2007/07/22 18:22:49 pooka Exp $ */
/*
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
@ -196,6 +196,8 @@ struct puffs_node {
struct timespec pn_mc_mtime;
u_quad_t pn_mc_size;
voff_t pn_serversize;
LIST_ENTRY(puffs_node) pn_hashent;
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs_vnops.c,v 1.89 2007/07/19 09:38:01 pooka Exp $ */
/* $NetBSD: puffs_vnops.c,v 1.90 2007/07/22 18:22:49 pooka Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.89 2007/07/19 09:38:01 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.90 2007/07/22 18:22:49 pooka Exp $");
#include <sys/param.h>
#include <sys/fstrans.h>
@ -757,26 +757,21 @@ puffs_getattr(void *v)
vap->va_size = pn->pn_mc_size;
} else {
if (rvap->va_size != VNOVAL
&& vp->v_type != VBLK && vp->v_type != VCHR)
&& vp->v_type != VBLK && vp->v_type != VCHR) {
uvm_vnp_setsize(vp, rvap->va_size);
pn->pn_serversize = rvap->va_size;
}
}
return 0;
}
int
puffs_setattr(void *v)
static int
puffs_dosetattr(struct vnode *vp, struct vattr *vap, kauth_cred_t cred,
struct lwp *l, int chsize)
{
struct vop_getattr_args /* {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
struct vattr *a_vap;
kauth_cred_t a_cred;
struct lwp *a_l;
} */ *ap = v;
struct puffs_node *pn = vp->v_data;
int error;
struct vattr *vap = ap->a_vap;
struct puffs_node *pn = ap->a_vp->v_data;
PUFFS_VNREQ(setattr);
@ -803,20 +798,37 @@ puffs_setattr(void *v)
}
(void)memcpy(&setattr_arg.pvnr_va, vap, sizeof(struct vattr));
puffs_credcvt(&setattr_arg.pvnr_cred, ap->a_cred);
puffs_cidcvt(&setattr_arg.pvnr_cid, ap->a_l);
puffs_credcvt(&setattr_arg.pvnr_cred, cred);
puffs_cidcvt(&setattr_arg.pvnr_cid, l);
error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_SETATTR,
&setattr_arg, sizeof(setattr_arg), 0, ap->a_vp, NULL);
error = puffs_vntouser(MPTOPUFFSMP(vp->v_mount), PUFFS_VN_SETATTR,
&setattr_arg, sizeof(setattr_arg), 0, vp, NULL);
if (error)
return error;
if (vap->va_size != VNOVAL)
uvm_vnp_setsize(ap->a_vp, vap->va_size);
if (vap->va_size != VNOVAL) {
pn->pn_serversize = vap->va_size;
if (chsize)
uvm_vnp_setsize(vp, vap->va_size);
}
return 0;
}
int
puffs_setattr(void *v)
{
struct vop_getattr_args /* {
const struct vnodeop_desc *a_desc;
struct vnode *a_vp;
struct vattr *a_vap;
kauth_cred_t a_cred;
struct lwp *a_l;
} */ *ap = v;
return puffs_dosetattr(ap->a_vp, ap->a_vap, ap->a_cred, ap->a_l, 1);
}
int
puffs_inactive(void *v)
{
@ -2168,6 +2180,7 @@ puffs_getpages(void *v)
int a_flags;
} */ *ap = v;
struct puffs_mount *pmp;
struct puffs_node *pn;
struct vnode *vp;
struct vm_page **pgs;
struct puffs_cacheinfo *pcinfo = NULL;
@ -2181,6 +2194,7 @@ puffs_getpages(void *v)
npages = *ap->a_count;
pgs = ap->a_m;
vp = ap->a_vp;
pn = vp->v_data;
locked = (ap->a_flags & PGO_LOCKED) != 0;
write = (ap->a_access_type & VM_PROT_WRITE) != 0;
@ -2188,6 +2202,29 @@ puffs_getpages(void *v)
pcrun = NULL;
runsizes = 0;
/*
* Check that we aren't trying to fault in pages which our file
* server doesn't know about. This happens if we extend a file by
* skipping some pages and later try to fault in pages which
* are between pn_serversize and vp_size. This check optimizes
* away the common case where a file is being extended.
*/
if (ap->a_offset >= pn->pn_serversize && ap->a_offset < vp->v_size) {
struct vattr va;
/* try again later when we can block */
if (locked)
ERROUT(EBUSY);
simple_unlock(&vp->v_interlock);
vattr_null(&va);
va.va_size = vp->v_size;
error = puffs_dosetattr(vp, &va, FSCRED, 0, 0);
if (error)
ERROUT(error);
simple_lock(&vp->v_interlock);
}
if (write && PUFFS_WCACHEINFO(pmp)) {
/* allocate worst-case memory */
runsizes = ((npages / 2) + 1) * sizeof(struct puffs_cacherun);