diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2010-12-22 02:10:01 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-12-22 02:10:01 -0500 |
commit | 752a4a95e3c96a8e8d3405b16d292f13e8c7856b (patch) | |
tree | 838e43696fdc45b83f082eef7230d79cfe699497 /mm/filemap.c | |
parent | bc3f67a3e1b20756d4bfa5886a6b8fd0c068e6a4 (diff) | |
parent | 90a8a73c06cc32b609a880d48449d7083327e11a (diff) |
Merge commit 'v2.6.37-rc7' into spi/next
Diffstat (limited to 'mm/filemap.c')
-rw-r--r-- | mm/filemap.c | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index 61ba5e405791..6b9aee20f242 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -143,13 +143,18 @@ void __remove_from_page_cache(struct page *page) | |||
143 | void remove_from_page_cache(struct page *page) | 143 | void remove_from_page_cache(struct page *page) |
144 | { | 144 | { |
145 | struct address_space *mapping = page->mapping; | 145 | struct address_space *mapping = page->mapping; |
146 | void (*freepage)(struct page *); | ||
146 | 147 | ||
147 | BUG_ON(!PageLocked(page)); | 148 | BUG_ON(!PageLocked(page)); |
148 | 149 | ||
150 | freepage = mapping->a_ops->freepage; | ||
149 | spin_lock_irq(&mapping->tree_lock); | 151 | spin_lock_irq(&mapping->tree_lock); |
150 | __remove_from_page_cache(page); | 152 | __remove_from_page_cache(page); |
151 | spin_unlock_irq(&mapping->tree_lock); | 153 | spin_unlock_irq(&mapping->tree_lock); |
152 | mem_cgroup_uncharge_cache_page(page); | 154 | mem_cgroup_uncharge_cache_page(page); |
155 | |||
156 | if (freepage) | ||
157 | freepage(page); | ||
153 | } | 158 | } |
154 | EXPORT_SYMBOL(remove_from_page_cache); | 159 | EXPORT_SYMBOL(remove_from_page_cache); |
155 | 160 | ||
@@ -644,7 +649,9 @@ repeat: | |||
644 | pagep = radix_tree_lookup_slot(&mapping->page_tree, offset); | 649 | pagep = radix_tree_lookup_slot(&mapping->page_tree, offset); |
645 | if (pagep) { | 650 | if (pagep) { |
646 | page = radix_tree_deref_slot(pagep); | 651 | page = radix_tree_deref_slot(pagep); |
647 | if (unlikely(!page || page == RADIX_TREE_RETRY)) | 652 | if (unlikely(!page)) |
653 | goto out; | ||
654 | if (radix_tree_deref_retry(page)) | ||
648 | goto repeat; | 655 | goto repeat; |
649 | 656 | ||
650 | if (!page_cache_get_speculative(page)) | 657 | if (!page_cache_get_speculative(page)) |
@@ -660,6 +667,7 @@ repeat: | |||
660 | goto repeat; | 667 | goto repeat; |
661 | } | 668 | } |
662 | } | 669 | } |
670 | out: | ||
663 | rcu_read_unlock(); | 671 | rcu_read_unlock(); |
664 | 672 | ||
665 | return page; | 673 | return page; |
@@ -777,12 +785,11 @@ repeat: | |||
777 | page = radix_tree_deref_slot((void **)pages[i]); | 785 | page = radix_tree_deref_slot((void **)pages[i]); |
778 | if (unlikely(!page)) | 786 | if (unlikely(!page)) |
779 | continue; | 787 | continue; |
780 | /* | 788 | if (radix_tree_deref_retry(page)) { |
781 | * this can only trigger if nr_found == 1, making livelock | 789 | if (ret) |
782 | * a non issue. | 790 | start = pages[ret-1]->index; |
783 | */ | ||
784 | if (unlikely(page == RADIX_TREE_RETRY)) | ||
785 | goto restart; | 791 | goto restart; |
792 | } | ||
786 | 793 | ||
787 | if (!page_cache_get_speculative(page)) | 794 | if (!page_cache_get_speculative(page)) |
788 | goto repeat; | 795 | goto repeat; |
@@ -830,11 +837,7 @@ repeat: | |||
830 | page = radix_tree_deref_slot((void **)pages[i]); | 837 | page = radix_tree_deref_slot((void **)pages[i]); |
831 | if (unlikely(!page)) | 838 | if (unlikely(!page)) |
832 | continue; | 839 | continue; |
833 | /* | 840 | if (radix_tree_deref_retry(page)) |
834 | * this can only trigger if nr_found == 1, making livelock | ||
835 | * a non issue. | ||
836 | */ | ||
837 | if (unlikely(page == RADIX_TREE_RETRY)) | ||
838 | goto restart; | 841 | goto restart; |
839 | 842 | ||
840 | if (page->mapping == NULL || page->index != index) | 843 | if (page->mapping == NULL || page->index != index) |
@@ -887,11 +890,7 @@ repeat: | |||
887 | page = radix_tree_deref_slot((void **)pages[i]); | 890 | page = radix_tree_deref_slot((void **)pages[i]); |
888 | if (unlikely(!page)) | 891 | if (unlikely(!page)) |
889 | continue; | 892 | continue; |
890 | /* | 893 | if (radix_tree_deref_retry(page)) |
891 | * this can only trigger if nr_found == 1, making livelock | ||
892 | * a non issue. | ||
893 | */ | ||
894 | if (unlikely(page == RADIX_TREE_RETRY)) | ||
895 | goto restart; | 894 | goto restart; |
896 | 895 | ||
897 | if (!page_cache_get_speculative(page)) | 896 | if (!page_cache_get_speculative(page)) |
@@ -1029,6 +1028,9 @@ find_page: | |||
1029 | goto page_not_up_to_date; | 1028 | goto page_not_up_to_date; |
1030 | if (!trylock_page(page)) | 1029 | if (!trylock_page(page)) |
1031 | goto page_not_up_to_date; | 1030 | goto page_not_up_to_date; |
1031 | /* Did it get truncated before we got the lock? */ | ||
1032 | if (!page->mapping) | ||
1033 | goto page_not_up_to_date_locked; | ||
1032 | if (!mapping->a_ops->is_partially_uptodate(page, | 1034 | if (!mapping->a_ops->is_partially_uptodate(page, |
1033 | desc, offset)) | 1035 | desc, offset)) |
1034 | goto page_not_up_to_date_locked; | 1036 | goto page_not_up_to_date_locked; |