diff options
author | Cesar Eduardo Barros <cesarb@cesarb.net> | 2011-03-22 19:33:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-22 20:44:08 -0400 |
commit | 40531542e2832419566c997af0808513f6f2815d (patch) | |
tree | 06e0bb32e53447f58a1821af1c4e960edbd97b0d /mm/swapfile.c | |
parent | c6a2b64ba5d09a1e281e85988ffd650655fa0f39 (diff) |
sys_swapon: separate final enabling of the swapfile
The block in sys_swapon which does the final adjustments to the
swap_info_struct and to swap_list is the same as the block which
re-inserts it again at sys_swapoff on failure of try_to_unuse(). Move
this code to a separate function, and use it both in sys_swapon and
sys_swapoff.
Signed-off-by: Cesar Eduardo Barros <cesarb@cesarb.net>
Tested-by: Eric B Munson <emunson@mgebm.net>
Acked-by: Eric B Munson <emunson@mgebm.net>
Reviewed-by: Pekka Enberg <penberg@kernel.org>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Hugh Dickins <hughd@google.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 | 84 |
1 files changed, 42 insertions, 42 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index 465d972f4c7c..7243044c4139 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -1550,6 +1550,36 @@ bad_bmap: | |||
1550 | goto out; | 1550 | goto out; |
1551 | } | 1551 | } |
1552 | 1552 | ||
1553 | static void enable_swap_info(struct swap_info_struct *p, int prio, | ||
1554 | unsigned char *swap_map) | ||
1555 | { | ||
1556 | int i, prev; | ||
1557 | |||
1558 | spin_lock(&swap_lock); | ||
1559 | if (prio >= 0) | ||
1560 | p->prio = prio; | ||
1561 | else | ||
1562 | p->prio = --least_priority; | ||
1563 | p->swap_map = swap_map; | ||
1564 | p->flags |= SWP_WRITEOK; | ||
1565 | nr_swap_pages += p->pages; | ||
1566 | total_swap_pages += p->pages; | ||
1567 | |||
1568 | /* insert swap space into swap_list: */ | ||
1569 | prev = -1; | ||
1570 | for (i = swap_list.head; i >= 0; i = swap_info[i]->next) { | ||
1571 | if (p->prio >= swap_info[i]->prio) | ||
1572 | break; | ||
1573 | prev = i; | ||
1574 | } | ||
1575 | p->next = i; | ||
1576 | if (prev < 0) | ||
1577 | swap_list.head = swap_list.next = p->type; | ||
1578 | else | ||
1579 | swap_info[prev]->next = p->type; | ||
1580 | spin_unlock(&swap_lock); | ||
1581 | } | ||
1582 | |||
1553 | SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | 1583 | SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) |
1554 | { | 1584 | { |
1555 | struct swap_info_struct *p = NULL; | 1585 | struct swap_info_struct *p = NULL; |
@@ -1621,26 +1651,14 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | |||
1621 | current->flags &= ~PF_OOM_ORIGIN; | 1651 | current->flags &= ~PF_OOM_ORIGIN; |
1622 | 1652 | ||
1623 | if (err) { | 1653 | if (err) { |
1654 | /* | ||
1655 | * reading p->prio and p->swap_map outside the lock is | ||
1656 | * safe here because only sys_swapon and sys_swapoff | ||
1657 | * change them, and there can be no other sys_swapon or | ||
1658 | * sys_swapoff for this swap_info_struct at this point. | ||
1659 | */ | ||
1624 | /* re-insert swap space back into swap_list */ | 1660 | /* re-insert swap space back into swap_list */ |
1625 | spin_lock(&swap_lock); | 1661 | enable_swap_info(p, p->prio, p->swap_map); |
1626 | if (p->prio < 0) | ||
1627 | p->prio = --least_priority; | ||
1628 | p->flags |= SWP_WRITEOK; | ||
1629 | nr_swap_pages += p->pages; | ||
1630 | total_swap_pages += p->pages; | ||
1631 | |||
1632 | prev = -1; | ||
1633 | for (i = swap_list.head; i >= 0; i = swap_info[i]->next) { | ||
1634 | if (p->prio >= swap_info[i]->prio) | ||
1635 | break; | ||
1636 | prev = i; | ||
1637 | } | ||
1638 | p->next = i; | ||
1639 | if (prev < 0) | ||
1640 | swap_list.head = swap_list.next = type; | ||
1641 | else | ||
1642 | swap_info[prev]->next = type; | ||
1643 | spin_unlock(&swap_lock); | ||
1644 | goto out_dput; | 1662 | goto out_dput; |
1645 | } | 1663 | } |
1646 | 1664 | ||
@@ -2037,7 +2055,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
2037 | char *name; | 2055 | char *name; |
2038 | struct file *swap_file = NULL; | 2056 | struct file *swap_file = NULL; |
2039 | struct address_space *mapping; | 2057 | struct address_space *mapping; |
2040 | int i, prev; | 2058 | int i; |
2059 | int prio; | ||
2041 | int error; | 2060 | int error; |
2042 | union swap_header *swap_header; | 2061 | union swap_header *swap_header; |
2043 | int nr_extents; | 2062 | int nr_extents; |
@@ -2134,30 +2153,11 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
2134 | } | 2153 | } |
2135 | 2154 | ||
2136 | mutex_lock(&swapon_mutex); | 2155 | mutex_lock(&swapon_mutex); |
2137 | spin_lock(&swap_lock); | 2156 | prio = -1; |
2138 | if (swap_flags & SWAP_FLAG_PREFER) | 2157 | if (swap_flags & SWAP_FLAG_PREFER) |
2139 | p->prio = | 2158 | prio = |
2140 | (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT; | 2159 | (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT; |
2141 | else | 2160 | enable_swap_info(p, prio, swap_map); |
2142 | p->prio = --least_priority; | ||
2143 | p->swap_map = swap_map; | ||
2144 | p->flags |= SWP_WRITEOK; | ||
2145 | nr_swap_pages += p->pages; | ||
2146 | total_swap_pages += p->pages; | ||
2147 | |||
2148 | /* insert swap space into swap_list: */ | ||
2149 | prev = -1; | ||
2150 | for (i = swap_list.head; i >= 0; i = swap_info[i]->next) { | ||
2151 | if (p->prio >= swap_info[i]->prio) | ||
2152 | break; | ||
2153 | prev = i; | ||
2154 | } | ||
2155 | p->next = i; | ||
2156 | if (prev < 0) | ||
2157 | swap_list.head = swap_list.next = p->type; | ||
2158 | else | ||
2159 | swap_info[prev]->next = p->type; | ||
2160 | spin_unlock(&swap_lock); | ||
2161 | 2161 | ||
2162 | printk(KERN_INFO "Adding %uk swap on %s. " | 2162 | printk(KERN_INFO "Adding %uk swap on %s. " |
2163 | "Priority:%d extents:%d across:%lluk %s%s\n", | 2163 | "Priority:%d extents:%d across:%lluk %s%s\n", |