vserver 2.0 rc7
[linux-2.6.git] / kernel / sysctl.c
index 79e7c09..d34b4e6 100644 (file)
 #include <linux/initrd.h>
 #include <linux/times.h>
 #include <linux/limits.h>
+#include <linux/dcache.h>
+#include <linux/syscalls.h>
+#include <linux/vserver/cvirt.h>
+
 #include <asm/uaccess.h>
+#include <asm/processor.h>
 
 #ifdef CONFIG_ROOT_NFS
 #include <linux/nfs_fs.h>
 #if defined(CONFIG_SYSCTL)
 
 /* External variables not in a header file. */
-extern int panic_timeout;
 extern int C_A_D;
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern int max_threads;
-extern atomic_t nr_queued_signals;
-extern int max_queued_signals;
 extern int sysrq_enabled;
 extern int core_uses_pid;
 extern char core_pattern[];
 extern int cad_pid;
 extern int pid_max;
-extern int sysctl_lower_zone_protection;
 extern int min_free_kbytes;
 extern int printk_ratelimit_jiffies;
 extern int printk_ratelimit_burst;
+extern int pid_max_min, pid_max_max;
+
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
+int unknown_nmi_panic;
+extern int proc_unknown_nmi_panic(ctl_table *, int, struct file *,
+                                 void __user *, size_t *, loff_t *);
+#endif
 
 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
 static int maxolduid = 65535;
@@ -77,6 +85,7 @@ extern char modprobe_path[];
 #ifdef CONFIG_HOTPLUG
 extern char hotplug_path[];
 #endif
+extern char vshelper_path[];
 #ifdef CONFIG_CHR_DEV_SG
 extern int sg_big_buff;
 #endif
@@ -110,20 +119,16 @@ extern int sysctl_userprocess_debug;
 
 extern int sysctl_hz_timer;
 
-#if defined(CONFIG_PPC32) && defined(CONFIG_6xx)
-extern unsigned long powersave_nap;
-int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
-                 void *buffer, size_t *lenp);
-#endif
-
 #ifdef CONFIG_BSD_PROCESS_ACCT
 extern int acct_parm[];
 #endif
 
+int randomize_va_space = 1;
+
 static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t,
                       ctl_table *, void **);
 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp);
+                 void __user *buffer, size_t *lenp, loff_t *ppos);
 
 static ctl_table root_table[];
 static struct ctl_table_header root_table_header =
@@ -143,6 +148,10 @@ extern ctl_table random_table[];
 extern ctl_table pty_table[];
 #endif
 
+#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
+int sysctl_legacy_va_layout;
+#endif
+
 /* /proc declarations: */
 
 #ifdef CONFIG_PROC_FS
