Commit 17ca04af authored by Josef Bacik's avatar Josef Bacik Committed by Chris Mason

Btrfs: unlock everything properly in the error case for nocow

I was getting hung on umount when a transaction was aborted because a range
of one of the free space inodes was still locked.  This is because the nocow
stuff doesn't unlock anything on error.  This fixed the problem and I
verified that is what was happening.  Thanks,
Signed-off-by: default avatarJosef Bacik <josef@redhat.com>
parent ee670f0a
...@@ -1136,8 +1136,18 @@ static noinline int run_delalloc_nocow(struct inode *inode, ...@@ -1136,8 +1136,18 @@ static noinline int run_delalloc_nocow(struct inode *inode,
u64 ino = btrfs_ino(inode); u64 ino = btrfs_ino(inode);
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) if (!path) {
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 -ENOMEM; return -ENOMEM;
}
nolock = btrfs_is_free_space_inode(root, inode); nolock = btrfs_is_free_space_inode(root, inode);
...@@ -1147,6 +1157,15 @@ static noinline int run_delalloc_nocow(struct inode *inode, ...@@ -1147,6 +1157,15 @@ static noinline int run_delalloc_nocow(struct inode *inode,
trans = btrfs_join_transaction(root); trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) { 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);
btrfs_free_path(path); btrfs_free_path(path);
return PTR_ERR(trans); return PTR_ERR(trans);
} }
...@@ -1327,8 +1346,11 @@ static noinline int run_delalloc_nocow(struct inode *inode, ...@@ -1327,8 +1346,11 @@ static noinline int run_delalloc_nocow(struct inode *inode,
} }
btrfs_release_path(path); btrfs_release_path(path);
if (cur_offset <= end && cow_start == (u64)-1) if (cur_offset <= end && cow_start == (u64)-1) {
cow_start = cur_offset; cow_start = cur_offset;
cur_offset = end;
}
if (cow_start != (u64)-1) { if (cow_start != (u64)-1) {
ret = cow_file_range(inode, locked_page, cow_start, end, ret = cow_file_range(inode, locked_page, cow_start, end,
page_started, nr_written, 1); page_started, nr_written, 1);
...@@ -1347,6 +1369,17 @@ static noinline int run_delalloc_nocow(struct inode *inode, ...@@ -1347,6 +1369,17 @@ static noinline int run_delalloc_nocow(struct inode *inode,
if (!ret) if (!ret)
ret = err; ret = err;
if (ret && cur_offset < end)
extent_clear_unlock_delalloc(inode,
&BTRFS_I(inode)->io_tree,
cur_offset, end, locked_page,
EXTENT_CLEAR_UNLOCK_PAGE |
EXTENT_CLEAR_UNLOCK |
EXTENT_CLEAR_DELALLOC |
EXTENT_CLEAR_DIRTY |
EXTENT_SET_WRITEBACK |
EXTENT_END_WRITEBACK);
btrfs_free_path(path); btrfs_free_path(path);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment