diff options
author | Mel Gorman <mgorman@suse.de> | 2012-07-31 19:44:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-31 21:42:47 -0400 |
commit | a509bc1a9e487d952d9404318f7f990166ab57a7 (patch) | |
tree | 40a8f8a20877da8a5b855cfbc3813c0874605093 /mm/swapfile.c | |
parent | 62c230bc1790923a1b35da03596a68a6c9b5b100 (diff) |
mm: swap: implement generic handler for swap_activate
The version of swap_activate introduced is sufficient for swap-over-NFS
but would not provide enough information to implement a generic handler.
This patch shuffles things slightly to ensure the same information is
available for aops->swap_activate() as is available to the core.
No functionality change.
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.c | 91 |
1 files changed, 5 insertions, 86 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index 6ffc87602f4a..7307fc928d7b 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -1345,7 +1345,7 @@ static void destroy_swap_extents(struct swap_info_struct *sis) | |||
1345 | * | 1345 | * |
1346 | * This function rather assumes that it is called in ascending page order. | 1346 | * This function rather assumes that it is called in ascending page order. |
1347 | */ | 1347 | */ |
1348 | static int | 1348 | int |
1349 | add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | 1349 | add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, |
1350 | unsigned long nr_pages, sector_t start_block) | 1350 | unsigned long nr_pages, sector_t start_block) |
1351 | { | 1351 | { |
@@ -1421,106 +1421,25 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span) | |||
1421 | struct file *swap_file = sis->swap_file; | 1421 | struct file *swap_file = sis->swap_file; |
1422 | struct address_space *mapping = swap_file->f_mapping; | 1422 | struct address_space *mapping = swap_file->f_mapping; |
1423 | struct inode *inode = mapping->host; | 1423 | struct inode *inode = mapping->host; |
1424 | unsigned blocks_per_page; | ||
1425 | unsigned long page_no; | ||
1426 | unsigned blkbits; | ||
1427 | sector_t probe_block; | ||
1428 | sector_t last_block; | ||
1429 | sector_t lowest_block = -1; | ||
1430 | sector_t highest_block = 0; | ||
1431 | int nr_extents = 0; | ||
1432 | int ret; | 1424 | int ret; |
1433 | 1425 | ||
1434 | if (S_ISBLK(inode->i_mode)) { | 1426 | if (S_ISBLK(inode->i_mode)) { |
1435 | ret = add_swap_extent(sis, 0, sis->max, 0); | 1427 | ret = add_swap_extent(sis, 0, sis->max, 0); |
1436 | *span = sis->pages; | 1428 | *span = sis->pages; |
1437 | goto out; | 1429 | return ret; |
1438 | } | 1430 | } |
1439 | 1431 | ||
1440 | if (mapping->a_ops->swap_activate) { | 1432 | if (mapping->a_ops->swap_activate) { |
1441 | ret = mapping->a_ops->swap_activate(swap_file); | 1433 | ret = mapping->a_ops->swap_activate(sis, swap_file, span); |
1442 | if (!ret) { | 1434 | if (!ret) { |
1443 | sis->flags |= SWP_FILE; | 1435 | sis->flags |= SWP_FILE; |
1444 | ret = add_swap_extent(sis, 0, sis->max, 0); | 1436 | ret = add_swap_extent(sis, 0, sis->max, 0); |
1445 | *span = sis->pages; | 1437 | *span = sis->pages; |
1446 | } | 1438 | } |
1447 | goto out; | 1439 | return ret; |
1448 | } | 1440 | } |
1449 | 1441 | ||
1450 | blkbits = inode->i_blkbits; | 1442 | return generic_swapfile_activate(sis, swap_file, span); |
1451 | blocks_per_page = PAGE_SIZE >> blkbits; | ||
1452 | |||
1453 | /* | ||
1454 | * Map all the blocks into the extent list. This code doesn't try | ||
1455 | * to be very smart. | ||
1456 | */ | ||
1457 | probe_block = 0; | ||
1458 | page_no = 0; | ||
1459 | last_block = i_size_read(inode) >> blkbits; | ||
1460 | while ((probe_block + blocks_per_page) <= last_block && | ||
1461 | page_no < sis->max) { | ||
1462 | unsigned block_in_page; | ||
1463 | sector_t first_block; | ||
1464 | |||
1465 | first_block = bmap(inode, probe_block); | ||
1466 | if (first_block == 0) | ||
1467 | goto bad_bmap; | ||
1468 | |||
1469 | /* | ||
1470 | * It must be PAGE_SIZE aligned on-disk | ||
1471 | */ | ||
1472 | if (first_block & (blocks_per_page - 1)) { | ||
1473 | probe_block++; | ||
1474 | goto reprobe; | ||
1475 | } | ||
1476 | |||
1477 | for (block_in_page = 1; block_in_page < blocks_per_page; | ||
1478 | block_in_page++) { | ||
1479 | sector_t block; | ||
1480 | |||
1481 | block = bmap(inode, probe_block + block_in_page); | ||
1482 | if (block == 0) | ||
1483 | goto bad_bmap; | ||
1484 | if (block != first_block + block_in_page) { | ||
1485 | /* Discontiguity */ | ||
1486 | probe_block++; | ||
1487 | goto reprobe; | ||
1488 | } | ||
1489 | } | ||
1490 | |||
1491 | first_block >>= (PAGE_SHIFT - blkbits); | ||
1492 | if (page_no) { /* exclude the header page */ | ||
1493 | if (first_block < lowest_block) | ||
1494 | lowest_block = first_block; | ||
1495 | if (first_block > highest_block) | ||
1496 | highest_block = first_block; | ||
1497 | } | ||
1498 | |||
1499 | /* | ||
1500 | * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks | ||
1501 | */ | ||
1502 | ret = add_swap_extent(sis, page_no, 1, first_block); | ||
1503 | if (ret < 0) | ||
1504 | goto out; | ||
1505 | nr_extents += ret; | ||
1506 | page_no++; | ||
1507 | probe_block += blocks_per_page; | ||
1508 | reprobe: | ||
1509 | continue; | ||
1510 | } | ||
1511 | ret = nr_extents; | ||
1512 | *span = 1 + highest_block - lowest_block; | ||
1513 | if (page_no == 0) | ||
1514 | page_no = 1; /* force Empty message */ | ||
1515 | sis->max = page_no; | ||
1516 | sis->pages = page_no - 1; | ||
1517 | sis->highest_bit = page_no - 1; | ||
1518 | out: | ||
1519 | return ret; | ||
1520 | bad_bmap: | ||
1521 | printk(KERN_ERR "swapon: swapfile has holes\n"); | ||
1522 | ret = -EINVAL; | ||
1523 | goto out; | ||
1524 | } | 1443 | } |
1525 | 1444 | ||
1526 | static void enable_swap_info(struct swap_info_struct *p, int prio, | 1445 | static void enable_swap_info(struct swap_info_struct *p, int prio, |