@@ -218,45 +227,50 @@ static ctl_table kern_table[] = {
                .ctl_name       = KERN_OSTYPE,
                .procname       = "ostype",
                .data           = system_utsname.sysname,
-               .maxlen         = 64,
+               .maxlen         = sizeof(system_utsname.sysname),
                .mode           = 0444,
                .proc_handler   = &proc_doutsstring,
+               .virt_handler   = &vx_uts_virt_handler,
                .strategy       = &sysctl_string,
        },
        {
                .ctl_name       = KERN_OSRELEASE,
                .procname       = "osrelease",
                .data           = system_utsname.release,
-               .maxlen         = 64,
+               .maxlen         = sizeof(system_utsname.release),
                .mode           = 0444,
                .proc_handler   = &proc_doutsstring,
+               .virt_handler   = &vx_uts_virt_handler,
                .strategy       = &sysctl_string,
        },
        {
                .ctl_name       = KERN_VERSION,
                .procname       = "version",
                .data           = system_utsname.version,
-               .maxlen         = 64,
+               .maxlen         = sizeof(system_utsname.version),
                .mode           = 0444,
                .proc_handler   = &proc_doutsstring,
+               .virt_handler   = &vx_uts_virt_handler,
                .strategy       = &sysctl_string,
        },
        {
                .ctl_name       = KERN_NODENAME,
                .procname       = "hostname",
                .data           = system_utsname.nodename,
-               .maxlen         = 64,
+               .maxlen         = sizeof(system_utsname.nodename),
                .mode           = 0644,
                .proc_handler   = &proc_doutsstring,
+               .virt_handler   = &vx_uts_virt_handler,
                .strategy       = &sysctl_string,
        },
        {
                .ctl_name       = KERN_DOMAINNAME,
                .procname       = "domainname",
                .data           = system_utsname.domainname,
-               .maxlen         = 64,
+               .maxlen         = sizeof(system_utsname.domainname),
                .mode           = 0644,
                .proc_handler   = &proc_doutsstring,
+               .virt_handler   = &vx_uts_virt_handler,
                .strategy       = &sysctl_string,
        },
        {
@@ -289,7 +303,7 @@ static ctl_table kern_table[] = {
                .procname       = "tainted",
                .data           = &tainted,
                .maxlen         = sizeof(int),
-               .mode           = 0644,
+               .mode           = 0444,
                .proc_handler   = &proc_dointvec,
        },
        {
@@ -354,22 +368,6 @@ static ctl_table kern_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
-#endif
-#if defined(CONFIG_PPC32) && defined(CONFIG_6xx)
-       {
-               .ctl_name       = KERN_PPC_POWERSAVE_NAP,
-               .procname       = "powersave-nap",
-               .data           = &powersave_nap,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
-       },
-       {
-               .ctl_name       = KERN_PPC_L2CR,
-               .procname       = "l2cr",
-               .mode           = 0644,
-               .proc_handler   = &proc_dol2crvec,
-       },
 #endif
        {
                .ctl_name       = KERN_CTLALTDEL,
@@ -392,7 +390,7 @@ static ctl_table kern_table[] = {
                .ctl_name       = KERN_MODPROBE,
                .procname       = "modprobe",
                .data           = &modprobe_path,
-               .maxlen         = 256,
+               .maxlen         = KMOD_PATH_LEN,
                .mode           = 0644,
                .proc_handler   = &proc_dostring,
                .strategy       = &sysctl_string,
@@ -403,12 +401,21 @@ static ctl_table kern_table[] = {
                .ctl_name       = KERN_HOTPLUG,
                .procname       = "hotplug",
                .data           = &hotplug_path,
-               .maxlen         = 256,
+               .maxlen         = HOTPLUG_PATH_LEN,
                .mode           = 0644,
                .proc_handler   = &proc_dostring,
                .strategy       = &sysctl_string,
        },
 #endif
+       {
+               .ctl_name       = KERN_VSHELPER,
+               .procname       = "vshelper",
+               .data           = &vshelper_path,
+               .maxlen         = 256,
+               .mode           = 0644,
+               .proc_handler   = &proc_dostring,
+               .strategy       = &sysctl_string,
+       },
 #ifdef CONFIG_CHR_DEV_SG
        {
                .ctl_name       = KERN_SG_BIG_BUFF,
@@ -429,22 +436,6 @@ static ctl_table kern_table[] = {
                .proc_handler   = &proc_dointvec,
        },
 #endif
-       {
-               .ctl_name       = KERN_RTSIGNR,
-               .procname       = "rtsig-nr",
-               .data           = &nr_queued_signals,
-               .maxlen         = sizeof(int),
-               .mode           = 0444,
-               .proc_handler   = &proc_dointvec,
-       },
-       {
-               .ctl_name       = KERN_RTSIGMAX,
-               .procname       = "rtsig-max",
-               .data           = &max_queued_signals,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
-       },
 #ifdef CONFIG_SYSVIPC
        {
                .ctl_name       = KERN_SHMMAX,
@@ -601,7 +592,10 @@ static ctl_table kern_table[] = {
                .data           = &pid_max,
                .maxlen         = sizeof (int),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = sysctl_intvec,
+               .extra1         = &pid_max_min,
+               .extra2         = &pid_max_max,
        },
        {
                .ctl_name       = KERN_PANIC_ON_OOPS,
@@ -636,6 +630,35 @@ static ctl_table kern_table[] = {
                .mode           = 0444,
                .proc_handler   = &proc_dointvec,
        },
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
+       {
+               .ctl_name       = KERN_UNKNOWN_NMI_PANIC,
+               .procname       = "unknown_nmi_panic",
+               .data           = &unknown_nmi_panic,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler   = &proc_unknown_nmi_panic,
+       },
+#endif
+#if defined(CONFIG_X86)
+       {
+               .ctl_name       = KERN_BOOTLOADER_TYPE,
+               .procname       = "bootloader_type",
+               .data           = &bootloader_type,
+               .maxlen         = sizeof (int),
+               .mode           = 0444,
+               .proc_handler   = &proc_dointvec,
+       },
+#endif
+       {
+               .ctl_name       = KERN_RANDOMIZE,
+               .procname       = "randomize_va_space",
+               .data           = &randomize_va_space,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
+
        { .ctl_name = 0 }
 };
 
@@ -738,16 +761,23 @@ static ctl_table vm_table[] = {
                .extra1         = (void *)&hugetlb_zero,
                .extra2         = (void *)&hugetlb_infinity,
         },
+        {
+               .ctl_name       = VM_HUGETLB_GROUP,
+               .procname       = "hugetlb_shm_group",
+               .data           = &sysctl_hugetlb_shm_group,
+               .maxlen         = sizeof(gid_t),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+        },
 #endif
        {
-               .ctl_name       = VM_LOWER_ZONE_PROTECTION,
-               .procname       = "lower_zone_protection",
-               .data           = &sysctl_lower_zone_protection,
-               .maxlen         = sizeof(sysctl_lower_zone_protection),
+               .ctl_name       = VM_LOWMEM_RESERVE_RATIO,
+               .procname       = "lowmem_reserve_ratio",
+               .data           = &sysctl_lowmem_reserve_ratio,
+               .maxlen         = sizeof(sysctl_lowmem_reserve_ratio),
                .mode           = 0644,
-               .proc_handler   = &lower_zone_protection_sysctl_handler,
+               .proc_handler   = &lowmem_reserve_ratio_sysctl_handler,
                .strategy       = &sysctl_intvec,
-               .extra1         = &zero,
        },
        {
                .ctl_name       = VM_MIN_FREE_KBYTES,
@@ -759,6 +789,7 @@ static ctl_table vm_table[] = {
                .strategy       = &sysctl_intvec,
                .extra1         = &zero,
        },
+#ifdef CONFIG_MMU
        {
                .ctl_name       = VM_MAX_MAP_COUNT,
                .procname       = "max_map_count",
@@ -767,6 +798,7 @@ static ctl_table vm_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dointvec
        },
+#endif
        {
                .ctl_name       = VM_LAPTOP_MODE,
                .procname       = "laptop_mode",
@@ -787,6 +819,39 @@ static ctl_table vm_table[] = {
                .strategy       = &sysctl_intvec,
                .extra1         = &zero,
        },
+       {
+               .ctl_name       = VM_VFS_CACHE_PRESSURE,
+               .procname       = "vfs_cache_pressure",
+               .data           = &sysctl_vfs_cache_pressure,
+               .maxlen         = sizeof(sysctl_vfs_cache_pressure),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero,
+       },
+#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
+       {
+               .ctl_name       = VM_LEGACY_VA_LAYOUT,
+               .procname       = "legacy_va_layout",
+               .data           = &sysctl_legacy_va_layout,
+               .maxlen         = sizeof(sysctl_legacy_va_layout),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero,
+       },
+#endif
+#ifdef CONFIG_SWAP
+       {
+               .ctl_name       = VM_SWAP_TOKEN_TIMEOUT,
+               .procname       = "swap_token_timeout",
+               .data           = &swap_token_default_timeout,
+               .maxlen         = sizeof(swap_token_default_timeout),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
+       },
+#endif
        { .ctl_name = 0 }
 };
 
@@ -865,6 +930,7 @@ static ctl_table fs_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
+#ifdef CONFIG_DNOTIFY
        {
                .ctl_name       = FS_DIR_NOTIFY,
                .procname       = "dir-notify-enable",
@@ -873,6 +939,8 @@ static ctl_table fs_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
+#endif
+#ifdef CONFIG_MMU
        {
                .ctl_name       = FS_LEASE_TIME,
                .procname       = "lease-break-time",
@@ -897,6 +965,7 @@ static ctl_table fs_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
+#endif
        { .ctl_name = 0 }
 };
 
@@ -1285,11 +1354,7 @@ static ssize_t do_rw_proc(int write, struct file * file, char __user * buf,
        
        res = count;
 
-       /*
-        * FIXME: we need to pass on ppos to the handler.
-        */
-
-       error = (*table->proc_handler) (table, write, file, buf, &res);
+       error = (*table->proc_handler) (table, write, file, buf, &res, ppos);
        if (error)
                return error;
        return res;
@@ -1328,6 +1393,7 @@ static ssize_t proc_writesys(struct file * file, const char __user * buf,
  * @filp: the file structure
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
+ * @ppos: file position
  *
  * Reads/writes a string from/to the user buffer. If the kernel
  * buffer provided is not large enough to hold the string, the
@@ -1339,18 +1405,22 @@ static ssize_t proc_writesys(struct file * file, const char __user * buf,
  * Returns 0 on success.
  */
 int proc_dostring(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp)
+                 void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-       size_t len;
+       size_t len, maxlen;
        char __user *p;
        char c;
+       void *data;
+
+       data = table->data;
+       maxlen = table->maxlen;
+
+       if (!data || !maxlen || !*lenp || (*ppos && !write))
+               return (*lenp = 0);
        
-       if (!table->data || !table->maxlen || !*lenp ||
-           (filp->f_pos && !write)) {
-               *lenp = 0;
-               return 0;
-       }
-       
+       if (table->virt_handler)
+               table->virt_handler(table, write, filp->f_xid, &data, &maxlen);
+
        if (write) {
                len = 0;
                p = buffer;
@@ -1361,28 +1431,28 @@ int proc_dostring(ctl_table *table, int write, struct file *filp,
                                break;
                        len++;
                }
-               if (len >= table->maxlen)
-                       len = table->maxlen-1;
-               if(copy_from_user(table->data, buffer, len))
+               if (len >= maxlen)
+                       len = maxlen-1;
+               if(copy_from_user(data, buffer, len))
                        return -EFAULT;
-               ((char *) table->data)[len] = 0;
-               filp->f_pos += *lenp;
+               ((char *) data)[len] = 0;
+               *ppos += *lenp;
        } else {
-               len = strlen(table->data);
-               if (len > table->maxlen)
-                       len = table->maxlen;
+               len = strlen(data);
+               if (len > maxlen)
+                       len = maxlen;
                if (len > *lenp)
                        len = *lenp;
                if (len)
-                       if(copy_to_user(buffer, table->data, len))
+                       if(copy_to_user(buffer, data, len))
                                return -EFAULT;
                if (len < *lenp) {
-                       if(put_user('\n', ((char *) buffer) + len))
+                       if(put_user('\n', ((char __user *) buffer) + len))
                                return -EFAULT;
                        len++;
                }
                *lenp = len;
-               filp->f_pos += len;
+               *ppos += len;
        }
        return 0;
 }
@@ -1393,17 +1463,17 @@ int proc_dostring(ctl_table *table, int write, struct file *filp,
  */
  
 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp)
+                 void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        int r;
 
        if (!write) {
                down_read(&uts_sem);
-               r=proc_dostring(table,0,filp,buffer,lenp);
+               r=proc_dostring(table,0,filp,buffer,lenp, ppos);
                up_read(&uts_sem);
        } else {
                down_write(&uts_sem);
-               r=proc_dostring(table,1,filp,buffer,lenp);
+               r=proc_dostring(table,1,filp,buffer,lenp, ppos);
                up_write(&uts_sem);
        }
        return r;
@@ -1429,20 +1499,21 @@ static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
 }
 
 static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp, 
+                 void __user *buffer, size_t *lenp, loff_t *ppos,
                  int (*conv)(int *negp, unsigned long *lvalp, int *valp,
                              int write, void *data),
                  void *data)
 {
-#define TMPBUFLEN 20
+#define TMPBUFLEN 21
        int *i, vleft, first=1, neg, val;
        unsigned long lval;
        size_t left, len;
        
        char buf[TMPBUFLEN], *p;
+       char __user *s = buffer;
        
        if (!table->data || !table->maxlen || !*lenp ||
-           (filp->f_pos && !write)) {
+           (*ppos && !write)) {
                *lenp = 0;
                return 0;
        }
@@ -1458,12 +1529,12 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
                if (write) {
                        while (left) {
                                char c;
-                               if (get_user(c,(char __user *) buffer))
+                               if (get_user(c, s))
                                        return -EFAULT;
                                if (!isspace(c))
                                        break;
                                left--;
-                               buffer++;
+                               s++;
                        }
                        if (!left)
                                break;
@@ -1471,7 +1542,7 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
                        len = left;
                        if (len > sizeof(buf) - 1)
                                len = sizeof(buf) - 1;
-                       if(copy_from_user(buf, buffer, len))
+                       if (copy_from_user(buf, s, len))
                                return -EFAULT;
                        buf[len] = 0;
                        p = buf;
@@ -1489,7 +1560,7 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
                                break;
                        if (neg)
                                val = -val;
-                       buffer += len;
+                       s += len;
                        left -= len;
 
                        if (conv(&neg, &lval, i, 1, data))
@@ -1506,23 +1577,22 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
                        len = strlen(buf);
                        if (len > left)
                                len = left;
-                       if(copy_to_user(buffer, buf, len))
+                       if(copy_to_user(s, buf, len))
                                return -EFAULT;
                        left -= len;
-                       buffer += len;
+                       s += len;
                }
        }
 
        if (!write && !first && left) {
-               if(put_user('\n', (char *) buffer))
+               if(put_user('\n', s))
                        return -EFAULT;
-               left--, buffer++;
+               left--, s++;
        }
        if (write) {
-               p = (char *) buffer;
                while (left) {
                        char c;
-                       if (get_user(c, p++))
+                       if (get_user(c, s++))
                                return -EFAULT;
                        if (!isspace(c))
                                break;
@@ -1532,7 +1602,7 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
        if (write && first)
                return -EINVAL;
        *lenp -= left;
-       filp->f_pos += *lenp;
+       *ppos += *lenp;
        return 0;
 #undef TMPBUFLEN
 }
@@ -1544,6 +1614,7 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
  * @filp: the file structure
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
+ * @ppos: file position
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
  * values from/to the user buffer, treated as an ASCII string. 
@@ -1551,9 +1622,9 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
  * Returns 0 on success.
  */
 int proc_dointvec(ctl_table *table, int write, struct file *filp,
-                    void __user *buffer, size_t *lenp)
+                    void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-    return do_proc_dointvec(table,write,filp,buffer,lenp,
+    return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
                            NULL,NULL);
 }
 
@@ -1599,7 +1670,7 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
  */
  
 int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
-                       void __user *buffer, size_t *lenp)
+                       void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        int op;
 
@@ -1608,7 +1679,7 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
        }
 
        op = (current->pid == 1) ? OP_SET : OP_AND;
-       return do_proc_dointvec(table,write,filp,buffer,lenp,
+       return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
                                do_proc_dointvec_bset_conv,&op);
 }
 
@@ -1648,6 +1719,7 @@ static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp,
  * @filp: the file structure
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
+ * @ppos: file position
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
  * values from/to the user buffer, treated as an ASCII string.
@@ -1658,30 +1730,32 @@ static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp,
  * Returns 0 on success.
  */
 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp)
+                 void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        struct do_proc_dointvec_minmax_conv_param param = {
                .min = (int *) table->extra1,
                .max = (int *) table->extra2,
        };
-       return do_proc_dointvec(table, write, filp, buffer, lenp,
+       return do_proc_dointvec(table, write, filp, buffer, lenp, ppos,
                                do_proc_dointvec_minmax_conv, &param);
 }
 
 static int do_proc_doulongvec_minmax(ctl_table *table, int write,
                                     struct file *filp,
-                                    void __user *buffer, size_t *lenp,
+                                    void __user *buffer,
+                                    size_t *lenp, loff_t *ppos,
                                     unsigned long convmul,
                                     unsigned long convdiv)
 {
-#define TMPBUFLEN 20
+#define TMPBUFLEN 21
        unsigned long *i, *min, *max, val;
        int vleft, first=1, neg;
        size_t len, left;
        char buf[TMPBUFLEN], *p;
+       char __user *s = buffer;
        
        if (!table->data || !table->maxlen || !*lenp ||
-           (filp->f_pos && !write)) {
+           (*ppos && !write)) {
                *lenp = 0;
                return 0;
        }
@@ -1696,12 +1770,12 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write,
                if (write) {
                        while (left) {
                                char c;
-                               if (get_user(c, (char __user *) buffer))
+                               if (get_user(c, s))
                                        return -EFAULT;
                                if (!isspace(c))
                                        break;
                                left--;
-                               buffer++;
+                               s++;
                        }
                        if (!left)
                                break;
@@ -1709,7 +1783,7 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write,
                        len = left;
                        if (len > TMPBUFLEN-1)
                                len = TMPBUFLEN-1;
-                       if (copy_from_user(buf, buffer, len))
+                       if (copy_from_user(buf, s, len))
                                return -EFAULT;
                        buf[len] = 0;
                        p = buf;
@@ -1725,7 +1799,7 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write,
                                break;
                        if (neg)
                                val = -val;
-                       buffer += len;
+                       s += len;
                        left -= len;
 
                        if(neg)
@@ -1741,23 +1815,22 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write,
                        len = strlen(buf);
                        if (len > left)
                                len = left;
-                       if(copy_to_user(buffer, buf, len))
+                       if(copy_to_user(s, buf, len))
                                return -EFAULT;
                        left -= len;
-                       buffer += len;
+                       s += len;
                }
        }
 
        if (!write && !first && left) {
-               if(put_user('\n', (char *) buffer))
+               if(put_user('\n', s))
                        return -EFAULT;
-               left--, buffer++;
+               left--, s++;
        }
        if (write) {
-               p = (char *) buffer;
                while (left) {
                        char c;
-                       if (get_user(c, p++))
+                       if (get_user(c, s++))
                                return -EFAULT;
                        if (!isspace(c))
                                break;
@@ -1767,7 +1840,7 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write,
        if (write && first)
                return -EINVAL;
        *lenp -= left;
-       filp->f_pos += *lenp;
+       *ppos += *lenp;
        return 0;
 #undef TMPBUFLEN
 }
@@ -1779,6 +1852,7 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write,
  * @filp: the file structure
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
+ * @ppos: file position
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
  * values from/to the user buffer, treated as an ASCII string.
@@ -1789,9 +1863,9 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write,
  * Returns 0 on success.
  */
 int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
-                          void __user *buffer, size_t *lenp)
+                          void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-    return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, 1l, 1l);
+    return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos, 1l, 1l);
 }
 
 /**
@@ -1801,6 +1875,7 @@ int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
  * @filp: the file structure
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
+ * @ppos: file position
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
  * values from/to the user buffer, treated as an ASCII string. The values
@@ -1813,10 +1888,11 @@ int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
  */
 int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
                                      struct file *filp,
-                                     void __user *buffer, size_t *lenp)
+                                     void __user *buffer,
+                                     size_t *lenp, loff_t *ppos)
 {
     return do_proc_doulongvec_minmax(table, write, filp, buffer,
-                                    lenp, HZ, 1000l);
+                                    lenp, ppos, HZ, 1000l);
 }
 
 
