diff options
| author | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 20:29:58 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 20:29:58 -0800 |
| commit | 22a160fb095ca694e9f7ee29f131382e1faec889 (patch) | |
| tree | a9df773ad9c22327533fc5937546937a33fbee76 | |
| parent | f97f22cb0b9dca2a797feccc580b3b8fdb238ac3 (diff) | |
v2.4.13.4 -> v2.4.13.5
- Andrew Morton: remove stale UnlockPage
- me: swap cache page locking update
| -rw-r--r-- | include/linux/mm.h | 15 | ||||
| -rw-r--r-- | include/linux/pagemap.h | 2 | ||||
| -rw-r--r-- | mm/memory.c | 13 | ||||
| -rw-r--r-- | mm/swap_state.c | 5 | ||||
| -rw-r--r-- | mm/swapfile.c | 48 |
5 files changed, 55 insertions, 28 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index 6cbd7ed4c464..f865aafd1445 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -466,20 +466,7 @@ static inline int is_page_cache_freeable(struct page * page) return page_count(page) - !!page->buffers == 1; } -/* - * Work out if there are any other processes sharing this - * swap cache page. Never mind the buffers. - */ -static inline int exclusive_swap_page(struct page *page) -{ - if (!PageLocked(page)) - BUG(); - if (!PageSwapCache(page)) - return 0; - if (page_count(page) - !!page->buffers != 2) /* 2: us + cache */ - return 0; - return swap_count(page) == 1; /* 1: just cache */ -} +extern int remove_exclusive_swap_page(struct page *); extern void __free_pte(pte_t); diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 1fda6fa35b24..5da8ca6af63b 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -29,7 +29,7 @@ #define PAGE_CACHE_ALIGN(addr) (((addr)+PAGE_CACHE_SIZE-1)&PAGE_CACHE_MASK) #define page_cache_get(x) get_page(x) -#define page_cache_release(x) __free_page(x) +#define page_cache_release(x) free_lru_page(x) static inline struct page *page_cache_alloc(struct address_space *x) { diff --git a/mm/memory.c b/mm/memory.c index df6ffe94f5ff..43316f253583 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -939,9 +939,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, if (TryLockPage(old_page)) break; /* Recheck swapcachedness once the page is locked */ - can_reuse = exclusive_swap_page(old_page); - if (can_reuse) - delete_from_swap_cache(old_page); + can_reuse = remove_exclusive_swap_page(old_page); UnlockPage(old_page); if (!can_reuse) break; @@ -965,7 +963,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, if (!new_page) goto no_mem; copy_cow_page(old_page,new_page,address); - free_lru_page(old_page); + page_cache_release(old_page); /* * Re-check the pte - we dropped the lock @@ -981,7 +979,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma, new_page = old_page; } spin_unlock(&mm->page_table_lock); - free_lru_page(new_page); + page_cache_release(new_page); return 1; /* Minor fault */ bad_wp_page: @@ -989,7 +987,7 @@ bad_wp_page: printk("do_wp_page: bogus page at address %08lx (page 0x%lx)\n",address,(unsigned long)old_page); return -1; no_mem: - free_lru_page(old_page); + page_cache_release(old_page); return -1; } @@ -1150,7 +1148,6 @@ static int do_swap_page(struct mm_struct * mm, */ spin_lock(&mm->page_table_lock); if (!pte_same(*page_table, orig_pte)) { - UnlockPage(page); page_cache_release(page); spin_unlock(&mm->page_table_lock); return 1; @@ -1283,7 +1280,7 @@ static int do_no_page(struct mm_struct * mm, struct vm_area_struct * vma, set_pte(page_table, entry); } else { /* One of our sibling threads was faster, back out. */ - free_lru_page(new_page); + page_cache_release(new_page); spin_unlock(&mm->page_table_lock); return 1; } diff --git a/mm/swap_state.c b/mm/swap_state.c index 30d0c085cd6d..4f7b9d6a17e2 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -137,11 +137,10 @@ void free_page_and_swap_cache(struct page *page) * - Marcelo */ if (PageSwapCache(page) && !TryLockPage(page)) { - if (exclusive_swap_page(page)) - delete_from_swap_cache(page); + remove_exclusive_swap_page(page); UnlockPage(page); } - free_lru_page(page); + page_cache_release(page); } /* diff --git a/mm/swapfile.c b/mm/swapfile.c index e1f34979e747..002f9849a122 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -224,6 +224,50 @@ void swap_free(swp_entry_t entry) } /* + * Work out if there are any other processes sharing this + * swap cache page. Free it if you can. Return success. + */ +int remove_exclusive_swap_page(struct page *page) +{ + int retval; + struct swap_info_struct * p; + swp_entry_t entry; + + if (!PageLocked(page)) + BUG(); + if (!PageSwapCache(page)) + return 0; + if (page_count(page) - !!page->buffers != 2) /* 2: us + cache */ + return 0; + + entry.val = page->index; + p = swap_info_get(entry); + if (!p) + return 0; + + /* Is the only swap cache user the cache itself? */ + retval = 0; + if (p->swap_map[SWP_OFFSET(entry)] == 1) { + /* Recheck the page count with the pagecache lock held.. */ + spin_lock(&pagecache_lock); + if (page_count(page) - !!page->buffers == 2) { + __delete_from_swap_cache(page); + retval = 1; + } + spin_unlock(&pagecache_lock); + } + swap_info_put(p); + + if (retval) { + block_flushpage(page, 0); + swap_free(entry); + page_cache_release(page); + } + + return retval; +} + +/* * Free the swap entry like above, but also try to * free the page cache entry if it is the last user. */ @@ -242,7 +286,7 @@ void free_swap_and_cache(swp_entry_t entry) page_cache_get(page); delete_from_swap_cache(page); UnlockPage(page); - free_lru_page(page); + page_cache_release(page); } } @@ -582,7 +626,7 @@ static int try_to_unuse(unsigned int type) */ SetPageDirty(page); UnlockPage(page); - free_lru_page(page); + page_cache_release(page); /* * Make sure that we aren't completely killing |
