X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=kernel%2Fsysctl.c;h=d34b4e64a957c7d19eb49f0daeb47c5562161cb2;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hp=79e7c090673dbd24ac0fcc80c7a2412cf7903d0b;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 79e7c0906..d34b4e64a 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -39,7 +39,12 @@ #include #include #include +#include +#include +#include + #include +#include #ifdef CONFIG_ROOT_NFS #include @@ -48,22 +53,25 @@ #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, ¶m); } 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);