@@ -1862,6 +1938,27 @@ static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
        return 0;
 }
 
+static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp,
+                                           int *valp,
+                                           int write, void *data)
+{
+       if (write) {
+               *valp = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);
+       } else {
+               int val = *valp;
+               unsigned long lval;
+               if (val < 0) {
+                       *negp = -1;
+                       lval = (unsigned long)-val;
+               } else {
+                       *negp = 0;
+                       lval = (unsigned long)val;
+               }
+               *lvalp = jiffies_to_msecs(lval);
+       }
+       return 0;
+}
+
 /**
  * proc_dointvec_jiffies - read a vector of integers as seconds
  * @table: the sysctl table
@@ -1869,6 +1966,7 @@ static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
  * @filp: the file structure
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
+ * @ppos: file position
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
  * values from/to the user buffer, treated as an ASCII string. 
@@ -1878,9 +1976,9 @@ static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
  * Returns 0 on success.
  */
 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
-                         void __user *buffer, size_t *lenp)
+                         void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-    return do_proc_dointvec(table,write,filp,buffer,lenp,
+    return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
                            do_proc_dointvec_jiffies_conv,NULL);
 }
 
@@ -1900,65 +1998,96 @@ int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
  * Returns 0 on success.
  */
 int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
-                                void __user *buffer, size_t *lenp)
+                                void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-    return do_proc_dointvec(table,write,filp,buffer,lenp,
+    return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
                            do_proc_dointvec_userhz_jiffies_conv,NULL);
 }
 
