diff options
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r-- | mm/swapfile.c | 204 |
1 files changed, 113 insertions, 91 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index f83f1c6f6196..dc88a7e4257e 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -49,7 +49,7 @@ static const char Unused_offset[] = "Unused swap offset entry "; | |||
49 | 49 | ||
50 | static struct swap_list_t swap_list = {-1, -1}; | 50 | static struct swap_list_t swap_list = {-1, -1}; |
51 | 51 | ||
52 | static struct swap_info_struct swap_info[MAX_SWAPFILES]; | 52 | static struct swap_info_struct *swap_info[MAX_SWAPFILES]; |
53 | 53 | ||
54 | static DEFINE_MUTEX(swapon_mutex); | 54 | static DEFINE_MUTEX(swapon_mutex); |
55 | 55 | ||
@@ -79,12 +79,11 @@ static inline unsigned short encode_swapmap(int count, bool has_cache) | |||
79 | return ret; | 79 | return ret; |
80 | } | 80 | } |
81 | 81 | ||
82 | /* returnes 1 if swap entry is freed */ | 82 | /* returns 1 if swap entry is freed */ |
83 | static int | 83 | static int |
84 | __try_to_reclaim_swap(struct swap_info_struct *si, unsigned long offset) | 84 | __try_to_reclaim_swap(struct swap_info_struct *si, unsigned long offset) |
85 | { | 85 | { |
86 | int type = si - swap_info; | 86 | swp_entry_t entry = swp_entry(si->type, offset); |
87 | swp_entry_t entry = swp_entry(type, offset); | ||
88 | struct page *page; | 87 | struct page *page; |
89 | int ret = 0; | 88 | int ret = 0; |
90 | 89 | ||
@@ -120,7 +119,7 @@ void swap_unplug_io_fn(struct backing_dev_info *unused_bdi, struct page *page) | |||
120 | down_read(&swap_unplug_sem); | 119 | down_read(&swap_unplug_sem); |
121 | entry.val = page_private(page); | 120 | entry.val = page_private(page); |
122 | if (PageSwapCache(page)) { | 121 | if (PageSwapCache(page)) { |
123 | struct block_device *bdev = swap_info[swp_type(entry)].bdev; | 122 | struct block_device *bdev = swap_info[swp_type(entry)]->bdev; |
124 | struct backing_dev_info *bdi; | 123 | struct backing_dev_info *bdi; |
125 | 124 | ||
126 | /* | 125 | /* |
@@ -467,10 +466,10 @@ swp_entry_t get_swap_page(void) | |||
467 | nr_swap_pages--; | 466 | nr_swap_pages--; |
468 | 467 | ||
469 | for (type = swap_list.next; type >= 0 && wrapped < 2; type = next) { | 468 | for (type = swap_list.next; type >= 0 && wrapped < 2; type = next) { |
470 | si = swap_info + type; | 469 | si = swap_info[type]; |
471 | next = si->next; | 470 | next = si->next; |
472 | if (next < 0 || | 471 | if (next < 0 || |
473 | (!wrapped && si->prio != swap_info[next].prio)) { | 472 | (!wrapped && si->prio != swap_info[next]->prio)) { |
474 | next = swap_list.head; | 473 | next = swap_list.head; |
475 | wrapped++; | 474 | wrapped++; |
476 | } | 475 | } |
@@ -503,8 +502,8 @@ swp_entry_t get_swap_page_of_type(int type) | |||
503 | pgoff_t offset; | 502 | pgoff_t offset; |
504 | 503 | ||
505 | spin_lock(&swap_lock); | 504 | spin_lock(&swap_lock); |
506 | si = swap_info + type; | 505 | si = swap_info[type]; |
507 | if (si->flags & SWP_WRITEOK) { | 506 | if (si && (si->flags & SWP_WRITEOK)) { |
508 | nr_swap_pages--; | 507 | nr_swap_pages--; |
509 | /* This is called for allocating swap entry, not cache */ | 508 | /* This is called for allocating swap entry, not cache */ |
510 | offset = scan_swap_map(si, SWAP_MAP); | 509 | offset = scan_swap_map(si, SWAP_MAP); |
@@ -528,7 +527,7 @@ static struct swap_info_struct * swap_info_get(swp_entry_t entry) | |||
528 | type = swp_type(entry); | 527 | type = swp_type(entry); |
529 | if (type >= nr_swapfiles) | 528 | if (type >= nr_swapfiles) |
530 | goto bad_nofile; | 529 | goto bad_nofile; |
531 | p = & swap_info[type]; | 530 | p = swap_info[type]; |
532 | if (!(p->flags & SWP_USED)) | 531 | if (!(p->flags & SWP_USED)) |
533 | goto bad_device; | 532 | goto bad_device; |
534 | offset = swp_offset(entry); | 533 | offset = swp_offset(entry); |
@@ -581,8 +580,9 @@ static int swap_entry_free(struct swap_info_struct *p, | |||
581 | p->lowest_bit = offset; | 580 | p->lowest_bit = offset; |
582 | if (offset > p->highest_bit) | 581 | if (offset > p->highest_bit) |
583 | p->highest_bit = offset; | 582 | p->highest_bit = offset; |
584 | if (p->prio > swap_info[swap_list.next].prio) | 583 | if (swap_list.next >= 0 && |
585 | swap_list.next = p - swap_info; | 584 | p->prio > swap_info[swap_list.next]->prio) |
585 | swap_list.next = p->type; | ||
586 | nr_swap_pages++; | 586 | nr_swap_pages++; |
587 | p->inuse_pages--; | 587 | p->inuse_pages--; |
588 | } | 588 | } |
@@ -741,14 +741,14 @@ int free_swap_and_cache(swp_entry_t entry) | |||
741 | int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) | 741 | int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) |
742 | { | 742 | { |
743 | struct block_device *bdev = NULL; | 743 | struct block_device *bdev = NULL; |
744 | int i; | 744 | int type; |
745 | 745 | ||
746 | if (device) | 746 | if (device) |
747 | bdev = bdget(device); | 747 | bdev = bdget(device); |
748 | 748 | ||
749 | spin_lock(&swap_lock); | 749 | spin_lock(&swap_lock); |
750 | for (i = 0; i < nr_swapfiles; i++) { | 750 | for (type = 0; type < nr_swapfiles; type++) { |
751 | struct swap_info_struct *sis = swap_info + i; | 751 | struct swap_info_struct *sis = swap_info[type]; |
752 | 752 | ||
753 | if (!(sis->flags & SWP_WRITEOK)) | 753 | if (!(sis->flags & SWP_WRITEOK)) |
754 | continue; | 754 | continue; |
@@ -758,7 +758,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) | |||
758 | *bdev_p = bdgrab(sis->bdev); | 758 | *bdev_p = bdgrab(sis->bdev); |
759 | 759 | ||
760 | spin_unlock(&swap_lock); | 760 | spin_unlock(&swap_lock); |
761 | return i; | 761 | return type; |
762 | } | 762 | } |
763 | if (bdev == sis->bdev) { | 763 | if (bdev == sis->bdev) { |
764 | struct swap_extent *se; | 764 | struct swap_extent *se; |
@@ -771,7 +771,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p) | |||
771 | 771 | ||
772 | spin_unlock(&swap_lock); | 772 | spin_unlock(&swap_lock); |
773 | bdput(bdev); | 773 | bdput(bdev); |
774 | return i; | 774 | return type; |
775 | } | 775 | } |
776 | } | 776 | } |
777 | } | 777 | } |
@@ -792,15 +792,17 @@ unsigned int count_swap_pages(int type, int free) | |||
792 | { | 792 | { |
793 | unsigned int n = 0; | 793 | unsigned int n = 0; |
794 | 794 | ||
795 | if (type < nr_swapfiles) { | 795 | spin_lock(&swap_lock); |
796 | spin_lock(&swap_lock); | 796 | if ((unsigned int)type < nr_swapfiles) { |
797 | if (swap_info[type].flags & SWP_WRITEOK) { | 797 | struct swap_info_struct *sis = swap_info[type]; |
798 | n = swap_info[type].pages; | 798 | |
799 | if (sis->flags & SWP_WRITEOK) { | ||
800 | n = sis->pages; | ||
799 | if (free) | 801 | if (free) |
800 | n -= swap_info[type].inuse_pages; | 802 | n -= sis->inuse_pages; |
801 | } | 803 | } |
802 | spin_unlock(&swap_lock); | ||
803 | } | 804 | } |
805 | spin_unlock(&swap_lock); | ||
804 | return n; | 806 | return n; |
805 | } | 807 | } |
806 | #endif | 808 | #endif |
@@ -1024,7 +1026,7 @@ static unsigned int find_next_to_unuse(struct swap_info_struct *si, | |||
1024 | */ | 1026 | */ |
1025 | static int try_to_unuse(unsigned int type) | 1027 | static int try_to_unuse(unsigned int type) |
1026 | { | 1028 | { |
1027 | struct swap_info_struct * si = &swap_info[type]; | 1029 | struct swap_info_struct *si = swap_info[type]; |
1028 | struct mm_struct *start_mm; | 1030 | struct mm_struct *start_mm; |
1029 | unsigned short *swap_map; | 1031 | unsigned short *swap_map; |
1030 | unsigned short swcount; | 1032 | unsigned short swcount; |
@@ -1270,10 +1272,10 @@ retry: | |||
1270 | static void drain_mmlist(void) | 1272 | static void drain_mmlist(void) |
1271 | { | 1273 | { |
1272 | struct list_head *p, *next; | 1274 | struct list_head *p, *next; |
1273 | unsigned int i; | 1275 | unsigned int type; |
1274 | 1276 | ||
1275 | for (i = 0; i < nr_swapfiles; i++) | 1277 | for (type = 0; type < nr_swapfiles; type++) |
1276 | if (swap_info[i].inuse_pages) | 1278 | if (swap_info[type]->inuse_pages) |
1277 | return; | 1279 | return; |
1278 | spin_lock(&mmlist_lock); | 1280 | spin_lock(&mmlist_lock); |
1279 | list_for_each_safe(p, next, &init_mm.mmlist) | 1281 | list_for_each_safe(p, next, &init_mm.mmlist) |
@@ -1293,7 +1295,7 @@ sector_t map_swap_page(swp_entry_t entry, struct block_device **bdev) | |||
1293 | struct swap_extent *se; | 1295 | struct swap_extent *se; |
1294 | pgoff_t offset; | 1296 | pgoff_t offset; |
1295 | 1297 | ||
1296 | sis = swap_info + swp_type(entry); | 1298 | sis = swap_info[swp_type(entry)]; |
1297 | *bdev = sis->bdev; | 1299 | *bdev = sis->bdev; |
1298 | 1300 | ||
1299 | offset = swp_offset(entry); | 1301 | offset = swp_offset(entry); |
@@ -1321,17 +1323,15 @@ sector_t map_swap_page(swp_entry_t entry, struct block_device **bdev) | |||
1321 | * Get the (PAGE_SIZE) block corresponding to given offset on the swapdev | 1323 | * Get the (PAGE_SIZE) block corresponding to given offset on the swapdev |
1322 | * corresponding to given index in swap_info (swap type). | 1324 | * corresponding to given index in swap_info (swap type). |
1323 | */ | 1325 | */ |
1324 | sector_t swapdev_block(int swap_type, pgoff_t offset) | 1326 | sector_t swapdev_block(int type, pgoff_t offset) |
1325 | { | 1327 | { |
1326 | struct swap_info_struct *sis; | ||
1327 | struct block_device *bdev; | 1328 | struct block_device *bdev; |
1328 | 1329 | ||
1329 | if (swap_type >= nr_swapfiles) | 1330 | if ((unsigned int)type >= nr_swapfiles) |
1330 | return 0; | 1331 | return 0; |
1331 | 1332 | if (!(swap_info[type]->flags & SWP_WRITEOK)) | |
1332 | sis = swap_info + swap_type; | 1333 | return 0; |
1333 | return (sis->flags & SWP_WRITEOK) ? | 1334 | return map_swap_page(swp_entry(type, offset), &bdev); |
1334 | map_swap_page(swp_entry(swap_type, offset), &bdev) : 0; | ||
1335 | } | 1335 | } |
1336 | #endif /* CONFIG_HIBERNATION */ | 1336 | #endif /* CONFIG_HIBERNATION */ |
1337 | 1337 | ||
@@ -1547,8 +1547,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | |||
1547 | mapping = victim->f_mapping; | 1547 | mapping = victim->f_mapping; |
1548 | prev = -1; | 1548 | prev = -1; |
1549 | spin_lock(&swap_lock); | 1549 | spin_lock(&swap_lock); |
1550 | for (type = swap_list.head; type >= 0; type = swap_info[type].next) { | 1550 | for (type = swap_list.head; type >= 0; type = swap_info[type]->next) { |
1551 | p = swap_info + type; | 1551 | p = swap_info[type]; |
1552 | if (p->flags & SWP_WRITEOK) { | 1552 | if (p->flags & SWP_WRITEOK) { |
1553 | if (p->swap_file->f_mapping == mapping) | 1553 | if (p->swap_file->f_mapping == mapping) |
1554 | break; | 1554 | break; |
@@ -1567,18 +1567,17 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | |||
1567 | spin_unlock(&swap_lock); | 1567 | spin_unlock(&swap_lock); |
1568 | goto out_dput; | 1568 | goto out_dput; |
1569 | } | 1569 | } |
1570 | if (prev < 0) { | 1570 | if (prev < 0) |
1571 | swap_list.head = p->next; | 1571 | swap_list.head = p->next; |
1572 | } else { | 1572 | else |
1573 | swap_info[prev].next = p->next; | 1573 | swap_info[prev]->next = p->next; |
1574 | } | ||
1575 | if (type == swap_list.next) { | 1574 | if (type == swap_list.next) { |
1576 | /* just pick something that's safe... */ | 1575 | /* just pick something that's safe... */ |
1577 | swap_list.next = swap_list.head; | 1576 | swap_list.next = swap_list.head; |
1578 | } | 1577 | } |
1579 | if (p->prio < 0) { | 1578 | if (p->prio < 0) { |
1580 | for (i = p->next; i >= 0; i = swap_info[i].next) | 1579 | for (i = p->next; i >= 0; i = swap_info[i]->next) |
1581 | swap_info[i].prio = p->prio--; | 1580 | swap_info[i]->prio = p->prio--; |
1582 | least_priority++; | 1581 | least_priority++; |
1583 | } | 1582 | } |
1584 | nr_swap_pages -= p->pages; | 1583 | nr_swap_pages -= p->pages; |
@@ -1596,16 +1595,16 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | |||
1596 | if (p->prio < 0) | 1595 | if (p->prio < 0) |
1597 | p->prio = --least_priority; | 1596 | p->prio = --least_priority; |
1598 | prev = -1; | 1597 | prev = -1; |
1599 | for (i = swap_list.head; i >= 0; i = swap_info[i].next) { | 1598 | for (i = swap_list.head; i >= 0; i = swap_info[i]->next) { |
1600 | if (p->prio >= swap_info[i].prio) | 1599 | if (p->prio >= swap_info[i]->prio) |
1601 | break; | 1600 | break; |
1602 | prev = i; | 1601 | prev = i; |
1603 | } | 1602 | } |
1604 | p->next = i; | 1603 | p->next = i; |
1605 | if (prev < 0) | 1604 | if (prev < 0) |
1606 | swap_list.head = swap_list.next = p - swap_info; | 1605 | swap_list.head = swap_list.next = type; |
1607 | else | 1606 | else |
1608 | swap_info[prev].next = p - swap_info; | 1607 | swap_info[prev]->next = type; |
1609 | nr_swap_pages += p->pages; | 1608 | nr_swap_pages += p->pages; |
1610 | total_swap_pages += p->pages; | 1609 | total_swap_pages += p->pages; |
1611 | p->flags |= SWP_WRITEOK; | 1610 | p->flags |= SWP_WRITEOK; |
@@ -1665,8 +1664,8 @@ out: | |||
1665 | /* iterator */ | 1664 | /* iterator */ |
1666 | static void *swap_start(struct seq_file *swap, loff_t *pos) | 1665 | static void *swap_start(struct seq_file *swap, loff_t *pos) |
1667 | { | 1666 | { |
1668 | struct swap_info_struct *ptr = swap_info; | 1667 | struct swap_info_struct *si; |
1669 | int i; | 1668 | int type; |
1670 | loff_t l = *pos; | 1669 | loff_t l = *pos; |
1671 | 1670 | ||
1672 | mutex_lock(&swapon_mutex); | 1671 | mutex_lock(&swapon_mutex); |
@@ -1674,11 +1673,13 @@ static void *swap_start(struct seq_file *swap, loff_t *pos) | |||
1674 | if (!l) | 1673 | if (!l) |
1675 | return SEQ_START_TOKEN; | 1674 | return SEQ_START_TOKEN; |
1676 | 1675 | ||
1677 | for (i = 0; i < nr_swapfiles; i++, ptr++) { | 1676 | for (type = 0; type < nr_swapfiles; type++) { |
1678 | if (!(ptr->flags & SWP_USED) || !ptr->swap_map) | 1677 | smp_rmb(); /* read nr_swapfiles before swap_info[type] */ |
1678 | si = swap_info[type]; | ||
1679 | if (!(si->flags & SWP_USED) || !si->swap_map) | ||
1679 | continue; | 1680 | continue; |
1680 | if (!--l) | 1681 | if (!--l) |
1681 | return ptr; | 1682 | return si; |
1682 | } | 1683 | } |
1683 | 1684 | ||
1684 | return NULL; | 1685 | return NULL; |
@@ -1686,21 +1687,21 @@ static void *swap_start(struct seq_file *swap, loff_t *pos) | |||
1686 | 1687 | ||
1687 | static void *swap_next(struct seq_file *swap, void *v, loff_t *pos) | 1688 | static void *swap_next(struct seq_file *swap, void *v, loff_t *pos) |
1688 | { | 1689 | { |
1689 | struct swap_info_struct *ptr; | 1690 | struct swap_info_struct *si = v; |
1690 | struct swap_info_struct *endptr = swap_info + nr_swapfiles; | 1691 | int type; |
1691 | 1692 | ||
1692 | if (v == SEQ_START_TOKEN) | 1693 | if (v == SEQ_START_TOKEN) |
1693 | ptr = swap_info; | 1694 | type = 0; |
1694 | else { | 1695 | else |
1695 | ptr = v; | 1696 | type = si->type + 1; |
1696 | ptr++; | ||
1697 | } | ||
1698 | 1697 | ||
1699 | for (; ptr < endptr; ptr++) { | 1698 | for (; type < nr_swapfiles; type++) { |
1700 | if (!(ptr->flags & SWP_USED) || !ptr->swap_map) | 1699 | smp_rmb(); /* read nr_swapfiles before swap_info[type] */ |
1700 | si = swap_info[type]; | ||
1701 | if (!(si->flags & SWP_USED) || !si->swap_map) | ||
1701 | continue; | 1702 | continue; |
1702 | ++*pos; | 1703 | ++*pos; |
1703 | return ptr; | 1704 | return si; |
1704 | } | 1705 | } |
1705 | 1706 | ||
1706 | return NULL; | 1707 | return NULL; |
@@ -1713,24 +1714,24 @@ static void swap_stop(struct seq_file *swap, void *v) | |||
1713 | 1714 | ||
1714 | static int swap_show(struct seq_file *swap, void *v) | 1715 | static int swap_show(struct seq_file *swap, void *v) |
1715 | { | 1716 | { |
1716 | struct swap_info_struct *ptr = v; | 1717 | struct swap_info_struct *si = v; |
1717 | struct file *file; | 1718 | struct file *file; |
1718 | int len; | 1719 | int len; |
1719 | 1720 | ||
1720 | if (ptr == SEQ_START_TOKEN) { | 1721 | if (si == SEQ_START_TOKEN) { |
1721 | seq_puts(swap,"Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"); | 1722 | seq_puts(swap,"Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"); |
1722 | return 0; | 1723 | return 0; |
1723 | } | 1724 | } |
1724 | 1725 | ||
1725 | file = ptr->swap_file; | 1726 | file = si->swap_file; |
1726 | len = seq_path(swap, &file->f_path, " \t\n\\"); | 1727 | len = seq_path(swap, &file->f_path, " \t\n\\"); |
1727 | seq_printf(swap, "%*s%s\t%u\t%u\t%d\n", | 1728 | seq_printf(swap, "%*s%s\t%u\t%u\t%d\n", |
1728 | len < 40 ? 40 - len : 1, " ", | 1729 | len < 40 ? 40 - len : 1, " ", |
1729 | S_ISBLK(file->f_path.dentry->d_inode->i_mode) ? | 1730 | S_ISBLK(file->f_path.dentry->d_inode->i_mode) ? |
1730 | "partition" : "file\t", | 1731 | "partition" : "file\t", |
1731 | ptr->pages << (PAGE_SHIFT - 10), | 1732 | si->pages << (PAGE_SHIFT - 10), |
1732 | ptr->inuse_pages << (PAGE_SHIFT - 10), | 1733 | si->inuse_pages << (PAGE_SHIFT - 10), |
1733 | ptr->prio); | 1734 | si->prio); |
1734 | return 0; | 1735 | return 0; |
1735 | } | 1736 | } |
1736 | 1737 | ||
@@ -1798,23 +1799,45 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
1798 | 1799 | ||
1799 | if (!capable(CAP_SYS_ADMIN)) | 1800 | if (!capable(CAP_SYS_ADMIN)) |
1800 | return -EPERM; | 1801 | return -EPERM; |
1802 | |||
1803 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
1804 | if (!p) | ||
1805 | return -ENOMEM; | ||
1806 | |||
1801 | spin_lock(&swap_lock); | 1807 | spin_lock(&swap_lock); |
1802 | p = swap_info; | 1808 | for (type = 0; type < nr_swapfiles; type++) { |
1803 | for (type = 0 ; type < nr_swapfiles ; type++,p++) | 1809 | if (!(swap_info[type]->flags & SWP_USED)) |
1804 | if (!(p->flags & SWP_USED)) | ||
1805 | break; | 1810 | break; |
1811 | } | ||
1806 | error = -EPERM; | 1812 | error = -EPERM; |
1807 | if (type >= MAX_SWAPFILES) { | 1813 | if (type >= MAX_SWAPFILES) { |
1808 | spin_unlock(&swap_lock); | 1814 | spin_unlock(&swap_lock); |
1815 | kfree(p); | ||
1809 | goto out; | 1816 | goto out; |
1810 | } | 1817 | } |
1811 | if (type >= nr_swapfiles) | ||
1812 | nr_swapfiles = type+1; | ||
1813 | memset(p, 0, sizeof(*p)); | ||
1814 | INIT_LIST_HEAD(&p->extent_list); | 1818 | INIT_LIST_HEAD(&p->extent_list); |
1819 | if (type >= nr_swapfiles) { | ||
1820 | p->type = type; | ||
1821 | swap_info[type] = p; | ||
1822 | /* | ||
1823 | * Write swap_info[type] before nr_swapfiles, in case a | ||
1824 | * racing procfs swap_start() or swap_next() is reading them. | ||
1825 | * (We never shrink nr_swapfiles, we never free this entry.) | ||
1826 | */ | ||
1827 | smp_wmb(); | ||
1828 | nr_swapfiles++; | ||
1829 | } else { | ||
1830 | kfree(p); | ||
1831 | p = swap_info[type]; | ||
1832 | /* | ||
1833 | * Do not memset this entry: a racing procfs swap_next() | ||
1834 | * would be relying on p->type to remain valid. | ||
1835 | */ | ||
1836 | } | ||
1815 | p->flags = SWP_USED; | 1837 | p->flags = SWP_USED; |
1816 | p->next = -1; | 1838 | p->next = -1; |
1817 | spin_unlock(&swap_lock); | 1839 | spin_unlock(&swap_lock); |
1840 | |||
1818 | name = getname(specialfile); | 1841 | name = getname(specialfile); |
1819 | error = PTR_ERR(name); | 1842 | error = PTR_ERR(name); |
1820 | if (IS_ERR(name)) { | 1843 | if (IS_ERR(name)) { |
@@ -1834,7 +1857,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
1834 | 1857 | ||
1835 | error = -EBUSY; | 1858 | error = -EBUSY; |
1836 | for (i = 0; i < nr_swapfiles; i++) { | 1859 | for (i = 0; i < nr_swapfiles; i++) { |
1837 | struct swap_info_struct *q = &swap_info[i]; | 1860 | struct swap_info_struct *q = swap_info[i]; |
1838 | 1861 | ||
1839 | if (i == type || !q->swap_file) | 1862 | if (i == type || !q->swap_file) |
1840 | continue; | 1863 | continue; |
@@ -1909,6 +1932,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
1909 | 1932 | ||
1910 | p->lowest_bit = 1; | 1933 | p->lowest_bit = 1; |
1911 | p->cluster_next = 1; | 1934 | p->cluster_next = 1; |
1935 | p->cluster_nr = 0; | ||
1912 | 1936 | ||
1913 | /* | 1937 | /* |
1914 | * Find out how many pages are allowed for a single swap | 1938 | * Find out how many pages are allowed for a single swap |
@@ -2015,18 +2039,16 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
2015 | 2039 | ||
2016 | /* insert swap space into swap_list: */ | 2040 | /* insert swap space into swap_list: */ |
2017 | prev = -1; | 2041 | prev = -1; |
2018 | for (i = swap_list.head; i >= 0; i = swap_info[i].next) { | 2042 | for (i = swap_list.head; i >= 0; i = swap_info[i]->next) { |
2019 | if (p->prio >= swap_info[i].prio) { | 2043 | if (p->prio >= swap_info[i]->prio) |
2020 | break; | 2044 | break; |
2021 | } | ||
2022 | prev = i; | 2045 | prev = i; |
2023 | } | 2046 | } |
2024 | p->next = i; | 2047 | p->next = i; |
2025 | if (prev < 0) { | 2048 | if (prev < 0) |
2026 | swap_list.head = swap_list.next = p - swap_info; | 2049 | swap_list.head = swap_list.next = type; |
2027 | } else { | 2050 | else |
2028 | swap_info[prev].next = p - swap_info; | 2051 | swap_info[prev]->next = type; |
2029 | } | ||
2030 | spin_unlock(&swap_lock); | 2052 | spin_unlock(&swap_lock); |
2031 | mutex_unlock(&swapon_mutex); | 2053 | mutex_unlock(&swapon_mutex); |
2032 | error = 0; | 2054 | error = 0; |
@@ -2063,15 +2085,15 @@ out: | |||
2063 | 2085 | ||
2064 | void si_swapinfo(struct sysinfo *val) | 2086 | void si_swapinfo(struct sysinfo *val) |
2065 | { | 2087 | { |
2066 | unsigned int i; | 2088 | unsigned int type; |
2067 | unsigned long nr_to_be_unused = 0; | 2089 | unsigned long nr_to_be_unused = 0; |
2068 | 2090 | ||
2069 | spin_lock(&swap_lock); | 2091 | spin_lock(&swap_lock); |
2070 | for (i = 0; i < nr_swapfiles; i++) { | 2092 | for (type = 0; type < nr_swapfiles; type++) { |
2071 | if (!(swap_info[i].flags & SWP_USED) || | 2093 | struct swap_info_struct *si = swap_info[type]; |
2072 | (swap_info[i].flags & SWP_WRITEOK)) | 2094 | |
2073 | continue; | 2095 | if ((si->flags & SWP_USED) && !(si->flags & SWP_WRITEOK)) |
2074 | nr_to_be_unused += swap_info[i].inuse_pages; | 2096 | nr_to_be_unused += si->inuse_pages; |
2075 | } | 2097 | } |
2076 | val->freeswap = nr_swap_pages + nr_to_be_unused; | 2098 | val->freeswap = nr_swap_pages + nr_to_be_unused; |
2077 | val->totalswap = total_swap_pages + nr_to_be_unused; | 2099 | val->totalswap = total_swap_pages + nr_to_be_unused; |
@@ -2104,7 +2126,7 @@ static int __swap_duplicate(swp_entry_t entry, bool cache) | |||
2104 | type = swp_type(entry); | 2126 | type = swp_type(entry); |
2105 | if (type >= nr_swapfiles) | 2127 | if (type >= nr_swapfiles) |
2106 | goto bad_file; | 2128 | goto bad_file; |
2107 | p = type + swap_info; | 2129 | p = swap_info[type]; |
2108 | offset = swp_offset(entry); | 2130 | offset = swp_offset(entry); |
2109 | 2131 | ||
2110 | spin_lock(&swap_lock); | 2132 | spin_lock(&swap_lock); |
@@ -2186,7 +2208,7 @@ int valid_swaphandles(swp_entry_t entry, unsigned long *offset) | |||
2186 | if (!our_page_cluster) /* no readahead */ | 2208 | if (!our_page_cluster) /* no readahead */ |
2187 | return 0; | 2209 | return 0; |
2188 | 2210 | ||
2189 | si = &swap_info[swp_type(entry)]; | 2211 | si = swap_info[swp_type(entry)]; |
2190 | target = swp_offset(entry); | 2212 | target = swp_offset(entry); |
2191 | base = (target >> our_page_cluster) << our_page_cluster; | 2213 | base = (target >> our_page_cluster) << our_page_cluster; |
2192 | end = base + (1 << our_page_cluster); | 2214 | end = base + (1 << our_page_cluster); |