shrink_mmap with fewer list modifications
Subsystems (2)
PATCH 1/1 shrink_mmap with fewer list modifications
Hi,
This patch improves Riels patch by using fewer list modifications. It could be applied to most shrink_mmaps but Riels version will gain the most.
Function:
- Do not delete + insert all pages while scanning.
- Scan until a suitable page is found, then move the head.
/RogerL
This time with diff -Naur ... and Riels patch removed... --
Home page:
http://www.norran.net/nra02596/
usr/src/linux/mm/filemap.c renamed from usr/src/linux/mm/filemap.c.riel +33 -14
@@ -258,23 +258,27 @@ count = nr_lru_pages / (priority +1 ); nr_dirty = priority; -/* we need pagemap_lru_lock for list_del() ... subtle code below */ +/* we need pagemap_lru_lock for lru_cache head movement... subtle code below */ spin_lock (&pagemap_lru_lock); -while (count >0 && (page_lru = lru_cache.prev) != &lru_cache) { + page_lru = &lru_cache; +while (count >0 ) { + page_lru = page_lru->prev; +if (page_lru == &lru_cache) +break ;/* one whole run */ + page = list_entry(page_lru, struct page, lru); -list_del (page_lru);if (PageTestandClearReferenced (page)) { page->age +=3 ;if (page->age >10 ) - page->age =0 ; - goto dispose_continue; + page->age =10 ; +continue ; }if (page->age) page->age--;if (page->age) - goto dispose_continue; +continue ; count--;/*
@@ -282,10 +286,20 @@* immediate tell are untouchable.. */ if (!page->buffers &&page_count (page) >1 ) - goto dispose_continue; +continue ;if (TryLockPage (page)) - goto dispose_continue; +continue ; + +/* move header before unlock... +* NOTE: the page to scan might move on while having +* pagemap_lru unlocked. Avoid rescanning same pages +* by moving head and set page_lru to NULL to avoid +* misuses! +*/ +list_del (&lru_cache); +list_add_tail (&lru_cache, page_lru); + page_lru =NULL ;/* Release the pagemap_lru lock even if the page is not yet queued in any lru queue since we have just locked down
@@ -322,6 +336,9 @@* We can't free pages unless there's just one user * (count == 2 because we added one ourselves above). */ +if (page_count (page) <2 ) +BUG (); +if (page_count (page) !=2 ) goto cache_unlock_continue;
@@ -345,7 +362,7 @@ }/* PageDeferswap -> we swap out the page now. */ if (gfp_mask & __GFP_IO) - goto async_swap; + goto async_swap_continue; goto cache_unlock_continue; }
@@ -368,27 +385,29 @@UnlockPage (page);page_cache_release (page); goto dispose_continue; -async_swap: +async_swap_continue:spin_unlock (&pagecache_lock);/* Do NOT unlock the page ... that is done after IO. */ ClearPageDirty (page);rw_swap_page (WRITE , page,0 ); +/* no lock held here? SMP? is page_cache_get enough? */ spin_lock (&pagemap_lru_lock);page_cache_release (page); dispose_continue: -list_add (page_lru, &lru_cache); + page_lru = &lru_cache; } goto out; made_inode_progress:page_cache_release (page); made_buffer_progress: -UnlockPage (page); -page_cache_release (page); - ret =1 ;spin_lock (&pagemap_lru_lock); +list_del (&page->lru);/* page_lru is NULL... */ /* nr_lru_pages needs the spinlock */ nr_lru_pages--; +UnlockPage (page); +page_cache_release (page); + ret =1 ; out:spin_unlock (&pagemap_lru_lock);