On Mon, 10 May 2004 14:42:49 -0400
Jeffrey Hutzelman <[EMAIL PROTECTED]> 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,
_______________________________________________
OpenAFS-devel mailing list
[EMAIL PROTECTED]
https://lists.openafs.org/mailman/listinfo/openafs-devel

Reply via email to