[OpenAFS-devel] Re: [OpenAFS] 2.6 kernel support anytime soon? Workarounds?

Pete Zaitcev zaitcev@redhat.com
Mon, 10 May 2004 12:11:07 -0700


On Mon, 10 May 2004 14:42:49 -0400
Jeffrey Hutzelman <jhutz@cmu.edu> wrote:

> Ah, but that's exactly what the Linux folks seem to think.  The broken 
> "tainting" model the Linux folks have adopted makes no provision for 
> non-GPL open-source licenses.  They assume that either your license is the 
> GPL, or you suck.

This characterization is incorrect. There's no problem loading
2-clause BSD licensed code, for instance.

> But that doesn't excuse the "your license is not exactly the same as our 
> license, and your architecture is not based on whatever bizarre ideas's 
> we've had in the last few years, so we hate your forever and ever and will 
> do everything in our power to try to screw you".

That's just what voices in your head tell you and it has no relation
to the real world.

> [...] The Linux 
> maintainers, on the other hand, tell us we can't have our syscall any more, 
> demand that we completly rearchitect the user-kernel interface that has 
> worked well for us on many platforms over a couple of decades, and then 
> WON'T EVEN GIVE US THE TOOLS TO DO SO.  That's just idiotic.

It is only your rant that is idiotic, because it's based on ignorance
and delusions.

I was working on some code to keep the user-kernel interface you're so
fond of, patch is attached...

-- Pete

Can mount /afs and do ls -l (returns empty).
Not trying to use auth yet, but klog(1) and tokens(1) work.
-- server steadfastly refuses to challenge us.

diff -urN -X dontdiff linux-2.6.1/arch/i386/kernel/entry.S linux-2.6.1-kafs/arch/i386/kernel/entry.S
--- linux-2.6.1/arch/i386/kernel/entry.S	2003-11-24 09:30:31.000000000 -0800
+++ linux-2.6.1-kafs/arch/i386/kernel/entry.S	2004-01-13 18:29:20.000000000 -0800
@@ -745,7 +745,7 @@
 	.long sys_bdflush
 	.long sys_sysfs		/* 135 */
 	.long sys_personality
-	.long sys_ni_syscall	/* reserved for afs_syscall */
+	.long sys_afs
 	.long sys_setfsuid16
 	.long sys_setfsgid16
 	.long sys_llseek	/* 140 */
diff -urN -X dontdiff linux-2.6.1/Documentation/filesystems/afs.txt linux-2.6.1-kafs/Documentation/filesystems/afs.txt
--- linux-2.6.1/Documentation/filesystems/afs.txt	2003-07-13 20:35:53.000000000 -0700
+++ linux-2.6.1-kafs/Documentation/filesystems/afs.txt	2004-01-16 09:31:54.000000000 -0800
@@ -27,8 +27,15 @@
 The first module is a driver for the RxRPC remote operation protocol, and the
 second is the actual filesystem driver for the AFS filesystem.
 
-Once the module has been loaded, more modules can be added by the following
-procedure:
+An alternative way to configure the root cell is to write the same
+module parameter syntax into /proc/fs/afs/rootcell. This is used mainly
+for kafs with OpenAFS compatibility mode, which must be built statically
+into kernels. Example:
+
+	echo "cambridge.redhat.com:172.16.18.91" > /proc/fs/afs/rootcell
+
+Once the module has been loaded and/or configured, more cells can be added
+by the following procedure:
 
 	echo add grand.central.org 18.7.14.88:128.2.191.224 >/proc/fs/afs/cells
 
diff -urN -X dontdiff linux-2.6.1/fs/afs/callback.c linux-2.6.1-kafs/fs/afs/callback.c
--- linux-2.6.1/fs/afs/callback.c	2003-10-01 15:18:00.000000000 -0700
+++ linux-2.6.1-kafs/fs/afs/callback.c	2004-04-12 00:05:06.000000000 -0700
@@ -19,6 +19,7 @@
 #include "server.h"
 #include "vnode.h"
 #include "internal.h"
+#include "cmservice.h"
 
 /*****************************************************************************/
 /*
@@ -166,3 +167,35 @@
 	_debug("SRXAFSCM_Probe(%p)\n",server);
 	return 0;
 } /* end SRXAFSCM_Probe() */
+
+/*****************************************************************************/
+/*
+ * Some weird func which allows the server to interrogate a client
+ * for no good reason...
+ */
+int SRXAFSCM_WhoAreYou(struct afs_if_addr *p)
+{
+	unsigned int n;
+
+	/* XXX XXX XXX */
+	memset(p, 0, sizeof(struct afs_if_addr));
+
+	p->ifnum = 1;
+	p->addrv[0] = htonl(0xc0a88005);
+	p->maskv[0] = htonl(0xffffff00);
+	p->mtuv[0] = 1500;
+
+	p->uuid.time_low = htonl(1);
+	n = 1 << 12;	/* version */
+	p->uuid.time_hi = htonl(n);
+	p->uuid.clock_seq_low = htonl(1);
+	p->uuid.node[0] = 0;
+	p->uuid.node[1] = 0xc0;
+	p->uuid.node[2] = 0xf0;
+	p->uuid.node[3] = 0x1c;
+	p->uuid.node[4] = 0xff;
+	p->uuid.node[5] = 0xff;
+	/* XXX XXX XXX */
+
+	return 0;
+}
diff -urN -X dontdiff linux-2.6.1/fs/afs/cell.c linux-2.6.1-kafs/fs/afs/cell.c
--- linux-2.6.1/fs/afs/cell.c	2003-10-01 15:18:00.000000000 -0700
+++ linux-2.6.1-kafs/fs/afs/cell.c	2004-01-13 18:29:20.000000000 -0800
@@ -31,11 +31,6 @@
 static DECLARE_RWSEM(afs_cells_sem); /* add/remove serialisation */
 static afs_cell_t *afs_cell_root;
 
-static char *rootcell;
-
-MODULE_PARM(rootcell,"s");
-MODULE_PARM_DESC(rootcell,"root AFS cell name and VL server IP addr list");
-
 #ifdef AFS_CACHING_SUPPORT
 static cachefs_match_val_t afs_cell_cache_match(void *target, const void *entry);
 static void afs_cell_cache_update(void *source, void *entry);
