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) |
