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>
This commit is contained in:
parent
79719d2ea5
commit
23aacadb39
@ -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));
|
||||
|
@ -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) {
|
||||
|
@ -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); \
|
||||
|
@ -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) {
|
||||
|
@ -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); \
|
||||
|
@ -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));
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
@ -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); \
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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) {
|
||||
|
@ -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); \
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user