diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
commit | 27cfca1ec98e91261b1a5355d10a8996464b63af (patch) | |
tree | 8e895a53e372fa682b4c0a585b9377d67ed70d0e /net/sunrpc | |
parent | 6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff) |
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too
o Upgrade to 2.1.89.
Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/.cvsignore | 1 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 67 | ||||
-rw-r--r-- | net/sunrpc/sched.c | 106 | ||||
-rw-r--r-- | net/sunrpc/stats.c | 58 | ||||
-rw-r--r-- | net/sunrpc/sunrpc_syms.c | 2 | ||||
-rw-r--r-- | net/sunrpc/svc.c | 61 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 36 | ||||
-rw-r--r-- | net/sunrpc/sysctl.c | 32 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 30 |
9 files changed, 249 insertions, 144 deletions
diff --git a/net/sunrpc/.cvsignore b/net/sunrpc/.cvsignore index 4671378ae..857dd22e9 100644 --- a/net/sunrpc/.cvsignore +++ b/net/sunrpc/.cvsignore @@ -1 +1,2 @@ .depend +.*.flags diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 7abaa691e..e8ca9a511 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -21,9 +21,6 @@ * Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de> */ -#include <linux/config.h> -#include <linux/module.h> - #include <asm/system.h> #include <asm/segment.h> @@ -72,20 +69,19 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname, struct rpc_program *program, u32 vers, int flavor) { struct rpc_version *version; - struct rpc_clnt *clnt; + struct rpc_clnt *clnt = NULL; dprintk("RPC: creating %s client for %s (xprt %p)\n", - program->name, servname, xprt); + program->name, servname, xprt); if (!xprt) - return NULL; - if (vers>= program->nrvers || !(version = program->version[vers])) - return NULL; + goto out; + if (vers >= program->nrvers || !(version = program->version[vers])) + goto out; - if (!(clnt = (struct rpc_clnt *) rpc_allocate(0, sizeof(*clnt)))) { - printk("RPC: out of memory in rpc_create_client\n"); - return NULL; - } + clnt = (struct rpc_clnt *) rpc_allocate(0, sizeof(*clnt)); + if (!clnt) + goto out_no_clnt; memset(clnt, 0, sizeof(*clnt)); clnt->cl_xprt = xprt; @@ -103,13 +99,20 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname, if (!clnt->cl_port) clnt->cl_autobind = 1; - if (!rpcauth_create(flavor, clnt)) { - printk("RPC: Couldn't create auth handle (flavor %d)\n", - flavor); - rpc_free(clnt); - return NULL; - } + if (!rpcauth_create(flavor, clnt)) + goto out_no_auth; +out: return clnt; + +out_no_clnt: + printk("RPC: out of memory in rpc_create_client\n"); + goto out; +out_no_auth: + printk("RPC: Couldn't create auth handle (flavor %d)\n", + flavor); + rpc_free(clnt); + clnt = NULL; + goto out; } /* @@ -753,8 +756,10 @@ call_verify(struct rpc_task *task) 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 +773,8 @@ call_verify(struct rpc_task *task) 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; } @@ -776,24 +782,3 @@ garbage: rpc_exit(task, -EIO); return NULL; } - -#ifdef MODULE -int -init_module(void) -{ -#ifdef RPC_DEBUG - rpc_register_sysctl(); -#endif - rpc_proc_init(); - return 0; -} - -void -cleanup_module(void) -{ -#ifdef RPC_DEBUG - rpc_unregister_sysctl(); -#endif - rpc_proc_exit(); -} -#endif diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 6e14bb287..765dc05fc 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -16,6 +16,7 @@ #include <linux/unistd.h> #include <linux/smp.h> #include <linux/smp_lock.h> + #include <linux/sunrpc/clnt.h> #ifdef RPC_DEBUG @@ -45,6 +46,11 @@ static struct rpc_wait_queue schedq = RPC_INIT_WAITQ("schedq"); static struct rpc_wait_queue childq = RPC_INIT_WAITQ("childq"); /* + * RPC tasks sit here while waiting for conditions to improve. + */ +static struct rpc_wait_queue delay_queue = RPC_INIT_WAITQ("delayq"); + +/* * All RPC tasks are linked into this list */ static struct rpc_task * all_tasks = NULL; @@ -92,7 +98,8 @@ rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task) } /* - * Remove request from queue + * Remove request from queue. + * Note: must be called with interrupts disabled. */ void rpc_remove_wait_queue(struct rpc_task *task) @@ -149,6 +156,9 @@ rpc_del_timer(struct rpc_task *task) /* * Make an RPC task runnable. + * + * Note: If the task is ASYNC, this must be called with + * interrupts disabled to protect the wait queue operation. */ static inline void rpc_make_runnable(struct rpc_task *task) @@ -313,8 +323,6 @@ static void __rpc_atrun(struct rpc_task *); void rpc_delay(struct rpc_task *task, unsigned long delay) { - static struct rpc_wait_queue delay_queue; - task->tk_timeout = delay; rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun); } @@ -388,12 +396,14 @@ __rpc_execute(struct rpc_task *task) /* 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); /* When the task received a signal, remove from * any queues etc, and make runnable again. */ - if (signalled()) + if (0 && signalled()) __rpc_wake_up(task); dprintk("RPC: %4d sync task resuming\n", @@ -433,10 +443,15 @@ rpc_execute(struct rpc_task *task) static int executing = 0; int incr = RPC_IS_ASYNC(task)? 1 : 0; - if (incr && (executing || rpc_inhibit)) { - printk("RPC: rpc_execute called recursively!\n"); - return; + if (incr) { + if (rpc_inhibit) { + printk("RPC: execution inhibited!\n"); + return; + } + if (executing) + printk("RPC: %d tasks executed\n", executing); } + executing += incr; __rpc_execute(task); executing -= incr; @@ -519,6 +534,7 @@ rpc_allocate(unsigned int flags, unsigned int size) if (flags & RPC_TASK_ASYNC) return NULL; current->timeout = jiffies + (HZ >> 4); + current->state = TASK_INTERRUPTIBLE; schedule(); } while (!signalled()); @@ -684,20 +700,27 @@ rpc_new_child(struct rpc_clnt *clnt, struct rpc_task *parent) { struct rpc_task *task; - if (!(task = rpc_new_task(clnt, NULL, RPC_TASK_ASYNC|RPC_TASK_CHILD))) { - parent->tk_status = -ENOMEM; - return NULL; - } + task = rpc_new_task(clnt, NULL, RPC_TASK_ASYNC | RPC_TASK_CHILD); + if (!task) + goto fail; task->tk_exit = rpc_child_exit; task->tk_calldata = parent; - return task; + +fail: + parent->tk_status = -ENOMEM; + return NULL; } void rpc_run_child(struct rpc_task *task, struct rpc_task *child, rpc_action func) { + unsigned long oldflags; + + save_flags(oldflags); cli(); rpc_make_runnable(child); + restore_flags(oldflags); + /* N.B. Is it possible for the child to have already finished? */ rpc_sleep_on(&childq, task, func, NULL); } @@ -711,6 +734,7 @@ rpc_killall_tasks(struct rpc_clnt *clnt) struct rpc_task **q, *rovr; dprintk("RPC: killing all tasks for client %p\n", clnt); + /* N.B. Why bother to inhibit? Nothing blocks here ... */ rpc_inhibit++; for (q = &all_tasks; (rovr = *q); q = &rovr->tk_next_task) { if (!clnt || rovr->tk_client == clnt) { @@ -792,29 +816,21 @@ static void 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); } @@ -901,3 +917,37 @@ out: up(&rpciod_sema); MOD_DEC_USE_COUNT; } + +#ifdef RPC_DEBUG +#include <linux/nfs_fs.h> +void rpc_show_tasks(void) +{ + struct rpc_task *t = all_tasks, *next; + struct nfs_wreq *wreq; + + if (!t) + return; + printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " + "-rpcwait -action- --exit--\n"); + for (; t; t = next) { + next = t->tk_next_task; + printk("%05d %04d %04x %06d %8p %6d %8p %08ld %8s %8p %8p\n", + t->tk_pid, t->tk_proc, t->tk_flags, t->tk_status, + t->tk_client, t->tk_client->cl_prog, + t->tk_rqstp, t->tk_timeout, + t->tk_rpcwait ? rpc_qname(t->tk_rpcwait) : " <NULL> ", + t->tk_action, t->tk_exit); + + if (!(t->tk_flags & RPC_TASK_NFSWRITE)) + continue; + /* NFS write requests */ + wreq = (struct nfs_wreq *) t->tk_calldata; + printk(" NFS: flgs=%08x, pid=%d, pg=%p, off=(%d, %d)\n", + wreq->wb_flags, wreq->wb_pid, wreq->wb_page, + wreq->wb_offset, wreq->wb_bytes); + printk(" name=%s/%s\n", + wreq->wb_dentry->d_parent->d_name.name, + wreq->wb_dentry->d_name.name); + } +} +#endif diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 90a23a232..94a5ba21c 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c @@ -12,6 +12,8 @@ * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> */ +#include <linux/module.h> + #include <linux/kernel.h> #include <linux/sched.h> #include <linux/proc_fs.h> @@ -20,7 +22,7 @@ #define RPCDBG_FACILITY RPCDBG_MISC -static struct proc_dir_entry *proc_net_rpc = 0; +static struct proc_dir_entry *proc_net_rpc = NULL; /* * Get RPC client stats @@ -161,15 +163,61 @@ void rpc_proc_init(void) { dprintk("RPC: registering /proc/net/rpc\n"); - if (!proc_net_rpc) - proc_net_rpc = create_proc_entry("net/rpc", S_IFDIR, 0); + if (!proc_net_rpc) { + struct proc_dir_entry *ent; + ent = create_proc_entry("net/rpc", S_IFDIR, 0); + if (ent) { +#ifdef MODULE + ent->fill_inode = rpc_modcount; +#endif + proc_net_rpc = ent; + } + } } void rpc_proc_exit(void) { dprintk("RPC: unregistering /proc/net/rpc\n"); - if (proc_net_rpc) + if (proc_net_rpc) { + proc_net_rpc = NULL; remove_proc_entry("net/rpc", 0); - proc_net_rpc = 0; + } +} + +#ifdef MODULE +/* + * This is called as the proc_dir_entry fill_inode function + * when an inode is going into or out of service (fill == 1 + * or 0 respectively). + * + * We use it here to keep the module from being unloaded + * while /proc inodes are in use. + */ +void rpc_modcount(struct inode *inode, int fill) +{ + if (fill) + MOD_INC_USE_COUNT; + else + MOD_DEC_USE_COUNT; +} + +int +init_module(void) +{ +#ifdef RPC_DEBUG + rpc_register_sysctl(); +#endif + rpc_proc_init(); + return 0; +} + +void +cleanup_module(void) +{ +#ifdef RPC_DEBUG + rpc_unregister_sysctl(); +#endif + rpc_proc_exit(); } +#endif diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 73f805f40..8c1df5a50 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c @@ -62,7 +62,6 @@ EXPORT_SYMBOL(rpcauth_releasecred); /* 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_drop); EXPORT_SYMBOL(svc_process); EXPORT_SYMBOL(svc_recv); EXPORT_SYMBOL(svc_wake_up); +EXPORT_SYMBOL(svc_makesock); /* RPC statistics */ #ifdef CONFIG_PROC_FS diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 79882845c..1d1c0a95e 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -172,7 +172,6 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port) { struct svc_program *progp; unsigned long flags; - sigset_t old_set; int i, error = 0, dummy; progp = serv->sv_program; @@ -180,18 +179,8 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port) 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 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port) 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 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) bufp = argp->buf; if (argp->len < 5) - goto dropit; + goto err_short_len; dir = ntohl(*bufp++); vers = ntohl(*bufp++); @@ -244,10 +232,8 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) 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 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) 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 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) 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 @@ err_bad_auth: 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 @@ err_bad_prog: #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 @@ err_bad_vers: 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 @@ err_garbage: #endif serv->sv_stats->rpcbadfmt++; svc_putlong(resp, rpc_garbage_args); - -error: - return svc_send(rqstp); + goto sendit; } diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 2701a8398..cec276857 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -131,10 +131,10 @@ svc_sock_dequeue(struct svc_serv *serv) { struct svc_sock *svsk; - disable_bh(NET_BH); + start_bh_atomic(); if ((svsk = serv->sv_sockets) != NULL) rpc_remove_list(&serv->sv_sockets, svsk); - enable_bh(NET_BH); + end_bh_atomic(); if (svsk) { dprintk("svc: socket %p dequeued\n", svsk->sk_sk); @@ -151,7 +151,7 @@ svc_sock_dequeue(struct svc_serv *serv) static inline void svc_sock_received(struct svc_sock *svsk, int count) { - disable_bh(NET_BH); + start_bh_atomic(); if ((svsk->sk_data -= count) < 0) { printk(KERN_NOTICE "svc: sk_data negative!\n"); svsk->sk_data = 0; @@ -163,7 +163,7 @@ svc_sock_received(struct svc_sock *svsk, int count) svsk->sk_sk); svc_sock_enqueue(svsk); } - enable_bh(NET_BH); + end_bh_atomic(); } /* @@ -172,7 +172,7 @@ svc_sock_received(struct svc_sock *svsk, int count) static inline void svc_sock_accepted(struct svc_sock *svsk) { - disable_bh(NET_BH); + start_bh_atomic(); svsk->sk_busy = 0; svsk->sk_conn--; if (svsk->sk_conn || svsk->sk_data || svsk->sk_close) { @@ -180,7 +180,7 @@ svc_sock_accepted(struct svc_sock *svsk) svsk->sk_sk); svc_sock_enqueue(svsk); } - enable_bh(NET_BH); + end_bh_atomic(); } /* @@ -739,9 +739,9 @@ again: if (signalled()) return -EINTR; - disable_bh(NET_BH); + start_bh_atomic(); if ((svsk = svc_sock_dequeue(serv)) != NULL) { - enable_bh(NET_BH); + end_bh_atomic(); rqstp->rq_sock = svsk; svsk->sk_inuse++; /* N.B. where is this decremented? */ } else { @@ -756,7 +756,7 @@ again: */ current->state = TASK_INTERRUPTIBLE; add_wait_queue(&rqstp->rq_wait, &wait); - enable_bh(NET_BH); + end_bh_atomic(); schedule(); if (!(svsk = rqstp->rq_sock)) { @@ -886,7 +886,7 @@ if (svsk->sk_sk == NULL) /* * 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 @@ svc_delete_socket(struct svc_sock *svsk) /* 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); +} + diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index 859d55853..a48e9c1ad 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c @@ -13,15 +13,11 @@ #include <linux/ctype.h> #include <linux/fs.h> #include <linux/sysctl.h> -#if LINUX_VERSION_CODE >= 0x020100 + #include <asm/uaccess.h> -#else -# include <linux/mm.h> -# define copy_from_user memcpy_fromfs -# define copy_to_user memcpy_tofs -# define access_ok !verify_area -#endif #include <linux/sunrpc/types.h> +#include <linux/sunrpc/sched.h> +#include <linux/sunrpc/stats.h> /* * Declare the debug flags here @@ -39,17 +35,23 @@ static ctl_table sunrpc_table[]; void rpc_register_sysctl(void) { - if (sunrpc_table_header) - return; - sunrpc_table_header = register_sysctl_table(sunrpc_table, 1); + if (!sunrpc_table_header) { + sunrpc_table_header = register_sysctl_table(sunrpc_table, 1); +#ifdef MODULE + if (sunrpc_table[0].de) + sunrpc_table[0].de->fill_inode = rpc_modcount; +#endif + } + } void rpc_unregister_sysctl(void) { - if (!sunrpc_table_header) - return; - unregister_sysctl_table(sunrpc_table_header); + if (sunrpc_table_header) { + unregister_sysctl_table(sunrpc_table_header); + sunrpc_table_header = NULL; + } } int @@ -93,6 +95,10 @@ proc_dodebug(ctl_table *table, int write, struct file *file, while (left && isspace(*p)) left--, p++; *(unsigned int *) table->data = value; + /* Display the RPC tasks on writing to rpc_debug */ + if (table->ctl_name == CTL_RPCDEBUG) { + rpc_show_tasks(); + } } else { if (!access_ok(VERIFY_WRITE, buffer, left)) return -EFAULT; diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index c76566399..f614cfa33 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -48,11 +48,11 @@ #include <linux/udp.h> #include <linux/unistd.h> #include <linux/sunrpc/clnt.h> +#include <linux/file.h> + #include <net/sock.h> -#if LINUX_VERSION_CODE >= 0x020100 #include <asm/uaccess.h> -#endif #define SOCK_HAS_USER_DATA @@ -319,7 +319,7 @@ xprt_close(struct rpc_xprt *xprt) sk->write_space = xprt->old_write_space; if (xprt->file) - close_fp(xprt->file); + fput(xprt->file); else sock_release(xprt->sock); } @@ -397,14 +397,14 @@ xprt_reconnect(struct rpc_task *task) task->tk_pid, status, xprt->connected); task->tk_timeout = 60 * HZ; - disable_bh(NET_BH); + start_bh_atomic(); if (!xprt->connected) { rpc_sleep_on(&xprt->reconn, task, xprt_reconn_status, xprt_reconn_timeout); - enable_bh(NET_BH); + end_bh_atomic(); return; } - enable_bh(NET_BH); + end_bh_atomic(); } xprt->connecting = 0; @@ -870,10 +870,10 @@ xprt_transmit(struct rpc_task *task) /* For fast networks/servers we have to put the request on * the pending list now: */ - disable_bh(NET_BH); + start_bh_atomic(); rpc_add_wait_queue(&xprt->pending, task); task->tk_callback = NULL; - enable_bh(NET_BH); + end_bh_atomic(); /* Continue transmitting the packet/record. We must be careful * to cope with writespace callbacks arriving _after_ we have @@ -891,16 +891,16 @@ xprt_transmit(struct rpc_task *task) task->tk_pid, xprt->snd_buf.io_len, req->rq_slen); task->tk_status = 0; - disable_bh(NET_BH); + start_bh_atomic(); if (!xprt->write_space) { /* Remove from pending */ rpc_remove_wait_queue(task); rpc_sleep_on(&xprt->sending, task, xprt_transmit_status, NULL); - enable_bh(NET_BH); + end_bh_atomic(); return; } - enable_bh(NET_BH); + end_bh_atomic(); } } @@ -943,12 +943,12 @@ xprt_receive(struct rpc_task *task) */ task->tk_timeout = req->rq_timeout.to_current; - disable_bh(NET_BH); + start_bh_atomic(); if (!req->rq_gotit) { rpc_sleep_on(&xprt->pending, task, xprt_receive_status, xprt_timer); } - enable_bh(NET_BH); + end_bh_atomic(); dprintk("RPC: %4d xprt_receive returns %d\n", task->tk_pid, task->tk_status); @@ -1079,7 +1079,7 @@ xprt_release(struct rpc_task *task) dprintk("RPC: %4d release request %p\n", task->tk_pid, req); /* remove slot from queue of pending */ - disable_bh(NET_BH); + start_bh_atomic(); if (task->tk_rpcwait) { printk("RPC: task of released request still queued!\n"); #ifdef RPC_DEBUG @@ -1088,7 +1088,7 @@ xprt_release(struct rpc_task *task) rpc_del_timer(task); rpc_remove_wait_queue(task); } - enable_bh(NET_BH); + end_bh_atomic(); /* Decrease congestion value. If congestion threshold is not yet * reached, pass on the request slot. |