The patch titled knfsd: add a callback for when last rpc thread finishes has been added to the -mm tree. Its filename is knfsd-add-a-callback-for-when-last-rpc-thread-finishes.patch See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: knfsd: add a callback for when last rpc thread finishes From: NeilBrown <neilb@xxxxxxx> 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 <neilb@xxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- 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 -puN fs/lockd/svc.c~knfsd-add-a-callback-for-when-last-rpc-thread-finishes fs/lockd/svc.c --- a/fs/lockd/svc.c~knfsd-add-a-callback-for-when-last-rpc-thread-finishes +++ a/fs/lockd/svc.c @@ -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 -puN fs/nfsd/nfssvc.c~knfsd-add-a-callback-for-when-last-rpc-thread-finishes fs/nfsd/nfssvc.c --- a/fs/nfsd/nfssvc.c~knfsd-add-a-callback-for-when-last-rpc-thread-finishes +++ a/fs/nfsd/nfssvc.c @@ -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 -puN include/linux/sunrpc/svc.h~knfsd-add-a-callback-for-when-last-rpc-thread-finishes include/linux/sunrpc/svc.h --- a/include/linux/sunrpc/svc.h~knfsd-add-a-callback-for-when-last-rpc-thread-finishes +++ a/include/linux/sunrpc/svc.h @@ -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 -puN net/sunrpc/svc.c~knfsd-add-a-callback-for-when-last-rpc-thread-finishes net/sunrpc/svc.c --- a/net/sunrpc/svc.c~knfsd-add-a-callback-for-when-last-rpc-thread-finishes +++ a/net/sunrpc/svc.c @@ -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; @@ -39,6 +40,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; @@ -91,6 +93,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, _ Patches currently in -mm which might be from neilb@xxxxxxx are ext3-avoid-triggering-ext3_error-on-bad-nfs-file-handle.patch ext3-avoid-triggering-ext3_error-on-bad-nfs-file-handle-fix.patch git-klibc.patch ext3-reject-filehandles-referring-to-special-files.patch ext2-reject-file-handles-with-bad-inode-numbers-early.patch knfsd-knfsd-add-some-missing-newlines-in-printks.patch knfsd-knfsd-remove-an-unused-variable-from-e_show.patch knfsd-knfsd-remove-an-unused-variable-from-auth_unix_lookup.patch knfsd-add-a-callback-for-when-last-rpc-thread-finishes.patch knfsd-add-a-callback-for-when-last-rpc-thread-finishes-tidy.patch knfsd-be-more-selective-in-which-sockets-lockd-listens-on.patch knfsd-remove-nfsd_versbits-as-intermediate-storage-for-desired-versions.patch knfsd-separate-out-some-parts-of-nfsd_svc-which-start-nfs-servers.patch knfsd-separate-out-some-parts-of-nfsd_svc-which-start-nfs-servers-tweaks.patch knfsd-define-new-nfsdfs-file-portlist-contains-list-of-ports.patch knfsd-define-new-nfsdfs-file-portlist-contains-list-of-ports-tidy.patch knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist.patch md-dm-reduce-stack-usage-with-stacked-block-devices.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html