diff options
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r-- | mm/swapfile.c | 49 |
1 files changed, 25 insertions, 24 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index bd1bb5920306..2f33edb8bee9 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -37,6 +37,7 @@ DEFINE_SPINLOCK(swap_lock); | |||
37 | unsigned int nr_swapfiles; | 37 | unsigned int nr_swapfiles; |
38 | long total_swap_pages; | 38 | long total_swap_pages; |
39 | static int swap_overflow; | 39 | static int swap_overflow; |
40 | static int least_priority; | ||
40 | 41 | ||
41 | static const char Bad_file[] = "Bad swap file entry "; | 42 | static const char Bad_file[] = "Bad swap file entry "; |
42 | static const char Unused_file[] = "Unused swap file entry "; | 43 | static const char Unused_file[] = "Unused swap file entry "; |
@@ -1260,6 +1261,11 @@ asmlinkage long sys_swapoff(const char __user * specialfile) | |||
1260 | /* just pick something that's safe... */ | 1261 | /* just pick something that's safe... */ |
1261 | swap_list.next = swap_list.head; | 1262 | swap_list.next = swap_list.head; |
1262 | } | 1263 | } |
1264 | if (p->prio < 0) { | ||
1265 | for (i = p->next; i >= 0; i = swap_info[i].next) | ||
1266 | swap_info[i].prio = p->prio--; | ||
1267 | least_priority++; | ||
1268 | } | ||
1263 | nr_swap_pages -= p->pages; | 1269 | nr_swap_pages -= p->pages; |
1264 | total_swap_pages -= p->pages; | 1270 | total_swap_pages -= p->pages; |
1265 | p->flags &= ~SWP_WRITEOK; | 1271 | p->flags &= ~SWP_WRITEOK; |
@@ -1272,9 +1278,14 @@ asmlinkage long sys_swapoff(const char __user * specialfile) | |||
1272 | if (err) { | 1278 | if (err) { |
1273 | /* re-insert swap space back into swap_list */ | 1279 | /* re-insert swap space back into swap_list */ |
1274 | spin_lock(&swap_lock); | 1280 | spin_lock(&swap_lock); |
1275 | for (prev = -1, i = swap_list.head; i >= 0; prev = i, i = swap_info[i].next) | 1281 | if (p->prio < 0) |
1282 | p->prio = --least_priority; | ||
1283 | prev = -1; | ||
1284 | for (i = swap_list.head; i >= 0; i = swap_info[i].next) { | ||
1276 | if (p->prio >= swap_info[i].prio) | 1285 | if (p->prio >= swap_info[i].prio) |
1277 | break; | 1286 | break; |
1287 | prev = i; | ||
1288 | } | ||
1278 | p->next = i; | 1289 | p->next = i; |
1279 | if (prev < 0) | 1290 | if (prev < 0) |
1280 | swap_list.head = swap_list.next = p - swap_info; | 1291 | swap_list.head = swap_list.next = p - swap_info; |
@@ -1447,7 +1458,6 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1447 | unsigned int type; | 1458 | unsigned int type; |
1448 | int i, prev; | 1459 | int i, prev; |
1449 | int error; | 1460 | int error; |
1450 | static int least_priority; | ||
1451 | union swap_header *swap_header = NULL; | 1461 | union swap_header *swap_header = NULL; |
1452 | int swap_header_version; | 1462 | int swap_header_version; |
1453 | unsigned int nr_good_pages = 0; | 1463 | unsigned int nr_good_pages = 0; |
@@ -1455,7 +1465,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1455 | sector_t span; | 1465 | sector_t span; |
1456 | unsigned long maxpages = 1; | 1466 | unsigned long maxpages = 1; |
1457 | int swapfilesize; | 1467 | int swapfilesize; |
1458 | unsigned short *swap_map; | 1468 | unsigned short *swap_map = NULL; |
1459 | struct page *page = NULL; | 1469 | struct page *page = NULL; |
1460 | struct inode *inode = NULL; | 1470 | struct inode *inode = NULL; |
1461 | int did_down = 0; | 1471 | int did_down = 0; |
@@ -1474,22 +1484,10 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1474 | } | 1484 | } |
1475 | if (type >= nr_swapfiles) | 1485 | if (type >= nr_swapfiles) |
1476 | nr_swapfiles = type+1; | 1486 | nr_swapfiles = type+1; |
1487 | memset(p, 0, sizeof(*p)); | ||
1477 | INIT_LIST_HEAD(&p->extent_list); | 1488 | INIT_LIST_HEAD(&p->extent_list); |
1478 | p->flags = SWP_USED; | 1489 | p->flags = SWP_USED; |
1479 | p->swap_file = NULL; | ||
1480 | p->old_block_size = 0; | ||
1481 | p->swap_map = NULL; | ||
1482 | p->lowest_bit = 0; | ||
1483 | p->highest_bit = 0; | ||
1484 | p->cluster_nr = 0; | ||
1485 | p->inuse_pages = 0; | ||
1486 | p->next = -1; | 1490 | p->next = -1; |
1487 | if (swap_flags & SWAP_FLAG_PREFER) { | ||
1488 | p->prio = | ||
1489 | (swap_flags & SWAP_FLAG_PRIO_MASK)>>SWAP_FLAG_PRIO_SHIFT; | ||
1490 | } else { | ||
1491 | p->prio = --least_priority; | ||
1492 | } | ||
1493 | spin_unlock(&swap_lock); | 1491 | spin_unlock(&swap_lock); |
1494 | name = getname(specialfile); | 1492 | name = getname(specialfile); |
1495 | error = PTR_ERR(name); | 1493 | error = PTR_ERR(name); |
@@ -1632,19 +1630,20 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1632 | goto bad_swap; | 1630 | goto bad_swap; |
1633 | 1631 | ||
1634 | /* OK, set up the swap map and apply the bad block list */ | 1632 | /* OK, set up the swap map and apply the bad block list */ |
1635 | if (!(p->swap_map = vmalloc(maxpages * sizeof(short)))) { | 1633 | swap_map = vmalloc(maxpages * sizeof(short)); |
1634 | if (!swap_map) { | ||
1636 | error = -ENOMEM; | 1635 | error = -ENOMEM; |
1637 | goto bad_swap; | 1636 | goto bad_swap; |
1638 | } | 1637 | } |
1639 | 1638 | ||
1640 | error = 0; | 1639 | error = 0; |
1641 | memset(p->swap_map, 0, maxpages * sizeof(short)); | 1640 | memset(swap_map, 0, maxpages * sizeof(short)); |
1642 | for (i = 0; i < swap_header->info.nr_badpages; i++) { | 1641 | for (i = 0; i < swap_header->info.nr_badpages; i++) { |
1643 | int page_nr = swap_header->info.badpages[i]; | 1642 | int page_nr = swap_header->info.badpages[i]; |
1644 | if (page_nr <= 0 || page_nr >= swap_header->info.last_page) | 1643 | if (page_nr <= 0 || page_nr >= swap_header->info.last_page) |
1645 | error = -EINVAL; | 1644 | error = -EINVAL; |
1646 | else | 1645 | else |
1647 | p->swap_map[page_nr] = SWAP_MAP_BAD; | 1646 | swap_map[page_nr] = SWAP_MAP_BAD; |
1648 | } | 1647 | } |
1649 | nr_good_pages = swap_header->info.last_page - | 1648 | nr_good_pages = swap_header->info.last_page - |
1650 | swap_header->info.nr_badpages - | 1649 | swap_header->info.nr_badpages - |
@@ -1654,7 +1653,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1654 | } | 1653 | } |
1655 | 1654 | ||
1656 | if (nr_good_pages) { | 1655 | if (nr_good_pages) { |
1657 | p->swap_map[0] = SWAP_MAP_BAD; | 1656 | swap_map[0] = SWAP_MAP_BAD; |
1658 | p->max = maxpages; | 1657 | p->max = maxpages; |
1659 | p->pages = nr_good_pages; | 1658 | p->pages = nr_good_pages; |
1660 | nr_extents = setup_swap_extents(p, &span); | 1659 | nr_extents = setup_swap_extents(p, &span); |
@@ -1672,6 +1671,12 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1672 | 1671 | ||
1673 | mutex_lock(&swapon_mutex); | 1672 | mutex_lock(&swapon_mutex); |
1674 | spin_lock(&swap_lock); | 1673 | spin_lock(&swap_lock); |
1674 | if (swap_flags & SWAP_FLAG_PREFER) | ||
1675 | p->prio = | ||
1676 | (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT; | ||
1677 | else | ||
1678 | p->prio = --least_priority; | ||
1679 | p->swap_map = swap_map; | ||
1675 | p->flags = SWP_ACTIVE; | 1680 | p->flags = SWP_ACTIVE; |
1676 | nr_swap_pages += nr_good_pages; | 1681 | nr_swap_pages += nr_good_pages; |
1677 | total_swap_pages += nr_good_pages; | 1682 | total_swap_pages += nr_good_pages; |
@@ -1707,12 +1712,8 @@ bad_swap: | |||
1707 | destroy_swap_extents(p); | 1712 | destroy_swap_extents(p); |
1708 | bad_swap_2: | 1713 | bad_swap_2: |
1709 | spin_lock(&swap_lock); | 1714 | spin_lock(&swap_lock); |
1710 | swap_map = p->swap_map; | ||
1711 | p->swap_file = NULL; | 1715 | p->swap_file = NULL; |
1712 | p->swap_map = NULL; | ||
1713 | p->flags = 0; | 1716 | p->flags = 0; |
1714 | if (!(swap_flags & SWAP_FLAG_PREFER)) | ||
1715 | ++least_priority; | ||
1716 | spin_unlock(&swap_lock); | 1717 | spin_unlock(&swap_lock); |
1717 | vfree(swap_map); | 1718 | vfree(swap_map); |
1718 | if (swap_file) | 1719 | if (swap_file) |