aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2010-10-24 11:01:27 -0400
committerChris Mason <chris.mason@oracle.com>2010-10-29 09:31:30 -0400
commitcb44921a09221f0a90217b44044448f63190f3e5 (patch)
tree5580522b6db6868c02d3072320e338442272cb2b /fs/btrfs
parent6b5b817f103450444f3f658a498f435d92a197e5 (diff)
Btrfs: don't loop forever on bad btree blocks
When btrfs discovers the generation number in a btree block is incorrect, it can loop forever without forcing the RAID code to try a valid mirror, and without returning EIO. This changes things to properly kick out the EIO. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index c3df14ce2cc2..6921231e0efb 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1577,13 +1577,33 @@ read_block_for_search(struct btrfs_trans_handle *trans,
1577 blocksize = btrfs_level_size(root, level - 1); 1577 blocksize = btrfs_level_size(root, level - 1);
1578 1578
1579 tmp = btrfs_find_tree_block(root, blocknr, blocksize); 1579 tmp = btrfs_find_tree_block(root, blocknr, blocksize);
1580 if (tmp && btrfs_buffer_uptodate(tmp, gen)) { 1580 if (tmp) {
1581 /* 1581 if (btrfs_buffer_uptodate(tmp, 0)) {
1582 * we found an up to date block without sleeping, return 1582 if (btrfs_buffer_uptodate(tmp, gen)) {
1583 * right away 1583 /*
1584 */ 1584 * we found an up to date block without
1585 *eb_ret = tmp; 1585 * sleeping, return
1586 return 0; 1586 * right away
1587 */
1588 *eb_ret = tmp;
1589 return 0;
1590 }
1591 /* the pages were up to date, but we failed
1592 * the generation number check. Do a full
1593 * read for the generation number that is correct.
1594 * We must do this without dropping locks so
1595 * we can trust our generation number
1596 */
1597 free_extent_buffer(tmp);
1598 tmp = read_tree_block(root, blocknr, blocksize, gen);
1599 if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
1600 *eb_ret = tmp;
1601 return 0;
1602 }
1603 free_extent_buffer(tmp);
1604 btrfs_release_path(NULL, p);
1605 return -EIO;
1606 }
1587 } 1607 }
1588 1608
1589 /* 1609 /*
@@ -1596,8 +1616,7 @@ read_block_for_search(struct btrfs_trans_handle *trans,
1596 btrfs_unlock_up_safe(p, level + 1); 1616 btrfs_unlock_up_safe(p, level + 1);
1597 btrfs_set_path_blocking(p); 1617 btrfs_set_path_blocking(p);
1598 1618
1599 if (tmp) 1619 free_extent_buffer(tmp);
1600 free_extent_buffer(tmp);
1601 if (p->reada) 1620 if (p->reada)
1602 reada_for_search(root, p, level, slot, key->objectid); 1621 reada_for_search(root, p, level, slot, key->objectid);
1603 1622