diff options
Diffstat (limited to 'fs/nfs/callback.c')
-rw-r--r-- | fs/nfs/callback.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index fcd97406a778..90c95adc8c1b 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/sunrpc/svc.h> | 14 | #include <linux/sunrpc/svc.h> |
15 | #include <linux/sunrpc/svcsock.h> | 15 | #include <linux/sunrpc/svcsock.h> |
16 | #include <linux/nfs_fs.h> | 16 | #include <linux/nfs_fs.h> |
17 | #include <linux/mutex.h> | ||
17 | 18 | ||
18 | #include <net/inet_sock.h> | 19 | #include <net/inet_sock.h> |
19 | 20 | ||
@@ -31,7 +32,7 @@ struct nfs_callback_data { | |||
31 | }; | 32 | }; |
32 | 33 | ||
33 | static struct nfs_callback_data nfs_callback_info; | 34 | static struct nfs_callback_data nfs_callback_info; |
34 | static DECLARE_MUTEX(nfs_callback_sema); | 35 | static DEFINE_MUTEX(nfs_callback_mutex); |
35 | static struct svc_program nfs4_callback_program; | 36 | static struct svc_program nfs4_callback_program; |
36 | 37 | ||
37 | unsigned int nfs_callback_set_tcpport; | 38 | unsigned int nfs_callback_set_tcpport; |
@@ -55,7 +56,12 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) | |||
55 | 56 | ||
56 | complete(&nfs_callback_info.started); | 57 | complete(&nfs_callback_info.started); |
57 | 58 | ||
58 | while (nfs_callback_info.users != 0 || !signalled()) { | 59 | for(;;) { |
60 | if (signalled()) { | ||
61 | if (nfs_callback_info.users == 0) | ||
62 | break; | ||
63 | flush_signals(current); | ||
64 | } | ||
59 | /* | 65 | /* |
60 | * Listen for a request on the socket | 66 | * Listen for a request on the socket |
61 | */ | 67 | */ |
@@ -73,6 +79,7 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) | |||
73 | svc_process(serv, rqstp); | 79 | svc_process(serv, rqstp); |
74 | } | 80 | } |
75 | 81 | ||
82 | svc_exit_thread(rqstp); | ||
76 | nfs_callback_info.pid = 0; | 83 | nfs_callback_info.pid = 0; |
77 | complete(&nfs_callback_info.stopped); | 84 | complete(&nfs_callback_info.stopped); |
78 | unlock_kernel(); | 85 | unlock_kernel(); |
@@ -89,7 +96,7 @@ int nfs_callback_up(void) | |||
89 | int ret = 0; | 96 | int ret = 0; |
90 | 97 | ||
91 | lock_kernel(); | 98 | lock_kernel(); |
92 | down(&nfs_callback_sema); | 99 | mutex_lock(&nfs_callback_mutex); |
93 | if (nfs_callback_info.users++ || nfs_callback_info.pid != 0) | 100 | if (nfs_callback_info.users++ || nfs_callback_info.pid != 0) |
94 | goto out; | 101 | goto out; |
95 | init_completion(&nfs_callback_info.started); | 102 | init_completion(&nfs_callback_info.started); |
@@ -115,7 +122,7 @@ int nfs_callback_up(void) | |||
115 | nfs_callback_info.serv = serv; | 122 | nfs_callback_info.serv = serv; |
116 | wait_for_completion(&nfs_callback_info.started); | 123 | wait_for_completion(&nfs_callback_info.started); |
117 | out: | 124 | out: |
118 | up(&nfs_callback_sema); | 125 | mutex_unlock(&nfs_callback_mutex); |
119 | unlock_kernel(); | 126 | unlock_kernel(); |
120 | return ret; | 127 | return ret; |
121 | out_destroy: | 128 | out_destroy: |
@@ -133,13 +140,15 @@ int nfs_callback_down(void) | |||
133 | int ret = 0; | 140 | int ret = 0; |
134 | 141 | ||
135 | lock_kernel(); | 142 | lock_kernel(); |
136 | down(&nfs_callback_sema); | 143 | mutex_lock(&nfs_callback_mutex); |
137 | if (--nfs_callback_info.users || nfs_callback_info.pid == 0) | 144 | nfs_callback_info.users--; |
138 | goto out; | 145 | do { |
139 | kill_proc(nfs_callback_info.pid, SIGKILL, 1); | 146 | if (nfs_callback_info.users != 0 || nfs_callback_info.pid == 0) |
140 | wait_for_completion(&nfs_callback_info.stopped); | 147 | break; |
141 | out: | 148 | if (kill_proc(nfs_callback_info.pid, SIGKILL, 1) < 0) |
142 | up(&nfs_callback_sema); | 149 | break; |
150 | } while (wait_for_completion_timeout(&nfs_callback_info.stopped, 5*HZ) == 0); | ||
151 | mutex_unlock(&nfs_callback_mutex); | ||
143 | unlock_kernel(); | 152 | unlock_kernel(); |
144 | return ret; | 153 | return ret; |
145 | } | 154 | } |