diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/swapfile.c | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index b0f56603b9be..763210732b5f 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -169,6 +169,7 @@ static int wait_for_discard(void *word) | |||
169 | static inline unsigned long scan_swap_map(struct swap_info_struct *si) | 169 | static inline unsigned long scan_swap_map(struct swap_info_struct *si) |
170 | { | 170 | { |
171 | unsigned long offset; | 171 | unsigned long offset; |
172 | unsigned long scan_base; | ||
172 | unsigned long last_in_cluster = 0; | 173 | unsigned long last_in_cluster = 0; |
173 | int latency_ration = LATENCY_LIMIT; | 174 | int latency_ration = LATENCY_LIMIT; |
174 | int found_free_cluster = 0; | 175 | int found_free_cluster = 0; |
@@ -181,10 +182,11 @@ static inline unsigned long scan_swap_map(struct swap_info_struct *si) | |||
181 | * all over the entire swap partition, so that we reduce | 182 | * all over the entire swap partition, so that we reduce |
182 | * overall disk seek times between swap pages. -- sct | 183 | * overall disk seek times between swap pages. -- sct |
183 | * But we do now try to find an empty cluster. -Andrea | 184 | * But we do now try to find an empty cluster. -Andrea |
185 | * And we let swap pages go all over an SSD partition. Hugh | ||
184 | */ | 186 | */ |
185 | 187 | ||
186 | si->flags += SWP_SCANNING; | 188 | si->flags += SWP_SCANNING; |
187 | offset = si->cluster_next; | 189 | scan_base = offset = si->cluster_next; |
188 | 190 | ||
189 | if (unlikely(!si->cluster_nr--)) { | 191 | if (unlikely(!si->cluster_nr--)) { |
190 | if (si->pages - si->inuse_pages < SWAPFILE_CLUSTER) { | 192 | if (si->pages - si->inuse_pages < SWAPFILE_CLUSTER) { |
@@ -206,7 +208,16 @@ static inline unsigned long scan_swap_map(struct swap_info_struct *si) | |||
206 | } | 208 | } |
207 | spin_unlock(&swap_lock); | 209 | spin_unlock(&swap_lock); |
208 | 210 | ||
209 | offset = si->lowest_bit; | 211 | /* |
212 | * If seek is expensive, start searching for new cluster from | ||
213 | * start of partition, to minimize the span of allocated swap. | ||
214 | * But if seek is cheap, search from our current position, so | ||
215 | * that swap is allocated from all over the partition: if the | ||
216 | * Flash Translation Layer only remaps within limited zones, | ||
217 | * we don't want to wear out the first zone too quickly. | ||
218 | */ | ||
219 | if (!(si->flags & SWP_SOLIDSTATE)) | ||
220 | scan_base = offset = si->lowest_bit; | ||
210 | last_in_cluster = offset + SWAPFILE_CLUSTER - 1; | 221 | last_in_cluster = offset + SWAPFILE_CLUSTER - 1; |
211 | 222 | ||
212 | /* Locate the first empty (unaligned) cluster */ | 223 | /* Locate the first empty (unaligned) cluster */ |
@@ -228,6 +239,27 @@ static inline unsigned long scan_swap_map(struct swap_info_struct *si) | |||
228 | } | 239 | } |
229 | 240 | ||
230 | offset = si->lowest_bit; | 241 | offset = si->lowest_bit; |
242 | last_in_cluster = offset + SWAPFILE_CLUSTER - 1; | ||
243 | |||
244 | /* Locate the first empty (unaligned) cluster */ | ||
245 | for (; last_in_cluster < scan_base; offset++) { | ||
246 | if (si->swap_map[offset]) | ||
247 | last_in_cluster = offset + SWAPFILE_CLUSTER; | ||
248 | else if (offset == last_in_cluster) { | ||
249 | spin_lock(&swap_lock); | ||
250 | offset -= SWAPFILE_CLUSTER - 1; | ||
251 | si->cluster_next = offset; | ||
252 | si->cluster_nr = SWAPFILE_CLUSTER - 1; | ||
253 | found_free_cluster = 1; | ||
254 | goto checks; | ||
255 | } | ||
256 | if (unlikely(--latency_ration < 0)) { | ||
257 | cond_resched(); | ||
258 | latency_ration = LATENCY_LIMIT; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | offset = scan_base; | ||
231 | spin_lock(&swap_lock); | 263 | spin_lock(&swap_lock); |
232 | si->cluster_nr = SWAPFILE_CLUSTER - 1; | 264 | si->cluster_nr = SWAPFILE_CLUSTER - 1; |
233 | si->lowest_alloc = 0; | 265 | si->lowest_alloc = 0; |
@@ -239,7 +271,7 @@ checks: | |||
239 | if (!si->highest_bit) | 271 | if (!si->highest_bit) |
240 | goto no_page; | 272 | goto no_page; |
241 | if (offset > si->highest_bit) | 273 | if (offset > si->highest_bit) |
242 | offset = si->lowest_bit; | 274 | scan_base = offset = si->lowest_bit; |
243 | if (si->swap_map[offset]) | 275 | if (si->swap_map[offset]) |
244 | goto scan; | 276 | goto scan; |
245 | 277 | ||
@@ -323,8 +355,18 @@ scan: | |||
323 | latency_ration = LATENCY_LIMIT; | 355 | latency_ration = LATENCY_LIMIT; |
324 | } | 356 | } |
325 | } | 357 | } |
358 | offset = si->lowest_bit; | ||
359 | while (++offset < scan_base) { | ||
360 | if (!si->swap_map[offset]) { | ||
361 | spin_lock(&swap_lock); | ||
362 | goto checks; | ||
363 | } | ||
364 | if (unlikely(--latency_ration < 0)) { | ||
365 | cond_resched(); | ||
366 | latency_ration = LATENCY_LIMIT; | ||
367 | } | ||
368 | } | ||
326 | spin_lock(&swap_lock); | 369 | spin_lock(&swap_lock); |
327 | goto checks; | ||
328 | 370 | ||
329 | no_page: | 371 | no_page: |
330 | si->flags -= SWP_SCANNING; | 372 | si->flags -= SWP_SCANNING; |