aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c56
1 files changed, 48 insertions, 8 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index e5b2533b691a..fedf8b9f03a2 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1325,12 +1325,12 @@ static noinline int reada_for_balance(struct btrfs_root *root,
1325 int ret = 0; 1325 int ret = 0;
1326 int blocksize; 1326 int blocksize;
1327 1327
1328 parent = path->nodes[level - 1]; 1328 parent = path->nodes[level + 1];
1329 if (!parent) 1329 if (!parent)
1330 return 0; 1330 return 0;
1331 1331
1332 nritems = btrfs_header_nritems(parent); 1332 nritems = btrfs_header_nritems(parent);
1333 slot = path->slots[level]; 1333 slot = path->slots[level + 1];
1334 blocksize = btrfs_level_size(root, level); 1334 blocksize = btrfs_level_size(root, level);
1335 1335
1336 if (slot > 0) { 1336 if (slot > 0) {
@@ -1341,7 +1341,7 @@ static noinline int reada_for_balance(struct btrfs_root *root,
1341 block1 = 0; 1341 block1 = 0;
1342 free_extent_buffer(eb); 1342 free_extent_buffer(eb);
1343 } 1343 }
1344 if (slot < nritems) { 1344 if (slot + 1 < nritems) {
1345 block2 = btrfs_node_blockptr(parent, slot + 1); 1345 block2 = btrfs_node_blockptr(parent, slot + 1);
1346 gen = btrfs_node_ptr_generation(parent, slot + 1); 1346 gen = btrfs_node_ptr_generation(parent, slot + 1);
1347 eb = btrfs_find_tree_block(root, block2, blocksize); 1347 eb = btrfs_find_tree_block(root, block2, blocksize);
@@ -1351,7 +1351,11 @@ static noinline int reada_for_balance(struct btrfs_root *root,
1351 } 1351 }
1352 if (block1 || block2) { 1352 if (block1 || block2) {
1353 ret = -EAGAIN; 1353 ret = -EAGAIN;
1354
1355 /* release the whole path */
1354 btrfs_release_path(root, path); 1356 btrfs_release_path(root, path);
1357
1358 /* read the blocks */
1355 if (block1) 1359 if (block1)
1356 readahead_tree_block(root, block1, blocksize, 0); 1360 readahead_tree_block(root, block1, blocksize, 0);
1357 if (block2) 1361 if (block2)
@@ -1361,7 +1365,7 @@ static noinline int reada_for_balance(struct btrfs_root *root,
1361 eb = read_tree_block(root, block1, blocksize, 0); 1365 eb = read_tree_block(root, block1, blocksize, 0);
1362 free_extent_buffer(eb); 1366 free_extent_buffer(eb);
1363 } 1367 }
1364 if (block1) { 1368 if (block2) {
1365 eb = read_tree_block(root, block2, blocksize, 0); 1369 eb = read_tree_block(root, block2, blocksize, 0);
1366 free_extent_buffer(eb); 1370 free_extent_buffer(eb);
1367 } 1371 }
@@ -1465,6 +1469,7 @@ read_block_for_search(struct btrfs_trans_handle *trans,
1465 u32 blocksize; 1469 u32 blocksize;
1466 struct extent_buffer *b = *eb_ret; 1470 struct extent_buffer *b = *eb_ret;
1467 struct extent_buffer *tmp; 1471 struct extent_buffer *tmp;
1472 int ret;
1468 1473
1469 blocknr = btrfs_node_blockptr(b, slot); 1474 blocknr = btrfs_node_blockptr(b, slot);
1470 gen = btrfs_node_ptr_generation(b, slot); 1475 gen = btrfs_node_ptr_generation(b, slot);
@@ -1472,6 +1477,10 @@ read_block_for_search(struct btrfs_trans_handle *trans,
1472 1477
1473 tmp = btrfs_find_tree_block(root, blocknr, blocksize); 1478 tmp = btrfs_find_tree_block(root, blocknr, blocksize);
1474 if (tmp && btrfs_buffer_uptodate(tmp, gen)) { 1479 if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
1480 /*
1481 * we found an up to date block without sleeping, return
1482 * right away
1483 */
1475 *eb_ret = tmp; 1484 *eb_ret = tmp;
1476 return 0; 1485 return 0;
1477 } 1486 }
@@ -1479,18 +1488,34 @@ read_block_for_search(struct btrfs_trans_handle *trans,
1479 /* 1488 /*
1480 * reduce lock contention at high levels 1489 * reduce lock contention at high levels
1481 * of the btree by dropping locks before 1490 * of the btree by dropping locks before
1482 * we read. 1491 * we read. Don't release the lock on the current
1492 * level because we need to walk this node to figure
1493 * out which blocks to read.
1483 */ 1494 */
1484 btrfs_release_path(NULL, p); 1495 btrfs_unlock_up_safe(p, level + 1);
1496 btrfs_set_path_blocking(p);
1497
1485 if (tmp) 1498 if (tmp)
1486 free_extent_buffer(tmp); 1499 free_extent_buffer(tmp);
1487 if (p->reada) 1500 if (p->reada)
1488 reada_for_search(root, p, level, slot, key->objectid); 1501 reada_for_search(root, p, level, slot, key->objectid);
1489 1502
1503 btrfs_release_path(NULL, p);
1504
1505 ret = -EAGAIN;
1490 tmp = read_tree_block(root, blocknr, blocksize, gen); 1506 tmp = read_tree_block(root, blocknr, blocksize, gen);
1491 if (tmp) 1507 if (tmp) {
1508 /*
1509 * If the read above didn't mark this buffer up to date,
1510 * it will never end up being up to date. Set ret to EIO now
1511 * and give up so that our caller doesn't loop forever
1512 * on our EAGAINs.
1513 */
1514 if (!btrfs_buffer_uptodate(tmp, 0))
1515 ret = -EIO;
1492 free_extent_buffer(tmp); 1516 free_extent_buffer(tmp);
1493 return -EAGAIN; 1517 }
1518 return ret;
1494} 1519}
1495 1520
1496/* 1521/*
@@ -1689,6 +1714,9 @@ cow_done:
1689 if (ret == -EAGAIN) 1714 if (ret == -EAGAIN)
1690 goto again; 1715 goto again;
1691 1716
1717 if (ret == -EIO)
1718 goto done;
1719
1692 if (!p->skip_locking) { 1720 if (!p->skip_locking) {
1693 int lret; 1721 int lret;
1694 1722
@@ -1731,6 +1759,8 @@ done:
1731 */ 1759 */
1732 if (!p->leave_spinning) 1760 if (!p->leave_spinning)
1733 btrfs_set_path_blocking(p); 1761 btrfs_set_path_blocking(p);
1762 if (ret < 0)
1763 btrfs_release_path(root, p);
1734 return ret; 1764 return ret;
1735} 1765}
1736 1766
@@ -4205,6 +4235,11 @@ again:
4205 if (ret == -EAGAIN) 4235 if (ret == -EAGAIN)
4206 goto again; 4236 goto again;
4207 4237
4238 if (ret < 0) {
4239 btrfs_release_path(root, path);
4240 goto done;
4241 }
4242
4208 if (!path->skip_locking) { 4243 if (!path->skip_locking) {
4209 ret = btrfs_try_spin_lock(next); 4244 ret = btrfs_try_spin_lock(next);
4210 if (!ret) { 4245 if (!ret) {
@@ -4239,6 +4274,11 @@ again:
4239 if (ret == -EAGAIN) 4274 if (ret == -EAGAIN)
4240 goto again; 4275 goto again;
4241 4276
4277 if (ret < 0) {
4278 btrfs_release_path(root, path);
4279 goto done;
4280 }
4281
4242 if (!path->skip_locking) { 4282 if (!path->skip_locking) {
4243 btrfs_assert_tree_locked(path->nodes[level]); 4283 btrfs_assert_tree_locked(path->nodes[level]);
4244 ret = btrfs_try_spin_lock(next); 4284 ret = btrfs_try_spin_lock(next);