linux-updates-20060309
[openafs.git] / src / afs / LINUX / osi_module.c
index 46948d2..8718c69 100644 (file)
@@ -24,7 +24,10 @@ RCSID
 #include "h/mm.h"
 
 #ifdef AFS_AMD64_LINUX20_ENV
-#include "../asm/ia32_unistd.h"
+#include <asm/ia32_unistd.h>
+#endif
+#ifdef AFS_SPARC64_LINUX20_ENV
+#include <linux/ioctl32.h>
 #endif
 
 #include <linux/proc_fs.h>
@@ -32,38 +35,11 @@ RCSID
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 #include <linux/init.h>
 #include <linux/sched.h>
-#endif
-#if !defined(EXPORTED_SYS_CALL_TABLE) && defined(HAVE_KERNEL_LINUX_SYSCALL_H)
-#include <linux/syscall.h>
-#endif
-
-#ifdef AFS_SPARC64_LINUX24_ENV
-#define __NR_setgroups32      82       /* This number is not exported for some bizarre reason. */
-#endif
-
-#if !defined(AFS_LINUX24_ENV)
-asmlinkage int (*sys_settimeofdayp) (struct timeval * tv,
-                                    struct timezone * tz);
-#endif
-asmlinkage long (*sys_setgroupsp) (int gidsetsize, gid_t * grouplist);
-#ifdef EXPORTED_SYS_CALL_TABLE
-#if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_S390X_LINUX24_ENV)
-extern unsigned int sys_call_table[];  /* changed to uint because SPARC64 and S390X have syscalltable of 32bit items */
-#else
-extern void *sys_call_table[]; /* safer for other linuces */
-#endif
-#else /* EXPORTED_SYS_CALL_TABLE */
-#if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_S390X_LINUX24_ENV)
-static unsigned int *sys_call_table;   /* changed to uint because SPARC64 and S390X have syscalltable of 32bit items */
-#else
-static void **sys_call_table;  /* safer for other linuces */
-#endif
+#include <linux/kernel.h>
 #endif
 
-#if defined(AFS_S390X_LINUX24_ENV)
-#define _S(x) ((x)<<1)
-#else
-#define _S(x) x
+#ifdef HAVE_KERNEL_LINUX_SEQ_FILE_H
+#include <linux/seq_file.h>
 #endif
 
 extern struct file_system_type afs_fs_type;
@@ -72,7 +48,9 @@ extern struct file_system_type afs_fs_type;
 static long get_page_offset(void);
 #endif
 
-#if defined(AFS_LINUX24_ENV)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
+DEFINE_MUTEX(afs_global_lock);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 DECLARE_MUTEX(afs_global_lock);
 #else
 struct semaphore afs_global_lock = MUTEX;
@@ -82,103 +60,172 @@ int afs_global_owner = 0;
 unsigned long afs_linux_page_offset = 0;       /* contains the PAGE_OFFSET value */
 #endif
 
-/* Since sys_ni_syscall is not exported, I need to cache it in order to restore
- * it.
- */
-#if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_S390X_LINUX24_ENV)
-static unsigned int afs_ni_syscall = 0;
-#else
-static void *afs_ni_syscall = 0;
+static inline int afs_ioctl(struct inode *, struct file *, unsigned int,
+                    unsigned long);
+#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL)
+static long afs_unlocked_ioctl(struct file *, unsigned int, unsigned long);
 #endif
 
-#ifdef AFS_AMD64_LINUX20_ENV
-#ifdef EXPORTED_IA32_SYS_CALL_TABLE
-extern void *ia32_sys_call_table[];
+static struct file_operations afs_syscall_fops = {
+#ifdef HAVE_UNLOCKED_IOCTL
+    .unlocked_ioctl = afs_unlocked_ioctl,
 #else
-static void **ia32_sys_call_table;
+    .ioctl = afs_ioctl,
+#endif
+#ifdef HAVE_COMPAT_IOCTL
+    .compat_ioctl = afs_unlocked_ioctl,
 #endif
+};
 
-static void *ia32_ni_syscall = 0;
-asmlinkage long (*sys32_setgroupsp) (int gidsetsize, u16 * grouplist);
-#if defined(__NR_ia32_setgroups32)
-asmlinkage long (*sys32_setgroups32p) (int gidsetsize, gid_t * grouplist);
-#endif /* __NR_ia32_setgroups32 */
-#endif /* AFS_AMD64_LINUX20_ENV */
+#ifdef HAVE_KERNEL_LINUX_SEQ_FILE_H
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+       struct afs_q *cq, *tq;
+       loff_t n = 0;
 
-#ifdef AFS_PPC64_LINUX20_ENV
-asmlinkage long (*sys32_setgroupsp)(int gidsetsize, gid_t *grouplist);
-#endif /* AFS_AMD64_LINUX20_ENV */
+       ObtainReadLock(&afs_xcell);
+       for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
+               tq = QNext(cq);
 