@@ -70,8 +65,8 @@
 	/* allocate and initialise a cell record */
 	cell = kmalloc(sizeof(afs_cell_t) + strlen(name) + 1,GFP_KERNEL);
 	if (!cell) {
-		_leave(" = -ENOMEM");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto nomem;
 	}
 
 	memset(cell,0,sizeof(afs_cell_t));
@@ -142,10 +137,14 @@
 	return 0;
 
  badaddr:
-	printk("kAFS: bad VL server IP address: '%s'\n",vllist);
+	printk(KERN_ERR "kAFS: bad VL server IP address: '%s'\n",vllist);
+	/* goto error; */
+
  error:
+	kfree(cell);
+ nomem:
 	up_write(&afs_cells_sem);
-	kfree(afs_cell_root);
+	_leave(" = %d", ret);
 	return ret;
 } /* end afs_cell_create() */
 
@@ -153,29 +152,53 @@
 /*
  * initialise the cell database from module parameters
  */
-int afs_cell_init(void)
+int afs_cell_init(char *rootcell)
 {
 	char *cp;
+	afs_cell_t *old_root, *new_root;
 	int ret;
 
 	_enter("");
 
-	if (!rootcell) {
-		printk("kAFS: no root cell specified\n");
-		return -EINVAL;
+	if (rootcell == NULL) {
+		/*
+		 * Module is loaded with no parameters, or built statically.
+		 * In the future we might initialize cell DB here.
+		 */
+		_leave(" = 0 (but no root)");
+		return 0;
 	}
 
 	cp = strchr(rootcell,':');
 	if (!cp) {
 		printk("kAFS: no VL server IP addresses specified\n");
+		_leave(" = %d (no colon)", -EINVAL);
 		return -EINVAL;
 	}
 
 	/* allocate a cell record for the root cell */
 	*cp++ = 0;
-	ret = afs_cell_create(rootcell,cp,&afs_cell_root);
-	if (ret==0)
-		afs_get_cell(afs_cell_root);
+	ret = afs_cell_create(rootcell,cp,&new_root);
+	if (ret != 0) {
+		_leave(" = %d", ret);
+		return ret;
+	}
+
+	/*
+	 * As afs_put_cell takes locks by itself, we have to do
+	 * a little gymnastics to be race-free.
+	 */
+	write_lock(&afs_cells_lock);
+	while (afs_cell_root) {
+		old_root = afs_cell_root;
+		afs_cell_root = NULL;
+		write_unlock(&afs_cells_lock);
+		afs_put_cell(old_root);
+		write_lock(&afs_cells_lock);
+	}
+	afs_get_cell(new_root);
+	afs_cell_root = new_root;
+	write_unlock(&afs_cells_lock);
 
 	_leave(" = %d",ret);
 	return ret;
@@ -217,9 +240,24 @@
 			ret = 0;
 	}
 	else {
-		cell = afs_cell_root;
-		afs_get_cell(cell);
-		ret = 0;
+		read_lock(&afs_cells_lock);
+
+		if ((cell = afs_cell_root) == NULL) {
+			/*
+			 * This should not happen unless user tries to mount
+			 * when root cell is not set. Return an impossibly
+			 * bizzare errno to alert the user. Things like
+			 * ENOENT might be "more appropriate" but they happen
+			 * for other reasons.
+			 */
+			ret = -EDOM;
+		}
+		else {
+			afs_get_cell(cell);
+			ret = 0;
+		}
+
+		read_unlock(&afs_cells_lock);
 	}
 
 	*_cell = cell;
@@ -403,7 +441,7 @@
 
 /*****************************************************************************/
 /*
- * purge in-memory cell database on module unload
+ * purge in-memory cell database on module unload or afs_init() failure
  * - the timeout daemon is stopped before calling this
  */
 void afs_cell_purge(void)
diff -urN -X dontdiff linux-2.6.1/fs/afs/cell.h linux-2.6.1-kafs/fs/afs/cell.h
--- linux-2.6.1/fs/afs/cell.h	2003-10-01 15:18:00.000000000 -0700
+++ linux-2.6.1-kafs/fs/afs/cell.h	2004-01-13 18:29:20.000000000 -0800
@@ -61,7 +61,7 @@
 	char			name[0];	/* cell name - must go last */
 };
 
-extern int afs_cell_init(void);
+extern int afs_cell_init(char *root_cell);
 
 extern int afs_cell_create(const char *name, char *vllist, struct afs_cell **_cell);
 
diff -urN -X dontdiff linux-2.6.1/fs/afs/cmservice.c linux-2.6.1-kafs/fs/afs/cmservice.c
--- linux-2.6.1/fs/afs/cmservice.c	2003-10-01 15:18:00.000000000 -0700
+++ linux-2.6.1-kafs/fs/afs/cmservice.c	2004-04-12 00:07:15.000000000 -0700
@@ -34,6 +34,7 @@
 static void _SRXAFSCM_CallBack(struct rxrpc_call *call);
 static void _SRXAFSCM_InitCallBackState(struct rxrpc_call *call);
 static void _SRXAFSCM_Probe(struct rxrpc_call *call);
+static void _SRXAFSCM_WhoAreYou(struct rxrpc_call *call);
 
 typedef void (*_SRXAFSCM_xxxx_t)(struct rxrpc_call *call);
 
@@ -80,8 +81,14 @@
 		.asize	= RXRPC_APP_MARK_EOF,
 		.name	= "GetXStats",
 		.user	= _SRXAFSCM_GetXStats,
-	}
+	},
 #endif
