diff options
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r-- | mm/swapfile.c | 412 |
1 files changed, 223 insertions, 189 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index 60cd24a55204..4b6e8bf986bc 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <asm/tlbflush.h> | 31 | #include <asm/tlbflush.h> |
32 | #include <linux/swapops.h> | 32 | #include <linux/swapops.h> |
33 | 33 | ||
34 | DEFINE_SPINLOCK(swaplock); | 34 | DEFINE_SPINLOCK(swap_lock); |
35 | unsigned int nr_swapfiles; | 35 | unsigned int nr_swapfiles; |
36 | long total_swap_pages; | 36 | long total_swap_pages; |
37 | static int swap_overflow; | 37 | static int swap_overflow; |
@@ -51,13 +51,11 @@ static DECLARE_MUTEX(swapon_sem); | |||
51 | 51 | ||
52 | /* | 52 | /* |
53 | * We need this because the bdev->unplug_fn can sleep and we cannot | 53 | * We need this because the bdev->unplug_fn can sleep and we cannot |
54 | * hold swap_list_lock while calling the unplug_fn. And swap_list_lock | 54 | * hold swap_lock while calling the unplug_fn. And swap_lock |
55 | * cannot be turned into a semaphore. | 55 | * cannot be turned into a semaphore. |
56 | */ | 56 | */ |
57 | static DECLARE_RWSEM(swap_unplug_sem); | 57 | static DECLARE_RWSEM(swap_unplug_sem); |
58 | 58 | ||
59 | #define SWAPFILE_CLUSTER 256 | ||
60 | |||
61 | void swap_unplug_io_fn(struct backing_dev_info *unused_bdi, struct page *page) | 59 | void swap_unplug_io_fn(struct backing_dev_info *unused_bdi, struct page *page) |
62 | { | 60 | { |
63 | swp_entry_t entry; | 61 | swp_entry_t entry; |
@@ -84,116 +82,135 @@ void swap_unplug_io_fn(struct backing_dev_info *unused_bdi, struct page *page) | |||
84 | up_read(&swap_unplug_sem); | 82 | up_read(&swap_unplug_sem); |
85 | } | 83 | } |
86 | 84 | ||
87 | static inline int scan_swap_map(struct swap_info_struct *si) | 85 | #define SWAPFILE_CLUSTER 256 |
86 | #define LATENCY_LIMIT 256 | ||
87 | |||
88 | static inline unsigned long scan_swap_map(struct swap_info_struct *si) | ||
88 | { | 89 | { |
89 | unsigned long offset; | 90 | unsigned long offset, last_in_cluster; |
91 | int latency_ration = LATENCY_LIMIT; | ||
92 | |||
90 | /* | 93 | /* |
91 | * We try to cluster swap pages by allocating them | 94 | * We try to cluster swap pages by allocating them sequentially |
92 | * sequentially in swap. Once we've allocated | 95 | * in swap. Once we've allocated SWAPFILE_CLUSTER pages this |
93 | * SWAPFILE_CLUSTER pages this way, however, we resort to | 96 | * way, however, we resort to first-free allocation, starting |
94 | * first-free allocation, starting a new cluster. This | 97 | * a new cluster. This prevents us from scattering swap pages |
95 | * prevents us from scattering swap pages all over the entire | 98 | * all over the entire swap partition, so that we reduce |
96 | * swap partition, so that we reduce overall disk seek times | 99 | * overall disk seek times between swap pages. -- sct |
97 | * between swap pages. -- sct */ | 100 | * But we do now try to find an empty cluster. -Andrea |
98 | if (si->cluster_nr) { | 101 | */ |
99 | while (si->cluster_next <= si->highest_bit) { | 102 | |
100 | offset = si->cluster_next++; | 103 | si->flags += SWP_SCANNING; |
104 | if (unlikely(!si->cluster_nr)) { | ||
105 | si->cluster_nr = SWAPFILE_CLUSTER - 1; | ||
106 | if (si->pages - si->inuse_pages < SWAPFILE_CLUSTER) | ||
107 | goto lowest; | ||
108 | spin_unlock(&swap_lock); | ||
109 | |||
110 | offset = si->lowest_bit; | ||
111 | last_in_cluster = offset + SWAPFILE_CLUSTER - 1; | ||
112 | |||
113 | /* Locate the first empty (unaligned) cluster */ | ||
114 | for (; last_in_cluster <= si->highest_bit; offset++) { | ||
101 | if (si->swap_map[offset]) | 115 | if (si->swap_map[offset]) |
102 | continue; | 116 | last_in_cluster = offset + SWAPFILE_CLUSTER; |
103 | si->cluster_nr--; | 117 | else if (offset == last_in_cluster) { |
104 | goto got_page; | 118 | spin_lock(&swap_lock); |
105 | } | 119 | si->cluster_next = offset-SWAPFILE_CLUSTER-1; |
106 | } | 120 | goto cluster; |
107 | si->cluster_nr = SWAPFILE_CLUSTER; | ||
108 | |||
109 | /* try to find an empty (even not aligned) cluster. */ | ||
110 | offset = si->lowest_bit; | ||
111 | check_next_cluster: | ||
112 | if (offset+SWAPFILE_CLUSTER-1 <= si->highest_bit) | ||
113 | { | ||
114 | unsigned long nr; | ||
115 | for (nr = offset; nr < offset+SWAPFILE_CLUSTER; nr++) | ||
116 | if (si->swap_map[nr]) | ||
117 | { | ||
118 | offset = nr+1; | ||
119 | goto check_next_cluster; | ||
120 | } | 121 | } |
121 | /* We found a completly empty cluster, so start | 122 | if (unlikely(--latency_ration < 0)) { |
122 | * using it. | 123 | cond_resched(); |
123 | */ | 124 | latency_ration = LATENCY_LIMIT; |
124 | goto got_page; | 125 | } |
126 | } | ||
127 | spin_lock(&swap_lock); | ||
128 | goto lowest; | ||
125 | } | 129 | } |
126 | /* No luck, so now go finegrined as usual. -Andrea */ | 130 | |
127 | for (offset = si->lowest_bit; offset <= si->highest_bit ; offset++) { | 131 | si->cluster_nr--; |
128 | if (si->swap_map[offset]) | 132 | cluster: |
129 | continue; | 133 | offset = si->cluster_next; |
130 | si->lowest_bit = offset+1; | 134 | if (offset > si->highest_bit) |
131 | got_page: | 135 | lowest: offset = si->lowest_bit; |
136 | checks: if (!(si->flags & SWP_WRITEOK)) | ||
137 | goto no_page; | ||
138 | if (!si->highest_bit) | ||
139 | goto no_page; | ||
140 | if (!si->swap_map[offset]) { | ||
132 | if (offset == si->lowest_bit) | 141 | if (offset == si->lowest_bit) |
133 | si->lowest_bit++; | 142 | si->lowest_bit++; |
134 | if (offset == si->highest_bit) | 143 | if (offset == si->highest_bit) |
135 | si->highest_bit--; | 144 | si->highest_bit--; |
136 | if (si->lowest_bit > si->highest_bit) { | 145 | si->inuse_pages++; |
146 | if (si->inuse_pages == si->pages) { | ||
137 | si->lowest_bit = si->max; | 147 | si->lowest_bit = si->max; |
138 | si->highest_bit = 0; | 148 | si->highest_bit = 0; |
139 | } | 149 | } |
140 | si->swap_map[offset] = 1; | 150 | si->swap_map[offset] = 1; |
141 | si->inuse_pages++; | 151 | si->cluster_next = offset + 1; |
142 | nr_swap_pages--; | 152 | si->flags -= SWP_SCANNING; |
143 | si->cluster_next = offset+1; | ||
144 | return offset; | 153 | return offset; |
145 | } | 154 | } |
146 | si->lowest_bit = si->max; | 155 | |
147 | si->highest_bit = 0; | 156 | spin_unlock(&swap_lock); |
157 | while (++offset <= si->highest_bit) { | ||
158 | if (!si->swap_map[offset]) { | ||
159 | spin_lock(&swap_lock); | ||
160 | goto checks; | ||
161 | } | ||
162 | if (unlikely(--latency_ration < 0)) { | ||
163 | cond_resched(); | ||
164 | latency_ration = LATENCY_LIMIT; | ||
165 | } | ||
166 | } | ||
167 | spin_lock(&swap_lock); | ||
168 | goto lowest; | ||
169 | |||
170 | no_page: | ||
171 | si->flags -= SWP_SCANNING; | ||
148 | return 0; | 172 | return 0; |
149 | } | 173 | } |
150 | 174 | ||
151 | swp_entry_t get_swap_page(void) | 175 | swp_entry_t get_swap_page(void) |
152 | { | 176 | { |
153 | struct swap_info_struct * p; | 177 | struct swap_info_struct *si; |
154 | unsigned long offset; | 178 | pgoff_t offset; |
155 | swp_entry_t entry; | 179 | int type, next; |
156 | int type, wrapped = 0; | 180 | int wrapped = 0; |
157 | 181 | ||
158 | entry.val = 0; /* Out of memory */ | 182 | spin_lock(&swap_lock); |
159 | swap_list_lock(); | ||
160 | type = swap_list.next; | ||
161 | if (type < 0) | ||
162 | goto out; | ||
163 | if (nr_swap_pages <= 0) | 183 | if (nr_swap_pages <= 0) |
164 | goto out; | 184 | goto noswap; |
185 | nr_swap_pages--; | ||
186 | |||
187 | for (type = swap_list.next; type >= 0 && wrapped < 2; type = next) { | ||
188 | si = swap_info + type; | ||
189 | next = si->next; | ||
190 | if (next < 0 || | ||
191 | (!wrapped && si->prio != swap_info[next].prio)) { | ||
192 | next = swap_list.head; | ||
193 | wrapped++; | ||
194 | } | ||
165 | 195 | ||
166 | while (1) { | 196 | if (!si->highest_bit) |
167 | p = &swap_info[type]; | 197 | continue; |
168 | if ((p->flags & SWP_ACTIVE) == SWP_ACTIVE) { | 198 | if (!(si->flags & SWP_WRITEOK)) |
169 | swap_device_lock(p); | 199 | continue; |
170 | offset = scan_swap_map(p); | 200 | |
171 | swap_device_unlock(p); | 201 | swap_list.next = next; |
172 | if (offset) { | 202 | offset = scan_swap_map(si); |
173 | entry = swp_entry(type,offset); | 203 | if (offset) { |
174 | type = swap_info[type].next; | 204 | spin_unlock(&swap_lock); |
175 | if (type < 0 || | 205 | return swp_entry(type, offset); |
176 | p->prio != swap_info[type].prio) { | ||
177 | swap_list.next = swap_list.head; | ||
178 | } else { | ||
179 | swap_list.next = type; | ||
180 | } | ||
181 | goto out; | ||
182 | } | ||
183 | } | 206 | } |
184 | type = p->next; | 207 | next = swap_list.next; |
185 | if (!wrapped) { | ||
186 | if (type < 0 || p->prio != swap_info[type].prio) { | ||
187 | type = swap_list.head; | ||
188 | wrapped = 1; | ||
189 | } | ||
190 | } else | ||
191 | if (type < 0) | ||
192 | goto out; /* out of swap space */ | ||
193 | } | 208 | } |
194 | out: | 209 | |
195 | swap_list_unlock(); | 210 | nr_swap_pages++; |
196 | return entry; | 211 | noswap: |
212 | spin_unlock(&swap_lock); | ||
213 | return (swp_entry_t) {0}; | ||
197 | } | 214 | } |
198 | 215 | ||
199 | static struct swap_info_struct * swap_info_get(swp_entry_t entry) | 216 | static struct swap_info_struct * swap_info_get(swp_entry_t entry) |
@@ -214,10 +231,7 @@ static struct swap_info_struct * swap_info_get(swp_entry_t entry) | |||
214 | goto bad_offset; | 231 | goto bad_offset; |
215 | if (!p->swap_map[offset]) | 232 | if (!p->swap_map[offset]) |
216 | goto bad_free; | 233 | goto bad_free; |
217 | swap_list_lock(); | 234 | spin_lock(&swap_lock); |
218 | if (p->prio > swap_info[swap_list.next].prio) | ||
219 | swap_list.next = type; | ||
220 | swap_device_lock(p); | ||
221 | return p; | 235 | return p; |
222 | 236 | ||
223 | bad_free: | 237 | bad_free: |
@@ -235,12 +249,6 @@ out: | |||
235 | return NULL; | 249 | return NULL; |
236 | } | 250 | } |
237 | 251 | ||
238 | static void swap_info_put(struct swap_info_struct * p) | ||
239 | { | ||
240 | swap_device_unlock(p); | ||
241 | swap_list_unlock(); | ||
242 | } | ||
243 | |||
244 | static int swap_entry_free(struct swap_info_struct *p, unsigned long offset) | 252 | static int swap_entry_free(struct swap_info_struct *p, unsigned long offset) |
245 | { | 253 | { |
246 | int count = p->swap_map[offset]; | 254 | int count = p->swap_map[offset]; |
@@ -253,6 +261,8 @@ static int swap_entry_free(struct swap_info_struct *p, unsigned long offset) | |||
253 | p->lowest_bit = offset; | 261 | p->lowest_bit = offset; |
254 | if (offset > p->highest_bit) | 262 | if (offset > p->highest_bit) |
255 | p->highest_bit = offset; | 263 | p->highest_bit = offset; |
264 | if (p->prio > swap_info[swap_list.next].prio) | ||
265 | swap_list.next = p - swap_info; | ||
256 | nr_swap_pages++; | 266 | nr_swap_pages++; |
257 | p->inuse_pages--; | 267 | p->inuse_pages--; |
258 | } | 268 | } |
@@ -271,7 +281,7 @@ void swap_free(swp_entry_t entry) | |||
271 | p = swap_info_get(entry); | 281 | p = swap_info_get(entry); |
272 | if (p) { | 282 | if (p) { |
273 | swap_entry_free(p, swp_offset(entry)); | 283 | swap_entry_free(p, swp_offset(entry)); |
274 | swap_info_put(p); | 284 | spin_unlock(&swap_lock); |
275 | } | 285 | } |
276 | } | 286 | } |
277 | 287 | ||
@@ -289,7 +299,7 @@ static inline int page_swapcount(struct page *page) | |||
289 | if (p) { | 299 | if (p) { |
290 | /* Subtract the 1 for the swap cache itself */ | 300 | /* Subtract the 1 for the swap cache itself */ |
291 | count = p->swap_map[swp_offset(entry)] - 1; | 301 | count = p->swap_map[swp_offset(entry)] - 1; |
292 | swap_info_put(p); | 302 | spin_unlock(&swap_lock); |
293 | } | 303 | } |
294 | return count; | 304 | return count; |
295 | } | 305 | } |
@@ -346,7 +356,7 @@ int remove_exclusive_swap_page(struct page *page) | |||
346 | } | 356 | } |
347 | write_unlock_irq(&swapper_space.tree_lock); | 357 | write_unlock_irq(&swapper_space.tree_lock); |
348 | } | 358 | } |
349 | swap_info_put(p); | 359 | spin_unlock(&swap_lock); |
350 | 360 | ||
351 | if (retval) { | 361 | if (retval) { |
352 | swap_free(entry); | 362 | swap_free(entry); |
@@ -369,7 +379,7 @@ void free_swap_and_cache(swp_entry_t entry) | |||
369 | if (p) { | 379 | if (p) { |
370 | if (swap_entry_free(p, swp_offset(entry)) == 1) | 380 | if (swap_entry_free(p, swp_offset(entry)) == 1) |
371 | page = find_trylock_page(&swapper_space, entry.val); | 381 | page = find_trylock_page(&swapper_space, entry.val); |
372 | swap_info_put(p); | 382 | spin_unlock(&swap_lock); |
373 | } | 383 | } |
374 | if (page) { | 384 | if (page) { |
375 | int one_user; | 385 | int one_user; |
@@ -531,17 +541,18 @@ static int unuse_mm(struct mm_struct *mm, | |||
531 | * Scan swap_map from current position to next entry still in use. | 541 | * Scan swap_map from current position to next entry still in use. |
532 | * Recycle to start on reaching the end, returning 0 when empty. | 542 | * Recycle to start on reaching the end, returning 0 when empty. |
533 | */ | 543 | */ |
534 | static int find_next_to_unuse(struct swap_info_struct *si, int prev) | 544 | static unsigned int find_next_to_unuse(struct swap_info_struct *si, |
545 | unsigned int prev) | ||
535 | { | 546 | { |
536 | int max = si->max; | 547 | unsigned int max = si->max; |
537 | int i = prev; | 548 | unsigned int i = prev; |
538 | int count; | 549 | int count; |
539 | 550 | ||
540 | /* | 551 | /* |
541 | * No need for swap_device_lock(si) here: we're just looking | 552 | * No need for swap_lock here: we're just looking |
542 | * for whether an entry is in use, not modifying it; false | 553 | * for whether an entry is in use, not modifying it; false |
543 | * hits are okay, and sys_swapoff() has already prevented new | 554 | * hits are okay, and sys_swapoff() has already prevented new |
544 | * allocations from this area (while holding swap_list_lock()). | 555 | * allocations from this area (while holding swap_lock). |
545 | */ | 556 | */ |
546 | for (;;) { | 557 | for (;;) { |
547 | if (++i >= max) { | 558 | if (++i >= max) { |
@@ -577,7 +588,7 @@ static int try_to_unuse(unsigned int type) | |||
577 | unsigned short swcount; | 588 | unsigned short swcount; |
578 | struct page *page; | 589 | struct page *page; |
579 | swp_entry_t entry; | 590 | swp_entry_t entry; |
580 | int i = 0; | 591 | unsigned int i = 0; |
581 | int retval = 0; | 592 | int retval = 0; |
582 | int reset_overflow = 0; | 593 | int reset_overflow = 0; |
583 | int shmem; | 594 | int shmem; |
@@ -731,9 +742,9 @@ static int try_to_unuse(unsigned int type) | |||
731 | * report them; but do report if we reset SWAP_MAP_MAX. | 742 | * report them; but do report if we reset SWAP_MAP_MAX. |
732 | */ | 743 | */ |
733 | if (*swap_map == SWAP_MAP_MAX) { | 744 | if (*swap_map == SWAP_MAP_MAX) { |
734 | swap_device_lock(si); | 745 | spin_lock(&swap_lock); |
735 | *swap_map = 1; | 746 | *swap_map = 1; |
736 | swap_device_unlock(si); | 747 | spin_unlock(&swap_lock); |
737 | reset_overflow = 1; | 748 | reset_overflow = 1; |
738 | } | 749 | } |
739 | 750 | ||
@@ -797,9 +808,9 @@ static int try_to_unuse(unsigned int type) | |||
797 | } | 808 | } |
798 | 809 | ||
799 | /* | 810 | /* |
800 | * After a successful try_to_unuse, if no swap is now in use, we know we | 811 | * After a successful try_to_unuse, if no swap is now in use, we know |
801 | * can empty the mmlist. swap_list_lock must be held on entry and exit. | 812 | * we can empty the mmlist. swap_lock must be held on entry and exit. |
802 | * Note that mmlist_lock nests inside swap_list_lock, and an mm must be | 813 | * Note that mmlist_lock nests inside swap_lock, and an mm must be |
803 | * added to the mmlist just after page_duplicate - before would be racy. | 814 | * added to the mmlist just after page_duplicate - before would be racy. |
804 | */ | 815 | */ |
805 | static void drain_mmlist(void) | 816 | static void drain_mmlist(void) |
@@ -832,9 +843,9 @@ sector_t map_swap_page(struct swap_info_struct *sis, pgoff_t offset) | |||
832 | offset < (se->start_page + se->nr_pages)) { | 843 | offset < (se->start_page + se->nr_pages)) { |
833 | return se->start_block + (offset - se->start_page); | 844 | return se->start_block + (offset - se->start_page); |
834 | } | 845 | } |
835 | lh = se->list.prev; | 846 | lh = se->list.next; |
836 | if (lh == &sis->extent_list) | 847 | if (lh == &sis->extent_list) |
837 | lh = lh->prev; | 848 | lh = lh->next; |
838 | se = list_entry(lh, struct swap_extent, list); | 849 | se = list_entry(lh, struct swap_extent, list); |
839 | sis->curr_swap_extent = se; | 850 | sis->curr_swap_extent = se; |
840 | BUG_ON(se == start_se); /* It *must* be present */ | 851 | BUG_ON(se == start_se); /* It *must* be present */ |
@@ -854,15 +865,13 @@ static void destroy_swap_extents(struct swap_info_struct *sis) | |||
854 | list_del(&se->list); | 865 | list_del(&se->list); |
855 | kfree(se); | 866 | kfree(se); |
856 | } | 867 | } |
857 | sis->nr_extents = 0; | ||
858 | } | 868 | } |
859 | 869 | ||
860 | /* | 870 | /* |
861 | * Add a block range (and the corresponding page range) into this swapdev's | 871 | * Add a block range (and the corresponding page range) into this swapdev's |
862 | * extent list. The extent list is kept sorted in block order. | 872 | * extent list. The extent list is kept sorted in page order. |
863 | * | 873 | * |
864 | * This function rather assumes that it is called in ascending sector_t order. | 874 | * This function rather assumes that it is called in ascending page order. |
865 | * It doesn't look for extent coalescing opportunities. | ||
866 | */ | 875 | */ |
867 | static int | 876 | static int |
868 | add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | 877 | add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, |
@@ -872,16 +881,15 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | |||
872 | struct swap_extent *new_se; | 881 | struct swap_extent *new_se; |
873 | struct list_head *lh; | 882 | struct list_head *lh; |
874 | 883 | ||
875 | lh = sis->extent_list.next; /* The highest-addressed block */ | 884 | lh = sis->extent_list.prev; /* The highest page extent */ |
876 | while (lh != &sis->extent_list) { | 885 | if (lh != &sis->extent_list) { |
877 | se = list_entry(lh, struct swap_extent, list); | 886 | se = list_entry(lh, struct swap_extent, list); |
878 | if (se->start_block + se->nr_pages == start_block && | 887 | BUG_ON(se->start_page + se->nr_pages != start_page); |
879 | se->start_page + se->nr_pages == start_page) { | 888 | if (se->start_block + se->nr_pages == start_block) { |
880 | /* Merge it */ | 889 | /* Merge it */ |
881 | se->nr_pages += nr_pages; | 890 | se->nr_pages += nr_pages; |
882 | return 0; | 891 | return 0; |
883 | } | 892 | } |
884 | lh = lh->next; | ||
885 | } | 893 | } |
886 | 894 | ||
887 | /* | 895 | /* |
@@ -894,16 +902,8 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | |||
894 | new_se->nr_pages = nr_pages; | 902 | new_se->nr_pages = nr_pages; |
895 | new_se->start_block = start_block; | 903 | new_se->start_block = start_block; |
896 | 904 | ||
897 | lh = sis->extent_list.prev; /* The lowest block */ | 905 | list_add_tail(&new_se->list, &sis->extent_list); |
898 | while (lh != &sis->extent_list) { | 906 | return 1; |
899 | se = list_entry(lh, struct swap_extent, list); | ||
900 | if (se->start_block > start_block) | ||
901 | break; | ||
902 | lh = lh->prev; | ||
903 | } | ||
904 | list_add_tail(&new_se->list, lh); | ||
905 | sis->nr_extents++; | ||
906 | return 0; | ||
907 | } | 907 | } |
908 | 908 | ||
909 | /* | 909 | /* |
@@ -926,7 +926,7 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | |||
926 | * requirements, they are simply tossed out - we will never use those blocks | 926 | * requirements, they are simply tossed out - we will never use those blocks |
927 | * for swapping. | 927 | * for swapping. |
928 | * | 928 | * |
929 | * For S_ISREG swapfiles we hold i_sem across the life of the swapon. This | 929 | * For S_ISREG swapfiles we set S_SWAPFILE across the life of the swapon. This |
930 | * prevents root from shooting her foot off by ftruncating an in-use swapfile, | 930 | * prevents root from shooting her foot off by ftruncating an in-use swapfile, |
931 | * which will scribble on the fs. | 931 | * which will scribble on the fs. |
932 | * | 932 | * |
@@ -937,7 +937,7 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | |||
937 | * This is extremely effective. The average number of iterations in | 937 | * This is extremely effective. The average number of iterations in |
938 | * map_swap_page() has been measured at about 0.3 per page. - akpm. | 938 | * map_swap_page() has been measured at about 0.3 per page. - akpm. |
939 | */ | 939 | */ |
940 | static int setup_swap_extents(struct swap_info_struct *sis) | 940 | static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span) |
941 | { | 941 | { |
942 | struct inode *inode; | 942 | struct inode *inode; |
943 | unsigned blocks_per_page; | 943 | unsigned blocks_per_page; |
@@ -945,11 +945,15 @@ static int setup_swap_extents(struct swap_info_struct *sis) | |||
945 | unsigned blkbits; | 945 | unsigned blkbits; |
946 | sector_t probe_block; | 946 | sector_t probe_block; |
947 | sector_t last_block; | 947 | sector_t last_block; |
948 | sector_t lowest_block = -1; | ||
949 | sector_t highest_block = 0; | ||
950 | int nr_extents = 0; | ||
948 | int ret; | 951 | int ret; |
949 | 952 | ||
950 | inode = sis->swap_file->f_mapping->host; | 953 | inode = sis->swap_file->f_mapping->host; |
951 | if (S_ISBLK(inode->i_mode)) { | 954 | if (S_ISBLK(inode->i_mode)) { |
952 | ret = add_swap_extent(sis, 0, sis->max, 0); | 955 | ret = add_swap_extent(sis, 0, sis->max, 0); |
956 | *span = sis->pages; | ||
953 | goto done; | 957 | goto done; |
954 | } | 958 | } |
955 | 959 | ||
@@ -994,22 +998,32 @@ static int setup_swap_extents(struct swap_info_struct *sis) | |||
994 | } | 998 | } |
995 | } | 999 | } |
996 | 1000 | ||
1001 | first_block >>= (PAGE_SHIFT - blkbits); | ||
1002 | if (page_no) { /* exclude the header page */ | ||
1003 | if (first_block < lowest_block) | ||
1004 | lowest_block = first_block; | ||
1005 | if (first_block > highest_block) | ||
1006 | highest_block = first_block; | ||
1007 | } | ||
1008 | |||
997 | /* | 1009 | /* |
998 | * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks | 1010 | * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks |
999 | */ | 1011 | */ |
1000 | ret = add_swap_extent(sis, page_no, 1, | 1012 | ret = add_swap_extent(sis, page_no, 1, first_block); |
1001 | first_block >> (PAGE_SHIFT - blkbits)); | 1013 | if (ret < 0) |
1002 | if (ret) | ||
1003 | goto out; | 1014 | goto out; |
1015 | nr_extents += ret; | ||
1004 | page_no++; | 1016 | page_no++; |
1005 | probe_block += blocks_per_page; | 1017 | probe_block += blocks_per_page; |
1006 | reprobe: | 1018 | reprobe: |
1007 | continue; | 1019 | continue; |
1008 | } | 1020 | } |
1009 | ret = 0; | 1021 | ret = nr_extents; |
1022 | *span = 1 + highest_block - lowest_block; | ||
1010 | if (page_no == 0) | 1023 | if (page_no == 0) |
1011 | ret = -EINVAL; | 1024 | page_no = 1; /* force Empty message */ |
1012 | sis->max = page_no; | 1025 | sis->max = page_no; |
1026 | sis->pages = page_no - 1; | ||
1013 | sis->highest_bit = page_no - 1; | 1027 | sis->highest_bit = page_no - 1; |
1014 | done: | 1028 | done: |
1015 | sis->curr_swap_extent = list_entry(sis->extent_list.prev, | 1029 | sis->curr_swap_extent = list_entry(sis->extent_list.prev, |
@@ -1069,7 +1083,7 @@ asmlinkage long sys_swapoff(const char __user * specialfile) | |||
1069 | 1083 | ||
1070 | mapping = victim->f_mapping; | 1084 | mapping = victim->f_mapping; |
1071 | prev = -1; | 1085 | prev = -1; |
1072 | swap_list_lock(); | 1086 | spin_lock(&swap_lock); |
1073 | for (type = swap_list.head; type >= 0; type = swap_info[type].next) { | 1087 | for (type = swap_list.head; type >= 0; type = swap_info[type].next) { |
1074 | p = swap_info + type; | 1088 | p = swap_info + type; |
1075 | if ((p->flags & SWP_ACTIVE) == SWP_ACTIVE) { | 1089 | if ((p->flags & SWP_ACTIVE) == SWP_ACTIVE) { |
@@ -1080,14 +1094,14 @@ asmlinkage long sys_swapoff(const char __user * specialfile) | |||
1080 | } | 1094 | } |
1081 | if (type < 0) { | 1095 | if (type < 0) { |
1082 | err = -EINVAL; | 1096 | err = -EINVAL; |
1083 | swap_list_unlock(); | 1097 | spin_unlock(&swap_lock); |
1084 | goto out_dput; | 1098 | goto out_dput; |
1085 | } | 1099 | } |
1086 | if (!security_vm_enough_memory(p->pages)) | 1100 | if (!security_vm_enough_memory(p->pages)) |
1087 | vm_unacct_memory(p->pages); | 1101 | vm_unacct_memory(p->pages); |
1088 | else { | 1102 | else { |
1089 | err = -ENOMEM; | 1103 | err = -ENOMEM; |
1090 | swap_list_unlock(); | 1104 | spin_unlock(&swap_lock); |
1091 | goto out_dput; | 1105 | goto out_dput; |
1092 | } | 1106 | } |
1093 | if (prev < 0) { | 1107 | if (prev < 0) { |
@@ -1102,18 +1116,15 @@ asmlinkage long sys_swapoff(const char __user * specialfile) | |||
1102 | nr_swap_pages -= p->pages; | 1116 | nr_swap_pages -= p->pages; |
1103 | total_swap_pages -= p->pages; | 1117 | total_swap_pages -= p->pages; |
1104 | p->flags &= ~SWP_WRITEOK; | 1118 | p->flags &= ~SWP_WRITEOK; |
1105 | swap_list_unlock(); | 1119 | spin_unlock(&swap_lock); |
1120 | |||
1106 | current->flags |= PF_SWAPOFF; | 1121 | current->flags |= PF_SWAPOFF; |
1107 | err = try_to_unuse(type); | 1122 | err = try_to_unuse(type); |
1108 | current->flags &= ~PF_SWAPOFF; | 1123 | current->flags &= ~PF_SWAPOFF; |
1109 | 1124 | ||
1110 | /* wait for any unplug function to finish */ | ||
1111 | down_write(&swap_unplug_sem); | ||
1112 | up_write(&swap_unplug_sem); | ||
1113 | |||
1114 | if (err) { | 1125 | if (err) { |
1115 | /* re-insert swap space back into swap_list */ | 1126 | /* re-insert swap space back into swap_list */ |
1116 | swap_list_lock(); | 1127 | spin_lock(&swap_lock); |
1117 | for (prev = -1, i = swap_list.head; i >= 0; prev = i, i = swap_info[i].next) | 1128 | for (prev = -1, i = swap_list.head; i >= 0; prev = i, i = swap_info[i].next) |
1118 | if (p->prio >= swap_info[i].prio) | 1129 | if (p->prio >= swap_info[i].prio) |
1119 | break; | 1130 | break; |
@@ -1125,22 +1136,35 @@ asmlinkage long sys_swapoff(const char __user * specialfile) | |||
1125 | nr_swap_pages += p->pages; | 1136 | nr_swap_pages += p->pages; |
1126 | total_swap_pages += p->pages; | 1137 | total_swap_pages += p->pages; |
1127 | p->flags |= SWP_WRITEOK; | 1138 | p->flags |= SWP_WRITEOK; |
1128 | swap_list_unlock(); | 1139 | spin_unlock(&swap_lock); |
1129 | goto out_dput; | 1140 | goto out_dput; |
1130 | } | 1141 | } |
1142 | |||
1143 | /* wait for any unplug function to finish */ | ||
1144 | down_write(&swap_unplug_sem); | ||
1145 | up_write(&swap_unplug_sem); | ||
1146 | |||
1147 | destroy_swap_extents(p); | ||
1131 | down(&swapon_sem); | 1148 | down(&swapon_sem); |
1132 | swap_list_lock(); | 1149 | spin_lock(&swap_lock); |
1133 | drain_mmlist(); | 1150 | drain_mmlist(); |
1134 | swap_device_lock(p); | 1151 | |
1152 | /* wait for anyone still in scan_swap_map */ | ||
1153 | p->highest_bit = 0; /* cuts scans short */ | ||
1154 | while (p->flags >= SWP_SCANNING) { | ||
1155 | spin_unlock(&swap_lock); | ||
1156 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1157 | schedule_timeout(1); | ||
1158 | spin_lock(&swap_lock); | ||
1159 | } | ||
1160 | |||
1135 | swap_file = p->swap_file; | 1161 | swap_file = p->swap_file; |
1136 | p->swap_file = NULL; | 1162 | p->swap_file = NULL; |
1137 | p->max = 0; | 1163 | p->max = 0; |
1138 | swap_map = p->swap_map; | 1164 | swap_map = p->swap_map; |
1139 | p->swap_map = NULL; | 1165 | p->swap_map = NULL; |
1140 | p->flags = 0; | 1166 | p->flags = 0; |
1141 | destroy_swap_extents(p); | 1167 | spin_unlock(&swap_lock); |
1142 | swap_device_unlock(p); | ||
1143 | swap_list_unlock(); | ||
1144 | up(&swapon_sem); | 1168 | up(&swapon_sem); |
1145 | vfree(swap_map); | 1169 | vfree(swap_map); |
1146 | inode = mapping->host; | 1170 | inode = mapping->host; |
@@ -1213,7 +1237,7 @@ static int swap_show(struct seq_file *swap, void *v) | |||
1213 | 1237 | ||
1214 | file = ptr->swap_file; | 1238 | file = ptr->swap_file; |
1215 | len = seq_path(swap, file->f_vfsmnt, file->f_dentry, " \t\n\\"); | 1239 | len = seq_path(swap, file->f_vfsmnt, file->f_dentry, " \t\n\\"); |
1216 | seq_printf(swap, "%*s%s\t%d\t%ld\t%d\n", | 1240 | seq_printf(swap, "%*s%s\t%u\t%u\t%d\n", |
1217 | len < 40 ? 40 - len : 1, " ", | 1241 | len < 40 ? 40 - len : 1, " ", |
1218 | S_ISBLK(file->f_dentry->d_inode->i_mode) ? | 1242 | S_ISBLK(file->f_dentry->d_inode->i_mode) ? |
1219 | "partition" : "file\t", | 1243 | "partition" : "file\t", |
@@ -1272,7 +1296,9 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1272 | static int least_priority; | 1296 | static int least_priority; |
1273 | union swap_header *swap_header = NULL; | 1297 | union swap_header *swap_header = NULL; |
1274 | int swap_header_version; | 1298 | int swap_header_version; |
1275 | int nr_good_pages = 0; | 1299 | unsigned int nr_good_pages = 0; |
1300 | int nr_extents = 0; | ||
1301 | sector_t span; | ||
1276 | unsigned long maxpages = 1; | 1302 | unsigned long maxpages = 1; |
1277 | int swapfilesize; | 1303 | int swapfilesize; |
1278 | unsigned short *swap_map; | 1304 | unsigned short *swap_map; |
@@ -1282,7 +1308,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1282 | 1308 | ||
1283 | if (!capable(CAP_SYS_ADMIN)) | 1309 | if (!capable(CAP_SYS_ADMIN)) |
1284 | return -EPERM; | 1310 | return -EPERM; |
1285 | swap_list_lock(); | 1311 | spin_lock(&swap_lock); |
1286 | p = swap_info; | 1312 | p = swap_info; |
1287 | for (type = 0 ; type < nr_swapfiles ; type++,p++) | 1313 | for (type = 0 ; type < nr_swapfiles ; type++,p++) |
1288 | if (!(p->flags & SWP_USED)) | 1314 | if (!(p->flags & SWP_USED)) |
@@ -1301,14 +1327,13 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1301 | * swp_entry_t or the architecture definition of a swap pte. | 1327 | * swp_entry_t or the architecture definition of a swap pte. |
1302 | */ | 1328 | */ |
1303 | if (type > swp_type(pte_to_swp_entry(swp_entry_to_pte(swp_entry(~0UL,0))))) { | 1329 | if (type > swp_type(pte_to_swp_entry(swp_entry_to_pte(swp_entry(~0UL,0))))) { |
1304 | swap_list_unlock(); | 1330 | spin_unlock(&swap_lock); |
1305 | goto out; | 1331 | goto out; |
1306 | } | 1332 | } |
1307 | if (type >= nr_swapfiles) | 1333 | if (type >= nr_swapfiles) |
1308 | nr_swapfiles = type+1; | 1334 | nr_swapfiles = type+1; |
1309 | INIT_LIST_HEAD(&p->extent_list); | 1335 | INIT_LIST_HEAD(&p->extent_list); |
1310 | p->flags = SWP_USED; | 1336 | p->flags = SWP_USED; |
1311 | p->nr_extents = 0; | ||
1312 | p->swap_file = NULL; | 1337 | p->swap_file = NULL; |
1313 | p->old_block_size = 0; | 1338 | p->old_block_size = 0; |
1314 | p->swap_map = NULL; | 1339 | p->swap_map = NULL; |
@@ -1316,7 +1341,6 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1316 | p->highest_bit = 0; | 1341 | p->highest_bit = 0; |
1317 | p->cluster_nr = 0; | 1342 | p->cluster_nr = 0; |
1318 | p->inuse_pages = 0; | 1343 | p->inuse_pages = 0; |
1319 | spin_lock_init(&p->sdev_lock); | ||
1320 | p->next = -1; | 1344 | p->next = -1; |
1321 | if (swap_flags & SWAP_FLAG_PREFER) { | 1345 | if (swap_flags & SWAP_FLAG_PREFER) { |
1322 | p->prio = | 1346 | p->prio = |
@@ -1324,7 +1348,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1324 | } else { | 1348 | } else { |
1325 | p->prio = --least_priority; | 1349 | p->prio = --least_priority; |
1326 | } | 1350 | } |
1327 | swap_list_unlock(); | 1351 | spin_unlock(&swap_lock); |
1328 | name = getname(specialfile); | 1352 | name = getname(specialfile); |
1329 | error = PTR_ERR(name); | 1353 | error = PTR_ERR(name); |
1330 | if (IS_ERR(name)) { | 1354 | if (IS_ERR(name)) { |
@@ -1426,6 +1450,8 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1426 | } | 1450 | } |
1427 | 1451 | ||
1428 | p->lowest_bit = 1; | 1452 | p->lowest_bit = 1; |
1453 | p->cluster_next = 1; | ||
1454 | |||
1429 | /* | 1455 | /* |
1430 | * Find out how many pages are allowed for a single swap | 1456 | * Find out how many pages are allowed for a single swap |
1431 | * device. There are two limiting factors: 1) the number of | 1457 | * device. There are two limiting factors: 1) the number of |
@@ -1446,6 +1472,10 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1446 | p->highest_bit = maxpages - 1; | 1472 | p->highest_bit = maxpages - 1; |
1447 | 1473 | ||
1448 | error = -EINVAL; | 1474 | error = -EINVAL; |
1475 | if (!maxpages) | ||
1476 | goto bad_swap; | ||
1477 | if (swap_header->info.nr_badpages && S_ISREG(inode->i_mode)) | ||
1478 | goto bad_swap; | ||
1449 | if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES) | 1479 | if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES) |
1450 | goto bad_swap; | 1480 | goto bad_swap; |
1451 | 1481 | ||
@@ -1470,35 +1500,40 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1470 | if (error) | 1500 | if (error) |
1471 | goto bad_swap; | 1501 | goto bad_swap; |
1472 | } | 1502 | } |
1473 | 1503 | ||
1474 | if (swapfilesize && maxpages > swapfilesize) { | 1504 | if (swapfilesize && maxpages > swapfilesize) { |
1475 | printk(KERN_WARNING | 1505 | printk(KERN_WARNING |
1476 | "Swap area shorter than signature indicates\n"); | 1506 | "Swap area shorter than signature indicates\n"); |
1477 | error = -EINVAL; | 1507 | error = -EINVAL; |
1478 | goto bad_swap; | 1508 | goto bad_swap; |
1479 | } | 1509 | } |
1510 | if (nr_good_pages) { | ||
1511 | p->swap_map[0] = SWAP_MAP_BAD; | ||
1512 | p->max = maxpages; | ||
1513 | p->pages = nr_good_pages; | ||
1514 | nr_extents = setup_swap_extents(p, &span); | ||
1515 | if (nr_extents < 0) { | ||
1516 | error = nr_extents; | ||
1517 | goto bad_swap; | ||
1518 | } | ||
1519 | nr_good_pages = p->pages; | ||
1520 | } | ||
1480 | if (!nr_good_pages) { | 1521 | if (!nr_good_pages) { |
1481 | printk(KERN_WARNING "Empty swap-file\n"); | 1522 | printk(KERN_WARNING "Empty swap-file\n"); |
1482 | error = -EINVAL; | 1523 | error = -EINVAL; |
1483 | goto bad_swap; | 1524 | goto bad_swap; |
1484 | } | 1525 | } |
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 | 1526 | ||
1493 | down(&swapon_sem); | 1527 | down(&swapon_sem); |
1494 | swap_list_lock(); | 1528 | spin_lock(&swap_lock); |
1495 | swap_device_lock(p); | ||
1496 | p->flags = SWP_ACTIVE; | 1529 | p->flags = SWP_ACTIVE; |
1497 | nr_swap_pages += nr_good_pages; | 1530 | nr_swap_pages += nr_good_pages; |
1498 | total_swap_pages += nr_good_pages; | 1531 | total_swap_pages += nr_good_pages; |
1499 | printk(KERN_INFO "Adding %dk swap on %s. Priority:%d extents:%d\n", | 1532 | |
1500 | nr_good_pages<<(PAGE_SHIFT-10), name, | 1533 | printk(KERN_INFO "Adding %uk swap on %s. " |
1501 | p->prio, p->nr_extents); | 1534 | "Priority:%d extents:%d across:%lluk\n", |
1535 | nr_good_pages<<(PAGE_SHIFT-10), name, p->prio, | ||
1536 | nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10)); | ||
1502 | 1537 | ||
1503 | /* insert swap space into swap_list: */ | 1538 | /* insert swap space into swap_list: */ |
1504 | prev = -1; | 1539 | prev = -1; |
@@ -1514,8 +1549,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1514 | } else { | 1549 | } else { |
1515 | swap_info[prev].next = p - swap_info; | 1550 | swap_info[prev].next = p - swap_info; |
1516 | } | 1551 | } |
1517 | swap_device_unlock(p); | 1552 | spin_unlock(&swap_lock); |
1518 | swap_list_unlock(); | ||
1519 | up(&swapon_sem); | 1553 | up(&swapon_sem); |
1520 | error = 0; | 1554 | error = 0; |
1521 | goto out; | 1555 | goto out; |
@@ -1524,16 +1558,16 @@ bad_swap: | |||
1524 | set_blocksize(bdev, p->old_block_size); | 1558 | set_blocksize(bdev, p->old_block_size); |
1525 | bd_release(bdev); | 1559 | bd_release(bdev); |
1526 | } | 1560 | } |
1561 | destroy_swap_extents(p); | ||
1527 | bad_swap_2: | 1562 | bad_swap_2: |
1528 | swap_list_lock(); | 1563 | spin_lock(&swap_lock); |
1529 | swap_map = p->swap_map; | 1564 | swap_map = p->swap_map; |
1530 | p->swap_file = NULL; | 1565 | p->swap_file = NULL; |
1531 | p->swap_map = NULL; | 1566 | p->swap_map = NULL; |
1532 | p->flags = 0; | 1567 | p->flags = 0; |
1533 | if (!(swap_flags & SWAP_FLAG_PREFER)) | 1568 | if (!(swap_flags & SWAP_FLAG_PREFER)) |
1534 | ++least_priority; | 1569 | ++least_priority; |
1535 | swap_list_unlock(); | 1570 | spin_unlock(&swap_lock); |
1536 | destroy_swap_extents(p); | ||
1537 | vfree(swap_map); | 1571 | vfree(swap_map); |
1538 | if (swap_file) | 1572 | if (swap_file) |
1539 | filp_close(swap_file, NULL); | 1573 | filp_close(swap_file, NULL); |
@@ -1557,7 +1591,7 @@ void si_swapinfo(struct sysinfo *val) | |||
1557 | unsigned int i; | 1591 | unsigned int i; |
1558 | unsigned long nr_to_be_unused = 0; | 1592 | unsigned long nr_to_be_unused = 0; |
1559 | 1593 | ||
1560 | swap_list_lock(); | 1594 | spin_lock(&swap_lock); |
1561 | for (i = 0; i < nr_swapfiles; i++) { | 1595 | for (i = 0; i < nr_swapfiles; i++) { |
1562 | if (!(swap_info[i].flags & SWP_USED) || | 1596 | if (!(swap_info[i].flags & SWP_USED) || |
1563 | (swap_info[i].flags & SWP_WRITEOK)) | 1597 | (swap_info[i].flags & SWP_WRITEOK)) |
@@ -1566,7 +1600,7 @@ void si_swapinfo(struct sysinfo *val) | |||
1566 | } | 1600 | } |
1567 | val->freeswap = nr_swap_pages + nr_to_be_unused; | 1601 | val->freeswap = nr_swap_pages + nr_to_be_unused; |
1568 | val->totalswap = total_swap_pages + nr_to_be_unused; | 1602 | val->totalswap = total_swap_pages + nr_to_be_unused; |
1569 | swap_list_unlock(); | 1603 | spin_unlock(&swap_lock); |
1570 | } | 1604 | } |
1571 | 1605 | ||
1572 | /* | 1606 | /* |
@@ -1587,7 +1621,7 @@ int swap_duplicate(swp_entry_t entry) | |||
1587 | p = type + swap_info; | 1621 | p = type + swap_info; |
1588 | offset = swp_offset(entry); | 1622 | offset = swp_offset(entry); |
1589 | 1623 | ||
1590 | swap_device_lock(p); | 1624 | spin_lock(&swap_lock); |
1591 | if (offset < p->max && p->swap_map[offset]) { | 1625 | if (offset < p->max && p->swap_map[offset]) { |
1592 | if (p->swap_map[offset] < SWAP_MAP_MAX - 1) { | 1626 | if (p->swap_map[offset] < SWAP_MAP_MAX - 1) { |
1593 | p->swap_map[offset]++; | 1627 | p->swap_map[offset]++; |
@@ -1599,7 +1633,7 @@ int swap_duplicate(swp_entry_t entry) | |||
1599 | result = 1; | 1633 | result = 1; |
1600 | } | 1634 | } |
1601 | } | 1635 | } |
1602 | swap_device_unlock(p); | 1636 | spin_unlock(&swap_lock); |
1603 | out: | 1637 | out: |
1604 | return result; | 1638 | return result; |
1605 | 1639 | ||
@@ -1615,7 +1649,7 @@ get_swap_info_struct(unsigned type) | |||
1615 | } | 1649 | } |
1616 | 1650 | ||
1617 | /* | 1651 | /* |
1618 | * swap_device_lock prevents swap_map being freed. Don't grab an extra | 1652 | * swap_lock prevents swap_map being freed. Don't grab an extra |
1619 | * reference on the swaphandle, it doesn't matter if it becomes unused. | 1653 | * reference on the swaphandle, it doesn't matter if it becomes unused. |
1620 | */ | 1654 | */ |
1621 | int valid_swaphandles(swp_entry_t entry, unsigned long *offset) | 1655 | int valid_swaphandles(swp_entry_t entry, unsigned long *offset) |
@@ -1631,7 +1665,7 @@ int valid_swaphandles(swp_entry_t entry, unsigned long *offset) | |||
1631 | toff++, i--; | 1665 | toff++, i--; |
1632 | *offset = toff; | 1666 | *offset = toff; |
1633 | 1667 | ||
1634 | swap_device_lock(swapdev); | 1668 | spin_lock(&swap_lock); |
1635 | do { | 1669 | do { |
1636 | /* Don't read-ahead past the end of the swap area */ | 1670 | /* Don't read-ahead past the end of the swap area */ |
1637 | if (toff >= swapdev->max) | 1671 | if (toff >= swapdev->max) |
@@ -1644,6 +1678,6 @@ int valid_swaphandles(swp_entry_t entry, unsigned long *offset) | |||
1644 | toff++; | 1678 | toff++; |
1645 | ret++; | 1679 | ret++; |
1646 | } while (--i); | 1680 | } while (--i); |
1647 | swap_device_unlock(swapdev); | 1681 | spin_unlock(&swap_lock); |
1648 | return ret; | 1682 | return ret; |
1649 | } | 1683 | } |