diff options
| -rw-r--r-- | lib/bitmap.c | 110 |
1 files changed, 76 insertions, 34 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c index 3fab1ce9ac65..f49eabe09271 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c | |||
| @@ -692,26 +692,44 @@ EXPORT_SYMBOL(bitmap_bitremap); | |||
| 692 | */ | 692 | */ |
| 693 | int bitmap_find_free_region(unsigned long *bitmap, int bits, int order) | 693 | int bitmap_find_free_region(unsigned long *bitmap, int bits, int order) |
| 694 | { | 694 | { |
| 695 | unsigned long mask; | 695 | int nbits; /* number of bits in region */ |
| 696 | int nbits = 1 << order; | 696 | int nlongs; /* num longs spanned by region in bitmap */ |
| 697 | int i; | 697 | int nbitsinlong; /* num bits of region in each spanned long */ |
| 698 | 698 | unsigned long mask; /* bitmask of bits [0 .. nbitsinlong-1] */ | |
| 699 | if (nbits > BITS_PER_LONG) | 699 | int i; /* scans bitmap by longs */ |
| 700 | return -EINVAL; | 700 | |
| 701 | nbits = 1 << order; | ||
| 702 | nlongs = (nbits + (BITS_PER_LONG - 1)) / BITS_PER_LONG; | ||
| 703 | nbitsinlong = nbits; | ||
| 704 | if (nbitsinlong > BITS_PER_LONG) | ||
| 705 | nbitsinlong = BITS_PER_LONG; | ||
| 701 | 706 | ||
| 702 | /* make a mask of the order */ | 707 | /* make a mask of the order */ |
| 703 | mask = (1UL << (nbits - 1)); | 708 | mask = (1UL << (nbitsinlong - 1)); |
| 704 | mask += mask - 1; | 709 | mask += mask - 1; |
| 705 | 710 | ||
| 706 | /* run up the bitmap nbits at a time */ | 711 | /* run up the bitmap nbitsinlong at a time */ |
| 707 | for (i = 0; i < bits; i += nbits) { | 712 | for (i = 0; i < bits; i += nbitsinlong) { |
| 708 | int index = i / BITS_PER_LONG; | 713 | int index = i / BITS_PER_LONG; |
| 709 | int offset = i - (index * BITS_PER_LONG); | 714 | int offset = i - (index * BITS_PER_LONG); |
| 710 | if ((bitmap[index] & (mask << offset)) == 0) { | 715 | int j, space = 1; |
| 716 | |||
| 717 | /* find space in the bitmap */ | ||
| 718 | for (j = 0; j < nlongs; j++) | ||
| 719 | if ((bitmap[index + j] & (mask << offset))) { | ||
| 720 | space = 0; | ||
| 721 | break; | ||
| 722 | } | ||
| 723 | |||
| 724 | /* keep looking */ | ||
| 725 | if (unlikely(!space)) | ||
| 726 | continue; | ||
| 727 | |||
| 728 | for (j = 0; j < nlongs; j++) | ||
| 711 | /* set region in bitmap */ | 729 | /* set region in bitmap */ |
| 712 | bitmap[index] |= (mask << offset); | 730 | bitmap[index + j] |= (mask << offset); |
| 713 | return i; | 731 | |
| 714 | } | 732 | return i; |
| 715 | } | 733 | } |
| 716 | return -ENOMEM; | 734 | return -ENOMEM; |
| 717 | } | 735 | } |
| @@ -728,13 +746,28 @@ EXPORT_SYMBOL(bitmap_find_free_region); | |||
| 728 | */ | 746 | */ |
| 729 | void bitmap_release_region(unsigned long *bitmap, int pos, int order) | 747 | void bitmap_release_region(unsigned long *bitmap, int pos, int order) |
| 730 | { | 748 | { |
| 731 | int nbits = 1 << order; | 749 | int nbits; /* number of bits in region */ |
| 732 | unsigned long mask = (1UL << (nbits - 1)); | 750 | int nlongs; /* num longs spanned by region in bitmap */ |
| 733 | int index = pos / BITS_PER_LONG; | 751 | int index; /* index first long of region in bitmap */ |
| 734 | int offset = pos - (index * BITS_PER_LONG); | 752 | int offset; /* bit offset region in bitmap[index] */ |
| 735 | 753 | int nbitsinlong; /* num bits of region in each spanned long */ | |
| 754 | unsigned long mask; /* bitmask of bits [0 .. nbitsinlong-1] */ | ||
| 755 | int i; /* scans bitmap by longs */ | ||
| 756 | |||
| 757 | nbits = 1 << order; | ||
| 758 | nlongs = (nbits + (BITS_PER_LONG - 1)) / BITS_PER_LONG; | ||
| 759 | index = pos / BITS_PER_LONG; | ||
| 760 | offset = pos - (index * BITS_PER_LONG); | ||
| 761 | |||
| 762 | nbitsinlong = nbits; | ||
| 763 | if (nbitsinlong > BITS_PER_LONG) | ||
| 764 | nbitsinlong = BITS_PER_LONG; | ||
| 765 | |||
| 766 | mask = (1UL << (nbitsinlong - 1)); | ||
| 736 | mask += mask - 1; | 767 | mask += mask - 1; |
| 737 | bitmap[index] &= ~(mask << offset); | 768 | |
| 769 | for (i = 0; i < nlongs; i++) | ||
| 770 | bitmap[index + i] &= ~(mask << offset); | ||
| 738 | } | 771 | } |
| 739 | EXPORT_SYMBOL(bitmap_release_region); | 772 | EXPORT_SYMBOL(bitmap_release_region); |
| 740 | 773 | ||
| @@ -750,22 +783,31 @@ EXPORT_SYMBOL(bitmap_release_region); | |||
| 750 | */ | 783 | */ |
| 751 | int bitmap_allocate_region(unsigned long *bitmap, int pos, int order) | 784 | int bitmap_allocate_region(unsigned long *bitmap, int pos, int order) |
| 752 | { | 785 | { |
| 753 | int nbits = 1 << order; | 786 | int nbits; /* number of bits in region */ |
| 754 | unsigned long mask = (1UL << (nbits - 1)); | 787 | int nlongs; /* num longs spanned by region in bitmap */ |
| 755 | int index = pos / BITS_PER_LONG; | 788 | int index; /* index first long of region in bitmap */ |
| 756 | int offset = pos - (index * BITS_PER_LONG); | 789 | int offset; /* bit offset region in bitmap[index] */ |
| 757 | 790 | int nbitsinlong; /* num bits of region in each spanned long */ | |
| 758 | /* | 791 | unsigned long mask; /* bitmask of bits [0 .. nbitsinlong-1] */ |
| 759 | * We don't do regions of nbits > BITS_PER_LONG. The | 792 | int i; /* scans bitmap by longs */ |
| 760 | * algorithm would be a simple look for multiple zeros in the | 793 | |
| 761 | * array, but there's no driver today that needs this. If you | 794 | nbits = 1 << order; |
| 762 | * trip this BUG(), you get to code it... | 795 | nlongs = (nbits + (BITS_PER_LONG - 1)) / BITS_PER_LONG; |
| 763 | */ | 796 | index = pos / BITS_PER_LONG; |
| 764 | BUG_ON(nbits > BITS_PER_LONG); | 797 | offset = pos - (index * BITS_PER_LONG); |
| 798 | |||
| 799 | nbitsinlong = nbits; | ||
| 800 | if (nbitsinlong > BITS_PER_LONG) | ||
| 801 | nbitsinlong = BITS_PER_LONG; | ||
| 802 | |||
| 803 | mask = (1UL << (nbitsinlong - 1)); | ||
| 765 | mask += mask - 1; | 804 | mask += mask - 1; |
| 766 | if (bitmap[index] & (mask << offset)) | 805 | |
| 767 | return -EBUSY; | 806 | for (i = 0; i < nlongs; i++) |
| 768 | bitmap[index] |= (mask << offset); | 807 | if (bitmap[index + i] & (mask << offset)) |
| 808 | return -EBUSY; | ||
| 809 | for (i = 0; i < nlongs; i++) | ||
| 810 | bitmap[index + i] |= (mask << offset); | ||
| 769 | return 0; | 811 | return 0; |
| 770 | } | 812 | } |
| 771 | EXPORT_SYMBOL(bitmap_allocate_region); | 813 | EXPORT_SYMBOL(bitmap_allocate_region); |