+/**
+ * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds
+ * @table: the sysctl table
+ * @write: %TRUE if this is a write to the sysctl file
+ * @filp: the file structure
+ * @buffer: the user buffer
+ * @lenp: the size of the user buffer
+ * @ppos: file position
+ * @ppos: the current position in the file
+ *
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
+ * values from/to the user buffer, treated as an ASCII string. 
+ * The values read are assumed to be in 1/1000 seconds, and 
+ * are converted into jiffies.
+ *
+ * Returns 0 on success.
+ */
+int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
+                            void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       return do_proc_dointvec(table, write, filp, buffer, lenp, ppos,
+                               do_proc_dointvec_ms_jiffies_conv, NULL);
+}
+
 #else /* CONFIG_PROC_FS */
 
 int proc_dostring(ctl_table *table, int write, struct file *filp,
-                 void *buffer, size_t *lenp)
+                 void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
-                           void *buffer, size_t *lenp)
+                           void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_dointvec(ctl_table *table, int write, struct file *filp,
-                 void *buffer, size_t *lenp)
+                 void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
-                       void *buffer, size_t *lenp)
+                       void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
-                   void *buffer, size_t *lenp)
+                   void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
-                   void *buffer, size_t *lenp)
+                   void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
-                   void *buffer, size_t *lenp)
+                   void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       return -ENOSYS;
+}
+
+int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
+                            void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
-                   void *buffer, size_t *lenp)
+                   void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
                                      struct file *filp,
