diff options
author | Rick Macklem <rmacklem@FreeBSD.org> | 2019-12-28 22:24:16 +0000 |
---|---|---|
committer | Rick Macklem <rmacklem@FreeBSD.org> | 2019-12-28 22:24:16 +0000 |
commit | 39ea5e3b5bdea8cbdb3d4e96315610f4d21e9e25 (patch) | |
tree | 7c0c7980dde12d1feeaf0c6a6b94fbd347c72993 /sys/fs | |
parent | ba1755d072fc1edc8e5a2b4900f64eea509a5083 (diff) | |
download | src-test2-39ea5e3b5bdea8cbdb3d4e96315610f4d21e9e25.tar.gz src-test2-39ea5e3b5bdea8cbdb3d4e96315610f4d21e9e25.zip |
Notes
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/nfs/nfs.h | 3 | ||||
-rw-r--r-- | sys/fs/nfs/nfs_commonport.c | 4 | ||||
-rw-r--r-- | sys/fs/nfs/nfs_commonsubs.c | 47 | ||||
-rw-r--r-- | sys/fs/nfs/nfsport.h | 1 |
4 files changed, 44 insertions, 11 deletions
diff --git a/sys/fs/nfs/nfs.h b/sys/fs/nfs/nfs.h index e47f0d130c08..c6fb59fa6b64 100644 --- a/sys/fs/nfs/nfs.h +++ b/sys/fs/nfs/nfs.h @@ -797,6 +797,9 @@ struct nfsslot { struct mbuf *nfssl_reply; }; +/* Enumerated type for nfsuserd state. */ +typedef enum { NOTRUNNING=0, STARTSTOP=1, RUNNING=2 } nfsuserd_state; + #endif /* _KERNEL */ #endif /* _NFS_NFS_H */ diff --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c index 71f2726a81cb..1a1e64cd823b 100644 --- a/sys/fs/nfs/nfs_commonport.c +++ b/sys/fs/nfs/nfs_commonport.c @@ -56,7 +56,7 @@ __FBSDID("$FreeBSD$"); #include <vm/uma.h> extern int nfscl_ticks; -extern int nfsrv_nfsuserd; +extern nfsuserd_state nfsrv_nfsuserd; extern struct nfssockreq nfsrv_nfsuserdsock; extern void (*nfsd_call_recall)(struct vnode *, int, struct ucred *, struct thread *); @@ -774,7 +774,7 @@ nfscommon_modevent(module_t mod, int type, void *data) break; case MOD_UNLOAD: - if (newnfs_numnfsd != 0 || nfsrv_nfsuserd != 0 || + if (newnfs_numnfsd != 0 || nfsrv_nfsuserd != NOTRUNNING || nfs_numnfscbd != 0) { error = EBUSY; break; diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index 139aa583e139..9214674b99e1 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -64,7 +64,8 @@ struct timeval nfsboottime; /* Copy boottime once, so it never changes */ int nfscl_ticks; int nfsrv_useacl = 1; struct nfssockreq nfsrv_nfsuserdsock; -int nfsrv_nfsuserd = 0; +nfsuserd_state nfsrv_nfsuserd = NOTRUNNING; +static int nfsrv_userdupcalls = 0; struct nfsreqhead nfsd_reqq; uid_t nfsrv_defaultuid = UID_NOBODY; gid_t nfsrv_defaultgid = GID_NOGROUP; @@ -3524,18 +3525,22 @@ nfsrv_nfsuserdport(struct nfsuserd_args *nargs, NFSPROC_T *p) int error; NFSLOCKNAMEID(); - if (nfsrv_nfsuserd) { + if (nfsrv_nfsuserd != NOTRUNNING) { NFSUNLOCKNAMEID(); error = EPERM; goto out; } - nfsrv_nfsuserd = 1; - NFSUNLOCKNAMEID(); + nfsrv_nfsuserd = STARTSTOP; /* * Set up the socket record and connect. + * Set nr_client NULL before unlocking, just to ensure that no other + * process/thread/core will use a bogus old value. This could only + * occur if the use of the nameid lock to protect nfsrv_nfsuserd is + * broken. */ rp = &nfsrv_nfsuserdsock; rp->nr_client = NULL; + NFSUNLOCKNAMEID(); rp->nr_sotype = SOCK_DGRAM; rp->nr_soproto = IPPROTO_UDP; rp->nr_lock = (NFSR_RESERVEDPORT | NFSR_LOCALHOST); @@ -3571,9 +3576,15 @@ nfsrv_nfsuserdport(struct nfsuserd_args *nargs, NFSPROC_T *p) rp->nr_vers = RPCNFSUSERD_VERS; if (error == 0) error = newnfs_connect(NULL, rp, NFSPROCCRED(p), p, 0); - if (error) { + if (error == 0) { + NFSLOCKNAMEID(); + nfsrv_nfsuserd = RUNNING; + NFSUNLOCKNAMEID(); + } else { free(rp->nr_nam, M_SONAME); - nfsrv_nfsuserd = 0; + NFSLOCKNAMEID(); + nfsrv_nfsuserd = NOTRUNNING; + NFSUNLOCKNAMEID(); } out: NFSEXITCODE(error); @@ -3588,14 +3599,21 @@ nfsrv_nfsuserddelport(void) { NFSLOCKNAMEID(); - if (nfsrv_nfsuserd == 0) { + if (nfsrv_nfsuserd != RUNNING) { NFSUNLOCKNAMEID(); return; } - nfsrv_nfsuserd = 0; + nfsrv_nfsuserd = STARTSTOP; + /* Wait for all upcalls to complete. */ + while (nfsrv_userdupcalls > 0) + msleep(&nfsrv_userdupcalls, NFSNAMEIDMUTEXPTR, PVFS, + "nfsupcalls", 0); NFSUNLOCKNAMEID(); newnfs_disconnect(&nfsrv_nfsuserdsock); free(nfsrv_nfsuserdsock.nr_nam, M_SONAME); + NFSLOCKNAMEID(); + nfsrv_nfsuserd = NOTRUNNING; + NFSUNLOCKNAMEID(); } /* @@ -3614,12 +3632,19 @@ nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name, NFSPROC_T *p) int error; NFSLOCKNAMEID(); - if (nfsrv_nfsuserd == 0) { + if (nfsrv_nfsuserd != RUNNING) { NFSUNLOCKNAMEID(); error = EPERM; goto out; } + /* + * Maintain a count of upcalls in progress, so that nfsrv_X() + * can wait until no upcalls are in progress. + */ + nfsrv_userdupcalls++; NFSUNLOCKNAMEID(); + KASSERT(nfsrv_userdupcalls > 0, + ("nfsrv_getuser: non-positive upcalls")); nd = &nfsd; cred = newnfs_getcred(); nd->nd_flag = ND_GSSINITREPLY; @@ -3638,6 +3663,10 @@ nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name, NFSPROC_T *p) } error = newnfs_request(nd, NULL, NULL, &nfsrv_nfsuserdsock, NULL, NULL, cred, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, NULL, 0, NULL, NULL); + NFSLOCKNAMEID(); + if (--nfsrv_userdupcalls == 0 && nfsrv_nfsuserd == STARTSTOP) + wakeup(&nfsrv_userdupcalls); + NFSUNLOCKNAMEID(); NFSFREECRED(cred); if (!error) { mbuf_freem(nd->nd_mrep); diff --git a/sys/fs/nfs/nfsport.h b/sys/fs/nfs/nfsport.h index 560b3bd231c8..8abb6a5d1173 100644 --- a/sys/fs/nfs/nfsport.h +++ b/sys/fs/nfs/nfsport.h @@ -669,6 +669,7 @@ void nfsrvd_rcv(struct socket *, void *, int); #define NFSLOCKSOCK() mtx_lock(&nfs_slock_mutex) #define NFSUNLOCKSOCK() mtx_unlock(&nfs_slock_mutex) #define NFSNAMEIDMUTEX extern struct mtx nfs_nameid_mutex +#define NFSNAMEIDMUTEXPTR (&nfs_nameid_mutex) #define NFSLOCKNAMEID() mtx_lock(&nfs_nameid_mutex) #define NFSUNLOCKNAMEID() mtx_unlock(&nfs_nameid_mutex) #define NFSNAMEIDREQUIRED() mtx_assert(&nfs_nameid_mutex, MA_OWNED) |