aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c59
1 files changed, 35 insertions, 24 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 03bb62a9ee24..d8b54715c2de 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -861,6 +861,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
861 int i_done; 861 int i_done;
862 struct btrfs_ordered_extent *ordered; 862 struct btrfs_ordered_extent *ordered;
863 struct extent_state *cached_state = NULL; 863 struct extent_state *cached_state = NULL;
864 struct extent_io_tree *tree;
864 gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping); 865 gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
865 866
866 if (isize == 0) 867 if (isize == 0)
@@ -871,18 +872,34 @@ static int cluster_pages_for_defrag(struct inode *inode,
871 num_pages << PAGE_CACHE_SHIFT); 872 num_pages << PAGE_CACHE_SHIFT);
872 if (ret) 873 if (ret)
873 return ret; 874 return ret;
874again:
875 ret = 0;
876 i_done = 0; 875 i_done = 0;
876 tree = &BTRFS_I(inode)->io_tree;
877 877
878 /* step one, lock all the pages */ 878 /* step one, lock all the pages */
879 for (i = 0; i < num_pages; i++) { 879 for (i = 0; i < num_pages; i++) {
880 struct page *page; 880 struct page *page;
881again:
881 page = find_or_create_page(inode->i_mapping, 882 page = find_or_create_page(inode->i_mapping,
882 start_index + i, mask); 883 start_index + i, mask);
883 if (!page) 884 if (!page)
884 break; 885 break;
885 886
887 page_start = page_offset(page);
888 page_end = page_start + PAGE_CACHE_SIZE - 1;
889 while (1) {
890 lock_extent(tree, page_start, page_end, GFP_NOFS);
891 ordered = btrfs_lookup_ordered_extent(inode,
892 page_start);
893 unlock_extent(tree, page_start, page_end, GFP_NOFS);
894 if (!ordered)
895 break;
896
897 unlock_page(page);
898 btrfs_start_ordered_extent(inode, ordered, 1);
899 btrfs_put_ordered_extent(ordered);
900 lock_page(page);
901 }
902
886 if (!PageUptodate(page)) { 903 if (!PageUptodate(page)) {
887 btrfs_readpage(NULL, page); 904 btrfs_readpage(NULL, page);
888 lock_page(page); 905 lock_page(page);
@@ -893,15 +910,22 @@ again:
893 break; 910 break;
894 } 911 }
895 } 912 }
913
896 isize = i_size_read(inode); 914 isize = i_size_read(inode);
897 file_end = (isize - 1) >> PAGE_CACHE_SHIFT; 915 file_end = (isize - 1) >> PAGE_CACHE_SHIFT;
898 if (!isize || page->index > file_end || 916 if (!isize || page->index > file_end) {
899 page->mapping != inode->i_mapping) {
900 /* whoops, we blew past eof, skip this page */ 917 /* whoops, we blew past eof, skip this page */
901 unlock_page(page); 918 unlock_page(page);
902 page_cache_release(page); 919 page_cache_release(page);
903 break; 920 break;
904 } 921 }
922
923 if (page->mapping != inode->i_mapping) {
924 unlock_page(page);
925 page_cache_release(page);
926 goto again;
927 }
928
905 pages[i] = page; 929 pages[i] = page;
906 i_done++; 930 i_done++;
907 } 931 }
@@ -924,25 +948,6 @@ again:
924 lock_extent_bits(&BTRFS_I(inode)->io_tree, 948 lock_extent_bits(&BTRFS_I(inode)->io_tree,
925 page_start, page_end - 1, 0, &cached_state, 949 page_start, page_end - 1, 0, &cached_state,
926 GFP_NOFS); 950 GFP_NOFS);
927 ordered = btrfs_lookup_first_ordered_extent(inode, page_end - 1);
928 if (ordered &&
929 ordered->file_offset + ordered->len > page_start &&
930 ordered->file_offset < page_end) {
931 btrfs_put_ordered_extent(ordered);
932 unlock_extent_cached(&BTRFS_I(inode)->io_tree,
933 page_start, page_end - 1,
934 &cached_state, GFP_NOFS);
935 for (i = 0; i < i_done; i++) {
936 unlock_page(pages[i]);
937 page_cache_release(pages[i]);
938 }
939 btrfs_wait_ordered_range(inode, page_start,
940 page_end - page_start);
941 goto again;
942 }
943 if (ordered)
944 btrfs_put_ordered_extent(ordered);
945
946 clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start, 951 clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start,
947 page_end - 1, EXTENT_DIRTY | EXTENT_DELALLOC | 952 page_end - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
948 EXTENT_DO_ACCOUNTING, 0, 0, &cached_state, 953 EXTENT_DO_ACCOUNTING, 0, 0, &cached_state,
@@ -1327,6 +1332,12 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
1327 goto out; 1332 goto out;
1328 } 1333 }
1329 1334
1335 if (name[0] == '.' &&
1336 (namelen == 1 || (name[1] == '.' && namelen == 2))) {
1337 ret = -EEXIST;
1338 goto out;
1339 }
1340
1330 if (subvol) { 1341 if (subvol) {
1331 ret = btrfs_mksubvol(&file->f_path, name, namelen, 1342 ret = btrfs_mksubvol(&file->f_path, name, namelen,
1332 NULL, transid, readonly); 1343 NULL, transid, readonly);