-                                     void *buffer, size_t *lenp)
+                                     void __user *buffer,
+                                     size_t *lenp, loff_t *ppos)
 {
     return -ENOSYS;
 }
@@ -1991,7 +2120,7 @@ int sysctl_string(ctl_table *table, int __user *name, int nlen,
                                len = table->maxlen;
                        if(copy_to_user(oldval, table->data, len))
                                return -EFAULT;
-                       if(put_user(0, ((char *) oldval) + len))
+                       if(put_user(0, ((char __user *) oldval) + len))
                                return -EFAULT;
                        if(put_user(len, oldlenp))
                                return -EFAULT;
@@ -2019,10 +2148,14 @@ int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
                void __user *newval, size_t newlen, void **context)
 {
-       int i, *vec, *min, *max;
-       size_t length;
 
        if (newval && newlen) {
+               int __user *vec = (int __user *) newval;
+               int *min = (int *) table->extra1;
+               int *max = (int *) table->extra2;
+               size_t length;
+               int i;
+
                if (newlen % sizeof(int) != 0)
                        return -EINVAL;
 
@@ -2033,10 +2166,6 @@ int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
                        newlen = table->maxlen;
                length = newlen / sizeof(int);
 
-               vec = (int *) newval;
-               min = (int *) table->extra1;
-               max = (int *) table->extra2;
-
                for (i = 0; i < length; i++) {
                        int value;
                        if (get_user(value, vec + i))
@@ -2063,7 +2192,7 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
                        if (olen!=sizeof(int))
                                return -EINVAL; 
                }
-               if (put_user(*(int *)(table->data) / HZ, (int *)oldval) || 
+               if (put_user(*(int *)(table->data)/HZ, (int __user *)oldval) ||
                    (oldlenp && put_user(sizeof(int),oldlenp)))
                        return -EFAULT;
        }
@@ -2071,13 +2200,40 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
                int new;
                if (newlen != sizeof(int))
                        return -EINVAL; 
-               if (get_user(new, (int *)newval))
+               if (get_user(new, (int __user *)newval))
                        return -EFAULT;
                *(int *)(table->data) = new*HZ; 
        }
        return 1;
 }
 
