[PATCH 4/5] mm, highmem: makes flush_all_zero_pkmaps() return index of last flushed entry
From: Joonsoo Kim <hidden>
Date: 2012-10-28 19:15:21
Also in:
lkml
Subsystem:
memory management, memory management - core, the rest · Maintainers:
Andrew Morton, David Hildenbrand, Linus Torvalds
In current code, after flush_all_zero_pkmaps() is invoked, then re-iterate all pkmaps. It can be optimized if flush_all_zero_pkmaps() return index of flushed entry. With this index, we can immediately map highmem page to virtual address represented by index. So change return type of flush_all_zero_pkmaps() and return index of last flushed entry. Signed-off-by: Joonsoo Kim <redacted>
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index ef788b5..0683869 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h@@ -32,6 +32,7 @@ static inline void invalidate_kernel_vmap_range(void *vaddr, int size) #ifdef CONFIG_HIGHMEM #include <asm/highmem.h> +#define PKMAP_INDEX_INVAL (-1) /* declarations for linux/mm/highmem.c */ unsigned int nr_free_highpages(void);
diff --git a/mm/highmem.c b/mm/highmem.c
index 731cf9a..65beb9a 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c@@ -106,10 +106,10 @@ struct page *kmap_to_page(void *vaddr) return virt_to_page(addr); } -static void flush_all_zero_pkmaps(void) +static int flush_all_zero_pkmaps(void) { int i; - int need_flush = 0; + int index = PKMAP_INDEX_INVAL; flush_cache_kmaps();
@@ -141,10 +141,12 @@ static void flush_all_zero_pkmaps(void) &pkmap_page_table[i]); set_page_address(page, NULL); - need_flush = 1; + index = i; } - if (need_flush) + if (index != PKMAP_INDEX_INVAL) flush_tlb_kernel_range(PKMAP_ADDR(0), PKMAP_ADDR(LAST_PKMAP)); + + return index; } /**
@@ -160,6 +162,7 @@ void kmap_flush_unused(void) static inline unsigned long map_new_virtual(struct page *page) { unsigned long vaddr; + int index = PKMAP_INDEX_INVAL; int count; start:
@@ -168,40 +171,45 @@ start: for (;;) { last_pkmap_nr = (last_pkmap_nr + 1) & LAST_PKMAP_MASK; if (!last_pkmap_nr) { - flush_all_zero_pkmaps(); - count = LAST_PKMAP; + index = flush_all_zero_pkmaps(); + if (index != PKMAP_INDEX_INVAL) + break; /* Found a usable entry */ } - if (!pkmap_count[last_pkmap_nr]) + if (!pkmap_count[last_pkmap_nr]) { + index = last_pkmap_nr; break; /* Found a usable entry */ - if (--count) - continue; - - /* - * Sleep for somebody else to unmap their entries - */ - { - DECLARE_WAITQUEUE(wait, current); - - __set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&pkmap_map_wait, &wait); - unlock_kmap(); - schedule(); - remove_wait_queue(&pkmap_map_wait, &wait); - lock_kmap(); - - /* Somebody else might have mapped it while we slept */ - if (page_address(page)) - return (unsigned long)page_address(page); - - /* Re-start */ - goto start; } + if (--count == 0) + break; } - vaddr = PKMAP_ADDR(last_pkmap_nr); + + /* + * Sleep for somebody else to unmap their entries + */ + if (index == PKMAP_INDEX_INVAL) { + DECLARE_WAITQUEUE(wait, current); + + __set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&pkmap_map_wait, &wait); + unlock_kmap(); + schedule(); + remove_wait_queue(&pkmap_map_wait, &wait); + lock_kmap(); + + /* Somebody else might have mapped it while we slept */ + vaddr = (unsigned long)page_address(page); + if (vaddr) + return vaddr; + + /* Re-start */ + goto start; + } + + vaddr = PKMAP_ADDR(index); set_pte_at(&init_mm, vaddr, - &(pkmap_page_table[last_pkmap_nr]), mk_pte(page, kmap_prot)); + &(pkmap_page_table[index]), mk_pte(page, kmap_prot)); - pkmap_count[last_pkmap_nr] = 1; + pkmap_count[index] = 1; set_page_address(page, (void *)vaddr); return vaddr;
--
1.7.9.5
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>