mirror of
https://github.com/opnsense/src.git
synced 2026-06-16 03:59:36 -04:00
nfsd: Avoid relocking vnode for NFSv4 Readdir
Without this patch, nfsv4_fillattr() relocks the vnode to test to see if extended attributes are supported. This is inefficient and could cause deadlocks if Readdir ever asks for this attribute. At this time, no extant NFSv4 client asks for this attribute for Readdir, but this patch fixes the problem in case a future client does so, by moving the test for extended attribute support to before the nfsv4_fillattr() call where the vnode is still locked. MFC after: 2 weeks
This commit is contained in:
parent
b153804256
commit
c00baac0ab
6 changed files with 40 additions and 29 deletions
|
|
@ -647,7 +647,8 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap,
|
|||
NFSATTRBIT_TIMECREATE))
|
||||
NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMECREATE);
|
||||
(void) nfsv4_fillattr(nd, vp->v_mount, vp, NULL, vap, NULL, 0,
|
||||
&attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL);
|
||||
&attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL,
|
||||
false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -2646,7 +2647,7 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
|
|||
NFSACL_T *saclp, struct vattr *vap, fhandle_t *fhp, int rderror,
|
||||
nfsattrbit_t *attrbitp, struct ucred *cred, NFSPROC_T *p, int isdgram,
|
||||
int reterr, int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno,
|
||||
struct statfs *pnfssf)
|
||||
struct statfs *pnfssf, bool xattrsupp)
|
||||
{
|
||||
int bitpos, retnum = 0;
|
||||
u_int32_t *tl;
|
||||
|
|
@ -2660,8 +2661,6 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
|
|||
struct nfsfsinfo fsinf;
|
||||
struct timespec temptime;
|
||||
NFSACL_T *aclp, *naclp = NULL;
|
||||
size_t atsiz;
|
||||
bool xattrsupp;
|
||||
short irflag;
|
||||
long has_pathconf;
|
||||
#ifdef QUOTA
|
||||
|
|
@ -2747,18 +2746,6 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
|
|||
}
|
||||
}
|
||||
|
||||
/* Check to see if Extended Attributes are supported. */
|
||||
xattrsupp = false;
|
||||
if (NFSISSET_ATTRBIT(retbitp, NFSATTRBIT_XATTRSUPPORT)) {
|
||||
if (NFSVOPLOCK(vp, LK_SHARED) == 0) {
|
||||
error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER,
|
||||
"xxx", NULL, &atsiz, cred, p);
|
||||
NFSVOPUNLOCK(vp);
|
||||
if (error != EOPNOTSUPP)
|
||||
xattrsupp = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Put out the attribute bitmap for the ones being filled in
|
||||
* and get the field for the number of attributes returned.
|
||||
|
|
|
|||
|
|
@ -395,8 +395,8 @@ int nfsrv_putopbit(struct nfsrv_descript *, nfsopbit_t *);
|
|||
void nfsrv_wcc(struct nfsrv_descript *, int, struct nfsvattr *, int,
|
||||
struct nfsvattr *);
|
||||
int nfsv4_fillattr(struct nfsrv_descript *, struct mount *, vnode_t, NFSACL_T *,
|
||||
struct vattr *, fhandle_t *, int, nfsattrbit_t *,
|
||||
struct ucred *, NFSPROC_T *, int, int, int, int, uint64_t, struct statfs *);
|
||||
struct vattr *, fhandle_t *, int, nfsattrbit_t *, struct ucred *,
|
||||
NFSPROC_T *, int, int, int, int, uint64_t, struct statfs *, bool);
|
||||
void nfsrv_fillattr(struct nfsrv_descript *, struct nfsvattr *);
|
||||
struct mbuf *nfsrv_adj(struct mbuf *, int, int);
|
||||
void nfsrv_postopattr(struct nfsrv_descript *, int, struct nfsvattr *);
|
||||
|
|
@ -735,7 +735,7 @@ int nfsvno_updfilerev(vnode_t, struct nfsvattr *, struct nfsrv_descript *,
|
|||
NFSPROC_T *);
|
||||
int nfsvno_fillattr(struct nfsrv_descript *, struct mount *, vnode_t,
|
||||
struct nfsvattr *, fhandle_t *, int, nfsattrbit_t *,
|
||||
struct ucred *, NFSPROC_T *, int, int, int, int, uint64_t);
|
||||
struct ucred *, NFSPROC_T *, int, int, int, int, uint64_t, bool);
|
||||
int nfsrv_sattr(struct nfsrv_descript *, vnode_t, struct nfsvattr *, nfsattrbit_t *,
|
||||
NFSACL_T *, NFSPROC_T *);
|
||||
int nfsv4_sattr(struct nfsrv_descript *, vnode_t, struct nfsvattr *, nfsattrbit_t *,
|
||||
|
|
|
|||
|
|
@ -5436,7 +5436,7 @@ nfsrpc_setaclrpc(vnode_t vp, struct ucred *cred, NFSPROC_T *p,
|
|||
NFSZERO_ATTRBIT(&attrbits);
|
||||
NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL);
|
||||
(void) nfsv4_fillattr(nd, vp->v_mount, vp, aclp, NULL, NULL, 0,
|
||||
&attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL);
|
||||
&attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL, false);
|
||||
error = nfscl_request(nd, vp, p, cred);
|
||||
if (error)
|
||||
return (error);
|
||||
|
|
|
|||
|
|
@ -3701,7 +3701,7 @@ nfscl_docb(struct nfsrv_descript *nd, NFSPROC_T *p)
|
|||
if (!error)
|
||||
(void) nfsv4_fillattr(nd, NULL, NULL, NULL, &va,
|
||||
NULL, 0, &rattrbits, NULL, p, 0, 0, 0, 0,
|
||||
(uint64_t)0, NULL);
|
||||
(uint64_t)0, NULL, false);
|
||||
break;
|
||||
case NFSV4OP_CBRECALL:
|
||||
NFSCL_DEBUG(4, "cbrecall\n");
|
||||
|
|
|
|||
|
|
@ -2112,7 +2112,8 @@ int
|
|||
nfsvno_fillattr(struct nfsrv_descript *nd, struct mount *mp, struct vnode *vp,
|
||||
struct nfsvattr *nvap, fhandle_t *fhp, int rderror, nfsattrbit_t *attrbitp,
|
||||
struct ucred *cred, struct thread *p, int isdgram, int reterr,
|
||||
int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno)
|
||||
int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno,
|
||||
bool xattrsupp)
|
||||
{
|
||||
struct statfs *sf;
|
||||
int error;
|
||||
|
|
@ -2131,7 +2132,7 @@ nfsvno_fillattr(struct nfsrv_descript *nd, struct mount *mp, struct vnode *vp,
|
|||
}
|
||||
error = nfsv4_fillattr(nd, mp, vp, NULL, &nvap->na_vattr, fhp, rderror,
|
||||
attrbitp, cred, p, isdgram, reterr, supports_nfsv4acls, at_root,
|
||||
mounted_on_fileno, sf);
|
||||
mounted_on_fileno, sf, xattrsupp);
|
||||
free(sf, M_TEMP);
|
||||
NFSEXITCODE2(0, nd);
|
||||
return (error);
|
||||
|
|
@ -2448,7 +2449,7 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram,
|
|||
struct nfsvattr nva, at, *nvap = &nva;
|
||||
struct mbuf *mb0, *mb1;
|
||||
struct nfsreferral *refp;
|
||||
int nlen, r, error = 0, getret = 1, usevget = 1;
|
||||
int nlen, r, error = 0, getret = 1, ret, usevget = 1;
|
||||
int siz, cnt, fullsiz, eofflag, ncookies, entrycnt;
|
||||
caddr_t bpos0, bpos1;
|
||||
u_int64_t off, toff, verf __unused;
|
||||
|
|
@ -2462,6 +2463,8 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram,
|
|||
uint64_t mounted_on_fileno;
|
||||
struct thread *p = curthread;
|
||||
int bextpg0, bextpg1, bextpgsiz0, bextpgsiz1;
|
||||
size_t atsiz;
|
||||
bool xattrsupp;
|
||||
|
||||
if (nd->nd_repstat) {
|
||||
nfsrv_postopattr(nd, getret, &at);
|
||||
|
|
@ -2936,9 +2939,18 @@ again:
|
|||
*tl++ = newnfs_true;
|
||||
txdr_hyper(*cookiep, tl);
|
||||
dirlen += nfsm_strtom(nd, dp->d_name, nlen);
|
||||
xattrsupp = false;
|
||||
if (nvp != NULL) {
|
||||
supports_nfsv4acls =
|
||||
nfs_supportsnfsv4acls(nvp);
|
||||
if (NFSISSET_ATTRBIT(&attrbits,
|
||||
NFSATTRBIT_XATTRSUPPORT)) {
|
||||
ret = VOP_GETEXTATTR(nvp,
|
||||
EXTATTR_NAMESPACE_USER,
|
||||
"xxx", NULL, &atsiz,
|
||||
nd->nd_cred, p);
|
||||
xattrsupp = ret != EOPNOTSUPP;
|
||||
}
|
||||
NFSVOPUNLOCK(nvp);
|
||||
} else
|
||||
supports_nfsv4acls = 0;
|
||||
|
|
@ -2958,13 +2970,13 @@ again:
|
|||
nvp, nvap, &nfh, r, &rderrbits,
|
||||
nd->nd_cred, p, isdgram, 0,
|
||||
supports_nfsv4acls, at_root,
|
||||
mounted_on_fileno);
|
||||
mounted_on_fileno, xattrsupp);
|
||||
} else {
|
||||
dirlen += nfsvno_fillattr(nd, new_mp,
|
||||
nvp, nvap, &nfh, r, &attrbits,
|
||||
nd->nd_cred, p, isdgram, 0,
|
||||
supports_nfsv4acls, at_root,
|
||||
mounted_on_fileno);
|
||||
mounted_on_fileno, xattrsupp);
|
||||
}
|
||||
if (nvp != NULL)
|
||||
vrele(nvp);
|
||||
|
|
@ -6356,7 +6368,7 @@ nfsrv_setacldsdorpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p,
|
|||
* the same type (VREG).
|
||||
*/
|
||||
nfsv4_fillattr(nd, NULL, vp, aclp, NULL, NULL, 0, &attrbits, NULL,
|
||||
NULL, 0, 0, 0, 0, 0, NULL);
|
||||
NULL, 0, 0, 0, 0, 0, NULL, false);
|
||||
error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
|
||||
NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
|
||||
if (error != 0) {
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,
|
|||
{
|
||||
struct nfsvattr nva;
|
||||
fhandle_t fh;
|
||||
int at_root = 0, error = 0, supports_nfsv4acls;
|
||||
int at_root = 0, error = 0, ret, supports_nfsv4acls;
|
||||
struct nfsreferral *refp;
|
||||
nfsattrbit_t attrbits, tmpbits;
|
||||
struct mount *mp;
|
||||
|
|
@ -250,6 +250,8 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,
|
|||
uint64_t mounted_on_fileno = 0;
|
||||
accmode_t accmode;
|
||||
struct thread *p = curthread;
|
||||
size_t atsiz;
|
||||
bool xattrsupp;
|
||||
|
||||
if (nd->nd_repstat)
|
||||
goto out;
|
||||
|
|
@ -307,6 +309,15 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,
|
|||
&nva, &attrbits, p);
|
||||
if (nd->nd_repstat == 0) {
|
||||
supports_nfsv4acls = nfs_supportsnfsv4acls(vp);
|
||||
xattrsupp = false;
|
||||
if (NFSISSET_ATTRBIT(&attrbits,
|
||||
NFSATTRBIT_XATTRSUPPORT)) {
|
||||
ret = VOP_GETEXTATTR(vp,
|
||||
EXTATTR_NAMESPACE_USER,
|
||||
"xxx", NULL, &atsiz, nd->nd_cred,
|
||||
p);
|
||||
xattrsupp = ret != EOPNOTSUPP;
|
||||
}
|
||||
mp = vp->v_mount;
|
||||
if (nfsrv_enable_crossmntpt != 0 &&
|
||||
vp->v_type == VDIR &&
|
||||
|
|
@ -340,7 +351,8 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,
|
|||
(void)nfsvno_fillattr(nd, mp, vp, &nva,
|
||||
&fh, 0, &attrbits, nd->nd_cred, p,
|
||||
isdgram, 1, supports_nfsv4acls,
|
||||
at_root, mounted_on_fileno);
|
||||
at_root, mounted_on_fileno,
|
||||
xattrsupp);
|
||||
vfs_unbusy(mp);
|
||||
}
|
||||
vrele(vp);
|
||||
|
|
|
|||
Loading…
Reference in a new issue