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:
parent
666d15456c
commit
9a0aaa5422
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue