aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/callback.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/callback.c')
-rw-r--r--fs/nfs/callback.c31
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
33static struct nfs_callback_data nfs_callback_info; 34static struct nfs_callback_data nfs_callback_info;
34static DECLARE_MUTEX(nfs_callback_sema); 35static DEFINE_MUTEX(nfs_callback_mutex);
35static struct svc_program nfs4_callback_program; 36static struct svc_program nfs4_callback_program;
36 37
37unsigned int nfs_callback_set_tcpport; 38unsigned 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);
117out: 124out:
118 up(&nfs_callback_sema); 125 mutex_unlock(&nfs_callback_mutex);
119 unlock_kernel(); 126 unlock_kernel();
120 return ret; 127 return ret;
121out_destroy: 128out_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;
141out: 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}