]>
Commit | Line | Data |
---|---|---|
9329f6f7 GKH |
1 | From 4a9be28c45bf02fa0436808bb6c0baeba30e120e Mon Sep 17 00:00:00 2001 |
2 | From: NeilBrown <neilb@suse.com> | |
3 | Date: Tue, 19 Mar 2019 11:33:24 +1100 | |
4 | Subject: NFS: fix mount/umount race in nlmclnt. | |
5 | ||
6 | From: NeilBrown <neilb@suse.com> | |
7 | ||
8 | commit 4a9be28c45bf02fa0436808bb6c0baeba30e120e upstream. | |
9 | ||
10 | If the last NFSv3 unmount from a given host races with a mount from the | |
11 | same host, we can destroy an nlm_host that is still in use. | |
12 | ||
13 | Specifically nlmclnt_lookup_host() can increment h_count on | |
14 | an nlm_host that nlmclnt_release_host() has just successfully called | |
15 | refcount_dec_and_test() on. | |
16 | Once nlmclnt_lookup_host() drops the mutex, nlm_destroy_host_lock() | |
17 | will be called to destroy the nlmclnt which is now in use again. | |
18 | ||
19 | The cause of the problem is that the dec_and_test happens outside the | |
20 | locked region. This is easily fixed by using | |
21 | refcount_dec_and_mutex_lock(). | |
22 | ||
23 | Fixes: 8ea6ecc8b075 ("lockd: Create client-side nlm_host cache") | |
24 | Cc: stable@vger.kernel.org (v2.6.38+) | |
25 | Signed-off-by: NeilBrown <neilb@suse.com> | |
26 | Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> | |
27 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
28 | ||
29 | --- | |
30 | fs/lockd/host.c | 3 +-- | |
31 | 1 file changed, 1 insertion(+), 2 deletions(-) | |
32 | ||
33 | --- a/fs/lockd/host.c | |
34 | +++ b/fs/lockd/host.c | |
35 | @@ -290,12 +290,11 @@ void nlmclnt_release_host(struct nlm_hos | |
36 | ||
37 | WARN_ON_ONCE(host->h_server); | |
38 | ||
39 | - if (refcount_dec_and_test(&host->h_count)) { | |
40 | + if (refcount_dec_and_mutex_lock(&host->h_count, &nlm_host_mutex)) { | |
41 | WARN_ON_ONCE(!list_empty(&host->h_lockowners)); | |
42 | WARN_ON_ONCE(!list_empty(&host->h_granted)); | |
43 | WARN_ON_ONCE(!list_empty(&host->h_reclaim)); | |
44 | ||
45 | - mutex_lock(&nlm_host_mutex); | |
46 | nlm_destroy_host_locked(host); | |
47 | mutex_unlock(&nlm_host_mutex); | |
48 | } |