diff options
author | rmacklem <rmacklem@FreeBSD.org> | 2010-08-28 21:41:18 +0000 |
---|---|---|
committer | rmacklem <rmacklem@FreeBSD.org> | 2010-08-28 21:41:18 +0000 |
commit | 3b7498e206fce85bc672ab8f554bcd6ebc0b398f (patch) | |
tree | a22b84f7bb4316f13607b78f621510c2215914fc /sys/fs/nfs | |
parent | 10773ba533b6afc49c6a607ff7b4c8dd6a3e0950 (diff) | |
download | FreeBSD-src-3b7498e206fce85bc672ab8f554bcd6ebc0b398f.zip FreeBSD-src-3b7498e206fce85bc672ab8f554bcd6ebc0b398f.tar.gz |
The timer routine in the experimental NFS server did not acquire
the correct mutex when checking nfsv4root_lock. Although this
could be fixed by adding mutex lock/unlock calls, zack.kirsch at
isilon.com suggested a better fix that uses a non-blocking
acquisition of a reference count on nfsv4root_lock. This fix
allows the weird NFSLOCKSTATE(); NFSUNLOCKSTATE(); synchronization
to be deleted. This patch applies this fix.
Tested by: zack.kirsch at isilon.com
MFC after: 2 weeks
Diffstat (limited to 'sys/fs/nfs')
-rw-r--r-- | sys/fs/nfs/nfs_commonsubs.c | 15 | ||||
-rw-r--r-- | sys/fs/nfs/nfs_var.h | 1 |
2 files changed, 16 insertions, 0 deletions
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index dc5b2dc..6585fce 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -1824,6 +1824,21 @@ nfsv4_getref(struct nfsv4lock *lp, int *isleptp, void *mutex) } /* + * Get a reference as above, but return failure instead of sleeping if + * an exclusive lock is held. + */ +APPLESTATIC int +nfsv4_getref_nonblock(struct nfsv4lock *lp) +{ + + if ((lp->nfslock_lock & NFSV4LOCK_LOCK) != 0) + return (0); + + lp->nfslock_usecnt++; + return (1); +} + +/* * Test for a lock. Return 1 if locked, 0 otherwise. */ APPLESTATIC int diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h index d6ecda2..d46983f 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -251,6 +251,7 @@ int nfsv4_lock(struct nfsv4lock *, int, int *, void *); void nfsv4_unlock(struct nfsv4lock *, int); void nfsv4_relref(struct nfsv4lock *); void nfsv4_getref(struct nfsv4lock *, int *, void *); +int nfsv4_getref_nonblock(struct nfsv4lock *); int nfsv4_testlock(struct nfsv4lock *); int nfsrv_mtostr(struct nfsrv_descript *, char *, int); int nfsrv_checkutf8(u_int8_t *, int); |