summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mm/percpu-internal.h3
-rw-r--r--mm/percpu-stats.c5
-rw-r--r--mm/percpu.c9
3 files changed, 15 insertions, 2 deletions
diff --git a/mm/percpu-internal.h b/mm/percpu-internal.h
index c876b5b5bc18..f02f31cea0e6 100644
--- a/mm/percpu-internal.h
+++ b/mm/percpu-internal.h
@@ -26,6 +26,9 @@ struct pcpu_chunk {
int start_offset; /* the overlap with the previous
region to have a page aligned
base_addr */
+ int end_offset; /* additional area required to
+ have the region end page
+ aligned */
int nr_populated; /* # of populated pages */
unsigned long populated[]; /* populated bitmap */
};
diff --git a/mm/percpu-stats.c b/mm/percpu-stats.c
index 32f3550ea099..ffbdb96cdbeb 100644
--- a/mm/percpu-stats.c
+++ b/mm/percpu-stats.c
@@ -51,7 +51,7 @@ static int find_max_map_used(void)
static void chunk_map_stats(struct seq_file *m, struct pcpu_chunk *chunk,
int *buffer)
{
- int i, s_index, last_alloc, alloc_sign, as_len;
+ int i, s_index, e_index, last_alloc, alloc_sign, as_len;
int *alloc_sizes, *p;
/* statistics */
int sum_frag = 0, max_frag = 0;
@@ -59,10 +59,11 @@ static void chunk_map_stats(struct seq_file *m, struct pcpu_chunk *chunk,
alloc_sizes = buffer;
s_index = (chunk->start_offset) ? 1 : 0;
+ e_index = chunk->map_used - ((chunk->end_offset) ? 1 : 0);
/* find last allocation */
last_alloc = -1;
- for (i = chunk->map_used - 1; i >= s_index; i--) {
+ for (i = e_index - 1; i >= s_index; i--) {
if (chunk->map[i] & 1) {
last_alloc = i;
break;
diff --git a/mm/percpu.c b/mm/percpu.c
index 2e785a77ce14..1d2c980fde3f 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -715,12 +715,16 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(void *base_addr,
int init_map_size)
{
struct pcpu_chunk *chunk;
+ int region_size;
+
+ region_size = PFN_ALIGN(start_offset + map_size);
chunk = memblock_virt_alloc(pcpu_chunk_struct_size, 0);
INIT_LIST_HEAD(&chunk->list);
INIT_LIST_HEAD(&chunk->map_extend_list);
chunk->base_addr = base_addr;
chunk->start_offset = start_offset;
+ chunk->end_offset = region_size - chunk->start_offset - map_size;
chunk->map = map;
chunk->map_alloc = init_map_size;
@@ -735,6 +739,11 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(void *base_addr,
chunk->map[2] = (chunk->start_offset + chunk->free_size) | 1;
chunk->map_used = 2;
+ if (chunk->end_offset) {
+ /* hide the end of the bitmap */
+ chunk->map[++chunk->map_used] = region_size | 1;
+ }
+
return chunk;
}