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 *);
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;
#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)
{
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;
}
#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>
void pte_chain_init(void)
{
}
-
-void swap_unplug_io_fn(struct backing_dev_info *)
-{
-}
};
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,
};
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);
}