aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/bitmap.c89
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 */
532static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits) 532static 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 */
622void bitmap_remap(unsigned long *dst, const unsigned long *src, 618void 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}
644EXPORT_SYMBOL(bitmap_remap); 639EXPORT_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 */
672int bitmap_bitremap(int oldbit, const unsigned long *old, 667int 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}
678EXPORT_SYMBOL(bitmap_bitremap); 677EXPORT_SYMBOL(bitmap_bitremap);
679 678