aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
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 /fs/btrfs/extent-tree.c
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>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c50
1 files changed, 46 insertions, 4 deletions
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;