summaryrefslogtreecommitdiffstats
path: root/sys/nfsserver
diff options
context:
space:
mode:
authordwmalone <dwmalone@FreeBSD.org>2000-10-24 10:13:36 +0000
committerdwmalone <dwmalone@FreeBSD.org>2000-10-24 10:13:36 +0000
commit23aacadb399d3f3dd29eaa0a598b0359a2cd352a (patch)
tree85dc5320ff541ac0d2796e656cd50c2ebbf1bbf7 /sys/nfsserver
parent79719d2ea5f8674e63d2a884d88c38227a3f1e38 (diff)
downloadFreeBSD-src-23aacadb399d3f3dd29eaa0a598b0359a2cd352a.zip
FreeBSD-src-23aacadb399d3f3dd29eaa0a598b0359a2cd352a.tar.gz
Problem to avoid processes getting stuck in "vmopar". From Ian's
mail: The problem seems to originate with NFS's postop_attr information that is returned with a read or write RPC. Within a vm_fault context, the code cannot deal with vnode_pager_setsize() shrinking a vnode. The workaround in the patch below stops the nfsm_postop_attr() macro from ever shrinking a vnode. If the new size in the postop_attr information is smaller, then it just sets the nfsnode n_attrstamp to 0 to stop the wrong size getting used in the future. This change only affects postop_attr attributes; the nfsm_loadattr() macro works as normal. The change is implemented by adding a new argument to nfs_loadattrcache() called 'dontshrink'. When this is non-zero, nfs_loadattrcache() will never reduce the vnode/nfsnode size; instead it zeros n_attrstamp. There remain other was processes can get stuck in vmopar. Submitted by: Ian Dowse <iedowse@maths.tcd.ie> Reviewed by: dillon Tested by: Vadim Belman <voland@lflat.org>
Diffstat (limited to 'sys/nfsserver')
-rw-r--r--sys/nfsserver/nfs.h2
-rw-r--r--sys/nfsserver/nfs_srvsubs.c15
-rw-r--r--sys/nfsserver/nfsm_subs.h4
-rw-r--r--sys/nfsserver/nfsrvstats.h2
4 files changed, 16 insertions, 7 deletions
diff --git a/sys/nfsserver/nfs.h b/sys/nfsserver/nfs.h
index e07a4f5..5c5a823 100644
--- a/sys/nfsserver/nfs.h
+++ b/sys/nfsserver/nfs.h
@@ -616,7 +616,7 @@ int nfs_request __P((struct vnode *, struct mbuf *, int, struct proc *,
struct ucred *, struct mbuf **, struct mbuf **,
caddr_t *));
int nfs_loadattrcache __P((struct vnode **, struct mbuf **, caddr_t *,
- struct vattr *));
+ struct vattr *, int));
int nfs_namei __P((struct nameidata *, fhandle_t *, int,
struct nfssvc_sock *, struct sockaddr *, struct mbuf **,
caddr_t *, struct vnode **, struct proc *, int, int));
diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c
index 5934465..95f7d5b 100644
--- a/sys/nfsserver/nfs_srvsubs.c
+++ b/sys/nfsserver/nfs_srvsubs.c
@@ -1203,11 +1203,12 @@ nfs_uninit(vfsp)
* copy the attributes to *vaper
*/
int
-nfs_loadattrcache(vpp, mdp, dposp, vaper)
+nfs_loadattrcache(vpp, mdp, dposp, vaper, dontshrink)
struct vnode **vpp;
struct mbuf **mdp;
caddr_t *dposp;
struct vattr *vaper;
+ int dontshrink;
{
register struct vnode *vp = *vpp;
register struct vattr *vap;
@@ -1323,9 +1324,18 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
vap->va_filerev = 0;
}
+ np->n_attrstamp = time_second;
if (vap->va_size != np->n_size) {
if (vap->va_type == VREG) {
- if (np->n_flag & NMODIFIED) {
+ if (dontshrink && vap->va_size < np->n_size) {
+ /*
+ * We've been told not to shrink the file;
+ * zero np->n_attrstamp to indicate that
+ * the attributes are stale.
+ */
+ vap->va_size = np->n_size;
+ np->n_attrstamp = 0;
+ } else if (np->n_flag & NMODIFIED) {
if (vap->va_size < np->n_size)
vap->va_size = np->n_size;
else
@@ -1338,7 +1348,6 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
np->n_size = vap->va_size;
}
}
- np->n_attrstamp = time_second;
if (vaper != NULL) {
bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
if (np->n_flag & NCHG) {
diff --git a/sys/nfsserver/nfsm_subs.h b/sys/nfsserver/nfsm_subs.h
index b13c009..0990fe4 100644
--- a/sys/nfsserver/nfsm_subs.h
+++ b/sys/nfsserver/nfsm_subs.h
@@ -212,7 +212,7 @@ struct mbuf *nfsm_rpchead __P((struct ucred *cr, int nmflag, int procid,
#define nfsm_loadattr(v, a) \
do { \
struct vnode *ttvp = (v); \
- if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a))) != 0) { \
+ if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a), 0)) != 0) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
@@ -226,7 +226,7 @@ struct mbuf *nfsm_rpchead __P((struct ucred *cr, int nmflag, int procid,
nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
if (((f) = fxdr_unsigned(int, *tl)) != 0) { \
if ((t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
- (struct vattr *)0)) != 0) { \
+ (struct vattr *)0, 1)) != 0) { \
error = t1; \
(f) = 0; \
m_freem(mrep); \
diff --git a/sys/nfsserver/nfsrvstats.h b/sys/nfsserver/nfsrvstats.h
index e07a4f5..5c5a823 100644
--- a/sys/nfsserver/nfsrvstats.h
+++ b/sys/nfsserver/nfsrvstats.h
@@ -616,7 +616,7 @@ int nfs_request __P((struct vnode *, struct mbuf *, int, struct proc *,
struct ucred *, struct mbuf **, struct mbuf **,
caddr_t *));
int nfs_loadattrcache __P((struct vnode **, struct mbuf **, caddr_t *,
- struct vattr *));
+ struct vattr *, int));
int nfs_namei __P((struct nameidata *, fhandle_t *, int,
struct nfssvc_sock *, struct sockaddr *, struct mbuf **,
caddr_t *, struct vnode **, struct proc *, int, int));
OpenPOWER on IntegriCloud