mirror of
https://github.com/opnsense/src.git
synced 2026-04-01 15:35:10 -04:00
nfscl: Add a "has acquired a delegation" flag for delegations
A problem was reported via email, where a large (130000+) accumulation of NFSv4 opens on an NFSv4 mount caused significant lock contention on the mutex used to protect the client mount's open/lock state. Although the root cause for the accumulation of opens was not resolved, it is obvious that the NFSv4 client is not designed to handle 100000+ opens efficiently. For a common case where delegations are not being issued by the NFSv4 server, the code acquires the mutex lock for open/lock state, finds the delegation list empty and just unlocks the mutex and returns. This patch adds an NFS mount point flag that is set when a delegation is issued for the mount. Then the patched code checks for this flag before acquiring the open/lock mutex, avoiding the need to acquire the lock for the case where delegations are not being issued by the NFSv4 server. This change appears to be performance neutral for a small number of opens, but should reduce lock contention for a large number of opens for the common case where server is not issuing delegations. This commit should not affect the high level semantics of delegation handling. MFC after: 2 weeks
This commit is contained in:
parent
334335cb14
commit
5e5ca4c8fc
2 changed files with 42 additions and 3 deletions
|
|
@ -438,20 +438,32 @@ nfscl_deleg(mount_t mp, struct nfsclclient *clp, u_int8_t *nfhp,
|
|||
int fhlen, struct ucred *cred, NFSPROC_T *p, struct nfscldeleg **dpp)
|
||||
{
|
||||
struct nfscldeleg *dp = *dpp, *tdp;
|
||||
struct nfsmount *nmp;
|
||||
|
||||
KASSERT(mp != NULL, ("nfscl_deleg: mp NULL"));
|
||||
nmp = VFSTONFS(mp);
|
||||
/*
|
||||
* First, if we have received a Read delegation for a file on a
|
||||
* read/write file system, just return it, because they aren't
|
||||
* useful, imho.
|
||||
*/
|
||||
if (mp != NULL && dp != NULL && !NFSMNT_RDONLY(mp) &&
|
||||
if (dp != NULL && !NFSMNT_RDONLY(mp) &&
|
||||
(dp->nfsdl_flags & NFSCLDL_READ)) {
|
||||
(void) nfscl_trydelegreturn(dp, cred, VFSTONFS(mp), p);
|
||||
nfscl_trydelegreturn(dp, cred, nmp, p);
|
||||
free(dp, M_NFSCLDELEG);
|
||||
*dpp = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Since a delegation might be added to the mount,
|
||||
* set NFSMNTP_DELEGISSUED now. If a delegation already
|
||||
* exagain ists, setting this flag is harmless.
|
||||
*/
|
||||
NFSLOCKMNT(nmp);
|
||||
nmp->nm_privflag |= NFSMNTP_DELEGISSUED;
|
||||
NFSUNLOCKMNT(nmp);
|
||||
|
||||
/* Look for the correct deleg, based upon FH */
|
||||
NFSLOCKCLSTATE();
|
||||
tdp = nfscl_finddeleg(clp, nfhp, fhlen);
|
||||
|
|
@ -3356,12 +3368,20 @@ nfscl_delegreturnvp(vnode_t vp, NFSPROC_T *p)
|
|||
struct nfscldeleg *dp;
|
||||
struct ucred *cred;
|
||||
struct nfsnode *np;
|
||||
struct nfsmount *nmp;
|
||||
|
||||
nmp = VFSTONFS(vp->v_mount);
|
||||
NFSLOCKMNT(nmp);
|
||||
if ((nmp->nm_privflag & NFSMNTP_DELEGISSUED) == 0) {
|
||||
NFSUNLOCKMNT(nmp);
|
||||
return;
|
||||
}
|
||||
NFSUNLOCKMNT(nmp);
|
||||
np = VTONFS(vp);
|
||||
cred = newnfs_getcred();
|
||||
dp = NULL;
|
||||
NFSLOCKCLSTATE();
|
||||
clp = VFSTONFS(vp->v_mount)->nm_clp;
|
||||
clp = nmp->nm_clp;
|
||||
if (clp != NULL)
|
||||
dp = nfscl_finddeleg(clp, np->n_fhp->nfh_fh,
|
||||
np->n_fhp->nfh_len);
|
||||
|
|
@ -4500,6 +4520,12 @@ nfscl_nodeleg(vnode_t vp, int writedeleg)
|
|||
nmp = VFSTONFS(vp->v_mount);
|
||||
if (!NFSHASNFSV4(nmp))
|
||||
return (1);
|
||||
NFSLOCKMNT(nmp);
|
||||
if ((nmp->nm_privflag & NFSMNTP_DELEGISSUED) == 0) {
|
||||
NFSUNLOCKMNT(nmp);
|
||||
return (1);
|
||||
}
|
||||
NFSUNLOCKMNT(nmp);
|
||||
NFSLOCKCLSTATE();
|
||||
clp = nfscl_findcl(nmp);
|
||||
if (clp == NULL) {
|
||||
|
|
@ -4856,6 +4882,12 @@ nfscl_delegmodtime(vnode_t vp)
|
|||
nmp = VFSTONFS(vp->v_mount);
|
||||
if (!NFSHASNFSV4(nmp))
|
||||
return;
|
||||
NFSLOCKMNT(nmp);
|
||||
if ((nmp->nm_privflag & NFSMNTP_DELEGISSUED) == 0) {
|
||||
NFSUNLOCKMNT(nmp);
|
||||
return;
|
||||
}
|
||||
NFSUNLOCKMNT(nmp);
|
||||
NFSLOCKCLSTATE();
|
||||
clp = nfscl_findcl(nmp);
|
||||
if (clp == NULL) {
|
||||
|
|
@ -4885,6 +4917,12 @@ nfscl_deleggetmodtime(vnode_t vp, struct timespec *mtime)
|
|||
nmp = VFSTONFS(vp->v_mount);
|
||||
if (!NFSHASNFSV4(nmp))
|
||||
return;
|
||||
NFSLOCKMNT(nmp);
|
||||
if ((nmp->nm_privflag & NFSMNTP_DELEGISSUED) == 0) {
|
||||
NFSUNLOCKMNT(nmp);
|
||||
return;
|
||||
}
|
||||
NFSUNLOCKMNT(nmp);
|
||||
NFSLOCKCLSTATE();
|
||||
clp = nfscl_findcl(nmp);
|
||||
if (clp == NULL) {
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ struct nfsmount {
|
|||
#define NFSMNTP_NOXATTR 0x00000080
|
||||
#define NFSMNTP_NOADVISE 0x00000100
|
||||
#define NFSMNTP_NOALLOCATE 0x00000200
|
||||
#define NFSMNTP_DELEGISSUED 0x00000400
|
||||
|
||||
/* New mount flags only used by the kernel via nmount(2). */
|
||||
#define NFSMNT_TLS 0x00000001
|
||||
|
|
|
|||
Loading…
Reference in a new issue