diff options
author | Hugh Dickins <hugh@veritas.com> | 2005-09-03 18:54:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@evo.osdl.org> | 2005-09-05 03:05:40 -0400 |
commit | e2244ec2efa4ee1edf391d0001d314933e2b2974 (patch) | |
tree | c9e43f9b6e11ce41d976025c6f9d94c273521132 | |
parent | b0d9bcd4bb79a7834f8492f2ae5c2655a551f23d (diff) |
[PATCH] swap: correct swapfile nr_good_pages
If a regular swapfile lies on a filesystem whose blocksize is less than
PAGE_SIZE, then setup_swap_extents may have to cut the number of usable swap
pages; but sys_swapon's nr_good_pages was not expecting that. Also,
setup_swap_extents takes no account of badpages listed in the swap header: not
worth doing so, but ensure nr_badpages is 0 for a regular swapfile.
Signed-off-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | mm/swapfile.c | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index 9f46d83b4ece..5ac5333f37a0 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -1008,8 +1008,9 @@ reprobe: | |||
1008 | } | 1008 | } |
1009 | ret = 0; | 1009 | ret = 0; |
1010 | if (page_no == 0) | 1010 | if (page_no == 0) |
1011 | ret = -EINVAL; | 1011 | page_no = 1; /* force Empty message */ |
1012 | sis->max = page_no; | 1012 | sis->max = page_no; |
1013 | sis->pages = page_no - 1; | ||
1013 | sis->highest_bit = page_no - 1; | 1014 | sis->highest_bit = page_no - 1; |
1014 | done: | 1015 | done: |
1015 | sis->curr_swap_extent = list_entry(sis->extent_list.prev, | 1016 | sis->curr_swap_extent = list_entry(sis->extent_list.prev, |
@@ -1446,6 +1447,10 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1446 | p->highest_bit = maxpages - 1; | 1447 | p->highest_bit = maxpages - 1; |
1447 | 1448 | ||
1448 | error = -EINVAL; | 1449 | error = -EINVAL; |
1450 | if (!maxpages) | ||
1451 | goto bad_swap; | ||
1452 | if (swap_header->info.nr_badpages && S_ISREG(inode->i_mode)) | ||
1453 | goto bad_swap; | ||
1449 | if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES) | 1454 | if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES) |
1450 | goto bad_swap; | 1455 | goto bad_swap; |
1451 | 1456 | ||
@@ -1470,25 +1475,27 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1470 | if (error) | 1475 | if (error) |
1471 | goto bad_swap; | 1476 | goto bad_swap; |
1472 | } | 1477 | } |
1473 | 1478 | ||
1474 | if (swapfilesize && maxpages > swapfilesize) { | 1479 | if (swapfilesize && maxpages > swapfilesize) { |
1475 | printk(KERN_WARNING | 1480 | printk(KERN_WARNING |
1476 | "Swap area shorter than signature indicates\n"); | 1481 | "Swap area shorter than signature indicates\n"); |
1477 | error = -EINVAL; | 1482 | error = -EINVAL; |
1478 | goto bad_swap; | 1483 | goto bad_swap; |
1479 | } | 1484 | } |
1485 | if (nr_good_pages) { | ||
1486 | p->swap_map[0] = SWAP_MAP_BAD; | ||
1487 | p->max = maxpages; | ||
1488 | p->pages = nr_good_pages; | ||
1489 | error = setup_swap_extents(p); | ||
1490 | if (error) | ||
1491 | goto bad_swap; | ||
1492 | nr_good_pages = p->pages; | ||
1493 | } | ||
1480 | if (!nr_good_pages) { | 1494 | if (!nr_good_pages) { |
1481 | printk(KERN_WARNING "Empty swap-file\n"); | 1495 | printk(KERN_WARNING "Empty swap-file\n"); |
1482 | error = -EINVAL; | 1496 | error = -EINVAL; |
1483 | goto bad_swap; | 1497 | goto bad_swap; |
1484 | } | 1498 | } |
1485 | p->swap_map[0] = SWAP_MAP_BAD; | ||
1486 | p->max = maxpages; | ||
1487 | p->pages = nr_good_pages; | ||
1488 | |||
1489 | error = setup_swap_extents(p); | ||
1490 | if (error) | ||
1491 | goto bad_swap; | ||
1492 | 1499 | ||
1493 | down(&swapon_sem); | 1500 | down(&swapon_sem); |
1494 | swap_list_lock(); | 1501 | swap_list_lock(); |