aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bitmap.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /lib/bitmap.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'lib/bitmap.c')
-rw-r--r--lib/bitmap.c116
1 files changed, 100 insertions, 16 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c
index ffb78c916ccd..3f3b68199d74 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -359,7 +359,6 @@ EXPORT_SYMBOL(bitmap_find_next_zero_area);
359 359
360#define CHUNKSZ 32 360#define CHUNKSZ 32
361#define nbits_to_hold_value(val) fls(val) 361#define nbits_to_hold_value(val) fls(val)
362#define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
363#define BASEDEC 10 /* fancier cpuset lists input in decimal */ 362#define BASEDEC 10 /* fancier cpuset lists input in decimal */
364 363
365/** 364/**
@@ -466,7 +465,7 @@ int __bitmap_parse(const char *buf, unsigned int buflen,
466 if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1)) 465 if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1))
467 return -EOVERFLOW; 466 return -EOVERFLOW;
468 467
469 chunk = (chunk << 4) | unhex(c); 468 chunk = (chunk << 4) | hex_to_bin(c);
470 ndigits++; totaldigits++; 469 ndigits++; totaldigits++;
471 } 470 }
472 if (ndigits == 0) 471 if (ndigits == 0)
@@ -572,8 +571,11 @@ int bitmap_scnlistprintf(char *buf, unsigned int buflen,
572EXPORT_SYMBOL(bitmap_scnlistprintf); 571EXPORT_SYMBOL(bitmap_scnlistprintf);
573 572
574/** 573/**
575 * bitmap_parselist - convert list format ASCII string to bitmap 574 * __bitmap_parselist - convert list format ASCII string to bitmap
576 * @bp: read nul-terminated user string from this buffer 575 * @buf: read nul-terminated user string from this buffer
576 * @buflen: buffer size in bytes. If string is smaller than this
577 * then it must be terminated with a \0.
578 * @is_user: location of buffer, 0 indicates kernel space
577 * @maskp: write resulting mask here 579 * @maskp: write resulting mask here
578 * @nmaskbits: number of bits in mask to be written 580 * @nmaskbits: number of bits in mask to be written
579 * 581 *
@@ -588,20 +590,63 @@ EXPORT_SYMBOL(bitmap_scnlistprintf);
588 * %-EINVAL: invalid character in string 590 * %-EINVAL: invalid character in string
589 * %-ERANGE: bit number specified too large for mask 591 * %-ERANGE: bit number specified too large for mask
590 */ 592 */
591int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits) 593static int __bitmap_parselist(const char *buf, unsigned int buflen,
594 int is_user, unsigned long *maskp,
595 int nmaskbits)
592{ 596{
593 unsigned a, b; 597 unsigned a, b;
598 int c, old_c, totaldigits;
599 const char __user *ubuf = buf;
600 int exp_digit, in_range;
594 601
602 totaldigits = c = 0;
595 bitmap_zero(maskp, nmaskbits); 603 bitmap_zero(maskp, nmaskbits);
596 do { 604 do {
597 if (!isdigit(*bp)) 605 exp_digit = 1;
598 return -EINVAL; 606 in_range = 0;
599 b = a = simple_strtoul(bp, (char **)&bp, BASEDEC); 607 a = b = 0;
600 if (*bp == '-') { 608
601 bp++; 609 /* Get the next cpu# or a range of cpu#'s */
602 if (!isdigit(*bp)) 610 while (buflen) {
611 old_c = c;
612 if (is_user) {
613 if (__get_user(c, ubuf++))
614 return -EFAULT;
615 } else
616 c = *buf++;
617 buflen--;
618 if (isspace(c))
619 continue;
620
621 /*
622 * If the last character was a space and the current
623 * character isn't '\0', we've got embedded whitespace.
624 * This is a no-no, so throw an error.
625 */
626 if (totaldigits && c && isspace(old_c))
627 return -EINVAL;
628
629 /* A '\0' or a ',' signal the end of a cpu# or range */
630 if (c == '\0' || c == ',')
631 break;
632
633 if (c == '-') {
634 if (exp_digit || in_range)
635 return -EINVAL;
636 b = 0;
637 in_range = 1;
638 exp_digit = 1;
639 continue;
640 }
641
642 if (!isdigit(c))
603 return -EINVAL; 643 return -EINVAL;
604 b = simple_strtoul(bp, (char **)&bp, BASEDEC); 644
645 b = b * 10 + (c - '0');
646 if (!in_range)
647 a = b;
648 exp_digit = 0;
649 totaldigits++;
605 } 650 }
606 if (!(a <= b)) 651 if (!(a <= b))
607 return -EINVAL; 652 return -EINVAL;
@@ -611,13 +656,52 @@ int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits)
611 set_bit(a, maskp); 656 set_bit(a, maskp);
612 a++; 657 a++;
613 } 658 }
614 if (*bp == ',') 659 } while (buflen && c == ',');
615 bp++;
616 } while (*bp != '\0' && *bp != '\n');
617 return 0; 660 return 0;
618} 661}
662
663int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits)
664{
665 char *nl = strchr(bp, '\n');
666 int len;
667
668 if (nl)
669 len = nl - bp;
670 else
671 len = strlen(bp);
672
673 return __bitmap_parselist(bp, len, 0, maskp, nmaskbits);
674}
619EXPORT_SYMBOL(bitmap_parselist); 675EXPORT_SYMBOL(bitmap_parselist);
620 676
677
678/**
679 * bitmap_parselist_user()
680 *
681 * @ubuf: pointer to user buffer containing string.
682 * @ulen: buffer size in bytes. If string is smaller than this
683 * then it must be terminated with a \0.
684 * @maskp: pointer to bitmap array that will contain result.
685 * @nmaskbits: size of bitmap, in bits.
686 *
687 * Wrapper for bitmap_parselist(), providing it with user buffer.
688 *
689 * We cannot have this as an inline function in bitmap.h because it needs
690 * linux/uaccess.h to get the access_ok() declaration and this causes
691 * cyclic dependencies.
692 */
693int bitmap_parselist_user(const char __user *ubuf,
694 unsigned int ulen, unsigned long *maskp,
695 int nmaskbits)
696{
697 if (!access_ok(VERIFY_READ, ubuf, ulen))
698 return -EFAULT;
699 return __bitmap_parselist((const char *)ubuf,
700 ulen, 1, maskp, nmaskbits);
701}
702EXPORT_SYMBOL(bitmap_parselist_user);
703
704
621/** 705/**
622 * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap 706 * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap
623 * @buf: pointer to a bitmap 707 * @buf: pointer to a bitmap
@@ -831,7 +915,7 @@ EXPORT_SYMBOL(bitmap_bitremap);
831 * @orig (i.e. bits 3, 5, 7 and 9) were also set. 915 * @orig (i.e. bits 3, 5, 7 and 9) were also set.
832 * 916 *
833 * When bit 11 is set in @orig, it means turn on the bit in 917 * When bit 11 is set in @orig, it means turn on the bit in
834 * @dst corresponding to whatever is the twelth bit that is 918 * @dst corresponding to whatever is the twelfth bit that is
835 * turned on in @relmap. In the above example, there were 919 * turned on in @relmap. In the above example, there were
836 * only ten bits turned on in @relmap (30..39), so that bit 920 * only ten bits turned on in @relmap (30..39), so that bit
837 * 11 was set in @orig had no affect on @dst. 921 * 11 was set in @orig had no affect on @dst.