aboutsummaryrefslogtreecommitdiffstats
path: root/mm/truncate.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/truncate.c')
-rw-r--r--mm/truncate.c149
1 files changed, 101 insertions, 48 deletions
diff --git a/mm/truncate.c b/mm/truncate.c
index 2330223841fb..e4b4cf0f4070 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -25,44 +25,85 @@
25#include <linux/rmap.h> 25#include <linux/rmap.h>
26#include "internal.h" 26#include "internal.h"
27 27
28static void clear_shadow_entry(struct address_space *mapping, pgoff_t index, 28/*
29 void *entry) 29 * Regular page slots are stabilized by the page lock even without the tree
30 * itself locked. These unlocked entries need verification under the tree
31 * lock.
32 */
33static inline void __clear_shadow_entry(struct address_space *mapping,
34 pgoff_t index, void *entry)
30{ 35{
31 struct radix_tree_node *node; 36 struct radix_tree_node *node;
32 void **slot; 37 void **slot;
33 38
34 spin_lock_irq(&mapping->tree_lock);
35 /*
36 * Regular page slots are stabilized by the page lock even
37 * without the tree itself locked. These unlocked entries
38 * need verification under the tree lock.
39 */
40 if (!__radix_tree_lookup(&mapping->page_tree, index, &node, &slot)) 39 if (!__radix_tree_lookup(&mapping->page_tree, index, &node, &slot))
41 goto unlock; 40 return;
42 if (*slot != entry) 41 if (*slot != entry)
43 goto unlock; 42 return;
44 __radix_tree_replace(&mapping->page_tree, node, slot, NULL, 43 __radix_tree_replace(&mapping->page_tree, node, slot, NULL,
45 workingset_update_node, mapping); 44 workingset_update_node);
46 mapping->nrexceptional--; 45 mapping->nrexceptional--;
47unlock: 46}
47
48static void clear_shadow_entry(struct address_space *mapping, pgoff_t index,
49 void *entry)
50{
51 spin_lock_irq(&mapping->tree_lock);
52 __clear_shadow_entry(mapping, index, entry);
48 spin_unlock_irq(&mapping->tree_lock); 53 spin_unlock_irq(&mapping->tree_lock);
49} 54}
50 55
51/* 56/*
52 * Unconditionally remove exceptional entry. Usually called from truncate path. 57 * Unconditionally remove exceptional entries. Usually called from truncate
58 * path. Note that the pagevec may be altered by this function by removing
59 * exceptional entries similar to what pagevec_remove_exceptionals does.
53 */ 60 */
54static void truncate_exceptional_entry(struct address_space *mapping, 61static void truncate_exceptional_pvec_entries(struct address_space *mapping,
55 pgoff_t index, void *entry) 62 struct pagevec *pvec, pgoff_t *indices,
63 pgoff_t end)
56{ 64{
65 int i, j;
66 bool dax, lock;
67
57 /* Handled by shmem itself */ 68 /* Handled by shmem itself */
58 if (shmem_mapping(mapping)) 69 if (shmem_mapping(mapping))
59 return; 70 return;
60 71
61 if (dax_mapping(mapping)) { 72 for (j = 0; j < pagevec_count(pvec); j++)
62 dax_delete_mapping_entry(mapping, index); 73 if (radix_tree_exceptional_entry(pvec->pages[j]))
74 break;
75
76 if (j == pagevec_count(pvec))
63 return; 77 return;
78
79 dax = dax_mapping(mapping);
80 lock = !dax && indices[j] < end;
81 if (lock)
82 spin_lock_irq(&mapping->tree_lock);
83
84 for (i = j; i < pagevec_count(pvec); i++) {
85 struct page *page = pvec->pages[i];
86 pgoff_t index = indices[i];
87
88 if (!radix_tree_exceptional_entry(page)) {
89 pvec->pages[j++] = page;
90 continue;
91 }
92
93 if (index >= end)
94 continue;
95
96 if (unlikely(dax)) {
97 dax_delete_mapping_entry(mapping, index);
98 continue;
99 }
100
101 __clear_shadow_entry(mapping, index, page);
64 } 102 }
65 clear_shadow_entry(mapping, index, entry); 103
104 if (lock)
105 spin_unlock_irq(&mapping->tree_lock);
106 pvec->nr = j;
66} 107}
67 108
68/* 109/*
@@ -134,11 +175,17 @@ void do_invalidatepage(struct page *page, unsigned int offset,
134 * its lock, b) when a concurrent invalidate_mapping_pages got there first and 175 * its lock, b) when a concurrent invalidate_mapping_pages got there first and
135 * c) when tmpfs swizzles a page between a tmpfs inode and swapper_space. 176 * c) when tmpfs swizzles a page between a tmpfs inode and swapper_space.
136 */ 177 */
137static int 178static void
138truncate_complete_page(struct address_space *mapping, struct page *page) 179truncate_cleanup_page(struct address_space *mapping, struct page *page)
139{ 180{
140 if (page->mapping != mapping) 181 if (page_mapped(page)) {
141 return -EIO; 182 loff_t holelen;
183
184 holelen = PageTransHuge(page) ? HPAGE_PMD_SIZE : PAGE_SIZE;
185 unmap_mapping_range(mapping,
186 (loff_t)page->index << PAGE_SHIFT,
187 holelen, 0);
188 }
142 189
143 if (page_has_private(page)) 190 if (page_has_private(page))
144 do_invalidatepage(page, 0, PAGE_SIZE); 191 do_invalidatepage(page, 0, PAGE_SIZE);
@@ -150,8 +197,6 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
150 */ 197 */
151 cancel_dirty_page(page); 198 cancel_dirty_page(page);
152 ClearPageMappedToDisk(page); 199 ClearPageMappedToDisk(page);
153 delete_from_page_cache(page);
154 return 0;
155} 200}
156 201
157/* 202/*
@@ -180,16 +225,14 @@ invalidate_complete_page(struct address_space *mapping, struct page *page)
180 225
181int truncate_inode_page(struct address_space *mapping, struct page *page) 226int truncate_inode_page(struct address_space *mapping, struct page *page)
182{ 227{
183 loff_t holelen;
184 VM_BUG_ON_PAGE(PageTail(page), page); 228 VM_BUG_ON_PAGE(PageTail(page), page);
185 229
186 holelen = PageTransHuge(page) ? HPAGE_PMD_SIZE : PAGE_SIZE; 230 if (page->mapping != mapping)
187 if (page_mapped(page)) { 231 return -EIO;
188 unmap_mapping_range(mapping, 232
189 (loff_t)page->index << PAGE_SHIFT, 233 truncate_cleanup_page(mapping, page);
190 holelen, 0); 234 delete_from_page_cache(page);
191 } 235 return 0;
192 return truncate_complete_page(mapping, page);
193} 236}
194 237
195/* 238/*
@@ -287,11 +330,19 @@ void truncate_inode_pages_range(struct address_space *mapping,
287 else 330 else
288 end = (lend + 1) >> PAGE_SHIFT; 331 end = (lend + 1) >> PAGE_SHIFT;
289 332
290 pagevec_init(&pvec, 0); 333 pagevec_init(&pvec);
291 index = start; 334 index = start;
292 while (index < end && pagevec_lookup_entries(&pvec, mapping, index, 335 while (index < end && pagevec_lookup_entries(&pvec, mapping, index,
293 min(end - index, (pgoff_t)PAGEVEC_SIZE), 336 min(end - index, (pgoff_t)PAGEVEC_SIZE),
294 indices)) { 337 indices)) {
338 /*
339 * Pagevec array has exceptional entries and we may also fail
340 * to lock some pages. So we store pages that can be deleted
341 * in a new pagevec.
342 */
343 struct pagevec locked_pvec;
344
345 pagevec_init(&locked_pvec);
295 for (i = 0; i < pagevec_count(&pvec); i++) { 346 for (i = 0; i < pagevec_count(&pvec); i++) {
296 struct page *page = pvec.pages[i]; 347 struct page *page = pvec.pages[i];
297 348
@@ -300,11 +351,8 @@ void truncate_inode_pages_range(struct address_space *mapping,
300 if (index >= end) 351 if (index >= end)
301 break; 352 break;
302 353
303 if (radix_tree_exceptional_entry(page)) { 354 if (radix_tree_exceptional_entry(page))
304 truncate_exceptional_entry(mapping, index,
305 page);
306 continue; 355 continue;
307 }
308 356
309 if (!trylock_page(page)) 357 if (!trylock_page(page))
310 continue; 358 continue;
@@ -313,15 +361,22 @@ void truncate_inode_pages_range(struct address_space *mapping,
313 unlock_page(page); 361 unlock_page(page);
314 continue; 362 continue;
315 } 363 }
316 truncate_inode_page(mapping, page); 364 if (page->mapping != mapping) {
317 unlock_page(page); 365 unlock_page(page);
366 continue;
367 }
368 pagevec_add(&locked_pvec, page);
318 } 369 }
319 pagevec_remove_exceptionals(&pvec); 370 for (i = 0; i < pagevec_count(&locked_pvec); i++)
371 truncate_cleanup_page(mapping, locked_pvec.pages[i]);
372 delete_from_page_cache_batch(mapping, &locked_pvec);
373 for (i = 0; i < pagevec_count(&locked_pvec); i++)
374 unlock_page(locked_pvec.pages[i]);
375 truncate_exceptional_pvec_entries(mapping, &pvec, indices, end);
320 pagevec_release(&pvec); 376 pagevec_release(&pvec);
321 cond_resched(); 377 cond_resched();
322 index++; 378 index++;
323 } 379 }
324
325 if (partial_start) { 380 if (partial_start) {
326 struct page *page = find_lock_page(mapping, start - 1); 381 struct page *page = find_lock_page(mapping, start - 1);
327 if (page) { 382 if (page) {
@@ -379,6 +434,7 @@ void truncate_inode_pages_range(struct address_space *mapping,
379 pagevec_release(&pvec); 434 pagevec_release(&pvec);
380 break; 435 break;
381 } 436 }
437
382 for (i = 0; i < pagevec_count(&pvec); i++) { 438 for (i = 0; i < pagevec_count(&pvec); i++) {
383 struct page *page = pvec.pages[i]; 439 struct page *page = pvec.pages[i];
384 440
@@ -390,11 +446,8 @@ void truncate_inode_pages_range(struct address_space *mapping,
390 break; 446 break;
391 } 447 }
392 448
393 if (radix_tree_exceptional_entry(page)) { 449 if (radix_tree_exceptional_entry(page))
394 truncate_exceptional_entry(mapping, index,
395 page);
396 continue; 450 continue;
397 }
398 451
399 lock_page(page); 452 lock_page(page);
400 WARN_ON(page_to_index(page) != index); 453 WARN_ON(page_to_index(page) != index);
@@ -402,7 +455,7 @@ void truncate_inode_pages_range(struct address_space *mapping,
402 truncate_inode_page(mapping, page); 455 truncate_inode_page(mapping, page);
403 unlock_page(page); 456 unlock_page(page);
404 } 457 }
405 pagevec_remove_exceptionals(&pvec); 458 truncate_exceptional_pvec_entries(mapping, &pvec, indices, end);
406 pagevec_release(&pvec); 459 pagevec_release(&pvec);
407 index++; 460 index++;
408 } 461 }
@@ -500,7 +553,7 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
500 unsigned long count = 0; 553 unsigned long count = 0;
501 int i; 554 int i;
502 555
503 pagevec_init(&pvec, 0); 556 pagevec_init(&pvec);
504 while (index <= end && pagevec_lookup_entries(&pvec, mapping, index, 557 while (index <= end && pagevec_lookup_entries(&pvec, mapping, index,
505 min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1, 558 min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1,
506 indices)) { 559 indices)) {
@@ -630,7 +683,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
630 if (mapping->nrpages == 0 && mapping->nrexceptional == 0) 683 if (mapping->nrpages == 0 && mapping->nrexceptional == 0)
631 goto out; 684 goto out;
632 685
633 pagevec_init(&pvec, 0); 686 pagevec_init(&pvec);
634 index = start; 687 index = start;
635 while (index <= end && pagevec_lookup_entries(&pvec, mapping, index, 688 while (index <= end && pagevec_lookup_entries(&pvec, mapping, index,
636 min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1, 689 min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1,