+/* Strategy function to convert jiffies to seconds */ 
+int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
+               void __user *oldval, size_t __user *oldlenp,
+               void __user *newval, size_t newlen, void **context)
+{
+       if (oldval) {
+               size_t olen;
+               if (oldlenp) { 
+                       if (get_user(olen, oldlenp))
+                               return -EFAULT;
+                       if (olen!=sizeof(int))
+                               return -EINVAL; 
+               }
+               if (put_user(jiffies_to_msecs(*(int *)(table->data)), (int __user *)oldval) ||
+                   (oldlenp && put_user(sizeof(int),oldlenp)))
+                       return -EFAULT;
+       }
+       if (newval && newlen) { 
+               int new;
+               if (newlen != sizeof(int))
+                       return -EINVAL; 
+               if (get_user(new, (int __user *)newval))
+                       return -EFAULT;
+               *(int *)(table->data) = msecs_to_jiffies(new);
+       }
+       return 1;
+}
 
 #else /* CONFIG_SYSCTL */
 
@@ -2108,51 +2264,65 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
        return -ENOSYS;
 }
 
+int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
+               void __user *oldval, size_t __user *oldlenp,
+               void __user *newval, size_t newlen, void **context)
+{
+       return -ENOSYS;
+}
+
 int proc_dostring(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp)
