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, |
