[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,