+	{
+		.id	= 212,
+		.asize	= RXRPC_APP_MARK_EOF,
+		.name	= "WhoAreYou",
+		.user	= _SRXAFSCM_WhoAreYou,
+	}
 };
 
 static struct rxrpc_service AFSCM_service = {
@@ -162,7 +169,9 @@
 
 		if (call) {
 			/* act upon it */
-			_debug("@@@ Begin Attend Call %p",call);
+			_debug("@@@ Begin Attend Call %p func %p {acs=%s}",
+			    call, call->app_user,
+			    rxrpc_call_states[call->app_call_state]);
 
 			func = call->app_user;
 			if (func)
@@ -641,3 +650,85 @@
 	_leave(" = %d",ret);
 
 } /* end _SRXAFSCM_Probe() */
+
+/*****************************************************************************/
+/*
+ */
+static void _SRXAFSCM_WhoAreYou(struct rxrpc_call *call)
+{
+	afs_server_t *server;
+	size_t count;
+	int ret = 0, removed;
+
+	_enter("%p{acs=%s}",call,rxrpc_call_states[call->app_call_state]);
+
+	server = afs_server_get_from_peer(call->conn->peer);
+
+	switch (call->app_call_state) {
+		/* we've received the last packet - drain all the data from the call */
+	case RXRPC_CSTATE_SRVR_GOT_ARGS:
+		_debug("WhoAreYou ARGS");
+		/* shouldn't be any args */
+		ret = -EBADMSG;
+		break;
+
+		/* send the reply when asked for it */
+	case RXRPC_CSTATE_SRVR_SND_REPLY:
+		_debug("WhoAreYou REPLY");
+
+		{
+			struct afs_if_addr *bp;
+			struct iovec piov[1];
+
+			bp = rxrpc_call_alloc_scratch(call,
+					sizeof(struct afs_if_addr));
+
+			/* invoke the actual service routine */
+			ret = SRXAFSCM_WhoAreYou(bp);
+			if (ret<0)
+				break;
+
+        		/* marshall the parameters */
+        		piov[0].iov_len = sizeof(struct afs_if_addr);
+        		piov[0].iov_base = bp;
+
+			/* send the parameters to the server */
+			ret = rxrpc_call_write_data(call,1,piov,
+					RXRPC_LAST_PACKET,GFP_KERNEL,0,&count);
+		}
+		break;
+
+		/* operation complete */
+	case RXRPC_CSTATE_COMPLETE:
+		_debug("WhoAreYou COMPLETE");
+		call->app_user = NULL;
+		removed = 0;
+		spin_lock(&afscm_calls_lock);
+		if (!list_empty(&call->app_link)) {
+			list_del_init(&call->app_link);
+			removed = 1;
+		}
+		spin_unlock(&afscm_calls_lock);
+
+		if (removed)
+			rxrpc_put_call(call);
+		break;
+
+		/* operation terminated on error */
+	case RXRPC_CSTATE_ERROR:
+		_debug("WhoAreYou ERROR");
+		call->app_user = NULL;
+		break;
+
+	default:
+		_debug("WhoAreYou state %d", call->app_call_state);
+		break;
+	}
+
+	if (ret<0)
+		rxrpc_call_abort(call,ret);
+
+	afs_put_server(server);
+
+	_leave(" = %d",ret);
+}
diff -urN -X dontdiff linux-2.6.1/fs/afs/cmservice.h linux-2.6.1-kafs/fs/afs/cmservice.h
--- linux-2.6.1/fs/afs/cmservice.h	2003-07-13 20:31:50.000000000 -0700
+++ linux-2.6.1-kafs/fs/afs/cmservice.h	2004-04-12 00:02:17.000000000 -0700
@@ -15,6 +15,27 @@
 #include <rxrpc/transport.h>
 #include "types.h"
 
+/*
+ */
+#define AFS_MAX_INTERFACE_ADDR 32
+
+struct afs_uuid {
+	u32 time_low;
+	u16 time_mid;
+	u16 time_hi;		/* Reserved 0xF000 little endian (?!) */
+	char clock_seq_hi;	/* Reserved 0x80 */
+	char clock_seq_low;
+	char node[6];
+};
+
+struct afs_if_addr {
+	int ifnum;	/* Number of interfaces */
+	struct afs_uuid uuid;
+	s32 addrv[AFS_MAX_INTERFACE_ADDR];
+	s32 maskv[AFS_MAX_INTERFACE_ADDR];
+	s32 mtuv[AFS_MAX_INTERFACE_ADDR];
+};
+
 /* cache manager start/stop */
 extern int afscm_start(void);
 extern void afscm_stop(void);
@@ -23,5 +44,6 @@
 extern int SRXAFSCM_InitCallBackState(afs_server_t *server);
 extern int SRXAFSCM_CallBack(afs_server_t *server, size_t count, afs_callback_t callbacks[]);
 extern int SRXAFSCM_Probe(afs_server_t *server);
+extern int SRXAFSCM_WhoAreYou(struct afs_if_addr *r);
 
 #endif /* _LINUX_AFS_CMSERVICE_H */
diff -urN -X dontdiff linux-2.6.1/fs/afs/inode.c linux-2.6.1-kafs/fs/afs/inode.c
--- linux-2.6.1/fs/afs/inode.c	2003-10-01 15:18:00.000000000 -0700
+++ linux-2.6.1-kafs/fs/afs/inode.c	2004-01-13 18:29:20.000000000 -0800
@@ -201,7 +201,11 @@
 	       vnode->cb_version,
 	       vnode->cb_timeout.timo_jif,
 	       vnode->cb_type,
+#ifdef AFS_CACHING_SUPPORT
 	       vnode->cache
+#else
+	       NULL
+#endif
 	       );
 	return 0;
 
diff -urN -X dontdiff linux-2.6.1/fs/afs/internal.h linux-2.6.1-kafs/fs/afs/internal.h
--- linux-2.6.1/fs/afs/internal.h	2003-10-01 15:18:00.000000000 -0700
+++ linux-2.6.1-kafs/fs/afs/internal.h	2004-04-12 00:01:55.000000000 -0700
@@ -17,6 +17,8 @@
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 
+/* #define __KDEBUG */ /* P3 */
+
 /*
  * debug tracing
  */
diff -urN -X dontdiff linux-2.6.1/fs/afs/main.c linux-2.6.1-kafs/fs/afs/main.c
--- linux-2.6.1/fs/afs/main.c	2003-10-01 15:18:00.000000000 -0700
+++ linux-2.6.1-kafs/fs/afs/main.c	2004-01-13 18:29:20.000000000 -0800
@@ -33,9 +33,19 @@
 static int afs_adding_peer(struct rxrpc_peer *peer);
 static void afs_discarding_peer(struct rxrpc_peer *peer);
 
-module_init(afs_init);
+/*
+ * XXX late_initcall is kludgy. But the only alternative seems to create
+ * a transport upon the first mount, which is worse. Or is it?
+ */
+/* module_init(afs_init); */
+late_initcall(afs_init);	/* Must be called after net/ to create socket */
 module_exit(afs_exit);
 
