diff options
| author | Paul Jackson <pj@sgi.com> | 2005-03-09 17:06:21 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-03-09 17:06:21 -0800 |
| commit | 794c8de9b9ae014f9d48583fb996cdcd135a2d6e (patch) | |
| tree | cc62e3413bf84cdb1635a69d8ee67743b1a7f3e7 /lib/bitmap.c | |
| parent | 883ba7443358b1143e78586b7984d799407d06e8 (diff) | |
[PATCH] new bitmap list format (for cpusets)
[This is a copy of the bitmap list format patch that I submitted to lkml
on 9 Aug 2004, after removing the prefix character fluff^Wstuff. I
include it here again just to get it associated with the current cpuset
patch, which will follow in a second email 10 seconds later. -pj]
A bitmap print and parse format that provides lists of ranges of numbers,
to be first used for by cpusets (next patch).
Cpusets provide a way to manage subsets of CPUs and Memory Nodes for
scheduling and memory placement, via a new virtual file system, usually
mounted at /dev/cpuset. Manipulation of cpusets can be done directly via
this file system, from the shell.
However, manipulating 512 bit cpumasks or 256 bit nodemasks (which will get
bigger) via hex mask strings is painful for humans.
The intention is to provide a format for the cpu and memory mask files in
/dev/cpusets that will stand the test of time. This format is supported by
a couple of new lib/bitmap.c routines, for printing and parsing these
strings. Wrappers for cpumask and nodemask are provided.
Signed-off-by: Paul Jackson <pj@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'lib/bitmap.c')
| -rw-r--r-- | lib/bitmap.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c index f7414e7fd046..d1388a5ce89c 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -291,6 +291,7 @@ EXPORT_SYMBOL(__bitmap_weight); #define nbits_to_hold_value(val) fls(val) #define roundup_power2(val,modulus) (((val) + (modulus) - 1) & ~((modulus) - 1)) #define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10)) +#define BASEDEC 10 /* fancier cpuset lists input in decimal */ /** * bitmap_scnprintf - convert bitmap to an ASCII hex string. @@ -409,6 +410,108 @@ int bitmap_parse(const char __user *ubuf, unsigned int ubuflen, } EXPORT_SYMBOL(bitmap_parse); +/* + * bscnl_emit(buf, buflen, rbot, rtop, bp) + * + * Helper routine for bitmap_scnlistprintf(). Write decimal number + * or range to buf, suppressing output past buf+buflen, with optional + * comma-prefix. Return len of what would be written to buf, if it + * all fit. + */ +static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len) +{ + if (len > 0) + len += scnprintf(buf + len, buflen - len, ","); + if (rbot == rtop) + len += scnprintf(buf + len, buflen - len, "%d", rbot); + else + len += scnprintf(buf + len, buflen - len, "%d-%d", rbot, rtop); + return len; +} + +/** + * bitmap_scnlistprintf - convert bitmap to list format ASCII string + * @buf: byte buffer into which string is placed + * @buflen: reserved size of @buf, in bytes + * @maskp: pointer to bitmap to convert + * @nmaskbits: size of bitmap, in bits + * + * Output format is a comma-separated list of decimal numbers and + * ranges. Consecutively set bits are shown as two hyphen-separated + * decimal numbers, the smallest and largest bit numbers set in + * the range. Output format is compatible with the format + * accepted as input by bitmap_parselist(). + * + * The return value is the number of characters which would be + * generated for the given input, excluding the trailing '\0', as + * per ISO C99. + */ +int bitmap_scnlistprintf(char *buf, unsigned int buflen, + const unsigned long *maskp, int nmaskbits) +{ + int len = 0; + /* current bit is 'cur', most recently seen range is [rbot, rtop] */ + int cur, rbot, rtop; + + rbot = cur = find_first_bit(maskp, nmaskbits); + while (cur < nmaskbits) { + rtop = cur; + cur = find_next_bit(maskp, nmaskbits, cur+1); + if (cur >= nmaskbits || cur > rtop + 1) { + len = bscnl_emit(buf, buflen, rbot, rtop, len); + rbot = cur; + } + } + return len; +} +EXPORT_SYMBOL(bitmap_scnlistprintf); + +/** + * bitmap_parselist - convert list format ASCII string to bitmap + * @buf: read nul-terminated user string from this buffer + * @mask: write resulting mask here + * @nmaskbits: number of bits in mask to be written + * + * Input format is a comma-separated list of decimal numbers and + * ranges. Consecutively set bits are shown as two hyphen-separated + * decimal numbers, the smallest and largest bit numbers set in + * the range. + * + * Returns 0 on success, -errno on invalid input strings: + * -EINVAL: second number in range smaller than first + * -EINVAL: invalid character in string + * -ERANGE: bit number specified too large for mask + */ +int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits) +{ + unsigned a, b; + + bitmap_zero(maskp, nmaskbits); + do { + if (!isdigit(*bp)) + return -EINVAL; + b = a = simple_strtoul(bp, (char **)&bp, BASEDEC); + if (*bp == '-') { + bp++; + if (!isdigit(*bp)) + return -EINVAL; + b = simple_strtoul(bp, (char **)&bp, BASEDEC); + } + if (!(a <= b)) + return -EINVAL; + if (b >= nmaskbits) + return -ERANGE; + while (a <= b) { + set_bit(a, maskp); + a++; + } + if (*bp == ',') + bp++; + } while (*bp != '\0' && *bp != '\n'); + return 0; +} +EXPORT_SYMBOL(bitmap_parselist); + /** * bitmap_find_free_region - find a contiguous aligned mem region * @bitmap: an array of unsigned longs corresponding to the bitmap |