-#ifdef AFS_SPARC64_LINUX20_ENV
-static unsigned int afs_ni_syscall32 = 0;
-asmlinkage int (*sys32_setgroupsp) (int gidsetsize,
-                                   __kernel_gid_t32 * grouplist);
-#if defined(__NR_setgroups32)
-asmlinkage int (*sys32_setgroups32p) (int gidsetsize,
-                                     __kernel_gid_t32 * grouplist);
-#endif /* __NR_setgroups32 */
-#ifdef EXPORTED_SYS_CALL_TABLE
-extern unsigned int sys_call_table32[];
-#else /* EXPORTED_SYS_CALL_TABLE */
-static unsigned int *sys_call_table32;
-#endif /* EXPORTED_SYS_CALL_TABLE */
-
-asmlinkage int
-afs_syscall32(long syscall, long parm1, long parm2, long parm3, long parm4,
-             long parm5)
+               if (n++ == *pos)
+                       break;
+       }
+       if (cq == &CellLRU)
+               return NULL;
+
+       return cq;
+}
+
+static void *c_next(struct seq_file *m, void *p, loff_t *pos)
 {
-    __asm__ __volatile__("srl %o4, 0, %o4\n\t" "mov %o7, %i7\n\t"
-                        "call afs_syscall\n\t" "srl %o5, 0, %o5\n\t"
-                        "ret\n\t" "nop");
+       struct afs_q *cq = p, *tq;
+
+       (*pos)++;
+       tq = QNext(cq);
+
+       if (tq == &CellLRU)
+               return NULL;
+
+       return tq;
 }
-#endif /* AFS_SPARC64_LINUX20_ENV */
 
-static int afs_ioctl(struct inode *, struct file *, unsigned int,
-                    unsigned long);
+static void c_stop(struct seq_file *m, void *p)
+{
+       ReleaseReadLock(&afs_xcell);
+}
 
-static struct file_operations afs_syscall_fops = {
-    .ioctl = afs_ioctl,
+static int c_show(struct seq_file *m, void *p)
+{
+       struct afs_q *cq = p;
+       struct cell *tc = QTOC(cq);
+       int j;
+
+       seq_printf(m, ">%s #(%d/%d)\n", tc->cellName,
+                  tc->cellNum, tc->cellIndex);
+
+       for (j = 0; j < MAXCELLHOSTS; j++) {
+               afs_uint32 addr;
+
+               if (!tc->cellHosts[j]) break;
+
+               addr = tc->cellHosts[j]->addr->sa_ip;
+               seq_printf(m, "%u.%u.%u.%u #%u.%u.%u.%u\n",
+                          NIPQUAD(addr), NIPQUAD(addr));
+       }
+
+       return 0;
+}
+
+static struct seq_operations afs_csdb_op = {
+       .start          = c_start,
+       .next           = c_next,
+       .stop           = c_stop,
+       .show           = c_show,
+};
+
+static int afs_csdb_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &afs_csdb_op);
+}
+
+static struct file_operations afs_csdb_operations = {
+       .open           = afs_csdb_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
 };
 
+#else /* HAVE_KERNEL_LINUX_SEQ_FILE_H */
+
 int
-csdbproc_read(char *buffer, char **start, off_t offset, int count,
-             int *eof, void *data)
+csdbproc_info(char *buffer, char **start, off_t offset, int
+length)
 {
-    int len, j;
+    int len = 0;
+    off_t pos = 0;
+    int cnt;
     struct afs_q *cq, *tq;
     struct cell *tc;
     char tbuffer[16];
+    /* 90 - 64 cellname, 10 for 32 bit num and index, plus
+       decor */
+    char temp[91];
     afs_uint32 addr;
     
-    len = 0;
     ObtainReadLock(&afs_xcell);
+
     for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
-       tc = QTOC(cq); tq = QNext(cq);
-       len += sprintf(buffer + len, ">%s #(%d/%d)\n", tc->cellName, 
-                      tc->cellNum, tc->cellIndex);
-       for (j = 0; j < MAXCELLHOSTS; j++) {
-           if (!tc->cellHosts[j]) break;
-           addr = ntohl(tc->cellHosts[j]->addr->sa_ip);
-           sprintf(tbuffer, "%d.%d.%d.%d", 
-                   (int)((addr>>24) & 0xff), (int)((addr>>16) & 0xff),
-                   (int)((addr>>8)  & 0xff), (int)( addr      & 0xff));
-            len += sprintf(buffer + len, "%s #%s\n", tbuffer, tbuffer);
-       }
+        tc = QTOC(cq); tq = QNext(cq);
+
+        pos += 90;
+
+        if (pos <= offset) {
+            len = 0;
+        } else {
+            sprintf(temp, ">%s #(%d/%d)\n", tc->cellName, 
+                    tc->cellNum, tc->cellIndex);
+            sprintf(buffer + len, "%-89s\n", temp);
+            len += 90;
+            if (pos >= offset+length) {
+                ReleaseReadLock(&afs_xcell);
+                goto done;
+            }
+        }
+
+        for (cnt = 0; cnt < MAXCELLHOSTS; cnt++) {
+            if (!tc->cellHosts[cnt]) break;
+            pos += 90;
+            if (pos <= offset) {
+                len = 0;
+            } else {
+                addr = ntohl(tc->cellHosts[cnt]->addr->sa_ip);
+                sprintf(tbuffer, "%d.%d.%d.%d", 
+                        (int)((addr>>24) & 0xff),
+(int)((addr>>16) & 0xff),
+                        (int)((addr>>8)  & 0xff), (int)( addr & 0xff));
+                sprintf(temp, "%s #%s\n", tbuffer, tbuffer);
+                sprintf(buffer + len, "%-89s\n", temp);
+                len += 90;
+                if (pos >= offset+length) {
+                    ReleaseReadLock(&afs_xcell);
+                    goto done;
+                }
+            }
+        }
     }
