Page MenuHomeFreeBSD

D21883.id63070.diff
No OneTemporary

D21883.id63070.diff

Index: sys/fs/nfs/nfsport.h
===================================================================
--- sys/fs/nfs/nfsport.h
+++ sys/fs/nfs/nfsport.h
@@ -878,6 +878,7 @@
int nfscl_loadattrcache(struct vnode **, struct nfsvattr *, void *, void *,
int, int);
int newnfs_realign(struct mbuf **, int);
+bool ncl_pager_setsize(struct vnode *vp, u_quad_t *nsizep);
/*
* If the port runs on an SMP box that can enforce Atomic ops with low
Index: sys/fs/nfsclient/nfs_clport.c
===================================================================
--- sys/fs/nfsclient/nfs_clport.c
+++ sys/fs/nfsclient/nfs_clport.c
@@ -414,10 +414,7 @@
struct nfsnode *np;
struct nfsmount *nmp;
struct timespec mtime_save;
- vm_object_t object;
- u_quad_t nsize;
int error, force_fid_err;
- bool setnsize;
error = 0;
@@ -565,27 +562,42 @@
if (np->n_attrstamp != 0)
KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, vap, error);
#endif
+ (void)ncl_pager_setsize(vp, NULL);
+ return (error);
+}
+
+bool
+ncl_pager_setsize(struct vnode *vp, u_quad_t *nsizep)
+{
+ struct nfsnode *np;
+ vm_object_t object;
+ struct vattr *vap;
+ u_quad_t nsize;
+ bool setnsize;
+
+ np = VTONFS(vp);
+ NFSASSERTNODE(np);
+
+ vap = &np->n_vattr.na_vattr;
nsize = vap->va_size;
object = vp->v_object;
setnsize = false;
- if (object != NULL) {
- if (OFF_TO_IDX(nsize + PAGE_MASK) < object->size) {
- /*
- * When shrinking the size, the call to
- * vnode_pager_setsize() cannot be done with
- * the mutex held, because we might need to
- * wait for a busy page. Delay it until after
- * the node is unlocked.
- */
+
+ if (object != NULL && nsize != object->un_pager.vnp.vnp_size) {
+ if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE)
setnsize = true;
- } else {
+ else
+ np->n_flag |= NVNSETSZSKIP;
+ }
+ if (nsizep == NULL) {
+ NFSUNLOCKNODE(np);
+ if (setnsize)
vnode_pager_setsize(vp, nsize);
- }
+ setnsize = false;
+ } else {
+ *nsizep = nsize;
}
- NFSUNLOCKNODE(np);
- if (setnsize)
- vnode_pager_setsize(vp, nsize);
- return (error);
+ return (setnsize);
}
/*
Index: sys/fs/nfsclient/nfs_clsubs.c
===================================================================
--- sys/fs/nfsclient/nfs_clsubs.c
+++ sys/fs/nfsclient/nfs_clsubs.c
@@ -185,6 +185,8 @@
struct vattr *vap;
struct nfsmount *nmp;
int timeo, mustflush;
+ u_quad_t nsize;
+ bool setnsize;
np = VTONFS(vp);
vap = &np->n_vattr.na_vattr;
@@ -230,6 +232,7 @@
return( ENOENT);
}
nfsstatsv1.attrcache_hits++;
+ setnsize = false;
if (vap->va_size != np->n_size) {
if (vap->va_type == VREG) {
if (np->n_flag & NMODIFIED) {
@@ -240,7 +243,7 @@
} else {
np->n_size = vap->va_size;
}
- vnode_pager_setsize(vp, np->n_size);
+ setnsize = ncl_pager_setsize(vp, &nsize);
} else {
np->n_size = vap->va_size;
}
@@ -253,6 +256,8 @@
vaper->va_mtime = np->n_mtim;
}
NFSUNLOCKNODE(np);
+ if (setnsize)
+ vnode_pager_setsize(vp, nsize);
KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap);
return (0);
}
Index: sys/fs/nfsclient/nfs_clvnops.c
===================================================================
--- sys/fs/nfsclient/nfs_clvnops.c
+++ sys/fs/nfsclient/nfs_clvnops.c
@@ -142,6 +142,7 @@
static vop_advlockasync_t nfs_advlockasync;
static vop_getacl_t nfs_getacl;
static vop_setacl_t nfs_setacl;
+static vop_lock1_t nfs_lock;
/*
* Global vfs data structures for nfs
@@ -160,6 +161,7 @@
.vop_putpages = ncl_putpages,
.vop_inactive = ncl_inactive,
.vop_link = nfs_link,
+ .vop_lock1 = nfs_lock,
.vop_lookup = nfs_lookup,
.vop_mkdir = nfs_mkdir,
.vop_mknod = nfs_mknod,
@@ -295,6 +297,73 @@
* rep->r_mtx : Protects the fields in an nfsreq.
*/
+static int
+nfs_lock(struct vop_lock1_args *ap)
+{
+ struct vnode *vp;
+ struct nfsnode *np;
+ u_quad_t nsize;
+ int error, lktype;
+ bool onfault;
+
+ vp = ap->a_vp;
+ lktype = ap->a_flags & LK_TYPE_MASK;
+ error = VOP_LOCK1_APV(&default_vnodeops, ap);
+ if (error != 0 || vp->v_op != &newnfs_vnodeops)
+ return (error);
+ np = VTONFS(vp);
+ NFSLOCKNODE(np);
+ if ((np->n_flag & NVNSETSZSKIP) == 0 || (lktype != LK_SHARED &&
+ lktype != LK_EXCLUSIVE && lktype != LK_UPGRADE &&
+ lktype != LK_TRYUPGRADE)) {
+ NFSUNLOCKNODE(np);
+ return (0);
+ }
+ onfault = (ap->a_flags & LK_EATTR_MASK) == LK_NOWAIT &&
+ (ap->a_flags & LK_INIT_MASK) == LK_CANRECURSE &&
+ (lktype == LK_SHARED || lktype == LK_EXCLUSIVE);
+ if (onfault && vp->v_vnlock->lk_recurse == 0) {
+ /*
+ * Force retry in vm_fault(), to make the lock request
+ * sleepable, which allows us to piggy-back the
+ * sleepable call to vnode_pager_setsize().
+ */
+ NFSUNLOCKNODE(np);
+ VOP_UNLOCK(vp, 0);
+ return (EBUSY);
+ }
+ if ((ap->a_flags & LK_NOWAIT) != 0 ||
+ (lktype == LK_SHARED && vp->v_vnlock->lk_recurse > 0)) {
+ NFSUNLOCKNODE(np);
+ return (0);
+ }
+ if (lktype == LK_SHARED) {
+ NFSUNLOCKNODE(np);
+ VOP_UNLOCK(vp, 0);
+ ap->a_flags &= ~(LK_TYPE_MASK | LK_INTERLOCK);
+ ap->a_flags |= LK_EXCLUSIVE;
+ error = VOP_LOCK1_APV(&default_vnodeops, ap);
+ if (error != 0 || vp->v_op != &newnfs_vnodeops)
+ return (error);
+ NFSLOCKNODE(np);
+ if ((np->n_flag & NVNSETSZSKIP) == 0) {
+ NFSUNLOCKNODE(np);
+ goto downgrade;
+ }
+ }
+ np->n_flag &= ~NVNSETSZSKIP;
+ nsize = np->n_size;
+ NFSUNLOCKNODE(np);
+ vnode_pager_setsize(vp, nsize);
+downgrade:
+ if (lktype == LK_SHARED) {
+ ap->a_flags &= ~(LK_TYPE_MASK | LK_INTERLOCK);
+ ap->a_flags |= LK_DOWNGRADE;
+ (void)VOP_LOCK1_APV(&default_vnodeops, ap);
+ }
+ return (0);
+}
+
static int
nfs34_access_otw(struct vnode *vp, int wmode, struct thread *td,
struct ucred *cred, u_int32_t *retmode)
Index: sys/fs/nfsclient/nfsnode.h
===================================================================
--- sys/fs/nfsclient/nfsnode.h
+++ sys/fs/nfsclient/nfsnode.h
@@ -163,6 +163,7 @@
#define NWRITEOPENED 0x00040000 /* Has been opened for writing */
#define NHASBEENLOCKED 0x00080000 /* Has been file locked. */
#define NDSCOMMIT 0x00100000 /* Commit is done via the DS. */
+#define NVNSETSZSKIP 0x00200000 /* Skipped vnode_pager_setsize() */
/*
* Convert between nfsnode pointers and vnode pointers
Index: sys/vm/vm_fault.c
===================================================================
--- sys/vm/vm_fault.c
+++ sys/vm/vm_fault.c
@@ -839,7 +839,12 @@
*/
if (fs.object->type != OBJT_DEFAULT ||
fs.object == fs.first_object) {
- if (fs.pindex >= fs.object->size) {
+ /*
+ * The vnode case is handled later, after the
+ * vnode is locked and just before pagein.
+ */
+ if (fs.object->type != OBJT_VNODE &&
+ fs.pindex >= fs.object->size) {
unlock_and_deallocate(&fs);
return (KERN_OUT_OF_BOUNDS);
}
@@ -1031,6 +1036,11 @@
}
fs.vp = vp;
}
+ if (fs.object->type == OBJT_VNODE &&
+ fs.pindex >= fs.object->size) {
+ unlock_and_deallocate(&fs);
+ return (KERN_OUT_OF_BOUNDS);
+ }
KASSERT(fs.vp == NULL || !fs.map->system_map,
("vm_fault: vnode-backed object mapped by system map"));
Index: sys/vm/vnode_pager.c
===================================================================
--- sys/vm/vnode_pager.c
+++ sys/vm/vnode_pager.c
@@ -440,7 +440,7 @@
if ((object = vp->v_object) == NULL)
return;
-/* ASSERT_VOP_ELOCKED(vp, "vnode_pager_setsize and not locked vnode"); */
+ ASSERT_VOP_ELOCKED(vp, "vnode_pager_setsize and not locked vnode");
VM_OBJECT_WLOCK(object);
if (object->type == OBJT_DEAD) {
VM_OBJECT_WUNLOCK(object);

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 17, 4:58 AM (5 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29808487
Default Alt Text
D21883.id63070.diff (7 KB)

Event Timeline