Messages in this thread Patch in this message | | | Date | Fri, 19 Dec 1997 13:23:08 -0500 | From | Bill Hawes <> | Subject | patch for 2.1.73 lockd/nfsd/sunrpc |
| |
The attached (somewhat messy) patch cleans up signal handling and moves some code common to lockd and nfsd.
Summary of Changes: The identical xx_makesock() routines in lockd and nfsd have been moved to the sunrpc module, as suggested in the comments in lockd.
In lockd/svc.c sigpending is now cleared before doing an interruptible wait while the daemon exits. Pending signals were causing a spurious "failed to exit" message (because no wait was being done.)
In lockd/mon.c a warning message is added for rpc failures.
In nfsd/nfssvc.c the local makesock() code is replaced with the sunrpc code, and some signal blocking code is reworked slightly.
In sunrpc/clnt.c retries for garbage args are enabled.
In sunrpc/svc.c signal blocking code is replaced by clearing sigpending, and some additional error tests are added.
In sunrpc/sched.c, a test is added to warn if the rpciod task processes a sync request (which would block all other RPC tasks.) The sigpending flag is cleared when killing RPC tasks at shutdown, instead of blocking signals.
Regards, Bill--- linux-2.1.73/fs/lockd/svc.c.old Mon Dec 1 11:14:13 1997 +++ linux-2.1.73/fs/lockd/svc.c Fri Dec 19 10:24:25 1997 @@ -18,7 +18,6 @@ #include <linux/sched.h> #include <linux/errno.h> -#include <linux/nfs.h> #include <linux/in.h> #include <linux/uio.h> #include <linux/version.h> @@ -33,11 +32,11 @@ #include <linux/sunrpc/svc.h> #include <linux/sunrpc/svcsock.h> #include <linux/lockd/lockd.h> - +#include <linux/nfs.h> #define NLMDBG_FACILITY NLMDBG_SVC #define LOCKD_BUFSIZE (1024 + NLMSSVC_XDRSIZE) -#define BLOCKABLE_SIGS (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) +#define ALLOWED_SIGS (sigmask(SIGKILL) | sigmask(SIGSTOP)) extern struct svc_program nlmsvc_program; struct nlmsvc_binding * nlmsvc_ops = NULL; @@ -148,23 +147,22 @@ } dprintk("lockd: request from %08x\n", - (unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr)); + (unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr)); /* * Look up the NFS client handle. The handle is needed for * all but the GRANTED callback RPCs. */ + rqstp->rq_client = NULL; if (nlmsvc_ops) { nlmsvc_ops->exp_readlock(); rqstp->rq_client = nlmsvc_ops->exp_getclient(&rqstp->rq_addr); - } else { - rqstp->rq_client = NULL; } - /* Process request with all signals blocked. */ + /* Process request with signals blocked. */ spin_lock_irq(¤t->sigmask_lock); - siginitsetinv(¤t->blocked, ~BLOCKABLE_SIGS); + siginitsetinv(¤t->blocked, ALLOWED_SIGS); recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); @@ -202,22 +200,6 @@ } /* - * Make a socket for lockd - * FIXME: Move this to net/sunrpc/svc.c so that we can share this with nfsd. - */ -static int -lockd_makesock(struct svc_serv *serv, int protocol, unsigned short port) -{ - struct sockaddr_in sin; - - dprintk("lockd: creating socket proto = %d\n", protocol); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - sin.sin_port = htons(port); - return svc_create_socket(serv, protocol, &sin); -} - -/* * Bring up the lockd process if it's not already up. */ int @@ -252,8 +234,8 @@ goto out; } - if ((error = lockd_makesock(serv, IPPROTO_UDP, 0)) < 0 - || (error = lockd_makesock(serv, IPPROTO_TCP, 0)) < 0) { + if ((error = svc_makesock(serv, IPPROTO_UDP, 0)) < 0 + || (error = svc_makesock(serv, IPPROTO_TCP, 0)) < 0) { printk("lockd_up: makesock failed, error=%d\n", error); goto destroy_and_out; } @@ -302,13 +284,17 @@ * Wait for the lockd process to exit, but since we're holding * the lockd semaphore, we can't wait around forever ... */ - current->timeout = jiffies + 5 * HZ; + current->sigpending = 0; + current->timeout = jiffies + HZ; interruptible_sleep_on(&lockd_exit); current->timeout = 0; if (nlmsvc_pid) { printk("lockd_down: lockd failed to exit, clearing pid\n"); nlmsvc_pid = 0; } + spin_lock_irq(¤t->sigmask_lock); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); out: up(&nlmsvc_sema); } --- linux-2.1.73/fs/lockd/mon.c.old Mon Apr 7 14:35:30 1997 +++ linux-2.1.73/fs/lockd/mon.c Fri Dec 19 10:24:25 1997 @@ -33,29 +33,38 @@ nsm_mon_unmon(struct nlm_host *host, char *what, u32 proc) { struct rpc_clnt *clnt; + int status; struct nsm_args args; struct nsm_res res; - int status; dprintk("lockd: nsm_%s(%s)\n", what, host->h_name); - if (!(clnt = nsm_create())) - return -EACCES; + status = -EACCES; + clnt = nsm_create(); + if (!clnt) + goto out; args.addr = host->h_addr.sin_addr.s_addr; args.prog = NLM_PROGRAM; args.vers = 1; args.proc = NLMPROC_NSM_NOTIFY; - if ((status = rpc_call(clnt, proc, &args, &res, 0)) < 0) - return status; + status = rpc_call(clnt, proc, &args, &res, 0); + if (status < 0) { + printk(KERN_DEBUG "nsm_mon_unmon: rpc failed, status=%d\n", + status); + goto out; + } + status = -EACCES; if (res.status != 0) { printk(KERN_NOTICE "lockd: cannot %s %s\n", what, host->h_name); - return -EACCES; + goto out; } nsm_local_state = res.state; - return 0; + status = 0; +out: + return status; } /* @@ -66,7 +75,8 @@ { int status; - if ((status = nsm_mon_unmon(host, "monitor", SM_MON)) >= 0) + status = nsm_mon_unmon(host, "monitor", SM_MON); + if (status >= 0) host->h_monitored = 1; return status; } @@ -90,28 +100,32 @@ static struct rpc_clnt * nsm_create(void) { - struct sockaddr_in sin; struct rpc_xprt *xprt; - struct rpc_clnt *clnt; + struct rpc_clnt *clnt = NULL; + struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_port = 0; - if (!(xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL))) - return NULL; + xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL); + if (!xprt) + goto out; clnt = rpc_create_client(xprt, "localhost", &nsm_program, SM_VERSION, RPC_AUTH_NULL); - if (!clnt) { - xprt_destroy(xprt); - } else { - clnt->cl_softrtry = 1; - clnt->cl_chatty = 1; - clnt->cl_oneshot = 1; - } + if (!clnt) + goto out_destroy; + clnt->cl_softrtry = 1; + clnt->cl_chatty = 1; + clnt->cl_oneshot = 1; +out: return clnt; + +out_destroy: + xprt_destroy(xprt); + goto out; } /* --- linux-2.1.73/fs/nfsd/nfssvc.c.old Fri Dec 5 18:32:36 1997 +++ linux-2.1.73/fs/nfsd/nfssvc.c Fri Dec 19 11:55:36 1997 @@ -36,28 +36,13 @@ #define NFSDDBG_FACILITY NFSDDBG_SVC #define NFSD_BUFSIZE (1024 + NFSSVC_MAXBLKSIZE) -#define BLOCKABLE_SIGS (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -#define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM)) +#define ALLOWED_SIGS (sigmask(SIGKILL) | sigmask(SIGSTOP)) +#define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGTERM)) extern struct svc_program nfsd_program; static void nfsd(struct svc_rqst *rqstp); struct timeval nfssvc_boot = { 0, 0 }; -/* - * Make a socket for nfsd - */ -static int -nfsd_makesock(struct svc_serv *serv, int protocol, unsigned short port) -{ - struct sockaddr_in sin; - - dprintk("nfsd: creating socket proto = %d\n", protocol); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - sin.sin_port = htons(port); - return svc_create_socket(serv, protocol, &sin); -} - int nfsd_svc(unsigned short port, int nrservs) { @@ -65,17 +50,19 @@ int error; dprintk("nfsd: creating service\n"); + error = -EINVAL; if (nrservs < 0) - return -EINVAL; + goto out; if (nrservs > NFSD_MAXSERVS) nrservs = NFSD_MAXSERVS; + error = -ENOMEM; serv = svc_create(&nfsd_program, NFSD_BUFSIZE, NFSSVC_XDRSIZE); if (serv == NULL) - return -ENOMEM; + goto out; - if ((error = nfsd_makesock(serv, IPPROTO_UDP, port)) < 0 - || (error = nfsd_makesock(serv, IPPROTO_TCP, port)) < 0) + if ((error = svc_makesock(serv, IPPROTO_UDP, port)) < 0 + || (error = svc_makesock(serv, IPPROTO_TCP, port)) < 0) goto failure; while (nrservs--) { @@ -86,6 +73,7 @@ failure: svc_destroy(serv); /* Release server */ +out: return error; } @@ -98,16 +86,15 @@ struct svc_serv *serv = rqstp->rq_server; int oldumask, err; - lock_kernel(); /* Lock module and set up kernel thread */ MOD_INC_USE_COUNT; + lock_kernel(); exit_mm(current); current->session = 1; current->pgrp = 1; sprintf(current->comm, "nfsd"); oldumask = current->fs->umask; /* Set umask to 0. */ - siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); current->fs->umask = 0; nfssvc_boot = xtime; /* record boot time */ lockd_up(); /* start lockd */ @@ -116,6 +103,12 @@ * The main request loop */ for (;;) { + /* Block all but the shutdown signals */ + spin_lock_irq(¤t->sigmask_lock); + siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + /* * Find a socket with data available and call its * recvfrom routine. @@ -140,18 +133,13 @@ svc_drop(rqstp); serv->sv_stats->rpcbadclnt++; } else { - /* Process request with all signals blocked. */ + /* Process request with signals blocked. */ spin_lock_irq(¤t->sigmask_lock); - siginitsetinv(¤t->blocked, ~BLOCKABLE_SIGS); + siginitsetinv(¤t->blocked, ALLOWED_SIGS); recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); svc_process(serv, rqstp); - - spin_lock_irq(¤t->sigmask_lock); - siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); } /* Unlock export hash tables */ --- linux-2.1.73/net/sunrpc/clnt.c.old Mon Dec 1 11:14:21 1997 +++ linux-2.1.73/net/sunrpc/clnt.c Fri Dec 19 10:41:46 1997 @@ -753,8 +753,10 @@ rpc_exit(task, error); return NULL; } - if (!(p = rpcauth_checkverf(task, p))) + if (!(p = rpcauth_checkverf(task, p))) { + printk("call_verify: auth check failed\n"); goto garbage; /* bad verifier, retry */ + } switch ((n = ntohl(*p++))) { case RPC_SUCCESS: return p; @@ -768,7 +770,8 @@ garbage: dprintk("RPC: %4d call_verify: server saw garbage\n", task->tk_pid); task->tk_client->cl_stats->rpcgarbage++; - if (0 && task->tk_garb_retry--) { + if (task->tk_garb_retry--) { + printk("RPC: garbage, retrying %4d\n", task->tk_pid); task->tk_action = call_encode; return NULL; } --- linux-2.1.73/net/sunrpc/svc.c.old Fri Dec 19 00:22:37 1997 +++ linux-2.1.73/net/sunrpc/svc.c Fri Dec 19 10:41:46 1997 @@ -172,7 +172,6 @@ { struct svc_program *progp; unsigned long flags; - sigset_t old_set; int i, error = 0, dummy; progp = serv->sv_program; @@ -180,18 +179,8 @@ dprintk("RPC: svc_register(%s, %s, %d)\n", progp->pg_name, proto == IPPROTO_UDP? "udp" : "tcp", port); - /* FIXME: What had been going on before was saving and restoring - current->signal. This as opposed to blocking signals? Do we - still need them to wake up out of schedule? In any case it - isn't playing nice and a better way should be found. */ - - if (!port) { - spin_lock_irqsave(¤t->sigmask_lock, flags); - old_set = current->blocked; - sigfillset(¤t->blocked); - recalc_sigpending(current); - spin_unlock_irqrestore(¤t->sigmask_lock, flags); - } + if (!port) + current->sigpending = 0; for (i = 0; i < progp->pg_nvers; i++) { if (progp->pg_vers[i] == NULL) @@ -207,7 +196,6 @@ if (!port) { spin_lock_irqsave(¤t->sigmask_lock, flags); - current->blocked = old_set; recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags); } @@ -235,7 +223,7 @@ bufp = argp->buf; if (argp->len < 5) - goto dropit; + goto err_short_len; dir = ntohl(*bufp++); vers = ntohl(*bufp++); @@ -244,10 +232,8 @@ svc_putlong(resp, xdr_one); /* REPLY */ svc_putlong(resp, xdr_zero); /* ACCEPT */ - if (dir != 0) { /* direction != CALL */ - serv->sv_stats->rpcbadfmt++; - goto dropit; /* drop request */ - } + if (dir != 0) /* direction != CALL */ + goto err_bad_dir; if (vers != 2) /* RPC version number */ goto err_bad_rpc; @@ -281,7 +267,7 @@ procp = versp->vs_proc + proc; if (proc >= versp->vs_nproc || !procp->pc_func) - goto err_unknown; + goto err_bad_proc; rqstp->rq_server = serv; rqstp->rq_procinfo = procp; @@ -329,21 +315,36 @@ if (procp->pc_release) procp->pc_release(rqstp, NULL, rqstp->rq_resp); - if (procp->pc_encode != NULL) - return svc_send(rqstp); + if (procp->pc_encode == NULL) + goto dropit; +sendit: + return svc_send(rqstp); dropit: dprintk("svc: svc_process dropit\n"); svc_drop(rqstp); return 0; +err_short_len: +#ifdef RPC_PARANOIA + printk("svc: short len %d, dropping request\n", argp->len); +#endif + goto dropit; /* drop request */ + +err_bad_dir: +#ifdef RPC_PARANOIA + printk("svc: bad direction %d, dropping request\n", dir); +#endif + serv->sv_stats->rpcbadfmt++; + goto dropit; /* drop request */ + err_bad_rpc: serv->sv_stats->rpcbadfmt++; resp->buf[-1] = xdr_one; /* REJECT */ svc_putlong(resp, xdr_zero); /* RPC_MISMATCH */ svc_putlong(resp, xdr_two); /* Only RPCv2 supported */ svc_putlong(resp, xdr_two); - goto error; + goto sendit; err_bad_auth: dprintk("svc: authentication failed (%ld)\n", ntohl(auth_stat)); @@ -351,7 +352,7 @@ resp->buf[-1] = xdr_one; /* REJECT */ svc_putlong(resp, xdr_one); /* AUTH_ERROR */ svc_putlong(resp, auth_stat); /* status */ - goto error; + goto sendit; err_bad_prog: #ifdef RPC_PARANOIA @@ -359,7 +360,7 @@ #endif serv->sv_stats->rpcbadfmt++; svc_putlong(resp, rpc_prog_unavail); - goto error; + goto sendit; err_bad_vers: #ifdef RPC_PARANOIA @@ -369,15 +370,15 @@ svc_putlong(resp, rpc_prog_mismatch); svc_putlong(resp, htonl(progp->pg_lovers)); svc_putlong(resp, htonl(progp->pg_hivers)); - goto error; + goto sendit; -err_unknown: +err_bad_proc: #ifdef RPC_PARANOIA printk("svc: unknown procedure (%d)\n", proc); #endif serv->sv_stats->rpcbadfmt++; svc_putlong(resp, rpc_proc_unavail); - goto error; + goto sendit; err_garbage: #ifdef RPC_PARANOIA @@ -385,7 +386,5 @@ #endif serv->sv_stats->rpcbadfmt++; svc_putlong(resp, rpc_garbage_args); - -error: - return svc_send(rqstp); + goto sendit; } --- linux-2.1.73/net/sunrpc/sched.c.old Wed Dec 3 10:42:35 1997 +++ linux-2.1.73/net/sunrpc/sched.c Fri Dec 19 10:41:46 1997 @@ -388,6 +388,8 @@ /* sync task: sleep here */ dprintk("RPC: %4d sync task going to sleep\n", task->tk_pid); + if (current->pid == rpciod_pid) + printk("RPC: rpciod waiting on sync task!\n"); current->timeout = 0; sleep_on(&task->tk_wait); @@ -792,29 +794,21 @@ rpciod_killall(void) { unsigned long flags; - sigset_t old_set; - - /* FIXME: What had been going on before was saving and restoring - current->signal. This as opposed to blocking signals? Do we - still need them to wake up out of schedule? In any case it - isn't playing nice and a better way should be found. */ - - spin_lock_irqsave(¤t->sigmask_lock, flags); - old_set = current->blocked; - sigfillset(¤t->blocked); - recalc_sigpending(current); - spin_unlock_irqrestore(¤t->sigmask_lock, flags); while (all_tasks) { + current->sigpending = 0; rpc_killall_tasks(NULL); __rpc_schedule(); - current->timeout = jiffies + HZ / 100; - need_resched = 1; - schedule(); + if (all_tasks) { +printk("rpciod_killall: waiting for tasks to exit\n"); + current->state = TASK_INTERRUPTIBLE; + current->timeout = jiffies + 1; + schedule(); + current->timeout = 0; + } } spin_lock_irqsave(¤t->sigmask_lock, flags); - current->blocked = old_set; recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags); } --- linux-2.1.73/net/sunrpc/svcsock.c.old Mon Dec 1 23:57:00 1997 +++ linux-2.1.73/net/sunrpc/svcsock.c Fri Dec 19 10:41:46 1997 @@ -886,7 +886,7 @@ /* * Create socket for RPC service. */ -int +static int svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin) { struct svc_sock *svsk; @@ -969,3 +969,19 @@ /* svsk->sk_server = NULL; */ } } + +/* + * Make a socket for nfsd and lockd + */ +int +svc_makesock(struct svc_serv *serv, int protocol, unsigned short port) +{ + struct sockaddr_in sin; + + dprintk("svc: creating socket proto = %d\n", protocol); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + sin.sin_port = htons(port); + return svc_create_socket(serv, protocol, &sin); +} + --- linux-2.1.73/net/sunrpc/sunrpc_syms.c.old Mon Dec 1 11:14:21 1997 +++ linux-2.1.73/net/sunrpc/sunrpc_syms.c Fri Dec 19 10:41:46 1997 @@ -62,7 +62,6 @@ /* RPC server stuff */ EXPORT_SYMBOL(svc_create); -EXPORT_SYMBOL(svc_create_socket); EXPORT_SYMBOL(svc_create_thread); EXPORT_SYMBOL(svc_exit_thread); EXPORT_SYMBOL(svc_destroy); @@ -70,6 +69,7 @@ EXPORT_SYMBOL(svc_process); EXPORT_SYMBOL(svc_recv); EXPORT_SYMBOL(svc_wake_up); +EXPORT_SYMBOL(svc_makesock); /* RPC statistics */ #ifdef CONFIG_PROC_FS --- linux-2.1.73/include/linux/sunrpc/svcsock.h.old Fri Dec 19 00:49:44 1997 +++ linux-2.1.73/include/linux/sunrpc/svcsock.h Fri Dec 19 10:41:46 1997 @@ -49,7 +49,7 @@ /* * Function prototypes. */ -int svc_create_socket(struct svc_serv *, int, struct sockaddr_in *); +int svc_makesock(struct svc_serv *, int, unsigned short); void svc_delete_socket(struct svc_sock *); int svc_recv(struct svc_serv *, struct svc_rqst *); int svc_send(struct svc_rqst *); | |