diff options
author | rmacklem <rmacklem@FreeBSD.org> | 2010-09-10 23:49:33 +0000 |
---|---|---|
committer | rmacklem <rmacklem@FreeBSD.org> | 2010-09-10 23:49:33 +0000 |
commit | 5120adc2800eb3369aa1263ee45dfc80738d4433 (patch) | |
tree | c526bfacc6337c82c67bd01964ef196aa9fdae87 /sys/fs | |
parent | 92f51406df5cac0f60fd61b7838cf4136653c13e (diff) | |
download | FreeBSD-src-5120adc2800eb3369aa1263ee45dfc80738d4433.zip FreeBSD-src-5120adc2800eb3369aa1263ee45dfc80738d4433.tar.gz |
This patch applies one of the two fixes suggested by
zack.kirsch at isilon.com for a race between nfsrv_freeopen()
and nfsrv_getlockfile() in the experimental NFS server that
he found during testing. Although nfsrv_freeopen() holds a
sleep lock on the lock file structure when called with
cansleep != 0, nfsrv_getlockfile() could still search the
list, once it acquired the NFSLOCKSTATE() mutex. I believe
that acquiring the mutex in nfsrv_freeopen() fixes the race.
MFC after: 2 weeks
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdstate.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c index a531751..df9f054 100644 --- a/sys/fs/nfsserver/nfs_nfsdstate.c +++ b/sys/fs/nfsserver/nfs_nfsdstate.c @@ -1085,8 +1085,11 @@ nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, NFSPROC_T *p) * associated with the open. * If there are locks associated with the open, the * nfslockfile structure can be freed via nfsrv_freelockowner(). - * (That is why the call must be here instead of after the loop.) + * Acquire the state mutex to avoid races with calls to + * nfsrv_getlockfile(). */ + if (cansleep != 0) + NFSLOCKSTATE(); if (lfp != NULL && LIST_EMPTY(&lfp->lf_open) && LIST_EMPTY(&lfp->lf_deleg) && LIST_EMPTY(&lfp->lf_lock) && LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) && @@ -1096,6 +1099,8 @@ nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, NFSPROC_T *p) ret = 1; } else ret = 0; + if (cansleep != 0) + NFSUNLOCKSTATE(); FREE((caddr_t)stp, M_NFSDSTATE); newnfsstats.srvopens--; nfsrv_openpluslock--; |