aboutsummaryrefslogtreecommitdiffstats
path: root/mm/percpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/percpu.c')
-rw-r--r--mm/percpu.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/mm/percpu.c b/mm/percpu.c
index daebf7a5343c..30e683f42861 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -707,20 +707,31 @@ static void pcpu_block_update_scan(struct pcpu_chunk *chunk, int bit_off,
707/** 707/**
708 * pcpu_chunk_refresh_hint - updates metadata about a chunk 708 * pcpu_chunk_refresh_hint - updates metadata about a chunk
709 * @chunk: chunk of interest 709 * @chunk: chunk of interest
710 * @full_scan: if we should scan from the beginning
710 * 711 *
711 * Iterates over the metadata blocks to find the largest contig area. 712 * Iterates over the metadata blocks to find the largest contig area.
712 * It also counts the populated pages and uses the delta to update the 713 * A full scan can be avoided on the allocation path as this is triggered
713 * global count. 714 * if we broke the contig_hint. In doing so, the scan_hint will be before
715 * the contig_hint or after if the scan_hint == contig_hint. This cannot
716 * be prevented on freeing as we want to find the largest area possibly
717 * spanning blocks.
714 */ 718 */
715static void pcpu_chunk_refresh_hint(struct pcpu_chunk *chunk) 719static void pcpu_chunk_refresh_hint(struct pcpu_chunk *chunk, bool full_scan)
716{ 720{
717 struct pcpu_block_md *chunk_md = &chunk->chunk_md; 721 struct pcpu_block_md *chunk_md = &chunk->chunk_md;
718 int bit_off, bits; 722 int bit_off, bits;
719 723
720 /* clear metadata */ 724 /* promote scan_hint to contig_hint */
721 chunk_md->contig_hint = 0; 725 if (!full_scan && chunk_md->scan_hint) {
726 bit_off = chunk_md->scan_hint_start + chunk_md->scan_hint;
727 chunk_md->contig_hint_start = chunk_md->scan_hint_start;
728 chunk_md->contig_hint = chunk_md->scan_hint;
729 chunk_md->scan_hint = 0;
730 } else {
731 bit_off = chunk_md->first_free;
732 chunk_md->contig_hint = 0;
733 }
722 734
723 bit_off = chunk_md->first_free;
724 bits = 0; 735 bits = 0;
725 pcpu_for_each_md_free_region(chunk, bit_off, bits) { 736 pcpu_for_each_md_free_region(chunk, bit_off, bits) {
726 pcpu_block_update(chunk_md, bit_off, bit_off + bits); 737 pcpu_block_update(chunk_md, bit_off, bit_off + bits);
@@ -880,6 +891,13 @@ static void pcpu_block_update_hint_alloc(struct pcpu_chunk *chunk, int bit_off,
880 if (nr_empty_pages) 891 if (nr_empty_pages)
881 pcpu_update_empty_pages(chunk, -nr_empty_pages); 892 pcpu_update_empty_pages(chunk, -nr_empty_pages);
882 893
894 if (pcpu_region_overlap(chunk_md->scan_hint_start,
895 chunk_md->scan_hint_start +
896 chunk_md->scan_hint,
897 bit_off,
898 bit_off + bits))
899 chunk_md->scan_hint = 0;
900
883 /* 901 /*
884 * The only time a full chunk scan is required is if the chunk 902 * The only time a full chunk scan is required is if the chunk
885 * contig hint is broken. Otherwise, it means a smaller space 903 * contig hint is broken. Otherwise, it means a smaller space
@@ -890,7 +908,7 @@ static void pcpu_block_update_hint_alloc(struct pcpu_chunk *chunk, int bit_off,
890 chunk_md->contig_hint, 908 chunk_md->contig_hint,
891 bit_off, 909 bit_off,
892 bit_off + bits)) 910 bit_off + bits))
893 pcpu_chunk_refresh_hint(chunk); 911 pcpu_chunk_refresh_hint(chunk, false);
894} 912}
895 913
896/** 914/**
@@ -1001,7 +1019,7 @@ static void pcpu_block_update_hint_free(struct pcpu_chunk *chunk, int bit_off,
1001 * the else condition below. 1019 * the else condition below.
1002 */ 1020 */
1003 if (((end - start) >= PCPU_BITMAP_BLOCK_BITS) || s_index != e_index) 1021 if (((end - start) >= PCPU_BITMAP_BLOCK_BITS) || s_index != e_index)
1004 pcpu_chunk_refresh_hint(chunk); 1022 pcpu_chunk_refresh_hint(chunk, true);
1005 else 1023 else
1006 pcpu_block_update(&chunk->chunk_md, 1024 pcpu_block_update(&chunk->chunk_md,
1007 pcpu_block_off_to_off(s_index, start), 1025 pcpu_block_off_to_off(s_index, start),
@@ -1074,7 +1092,7 @@ static int pcpu_find_block_fit(struct pcpu_chunk *chunk, int alloc_bits,
1074 if (bit_off + alloc_bits > chunk_md->contig_hint) 1092 if (bit_off + alloc_bits > chunk_md->contig_hint)
1075 return -1; 1093 return -1;
1076 1094
1077 bit_off = chunk_md->first_free; 1095 bit_off = pcpu_next_hint(chunk_md, alloc_bits);
1078 bits = 0; 1096 bits = 0;
1079 pcpu_for_each_fit_region(chunk, alloc_bits, align, bit_off, bits) { 1097 pcpu_for_each_fit_region(chunk, alloc_bits, align, bit_off, bits) {
1080 if (!pop_only || pcpu_is_populated(chunk, bit_off, bits, 1098 if (!pop_only || pcpu_is_populated(chunk, bit_off, bits,