aboutsummaryrefslogtreecommitdiffstats
path: root/mm/swapfile.c
diff options
context:
space:
mode:
authorMel Gorman <mgorman@suse.de>2012-07-31 19:44:55 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-31 21:42:47 -0400
commit62c230bc1790923a1b35da03596a68a6c9b5b100 (patch)
tree46b300a00929087627e029b0f4d53e486a97ba7f /mm/swapfile.c
parent18022c5d8627a7a9ba8097a0f238b513fae6f5b8 (diff)
mm: add support for a filesystem to activate swap files and use direct_IO for writing swap pages
Currently swapfiles are managed entirely by the core VM by using ->bmap to allocate space and write to the blocks directly. This effectively ensures that the underlying blocks are allocated and avoids the need for the swap subsystem to locate what physical blocks store offsets within a file. If the swap subsystem is to use the filesystem information to locate the blocks, it is critical that information such as block groups, block bitmaps and the block descriptor table that map the swap file were resident in memory. This patch adds address_space_operations that the VM can call when activating or deactivating swap backed by a file. int swap_activate(struct file *); int swap_deactivate(struct file *); The ->swap_activate() method is used to communicate to the file that the VM relies on it, and the address_space should take adequate measures such as reserving space in the underlying device, reserving memory for mempools and pinning information such as the block descriptor table in memory. The ->swap_deactivate() method is called on sys_swapoff() if ->swap_activate() returned success. After a successful swapfile ->swap_activate, the swapfile is marked SWP_FILE and swapper_space.a_ops will proxy to sis->swap_file->f_mappings->a_ops using ->direct_io to write swapcache pages and ->readpage to read. It is perfectly possible that direct_IO be used to read the swap pages but it is an unnecessary complication. Similarly, it is possible that ->writepage be used instead of direct_io to write the pages but filesystem developers have stated that calling writepage from the VM is undesirable for a variety of reasons and using direct_IO opens up the possibility of writing back batches of swap pages in the future. [a.p.zijlstra@chello.nl: Original patch] Signed-off-by: Mel Gorman <mgorman@suse.de> Acked-by: Rik van Riel <riel@redhat.com> Cc: Christoph Hellwig <hch@infradead.org> Cc: David S. Miller <davem@davemloft.net> Cc: Eric B Munson <emunson@mgebm.net> Cc: Eric Paris <eparis@redhat.com> Cc: James Morris <jmorris@namei.org> Cc: Mel Gorman <mgorman@suse.de> Cc: Mike Christie <michaelc@cs.wisc.edu> Cc: Neil Brown <neilb@suse.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> Cc: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: Xiaotian Feng <dfeng@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r--mm/swapfile.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c
index f89af5ba2eb2..6ffc87602f4a 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1329,6 +1329,14 @@ static void destroy_swap_extents(struct swap_info_struct *sis)
1329 list_del(&se->list); 1329 list_del(&se->list);
1330 kfree(se); 1330 kfree(se);
1331 } 1331 }
1332
1333 if (sis->flags & SWP_FILE) {
1334 struct file *swap_file = sis->swap_file;
1335 struct address_space *mapping = swap_file->f_mapping;
1336
1337 sis->flags &= ~SWP_FILE;
1338 mapping->a_ops->swap_deactivate(swap_file);
1339 }
1332} 1340}
1333 1341
1334/* 1342/*
@@ -1410,7 +1418,9 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
1410 */ 1418 */
1411static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span) 1419static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span)
1412{ 1420{
1413 struct inode *inode; 1421 struct file *swap_file = sis->swap_file;
1422 struct address_space *mapping = swap_file->f_mapping;
1423 struct inode *inode = mapping->host;
1414 unsigned blocks_per_page; 1424 unsigned blocks_per_page;
1415 unsigned long page_no; 1425 unsigned long page_no;
1416 unsigned blkbits; 1426 unsigned blkbits;
@@ -1421,13 +1431,22 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span)
1421 int nr_extents = 0; 1431 int nr_extents = 0;
1422 int ret; 1432 int ret;
1423 1433
1424 inode = sis->swap_file->f_mapping->host;
1425 if (S_ISBLK(inode->i_mode)) { 1434 if (S_ISBLK(inode->i_mode)) {
1426 ret = add_swap_extent(sis, 0, sis->max, 0); 1435 ret = add_swap_extent(sis, 0, sis->max, 0);
1427 *span = sis->pages; 1436 *span = sis->pages;
1428 goto out; 1437 goto out;
1429 } 1438 }
1430 1439
1440 if (mapping->a_ops->swap_activate) {
1441 ret = mapping->a_ops->swap_activate(swap_file);
1442 if (!ret) {
1443 sis->flags |= SWP_FILE;
1444 ret = add_swap_extent(sis, 0, sis->max, 0);
1445 *span = sis->pages;
1446 }
1447 goto out;
1448 }
1449
1431 blkbits = inode->i_blkbits; 1450 blkbits = inode->i_blkbits;
1432 blocks_per_page = PAGE_SIZE >> blkbits; 1451 blocks_per_page = PAGE_SIZE >> blkbits;
1433 1452