svn commit: r354398 - in stable/12/sys/fs: nfs nfsclient
Konstantin Belousov
kib at FreeBSD.org
Wed Nov 6 15:11:53 UTC 2019
Author: kib
Date: Wed Nov 6 15:11:51 2019
New Revision: 354398
URL: https://svnweb.freebsd.org/changeset/base/354398
Log:
MFC r353891:
Fix interface between nfsclient and vnode pager.
Modified:
stable/12/sys/fs/nfs/nfsport.h
stable/12/sys/fs/nfsclient/nfs_clnode.c
stable/12/sys/fs/nfsclient/nfs_clport.c
stable/12/sys/fs/nfsclient/nfs_clsubs.c
stable/12/sys/fs/nfsclient/nfs_clvnops.c
stable/12/sys/fs/nfsclient/nfsnode.h
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/sys/fs/nfs/nfsport.h
==============================================================================
--- stable/12/sys/fs/nfs/nfsport.h Wed Nov 6 14:58:25 2019 (r354397)
+++ stable/12/sys/fs/nfs/nfsport.h Wed Nov 6 15:11:51 2019 (r354398)
@@ -880,6 +880,7 @@ MALLOC_DECLARE(M_NEWNFSDSESSION);
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
Modified: stable/12/sys/fs/nfsclient/nfs_clnode.c
==============================================================================
--- stable/12/sys/fs/nfsclient/nfs_clnode.c Wed Nov 6 14:58:25 2019 (r354397)
+++ stable/12/sys/fs/nfsclient/nfs_clnode.c Wed Nov 6 15:11:51 2019 (r354398)
@@ -162,6 +162,8 @@ ncl_nget(struct mount *mntp, u_int8_t *fhp, int fhsize
vp->v_type = VDIR;
vp->v_vflag |= VV_ROOT;
}
+
+ vp->v_vflag |= VV_VMSIZEVNLOCK;
np->n_fhp = malloc(sizeof (struct nfsfh) + fhsize,
M_NFSFH, M_WAITOK);
Modified: stable/12/sys/fs/nfsclient/nfs_clport.c
==============================================================================
--- stable/12/sys/fs/nfsclient/nfs_clport.c Wed Nov 6 14:58:25 2019 (r354397)
+++ stable/12/sys/fs/nfsclient/nfs_clport.c Wed Nov 6 15:11:51 2019 (r354398)
@@ -246,6 +246,8 @@ nfscl_nget(struct mount *mntp, struct vnode *dvp, stru
vp->v_type = VDIR;
vp->v_vflag |= VV_ROOT;
}
+
+ vp->v_vflag |= VV_VMSIZEVNLOCK;
np->n_fhp = nfhp;
/*
@@ -414,10 +416,7 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvatt
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 +564,53 @@ out:
if (np->n_attrstamp != 0)
KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, vap, error);
#endif
+ (void)ncl_pager_setsize(vp, NULL);
+ return (error);
+}
+
+/*
+ * Call vnode_pager_setsize() if the size of the node changed, as
+ * recorded in nfsnode vs. v_object, or delay the call if notifying
+ * the pager is not possible at the moment.
+ *
+ * If nsizep is non-NULL, the call is delayed and the new node size is
+ * provided. Caller should itself call vnode_pager_setsize() if
+ * function returned true. If nsizep is NULL, function tries to call
+ * vnode_pager_setsize() itself if needed and possible, and the nfs
+ * node is unlocked unconditionally, the return value is not useful.
+ */
+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);
}
/*
Modified: stable/12/sys/fs/nfsclient/nfs_clsubs.c
==============================================================================
--- stable/12/sys/fs/nfsclient/nfs_clsubs.c Wed Nov 6 14:58:25 2019 (r354397)
+++ stable/12/sys/fs/nfsclient/nfs_clsubs.c Wed Nov 6 15:11:51 2019 (r354398)
@@ -185,6 +185,8 @@ ncl_getattrcache(struct vnode *vp, struct vattr *vaper
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 @@ ncl_getattrcache(struct vnode *vp, struct vattr *vaper
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 @@ ncl_getattrcache(struct vnode *vp, struct vattr *vaper
} 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 @@ ncl_getattrcache(struct vnode *vp, struct vattr *vaper
vaper->va_mtime = np->n_mtim;
}
NFSUNLOCKNODE(np);
+ if (setnsize)
+ vnode_pager_setsize(vp, nsize);
KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap);
return (0);
}
Modified: stable/12/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- stable/12/sys/fs/nfsclient/nfs_clvnops.c Wed Nov 6 14:58:25 2019 (r354397)
+++ stable/12/sys/fs/nfsclient/nfs_clvnops.c Wed Nov 6 15:11:51 2019 (r354398)
@@ -142,6 +142,7 @@ static vop_advlock_t nfs_advlock;
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
@@ -159,6 +160,7 @@ struct vop_vector newnfs_vnodeops = {
.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,
@@ -269,6 +271,73 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_directio_allow_mmap
rep->r_mtx
* 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,
Modified: stable/12/sys/fs/nfsclient/nfsnode.h
==============================================================================
--- stable/12/sys/fs/nfsclient/nfsnode.h Wed Nov 6 14:58:25 2019 (r354397)
+++ stable/12/sys/fs/nfsclient/nfsnode.h Wed Nov 6 15:11:51 2019 (r354398)
@@ -163,6 +163,7 @@ struct nfsnode {
#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
More information about the svn-src-stable-12
mailing list