MFC: r259854

The NFSv4 server would call VOP_SETATTR() with a shared locked vnode
when a Getattr for a file is done by a client other than the one that
holds the file's delegation. This would only happen when delegations
are enabled and the problem is fixed by this patch.
This commit is contained in:
rmacklem 2014-01-01 02:49:45 +00:00
parent 0b3ac62883
commit e876d4736c
3 changed files with 12 additions and 5 deletions

View File

@ -613,7 +613,7 @@ void nfsvno_open(struct nfsrv_descript *, struct nameidata *, nfsquad_t,
nfsv4stateid_t *, struct nfsstate *, int *, struct nfsvattr *, int32_t *,
int, NFSACL_T *, nfsattrbit_t *, struct ucred *, NFSPROC_T *,
struct nfsexstuff *, vnode_t *);
void nfsvno_updfilerev(vnode_t, struct nfsvattr *, struct ucred *,
int nfsvno_updfilerev(vnode_t, struct nfsvattr *, struct ucred *,
NFSPROC_T *);
int nfsvno_fillattr(struct nfsrv_descript *, struct mount *, vnode_t,
struct nfsvattr *, fhandle_t *, int, nfsattrbit_t *,

View File

@ -1469,8 +1469,9 @@ nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp,
* Updates the file rev and sets the mtime and ctime
* to the current clock time, returning the va_filerev and va_Xtime
* values.
* Return ESTALE to indicate the vnode is VI_DOOMED.
*/
void
int
nfsvno_updfilerev(struct vnode *vp, struct nfsvattr *nvap,
struct ucred *cred, struct thread *p)
{
@ -1478,8 +1479,14 @@ nfsvno_updfilerev(struct vnode *vp, struct nfsvattr *nvap,
VATTR_NULL(&va);
vfs_timestamp(&va.va_mtime);
if (NFSVOPISLOCKED(vp) != LK_EXCLUSIVE) {
NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY);
if ((vp->v_iflag & VI_DOOMED) != 0)
return (ESTALE);
}
(void) VOP_SETATTR(vp, &va, cred);
(void) nfsvno_getattr(vp, nvap, cred, p, 1);
return (0);
}
/*

View File

@ -4853,15 +4853,15 @@ nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp,
nva.na_filerev > delegfilerev) ||
(NFSVNO_ISSETSIZE(&nva) &&
nva.na_size != nvap->na_size)) {
nfsvno_updfilerev(vp, nvap, cred, p);
error = nfsvno_updfilerev(vp, nvap, cred, p);
if (NFSVNO_ISSETSIZE(&nva))
nvap->na_size = nva.na_size;
}
}
} else
error = 0; /* Ignore callback errors for now. */
} else {
NFSUNLOCKSTATE();
}
error = 0;
out:
NFSEXITCODE2(error, nd);