+
     ReleaseReadLock(&afs_xcell);
     
-    if (offset >= len) {
-       *start = buffer;
-       *eof = 1;
-       return 0;
-    }
-    *start = buffer + offset;
-    if ((len -= offset) > count)
-       return count;
-    *eof = 1;
+done:
+    *start = buffer + len - (pos - offset);
+    len = pos - offset;
+    if (len > length)
+        len = length;
     return len;
 }
 
+#endif /* HAVE_KERNEL_LINUX_SEQ_FILE_H */
+
 int
 peerproc_read(char *buffer, char **start, off_t offset, int count,
              int *eof, void *data)
@@ -505,10 +552,15 @@ callproc_read(char *buffer, char **start, off_t offset, int count,
 }
 
 static struct proc_dir_entry *openafs_procfs;
+#if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
+static int ioctl32_done;
+#endif
 
+#ifdef AFS_LINUX24_ENV
 static int
-afsproc_init()
+afsproc_init(void)
 {
+    struct proc_dir_entry *entry2;
     struct proc_dir_entry *entry1;
     struct proc_dir_entry *entry;
 
@@ -519,7 +571,13 @@ afsproc_init()
 
     entry1->owner = THIS_MODULE;
 
-    entry = create_proc_read_entry(PROC_CELLSERVDB_NAME, (S_IFREG|S_IRUGO), openafs_procfs, csdbproc_read, NULL);
+#ifdef HAVE_KERNEL_LINUX_SEQ_FILE_H
+    entry2 = create_proc_entry(PROC_CELLSERVDB_NAME, 0, openafs_procfs);
+    if (entry2)
+       entry2->proc_fops = &afs_csdb_operations;
+#else
+    entry2 = create_proc_info_entry(PROC_CELLSERVDB_NAME, (S_IFREG|S_IRUGO), openafs_procfs, csdbproc_info);
+#endif
 
     entry = create_proc_read_entry(PROC_PEER_NAME, (S_IFREG|S_IRUGO), openafs_procfs, peerproc_read, NULL);
 
@@ -532,12 +590,16 @@ afsproc_init()
     entry = create_proc_read_entry(PROC_SERVICES_NAME, (S_IFREG|S_IRUGO), openafs_procfs, servicesproc_read, NULL);
 
     entry = create_proc_read_entry(PROC_RXSTATS_NAME, (S_IFREG|S_IRUGO), openafs_procfs, rxstatsproc_read, NULL);
+#if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
+    if (register_ioctl32_conversion(VIOC_SYSCALL32, NULL) == 0) 
+           ioctl32_done = 1;
+#endif
 
     return 0;
 }
 
 static void
-afsproc_exit()
+afsproc_exit(void)
 {
     remove_proc_entry(PROC_RXSTATS_NAME, openafs_procfs);
     remove_proc_entry(PROC_SERVICES_NAME, openafs_procfs);
@@ -548,7 +610,12 @@ afsproc_exit()
     remove_proc_entry(PROC_CELLSERVDB_NAME, openafs_procfs);
     remove_proc_entry(PROC_SYSCALL_NAME, openafs_procfs);
     remove_proc_entry(PROC_FSDIRNAME, proc_root_fs);
+#if defined(NEED_IOCTL32) && !defined(HAVE_COMPAT_IOCTL)
+    if (ioctl32_done)
+           unregister_ioctl32_conversion(VIOC_SYSCALL32);
+#endif
 }
+#endif
 
 extern asmlinkage long
 afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4);
