nfsd has some cleanup that it wants to do when the last thread
exits, and there will shortly be some more.
So collect this all into one place and define a callback for
an rpc service to call when the service is about to be destroyed.
Signed-off-by: Neil Brown <[email protected]>
### Diffstat output
./fs/lockd/svc.c | 2 +-
./fs/nfsd/nfssvc.c | 40 ++++++++++++++++++----------------------
./include/linux/sunrpc/svc.h | 8 +++++++-
./net/sunrpc/svc.c | 7 ++++++-
4 files changed, 32 insertions(+), 25 deletions(-)
diff .prev/fs/lockd/svc.c ./fs/lockd/svc.c
--- .prev/fs/lockd/svc.c 2006-07-24 14:55:00.000000000 +1000
+++ ./fs/lockd/svc.c 2006-07-24 15:13:40.000000000 +1000
@@ -236,7 +236,7 @@ lockd_up(void)
"lockd_up: no pid, %d users??\n", nlmsvc_users);
error = -ENOMEM;
- serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE);
+ serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL);
if (!serv) {
printk(KERN_WARNING "lockd_up: create service failed\n");
goto out;
diff .prev/fs/nfsd/nfssvc.c ./fs/nfsd/nfssvc.c
--- .prev/fs/nfsd/nfssvc.c 2006-07-24 14:50:53.000000000 +1000
+++ ./fs/nfsd/nfssvc.c 2006-07-24 15:14:31.000000000 +1000
@@ -130,11 +130,25 @@ int nfsd_nrthreads(void)
return nfsd_serv->sv_nrthreads;
}
+static int killsig = 0; /* signal that was used to kill last nfsd */
+static void nfsd_last_thread(struct svc_serv *serv)
+{
+ /* When last nfsd thread exits we need to do some clean-up */
+ nfsd_serv = NULL;
+ nfsd_racache_shutdown();
+ nfs4_state_shutdown();
+
+ printk(KERN_WARNING "nfsd: last server has exited\n");
+ if (killsig != SIG_NOCLEAN) {
+ printk(KERN_WARNING "nfsd: unexporting all filesystems\n");
+ nfsd_export_flush();
+ }
+}
int
nfsd_svc(unsigned short port, int nrservs)
{
int error;
- int none_left, found_one, i;
+ int found_one, i;
struct list_head *victim;
lock_kernel();
@@ -197,7 +211,8 @@ nfsd_svc(unsigned short port, int nrserv
atomic_set(&nfsd_busy, 0);
error = -ENOMEM;
- nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE);
+ nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE,
+ nfsd_last_thread);
if (nfsd_serv == NULL)
goto out;
error = svc_makesock(nfsd_serv, IPPROTO_UDP, port);
@@ -231,13 +246,7 @@ nfsd_svc(unsigned short port, int nrserv
nrservs++;
}
failure:
- none_left = (nfsd_serv->sv_nrthreads == 1);
svc_destroy(nfsd_serv); /* Release server */
- if (none_left) {
- nfsd_serv = NULL;
- nfsd_racache_shutdown();
- nfs4_state_shutdown();
- }
out:
unlock_kernel();
return error;
@@ -353,7 +362,7 @@ nfsd(struct svc_rqst *rqstp)
if (sigismember(¤t->pending.signal, signo) &&
!sigismember(¤t->blocked, signo))
break;
- err = signo;
+ killsig = signo;
}
/* Clear signals before calling lockd_down() and svc_exit_thread() */
flush_signals(current);
@@ -362,19 +371,6 @@ nfsd(struct svc_rqst *rqstp)
/* Release lockd */
lockd_down();
-
- /* Check if this is last thread */
- if (serv->sv_nrthreads==1) {
-
- printk(KERN_WARNING "nfsd: last server has exited\n");
- if (err != SIG_NOCLEAN) {
- printk(KERN_WARNING "nfsd: unexporting all filesystems\n");
- nfsd_export_flush();
- }
- nfsd_serv = NULL;
- nfsd_racache_shutdown(); /* release read-ahead cache */
- nfs4_state_shutdown();
- }
list_del(&me.list);
nfsdstats.th_cnt --;
diff .prev/include/linux/sunrpc/svc.h ./include/linux/sunrpc/svc.h
--- .prev/include/linux/sunrpc/svc.h 2006-07-24 14:42:06.000000000 +1000
+++ ./include/linux/sunrpc/svc.h 2006-07-24 15:13:40.000000000 +1000
@@ -42,6 +42,11 @@ struct svc_serv {
int sv_tmpcnt; /* count of temporary sockets */
char * sv_name; /* service name */
+
+ void (*sv_shutdown)(struct svc_serv *serv);
+ /* Callback to use when last thread
+ * exits.
+ */
};
/*
@@ -311,7 +316,8 @@ typedef void (*svc_thread_fn)(struct sv
/*
* Function prototypes.
*/
-struct svc_serv * svc_create(struct svc_program *, unsigned int);
+struct svc_serv * svc_create(struct svc_program *, unsigned int,
+ void (*shutdown)(struct svc_serv*));
int svc_create_thread(svc_thread_fn, struct svc_serv *);
void svc_exit_thread(struct svc_rqst *);
void svc_destroy(struct svc_serv *);
diff .prev/net/sunrpc/svc.c ./net/sunrpc/svc.c
--- .prev/net/sunrpc/svc.c 2006-07-24 14:40:46.000000000 +1000
+++ ./net/sunrpc/svc.c 2006-07-24 15:13:40.000000000 +1000
@@ -26,7 +26,8 @@
* Create an RPC service
*/
struct svc_serv *
-svc_create(struct svc_program *prog, unsigned int bufsize)
+svc_create(struct svc_program *prog, unsigned int bufsize,
+ void (*shutdown)(struct svc_serv *serv))
{
struct svc_serv *serv;
int vers;
@@ -40,6 +41,7 @@ svc_create(struct svc_program *prog, uns
serv->sv_nrthreads = 1;
serv->sv_stats = prog->pg_stats;
serv->sv_bufsz = bufsize? bufsize : 4096;
+ serv->sv_shutdown = shutdown;
xdrsize = 0;
while (prog) {
prog->pg_lovers = prog->pg_nvers-1;
@@ -92,6 +94,9 @@ svc_destroy(struct svc_serv *serv)
sk_list);
svc_delete_socket(svsk);
}
+ if (serv->sv_shutdown)
+ serv->sv_shutdown(serv);
+
while (!list_empty(&serv->sv_permsocks)) {
svsk = list_entry(serv->sv_permsocks.next,
struct svc_sock,
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]