aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorLiu Bo <liubo2009@cn.fujitsu.com>2012-03-29 09:57:44 -0400
committerChris Mason <chris.mason@oracle.com>2012-03-29 09:57:44 -0400
commit1f12bd063285b059cb63315d1424dae1ddd87a64 (patch)
treed0c9c7be653b3306f9cfb76ba9805f36c9295e37 /fs/btrfs/ioctl.c
parentecb8bea87d05fd2d1fc0718e1e4bbf09c7c6045a (diff)
Btrfs: fix the mismatch of page->mapping
commit 600a45e1d5e376f679ff9ecc4ce9452710a6d27c (Btrfs: fix deadlock on page lock when doing auto-defragment) fixes the deadlock on page, but it also introduces another bug. A page may have been truncated after unlock & lock. So we need to find it again to get the right one. And since we've held i_mutex lock, inode size remains unchanged and we can drop isize overflow checks. Signed-off-by: Liu Bo <liubo2009@cn.fujitsu.com> Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c35
1 files changed, 19 insertions, 16 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 45910d4b8f65..de46fa218590 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -871,6 +871,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
871 u64 isize = i_size_read(inode); 871 u64 isize = i_size_read(inode);
872 u64 page_start; 872 u64 page_start;
873 u64 page_end; 873 u64 page_end;
874 u64 page_cnt;
874 int ret; 875 int ret;
875 int i; 876 int i;
876 int i_done; 877 int i_done;
@@ -879,19 +880,21 @@ static int cluster_pages_for_defrag(struct inode *inode,
879 struct extent_io_tree *tree; 880 struct extent_io_tree *tree;
880 gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping); 881 gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
881 882
882 if (isize == 0)
883 return 0;
884 file_end = (isize - 1) >> PAGE_CACHE_SHIFT; 883 file_end = (isize - 1) >> PAGE_CACHE_SHIFT;
884 if (!isize || start_index > file_end)
885 return 0;
886
887 page_cnt = min_t(u64, (u64)num_pages, (u64)file_end - start_index + 1);
885 888
886 ret = btrfs_delalloc_reserve_space(inode, 889 ret = btrfs_delalloc_reserve_space(inode,
887 num_pages << PAGE_CACHE_SHIFT); 890 page_cnt << PAGE_CACHE_SHIFT);
888 if (ret) 891 if (ret)
889 return ret; 892 return ret;
890 i_done = 0; 893 i_done = 0;
891 tree = &BTRFS_I(inode)->io_tree; 894 tree = &BTRFS_I(inode)->io_tree;
892 895
893 /* step one, lock all the pages */ 896 /* step one, lock all the pages */
894 for (i = 0; i < num_pages; i++) { 897 for (i = 0; i < page_cnt; i++) {
895 struct page *page; 898 struct page *page;
896again: 899again:
897 page = find_or_create_page(inode->i_mapping, 900 page = find_or_create_page(inode->i_mapping,
@@ -913,6 +916,15 @@ again:
913 btrfs_start_ordered_extent(inode, ordered, 1); 916 btrfs_start_ordered_extent(inode, ordered, 1);
914 btrfs_put_ordered_extent(ordered); 917 btrfs_put_ordered_extent(ordered);
915 lock_page(page); 918 lock_page(page);
919 /*
920 * we unlocked the page above, so we need check if
921 * it was released or not.
922 */
923 if (page->mapping != inode->i_mapping) {
924 unlock_page(page);
925 page_cache_release(page);
926 goto again;
927 }
916 } 928 }
917 929
918 if (!PageUptodate(page)) { 930 if (!PageUptodate(page)) {
@@ -926,15 +938,6 @@ again:
926 } 938 }
927 } 939 }
928 940
929 isize = i_size_read(inode);
930 file_end = (isize - 1) >> PAGE_CACHE_SHIFT;
931 if (!isize || page->index > file_end) {
932 /* whoops, we blew past eof, skip this page */
933 unlock_page(page);
934 page_cache_release(page);
935 break;
936 }
937
938 if (page->mapping != inode->i_mapping) { 941 if (page->mapping != inode->i_mapping) {
939 unlock_page(page); 942 unlock_page(page);
940 page_cache_release(page); 943 page_cache_release(page);
@@ -967,12 +970,12 @@ again:
967 EXTENT_DO_ACCOUNTING, 0, 0, &cached_state, 970 EXTENT_DO_ACCOUNTING, 0, 0, &cached_state,
968 GFP_NOFS); 971 GFP_NOFS);
969 972
970 if (i_done != num_pages) { 973 if (i_done != page_cnt) {
971 spin_lock(&BTRFS_I(inode)->lock); 974 spin_lock(&BTRFS_I(inode)->lock);
972 BTRFS_I(inode)->outstanding_extents++; 975 BTRFS_I(inode)->outstanding_extents++;
973 spin_unlock(&BTRFS_I(inode)->lock); 976 spin_unlock(&BTRFS_I(inode)->lock);
974 btrfs_delalloc_release_space(inode, 977 btrfs_delalloc_release_space(inode,
975 (num_pages - i_done) << PAGE_CACHE_SHIFT); 978 (page_cnt - i_done) << PAGE_CACHE_SHIFT);
976 } 979 }
977 980
978 981
@@ -997,7 +1000,7 @@ out:
997 unlock_page(pages[i]); 1000 unlock_page(pages[i]);
998 page_cache_release(pages[i]); 1001 page_cache_release(pages[i]);
999 } 1002 }
1000 btrfs_delalloc_release_space(inode, num_pages << PAGE_CACHE_SHIFT); 1003 btrfs_delalloc_release_space(inode, page_cnt << PAGE_CACHE_SHIFT);
1001 return ret; 1004 return ret;
1002 1005
1003} 1006}