if (maxnode > PAGE_SIZE*BITS_PER_BYTE)
return -EINVAL;
- - nlongs = BITS_TO_LONGS(maxnode);
- - if ((maxnode % BITS_PER_LONG) == 0)
- - endmask = ~0UL;
- - else
- - endmask = (1UL << (maxnode % BITS_PER_LONG)) - 1;
- -
/*
* When the user specified more nodes than supported just check
- - * if the non supported part is all zero.
- - *
- - * If maxnode have more longs than MAX_NUMNODES, check
- - * the bits in that area first. And then go through to
- - * check the rest bits which equal or bigger than MAX_NUMNODES.
- - * Otherwise, just check bits [MAX_NUMNODES, maxnode).
+ + * if the non supported part is all zero, one word at a time,
+ + * starting at the end.
*/
- - if (nlongs > BITS_TO_LONGS(MAX_NUMNODES)) {
- - for (k = BITS_TO_LONGS(MAX_NUMNODES); k < nlongs; k++) {
- - if (get_user(t, nmask + k))
- - return -EFAULT;
- - if (k == nlongs - 1) {
- - if (t & endmask)
- - return -EINVAL;
- - } else if (t)
- - return -EINVAL;
- - }
- - nlongs = BITS_TO_LONGS(MAX_NUMNODES);
- - endmask = ~0UL;
- - }
-
- if (maxnode > MAX_NUMNODES && MAX_NUMNODES % BITS_PER_LONG != 0) {
- unsigned long valid_mask = endmask;
+ + while (maxnode > MAX_NUMNODES) {
+ + unsigned long bits = min_t(unsigned long, maxnode, BITS_PER_LONG);
+ + unsigned long t;
- if (maxnode > MAX_NUMNODES && MAX_NUMNODES % BITS_PER_LONG != 0) {
- unsigned long valid_mask = endmask;
-
- - valid_mask &= ~((1UL << (MAX_NUMNODES % BITS_PER_LONG)) - 1);
- - if (get_user(t, nmask + nlongs - 1))
+ + if (get_bitmap(&t, &nmask[maxnode / BITS_PER_LONG], bits))
return -EFAULT;
- - if (t & valid_mask)
+ +
+ + if (maxnode - bits >= MAX_NUMNODES) {
+ + maxnode -= bits;
+ + } else {
+ + maxnode = MAX_NUMNODES;
+ + t &= ~((1UL << (MAX_NUMNODES % BITS_PER_LONG)) - 1);
+ + }
+ + if (t)
return -EINVAL;
}