lkml.org 
[lkml]   [2016]   [Jul]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    SubjectRe: [PATCH v3] lib/bitmap.c: enhance bitmap syntax
    From
    Date


    在 16/7/17 16:10, Noam Camus 写道:
    > From: Noam Camus <noamca@mellanox.com>
    >
    > Today there are platforms with many CPUs (up to 4K).
    > Trying to boot only part of the CPUs may result in too long string.
    >
    > For example lets take NPS platform that is part of arch/arc.
    > This platform have SMP system with 256 cores each with
    > 16 HW threads (SMT machine) where HW thread appears as CPU to the kernel.
    > In this example there is total of 4K CPUs.
    > When one tries to boot only part of the HW threads from each core the
    > string representing the map may be long...
    > For example if for sake of performance we decided to boot only first half
    > of HW threads of each core the map will look like:
    > 0-7,16-23,32-39,...,4080-4087
    >
    > This patch introduce new syntax to accommodate with such use case.
    > I added an optional postfix to a range of CPUs which will choose
    > according to given modulo the desired range of reminders i.e.:
    > <cpus range>%modulo=<range of reminders>
    >
    > For example, above map can be described in new syntax like this:
    > 0-4095%16=0-7
    >

    I really think it is better to implement one function to generic a string which contanis the cpus you want to boot on, then pass this string to __bitmap_parselist.

    > Note that this patch is backward compatible with current syntax.
    >
    > Signed-off-by: Noam Camus <noamca@mellanox.com>
    > ---
    > Any sugestions for simpler syntax which keeps its generality are welcomed.
    >
    > Change Log:
    > V2: Fix typo in example at function header for __bitmap_parselist()
    > V3: Fix typo in commit log and also typo at example
    > ---
    > lib/bitmap.c | 44 ++++++++++++++++++++++++++++++++++++++++----
    > 1 files changed, 40 insertions(+), 4 deletions(-)
    >
    > diff --git a/lib/bitmap.c b/lib/bitmap.c
    > index c66da50..bccfd87 100644
    > --- a/lib/bitmap.c
    > +++ b/lib/bitmap.c
    > @@ -496,6 +496,9 @@ EXPORT_SYMBOL(bitmap_print_to_pagebuf);
    > * ranges. Consecutively set bits are shown as two hyphen-separated
    > * decimal numbers, the smallest and largest bit numbers set in
    > * the range.
    > + * Optionally each range can be postfixed to denote that only parts of it
    > + * should be set. The parts are the range of reminders modulo some value.
    > + * i.e. range%mod=rem_range e.g. 0-1023%256=0-1 ==> 0,1,256,257,512,513,768,769
    > *
    > * Returns 0 on success, -errno on invalid input strings.
    > * Error values:
    > @@ -507,12 +510,14 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen,
    > int is_user, unsigned long *maskp,
    > int nmaskbits)
    > {
    > - unsigned a, b;
    > + unsigned int a, b, old_a, old_b, mod_val, mod_a, mod_b;
    > int c, old_c, totaldigits, ndigits;
    > const char __user __force *ubuf = (const char __user __force *)buf;
    > int at_start, in_range;
    >
    > totaldigits = c = 0;
    > + old_a = old_b = 0;
    > + mod_val = mod_a = mod_b = 0;
    > bitmap_zero(maskp, nmaskbits);
    > do {
    > at_start = 1;
    > @@ -547,6 +552,23 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen,
    > if ((totaldigits != ndigits) && isspace(old_c))
    > return -EINVAL;
    >
    > + if (c == '=') {
    > + mod_val = a;
    > + at_start = 1;
    > + in_range = 0;
    > + a = b = 0;
    > + continue;
    > + }
    > +
    > + if (c == '%') {
    > + old_a = a;
    > + old_b = b;
    > + at_start = 1;
    > + in_range = 0;
    > + a = b = 0;
    > + continue;
    > + }
    > +
    > if (c == '-') {
    > if (at_start || in_range)
    > return -EINVAL;
    > @@ -567,17 +589,31 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen,
    > }
    > if (ndigits == totaldigits)
    > continue;
    > + if (mod_val) {
    > + mod_a = a;
    > + mod_b = b;
    > + a = old_a;
    > + b = old_b;
    > + old_a = old_b = 0;
    > + }
    > /* if no digit is after '-', it's wrong*/
    > if (at_start && in_range)
    > return -EINVAL;
    > - if (!(a <= b))
    > + if (!(a <= b) || !(mod_a <= mod_b))
    > return -EINVAL;
    > - if (b >= nmaskbits)
    > + if (b >= nmaskbits || (mod_val && (mod_b >= mod_val)))
    > return -ERANGE;
    > while (a <= b) {
    > - set_bit(a, maskp);
    > + if (mod_val) {
    > + unsigned int rem = a % mod_val;
    > +
    > + if (rem >= mod_a && rem <= mod_b)
    > + set_bit(a, maskp);
    > + } else
    > + set_bit(a, maskp);
    > a++;
    > }
    > + mod_val = mod_a = mod_b = 0;
    > } while (buflen && c == ',');
    > return 0;
    > }
    >

    \
     
     \ /
      Last update: 2016-07-17 16:41    [W:3.596 / U:0.428 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site