@@ -559,59 +626,64 @@ afs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 {
 
     struct afsprocdata sysargs;
+#ifdef NEED_IOCTL32
+    struct afsprocdata32 sysargs32;
+#endif
 
-    if (cmd != VIOC_SYSCALL) return -EINVAL;
-
-    if (copy_from_user(&sysargs, (void *)arg, sizeof(struct afsprocdata)))
-       return -EFAULT;
-
-    return afs_syscall(sysargs.syscall, sysargs.param1,
-                      sysargs.param2, sysargs.param3, sysargs.param4);
-}
+    if (cmd != VIOC_SYSCALL && cmd != VIOC_SYSCALL32) return -EINVAL;
 
-#ifdef AFS_IA64_LINUX20_ENV
+#ifdef NEED_IOCTL32
+#ifdef AFS_LINUX26_ENV 
+#ifdef AFS_S390X_LINUX26_ENV
+    if (test_thread_flag(TIF_31BIT))
+#elif AFS_AMD64_LINUX20_ENV
+    if (test_thread_flag(TIF_IA32))
+#else
+    if (test_thread_flag(TIF_32BIT))
+#endif /* AFS_S390X_LINUX26_ENV */
+#else
+#ifdef AFS_SPARC64_LINUX24_ENV
+    if (current->thread.flags & SPARC_FLAG_32BIT)
+#elif defined(AFS_SPARC64_LINUX20_ENV)
+    if (current->tss.flags & SPARC_FLAG_32BIT)
+#elif defined(AFS_AMD64_LINUX20_ENV)
+    if (current->thread.flags & THREAD_IA32)
+#elif defined(AFS_PPC64_LINUX20_ENV)
+    if (current->thread.flags & PPC_FLAG_32BIT)
+#elif defined(AFS_S390X_LINUX20_ENV)
+    if (current->thread.flags & S390_FLAG_31BIT)
+#else
+#error Not done for this linux type
+#endif /* AFS_LINUX26_ENV */
+#endif /* NEED_IOCTL32 */
+    {
+       if (copy_from_user(&sysargs32, (void *)arg,
+                          sizeof(struct afsprocdata32)))
+           return -EFAULT;
+
+       return afs_syscall((unsigned long)sysargs32.syscall,
+                          (unsigned long)sysargs32.param1,
+                          (unsigned long)sysargs32.param2,
+                          (unsigned long)sysargs32.param3,
+                          (unsigned long)sysargs32.param4);
+    } else
+#endif
+    {
+       if (copy_from_user(&sysargs, (void *)arg, sizeof(struct afsprocdata)))
+           return -EFAULT;
 
-asmlinkage long
-afs_syscall_stub(int r0, int r1, long r2, long r3, long r4, long gp)
-{
-    __asm__ __volatile__("alloc r42 = ar.pfs, 8, 3, 6, 0\n\t" "mov r41 = b0\n\t"       /* save rp */
-                        "mov out0 = in0\n\t" "mov out1 = in1\n\t" "mov out2 = in2\n\t" "mov out3 = in3\n\t" "mov out4 = in4\n\t" "mov out5 = gp\n\t"   /* save gp */
-                        ";;\n" ".L1:    mov r3 = ip\n\t" ";;\n\t" "addl r15=.fptr_afs_syscall-.L1,r3\n\t" ";;\n\t" "ld8 r15=[r15]\n\t" ";;\n\t" "ld8 r16=[r15],8\n\t" ";;\n\t" "ld8 gp=[r15]\n\t" "mov b6=r16\n\t" "br.call.sptk.many b0 = b6\n\t" ";;\n\t" "mov ar.pfs = r42\n\t" "mov b0 = r41\n\t" "mov gp = r48\n\t"       /* restore gp */
-                        "br.ret.sptk.many b0\n" ".fptr_afs_syscall:\n\t"
-                        "data8 @fptr(afs_syscall)");
+       return afs_syscall(sysargs.syscall, sysargs.param1,
+                          sysargs.param2, sysargs.param3, sysargs.param4);
+    }
 }
 