+static char *rootcell;
+
+MODULE_PARM(rootcell,"s");
+MODULE_PARM_DESC(rootcell,"root AFS cell name and VL server IP addr list");
+
 MODULE_DESCRIPTION("AFS Client File System");
 MODULE_AUTHOR("Red Hat, Inc.");
 MODULE_LICENSE("GPL");
@@ -88,7 +98,7 @@
 #endif
 
 	/* initialise the cell DB */
-	ret = afs_cell_init();
+	ret = afs_cell_init(rootcell);
 	if (ret < 0)
 		goto error_cache;
 
diff -urN -X dontdiff linux-2.6.1/fs/afs/Makefile linux-2.6.1-kafs/fs/afs/Makefile
--- linux-2.6.1/fs/afs/Makefile	2003-10-01 15:18:00.000000000 -0700
+++ linux-2.6.1-kafs/fs/afs/Makefile	2004-01-13 18:29:20.000000000 -0800
@@ -20,6 +20,7 @@
 	proc.o \
 	server.o \
 	super.o \
+	sys.o \
 	vlclient.o \
 	vlocation.o \
 	vnode.o \
diff -urN -X dontdiff linux-2.6.1/fs/afs/proc.c linux-2.6.1-kafs/fs/afs/proc.c
--- linux-2.6.1/fs/afs/proc.c	2003-07-13 20:32:29.000000000 -0700
+++ linux-2.6.1-kafs/fs/afs/proc.c	2004-01-13 18:29:20.000000000 -0800
@@ -44,6 +44,19 @@
 	.release	= seq_release,
 };
 
+static int afs_proc_rootcell_open(struct inode *inode, struct file *file);
+static int afs_proc_rootcell_release(struct inode *inode, struct file *file);
+static ssize_t afs_proc_rootcell_read(struct file *file, char *buf, size_t size, loff_t *_pos);
+static ssize_t afs_proc_rootcell_write(struct file *file, const char *buf, size_t size, loff_t *_pos);
+
+static struct file_operations afs_proc_rootcell_fops = {
+	.open		= afs_proc_rootcell_open,
+	.read		= afs_proc_rootcell_read,
+	.write		= afs_proc_rootcell_write,
+	.llseek		= no_llseek,
+	.release	= afs_proc_rootcell_release
+};
+
 static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file);
 static int afs_proc_cell_volumes_release(struct inode *inode, struct file *file);
 static void *afs_proc_cell_volumes_start(struct seq_file *p, loff_t *pos);
@@ -128,13 +141,17 @@
 	p->proc_fops = &afs_proc_cells_fops;
 	p->owner = THIS_MODULE;
 
+	p = create_proc_entry("rootcell",0,proc_afs);
+	if (!p)
+		goto error_cells;
+	p->proc_fops = &afs_proc_rootcell_fops;
+	p->owner = THIS_MODULE;
+
 	_leave(" = 0");
 	return 0;
 
-#if 0
  error_cells:
 	remove_proc_entry("cells",proc_afs);
-#endif
  error_proc:
 	remove_proc_entry("fs/afs",NULL);
  error:
