aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2008-12-12 10:03:38 -0500
committerChris Mason <chris.mason@oracle.com>2008-12-12 10:03:38 -0500
commit17d217fe970d34720f4f1633dca73a6aa2f3d9d1 (patch)
tree4e2e716400cc45a6697475629f4c046b96ff76e7
parente4404d6e8da678d852b7f767f665f8edf76c9e9f (diff)
Btrfs: fix nodatasum handling in balancing code
Checksums on data can be disabled by mount option, so it's possible some data extents don't have checksums or have invalid checksums. This causes trouble for data relocation. This patch contains following things to make data relocation work. 1) make nodatasum/nodatacow mount option only affects new files. Checksums and COW on data are only controlled by the inode flags. 2) check the existence of checksum in the nodatacow checker. If checksums exist, force COW the data extent. This ensure that checksum for a given block is either valid or does not exist. 3) update data relocation code to properly handle the case of checksum missing. Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
-rw-r--r--fs/btrfs/compression.c9
-rw-r--r--fs/btrfs/ctree.h5
-rw-r--r--fs/btrfs/extent-tree.c50
-rw-r--r--fs/btrfs/extent_io.h1
-rw-r--r--fs/btrfs/file-item.c114
-rw-r--r--fs/btrfs/file.c8
-rw-r--r--fs/btrfs/inode.c74
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,
1702int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans, 1702int 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);
1704int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans, 1704int 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);
1706int btrfs_extent_post_op(struct btrfs_trans_handle *trans, 1706int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
1707 struct btrfs_root *root); 1707 struct btrfs_root *root);
1708int btrfs_copy_pinned(struct btrfs_root *root, struct extent_io_tree *copy); 1708int 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);
1790int btrfs_add_dead_reloc_root(struct btrfs_root *root); 1790int btrfs_add_dead_reloc_root(struct btrfs_root *root);
1791int btrfs_cleanup_reloc_trees(struct btrfs_root *root); 1791int btrfs_cleanup_reloc_trees(struct btrfs_root *root);
1792int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len);
1792u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags); 1793u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags);
1793/* ctree.c */ 1794/* ctree.c */
1794int btrfs_previous_item(struct btrfs_root *root, 1795int btrfs_previous_item(struct btrfs_root *root,
@@ -1994,6 +1995,8 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans,
1994int btrfs_csum_truncate(struct btrfs_trans_handle *trans, 1995int 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);
1998int 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
1361int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans, 1361int 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);
5539out: 5540out:
@@ -5546,6 +5547,47 @@ out:
5546 return inode; 5547 return inode;
5547} 5548}
5548 5549
5550int 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
5549int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start) 5591int 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
143int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, 144int 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
239int 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], &sector_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;
334fail:
335 btrfs_free_path(path);
336 return ret;
337}
338
231int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, 339int 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
920static 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);