|
@@ -804,14 +804,14 @@ static u64 get_extent_allocation_hint(struct inode *inode, u64 start,
|
|
* required to start IO on it. It may be clean and already done with
|
|
* required to start IO on it. It may be clean and already done with
|
|
* IO when we return.
|
|
* IO when we return.
|
|
*/
|
|
*/
|
|
-static noinline int cow_file_range(struct inode *inode,
|
|
|
|
- struct page *locked_page,
|
|
|
|
- u64 start, u64 end, int *page_started,
|
|
|
|
- unsigned long *nr_written,
|
|
|
|
- int unlock)
|
|
|
|
|
|
+static noinline int __cow_file_range(struct btrfs_trans_handle *trans,
|
|
|
|
+ struct inode *inode,
|
|
|
|
+ struct btrfs_root *root,
|
|
|
|
+ struct page *locked_page,
|
|
|
|
+ u64 start, u64 end, int *page_started,
|
|
|
|
+ unsigned long *nr_written,
|
|
|
|
+ int unlock)
|
|
{
|
|
{
|
|
- struct btrfs_root *root = BTRFS_I(inode)->root;
|
|
|
|
- struct btrfs_trans_handle *trans;
|
|
|
|
u64 alloc_hint = 0;
|
|
u64 alloc_hint = 0;
|
|
u64 num_bytes;
|
|
u64 num_bytes;
|
|
unsigned long ram_size;
|
|
unsigned long ram_size;
|
|
@@ -824,25 +824,10 @@ static noinline int cow_file_range(struct inode *inode,
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
BUG_ON(btrfs_is_free_space_inode(inode));
|
|
BUG_ON(btrfs_is_free_space_inode(inode));
|
|
- trans = btrfs_join_transaction(root);
|
|
|
|
- if (IS_ERR(trans)) {
|
|
|
|
- extent_clear_unlock_delalloc(inode,
|
|
|
|
- &BTRFS_I(inode)->io_tree,
|
|
|
|
- start, end, locked_page,
|
|
|
|
- EXTENT_CLEAR_UNLOCK_PAGE |
|
|
|
|
- EXTENT_CLEAR_UNLOCK |
|
|
|
|
- EXTENT_CLEAR_DELALLOC |
|
|
|
|
- EXTENT_CLEAR_DIRTY |
|
|
|
|
- EXTENT_SET_WRITEBACK |
|
|
|
|
- EXTENT_END_WRITEBACK);
|
|
|
|
- return PTR_ERR(trans);
|
|
|
|
- }
|
|
|
|
- trans->block_rsv = &root->fs_info->delalloc_block_rsv;
|
|
|
|
|
|
|
|
num_bytes = (end - start + blocksize) & ~(blocksize - 1);
|
|
num_bytes = (end - start + blocksize) & ~(blocksize - 1);
|
|
num_bytes = max(blocksize, num_bytes);
|
|
num_bytes = max(blocksize, num_bytes);
|
|
disk_num_bytes = num_bytes;
|
|
disk_num_bytes = num_bytes;
|
|
- ret = 0;
|
|
|
|
|
|
|
|
/* if this is a small write inside eof, kick off defrag */
|
|
/* if this is a small write inside eof, kick off defrag */
|
|
if (num_bytes < 64 * 1024 &&
|
|
if (num_bytes < 64 * 1024 &&
|
|
@@ -953,11 +938,9 @@ static noinline int cow_file_range(struct inode *inode,
|
|
alloc_hint = ins.objectid + ins.offset;
|
|
alloc_hint = ins.objectid + ins.offset;
|
|
start += cur_alloc_size;
|
|
start += cur_alloc_size;
|
|
}
|
|
}
|
|
- ret = 0;
|
|
|
|
out:
|
|
out:
|
|
- btrfs_end_transaction(trans, root);
|
|
|
|
-
|
|
|
|
return ret;
|
|
return ret;
|
|
|
|
+
|
|
out_unlock:
|
|
out_unlock:
|
|
extent_clear_unlock_delalloc(inode,
|
|
extent_clear_unlock_delalloc(inode,
|
|
&BTRFS_I(inode)->io_tree,
|
|
&BTRFS_I(inode)->io_tree,
|
|
@@ -972,6 +955,39 @@ out_unlock:
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static noinline int cow_file_range(struct inode *inode,
|
|
|
|
+ struct page *locked_page,
|
|
|
|
+ u64 start, u64 end, int *page_started,
|
|
|
|
+ unsigned long *nr_written,
|
|
|
|
+ int unlock)
|
|
|
|
+{
|
|
|
|
+ struct btrfs_trans_handle *trans;
|
|
|
|
+ struct btrfs_root *root = BTRFS_I(inode)->root;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ trans = btrfs_join_transaction(root);
|
|
|
|
+ if (IS_ERR(trans)) {
|
|
|
|
+ extent_clear_unlock_delalloc(inode,
|
|
|
|
+ &BTRFS_I(inode)->io_tree,
|
|
|
|
+ start, end, locked_page,
|
|
|
|
+ EXTENT_CLEAR_UNLOCK_PAGE |
|
|
|
|
+ EXTENT_CLEAR_UNLOCK |
|
|
|
|
+ EXTENT_CLEAR_DELALLOC |
|
|
|
|
+ EXTENT_CLEAR_DIRTY |
|
|
|
|
+ EXTENT_SET_WRITEBACK |
|
|
|
|
+ EXTENT_END_WRITEBACK);
|
|
|
|
+ return PTR_ERR(trans);
|
|
|
|
+ }
|
|
|
|
+ trans->block_rsv = &root->fs_info->delalloc_block_rsv;
|
|
|
|
+
|
|
|
|
+ ret = __cow_file_range(trans, inode, root, locked_page, start, end,
|
|
|
|
+ page_started, nr_written, unlock);
|
|
|
|
+
|
|
|
|
+ btrfs_end_transaction(trans, root);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* work queue call back to started compression on a file and pages
|
|
* work queue call back to started compression on a file and pages
|
|
*/
|
|
*/
|
|
@@ -1282,9 +1298,9 @@ out_check:
|
|
|
|
|
|
btrfs_release_path(path);
|
|
btrfs_release_path(path);
|
|
if (cow_start != (u64)-1) {
|
|
if (cow_start != (u64)-1) {
|
|
- ret = cow_file_range(inode, locked_page, cow_start,
|
|
|
|
- found_key.offset - 1, page_started,
|
|
|
|
- nr_written, 1);
|
|
|
|
|
|
+ ret = __cow_file_range(trans, inode, root, locked_page,
|
|
|
|
+ cow_start, found_key.offset - 1,
|
|
|
|
+ page_started, nr_written, 1);
|
|
if (ret) {
|
|
if (ret) {
|
|
btrfs_abort_transaction(trans, root, ret);
|
|
btrfs_abort_transaction(trans, root, ret);
|
|
goto error;
|
|
goto error;
|
|
@@ -1353,8 +1369,9 @@ out_check:
|
|
}
|
|
}
|
|
|
|
|
|
if (cow_start != (u64)-1) {
|
|
if (cow_start != (u64)-1) {
|
|
- ret = cow_file_range(inode, locked_page, cow_start, end,
|
|
|
|
- page_started, nr_written, 1);
|
|
|
|
|
|
+ ret = __cow_file_range(trans, inode, root, locked_page,
|
|
|
|
+ cow_start, end,
|
|
|
|
+ page_started, nr_written, 1);
|
|
if (ret) {
|
|
if (ret) {
|
|
btrfs_abort_transaction(trans, root, ret);
|
|
btrfs_abort_transaction(trans, root, ret);
|
|
goto error;
|
|
goto error;
|