diff options
| author | Andrew Morton <akpm@osdl.org> | 2004-04-17 20:55:06 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-04-17 20:55:06 -0700 |
| commit | 3df9aaf34e68c9256b08d02ca65ced12bf9e8d9e (patch) | |
| tree | f05bfe114893f8679f878bbb747c9c0077c3911c | |
| parent | c4d92e6b147b133848e8d89a734efdd2c3302d14 (diff) | |
[PATCH] rmap: swap_unplug page
From: Hugh Dickins <hugh@veritas.com>
Good example of "swapper_space considered harmful": swap_unplug_io_fn was
originally designed for calling via swapper_space.backing_dev_info; but
that way it loses track of which device is to be unplugged, so had to
unplug all swap devices. But now sync_page tests SwapCache anyway, can
call swap_unplug_io_fn with page, which leads direct to the device.
Reverted -mc4's CONFIG_SWAP=n fix, just add another NOTHING for it.
Reverted -mc3's editorial adjustments to swap_backing_dev_info and
swapper_space initializations: they document the few fields which are
actually used now, as comment above them says (sound of slapped wrist).
| -rw-r--r-- | include/linux/swap.h | 5 | ||||
| -rw-r--r-- | mm/filemap.c | 2 | ||||
| -rw-r--r-- | mm/nommu.c | 5 | ||||
| -rw-r--r-- | mm/swap_state.c | 4 | ||||
| -rw-r--r-- | mm/swapfile.c | 23 |
5 files changed, 20 insertions, 19 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h index f911d8afb8a5..5c5a79729041 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -181,8 +181,6 @@ extern int vm_swappiness; extern int shmem_unuse(swp_entry_t entry, struct page *page); #endif /* CONFIG_MMU */ -extern void swap_unplug_io_fn(struct backing_dev_info *); - #ifdef CONFIG_SWAP /* linux/mm/page_io.c */ extern int swap_readpage(struct file *, struct page *); @@ -218,7 +216,7 @@ extern sector_t map_swap_page(struct swap_info_struct *, pgoff_t); extern struct swap_info_struct *get_swap_info_struct(unsigned); extern int can_share_swap_page(struct page *); extern int remove_exclusive_swap_page(struct page *); -struct backing_dev_info; +extern void swap_unplug_io_fn(struct page *); extern struct swap_list_t swap_list; extern spinlock_t swaplock; @@ -252,6 +250,7 @@ extern spinlock_t swaplock; #define move_from_swap_cache(p, i, m) 1 #define __delete_from_swap_cache(p) /*NOTHING*/ #define delete_from_swap_cache(p) /*NOTHING*/ +#define swap_unplug_io_fn(p) /*NOTHING*/ static inline int remove_exclusive_swap_page(struct page *p) { diff --git a/mm/filemap.c b/mm/filemap.c index 4149342710f1..a82e900593da 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -127,7 +127,7 @@ static inline int sync_page(struct page *page) if (mapping->a_ops && mapping->a_ops->sync_page) return mapping->a_ops->sync_page(page); } else if (PageSwapCache(page)) { - swap_unplug_io_fn(NULL); + swap_unplug_io_fn(page); } return 0; } diff --git a/mm/nommu.c b/mm/nommu.c index 1432dbab85eb..c940756b49e5 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -18,7 +18,6 @@ #include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/blkdev.h> -#include <linux/backing-dev.h> #include <asm/pgalloc.h> #include <asm/uaccess.h> @@ -572,7 +571,3 @@ unsigned long get_unmapped_area(struct file *file, unsigned long addr, void pte_chain_init(void) { } - -void swap_unplug_io_fn(struct backing_dev_info *) -{ -} diff --git a/mm/swap_state.c b/mm/swap_state.c index d76b2d1bcf79..b6232384d411 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -25,13 +25,13 @@ static struct address_space_operations swap_aops = { }; static struct backing_dev_info swap_backing_dev_info = { - .memory_backed = 1, /* Does not contribute to dirty memory */ - .unplug_io_fn = swap_unplug_io_fn, + .state = 0, /* uncongested */ }; struct address_space swapper_space = { .page_tree = RADIX_TREE_INIT(GFP_ATOMIC), .tree_lock = SPIN_LOCK_UNLOCKED, + .nrpages = 0, /* total_swapcache_pages */ .a_ops = &swap_aops, .backing_dev_info = &swap_backing_dev_info, }; diff --git a/mm/swapfile.c b/mm/swapfile.c index c3ece5503ddb..3103178c6e52 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -86,19 +86,26 @@ static void remove_swap_bdev(struct block_device *bdev) BUG(); } -void swap_unplug_io_fn(struct backing_dev_info *unused_bdi) +/* + * Unlike a standard unplug_io_fn, swap_unplug_io_fn is never called + * through swap's backing_dev_info (which is only used by shrink_list), + * but directly from sync_page when PageSwapCache: and takes the page + * as argument, so that it can find the right device from swp_entry_t. + */ +void swap_unplug_io_fn(struct page *page) { - int i; + swp_entry_t entry; down(&swap_bdevs_sem); - for (i = 0; i < MAX_SWAPFILES; i++) { - struct block_device *bdev = swap_bdevs[i]; + entry.val = page->private; + if (PageSwapCache(page)) { + struct block_device *bdev = swap_bdevs[swp_type(entry)]; struct backing_dev_info *bdi; - if (bdev == NULL) - break; - bdi = bdev->bd_inode->i_mapping->backing_dev_info; - (*bdi->unplug_io_fn)(bdi); + if (bdev) { + bdi = bdev->bd_inode->i_mapping->backing_dev_info; + (*bdi->unplug_io_fn)(bdi); + } } up(&swap_bdevs_sem); } |
