diff options
Diffstat (limited to 'mm/truncate.c')
-rw-r--r-- | mm/truncate.c | 26 |
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 @@ | |||
25 | static void clear_exceptional_entry(struct address_space *mapping, | 25 | static 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); | ||
61 | unlock: | ||
40 | spin_unlock_irq(&mapping->tree_lock); | 62 | spin_unlock_irq(&mapping->tree_lock); |
41 | } | 63 | } |
42 | 64 | ||