patch for 2.1.78 sunrpc

Bill Hawes (whawes@star.net)
Sun, 11 Jan 1998 13:01:57 -0500


This is a multi-part message in MIME format.
--------------39B576A994EA322E274B6FB2
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

The attached patch for 2.1.78 sunrpc adds some debugging code to display
the RPC task list when requested. It shows basic information for all
tasks, and for NFS writeback requests shows the NFS-specific flags and
other data. Hopefully this will help track down the cause of the stuck
RPC tasks.

The task list is displayed in response to a write to the
/proc/sys/sunrpc/rpc_debug flag (any write, 0 or 1).

I've also added a fill_inode operation to the proc_dir_entry structure
for the RPC debugging /proc entry; this will keep the module from being
unloaded while an inode still refers to the entry.

The patch depends on the updated NFS client patch just posted, as it
needs the structure definitions moved into nfs_fs.h.

Regards,
Bill
--------------39B576A994EA322E274B6FB2
Content-Type: text/plain; charset=us-ascii; name="sunrpc_78-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="sunrpc_78-patch"

--- linux-2.1.78/include/linux/sunrpc/sched.h.old Sat Jan 10 12:44:02 1998
+++ linux-2.1.78/include/linux/sunrpc/sched.h Sat Jan 10 14:29:04 1998
@@ -89,6 +89,7 @@
#define RPC_TASK_ROOTCREDS 0x0100 /* force root creds */
#define RPC_TASK_DYNAMIC 0x0200 /* task was kmalloc'ed */
#define RPC_TASK_KILLED 0x0400 /* task was killed */
+#define RPC_TASK_NFSWRITE 0x1000 /* an NFS writeback */

#define RPC_IS_RUNNING(t) ((t)->tk_flags & RPC_TASK_RUNNING)
#define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC)
@@ -145,6 +146,9 @@
void rpc_free(void *);
int rpciod_up(void);
void rpciod_down(void);
+#ifdef RPC_DEBUG
+void rpc_show_tasks(void);
+#endif

extern __inline__ void *
rpc_malloc(struct rpc_task *task, unsigned int size)
--- linux-2.1.78/include/linux/sunrpc/stats.h.old Tue Jan 6 12:15:39 1998
+++ linux-2.1.78/include/linux/sunrpc/stats.h Sun Jan 11 13:21:53 1998
@@ -40,6 +40,9 @@

void rpc_proc_init(void);
void rpc_proc_exit(void);
+#ifdef MODULE
+void rpc_modcount(struct inode *, int);
+#endif

struct proc_dir_entry * rpc_proc_register(struct rpc_stat *);
void rpc_proc_unregister(const char *);
--- linux-2.1.78/net/sunrpc/clnt.c.old Sat Dec 20 16:58:32 1997
+++ linux-2.1.78/net/sunrpc/clnt.c Sat Jan 10 19:52:24 1998
@@ -22,7 +22,6 @@
*/

#include <linux/config.h>
-#include <linux/module.h>

#include <asm/system.h>
#include <asm/segment.h>
@@ -72,20 +71,19 @@
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 +101,20 @@
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;
}

/*
@@ -779,24 +784,3 @@
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
--- linux-2.1.78/net/sunrpc/sched.c.old Tue Dec 30 16:09:00 1997
+++ linux-2.1.78/net/sunrpc/sched.c Sat Jan 10 18:20:29 1998
@@ -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
@@ -906,3 +907,35 @@
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- --rqstp- -timeout "
+ "-rpcwait -action- --exit--\n");
+ for (; t; t = next) {
+ next = t->tk_next_task;
+ printk("%05d %04d %04x %06d %8p %8p %08ld %8p %8p %8p\n",
+ t->tk_pid, t->tk_proc, t->tk_flags, t->tk_status,
+ t->tk_client, t->tk_rqstp, t->tk_timeout,
+ t->tk_rpcwait, 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
--- linux-2.1.78/net/sunrpc/sysctl.c.old Mon Apr 7 14:35:33 1997
+++ linux-2.1.78/net/sunrpc/sysctl.c Sat Jan 10 17:45:24 1998
@@ -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,21 @@
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);
+ if (sunrpc_table[0].de)
+ sunrpc_table[0].de->fill_inode = rpc_modcount;
+ }
+
}

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 +93,10 @@
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;
--- linux-2.1.78/net/sunrpc/stats.c.old Sun Apr 13 13:18:23 1997
+++ linux-2.1.78/net/sunrpc/stats.c Sat Jan 10 17:51:57 1998
@@ -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 @@
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

--------------39B576A994EA322E274B6FB2--