pm: hibernation: simplify memory bitmap
This patch simplifies the memory bitmap manipulations. - remove the member size in struct bm_block It is not necessary for struct bm_block to have the number of bit chunks that can be calculated by using end_pfn and start_pfn. - use find_next_bit() for memory_bm_next_pfn No need to invent the bitmap library only for the memory bitmap. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
8111d1b552
commit
0d83304c7e
1 changed files with 20 additions and 66 deletions
|
@ -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
|
* objects. The main list's elements are of type struct zone_bitmap
|
||||||
* and each of them corresonds to one zone. For each 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
|
* object there is a list of objects of type struct bm_block that
|
||||||
* represent each blocks of bit chunks in which information is
|
* represent each blocks of bitmap in which information is stored.
|
||||||
* stored.
|
|
||||||
*
|
*
|
||||||
* struct memory_bitmap contains a pointer to the main list of zone
|
* struct memory_bitmap contains a pointer to the main list of zone
|
||||||
* bitmap objects, a struct bm_position used for browsing the bitmap,
|
* 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.
|
* pfns that correspond to the start and end of the represented zone.
|
||||||
*
|
*
|
||||||
* struct bm_block contains a pointer to the memory page in which
|
* struct bm_block contains a pointer to the memory page in which
|
||||||
* information is stored (in the form of a block of bit chunks
|
* information is stored (in the form of a block of bitmap)
|
||||||
* of type unsigned long each). It also contains the pfns that
|
* It also contains the pfns that correspond to the start and end of
|
||||||
* correspond to the start and end of the represented memory area and
|
* the represented memory area.
|
||||||
* the number of bit chunks in the block.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define BM_END_OF_MAP (~0UL)
|
#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)
|
#define BM_BITS_PER_BLOCK (PAGE_SIZE << 3)
|
||||||
|
|
||||||
struct bm_block {
|
struct bm_block {
|
||||||
struct bm_block *next; /* next element of the list */
|
struct bm_block *next; /* next element of the list */
|
||||||
unsigned long start_pfn; /* pfn represented by the first bit */
|
unsigned long start_pfn; /* pfn represented by the first bit */
|
||||||
unsigned long end_pfn; /* pfn represented by the last bit plus 1 */
|
unsigned long end_pfn; /* pfn represented by the last bit plus 1 */
|
||||||
unsigned int size; /* number of bit chunks */
|
unsigned long *data; /* bitmap representing pages */
|
||||||
unsigned long *data; /* chunks of bits 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 {
|
||||||
struct zone_bitmap *next; /* next element of the list */
|
struct zone_bitmap *next; /* next element of the list */
|
||||||
unsigned long start_pfn; /* minimal pfn in this zone */
|
unsigned long start_pfn; /* minimal pfn in this zone */
|
||||||
|
@ -257,7 +257,6 @@ struct zone_bitmap {
|
||||||
struct bm_position {
|
struct bm_position {
|
||||||
struct zone_bitmap *zone_bm;
|
struct zone_bitmap *zone_bm;
|
||||||
struct bm_block *block;
|
struct bm_block *block;
|
||||||
int chunk;
|
|
||||||
int bit;
|
int bit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -272,12 +271,6 @@ struct memory_bitmap {
|
||||||
|
|
||||||
/* Functions that operate on memory bitmaps */
|
/* 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)
|
static void memory_bm_position_reset(struct memory_bitmap *bm)
|
||||||
{
|
{
|
||||||
struct zone_bitmap *zone_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;
|
zone_bm = bm->zone_bm_list;
|
||||||
bm->cur.zone_bm = zone_bm;
|
bm->cur.zone_bm = zone_bm;
|
||||||
bm->cur.block = zone_bm->bm_blocks;
|
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);
|
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;
|
bb->start_pfn = pfn;
|
||||||
if (nr >= BM_BITS_PER_BLOCK) {
|
if (nr >= BM_BITS_PER_BLOCK) {
|
||||||
pfn += BM_BITS_PER_BLOCK;
|
pfn += BM_BITS_PER_BLOCK;
|
||||||
bb->size = BM_CHUNKS_PER_BLOCK;
|
|
||||||
nr -= BM_BITS_PER_BLOCK;
|
nr -= BM_BITS_PER_BLOCK;
|
||||||
} else {
|
} else {
|
||||||
/* This is executed only once in the loop */
|
/* This is executed only once in the loop */
|
||||||
pfn += nr;
|
pfn += nr;
|
||||||
bb->size = DIV_ROUND_UP(nr, BM_BITS_PER_CHUNK);
|
|
||||||
}
|
}
|
||||||
bb->end_pfn = pfn;
|
bb->end_pfn = pfn;
|
||||||
bb = bb->next;
|
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;
|
zone_bm->cur_block = bb;
|
||||||
pfn -= bb->start_pfn;
|
pfn -= bb->start_pfn;
|
||||||
*bit_nr = pfn % BM_BITS_PER_CHUNK;
|
*bit_nr = pfn;
|
||||||
*addr = bb->data + pfn / BM_BITS_PER_CHUNK;
|
*addr = bb->data;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,36 +519,6 @@ static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn)
|
||||||
return test_bit(bit, addr);
|
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
|
* 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
|
* 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 zone_bitmap *zone_bm;
|
||||||
struct bm_block *bb;
|
struct bm_block *bb;
|
||||||
int chunk;
|
|
||||||
int bit;
|
int bit;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
bb = bm->cur.block;
|
bb = bm->cur.block;
|
||||||
do {
|
do {
|
||||||
chunk = bm->cur.chunk;
|
|
||||||
bit = bm->cur.bit;
|
bit = bm->cur.bit;
|
||||||
do {
|
bit = find_next_bit(bb->data, bm_block_bits(bb), bit);
|
||||||
bit = next_bit_in_chunk(bit, bb->data + chunk);
|
if (bit < bm_block_bits(bb))
|
||||||
if (bit >= 0)
|
goto Return_pfn;
|
||||||
goto Return_pfn;
|
|
||||||
|
|
||||||
chunk = next_chunk_in_block(chunk, bb);
|
|
||||||
bit = -1;
|
|
||||||
} while (chunk >= 0);
|
|
||||||
bb = bb->next;
|
bb = bb->next;
|
||||||
bm->cur.block = bb;
|
bm->cur.block = bb;
|
||||||
memory_bm_reset_chunk(bm);
|
bm->cur.bit = 0;
|
||||||
} while (bb);
|
} while (bb);
|
||||||
zone_bm = bm->cur.zone_bm->next;
|
zone_bm = bm->cur.zone_bm->next;
|
||||||
if (zone_bm) {
|
if (zone_bm) {
|
||||||
bm->cur.zone_bm = zone_bm;
|
bm->cur.zone_bm = zone_bm;
|
||||||
bm->cur.block = zone_bm->bm_blocks;
|
bm->cur.block = zone_bm->bm_blocks;
|
||||||
memory_bm_reset_chunk(bm);
|
bm->cur.bit = 0;
|
||||||
}
|
}
|
||||||
} while (zone_bm);
|
} while (zone_bm);
|
||||||
memory_bm_position_reset(bm);
|
memory_bm_position_reset(bm);
|
||||||
return BM_END_OF_MAP;
|
return BM_END_OF_MAP;
|
||||||
|
|
||||||
Return_pfn:
|
Return_pfn:
|
||||||
bm->cur.chunk = chunk;
|
bm->cur.bit = bit + 1;
|
||||||
bm->cur.bit = bit;
|
return bb->start_pfn + bit;
|
||||||
return bb->start_pfn + chunk * BM_BITS_PER_CHUNK + bit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue