diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/bitmap.c | 89 |
1 files changed, 44 insertions, 45 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c index 23d3b1147fe9..48e708381d44 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c | |||
@@ -519,7 +519,7 @@ EXPORT_SYMBOL(bitmap_parselist); | |||
519 | * | 519 | * |
520 | * Map the bit at position @pos in @buf (of length @bits) to the | 520 | * Map the bit at position @pos in @buf (of length @bits) to the |
521 | * ordinal of which set bit it is. If it is not set or if @pos | 521 | * ordinal of which set bit it is. If it is not set or if @pos |
522 | * is not a valid bit position, map to zero (0). | 522 | * is not a valid bit position, map to -1. |
523 | * | 523 | * |
524 | * If for example, just bits 4 through 7 are set in @buf, then @pos | 524 | * If for example, just bits 4 through 7 are set in @buf, then @pos |
525 | * values 4 through 7 will get mapped to 0 through 3, respectively, | 525 | * values 4 through 7 will get mapped to 0 through 3, respectively, |
@@ -531,18 +531,19 @@ EXPORT_SYMBOL(bitmap_parselist); | |||
531 | */ | 531 | */ |
532 | static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits) | 532 | static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits) |
533 | { | 533 | { |
534 | int ord = 0; | 534 | int i, ord; |
535 | 535 | ||
536 | if (pos >= 0 && pos < bits) { | 536 | if (pos < 0 || pos >= bits || !test_bit(pos, buf)) |
537 | int i; | 537 | return -1; |
538 | 538 | ||
539 | for (i = find_first_bit(buf, bits); | 539 | i = find_first_bit(buf, bits); |
540 | i < pos; | 540 | ord = 0; |
541 | i = find_next_bit(buf, bits, i + 1)) | 541 | while (i < pos) { |
542 | ord++; | 542 | i = find_next_bit(buf, bits, i + 1); |
543 | if (i > pos) | 543 | ord++; |
544 | ord = 0; | ||
545 | } | 544 | } |
545 | BUG_ON(i != pos); | ||
546 | |||
546 | return ord; | 547 | return ord; |
547 | } | 548 | } |
548 | 549 | ||
@@ -553,11 +554,12 @@ static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits) | |||
553 | * @bits: number of valid bit positions in @buf | 554 | * @bits: number of valid bit positions in @buf |
554 | * | 555 | * |
555 | * Map the ordinal offset of bit @ord in @buf to its position in @buf. | 556 | * Map the ordinal offset of bit @ord in @buf to its position in @buf. |
556 | * If @ord is not the ordinal offset of a set bit in @buf, map to zero (0). | 557 | * Value of @ord should be in range 0 <= @ord < weight(buf), else |
558 | * results are undefined. | ||
557 | * | 559 | * |
558 | * If for example, just bits 4 through 7 are set in @buf, then @ord | 560 | * If for example, just bits 4 through 7 are set in @buf, then @ord |
559 | * values 0 through 3 will get mapped to 4 through 7, respectively, | 561 | * values 0 through 3 will get mapped to 4 through 7, respectively, |
560 | * and all other @ord valuds will get mapped to 0. When @ord value 3 | 562 | * and all other @ord values return undefined values. When @ord value 3 |
561 | * gets mapped to (returns) @pos value 7 in this example, that means | 563 | * gets mapped to (returns) @pos value 7 in this example, that means |
562 | * that the 3rd set bit (starting with 0th) is at position 7 in @buf. | 564 | * that the 3rd set bit (starting with 0th) is at position 7 in @buf. |
563 | * | 565 | * |
@@ -583,8 +585,8 @@ static int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits) | |||
583 | 585 | ||
584 | /** | 586 | /** |
585 | * bitmap_remap - Apply map defined by a pair of bitmaps to another bitmap | 587 | * bitmap_remap - Apply map defined by a pair of bitmaps to another bitmap |
586 | * @src: subset to be remapped | ||
587 | * @dst: remapped result | 588 | * @dst: remapped result |
589 | * @src: subset to be remapped | ||
588 | * @old: defines domain of map | 590 | * @old: defines domain of map |
589 | * @new: defines range of map | 591 | * @new: defines range of map |
590 | * @bits: number of bits in each of these bitmaps | 592 | * @bits: number of bits in each of these bitmaps |
@@ -596,49 +598,42 @@ static int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits) | |||
596 | * weight of @old, map the position of the n-th set bit in @old to | 598 | * weight of @old, map the position of the n-th set bit in @old to |
597 | * the position of the m-th set bit in @new, where m == n % w. | 599 | * the position of the m-th set bit in @new, where m == n % w. |
598 | * | 600 | * |
599 | * If either of the @old and @new bitmaps are empty, or if@src and @dst | 601 | * If either of the @old and @new bitmaps are empty, or if @src and |
600 | * point to the same location, then this routine does nothing. | 602 | * @dst point to the same location, then this routine copies @src |
603 | * to @dst. | ||
601 | * | 604 | * |
602 | * The positions of unset bits in @old are mapped to the position of | 605 | * The positions of unset bits in @old are mapped to themselves |
603 | * the first set bit in @new. | 606 | * (the identify map). |
604 | * | 607 | * |
605 | * Apply the above specified mapping to @src, placing the result in | 608 | * Apply the above specified mapping to @src, placing the result in |
606 | * @dst, clearing any bits previously set in @dst. | 609 | * @dst, clearing any bits previously set in @dst. |
607 | * | 610 | * |
608 | * The resulting value of @dst will have either the same weight as | ||
609 | * @src, or less weight in the general case that the mapping wasn't | ||
610 | * injective due to the weight of @new being less than that of @old. | ||
611 | * The resulting value of @dst will never have greater weight than | ||
612 | * that of @src, except perhaps in the case that one of the above | ||
613 | * conditions was not met and this routine just returned. | ||
614 | * | ||
615 | * For example, lets say that @old has bits 4 through 7 set, and | 611 | * For example, lets say that @old has bits 4 through 7 set, and |
616 | * @new has bits 12 through 15 set. This defines the mapping of bit | 612 | * @new has bits 12 through 15 set. This defines the mapping of bit |
617 | * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other | 613 | * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other |
618 | * bit positions to 12 (the first set bit in @new. So if say @src | 614 | * bit positions unchanged. So if say @src comes into this routine |
619 | * comes into this routine with bits 1, 5 and 7 set, then @dst should | 615 | * with bits 1, 5 and 7 set, then @dst should leave with bits 1, |
620 | * leave with bits 12, 13 and 15 set. | 616 | * 13 and 15 set. |
621 | */ | 617 | */ |
622 | void bitmap_remap(unsigned long *dst, const unsigned long *src, | 618 | void bitmap_remap(unsigned long *dst, const unsigned long *src, |
623 | const unsigned long *old, const unsigned long *new, | 619 | const unsigned long *old, const unsigned long *new, |
624 | int bits) | 620 | int bits) |
625 | { | 621 | { |
626 | int s; | 622 | int oldbit, w; |
627 | 623 | ||
628 | if (bitmap_weight(old, bits) == 0) | ||
629 | return; | ||
630 | if (bitmap_weight(new, bits) == 0) | ||
631 | return; | ||
632 | if (dst == src) /* following doesn't handle inplace remaps */ | 624 | if (dst == src) /* following doesn't handle inplace remaps */ |
633 | return; | 625 | return; |
634 | |||
635 | bitmap_zero(dst, bits); | 626 | bitmap_zero(dst, bits); |
636 | for (s = find_first_bit(src, bits); | 627 | |
637 | s < bits; | 628 | w = bitmap_weight(new, bits); |
638 | s = find_next_bit(src, bits, s + 1)) { | 629 | for (oldbit = find_first_bit(src, bits); |
639 | int x = bitmap_pos_to_ord(old, s, bits); | 630 | oldbit < bits; |
640 | int y = bitmap_ord_to_pos(new, x, bits); | 631 | oldbit = find_next_bit(src, bits, oldbit + 1)) { |
641 | set_bit(y, dst); | 632 | int n = bitmap_pos_to_ord(old, oldbit, bits); |
633 | if (n < 0 || w == 0) | ||
634 | set_bit(oldbit, dst); /* identity map */ | ||
635 | else | ||
636 | set_bit(bitmap_ord_to_pos(new, n % w, bits), dst); | ||
642 | } | 637 | } |
643 | } | 638 | } |
644 | EXPORT_SYMBOL(bitmap_remap); | 639 | EXPORT_SYMBOL(bitmap_remap); |
@@ -657,8 +652,8 @@ EXPORT_SYMBOL(bitmap_remap); | |||
657 | * weight of @old, map the position of the n-th set bit in @old to | 652 | * weight of @old, map the position of the n-th set bit in @old to |
658 | * the position of the m-th set bit in @new, where m == n % w. | 653 | * the position of the m-th set bit in @new, where m == n % w. |
659 | * | 654 | * |
660 | * The positions of unset bits in @old are mapped to the position of | 655 | * The positions of unset bits in @old are mapped to themselves |
661 | * the first set bit in @new. | 656 | * (the identify map). |
662 | * | 657 | * |
663 | * Apply the above specified mapping to bit position @oldbit, returning | 658 | * Apply the above specified mapping to bit position @oldbit, returning |
664 | * the new bit position. | 659 | * the new bit position. |
@@ -666,14 +661,18 @@ EXPORT_SYMBOL(bitmap_remap); | |||
666 | * For example, lets say that @old has bits 4 through 7 set, and | 661 | * For example, lets say that @old has bits 4 through 7 set, and |
667 | * @new has bits 12 through 15 set. This defines the mapping of bit | 662 | * @new has bits 12 through 15 set. This defines the mapping of bit |
668 | * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other | 663 | * position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other |
669 | * bit positions to 12 (the first set bit in @new. So if say @oldbit | 664 | * bit positions unchanged. So if say @oldbit is 5, then this routine |
670 | * is 5, then this routine returns 13. | 665 | * returns 13. |
671 | */ | 666 | */ |
672 | int bitmap_bitremap(int oldbit, const unsigned long *old, | 667 | int bitmap_bitremap(int oldbit, const unsigned long *old, |
673 | const unsigned long *new, int bits) | 668 | const unsigned long *new, int bits) |
674 | { | 669 | { |
675 | int x = bitmap_pos_to_ord(old, oldbit, bits); | 670 | int w = bitmap_weight(new, bits); |
676 | return bitmap_ord_to_pos(new, x, bits); | 671 | int n = bitmap_pos_to_ord(old, oldbit, bits); |
672 | if (n < 0 || w == 0) | ||
673 | return oldbit; | ||
674 | else | ||
675 | return bitmap_ord_to_pos(new, n % w, bits); | ||
677 | } | 676 | } |
678 | EXPORT_SYMBOL(bitmap_bitremap); | 677 | EXPORT_SYMBOL(bitmap_bitremap); |
679 | 678 | ||