diff options
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 70 |
1 files changed, 34 insertions, 36 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 4b833972273a..f19e1259a971 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -112,8 +112,6 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
112 | int err = 0; | 112 | int err = 0; |
113 | int i; | 113 | int i; |
114 | struct inode *inode = fdentry(file)->d_inode; | 114 | struct inode *inode = fdentry(file)->d_inode; |
115 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | ||
116 | u64 hint_byte; | ||
117 | u64 num_bytes; | 115 | u64 num_bytes; |
118 | u64 start_pos; | 116 | u64 start_pos; |
119 | u64 end_of_last_block; | 117 | u64 end_of_last_block; |
@@ -125,23 +123,10 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
125 | root->sectorsize - 1) & ~((u64)root->sectorsize - 1); | 123 | root->sectorsize - 1) & ~((u64)root->sectorsize - 1); |
126 | 124 | ||
127 | end_of_last_block = start_pos + num_bytes - 1; | 125 | end_of_last_block = start_pos + num_bytes - 1; |
126 | err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block); | ||
127 | if (err) | ||
128 | return err; | ||
128 | 129 | ||
129 | lock_extent(io_tree, start_pos, end_of_last_block, GFP_NOFS); | ||
130 | trans = btrfs_join_transaction(root, 1); | ||
131 | if (!trans) { | ||
132 | err = -ENOMEM; | ||
133 | goto out_unlock; | ||
134 | } | ||
135 | btrfs_set_trans_block_group(trans, inode); | ||
136 | hint_byte = 0; | ||
137 | |||
138 | set_extent_uptodate(io_tree, start_pos, end_of_last_block, GFP_NOFS); | ||
139 | |||
140 | /* check for reserved extents on each page, we don't want | ||
141 | * to reset the delalloc bit on things that already have | ||
142 | * extents reserved. | ||
143 | */ | ||
144 | btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block); | ||
145 | for (i = 0; i < num_pages; i++) { | 130 | for (i = 0; i < num_pages; i++) { |
146 | struct page *p = pages[i]; | 131 | struct page *p = pages[i]; |
147 | SetPageUptodate(p); | 132 | SetPageUptodate(p); |
@@ -155,9 +140,6 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
155 | * at this time. | 140 | * at this time. |
156 | */ | 141 | */ |
157 | } | 142 | } |
158 | err = btrfs_end_transaction(trans, root); | ||
159 | out_unlock: | ||
160 | unlock_extent(io_tree, start_pos, end_of_last_block, GFP_NOFS); | ||
161 | return err; | 143 | return err; |
162 | } | 144 | } |
163 | 145 | ||
@@ -189,18 +171,18 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
189 | if (!split2) | 171 | if (!split2) |
190 | split2 = alloc_extent_map(GFP_NOFS); | 172 | split2 = alloc_extent_map(GFP_NOFS); |
191 | 173 | ||
192 | spin_lock(&em_tree->lock); | 174 | write_lock(&em_tree->lock); |
193 | em = lookup_extent_mapping(em_tree, start, len); | 175 | em = lookup_extent_mapping(em_tree, start, len); |
194 | if (!em) { | 176 | if (!em) { |
195 | spin_unlock(&em_tree->lock); | 177 | write_unlock(&em_tree->lock); |
196 | break; | 178 | break; |
197 | } | 179 | } |
198 | flags = em->flags; | 180 | flags = em->flags; |
199 | if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) { | 181 | if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) { |
200 | spin_unlock(&em_tree->lock); | ||
201 | if (em->start <= start && | 182 | if (em->start <= start && |
202 | (!testend || em->start + em->len >= start + len)) { | 183 | (!testend || em->start + em->len >= start + len)) { |
203 | free_extent_map(em); | 184 | free_extent_map(em); |
185 | write_unlock(&em_tree->lock); | ||
204 | break; | 186 | break; |
205 | } | 187 | } |
206 | if (start < em->start) { | 188 | if (start < em->start) { |
@@ -210,6 +192,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
210 | start = em->start + em->len; | 192 | start = em->start + em->len; |
211 | } | 193 | } |
212 | free_extent_map(em); | 194 | free_extent_map(em); |
195 | write_unlock(&em_tree->lock); | ||
213 | continue; | 196 | continue; |
214 | } | 197 | } |
215 | compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags); | 198 | compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags); |
@@ -260,7 +243,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
260 | free_extent_map(split); | 243 | free_extent_map(split); |
261 | split = NULL; | 244 | split = NULL; |
262 | } | 245 | } |
263 | spin_unlock(&em_tree->lock); | 246 | write_unlock(&em_tree->lock); |
264 | 247 | ||
265 | /* once for us */ | 248 | /* once for us */ |
266 | free_extent_map(em); | 249 | free_extent_map(em); |
@@ -289,7 +272,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | |||
289 | noinline int btrfs_drop_extents(struct btrfs_trans_handle *trans, | 272 | noinline int btrfs_drop_extents(struct btrfs_trans_handle *trans, |
290 | struct btrfs_root *root, struct inode *inode, | 273 | struct btrfs_root *root, struct inode *inode, |
291 | u64 start, u64 end, u64 locked_end, | 274 | u64 start, u64 end, u64 locked_end, |
292 | u64 inline_limit, u64 *hint_byte) | 275 | u64 inline_limit, u64 *hint_byte, int drop_cache) |
293 | { | 276 | { |
294 | u64 extent_end = 0; | 277 | u64 extent_end = 0; |
295 | u64 search_start = start; | 278 | u64 search_start = start; |
@@ -314,7 +297,8 @@ noinline int btrfs_drop_extents(struct btrfs_trans_handle *trans, | |||
314 | int ret; | 297 | int ret; |
315 | 298 | ||
316 | inline_limit = 0; | 299 | inline_limit = 0; |
317 | btrfs_drop_extent_cache(inode, start, end - 1, 0); | 300 | if (drop_cache) |
301 | btrfs_drop_extent_cache(inode, start, end - 1, 0); | ||
318 | 302 | ||
319 | path = btrfs_alloc_path(); | 303 | path = btrfs_alloc_path(); |
320 | if (!path) | 304 | if (!path) |
@@ -936,21 +920,35 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
936 | start_pos = pos; | 920 | start_pos = pos; |
937 | 921 | ||
938 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | 922 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); |
923 | |||
924 | /* do the reserve before the mutex lock in case we have to do some | ||
925 | * flushing. We wouldn't deadlock, but this is more polite. | ||
926 | */ | ||
927 | err = btrfs_reserve_metadata_for_delalloc(root, inode, 1); | ||
928 | if (err) | ||
929 | goto out_nolock; | ||
930 | |||
931 | mutex_lock(&inode->i_mutex); | ||
932 | |||
939 | current->backing_dev_info = inode->i_mapping->backing_dev_info; | 933 | current->backing_dev_info = inode->i_mapping->backing_dev_info; |
940 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); | 934 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); |
941 | if (err) | 935 | if (err) |
942 | goto out_nolock; | 936 | goto out; |
937 | |||
943 | if (count == 0) | 938 | if (count == 0) |
944 | goto out_nolock; | 939 | goto out; |
945 | 940 | ||
946 | err = file_remove_suid(file); | 941 | err = file_remove_suid(file); |
947 | if (err) | 942 | if (err) |
948 | goto out_nolock; | 943 | goto out; |
944 | |||
949 | file_update_time(file); | 945 | file_update_time(file); |
950 | 946 | ||
951 | pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL); | 947 | pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL); |
952 | 948 | ||
953 | mutex_lock(&inode->i_mutex); | 949 | /* generic_write_checks can change our pos */ |
950 | start_pos = pos; | ||
951 | |||
954 | BTRFS_I(inode)->sequence++; | 952 | BTRFS_I(inode)->sequence++; |
955 | first_index = pos >> PAGE_CACHE_SHIFT; | 953 | first_index = pos >> PAGE_CACHE_SHIFT; |
956 | last_index = (pos + count) >> PAGE_CACHE_SHIFT; | 954 | last_index = (pos + count) >> PAGE_CACHE_SHIFT; |
@@ -1024,9 +1022,8 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1024 | } | 1022 | } |
1025 | 1023 | ||
1026 | if (will_write) { | 1024 | if (will_write) { |
1027 | btrfs_fdatawrite_range(inode->i_mapping, pos, | 1025 | filemap_fdatawrite_range(inode->i_mapping, pos, |
1028 | pos + write_bytes - 1, | 1026 | pos + write_bytes - 1); |
1029 | WB_SYNC_ALL); | ||
1030 | } else { | 1027 | } else { |
1031 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, | 1028 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, |
1032 | num_pages); | 1029 | num_pages); |
@@ -1047,6 +1044,7 @@ out: | |||
1047 | mutex_unlock(&inode->i_mutex); | 1044 | mutex_unlock(&inode->i_mutex); |
1048 | if (ret) | 1045 | if (ret) |
1049 | err = ret; | 1046 | err = ret; |
1047 | btrfs_unreserve_metadata_for_delalloc(root, inode, 1); | ||
1050 | 1048 | ||
1051 | out_nolock: | 1049 | out_nolock: |
1052 | kfree(pages); | 1050 | kfree(pages); |
@@ -1203,7 +1201,7 @@ out: | |||
1203 | return ret > 0 ? EIO : ret; | 1201 | return ret > 0 ? EIO : ret; |
1204 | } | 1202 | } |
1205 | 1203 | ||
1206 | static struct vm_operations_struct btrfs_file_vm_ops = { | 1204 | static const struct vm_operations_struct btrfs_file_vm_ops = { |
1207 | .fault = filemap_fault, | 1205 | .fault = filemap_fault, |
1208 | .page_mkwrite = btrfs_page_mkwrite, | 1206 | .page_mkwrite = btrfs_page_mkwrite, |
1209 | }; | 1207 | }; |
@@ -1215,7 +1213,7 @@ static int btrfs_file_mmap(struct file *filp, struct vm_area_struct *vma) | |||
1215 | return 0; | 1213 | return 0; |
1216 | } | 1214 | } |
1217 | 1215 | ||
1218 | struct file_operations btrfs_file_operations = { | 1216 | const struct file_operations btrfs_file_operations = { |
1219 | .llseek = generic_file_llseek, | 1217 | .llseek = generic_file_llseek, |
1220 | .read = do_sync_read, | 1218 | .read = do_sync_read, |
1221 | .aio_read = generic_file_aio_read, | 1219 | .aio_read = generic_file_aio_read, |