On Monday 08 February 2010 05:21:50 you wrote: > Octavian Purdila wrote: > > On Friday 05 February 2010 06:45:38 you wrote: > >> Again, using bitmap algorithm is not a problem and it's better, the > >> problem is sysctl interface, how would you plan to interact with users > >> via sysctl/proc if you use bitmap to handle this? I would like to hear > >> more details about this. > > > > We could use something like positive values for setting and negative for > > reset (e.g. 3 would set the port in the bitmap and -3 would reset it). > > Hmm, then how do you output the info of those ports? Arrays of bitmaps? > See the patch bellow (work in progress). BTW, while working on it I added some helpers, which we can use to rewrite the proc_doint/long stuff. I think it will help with readability and eliminates some code duplication as well. What do you guys think about that? --- linux_2.6.32/main/src/kernel/sysctl.c +++ linux_2.6.32/main/src/kernel/sysctl.c @@ -250,6 +250,11 @@ static int max_wakeup_granularity_ns = NSEC_PER_SEC; /* 1 second */ #endif +static unsigned long test_bitmap[65535/sizeof(long)]; +static int proc_dobitmap(struct ctl_table *table, int write, + void __user *buf, size_t *lenp, loff_t *ppos); + + static struct ctl_table kern_table[] = { { .ctl_name = CTL_UNNUMBERED, @@ -1032,6 +1037,15 @@ .proc_handler = &proc_dointvec, }, #endif + { + .ctl_name = CTL_UNNUMBERED, + .procname = "bitmap_test", + .data = &test_bitmap, + .maxlen = 65535, + .mode = 0644, + .proc_handler = &proc_dobitmap, + }, + /* * NOTE: do not add new entries to this table unless you have read * Documentation/sysctl/ctl_unnumbered.txt @@ -2902,6 +2916,194 @@ return 0; } +static int proc_skip_wspace(char __user **buf, size_t *size) +{ + char c; + + while (*size) { + if (get_user(c, *buf)) + return -EFAULT; + if (!isspace(c)) + break; + *size--; *buf++; + } + + return 0; +} + +static inline int _proc_get_ulong(char __user **buf, size_t *size, + unsigned long *val, bool *neg) +{ +#define TMPBUFLEN 21 + int len = *size; + char *p, tmp[TMPBUFLEN]; + + if (len > TMPBUFLEN-1) + len = TMPBUFLEN-1; + + if (copy_from_user(tmp, *buf, len)) + return -EFAULT; + + tmp[len] = 0; + p = tmp; + if (*p == '-' && *size > 1) { + *neg = 1; + p++; + } + if (*p < '0' || *p > '9') + return -EINVAL; + + *val = simple_strtoul(p, &p, 0); + + len = p - tmp; + if ((len < *size) && *p && !isspace(*p)) + return -EINVAL; + + *buf += len; *size -= len; + + return 0; +#undef TMPBUFLEN +} + +static int proc_get_long(char __user **buf, size_t *size, long *val) +{ + int err; + bool neg; + unsigned long uval; + + err = _proc_get_ulong(buf, size, &uval, &neg); + if (err) + return err; + + if (neg) + *val = -uval; + else + *val = uval; + + return 0; +} + +static int proc_get_ulong(char __user **buf, size_t *size, unsigned long *val) +{ + int err; + bool neg; + + err = _proc_get_ulong(buf, size, val, &neg); + if (err) + return err; + if (neg) + return -EINVAL; + + return 0; +} + +static int proc_put_ulong(char __user **buf, size_t *size, unsigned long val, + bool first) +{ +#define TMPBUFLEN 21 + int len; + char tmp[TMPBUFLEN], *p = tmp; + + if (!first) + *p++ = '\t'; + sprintf(p, "%lu", val); + len = strlen(tmp); + if (len > *size) + len = *size; + if (copy_to_user(*buf, tmp, len)) + return -EFAULT; + *size -= len; + *buf += len; + return 0; +#undef TMPBUFLEN +} + +static int proc_put_newline(char __user **buf, size_t *size) +{ + if (*size) { + if (put_user('\n', *buf)) + return -EFAULT; + *size--, *buf++; + } + return 0; +} + +static int proc_dobitmap(struct ctl_table *table, int write, + void __user *buf, size_t *lenp, loff_t *ppos) +{ + bool first = 1; + unsigned long *bitmap = (unsigned long *) table->data; + unsigned long bitmap_len = table->maxlen; + int left = *lenp, err = 0; + char __user *buffer = (char __user *) buf; + + if (!bitmap_len || !left || (*ppos && !write)) { + *lenp = 0; + return 0; + } + + if (write) { + while (left) { + long val; + + err = proc_skip_wspace(&buffer, &left); + if (err) + break; + if (!left) { + err = -EINVAL; + break; + } + err = proc_get_long(&buffer, &left, &val); + if (err) + break; + if (abs(val) > bitmap_len) { + err = -EINVAL; + break; + } + + if (val < 0) + clear_bit(-val, bitmap); + else + set_bit(val, bitmap); + + first = 0; + } + if (!err) + err = proc_skip_wspace(&buffer, &left); + } else { + unsigned long bit = 0; + + while (left) { + bit = find_next_bit(bitmap, bitmap_len, bit); + printk("%s:%d %lu\n", __func__, __LINE__, bit); + if (bit >= bitmap_len) + break; + err = proc_put_ulong(&buffer, &left, bit, first); + printk("%s:%d %d\n", __func__, __LINE__, err); + if (err) + break; + first = 0; bit++; + } + if (!err) + err = proc_put_newline(&buffer, &left); + } + + if (first) { + if (write && !err) + err = -EINVAL; + if (err) + return err; + } + + if (err == -EFAULT) + return err; + + printk("%s:%d %d %d\n", __func__, __LINE__, *lenp, left); + *lenp -= left; + *ppos += *lenp; + return 0; +} + #else /* CONFIG_PROC_FS */ int proc_dostring(struct ctl_table *table, int write, -- To unsubscribe from this list: send the line "unsubscribe linux-sctp" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html