|
@@ -205,8 +205,7 @@ static void chain_free(struct chain_allocator *ca, int clear_page_nosave)
|
|
|
* objects. The main list's elements are of type struct zone_bitmap
|
|
|
* and each of them corresonds to one zone. For each zone bitmap
|
|
|
* object there is a list of objects of type struct bm_block that
|
|
|
- * represent each blocks of bit chunks in which information is
|
|
|
- * stored.
|
|
|
+ * represent each blocks of bitmap in which information is stored.
|
|
|
*
|
|
|
* struct memory_bitmap contains a pointer to the main list of zone
|
|
|
* bitmap objects, a struct bm_position used for browsing the bitmap,
|
|
@@ -224,26 +223,27 @@ static void chain_free(struct chain_allocator *ca, int clear_page_nosave)
|
|
|
* pfns that correspond to the start and end of the represented zone.
|
|
|
*
|
|
|
* struct bm_block contains a pointer to the memory page in which
|
|
|
- * information is stored (in the form of a block of bit chunks
|
|
|
- * of type unsigned long each). It also contains the pfns that
|
|
|
- * correspond to the start and end of the represented memory area and
|
|
|
- * the number of bit chunks in the block.
|
|
|
+ * information is stored (in the form of a block of bitmap)
|
|
|
+ * It also contains the pfns that correspond to the start and end of
|
|
|
+ * the represented memory area.
|
|
|
*/
|
|
|
|
|
|
#define BM_END_OF_MAP (~0UL)
|
|
|
|
|
|
-#define BM_CHUNKS_PER_BLOCK (PAGE_SIZE / sizeof(long))
|
|
|
-#define BM_BITS_PER_CHUNK (sizeof(long) << 3)
|
|
|
#define BM_BITS_PER_BLOCK (PAGE_SIZE << 3)
|
|
|
|
|
|
struct bm_block {
|
|
|
struct bm_block *next; /* next element of the list */
|
|
|
unsigned long start_pfn; /* pfn represented by the first bit */
|
|
|
unsigned long end_pfn; /* pfn represented by the last bit plus 1 */
|
|
|
- unsigned int size; /* number of bit chunks */
|
|
|
- unsigned long *data; /* chunks of bits representing pages */
|
|
|
+ unsigned long *data; /* bitmap representing pages */
|
|
|
};
|
|
|
|
|
|
+static inline unsigned long bm_block_bits(struct bm_block *bb)
|
|
|
+{
|
|
|
+ return bb->end_pfn - bb->start_pfn;
|
|
|
+}
|
|
|
+
|
|
|
struct zone_bitmap {
|
|
|
struct zone_bitmap *next; /* next element of the list */
|
|
|
unsigned long start_pfn; /* minimal pfn in this zone */
|
|
@@ -257,7 +257,6 @@ struct zone_bitmap {
|
|
|
struct bm_position {
|
|
|
struct zone_bitmap *zone_bm;
|
|
|
struct bm_block *block;
|
|
|
- int chunk;
|
|
|
int bit;
|
|
|
};
|
|
|
|
|
@@ -272,12 +271,6 @@ struct memory_bitmap {
|
|
|
|
|
|
/* Functions that operate on memory bitmaps */
|
|
|
|
|
|
-static inline void memory_bm_reset_chunk(struct memory_bitmap *bm)
|
|
|
-{
|
|
|
- bm->cur.chunk = 0;
|
|
|
- bm->cur.bit = -1;
|
|
|
-}
|
|
|
-
|
|
|
static void memory_bm_position_reset(struct memory_bitmap *bm)
|
|
|
{
|
|
|
struct zone_bitmap *zone_bm;
|
|
@@ -285,7 +278,7 @@ static void memory_bm_position_reset(struct memory_bitmap *bm)
|
|
|
zone_bm = bm->zone_bm_list;
|
|
|
bm->cur.zone_bm = zone_bm;
|
|
|
bm->cur.block = zone_bm->bm_blocks;
|
|
|
- memory_bm_reset_chunk(bm);
|
|
|
+ bm->cur.bit = 0;
|
|
|
}
|
|
|
|
|
|
static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free);
|
|
@@ -394,12 +387,10 @@ memory_bm_create(struct memory_bitmap *bm, gfp_t gfp_mask, int safe_needed)
|
|
|
bb->start_pfn = pfn;
|
|
|
if (nr >= BM_BITS_PER_BLOCK) {
|
|
|
pfn += BM_BITS_PER_BLOCK;
|
|
|
- bb->size = BM_CHUNKS_PER_BLOCK;
|
|
|
nr -= BM_BITS_PER_BLOCK;
|
|
|
} else {
|
|
|
/* This is executed only once in the loop */
|
|
|
pfn += nr;
|
|
|
- bb->size = DIV_ROUND_UP(nr, BM_BITS_PER_CHUNK);
|
|
|
}
|
|
|
bb->end_pfn = pfn;
|
|
|
bb = bb->next;
|
|
@@ -478,8 +469,8 @@ static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
|
|
|
}
|
|
|
zone_bm->cur_block = bb;
|
|
|
pfn -= bb->start_pfn;
|
|
|
- *bit_nr = pfn % BM_BITS_PER_CHUNK;
|
|
|
- *addr = bb->data + pfn / BM_BITS_PER_CHUNK;
|
|
|
+ *bit_nr = pfn;
|
|
|
+ *addr = bb->data;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -528,36 +519,6 @@ static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn)
|
|
|
return test_bit(bit, addr);
|
|
|
}
|
|
|
|
|
|
-/* Two auxiliary functions for memory_bm_next_pfn */
|
|
|
-
|
|
|
-/* Find the first set bit in the given chunk, if there is one */
|
|
|
-
|
|
|
-static inline int next_bit_in_chunk(int bit, unsigned long *chunk_p)
|
|
|
-{
|
|
|
- bit++;
|
|
|
- while (bit < BM_BITS_PER_CHUNK) {
|
|
|
- if (test_bit(bit, chunk_p))
|
|
|
- return bit;
|
|
|
-
|
|
|
- bit++;
|
|
|
- }
|
|
|
- return -1;
|
|
|
-}
|
|
|
-
|
|
|
-/* Find a chunk containing some bits set in given block of bits */
|
|
|
-
|
|
|
-static inline int next_chunk_in_block(int n, struct bm_block *bb)
|
|
|
-{
|
|
|
- n++;
|
|
|
- while (n < bb->size) {
|
|
|
- if (bb->data[n])
|
|
|
- return n;
|
|
|
-
|
|
|
- n++;
|
|
|
- }
|
|
|
- return -1;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* memory_bm_next_pfn - find the pfn that corresponds to the next set bit
|
|
|
* in the bitmap @bm. If the pfn cannot be found, BM_END_OF_MAP is
|
|
@@ -571,40 +532,33 @@ static unsigned long memory_bm_next_pfn(struct memory_bitmap *bm)
|
|
|
{
|
|
|
struct zone_bitmap *zone_bm;
|
|
|
struct bm_block *bb;
|
|
|
- int chunk;
|
|
|
int bit;
|
|
|
|
|
|
do {
|
|
|
bb = bm->cur.block;
|
|
|
do {
|
|
|
- chunk = bm->cur.chunk;
|
|
|
bit = bm->cur.bit;
|
|
|
- do {
|
|
|
- bit = next_bit_in_chunk(bit, bb->data + chunk);
|
|
|
- if (bit >= 0)
|
|
|
- goto Return_pfn;
|
|
|
-
|
|
|
- chunk = next_chunk_in_block(chunk, bb);
|
|
|
- bit = -1;
|
|
|
- } while (chunk >= 0);
|
|
|
+ bit = find_next_bit(bb->data, bm_block_bits(bb), bit);
|
|
|
+ if (bit < bm_block_bits(bb))
|
|
|
+ goto Return_pfn;
|
|
|
+
|
|
|
bb = bb->next;
|
|
|
bm->cur.block = bb;
|
|
|
- memory_bm_reset_chunk(bm);
|
|
|
+ bm->cur.bit = 0;
|
|
|
} while (bb);
|
|
|
zone_bm = bm->cur.zone_bm->next;
|
|
|
if (zone_bm) {
|
|
|
bm->cur.zone_bm = zone_bm;
|
|
|
bm->cur.block = zone_bm->bm_blocks;
|
|
|
- memory_bm_reset_chunk(bm);
|
|
|
+ bm->cur.bit = 0;
|
|
|
}
|
|
|
} while (zone_bm);
|
|
|
memory_bm_position_reset(bm);
|
|
|
return BM_END_OF_MAP;
|
|
|
|
|
|
Return_pfn:
|
|
|
- bm->cur.chunk = chunk;
|
|
|
- bm->cur.bit = bit;
|
|
|
- return bb->start_pfn + chunk * BM_BITS_PER_CHUNK + bit;
|
|
|
+ bm->cur.bit = bit + 1;
|
|
|
+ return bb->start_pfn + bit;
|
|
|
}
|
|
|
|
|
|
/**
|