diff options
| -rw-r--r-- | include/linux/sysctl.h | 3 | ||||
| -rw-r--r-- | kernel/sysctl.c | 91 | ||||
| -rw-r--r-- | net/ipv4/route.c | 6 |
3 files changed, 97 insertions, 3 deletions
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 33642be4ce00..6b084680aaa1 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -797,6 +797,8 @@ extern int proc_dointvec_jiffies(ctl_table *, int, struct file *, void __user *, size_t *, loff_t *); extern int proc_dointvec_userhz_jiffies(ctl_table *, int, struct file *, void __user *, size_t *, loff_t *); +extern int proc_dointvec_ms_jiffies(ctl_table *, int, struct file *, + void __user *, size_t *, loff_t *); extern int proc_doulongvec_minmax(ctl_table *, int, struct file *, void __user *, size_t *, loff_t *); extern int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int, @@ -814,6 +816,7 @@ extern int do_sysctl_strategy (ctl_table *table, extern ctl_handler sysctl_string; extern ctl_handler sysctl_intvec; extern ctl_handler sysctl_jiffies; +extern ctl_handler sysctl_ms_jiffies; /* diff --git a/kernel/sysctl.c b/kernel/sysctl.c index ec430d0e5b01..a72dd5677c8f 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1902,6 +1902,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 @@ -1946,6 +1967,28 @@ int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp, 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 + * + * 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, @@ -1990,6 +2033,12 @@ int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp, 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, loff_t *ppos) { @@ -2119,6 +2168,33 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen, 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 */ @@ -2149,6 +2225,13 @@ 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, loff_t *ppos) { @@ -2185,6 +2268,12 @@ int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp, 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, loff_t *ppos) { @@ -2219,11 +2308,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); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 24e7f12f1972..6a3e73b0ecf1 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2545,10 +2545,10 @@ ctl_table ipv4_route_table[] = { .ctl_name = NET_IPV4_ROUTE_GC_MIN_INTERVAL_MS, .procname = "gc_min_interval_ms", .data = &ip_rt_gc_min_interval, - .maxlen = sizeof(unsigned long), + .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_doulongvec_ms_jiffies_minmax, - .strategy = &sysctl_jiffies, + .proc_handler = &proc_dointvec_ms_jiffies, + .strategy = &sysctl_ms_jiffies, }, { .ctl_name = NET_IPV4_ROUTE_GC_TIMEOUT, |
