diff options
-rw-r--r-- | fs/lockd/svc.c | 2 | ||||
-rw-r--r-- | fs/nfs/callback.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfssvc.c | 40 | ||||
-rw-r--r-- | include/linux/sunrpc/svc.h | 8 | ||||
-rw-r--r-- | net/sunrpc/svc.c | 7 |
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 | ||
133 | static int killsig; /* signal that was used to kill last nfsd */ | ||
134 | static 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 | } | ||
133 | int | 147 | int |
134 | nfsd_svc(unsigned short port, int nrservs) | 148 | nfsd_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(¤t->pending.signal, signo) && | 362 | if (sigismember(¤t->pending.signal, signo) && |
354 | !sigismember(¤t->blocked, signo)) | 363 | !sigismember(¤t->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 | */ |
331 | struct svc_serv * svc_create(struct svc_program *, unsigned int); | 336 | struct svc_serv * svc_create(struct svc_program *, unsigned int, |
337 | void (*shutdown)(struct svc_serv*)); | ||
332 | int svc_create_thread(svc_thread_fn, struct svc_serv *); | 338 | int svc_create_thread(svc_thread_fn, struct svc_serv *); |
333 | void svc_exit_thread(struct svc_rqst *); | 339 | void svc_exit_thread(struct svc_rqst *); |
334 | void svc_destroy(struct svc_serv *); | 340 | void 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 | */ |
28 | struct svc_serv * | 28 | struct svc_serv * |
29 | svc_create(struct svc_program *prog, unsigned int bufsize) | 29 | svc_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, |