diff -Nraup a/include/linux/sysctl.h b/include/linux/sysctl.h --- a/include/linux/sysctl.h 2004-10-18 05:11:39.000000000 -0700 +++ b/include/linux/sysctl.h 2004-10-25 00:05:05.694979402 -0700 @@ -794,6 +794,8 @@ extern int proc_dointvec_userhz_jiffies( 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_doulonglongvec_minmax(ctl_table *, int, struct file *, + void __user *, size_t *, loff_t *); extern int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int, struct file *, void __user *, size_t *, loff_t *); diff -Nraup a/kernel/sysctl.c b/kernel/sysctl.c --- a/kernel/sysctl.c 2004-10-18 05:11:39.000000000 -0700 +++ b/kernel/sysctl.c 2004-10-25 00:06:06.688142718 -0700 @@ -1804,6 +1804,117 @@ int proc_doulongvec_minmax(ctl_table *ta return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos, 1l, 1l); } +static int do_proc_doulonglongvec_minmax(ctl_table *table, int write, + struct file *filp, + void __user *buffer, + size_t *lenp, loff_t *ppos, + unsigned long long convmul, + unsigned long long convdiv) +{ +#define TMPBUFLEN 21 + unsigned long 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 || + (*ppos && !write)) { + *lenp = 0; + return 0; + } + + i = (unsigned long long *) table->data; + min = (unsigned long long *) table->extra1; + max = (unsigned long long *) table->extra2; + vleft = table->maxlen / sizeof(unsigned long long); + left = *lenp; + + for (; left && vleft--; i++, min++, max++, first=0) { + if (write) { + while (left) { + char c; + if (get_user(c, s)) + return -EFAULT; + if (!isspace(c)) + break; + left--; + s++; + } + if (!left) + break; + neg = 0; + len = left; + if (len > TMPBUFLEN-1) + len = TMPBUFLEN-1; + if (copy_from_user(buf, s, len)) + return -EFAULT; + buf[len] = 0; + p = buf; + if (*p == '-' && left > 1) { + neg = 1; + left--, p++; + } + if (*p < '0' || *p > '9') + break; + val = simple_strtoull(p, &p, 0) * convmul / convdiv ; + len = p-buf; + if ((len < left) && *p && !isspace(*p)) + break; + if (neg) + val = -val; + s += len; + left -= len; + + if(neg) + continue; + if ((min && val < *min) || (max && val > *max)) + continue; + *i = val; + } else { + p = buf; + if (!first) + *p++ = '\t'; + sprintf(p, "%llu", convdiv * (*i) / convmul); + len = strlen(buf); + if (len > left) + len = left; + if(copy_to_user(s, buf, len)) + return -EFAULT; + left -= len; + s += len; + } + } + + if (!write && !first && left) { + if(put_user('\n', s)) + return -EFAULT; + left--, s++; + } + if (write) { + while (left) { + char c; + if (get_user(c, s++)) + return -EFAULT; + if (!isspace(c)) + break; + left--; + } + } + if (write && first) + return -EINVAL; + *lenp -= left; + *ppos += *lenp; + return 0; +#undef TMPBUFLEN +} + +int proc_doulonglongvec_minmax(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return do_proc_doulonglongvec_minmax(table, write, filp, buffer, lenp, ppos, 1LLU, 1LLU); +} + /** * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values * @table: the sysctl table @@ -2192,6 +2303,7 @@ EXPORT_SYMBOL(proc_dointvec_minmax); EXPORT_SYMBOL(proc_dointvec_userhz_jiffies); EXPORT_SYMBOL(proc_dostring); EXPORT_SYMBOL(proc_doulongvec_minmax); +EXPORT_SYMBOL(proc_doulonglongvec_minmax); EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax); EXPORT_SYMBOL(register_sysctl_table); EXPORT_SYMBOL(sysctl_intvec);