Loading fs/btrfs/ctree.h +2 −1 Original line number Diff line number Diff line Loading @@ -1403,7 +1403,8 @@ static inline struct dentry *fdentry(struct file *file) { } /* extent-tree.c */ int btrfs_cross_ref_exists(struct btrfs_root *root, int btrfs_cross_ref_exists(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, u64 bytenr); int btrfs_extent_post_op(struct btrfs_trans_handle *trans, struct btrfs_root *root); Loading fs/btrfs/extent-tree.c +5 −6 Original line number Diff line number Diff line Loading @@ -893,10 +893,10 @@ static int get_reference_status(struct btrfs_root *root, u64 bytenr, return ret; } int btrfs_cross_ref_exists(struct btrfs_root *root, int btrfs_cross_ref_exists(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, u64 bytenr) { struct btrfs_trans_handle *trans; struct btrfs_root *old_root; struct btrfs_path *path = NULL; struct extent_buffer *eb; Loading @@ -908,6 +908,7 @@ int btrfs_cross_ref_exists(struct btrfs_root *root, int level; int ret; BUG_ON(trans == NULL); BUG_ON(key->type != BTRFS_EXTENT_DATA_KEY); ret = get_reference_status(root, bytenr, 0, key->objectid, &min_generation, &ref_count); Loading @@ -917,7 +918,6 @@ int btrfs_cross_ref_exists(struct btrfs_root *root, if (ref_count != 1) return 1; trans = btrfs_start_transaction(root, 0); old_root = root->dirty_root->root; ref_generation = old_root->root_key.offset; Loading Loading @@ -973,7 +973,6 @@ int btrfs_cross_ref_exists(struct btrfs_root *root, out: if (path) btrfs_free_path(path); btrfs_end_transaction(trans, root); return ret; } Loading Loading @@ -3320,7 +3319,7 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start) mutex_unlock(&root->fs_info->alloc_mutex); btrfs_start_delalloc_inodes(root); btrfs_wait_ordered_extents(tree_root); btrfs_wait_ordered_extents(tree_root, 0); mutex_lock(&root->fs_info->alloc_mutex); Loading Loading @@ -3407,7 +3406,7 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start) btrfs_clean_old_snapshots(tree_root); btrfs_start_delalloc_inodes(root); btrfs_wait_ordered_extents(tree_root); btrfs_wait_ordered_extents(tree_root, 0); trans = btrfs_start_transaction(tree_root, 1); btrfs_commit_transaction(trans, tree_root); Loading fs/btrfs/inode.c +38 −22 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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; Loading Loading @@ -244,12 +245,11 @@ static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end) 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 Loading @@ -260,24 +260,32 @@ static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end) if (!block_group || block_group->ro) goto not_found; start = extent_end; } else { goto not_found; } loop: if (start > end) { btrfs_free_path(path); return 0; 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 { not_found: btrfs_release_path(root, path); cow_file_range(inode, start, end); start = end + 1; goto loop; btrfs_end_transaction(trans, root); btrfs_free_path(path); return cow_file_range(inode, start, end); } 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) Loading Loading @@ -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); Loading Loading @@ -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, Loading Loading @@ -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); Loading fs/btrfs/ioctl.c +1 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ #include <linux/bit_spinlock.h> #include <linux/version.h> #include <linux/xattr.h> #include <linux/vmalloc.h> #include "ctree.h" #include "disk-io.h" #include "transaction.h" Loading fs/btrfs/ordered-data.c +13 −3 Original line number Diff line number Diff line Loading @@ -152,7 +152,7 @@ static inline struct rb_node *tree_search(struct btrfs_ordered_inode_tree *tree, * inserted. */ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, u64 start, u64 len) u64 start, u64 len, int nocow) { struct btrfs_ordered_inode_tree *tree; struct rb_node *node; Loading @@ -168,6 +168,8 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, entry->start = start; entry->len = len; entry->inode = inode; if (nocow) set_bit(BTRFS_ORDERED_NOCOW, &entry->flags); /* one ref for the tree */ atomic_set(&entry->refs, 1); Loading Loading @@ -303,10 +305,11 @@ int btrfs_remove_ordered_extent(struct inode *inode, return 0; } int btrfs_wait_ordered_extents(struct btrfs_root *root) int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only) { struct list_head splice; struct list_head *cur; struct list_head *tmp; struct btrfs_ordered_extent *ordered; struct inode *inode; Loading @@ -314,10 +317,16 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root) spin_lock(&root->fs_info->ordered_extent_lock); list_splice_init(&root->fs_info->ordered_extents, &splice); while(!list_empty(&splice)) { list_for_each_safe(cur, tmp, &splice) { cur = splice.next; ordered = list_entry(cur, struct btrfs_ordered_extent, root_extent_list); if (nocow_only && !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) { cond_resched_lock(&root->fs_info->ordered_extent_lock); continue; } list_del_init(&ordered->root_extent_list); atomic_inc(&ordered->refs); inode = ordered->inode; Loading @@ -338,6 +347,7 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root) spin_lock(&root->fs_info->ordered_extent_lock); } list_splice_init(&splice, &root->fs_info->ordered_extents); spin_unlock(&root->fs_info->ordered_extent_lock); return 0; } Loading Loading
fs/btrfs/ctree.h +2 −1 Original line number Diff line number Diff line Loading @@ -1403,7 +1403,8 @@ static inline struct dentry *fdentry(struct file *file) { } /* extent-tree.c */ int btrfs_cross_ref_exists(struct btrfs_root *root, int btrfs_cross_ref_exists(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, u64 bytenr); int btrfs_extent_post_op(struct btrfs_trans_handle *trans, struct btrfs_root *root); Loading
fs/btrfs/extent-tree.c +5 −6 Original line number Diff line number Diff line Loading @@ -893,10 +893,10 @@ static int get_reference_status(struct btrfs_root *root, u64 bytenr, return ret; } int btrfs_cross_ref_exists(struct btrfs_root *root, int btrfs_cross_ref_exists(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, u64 bytenr) { struct btrfs_trans_handle *trans; struct btrfs_root *old_root; struct btrfs_path *path = NULL; struct extent_buffer *eb; Loading @@ -908,6 +908,7 @@ int btrfs_cross_ref_exists(struct btrfs_root *root, int level; int ret; BUG_ON(trans == NULL); BUG_ON(key->type != BTRFS_EXTENT_DATA_KEY); ret = get_reference_status(root, bytenr, 0, key->objectid, &min_generation, &ref_count); Loading @@ -917,7 +918,6 @@ int btrfs_cross_ref_exists(struct btrfs_root *root, if (ref_count != 1) return 1; trans = btrfs_start_transaction(root, 0); old_root = root->dirty_root->root; ref_generation = old_root->root_key.offset; Loading Loading @@ -973,7 +973,6 @@ int btrfs_cross_ref_exists(struct btrfs_root *root, out: if (path) btrfs_free_path(path); btrfs_end_transaction(trans, root); return ret; } Loading Loading @@ -3320,7 +3319,7 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start) mutex_unlock(&root->fs_info->alloc_mutex); btrfs_start_delalloc_inodes(root); btrfs_wait_ordered_extents(tree_root); btrfs_wait_ordered_extents(tree_root, 0); mutex_lock(&root->fs_info->alloc_mutex); Loading Loading @@ -3407,7 +3406,7 @@ int btrfs_shrink_extent_tree(struct btrfs_root *root, u64 shrink_start) btrfs_clean_old_snapshots(tree_root); btrfs_start_delalloc_inodes(root); btrfs_wait_ordered_extents(tree_root); btrfs_wait_ordered_extents(tree_root, 0); trans = btrfs_start_transaction(tree_root, 1); btrfs_commit_transaction(trans, tree_root); Loading
fs/btrfs/inode.c +38 −22 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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; Loading Loading @@ -244,12 +245,11 @@ static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end) 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 Loading @@ -260,24 +260,32 @@ static int run_delalloc_nocow(struct inode *inode, u64 start, u64 end) if (!block_group || block_group->ro) goto not_found; start = extent_end; } else { goto not_found; } loop: if (start > end) { btrfs_free_path(path); return 0; 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 { not_found: btrfs_release_path(root, path); cow_file_range(inode, start, end); start = end + 1; goto loop; btrfs_end_transaction(trans, root); btrfs_free_path(path); return cow_file_range(inode, start, end); } 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) Loading Loading @@ -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); Loading Loading @@ -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, Loading Loading @@ -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); Loading
fs/btrfs/ioctl.c +1 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ #include <linux/bit_spinlock.h> #include <linux/version.h> #include <linux/xattr.h> #include <linux/vmalloc.h> #include "ctree.h" #include "disk-io.h" #include "transaction.h" Loading
fs/btrfs/ordered-data.c +13 −3 Original line number Diff line number Diff line Loading @@ -152,7 +152,7 @@ static inline struct rb_node *tree_search(struct btrfs_ordered_inode_tree *tree, * inserted. */ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, u64 start, u64 len) u64 start, u64 len, int nocow) { struct btrfs_ordered_inode_tree *tree; struct rb_node *node; Loading @@ -168,6 +168,8 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, entry->start = start; entry->len = len; entry->inode = inode; if (nocow) set_bit(BTRFS_ORDERED_NOCOW, &entry->flags); /* one ref for the tree */ atomic_set(&entry->refs, 1); Loading Loading @@ -303,10 +305,11 @@ int btrfs_remove_ordered_extent(struct inode *inode, return 0; } int btrfs_wait_ordered_extents(struct btrfs_root *root) int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only) { struct list_head splice; struct list_head *cur; struct list_head *tmp; struct btrfs_ordered_extent *ordered; struct inode *inode; Loading @@ -314,10 +317,16 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root) spin_lock(&root->fs_info->ordered_extent_lock); list_splice_init(&root->fs_info->ordered_extents, &splice); while(!list_empty(&splice)) { list_for_each_safe(cur, tmp, &splice) { cur = splice.next; ordered = list_entry(cur, struct btrfs_ordered_extent, root_extent_list); if (nocow_only && !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) { cond_resched_lock(&root->fs_info->ordered_extent_lock); continue; } list_del_init(&ordered->root_extent_list); atomic_inc(&ordered->refs); inode = ordered->inode; Loading @@ -338,6 +347,7 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root) spin_lock(&root->fs_info->ordered_extent_lock); } list_splice_init(&splice, &root->fs_info->ordered_extents); spin_unlock(&root->fs_info->ordered_extent_lock); return 0; } Loading