aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2012-05-31 15:58:55 -0400
committerChris Mason <chris.mason@oracle.com>2012-06-14 21:29:15 -0400
commit17ca04aff7e6171df684b7b65804df8830eb8c15 (patch)
tree6fa1d7daf40ba3c2df952dd30c660c88f418c1fd
parentee670f0af35871edb492db5ba406cef36d1b7c21 (diff)
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: Josef Bacik <josef@redhat.com>
-rw-r--r--fs/btrfs/inode.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index ccd6355af73..b7f398c36cb 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1136,8 +1136,18 @@ static noinline int run_delalloc_nocow(struct inode *inode,
1136 u64 ino = btrfs_ino(inode); 1136 u64 ino = btrfs_ino(inode);
1137 1137
1138 path = btrfs_alloc_path(); 1138 path = btrfs_alloc_path();
1139 if (!path) 1139 if (!path) {
1140 extent_clear_unlock_delalloc(inode,
1141 &BTRFS_I(inode)->io_tree,
1142 start, end, locked_page,
1143 EXTENT_CLEAR_UNLOCK_PAGE |
1144 EXTENT_CLEAR_UNLOCK |
1145 EXTENT_CLEAR_DELALLOC |
1146 EXTENT_CLEAR_DIRTY |
1147 EXTENT_SET_WRITEBACK |
1148 EXTENT_END_WRITEBACK);
1140 return -ENOMEM; 1149 return -ENOMEM;
1150 }
1141 1151
1142 nolock = btrfs_is_free_space_inode(root, inode); 1152 nolock = btrfs_is_free_space_inode(root, inode);
1143 1153
@@ -1147,6 +1157,15 @@ static noinline int run_delalloc_nocow(struct inode *inode,
1147 trans = btrfs_join_transaction(root); 1157 trans = btrfs_join_transaction(root);
1148 1158
1149 if (IS_ERR(trans)) { 1159 if (IS_ERR(trans)) {
1160 extent_clear_unlock_delalloc(inode,
1161 &BTRFS_I(inode)->io_tree,
1162 start, end, locked_page,
1163 EXTENT_CLEAR_UNLOCK_PAGE |
1164 EXTENT_CLEAR_UNLOCK |
1165 EXTENT_CLEAR_DELALLOC |
1166 EXTENT_CLEAR_DIRTY |
1167 EXTENT_SET_WRITEBACK |
1168 EXTENT_END_WRITEBACK);
1150 btrfs_free_path(path); 1169 btrfs_free_path(path);
1151 return PTR_ERR(trans); 1170 return PTR_ERR(trans);
1152 } 1171 }
@@ -1327,8 +1346,11 @@ out_check:
1327 } 1346 }
1328 btrfs_release_path(path); 1347 btrfs_release_path(path);
1329 1348
1330 if (cur_offset <= end && cow_start == (u64)-1) 1349 if (cur_offset <= end && cow_start == (u64)-1) {
1331 cow_start = cur_offset; 1350 cow_start = cur_offset;
1351 cur_offset = end;
1352 }
1353
1332 if (cow_start != (u64)-1) { 1354 if (cow_start != (u64)-1) {
1333 ret = cow_file_range(inode, locked_page, cow_start, end, 1355 ret = cow_file_range(inode, locked_page, cow_start, end,
1334 page_started, nr_written, 1); 1356 page_started, nr_written, 1);
@@ -1347,6 +1369,17 @@ error:
1347 if (!ret) 1369 if (!ret)
1348 ret = err; 1370 ret = err;
1349 1371
1372 if (ret && cur_offset < end)
1373 extent_clear_unlock_delalloc(inode,
1374 &BTRFS_I(inode)->io_tree,
1375 cur_offset, end, locked_page,
1376 EXTENT_CLEAR_UNLOCK_PAGE |
1377 EXTENT_CLEAR_UNLOCK |
1378 EXTENT_CLEAR_DELALLOC |
1379 EXTENT_CLEAR_DIRTY |
1380 EXTENT_SET_WRITEBACK |
1381 EXTENT_END_WRITEBACK);
1382
1350 btrfs_free_path(path); 1383 btrfs_free_path(path);
1351 return ret; 1384 return ret;
1352} 1385}