aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorHugh Dickins <hugh@veritas.com>2008-02-05 01:28:51 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-05 12:44:15 -0500
commitd9fe526a83b84edc9c5ff217a00c896bfc20b2ce (patch)
treeaecb9dbd92108915ba255df8f04d106c2099bf48 /mm
parent73b1262fa43a778b1e154deea632cdef5009d6a1 (diff)
tmpfs: allow filepage alongside swappage
tmpfs has long allowed for a fresh filepage to be created in pagecache, just before shmem_getpage gets the chance to match it up with the swappage which already belongs to that offset. But unionfs_writepage now does a find_or_create_page, divorced from shmem_getpage, which leaves conflicting filepage and swappage outstanding indefinitely, when unionfs is over tmpfs. Therefore shmem_writepage (where a page is swizzled from file to swap) must now be on the lookout for existing swap, ready to free it in favour of the more uptodate filepage, instead of BUGging on that clash. And when the add_to_page_cache fails in shmem_unuse_inode, it must defer to an uptodate filepage, otherwise swapoff would hang. Whereas when add_to_page_cache fails in shmem_getpage, it should retry in the same way it already does. Signed-off-by: Hugh Dickins <hugh@veritas.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/shmem.c69
1 files changed, 44 insertions, 25 deletions
diff --git a/mm/shmem.c b/mm/shmem.c
index e577adf4ae85..4ae47f54c822 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -827,6 +827,7 @@ static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, s
827 struct page *subdir; 827 struct page *subdir;
828 swp_entry_t *ptr; 828 swp_entry_t *ptr;
829 int offset; 829 int offset;
830 int error;
830 831
831 idx = 0; 832 idx = 0;
832 ptr = info->i_direct; 833 ptr = info->i_direct;
@@ -884,7 +885,20 @@ lost2:
884found: 885found:
885 idx += offset; 886 idx += offset;
886 inode = &info->vfs_inode; 887 inode = &info->vfs_inode;
887 if (add_to_page_cache(page, inode->i_mapping, idx, GFP_ATOMIC) == 0) { 888 error = add_to_page_cache(page, inode->i_mapping, idx, GFP_ATOMIC);
889 if (error == -EEXIST) {
890 struct page *filepage = find_get_page(inode->i_mapping, idx);
891 if (filepage) {
892 /*
893 * There might be a more uptodate page coming down
894 * from a stacked writepage: forget our swappage if so.
895 */
896 if (PageUptodate(filepage))
897 error = 0;
898 page_cache_release(filepage);
899 }
900 }
901 if (!error) {
888 delete_from_swap_cache(page); 902 delete_from_swap_cache(page);
889 set_page_dirty(page); 903 set_page_dirty(page);
890 info->flags |= SHMEM_PAGEIN; 904 info->flags |= SHMEM_PAGEIN;
@@ -937,44 +951,45 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
937 struct inode *inode; 951 struct inode *inode;
938 952
939 BUG_ON(!PageLocked(page)); 953 BUG_ON(!PageLocked(page));
940 /*
941 * shmem_backing_dev_info's capabilities prevent regular writeback or
942 * sync from ever calling shmem_writepage; but a stacking filesystem
943 * may use the ->writepage of its underlying filesystem, in which case
944 * we want to do nothing when that underlying filesystem is tmpfs
945 * (writing out to swap is useful as a response to memory pressure, but
946 * of no use to stabilize the data) - just redirty the page, unlock it
947 * and claim success in this case. AOP_WRITEPAGE_ACTIVATE, and the
948 * page_mapped check below, must be avoided unless we're in reclaim.
949 */
950 if (!wbc->for_reclaim) {
951 set_page_dirty(page);
952 unlock_page(page);
953 return 0;
954 }
955 BUG_ON(page_mapped(page));
956
957 mapping = page->mapping; 954 mapping = page->mapping;
958 index = page->index; 955 index = page->index;
959 inode = mapping->host; 956 inode = mapping->host;
960 info = SHMEM_I(inode); 957 info = SHMEM_I(inode);
961 if (info->flags & VM_LOCKED) 958 if (info->flags & VM_LOCKED)
962 goto redirty; 959 goto redirty;
963 swap = get_swap_page(); 960 if (!total_swap_pages)
964 if (!swap.val)
965 goto redirty; 961 goto redirty;
966 962
963 /*
964 * shmem_backing_dev_info's capabilities prevent regular writeback or
965 * sync from ever calling shmem_writepage; but a stacking filesystem
966 * may use the ->writepage of its underlying filesystem, in which case
967 * tmpfs should write out to swap only in response to memory pressure,
968 * and not for pdflush or sync. However, in those cases, we do still
969 * want to check if there's a redundant swappage to be discarded.
970 */
971 if (wbc->for_reclaim)
972 swap = get_swap_page();
973 else
974 swap.val = 0;
975
967 spin_lock(&info->lock); 976 spin_lock(&info->lock);
968 shmem_recalc_inode(inode);
969 if (index >= info->next_index) { 977 if (index >= info->next_index) {
970 BUG_ON(!(info->flags & SHMEM_TRUNCATE)); 978 BUG_ON(!(info->flags & SHMEM_TRUNCATE));
971 goto unlock; 979 goto unlock;
972 } 980 }
973 entry = shmem_swp_entry(info, index, NULL); 981 entry = shmem_swp_entry(info, index, NULL);
974 BUG_ON(!entry); 982 if (entry->val) {
975 BUG_ON(entry->val); 983 /*
984 * The more uptodate page coming down from a stacked
985 * writepage should replace our old swappage.
986 */
987 free_swap_and_cache(*entry);
988 shmem_swp_set(info, entry, 0);
989 }
990 shmem_recalc_inode(inode);
976 991
977 if (add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) { 992 if (swap.val && add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) {
978 remove_from_page_cache(page); 993 remove_from_page_cache(page);
979 shmem_swp_set(info, entry, swap.val); 994 shmem_swp_set(info, entry, swap.val);
980 shmem_swp_unmap(entry); 995 shmem_swp_unmap(entry);
@@ -986,6 +1001,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
986 spin_unlock(&shmem_swaplist_lock); 1001 spin_unlock(&shmem_swaplist_lock);
987 } 1002 }
988 swap_duplicate(swap); 1003 swap_duplicate(swap);
1004 BUG_ON(page_mapped(page));
989 page_cache_release(page); /* pagecache ref */ 1005 page_cache_release(page); /* pagecache ref */
990 set_page_dirty(page); 1006 set_page_dirty(page);
991 unlock_page(page); 1007 unlock_page(page);
@@ -998,7 +1014,10 @@ unlock:
998 swap_free(swap); 1014 swap_free(swap);
999redirty: 1015redirty:
1000 set_page_dirty(page); 1016 set_page_dirty(page);
1001 return AOP_WRITEPAGE_ACTIVATE; /* Return with the page locked */ 1017 if (wbc->for_reclaim)
1018 return AOP_WRITEPAGE_ACTIVATE; /* Return with page locked */
1019 unlock_page(page);
1020 return 0;
1002} 1021}
1003 1022
1004#ifdef CONFIG_NUMA 1023#ifdef CONFIG_NUMA