diff options
-rw-r--r-- | fs/btrfs/compression.c | 9 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 5 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 50 | ||||
-rw-r--r-- | fs/btrfs/extent_io.h | 1 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 114 | ||||
-rw-r--r-- | fs/btrfs/file.c | 8 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 74 |
7 files changed, 226 insertions, 35 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index ad7274137309..2436163d5436 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
@@ -124,8 +124,7 @@ static int check_compressed_csum(struct inode *inode, | |||
124 | u32 csum; | 124 | u32 csum; |
125 | u32 *cb_sum = &cb->sums; | 125 | u32 *cb_sum = &cb->sums; |
126 | 126 | ||
127 | if (btrfs_test_opt(root, NODATASUM) || | 127 | if (btrfs_test_flag(inode, NODATASUM)) |
128 | btrfs_test_flag(inode, NODATASUM)) | ||
129 | return 0; | 128 | return 0; |
130 | 129 | ||
131 | for (i = 0; i < cb->nr_pages; i++) { | 130 | for (i = 0; i < cb->nr_pages; i++) { |
@@ -671,8 +670,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
671 | */ | 670 | */ |
672 | atomic_inc(&cb->pending_bios); | 671 | atomic_inc(&cb->pending_bios); |
673 | 672 | ||
674 | if (!btrfs_test_opt(root, NODATASUM) && | 673 | if (!btrfs_test_flag(inode, NODATASUM)) { |
675 | !btrfs_test_flag(inode, NODATASUM)) { | ||
676 | btrfs_lookup_bio_sums(root, inode, comp_bio, | 674 | btrfs_lookup_bio_sums(root, inode, comp_bio, |
677 | sums); | 675 | sums); |
678 | } | 676 | } |
@@ -699,8 +697,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
699 | ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, 0); | 697 | ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, 0); |
700 | BUG_ON(ret); | 698 | BUG_ON(ret); |
701 | 699 | ||
702 | if (!btrfs_test_opt(root, NODATASUM) && | 700 | if (!btrfs_test_flag(inode, NODATASUM)) { |
703 | !btrfs_test_flag(inode, NODATASUM)) { | ||
704 | btrfs_lookup_bio_sums(root, inode, comp_bio, sums); | 701 | btrfs_lookup_bio_sums(root, inode, comp_bio, sums); |
705 | } | 702 | } |
706 | 703 | ||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 8733081d97a3..b89999de4564 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1702,7 +1702,7 @@ int btrfs_update_pinned_extents(struct btrfs_root *root, | |||
1702 | int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans, | 1702 | int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans, |
1703 | struct btrfs_root *root, struct extent_buffer *leaf); | 1703 | struct btrfs_root *root, struct extent_buffer *leaf); |
1704 | int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans, | 1704 | int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans, |
1705 | struct btrfs_root *root, u64 bytenr); | 1705 | struct btrfs_root *root, u64 objectid, u64 bytenr); |
1706 | int btrfs_extent_post_op(struct btrfs_trans_handle *trans, | 1706 | int btrfs_extent_post_op(struct btrfs_trans_handle *trans, |
1707 | struct btrfs_root *root); | 1707 | struct btrfs_root *root); |
1708 | int btrfs_copy_pinned(struct btrfs_root *root, struct extent_io_tree *copy); | 1708 | int btrfs_copy_pinned(struct btrfs_root *root, struct extent_io_tree *copy); |
@@ -1789,6 +1789,7 @@ int btrfs_reloc_tree_cache_ref(struct btrfs_trans_handle *trans, | |||
1789 | struct extent_buffer *buf, u64 orig_start); | 1789 | struct extent_buffer *buf, u64 orig_start); |
1790 | int btrfs_add_dead_reloc_root(struct btrfs_root *root); | 1790 | int btrfs_add_dead_reloc_root(struct btrfs_root *root); |
1791 | int btrfs_cleanup_reloc_trees(struct btrfs_root *root); | 1791 | int btrfs_cleanup_reloc_trees(struct btrfs_root *root); |
1792 | int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len); | ||
1792 | u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags); | 1793 | u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags); |
1793 | /* ctree.c */ | 1794 | /* ctree.c */ |
1794 | int btrfs_previous_item(struct btrfs_root *root, | 1795 | int btrfs_previous_item(struct btrfs_root *root, |
@@ -1994,6 +1995,8 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, | |||
1994 | int btrfs_csum_truncate(struct btrfs_trans_handle *trans, | 1995 | int btrfs_csum_truncate(struct btrfs_trans_handle *trans, |
1995 | struct btrfs_root *root, struct btrfs_path *path, | 1996 | struct btrfs_root *root, struct btrfs_path *path, |
1996 | u64 isize); | 1997 | u64 isize); |
1998 | int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, | ||
1999 | u64 end, struct list_head *list); | ||
1997 | /* inode.c */ | 2000 | /* inode.c */ |
1998 | 2001 | ||
1999 | /* RHEL and EL kernels have a patch that renames PG_checked to FsMisc */ | 2002 | /* RHEL and EL kernels have a patch that renames PG_checked to FsMisc */ |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 171057a32679..8004695d24d6 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1359,7 +1359,7 @@ out: | |||
1359 | } | 1359 | } |
1360 | 1360 | ||
1361 | int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans, | 1361 | int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans, |
1362 | struct btrfs_root *root, u64 bytenr) | 1362 | struct btrfs_root *root, u64 objectid, u64 bytenr) |
1363 | { | 1363 | { |
1364 | struct btrfs_root *extent_root = root->fs_info->extent_root; | 1364 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
1365 | struct btrfs_path *path; | 1365 | struct btrfs_path *path; |
@@ -1418,8 +1418,9 @@ int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans, | |||
1418 | ref_item = btrfs_item_ptr(leaf, path->slots[0], | 1418 | ref_item = btrfs_item_ptr(leaf, path->slots[0], |
1419 | struct btrfs_extent_ref); | 1419 | struct btrfs_extent_ref); |
1420 | ref_root = btrfs_ref_root(leaf, ref_item); | 1420 | ref_root = btrfs_ref_root(leaf, ref_item); |
1421 | if (ref_root != root->root_key.objectid && | 1421 | if ((ref_root != root->root_key.objectid && |
1422 | ref_root != BTRFS_TREE_LOG_OBJECTID) { | 1422 | ref_root != BTRFS_TREE_LOG_OBJECTID) || |
1423 | objectid != btrfs_ref_objectid(leaf, ref_item)) { | ||
1423 | ret = 1; | 1424 | ret = 1; |
1424 | goto out; | 1425 | goto out; |
1425 | } | 1426 | } |
@@ -5367,7 +5368,6 @@ static int noinline relocate_one_extent(struct btrfs_root *extent_root, | |||
5367 | if (ret) | 5368 | if (ret) |
5368 | goto out; | 5369 | goto out; |
5369 | } | 5370 | } |
5370 | btrfs_record_root_in_trans(found_root); | ||
5371 | ret = replace_one_extent(trans, found_root, | 5371 | ret = replace_one_extent(trans, found_root, |
5372 | path, extent_key, | 5372 | path, extent_key, |
5373 | &first_key, ref_path, | 5373 | &first_key, ref_path, |
@@ -5534,6 +5534,7 @@ static struct inode noinline *create_reloc_inode(struct btrfs_fs_info *fs_info, | |||
5534 | } else { | 5534 | } else { |
5535 | BUG_ON(1); | 5535 | BUG_ON(1); |
5536 | } | 5536 | } |
5537 | BTRFS_I(inode)->index_cnt = group->key.objectid; | ||
5537 | 5538 | ||
5538 | err = btrfs_orphan_add(trans, inode); | 5539 | err = btrfs_orphan_add(trans, inode); |
5539 | out: | 5540 | out: |
@@ -5546,6 +5547,47 @@ out: | |||
5546 | return inode; | 5547 | return inode; |
5547 | } | 5548 | } |
5548 | 5549 | ||
5550 | int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len) | ||
5551 | { | ||
5552 | |||
5553 | struct btrfs_ordered_sum *sums; | ||
5554 | struct btrfs_sector_sum *sector_sum; | ||
5555 | struct btrfs_ordered_extent *ordered; | ||
5556 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
5557 | struct list_head list; | ||
5558 | size_t offset; | ||
5559 | int ret; | ||
5560 | u64 disk_bytenr; | ||
5561 | |||
5562 | INIT_LIST_HEAD(&list); | ||
5563 | |||
5564 | ordered = btrfs_lookup_ordered_extent(inode, file_pos); | ||
5565 | BUG_ON(ordered->file_offset != file_pos || ordered->len != len); | ||
5566 | |||
5567 | disk_bytenr = file_pos + BTRFS_I(inode)->index_cnt; | ||
5568 | ret = btrfs_lookup_csums_range(root, disk_bytenr, | ||
5569 | disk_bytenr + len - 1, &list); | ||
5570 | |||
5571 | while (!list_empty(&list)) { | ||
5572 | sums = list_entry(list.next, struct btrfs_ordered_sum, list); | ||
5573 | list_del_init(&sums->list); | ||
5574 | |||
5575 | sector_sum = sums->sums; | ||
5576 | sums->bytenr = ordered->start; | ||
5577 | |||
5578 | offset = 0; | ||
5579 | while (offset < sums->len) { | ||
5580 | sector_sum->bytenr += ordered->start - disk_bytenr; | ||
5581 | sector_sum++; | ||
5582 | offset += root->sectorsize; | ||
5583 | } | ||
5584 | |||
5585 | btrfs_add_ordered_sum(inode, ordered, sums); | ||
5586 | } | ||
5587 | btrfs_put_ordered_extent(ordered); | ||
5588 | return 0; | ||
5589 | } | ||
5590 | |||
5549 | int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start) | 5591 | int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start) |
5550 | { | 5592 | { |
5551 | struct btrfs_trans_handle *trans; | 5593 | struct btrfs_trans_handle *trans; |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 2d5f67065b69..c5b483a79137 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #define EXTENT_ORDERED (1 << 9) | 16 | #define EXTENT_ORDERED (1 << 9) |
17 | #define EXTENT_ORDERED_METADATA (1 << 10) | 17 | #define EXTENT_ORDERED_METADATA (1 << 10) |
18 | #define EXTENT_BOUNDARY (1 << 11) | 18 | #define EXTENT_BOUNDARY (1 << 11) |
19 | #define EXTENT_NODATASUM (1 << 12) | ||
19 | #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) | 20 | #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) |
20 | 21 | ||
21 | /* flags for bio submission */ | 22 | /* flags for bio submission */ |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 3ebef871ee6c..df0447632dbd 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -140,6 +140,7 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, | |||
140 | return ret; | 140 | return ret; |
141 | } | 141 | } |
142 | 142 | ||
143 | |||
143 | int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, | 144 | int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, |
144 | struct bio *bio, u32 *dst) | 145 | struct bio *bio, u32 *dst) |
145 | { | 146 | { |
@@ -185,9 +186,16 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, | |||
185 | if (ret == -ENOENT || ret == -EFBIG) | 186 | if (ret == -ENOENT || ret == -EFBIG) |
186 | ret = 0; | 187 | ret = 0; |
187 | sum = 0; | 188 | sum = 0; |
188 | printk("no csum found for inode %lu start " | 189 | if (BTRFS_I(inode)->root->root_key.objectid == |
189 | "%llu\n", inode->i_ino, | 190 | BTRFS_DATA_RELOC_TREE_OBJECTID) { |
190 | (unsigned long long)offset); | 191 | set_extent_bits(io_tree, offset, |
192 | offset + bvec->bv_len - 1, | ||
193 | EXTENT_NODATASUM, GFP_NOFS); | ||
194 | } else { | ||
195 | printk("no csum found for inode %lu " | ||
196 | "start %llu\n", inode->i_ino, | ||
197 | (unsigned long long)offset); | ||
198 | } | ||
191 | item = NULL; | 199 | item = NULL; |
192 | btrfs_release_path(root, path); | 200 | btrfs_release_path(root, path); |
193 | goto found; | 201 | goto found; |
@@ -228,6 +236,106 @@ found: | |||
228 | return 0; | 236 | return 0; |
229 | } | 237 | } |
230 | 238 | ||
239 | int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, | ||
240 | struct list_head *list) | ||
241 | { | ||
242 | struct btrfs_key key; | ||
243 | struct btrfs_path *path; | ||
244 | struct extent_buffer *leaf; | ||
245 | struct btrfs_ordered_sum *sums; | ||
246 | struct btrfs_sector_sum *sector_sum; | ||
247 | struct btrfs_csum_item *item; | ||
248 | unsigned long offset; | ||
249 | int ret; | ||
250 | size_t size; | ||
251 | u64 csum_end; | ||
252 | u16 csum_size = btrfs_super_csum_size(&root->fs_info->super_copy); | ||
253 | |||
254 | path = btrfs_alloc_path(); | ||
255 | BUG_ON(!path); | ||
256 | |||
257 | key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; | ||
258 | key.offset = start; | ||
259 | key.type = BTRFS_EXTENT_CSUM_KEY; | ||
260 | |||
261 | ret = btrfs_search_slot(NULL, root->fs_info->csum_root, | ||
262 | &key, path, 0, 0); | ||
263 | if (ret < 0) | ||
264 | goto fail; | ||
265 | if (ret > 0 && path->slots[0] > 0) { | ||
266 | leaf = path->nodes[0]; | ||
267 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1); | ||
268 | if (key.objectid == BTRFS_EXTENT_CSUM_OBJECTID && | ||
269 | key.type == BTRFS_EXTENT_CSUM_KEY) { | ||
270 | offset = (start - key.offset) >> | ||
271 | root->fs_info->sb->s_blocksize_bits; | ||
272 | if (offset * csum_size < | ||
273 | btrfs_item_size_nr(leaf, path->slots[0] - 1)) | ||
274 | path->slots[0]--; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | while (start <= end) { | ||
279 | leaf = path->nodes[0]; | ||
280 | if (path->slots[0] >= btrfs_header_nritems(leaf)) { | ||
281 | ret = btrfs_next_leaf(root->fs_info->csum_root, path); | ||
282 | if (ret < 0) | ||
283 | goto fail; | ||
284 | if (ret > 0) | ||
285 | break; | ||
286 | leaf = path->nodes[0]; | ||
287 | } | ||
288 | |||
289 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
290 | if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || | ||
291 | key.type != BTRFS_EXTENT_CSUM_KEY) | ||
292 | break; | ||
293 | |||
294 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
295 | if (key.offset > end) | ||
296 | break; | ||
297 | |||
298 | if (key.offset > start) | ||
299 | start = key.offset; | ||
300 | |||
301 | size = btrfs_item_size_nr(leaf, path->slots[0]); | ||
302 | csum_end = key.offset + (size / csum_size) * root->sectorsize; | ||
303 | |||
304 | size = min(csum_end, end + 1) - start; | ||
305 | sums = kzalloc(btrfs_ordered_sum_size(root, size), GFP_NOFS); | ||
306 | BUG_ON(!sums); | ||
307 | |||
308 | sector_sum = sums->sums; | ||
309 | sums->bytenr = start; | ||
310 | sums->len = size; | ||
311 | |||
312 | offset = (start - key.offset) >> | ||
313 | root->fs_info->sb->s_blocksize_bits; | ||
314 | offset *= csum_size; | ||
315 | |||
316 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], | ||
317 | struct btrfs_csum_item); | ||
318 | while (size > 0) { | ||
319 | read_extent_buffer(path->nodes[0], §or_sum->sum, | ||
320 | ((unsigned long)item) + offset, | ||
321 | csum_size); | ||
322 | sector_sum->bytenr = start; | ||
323 | |||
324 | size -= root->sectorsize; | ||
325 | start += root->sectorsize; | ||
326 | offset += csum_size; | ||
327 | sector_sum++; | ||
328 | } | ||
329 | list_add_tail(&sums->list, list); | ||
330 | |||
331 | path->slots[0]++; | ||
332 | } | ||
333 | ret = 0; | ||
334 | fail: | ||
335 | btrfs_free_path(path); | ||
336 | return ret; | ||
337 | } | ||
338 | |||
231 | int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | 339 | int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, |
232 | struct bio *bio, u64 file_start, int contig) | 340 | struct bio *bio, u64 file_start, int contig) |
233 | { | 341 | { |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 71bfe3a6a444..507081059d97 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1060,14 +1060,6 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1060 | last_index = (pos + count) >> PAGE_CACHE_SHIFT; | 1060 | last_index = (pos + count) >> PAGE_CACHE_SHIFT; |
1061 | 1061 | ||
1062 | /* | 1062 | /* |
1063 | * if this is a nodatasum mount, force summing off for the inode | ||
1064 | * all the time. That way a later mount with summing on won't | ||
1065 | * get confused | ||
1066 | */ | ||
1067 | if (btrfs_test_opt(root, NODATASUM)) | ||
1068 | btrfs_set_flag(inode, NODATASUM); | ||
1069 | |||
1070 | /* | ||
1071 | * there are lots of better ways to do this, but this code | 1063 | * there are lots of better ways to do this, but this code |
1072 | * makes sure the first and last page in the file range are | 1064 | * makes sure the first and last page in the file range are |
1073 | * up to date and ready for cow | 1065 | * up to date and ready for cow |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 0a28b7706314..e64a4fe19a60 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -771,6 +771,13 @@ static noinline int cow_file_range(struct inode *inode, | |||
771 | ram_size, cur_alloc_size, 0); | 771 | ram_size, cur_alloc_size, 0); |
772 | BUG_ON(ret); | 772 | BUG_ON(ret); |
773 | 773 | ||
774 | if (root->root_key.objectid == | ||
775 | BTRFS_DATA_RELOC_TREE_OBJECTID) { | ||
776 | ret = btrfs_reloc_clone_csums(inode, start, | ||
777 | cur_alloc_size); | ||
778 | BUG_ON(ret); | ||
779 | } | ||
780 | |||
774 | if (disk_num_bytes < cur_alloc_size) { | 781 | if (disk_num_bytes < cur_alloc_size) { |
775 | printk("num_bytes %Lu cur_alloc %Lu\n", disk_num_bytes, | 782 | printk("num_bytes %Lu cur_alloc %Lu\n", disk_num_bytes, |
776 | cur_alloc_size); | 783 | cur_alloc_size); |
@@ -910,6 +917,26 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page, | |||
910 | return 0; | 917 | return 0; |
911 | } | 918 | } |
912 | 919 | ||
920 | static int noinline csum_exist_in_range(struct btrfs_root *root, | ||
921 | u64 bytenr, u64 num_bytes) | ||
922 | { | ||
923 | int ret; | ||
924 | struct btrfs_ordered_sum *sums; | ||
925 | LIST_HEAD(list); | ||
926 | |||
927 | ret = btrfs_lookup_csums_range(root, bytenr, bytenr + num_bytes - 1, | ||
928 | &list); | ||
929 | if (ret == 0 && list_empty(&list)) | ||
930 | return 0; | ||
931 | |||
932 | while (!list_empty(&list)) { | ||
933 | sums = list_entry(list.next, struct btrfs_ordered_sum, list); | ||
934 | list_del(&sums->list); | ||
935 | kfree(sums); | ||
936 | } | ||
937 | return 1; | ||
938 | } | ||
939 | |||
913 | /* | 940 | /* |
914 | * when nowcow writeback call back. This checks for snapshots or COW copies | 941 | * when nowcow writeback call back. This checks for snapshots or COW copies |
915 | * of the extents that exist in the file, and COWs the file as required. | 942 | * of the extents that exist in the file, and COWs the file as required. |
@@ -971,6 +998,7 @@ next_slot: | |||
971 | 998 | ||
972 | nocow = 0; | 999 | nocow = 0; |
973 | disk_bytenr = 0; | 1000 | disk_bytenr = 0; |
1001 | num_bytes = 0; | ||
974 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | 1002 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
975 | 1003 | ||
976 | if (found_key.objectid > inode->i_ino || | 1004 | if (found_key.objectid > inode->i_ino || |
@@ -996,19 +1024,29 @@ next_slot: | |||
996 | path->slots[0]++; | 1024 | path->slots[0]++; |
997 | goto next_slot; | 1025 | goto next_slot; |
998 | } | 1026 | } |
1027 | if (disk_bytenr == 0) | ||
1028 | goto out_check; | ||
999 | if (btrfs_file_extent_compression(leaf, fi) || | 1029 | if (btrfs_file_extent_compression(leaf, fi) || |
1000 | btrfs_file_extent_encryption(leaf, fi) || | 1030 | btrfs_file_extent_encryption(leaf, fi) || |
1001 | btrfs_file_extent_other_encoding(leaf, fi)) | 1031 | btrfs_file_extent_other_encoding(leaf, fi)) |
1002 | goto out_check; | 1032 | goto out_check; |
1003 | if (disk_bytenr == 0) | ||
1004 | goto out_check; | ||
1005 | if (extent_type == BTRFS_FILE_EXTENT_REG && !force) | 1033 | if (extent_type == BTRFS_FILE_EXTENT_REG && !force) |
1006 | goto out_check; | 1034 | goto out_check; |
1007 | if (btrfs_cross_ref_exist(trans, root, disk_bytenr)) | ||
1008 | goto out_check; | ||
1009 | if (btrfs_extent_readonly(root, disk_bytenr)) | 1035 | if (btrfs_extent_readonly(root, disk_bytenr)) |
1010 | goto out_check; | 1036 | goto out_check; |
1037 | if (btrfs_cross_ref_exist(trans, root, inode->i_ino, | ||
1038 | disk_bytenr)) | ||
1039 | goto out_check; | ||
1011 | disk_bytenr += btrfs_file_extent_offset(leaf, fi); | 1040 | disk_bytenr += btrfs_file_extent_offset(leaf, fi); |
1041 | disk_bytenr += cur_offset - found_key.offset; | ||
1042 | num_bytes = min(end + 1, extent_end) - cur_offset; | ||
1043 | /* | ||
1044 | * force cow if csum exists in the range. | ||
1045 | * this ensure that csum for a given extent are | ||
1046 | * either valid or do not exist. | ||
1047 | */ | ||
1048 | if (csum_exist_in_range(root, disk_bytenr, num_bytes)) | ||
1049 | goto out_check; | ||
1012 | nocow = 1; | 1050 | nocow = 1; |
1013 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | 1051 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { |
1014 | extent_end = found_key.offset + | 1052 | extent_end = found_key.offset + |
@@ -1041,8 +1079,6 @@ out_check: | |||
1041 | cow_start = (u64)-1; | 1079 | cow_start = (u64)-1; |
1042 | } | 1080 | } |
1043 | 1081 | ||
1044 | disk_bytenr += cur_offset - found_key.offset; | ||
1045 | num_bytes = min(end + 1, extent_end) - cur_offset; | ||
1046 | if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) { | 1082 | if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) { |
1047 | struct extent_map *em; | 1083 | struct extent_map *em; |
1048 | struct extent_map_tree *em_tree; | 1084 | struct extent_map_tree *em_tree; |
@@ -1105,11 +1141,9 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page, | |||
1105 | u64 start, u64 end, int *page_started, | 1141 | u64 start, u64 end, int *page_started, |
1106 | unsigned long *nr_written) | 1142 | unsigned long *nr_written) |
1107 | { | 1143 | { |
1108 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
1109 | int ret; | 1144 | int ret; |
1110 | 1145 | ||
1111 | if (btrfs_test_opt(root, NODATACOW) || | 1146 | if (btrfs_test_flag(inode, NODATACOW)) |
1112 | btrfs_test_flag(inode, NODATACOW)) | ||
1113 | ret = run_delalloc_nocow(inode, locked_page, start, end, | 1147 | ret = run_delalloc_nocow(inode, locked_page, start, end, |
1114 | page_started, 1, nr_written); | 1148 | page_started, 1, nr_written); |
1115 | else if (btrfs_test_flag(inode, PREALLOC)) | 1149 | else if (btrfs_test_flag(inode, PREALLOC)) |
@@ -1252,8 +1286,7 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
1252 | ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0); | 1286 | ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0); |
1253 | BUG_ON(ret); | 1287 | BUG_ON(ret); |
1254 | 1288 | ||
1255 | skip_sum = btrfs_test_opt(root, NODATASUM) || | 1289 | skip_sum = btrfs_test_flag(inode, NODATASUM); |
1256 | btrfs_test_flag(inode, NODATASUM); | ||
1257 | 1290 | ||
1258 | if (!(rw & (1 << BIO_RW))) { | 1291 | if (!(rw & (1 << BIO_RW))) { |
1259 | if (bio_flags & EXTENT_BIO_COMPRESSED) { | 1292 | if (bio_flags & EXTENT_BIO_COMPRESSED) { |
@@ -1263,6 +1296,9 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
1263 | btrfs_lookup_bio_sums(root, inode, bio, NULL); | 1296 | btrfs_lookup_bio_sums(root, inode, bio, NULL); |
1264 | goto mapit; | 1297 | goto mapit; |
1265 | } else if (!skip_sum) { | 1298 | } else if (!skip_sum) { |
1299 | /* csum items have already been cloned */ | ||
1300 | if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID) | ||
1301 | goto mapit; | ||
1266 | /* we're doing a write, do the async checksumming */ | 1302 | /* we're doing a write, do the async checksumming */ |
1267 | return btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, | 1303 | return btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, |
1268 | inode, rw, bio, mirror_num, | 1304 | inode, rw, bio, mirror_num, |
@@ -1692,9 +1728,15 @@ static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end, | |||
1692 | ClearPageChecked(page); | 1728 | ClearPageChecked(page); |
1693 | goto good; | 1729 | goto good; |
1694 | } | 1730 | } |
1695 | if (btrfs_test_opt(root, NODATASUM) || | 1731 | if (btrfs_test_flag(inode, NODATASUM)) |
1696 | btrfs_test_flag(inode, NODATASUM)) | 1732 | return 0; |
1733 | |||
1734 | if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID && | ||
1735 | test_range_bit(io_tree, start, end, EXTENT_NODATASUM, 1)) { | ||
1736 | clear_extent_bits(io_tree, start, end, EXTENT_NODATASUM, | ||
1737 | GFP_NOFS); | ||
1697 | return 0; | 1738 | return 0; |
1739 | } | ||
1698 | 1740 | ||
1699 | if (state && state->start == start) { | 1741 | if (state && state->start == start) { |
1700 | private = state->private; | 1742 | private = state->private; |
@@ -3391,6 +3433,12 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
3391 | owner = 1; | 3433 | owner = 1; |
3392 | BTRFS_I(inode)->block_group = | 3434 | BTRFS_I(inode)->block_group = |
3393 | btrfs_find_block_group(root, 0, alloc_hint, owner); | 3435 | btrfs_find_block_group(root, 0, alloc_hint, owner); |
3436 | if ((mode & S_IFREG)) { | ||
3437 | if (btrfs_test_opt(root, NODATASUM)) | ||
3438 | btrfs_set_flag(inode, NODATASUM); | ||
3439 | if (btrfs_test_opt(root, NODATACOW)) | ||
3440 | btrfs_set_flag(inode, NODATACOW); | ||
3441 | } | ||
3394 | 3442 | ||
3395 | key[0].objectid = objectid; | 3443 | key[0].objectid = objectid; |
3396 | btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY); | 3444 | btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY); |