+                 void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_dointvec(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp)
+                 void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
-                       void __user *buffer, size_t *lenp)
+                       void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
-                   void __user *buffer, size_t *lenp)
+                   void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
-                         void *buffer, size_t *lenp)
+                         void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
-                         void *buffer, size_t *lenp)
+                         void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       return -ENOSYS;
+}
+
+int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
+                            void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
-                   void __user *buffer, size_t *lenp)
+                   void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        return -ENOSYS;
 }
 
 int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
                                      struct file *filp,
-                                     void __user *buffer, size_t *lenp)
+                                     void __user *buffer,
+                                     size_t *lenp, loff_t *ppos)
 {
     return -ENOSYS;
 }
@@ -2160,7 +2330,7 @@ int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
 struct ctl_table_header * register_sysctl_table(ctl_table * table, 
                                                int insert_at_head)
 {
-       return 0;
+       return NULL;
 }
 
 void unregister_sysctl_table(struct ctl_table_header * table)
@@ -2177,11 +2347,13 @@ EXPORT_SYMBOL(proc_dointvec);
 EXPORT_SYMBOL(proc_dointvec_jiffies);
 EXPORT_SYMBOL(proc_dointvec_minmax);
 EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
+EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
 EXPORT_SYMBOL(proc_dostring);
 EXPORT_SYMBOL(proc_doulongvec_minmax);
 EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
 EXPORT_SYMBOL(register_sysctl_table);
 EXPORT_SYMBOL(sysctl_intvec);
 EXPORT_SYMBOL(sysctl_jiffies);
+EXPORT_SYMBOL(sysctl_ms_jiffies);
 EXPORT_SYMBOL(sysctl_string);
 EXPORT_SYMBOL(unregister_sysctl_table);