@@ -248,7 +265,7 @@
 /*****************************************************************************/
 /*
  * handle writes to /proc/fs/afs/cells
- * - to add cells: echo "add <cellname> <IP>[:<IP>][:<IP>]*
+ * - to add cells: echo "add <cellname> <IP>[:<IP>][:<IP>]"
  */
 static ssize_t afs_proc_cells_write(struct file *file, const char *buf, size_t size, loff_t *_pos)
 {
@@ -313,6 +330,67 @@
 
 /*****************************************************************************/
 /*
+ * Stubs for /proc/fs/afs/rootcell
+ */
+static int afs_proc_rootcell_open(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static int afs_proc_rootcell_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static ssize_t afs_proc_rootcell_read(struct file *file, char *buf, size_t size, loff_t *_pos)
+{
+	return 0;
+}
+
+/*****************************************************************************/
+/*
+ * handle writes to /proc/fs/afs/rootcell
+ * - to initialize rootcell: echo "cell.name:192.168.231.14"
+ */
+static ssize_t afs_proc_rootcell_write(struct file *file, const char *buf, size_t size, loff_t *_pos)
+{
+	char *kbuf, *s;
+	int ret;
+
+	/* start by dragging the command into memory */
+	if (size<=1 || size>=PAGE_SIZE)
+		return -EINVAL;
+
+	ret = -ENOMEM;
+	kbuf = kmalloc(size+1,GFP_KERNEL);
+	if (!kbuf)
+		goto nomem;
+
+	ret = -EFAULT;
+	if (copy_from_user(kbuf,buf,size)!=0)
+		goto infault;
+	kbuf[size] = 0;
+
+	/* trim to first NL */
+	s = memchr(kbuf,'\n',size);
+	if (s) *s = 0;
+
+	/* determine command to perform */
+	_debug("rootcell=%s",kbuf);
+
+	ret = afs_cell_init(kbuf);
+	if (ret >= 0)
+		ret = size;	/* Consume everything, always */
+
+ infault:
+	kfree(kbuf);
+ nomem:
+	_leave(" = %d",ret);
+	return ret;
+}
+
+/*****************************************************************************/
+/*
  * initialise /proc/fs/afs/<cell>/
  */
 int afs_proc_cell_setup(afs_cell_t *cell)
diff -urN -X dontdiff linux-2.6.1/fs/afs/super.c linux-2.6.1-kafs/fs/afs/super.c
--- linux-2.6.1/fs/afs/super.c	2003-10-01 15:18:00.000000000 -0700
+++ linux-2.6.1-kafs/fs/afs/super.c	2004-01-15 14:35:45.000000000 -0800
@@ -35,14 +35,6 @@
 	struct afs_volume	*volume;
 };
 
-static inline char *strdup(const char *s)
-{
-	char *ns = kmalloc(strlen(s) + 1, GFP_KERNEL);
-	if (ns)
-		strcpy(ns, s);
-	return ns;
-}
-
 static void afs_i_init_once(void *foo, kmem_cache_t *cachep,
 			    unsigned long flags);
 
diff -urN -X dontdiff linux-2.6.1/fs/afs/sys.c linux-2.6.1-kafs/fs/afs/sys.c
--- linux-2.6.1/fs/afs/sys.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.1-kafs/fs/afs/sys.c	2004-01-13 18:29:20.000000000 -0800
@@ -0,0 +1,513 @@
+/*
+ * This code was inspired by OpenAFS, developed by IBM Corp.,
+ * and available under IBM Public License. The crazy maze of
+ * #ifdef's there was probably the greatest inspiration,
+ * closely followed by its stack eating inclinations.
+ * Other than that, we are trying to stay as compatible as possible.
+ *
+ * Copyright (c) 2003,2004 Pete Zaitcev
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#include <asm/ioctl.h>		/* _IOW */
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#include "sys.h"
+
+#define AFS_SECRTOK_SZ	56
+#define AFS_OPENTOK_SZ	24
+
+/*
+ * Structure to keep tokens.
+ *
+ * A table seems to be the best fit for the requirements.
+ *   UID   PAG   Cell     Data (open and secret)
+ *  ----- ----- -------- -----------------:--------------------
+ *
+ * Currently, we search by UID only. A list indexes them (XXX STUPID => tree).
+ * Since we never search by cell, there is no index/search.
+ */
+struct afs_token {
+	/*
+	 * Column 1: UID. Indexable.
+	 */
+	uid_t uid;		/* UNIX ID == User ID (!= AID) */
+	struct list_head uid_link;	/* Index in-line is superior */
+
+	/*
+	 * Column 2: PAG. Will be indexeable when we start tracking exit(2).
+	 */
+	int pag;
+
+	/*
+	 * Column 3: Cell.
+	 * XXX Cell IDs are not done yet. BTW, they are user-visible.
+	 */
+	char *cell_name;
+	struct list_head cell_link;	/* Index in-line is superior */
+
+	/*
+	 * Data.
+	 */
+	int ref;		/* Use count. Not used much while we have one index only */
+	int otsize, stsize;	/* Number of bytes in the tokens */
+	unsigned char stok[AFS_SECRTOK_SZ];
+	unsigned char otok[AFS_OPENTOK_SZ];
+};
+
+struct afs_tok_index_uid {
+	struct list_head list;
+};
+
+struct afs_tok_index_cell {
+	struct list_head list;
+};
+
+/*
+ */
+struct afs_pioctl_arg {
+	/* __user */  void *iptr;
+	/* __user */  void *optr;
+	short isize;
+	short osize;
+};
+
+#define AFSPIOCSETTOK _IOW('V', 3, struct afs_pioctl_arg)
+#define AFSPIOCGETTOK _IOW('V', 8, struct afs_pioctl_arg)
+
+static long sys_afs_pioctl(unsigned long param1, unsigned long param2,
+    unsigned long param3, unsigned long param4);
+static int pioctl_set_tokens(const unsigned char *ibuf, int isize);
+static int pioctl_get_tokens(unsigned int inp, int isize,
+    unsigned char *obuf, int osize);
+
+/*
+ * Index anchors.
+ */
+static DECLARE_MUTEX(tok_lock);
+static struct afs_tok_index_uid tok_anchor_uid = {
+	.list = LIST_HEAD_INIT(tok_anchor_uid.list)
+};
+static struct afs_tok_index_cell tok_anchor_cell = {
+	.list = LIST_HEAD_INIT(tok_anchor_cell.list)
+};
+
+/*
+ * Regular getting and putting.
+ *
+ * These rely on tok_lock.
+ *
+ * We do not BUG() because stack traces are mostly useless.
+ * Better to warn and leak.
+ */
+/* static void tok_get(struct afs_token *tok); */ /* No cloning currently */
+static void tok_put(struct afs_token *tok)
+{
+
+	if (tok == NULL) {
+		printk(KERN_WARNING "kafs: sloppy (null token)\n");
+		return;
+	}
+
+	if (tok->ref <= 0) {
+		printk(KERN_WARNING "kafs: token ref corrupt (0x%x)\n",
+		    tok->ref);
+		return;
+	}
+
+	if (--tok->ref == 0) {
+		if (tok->uid_link.next != NULL &&
+		    tok->uid_link.next != LIST_POISON1) {
+			printk(KERN_WARNING "kafs: token busy on put\n");
+			return;
+		}
+		kfree(tok);
+	}
+}
+
+/*
+ * Add a token to the table. This stitches it into all indexes.
+ *
+ * The tok_lock is taken.
+ *
+ * The reference passes from the caller to the table, so do not
+ * continue to use the *tok after the tok_add, do not tok_put it or anything.
+ */
+static void tok_add(struct afs_token *tok)
+{
+
+	/*
+	 * We need one reference which we pass on to the indexes.
+	 */
+	if (tok->ref <= 0) {
+		printk(KERN_WARNING "kafs: token unreferenced on add\n");
+		return;
+	}
+
+	if (tok->uid_link.next != NULL && tok->uid_link.next != LIST_POISON1) {
+		printk(KERN_WARNING "kafs: token busy on add\n");
+		/* tok_put(tok); */ /* Better make it leak than crash */
+		return;
+	}
+
+	list_add(&tok->uid_link, &tok_anchor_uid.list);
+	list_add(&tok->cell_link, &tok_anchor_cell.list);
+}
+
+/*
+ * Delete token from the table.
+ *
+ * The tok_lock is taken.
+ */
+static void tok_delete(struct afs_token *tok)
+{
+	list_del(&tok->uid_link);
+	list_del(&tok->cell_link);
+	tok_put(tok);		/* Drop one for indices */
+}
+
+/*
+ * Select with (token.uid == uid).
+ *
+ * Notice we do not return a referenced token, because the locking is
+ * external to the table manipulation functions. If needed, do tok_get()
+ * before dropping the lock.
+ *
+ * XXX Should return a list.
+ * XXX Should accept an expression.
+ */
+static struct afs_token *tok_uidx_lookup(struct afs_tok_index_uid *t, int uid)
+{
+	struct list_head *pos;
+	struct afs_token *tp;
+
+	list_for_each(pos, &tok_anchor_uid.list) {
+		tp = list_entry(pos, struct afs_token, uid_link);
+		if (tp->uid == uid) {
+			return tp;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * Mother Of All Multiplexing Syscalls
+ */
+asmlinkage long sys_afs(unsigned long sysno, unsigned long param1,
+    unsigned long param2, unsigned long param3, unsigned long param4)
+{
+	// XXX if (syscall == AFSCALL_ICL || syscall == AFSCALL_CALL) { p5,p6 }
+
+/* P3 */ /* printk("sys_afs: %d\n", (int)sysno); */
+	switch (sysno) {
+	case AFSCALL_PIOCTL:
+		return sys_afs_pioctl(param1, param2, param3, param4);
+	default: ;
+	}
+	return -EINVAL;
+}
+
+static long sys_afs_pioctl(
+    unsigned long param1,	/* __user char *path; */
+    unsigned long param2,	/* unsigned int cmd; */
+    unsigned long param3,	/* [void*|unsigned long] arg; */
+    unsigned long param4)	/* int follow; */
+{
+	unsigned int cmd = param2;
+	struct afs_pioctl_arg b;	/* Very small struct */
+	unsigned char *ibuf, *obuf;
+	u32 inp;
+	int rc;
+
+/* P3 */ /* printk("pioctl 0x%lx 0x%lx 0x%lx 0x%lx\n",
+ param1, param2, param3, param4); */
+	if (copy_from_user(&b, (void *)param3, sizeof(struct afs_pioctl_arg)))
+		return -EFAULT;
+/* P3 */ /* printk("pioctl cmd 0x%x in 0x%x[%d] out 0x%x[%d]\n",
+   cmd, (int)b.iptr, b.isize, (int)b.optr, b.osize); */
+
+	if (param1 != 0)	/* XXX No paths yet */
+		return -EINVAL;
+
+	switch (cmd) {
+	case AFSPIOCSETTOK:
+		if (b.isize <= 0)     /* No upper limit because it's a short */
+			return -EINVAL;
+		if ((ibuf = kmalloc(b.isize, GFP_KERNEL)) == NULL)
+			return -ENOMEM;
+		if (copy_from_user(ibuf, b.iptr, b.isize)) {
+			kfree(ibuf);
+			return -EFAULT;
+		}
+		rc = pioctl_set_tokens(ibuf, b.isize);
+		kfree(ibuf);
+		return rc;
+	case AFSPIOCGETTOK:
+		if (b.isize < 0)
+			return -EINVAL;
+		if (b.isize != 0) {
+			if (b.isize < sizeof(u32))
+				return -EINVAL;
+			if (copy_from_user((char *) &inp, b.iptr, sizeof(u32)))
+				return -EFAULT;
+		}
+
+		if (b.osize <= 0)
+			return -EINVAL;
+		/*
+		 * This behaviour is intended to match OpenAFS which
+		 * simply truncates the result
+		 * (as long as it is smaller than PIGGYSIZE).
+		 */
+		obuf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
+		if (obuf == NULL)
+			return -ENOMEM;
+		rc = pioctl_get_tokens(inp, b.isize, obuf, PAGE_SIZE);
+		if (rc >= PIGGYSIZE) {
+			rc = -E2BIG;
+		} else if (rc >= 0) {
+			if ((rc = b.osize) > PAGE_SIZE)
+				rc = PAGE_SIZE;
+			if (copy_to_user(b.optr, obuf, rc))
+				rc = -EFAULT;
+			else
+				rc = 0;
+		} else {
+			;  /* Error of some kind */
+		}
+		free_page((unsigned long)obuf);
+		return rc;
+	default: ;
+	}
+	return -EINVAL;
+}
+
+/*
+ * Parse the ibuf[isize] and fill *tok.
+ *
+ * memcpy(&i, p, 4) is a necessary evil: alignment.
+ */
+static int pioctl_set_tokens_parse(const unsigned char *ibuf, int isize,
+    struct afs_token *tok)
+{
+	const unsigned char *p;
+	int togo;
+	int stlen, otlen;
+	int flag;
+	char *cellname;
+
+	togo = isize;
+	p = ibuf;
+
+	if (togo < sizeof(int))
+		return -EINVAL;
+	memcpy(&stlen, p, sizeof(int));
+	p += sizeof(int);
+	togo -= sizeof(int);
+
+	if (stlen != AFS_SECRTOK_SZ) {
+		printk(KERN_DEBUG "pioctl_set_tokens:"
+		    " secret token lengh %d expected %d\n",
+		    stlen, AFS_SECRTOK_SZ);
+		if (stlen < 0)
+			return -EINVAL;
+		/* Variable size is all right, probably... */
+	}
+
+	if (togo < stlen)
+		return -EINVAL;
+	memcpy(tok->stok, p, stlen);
+	tok->stsize = stlen;
+	p += stlen;
+	togo -= stlen;
+
+	if (togo < sizeof(int))
+		return -EINVAL;
+	memcpy(&otlen, p, sizeof(int));
+	p += sizeof(int);
+	togo -= sizeof(int);
+
+	if (otlen != AFS_OPENTOK_SZ) {
+		printk(KERN_DEBUG "pioctl_set_tokens:"
+		    " open token lenght %d expected %d\n",
+		    otlen, AFS_OPENTOK_SZ);
+		return -EINVAL;
+	}
+
+	if (togo < otlen)
+		return -EINVAL;
+	memcpy(tok->otok, p, otlen);
+	tok->otsize = otlen;
+	p += otlen;
+	togo -= otlen;
+
+	if (togo != 0) {
+		/* Extra? Must be a flag and possibly a cell name. */
+		if (togo < sizeof(int))
+			return -EINVAL;
+		memcpy(&flag, p, sizeof(int));
+		p += sizeof(int);
+		togo -= sizeof(int);
+
+		if (togo < 2)		/* At least one char and a null */
+			return -EINVAL;
+		if ((cellname = kmalloc(togo, GFP_USER)) == NULL)
+			return -ENOMEM;
+		memcpy(cellname, p, togo-1);
+		cellname[togo-1] = 0;
+
+/* P3 */ /* printk("pioctl_set_tokens: secret [%d], (%s)\n", stlen, cellname); */
+
+		/* XXX Good time to look up the cell. Just store for now. */
+		tok->cell_name = cellname;
+
+	} else {
+/* P3 */ /* printk("pioctl_set_tokens: secret [%d], primary\n", stlen); */
+		/* XXX Lookup if primary is set; Abort if not. */
+	}
+
+	return 0;
+}
+
+static int pioctl_set_tokens(const unsigned char *ibuf, int isize)
+{
+	struct afs_token *tok;
+	struct afs_token *t1;
+	int err;
+
+	err = -ENOMEM;
+	if ((tok = kmalloc(sizeof(struct afs_token), GFP_USER)) == NULL)
+		goto no_core_for_tok;
+	memset(tok, 0, sizeof(struct afs_token));
+	tok->ref = 1;
+
+	/* uid_t uid,euid,suid,fsuid; <--- which one? */
+	/* Using effective uid makes all suid programs to fail. */
+	tok->uid = current->uid;
+
+	if ((err = pioctl_set_tokens_parse(ibuf, isize, tok)) != 0)
+		goto bad_parse;
+
+	down(&tok_lock);
+
+	/*
+	 * XXX Need to select by uid, cell, pag. This way we'll never
+	 * have to deal with a list.
+	 */
+	if ((t1 = tok_uidx_lookup(&tok_anchor_uid, tok->uid)) != NULL) {
+		tok_delete(t1);
+	}
+
+	tok_add(tok);
+
+	up(&tok_lock);
+
+	return 0;
+
+bad_parse:
+	tok_put(tok);
+no_core_for_tok:
+	return err;
+}
+
+/*
+ * The checks for boundaries here should never trigger, in fact
+ * OpenAFS does not check them at all. But let's be safe and polite.
+ */
+static int pioctl_get_tokens_marshall(struct afs_token *tok, int isize,
+    unsigned char *obuf, int osize)
+{
+	int ocount;
+	s32 stlen, otlen, cid;
+	int cell_name_len;
+
+	ocount = 0;
+
+	if ((stlen = tok->stsize) < 56)
+		stlen = 56;
+
+	if (osize-ocount < sizeof(s32))
+		return -EINVAL;
+	memcpy(obuf, (char *)&stlen, sizeof(s32));
+	obuf += sizeof(s32);
+	ocount += sizeof(s32);
+
+	if (osize-ocount < stlen)
+		return -EINVAL;
+	memcpy(obuf, tok->stok, tok->stsize);	/* Into pre-zeroed space */
+	obuf += stlen;
+	ocount += stlen;
+
+	otlen = AFS_OPENTOK_SZ;
+	if (osize-ocount < sizeof(s32))
+		return -EINVAL;
+	memcpy(obuf, (char *)&otlen, sizeof(s32));
+	obuf += sizeof(s32);
+	ocount += sizeof(s32);
+
+	if (osize-ocount < AFS_OPENTOK_SZ)
+		return -EINVAL;
+	memcpy(obuf, tok->otok, AFS_OPENTOK_SZ);
+	obuf += AFS_OPENTOK_SZ;
+	ocount += AFS_OPENTOK_SZ;
+
+	if (isize) {
+		cid = 1;	/* XXX Lookup from tok->cell_foo */
+		if (osize-ocount < sizeof(s32))
+			return -EINVAL;
+		memcpy(obuf, (char *)&cid, sizeof(s32));
+		obuf += sizeof(s32);
+		ocount += sizeof(s32);
+
+		if (tok->cell_name == NULL) {
+			*obuf++ = 0;
+			ocount++;
+		} else {
+			cell_name_len = strlen(tok->cell_name);
+			if (osize-ocount < cell_name_len+1)
+				return -EINVAL;
+			strcpy(obuf, tok->cell_name);
+			obuf += cell_name_len+1;
+		}
+	}
+
+	return ocount;
+}
+
+static int pioctl_get_tokens(unsigned int inp, int isize,
+    unsigned char *obuf, int osize)
+{
+	int uid;
+	struct afs_token *tok;
+	int ocount;
+
+	down(&tok_lock);
+
+	/* uid_t uid,euid,suid,fsuid; <--- which one? */
+	uid = current->uid;
+
+	if ((tok = tok_uidx_lookup(&tok_anchor_uid, uid)) == NULL) {
+		up(&tok_lock);
+		return -ENOTCONN;
+	}
+	if (isize != 0) {
+		if (inp != 0) {
+			up(&tok_lock);
+			return -EDOM;
+		}
+	}
+
+	/*
+	 * A good place to do tok_get(); up(), if we ever hit a performance
+	 * bottleneck. As it is, why bother. No premature optimizations!
+	 */
+
+	ocount = pioctl_get_tokens_marshall(tok, isize, obuf, osize);
+	up(&tok_lock);
+	return ocount;
+}
diff -urN -X dontdiff linux-2.6.1/fs/afs/sys.h linux-2.6.1-kafs/fs/afs/sys.h
--- linux-2.6.1/fs/afs/sys.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.1-kafs/fs/afs/sys.h	2004-01-13 18:29:20.000000000 -0800
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ *
+ * This seems to be compatible with GPL.
+ */
+
+/*
+ * AFS system call opcodes
+ */
+
+#define	AFSOP_START_RXCALLBACK	  0	/* no aux parms */
+#define	AFSOP_START_AFS		  1	/* no aux parms */
+#define	AFSOP_START_BKG		  2	/* no aux parms */
+#define	AFSOP_START_TRUNCDAEMON	  3	/* no aux parms */
+#define AFSOP_START_CS		  4	/* no aux parms */
+
+#define	AFSOP_ADDCELL		  5	/* parm 2 = cell str */
+#define	AFSOP_CACHEINIT		  6	/* parms 2-4 -> cache sizes */
+#define	AFSOP_CACHEINFO		  7	/* the cacheinfo file */
+#define	AFSOP_VOLUMEINFO	  8	/* the volumeinfo file */
+#define	AFSOP_CACHEFILE		  9	/* a random cache file (V*) */
+#define	AFSOP_CACHEINODE	 10	/* random cache file by inode */
+#define	AFSOP_AFSLOG		 11	/* output log file */
+#define	AFSOP_ROOTVOLUME	 12	/* non-standard root volume name */
+#define	AFSOP_STARTLOG		 14	/* temporary: Start afs logging */
+#define	AFSOP_ENDLOG		 15	/* temporary: End afs logging */
+#define AFSOP_AFS_VFSMOUNT	 16	/* vfsmount cover for hpux */
+#define AFSOP_ADVISEADDR	 17	/* to init rx cid generator */
+#define AFSOP_CLOSEWAIT 	 18	/* make all closes synchronous */
+#define	AFSOP_RXEVENT_DAEMON	 19	/* rxevent daemon */
+#define	AFSOP_GETMTU		 20	/* stand-in for SIOCGIFMTU, for now */
+#define	AFSOP_GETIFADDRS	 21	/* get machine's ethernet interfaces */
+
+#define	AFSOP_ADDCELL2		 29	/* 2nd add cell protocol interface */
+#define	AFSOP_AFSDB_HANDLER	 30	/* userspace AFSDB lookup handler */
+#define	AFSOP_SET_DYNROOT	 31	/* enable/disable dynroot support */
+#define	AFSOP_ADDCELLALIAS	 32	/* create alias for existing cell */
+#define	AFSOP_SET_FAKESTAT	 33	/* enable/disable fakestat support */
+#define	AFSOP_CELLINFO		 34	/* set the cellinfo file name */
+#define	AFSOP_SET_THISCELL	 35	/* set the primary cell */
+#define AFSOP_BASIC_INIT	 36	/* used to be part of START_AFS */
+
+/* The range 20-30 is reserved for AFS system offsets in the afs_syscall */
+#define	AFSCALL_PIOCTL		20
+#define	AFSCALL_SETPAG		21
+#define	AFSCALL_IOPEN		22
+#define	AFSCALL_ICREATE		23
+#define	AFSCALL_IREAD		24
+#define	AFSCALL_IWRITE		25
+#define	AFSCALL_IINC		26
+#define	AFSCALL_IDEC		27
+#define	AFSCALL_CALL		28
+
+#define AFSCALL_ICL             30
+
+/* 64 bit versions of inode system calls. */
+#define AFSCALL_IOPEN64		41
+#define AFSCALL_ICREATE64	42
+#define AFSCALL_IINC64		43
+#define AFSCALL_IDEC64		44
+#define AFSCALL_ILISTINODE64	45	/* Used by ListViceInodes */
+#define AFSCALL_ICREATENAME64	46	/* pass in platform specific pointer
+					 * used to create a name in in a
+					 * directory.
+					 */
+
+/* afs.h */
+#define PIGGYSIZE	1350		/* max piggyback size */
diff -urN -X dontdiff linux-2.6.1/fs/afs/vnode.c linux-2.6.1-kafs/fs/afs/vnode.c
--- linux-2.6.1/fs/afs/vnode.c	2003-10-01 15:18:01.000000000 -0700
+++ linux-2.6.1-kafs/fs/afs/vnode.c	2004-01-13 21:52:45.000000000 -0800
@@ -225,8 +225,6 @@
 		if (ret<0)
 			return ret;
 
-		_debug("USING SERVER: %08x\n",ntohl(server->addr.s_addr));
-
 		ret = afs_rxfs_fetch_file_status(server,vnode,NULL);
 
 	} while (!afs_volume_release_fileserver(vnode->volume,server,ret));
@@ -266,8 +264,6 @@
 		if (ret<0)
 			return ret;
 
-		_debug("USING SERVER: %08x\n",ntohl(server->addr.s_addr));
-
 		ret = afs_rxfs_fetch_file_data(server,vnode,desc,NULL);
 
 	} while (!afs_volume_release_fileserver(vnode->volume,server,ret));
diff -urN -X dontdiff linux-2.6.1/fs/afs/volume.c linux-2.6.1-kafs/fs/afs/volume.c
--- linux-2.6.1/fs/afs/volume.c	2003-10-01 15:18:01.000000000 -0700
+++ linux-2.6.1-kafs/fs/afs/volume.c	2004-01-13 18:29:20.000000000 -0800
@@ -108,6 +108,7 @@
 	if (volname) {
 		cellname = name;
 		cellnamesz = volname - name;
+		volname++;
 	}
 	else {
 		volname = name;
diff -urN -X dontdiff linux-2.6.1/net/rxrpc/connection.c linux-2.6.1-kafs/net/rxrpc/connection.c
--- linux-2.6.1/net/rxrpc/connection.c	2003-10-01 15:18:26.000000000 -0700
+++ linux-2.6.1-kafs/net/rxrpc/connection.c	2004-02-22 19:12:52.000000000 -0800
@@ -640,8 +640,9 @@
 	msghdr.msg_controllen	= 0;
 	msghdr.msg_flags	= MSG_CONFIRM | MSG_DONTWAIT;
 
-	_net("Sending message type %d of %Zd bytes to %08x:%d",
+	_net("Sending message type %d #%d of %Zd bytes to %08x:%d",
 	     msg->hdr.type,
+	     ntohl(msg->hdr.serial),
 	     msg->dsize,
 	     htonl(conn->addr.sin_addr.s_addr),
 	     htons(conn->addr.sin_port));
diff -urN -X dontdiff linux-2.6.1/net/rxrpc/transport.c linux-2.6.1-kafs/net/rxrpc/transport.c
--- linux-2.6.1/net/rxrpc/transport.c	2003-10-01 15:18:26.000000000 -0700
+++ linux-2.6.1-kafs/net/rxrpc/transport.c	2004-02-22 19:12:42.000000000 -0800
@@ -130,7 +130,18 @@
 	return 0;
 
  error:
-	rxrpc_put_transport(trans);
+	/* finish cleaning up the transport (not really needed here, but...) */
+	if (trans->socket)
+		trans->socket->ops->shutdown(trans->socket, 2);
+
+	/* close the socket */
+	if (trans->socket) {
+		trans->socket->sk->sk_user_data = NULL;
+		sock_release(trans->socket);
+		trans->socket = NULL;
+	}
+
+	kfree(trans);
 
 	_leave(" = %d", ret);
 	return ret;
@@ -338,8 +349,9 @@
 	msg->offset = sizeof(struct udphdr) + sizeof(struct rxrpc_header);
 	msg->dsize = msg->pkt->len - msg->offset;
 
-	_net("Rx Received packet from %s (%08x;%08x,%1x,%d,%s,%02x,%d,%d)",
+	_net("Rx Received packet from %s (#%d %08x;%08x,%1x,%d,%s,%02x,%d,%d)",
 	     msg->hdr.flags & RXRPC_CLIENT_INITIATED ? "client" : "server",
+	     ntohl(msg->hdr.serial),
 	     ntohl(msg->hdr.epoch),
 	     (ntohl(msg->hdr.cid) & RXRPC_CIDMASK) >> RXRPC_CIDSHIFT,
 	     ntohl(msg->hdr.cid) & RXRPC_CHANNELMASK,