summaryrefslogtreecommitdiff
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2008-08-05 13:05:02 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:06 -0400
commit7ea394f1192bee1af67ea4762c88ef4b7b0487a8 (patch)
treee2c593d054d802bc71e86508a5b7523ff80cc1ea /fs/btrfs/inode.c
parent00e4e6b33a0f78aab4b788d6d31c884fd8bf88da (diff)
downloadlwn-7ea394f1192bee1af67ea4762c88ef4b7b0487a8.tar.gz
lwn-7ea394f1192bee1af67ea4762c88ef4b7b0487a8.zip
Btrfs: Fix nodatacow for the new data=ordered mode
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c60
1 files changed, 38 insertions, 22 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 4d8ffc01931e..c33053ba3816 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -166,7 +166,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end)
cur_alloc_size = ins.offset;
ret = btrfs_add_ordered_extent(inode, start, ins.objectid,
- ins.offset);
+ ins.offset, 0);
BUG_ON(ret);
if (num_bytes < cur_alloc_size) {
printk("num_bytes %Lu cur_alloc %Lu\n", num_bytes,
@@ -187,31 +187,32 @@ static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end)
u64 extent_start;
u64 extent_end;
u64 bytenr;
- u64 cow_end;
u64 loops = 0;
u64 total_fs_bytes;
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_block_group_cache *block_group;
+ struct btrfs_trans_handle *trans;
struct extent_buffer *leaf;
int found_type;
struct btrfs_path *path;
struct btrfs_file_extent_item *item;
int ret;
- int err;
+ int err = 0;
struct btrfs_key found_key;
total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy);
path = btrfs_alloc_path();
BUG_ON(!path);
+ trans = btrfs_join_transaction(root, 1);
+ BUG_ON(!trans);
again:
ret = btrfs_lookup_file_extent(NULL, root, path,
inode->i_ino, start, 0);
if (ret < 0) {
- btrfs_free_path(path);
- return ret;
+ err = ret;
+ goto out;
}
- cow_end = end;
if (ret != 0) {
if (path->slots[0] == 0)
goto not_found;
@@ -244,12 +245,11 @@ again:
if (start < extent_start || start >= extent_end)
goto not_found;
- cow_end = min(end, extent_end - 1);
bytenr = btrfs_file_extent_disk_bytenr(leaf, item);
if (bytenr == 0)
goto not_found;
- if (btrfs_cross_ref_exists(root, &found_key, bytenr))
+ if (btrfs_cross_ref_exists(trans, root, &found_key, bytenr))
goto not_found;
/*
* we may be called by the resizer, make sure we're inside
@@ -260,24 +260,32 @@ again:
if (!block_group || block_group->ro)
goto not_found;
+ bytenr += btrfs_file_extent_offset(leaf, item);
+ extent_num_bytes = min(end + 1, extent_end) - start;
+ ret = btrfs_add_ordered_extent(inode, start, bytenr,
+ extent_num_bytes, 1);
+ if (ret) {
+ err = ret;
+ goto out;
+ }
+
+ btrfs_release_path(root, path);
start = extent_end;
+ if (start <= end) {
+ loops++;
+ goto again;
+ }
} else {
- goto not_found;
- }
-loop:
- if (start > end) {
+not_found:
+ btrfs_end_transaction(trans, root);
btrfs_free_path(path);
- return 0;
+ return cow_file_range(inode, start, end);
}
- btrfs_release_path(root, path);
- loops++;
- goto again;
-
-not_found:
- btrfs_release_path(root, path);
- cow_file_range(inode, start, end);
- start = end + 1;
- goto loop;
+out:
+ WARN_ON(err);
+ btrfs_end_transaction(trans, root);
+ btrfs_free_path(path);
+ return err;
}
static int run_delalloc_range(struct inode *inode, u64 start, u64 end)
@@ -385,6 +393,11 @@ int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
goto mapit;
}
+ if (btrfs_test_opt(root, NODATASUM) ||
+ btrfs_test_flag(inode, NODATASUM)) {
+ goto mapit;
+ }
+
return btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info,
inode, rw, bio, mirror_num,
__btrfs_submit_bio_hook);
@@ -527,6 +540,8 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
ordered_extent = btrfs_lookup_ordered_extent(inode, start);
BUG_ON(!ordered_extent);
+ if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags))
+ goto nocow;
lock_extent(io_tree, ordered_extent->file_offset,
ordered_extent->file_offset + ordered_extent->len - 1,
@@ -567,6 +582,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
unlock_extent(io_tree, ordered_extent->file_offset,
ordered_extent->file_offset + ordered_extent->len - 1,
GFP_NOFS);
+nocow:
add_pending_csums(trans, inode, ordered_extent->file_offset,
&ordered_extent->list);