aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/lockd/svc.c2
-rw-r--r--fs/nfs/callback.c2
-rw-r--r--fs/nfsd/nfssvc.c40
-rw-r--r--include/linux/sunrpc/svc.h8
-rw-r--r--net/sunrpc/svc.c7
5 files changed, 33 insertions, 26 deletions
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 9a991b52c647..13feba45030e 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -236,7 +236,7 @@ lockd_up(void)
236 "lockd_up: no pid, %d users??\n", nlmsvc_users); 236 "lockd_up: no pid, %d users??\n", nlmsvc_users);
237 237
238 error = -ENOMEM; 238 error = -ENOMEM;
239 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE); 239 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL);
240 if (!serv) { 240 if (!serv) {
241 printk(KERN_WARNING "lockd_up: create service failed\n"); 241 printk(KERN_WARNING "lockd_up: create service failed\n");
242 goto out; 242 goto out;
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index a3ee11364db0..e244cdc7afab 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -116,7 +116,7 @@ int nfs_callback_up(void)
116 goto out; 116 goto out;
117 init_completion(&nfs_callback_info.started); 117 init_completion(&nfs_callback_info.started);
118 init_completion(&nfs_callback_info.stopped); 118 init_completion(&nfs_callback_info.stopped);
119 serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE); 119 serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
120 ret = -ENOMEM; 120 ret = -ENOMEM;
121 if (!serv) 121 if (!serv)
122 goto out_err; 122 goto out_err;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index ec1decf29bab..c52c99964a4c 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -130,11 +130,25 @@ int nfsd_nrthreads(void)
130 return nfsd_serv->sv_nrthreads; 130 return nfsd_serv->sv_nrthreads;
131} 131}
132 132
133static int killsig; /* signal that was used to kill last nfsd */
134static void nfsd_last_thread(struct svc_serv *serv)
135{
136 /* When last nfsd thread exits we need to do some clean-up */
137 nfsd_serv = NULL;
138 nfsd_racache_shutdown();
139 nfs4_state_shutdown();
140
141 printk(KERN_WARNING "nfsd: last server has exited\n");
142 if (killsig != SIG_NOCLEAN) {
143 printk(KERN_WARNING "nfsd: unexporting all filesystems\n");
144 nfsd_export_flush();
145 }
146}
133int 147int
134nfsd_svc(unsigned short port, int nrservs) 148nfsd_svc(unsigned short port, int nrservs)
135{ 149{
136 int error; 150 int error;
137 int none_left, found_one, i; 151 int found_one, i;
138 struct list_head *victim; 152 struct list_head *victim;
139 153
140 lock_kernel(); 154 lock_kernel();
@@ -197,7 +211,8 @@ nfsd_svc(unsigned short port, int nrservs)
197 211
198 atomic_set(&nfsd_busy, 0); 212 atomic_set(&nfsd_busy, 0);
199 error = -ENOMEM; 213 error = -ENOMEM;
200 nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE); 214 nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE,
215 nfsd_last_thread);
201 if (nfsd_serv == NULL) 216 if (nfsd_serv == NULL)
202 goto out; 217 goto out;
203 error = svc_makesock(nfsd_serv, IPPROTO_UDP, port); 218 error = svc_makesock(nfsd_serv, IPPROTO_UDP, port);
@@ -231,13 +246,7 @@ nfsd_svc(unsigned short port, int nrservs)
231 nrservs++; 246 nrservs++;
232 } 247 }
233 failure: 248 failure:
234 none_left = (nfsd_serv->sv_nrthreads == 1);
235 svc_destroy(nfsd_serv); /* Release server */ 249 svc_destroy(nfsd_serv); /* Release server */
236 if (none_left) {
237 nfsd_serv = NULL;
238 nfsd_racache_shutdown();
239 nfs4_state_shutdown();
240 }
241 out: 250 out:
242 unlock_kernel(); 251 unlock_kernel();
243 return error; 252 return error;
@@ -353,7 +362,7 @@ nfsd(struct svc_rqst *rqstp)
353 if (sigismember(&current->pending.signal, signo) && 362 if (sigismember(&current->pending.signal, signo) &&
354 !sigismember(&current->blocked, signo)) 363 !sigismember(&current->blocked, signo))
355 break; 364 break;
356 err = signo; 365 killsig = signo;
357 } 366 }
358 /* Clear signals before calling lockd_down() and svc_exit_thread() */ 367 /* Clear signals before calling lockd_down() and svc_exit_thread() */
359 flush_signals(current); 368 flush_signals(current);
@@ -362,19 +371,6 @@ nfsd(struct svc_rqst *rqstp)
362 371
363 /* Release lockd */ 372 /* Release lockd */
364 lockd_down(); 373 lockd_down();
365
366 /* Check if this is last thread */
367 if (serv->sv_nrthreads==1) {
368
369 printk(KERN_WARNING "nfsd: last server has exited\n");
370 if (err != SIG_NOCLEAN) {
371 printk(KERN_WARNING "nfsd: unexporting all filesystems\n");
372 nfsd_export_flush();
373 }
374 nfsd_serv = NULL;
375 nfsd_racache_shutdown(); /* release read-ahead cache */
376 nfs4_state_shutdown();
377 }
378 list_del(&me.list); 374 list_del(&me.list);
379 nfsdstats.th_cnt --; 375 nfsdstats.th_cnt --;
380 376
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 73140ee5c638..bff5e9b486c2 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -42,6 +42,11 @@ struct svc_serv {
42 int sv_tmpcnt; /* count of temporary sockets */ 42 int sv_tmpcnt; /* count of temporary sockets */
43 43
44 char * sv_name; /* service name */ 44 char * sv_name; /* service name */
45
46 void (*sv_shutdown)(struct svc_serv *serv);
47 /* Callback to use when last thread
48 * exits.
49 */
45}; 50};
46 51
47/* 52/*
@@ -328,7 +333,8 @@ typedef void (*svc_thread_fn)(struct svc_rqst *);
328/* 333/*
329 * Function prototypes. 334 * Function prototypes.
330 */ 335 */
331struct svc_serv * svc_create(struct svc_program *, unsigned int); 336struct svc_serv * svc_create(struct svc_program *, unsigned int,
337 void (*shutdown)(struct svc_serv*));
332int svc_create_thread(svc_thread_fn, struct svc_serv *); 338int svc_create_thread(svc_thread_fn, struct svc_serv *);
333void svc_exit_thread(struct svc_rqst *); 339void svc_exit_thread(struct svc_rqst *);
334void svc_destroy(struct svc_serv *); 340void svc_destroy(struct svc_serv *);
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 44b8d9d4c18a..f5aee4c61676 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -26,7 +26,8 @@
26 * Create an RPC service 26 * Create an RPC service
27 */ 27 */
28struct svc_serv * 28struct svc_serv *
29svc_create(struct svc_program *prog, unsigned int bufsize) 29svc_create(struct svc_program *prog, unsigned int bufsize,
30 void (*shutdown)(struct svc_serv *serv))
30{ 31{
31 struct svc_serv *serv; 32 struct svc_serv *serv;
32 int vers; 33 int vers;
@@ -39,6 +40,7 @@ svc_create(struct svc_program *prog, unsigned int bufsize)
39 serv->sv_nrthreads = 1; 40 serv->sv_nrthreads = 1;
40 serv->sv_stats = prog->pg_stats; 41 serv->sv_stats = prog->pg_stats;
41 serv->sv_bufsz = bufsize? bufsize : 4096; 42 serv->sv_bufsz = bufsize? bufsize : 4096;
43 serv->sv_shutdown = shutdown;
42 xdrsize = 0; 44 xdrsize = 0;
43 while (prog) { 45 while (prog) {
44 prog->pg_lovers = prog->pg_nvers-1; 46 prog->pg_lovers = prog->pg_nvers-1;
@@ -91,6 +93,9 @@ svc_destroy(struct svc_serv *serv)
91 sk_list); 93 sk_list);
92 svc_delete_socket(svsk); 94 svc_delete_socket(svsk);
93 } 95 }
96 if (serv->sv_shutdown)
97 serv->sv_shutdown(serv);
98
94 while (!list_empty(&serv->sv_permsocks)) { 99 while (!list_empty(&serv->sv_permsocks)) {
95 svsk = list_entry(serv->sv_permsocks.next, 100 svsk = list_entry(serv->sv_permsocks.next,
96 struct svc_sock, 101 struct svc_sock,