-asmlinkage long
-afs_xsetgroups_stub(int r0, int r1, long r2, long r3, long r4, long gp)
-{
-    __asm__ __volatile__("alloc r42 = ar.pfs, 8, 3, 6, 0\n\t" "mov r41 = b0\n\t"       /* save rp */
-                        "mov out0 = in0\n\t" "mov out1 = in1\n\t" "mov out2 = in2\n\t" "mov out3 = in3\n\t" "mov out4 = in4\n\t" "mov out5 = gp\n\t"   /* save gp */
-                        ";;\n" ".L2:    mov r3 = ip\n\t" ";;\n\t" "addl r15=.fptr_afs_xsetgroups - .L2,r3\n\t" ";;\n\t" "ld8 r15=[r15]\n\t" ";;\n\t" "ld8 r16=[r15],8\n\t" ";;\n\t" "ld8 gp=[r15]\n\t" "mov b6=r16\n\t" "br.call.sptk.many b0 = b6\n\t" ";;\n\t" "mov ar.pfs = r42\n\t" "mov b0 = r41\n\t" "mov gp = r48\n\t"  /* restore gp */
-                        "br.ret.sptk.many b0\n" ".fptr_afs_xsetgroups:\n\t"
-                        "data8 @fptr(afs_xsetgroups)");
+#if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL)
+static long afs_unlocked_ioctl(struct file *file, unsigned int cmd,
+                               unsigned long arg) {
+    return afs_ioctl(FILE_INODE(file), file, cmd, arg);
 }
-
-struct fptr {
-    void *ip;
-    unsigned long gp;
-};
-
-#endif /* AFS_IA64_LINUX20_ENV */
-
-#ifdef AFS_LINUX24_ENV
-asmlinkage int (*sys_setgroups32p) (int gidsetsize,
-                                   __kernel_gid32_t * grouplist);
-#endif /* AFS_LINUX24_ENV */
-
-#if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_S390X_LINUX24_ENV)
-#define POINTER2SYSCALL (unsigned int)(unsigned long)
-#define SYSCALL2POINTER (void *)(long)
-#else
-#define POINTER2SYSCALL (void *)
-#define SYSCALL2POINTER (void *)
 #endif
 
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 int __init
 afs_init(void)
@@ -620,45 +692,7 @@ int
 init_module(void)
 #endif
 {
-#if defined(AFS_IA64_LINUX20_ENV)
-    unsigned long kernel_gp = 0;
-    static struct fptr sys_setgroups;
-#endif /* defined(AFS_IA64_LINUX20_ENV) */
-    extern long afs_xsetgroups();
-#if defined(__NR_setgroups32)
-    extern int afs_xsetgroups32();
-#endif /* __NR_setgroups32 */
-#if defined(AFS_SPARC64_LINUX20_ENV) || defined (AFS_AMD64_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
-    extern int afs32_xsetgroups();
-#if (defined(__NR_setgroups32) && defined(AFS_SPARC64_LINUX20_ENV))
-    extern int afs32_xsetgroups32();
-#endif /* defined(__NR_setgroups32) && defined(AFS_SPARC64_LINUX20_ENV) */
-#if (defined(__NR_ia32_setgroups32) && defined(AFS_AMD64_LINUX20_ENV))
-    extern int afs32_xsetgroups32();
-#endif /* (defined(__NR_ia32_setgroups32) && defined(AFS_AMD64_LINUX20_ENV) */
-#endif /* AFS_SPARC64_LINUX20_ENV || AFS_AMD64_LINUX20_ENV || AFS_PPC64_LINUX20_ENV */
-
-#if !defined(EXPORTED_SYS_CALL_TABLE) || (defined(AFS_AMD64_LINUX20_ENV) && !defined(EXPORTED_IA32_SYS_CALL_TABLE))
-    unsigned long *ptr;
-    unsigned long offset=0;
-    unsigned long datalen=0;
-#if defined(EXPORTED_KALLSYMS_SYMBOL)
-    unsigned long token=0;
-#endif
-#if defined(EXPORTED_KALLSYMS_SYMBOL) || defined(EXPORTED_KALLSYMS_ADDRESS)
-    int ret;
-    char *mod_name;
-    unsigned long mod_start=0;
-    unsigned long mod_end=0;
-    char *sec_name;
-    unsigned long sec_start=0;
-    unsigned long sec_end=0;
-    char *sym_name;
-    unsigned long sym_start=0;
-    unsigned long sym_end=0;
-#endif
-#endif /* EXPORTED_SYS_CALL_TABLE */
-
+    int err;
     RWLOCK_INIT(&afs_xosi, "afs_xosi");
 
 #if !defined(AFS_LINUX24_ENV)
@@ -674,248 +708,19 @@ init_module(void)
 #endif /* AFS_S390_LINUX22_ENV */
 #endif /* !defined(AFS_LINUX24_ENV) */
 
-#ifndef EXPORTED_SYS_CALL_TABLE
-    sys_call_table = 0;
-
-#ifdef EXPORTED_KALLSYMS_SYMBOL
-    ret = 1;
-    token = 0;
-    while (ret) {
-       sym_start = 0;
-       ret =
-           kallsyms_symbol_to_address("sys_call_table", &token, &mod_name,
-                                      &mod_start, &mod_end, &sec_name,
-                                      &sec_start, &sec_end, &sym_name,
-                                      &sym_start, &sym_end);
-       if (ret && !strcmp(mod_name, "kernel"))
-           break;
-    }
-    if (ret && sym_start) {
-       sys_call_table = sym_start;
-    }
-#elif defined(EXPORTED_KALLSYMS_ADDRESS)
-    ret =
-       kallsyms_address_to_symbol((unsigned long)&init_mm, &mod_name,
-                                  &mod_start, &mod_end, &sec_name,
-                                  &sec_start, &sec_end, &sym_name,
-                                  &sym_start, &sym_end);
-    ptr = (unsigned long *)sec_start;
-    datalen = (sec_end - sec_start) / sizeof(unsigned long);
-#elif defined(AFS_IA64_LINUX20_ENV)
-    ptr = (unsigned long *)(&sys_close - 0x180000);
-    datalen = 0x180000 / sizeof(ptr);
-#elif defined(AFS_AMD64_LINUX20_ENV)
-    ptr = (unsigned long *)&init_mm;
-    datalen = 0x360000 / sizeof(ptr);
-#else
-    ptr = (unsigned long *)&init_mm;
-    datalen = 16384;
-#endif
-    for (offset = 0; offset < datalen; ptr++, offset++) {
-#if defined(AFS_IA64_LINUX20_ENV)
-       unsigned long close_ip =
-           (unsigned long)((struct fptr *)&sys_close)->ip;
-       unsigned long chdir_ip =
-           (unsigned long)((struct fptr *)&sys_chdir)->ip;
-       unsigned long write_ip =
-           (unsigned long)((struct fptr *)&sys_write)->ip;
-       if (ptr[0] == close_ip && ptr[__NR_chdir - __NR_close] == chdir_ip
-           && ptr[__NR_write - __NR_close] == write_ip) {
-           sys_call_table = (void *)&(ptr[-1 * (__NR_close - 1024)]);
-           break;
-       }
-#elif defined(EXPORTED_SYS_WAIT4) && defined(EXPORTED_SYS_CLOSE)
-       if (ptr[0] == (unsigned long)&sys_close
-           && ptr[__NR_wait4 - __NR_close] == (unsigned long)&sys_wait4) {
-           sys_call_table = ptr - __NR_close;
-           break;
-       }
-#elif defined(EXPORTED_SYS_CHDIR) && defined(EXPORTED_SYS_CLOSE)
-       if (ptr[0] == (unsigned long)&sys_close
-           && ptr[__NR_chdir - __NR_close] == (unsigned long)&sys_chdir) {
-           sys_call_table = ptr - __NR_close;
-           break;
-       }
-#elif defined(EXPORTED_SYS_OPEN)
-       if (ptr[0] == (unsigned long)&sys_exit
-           && ptr[__NR_open - __NR_exit] == (unsigned long)&sys_open) {
-           sys_call_table = ptr - __NR_exit;
-           break;
-       }
-#else /* EXPORTED_SYS_OPEN */
-       break;
-#endif /* EXPORTED_KALLSYMS_ADDRESS */
-    }
-#ifdef EXPORTED_KALLSYMS_ADDRESS
-    ret =
-       kallsyms_address_to_symbol((unsigned long)sys_call_table, &mod_name,
-                                  &mod_start, &mod_end, &sec_name,
-                                  &sec_start, &sec_end, &sym_name,
-                                  &sym_start, &sym_end);
-    if (ret && strcmp(sym_name, "sys_call_table"))
-       sys_call_table = 0;
-#endif /* EXPORTED_KALLSYMS_ADDRESS */
-    if (!sys_call_table) {
-       printf("Failed to find address of sys_call_table\n");
-    } else {
-       printf("Found sys_call_table at %lx\n", (unsigned long)sys_call_table);
-#if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_S390X_LINUX24_ENV)
-       error cant support this yet.;
-#endif /* AFS_SPARC64_LINUX20_ENV */
-#endif /* EXPORTED_SYS_CALL_TABLE */
-
-#ifdef AFS_AMD64_LINUX20_ENV
-#ifndef EXPORTED_IA32_SYS_CALL_TABLE
-       ia32_sys_call_table = 0;
-#ifdef EXPORTED_KALLSYMS_SYMBOL
-       ret = 1;
-       token = 0;
-       while (ret) {
-           sym_start = 0;
-           ret = kallsyms_symbol_to_address("ia32_sys_call_table", &token,
-                                            &mod_name, &mod_start, &mod_end,
-                                            &sec_name, &sec_start, &sec_end,
-                                            &sym_name, &sym_start, &sym_end);
-           if (ret && !strcmp(mod_name, "kernel"))
-               break;
-       }
-       if (ret && sym_start) {
-           ia32_sys_call_table = sym_start;
-       }
-#else /* EXPORTED_KALLSYMS_SYMBOL */
-#ifdef EXPORTED_KALLSYMS_ADDRESS
-       ret = kallsyms_address_to_symbol((unsigned long)
-                                        &interruptible_sleep_on,
-                                        &mod_name, &mod_start, &mod_end,
-                                        &sec_name, &sec_start, &sec_end,
-                                        &sym_name, &sym_start, &sym_end);
-       ptr = (unsigned long *)sec_start;
-       datalen = (sec_end - sec_start) / sizeof(unsigned long);
-#else /* EXPORTED_KALLSYMS_ADDRESS */
-#if defined(AFS_AMD64_LINUX20_ENV)
-       ptr = (unsigned long *)&interruptible_sleep_on;
-       datalen = 0x180000 / sizeof(ptr);
-#else /* AFS_AMD64_LINUX20_ENV */
-       ptr = (unsigned long *)&interruptible_sleep_on;
-       datalen = 16384;
-#endif /* AFS_AMD64_LINUX20_ENV */
-#endif /* EXPORTED_KALLSYMS_ADDRESS */
-       for (offset = 0; offset < datalen; ptr++, offset++) {
-           if (ptr[0] == (unsigned long)&sys_exit
-               && ptr[__NR_ia32_open - __NR_ia32_exit] ==
-               (unsigned long)&sys_open) {
-                   ia32_sys_call_table = ptr - __NR_ia32_exit;
-                   break;
-           }
-       }
-#ifdef EXPORTED_KALLSYMS_ADDRESS
-       ret = kallsyms_address_to_symbol((unsigned long)ia32_sys_call_table,
-                                        &mod_name, &mod_start, &mod_end,
-                                        &sec_name, &sec_start, &sec_end,
-                                        &sym_name, &sym_start, &sym_end);
-       if (ret && strcmp(sym_name, "ia32_sys_call_table"))
-           ia32_sys_call_table = 0;
-#endif /* EXPORTED_KALLSYMS_ADDRESS */
-#endif /* EXPORTED_KALLSYMS_SYMBOL */
-       if (!ia32_sys_call_table) {
-           printf("Warning: Failed to find address of ia32_sys_call_table\n");
-       } else {
-           printf("Found ia32_sys_call_table at %lx\n", (unsigned long)ia32_sys_call_table);
-       }
-#else
-       printf("Found ia32_sys_call_table at %lx\n", (unsigned long)ia32_sys_call_table);
-#endif /* IA32_SYS_CALL_TABLE */
-#endif
-
-       /* Initialize pointers to kernel syscalls. */
-#if !defined(AFS_LINUX24_ENV)
-       sys_settimeofdayp = SYSCALL2POINTER sys_call_table[_S(__NR_settimeofday)];
-#endif /* AFS_IA64_LINUX20_ENV */
-
-       /* setup AFS entry point. */
-       if (
-#if defined(AFS_IA64_LINUX20_ENV)
-               SYSCALL2POINTER sys_call_table[__NR_afs_syscall - 1024]
-#else
-               SYSCALL2POINTER sys_call_table[_S(__NR_afs_syscall)]
-#endif
-               == afs_syscall) {
-           printf("AFS syscall entry point already in use!\n");
-           return -EBUSY;
-       }
-#if defined(AFS_IA64_LINUX20_ENV)
-       afs_ni_syscall = sys_call_table[__NR_afs_syscall - 1024];
-       sys_call_table[__NR_afs_syscall - 1024] =
-               POINTER2SYSCALL((struct fptr *)afs_syscall_stub)->ip;
-#else /* AFS_IA64_LINUX20_ENV */
-       afs_ni_syscall = sys_call_table[_S(__NR_afs_syscall)];
-       sys_call_table[_S(__NR_afs_syscall)] = POINTER2SYSCALL afs_syscall;
-#ifdef AFS_SPARC64_LINUX20_ENV
-       afs_ni_syscall32 = sys_call_table32[__NR_afs_syscall];
-       sys_call_table32[__NR_afs_syscall] = POINTER2SYSCALL afs_syscall32;
-#endif
-#endif /* AFS_IA64_LINUX20_ENV */
-#ifdef AFS_AMD64_LINUX20_ENV
-       if (ia32_sys_call_table) {
-           ia32_ni_syscall = ia32_sys_call_table[__NR_ia32_afs_syscall];
-           ia32_sys_call_table[__NR_ia32_afs_syscall] =
-                   POINTER2SYSCALL afs_syscall;
-       }
-#endif /* AFS_S390_LINUX22_ENV */
-#ifndef EXPORTED_SYS_CALL_TABLE
-    }
-#endif /* EXPORTED_SYS_CALL_TABLE */
     osi_Init();
-    register_filesystem(&afs_fs_type);
-
-    /* Intercept setgroups calls */
-    if (sys_call_table) {
-#if defined(AFS_IA64_LINUX20_ENV)
-    sys_setgroupsp = (void *)&sys_setgroups;
-
-    ((struct fptr *)sys_setgroupsp)->ip =
-       SYSCALL2POINTER sys_call_table[__NR_setgroups - 1024];
-    ((struct fptr *)sys_setgroupsp)->gp = kernel_gp;
-
-    sys_call_table[__NR_setgroups - 1024] =
-       POINTER2SYSCALL((struct fptr *)afs_xsetgroups_stub)->ip;
-#else /* AFS_IA64_LINUX20_ENV */
-    sys_setgroupsp = SYSCALL2POINTER sys_call_table[_S(__NR_setgroups)];
-    sys_call_table[_S(__NR_setgroups)] = POINTER2SYSCALL afs_xsetgroups;
-#ifdef AFS_SPARC64_LINUX20_ENV
-    sys32_setgroupsp = SYSCALL2POINTER sys_call_table32[__NR_setgroups];
-    sys_call_table32[__NR_setgroups] = POINTER2SYSCALL afs32_xsetgroups;
-#endif /* AFS_SPARC64_LINUX20_ENV */
-#if defined(__NR_setgroups32)
-    sys_setgroups32p = SYSCALL2POINTER sys_call_table[__NR_setgroups32];
-    sys_call_table[__NR_setgroups32] = POINTER2SYSCALL afs_xsetgroups32;
-#ifdef AFS_SPARC64_LINUX20_ENV
-       sys32_setgroups32p =
-           SYSCALL2POINTER sys_call_table32[__NR_setgroups32];
-       sys_call_table32[__NR_setgroups32] =
-           POINTER2SYSCALL afs32_xsetgroups32;
-#endif /* AFS_SPARC64_LINUX20_ENV */
-#endif /* __NR_setgroups32 */
-#ifdef AFS_AMD64_LINUX20_ENV
-    if (ia32_sys_call_table) {
-       sys32_setgroupsp =
-           SYSCALL2POINTER ia32_sys_call_table[__NR_ia32_setgroups];
-       ia32_sys_call_table[__NR_ia32_setgroups] =
-           POINTER2SYSCALL afs32_xsetgroups;
-#if defined(__NR_ia32_setgroups32)
-       sys32_setgroups32p =
-           SYSCALL2POINTER ia32_sys_call_table[__NR_ia32_setgroups32];
-       ia32_sys_call_table[__NR_ia32_setgroups32] =
-           POINTER2SYSCALL afs32_xsetgroups32;
-#endif /* __NR_ia32_setgroups32 */
-    }
-#endif /* AFS_AMD64_LINUX20_ENV */
-#endif /* AFS_IA64_LINUX20_ENV */
-
-    }
 
+    err = osi_syscall_init();
+    if (err)
+       return err;
+    err = afs_init_inodecache();
+    if (err)
+       return err;
+    register_filesystem(&afs_fs_type);
     osi_sysctl_init();
+#ifdef AFS_LINUX24_ENV
     afsproc_init();
+#endif
 
     return 0;
 }
@@ -929,49 +734,20 @@ cleanup_module(void)
 #endif
 {
     osi_sysctl_clean();
-    if (sys_call_table) {
-#if defined(AFS_IA64_LINUX20_ENV)
-    sys_call_table[__NR_setgroups - 1024] =
-       POINTER2SYSCALL((struct fptr *)sys_setgroupsp)->ip;
-    sys_call_table[__NR_afs_syscall - 1024] = afs_ni_syscall;
-#else /* AFS_IA64_LINUX20_ENV */
-    sys_call_table[_S(__NR_setgroups)] = POINTER2SYSCALL sys_setgroupsp;
-    sys_call_table[_S(__NR_afs_syscall)] = afs_ni_syscall;
-# ifdef AFS_SPARC64_LINUX20_ENV
-    sys_call_table32[__NR_setgroups] = POINTER2SYSCALL sys32_setgroupsp;
-    sys_call_table32[__NR_afs_syscall] = afs_ni_syscall32;
-# endif
-# if defined(__NR_setgroups32)
-    sys_call_table[__NR_setgroups32] = POINTER2SYSCALL sys_setgroups32p;
-# ifdef AFS_SPARC64_LINUX20_ENV
-       sys_call_table32[__NR_setgroups32] =
-           POINTER2SYSCALL sys32_setgroups32p;
-# endif
-# endif
-#endif /* AFS_IA64_LINUX20_ENV */
-#ifdef AFS_AMD64_LINUX20_ENV
-    if (ia32_sys_call_table) {
-       ia32_sys_call_table[__NR_ia32_setgroups] =
-           POINTER2SYSCALL sys32_setgroupsp;
-       ia32_sys_call_table[__NR_ia32_afs_syscall] =
-           POINTER2SYSCALL ia32_ni_syscall;
-# if defined(__NR_setgroups32)
-       ia32_sys_call_table[__NR_ia32_setgroups32] =
-           POINTER2SYSCALL sys32_setgroups32p;
-#endif
-    }
-#endif
-    }
+    osi_syscall_clean();
     unregister_filesystem(&afs_fs_type);
 
-    osi_linux_free_inode_pages();      /* Invalidate all pages using AFS inodes. */
+    afs_destroy_inodecache();
     osi_linux_free_afs_memory();
 
+#ifdef AFS_LINUX24_ENV
     afsproc_exit();
+#endif
     return;
 }
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+MODULE_LICENSE("http://www.openafs.org/dl/license10.html");
 module_init(afs_init);
 module_exit(afs_cleanup);
 #endif