aboutsummaryrefslogtreecommitdiffstats
path: root/mm/truncate.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/truncate.c')
-rw-r--r--mm/truncate.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/mm/truncate.c b/mm/truncate.c
index 0db9258319f0..e5cc39ab0751 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -25,6 +25,9 @@
25static void clear_exceptional_entry(struct address_space *mapping, 25static void clear_exceptional_entry(struct address_space *mapping,
26 pgoff_t index, void *entry) 26 pgoff_t index, void *entry)
27{ 27{
28 struct radix_tree_node *node;
29 void **slot;
30
28 /* Handled by shmem itself */ 31 /* Handled by shmem itself */
29 if (shmem_mapping(mapping)) 32 if (shmem_mapping(mapping))
30 return; 33 return;
@@ -35,8 +38,27 @@ static void clear_exceptional_entry(struct address_space *mapping,
35 * without the tree itself locked. These unlocked entries 38 * without the tree itself locked. These unlocked entries
36 * need verification under the tree lock. 39 * need verification under the tree lock.
37 */ 40 */
38 if (radix_tree_delete_item(&mapping->page_tree, index, entry) == entry) 41 if (!__radix_tree_lookup(&mapping->page_tree, index, &node, &slot))
39 mapping->nrshadows--; 42 goto unlock;
43 if (*slot != entry)
44 goto unlock;
45 radix_tree_replace_slot(slot, NULL);
46 mapping->nrshadows--;
47 if (!node)
48 goto unlock;
49 workingset_node_shadows_dec(node);
50 /*
51 * Don't track node without shadow entries.
52 *
53 * Avoid acquiring the list_lru lock if already untracked.
54 * The list_empty() test is safe as node->private_list is
55 * protected by mapping->tree_lock.
56 */
57 if (!workingset_node_shadows(node) &&
58 !list_empty(&node->private_list))
59 list_lru_del(&workingset_shadow_nodes, &node->private_list);
60 __radix_tree_delete_node(&mapping->page_tree, node);
61unlock:
40 spin_unlock_irq(&mapping->tree_lock); 62 spin_unlock_irq(&mapping->tree_lock);
41} 63}
42 64