diff options
| -rw-r--r-- | fs/btrfs/ctree.c | 28 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 18 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.h | 3 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 2 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 4 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.h | 4 | ||||
| -rw-r--r-- | fs/btrfs/scrub.c | 7 | ||||
| -rw-r--r-- | fs/btrfs/tree-log.c | 2 |
8 files changed, 47 insertions, 21 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index e801f226d7e0..4106264fbc65 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -220,10 +220,12 @@ struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root) | |||
| 220 | */ | 220 | */ |
| 221 | static void add_root_to_dirty_list(struct btrfs_root *root) | 221 | static void add_root_to_dirty_list(struct btrfs_root *root) |
| 222 | { | 222 | { |
| 223 | spin_lock(&root->fs_info->trans_lock); | ||
| 223 | if (root->track_dirty && list_empty(&root->dirty_list)) { | 224 | if (root->track_dirty && list_empty(&root->dirty_list)) { |
| 224 | list_add(&root->dirty_list, | 225 | list_add(&root->dirty_list, |
| 225 | &root->fs_info->dirty_cowonly_roots); | 226 | &root->fs_info->dirty_cowonly_roots); |
| 226 | } | 227 | } |
| 228 | spin_unlock(&root->fs_info->trans_lock); | ||
| 227 | } | 229 | } |
| 228 | 230 | ||
| 229 | /* | 231 | /* |
| @@ -723,7 +725,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
| 723 | 725 | ||
| 724 | cur = btrfs_find_tree_block(root, blocknr, blocksize); | 726 | cur = btrfs_find_tree_block(root, blocknr, blocksize); |
| 725 | if (cur) | 727 | if (cur) |
| 726 | uptodate = btrfs_buffer_uptodate(cur, gen); | 728 | uptodate = btrfs_buffer_uptodate(cur, gen, 0); |
| 727 | else | 729 | else |
| 728 | uptodate = 0; | 730 | uptodate = 0; |
| 729 | if (!cur || !uptodate) { | 731 | if (!cur || !uptodate) { |
| @@ -1358,7 +1360,12 @@ static noinline int reada_for_balance(struct btrfs_root *root, | |||
| 1358 | block1 = btrfs_node_blockptr(parent, slot - 1); | 1360 | block1 = btrfs_node_blockptr(parent, slot - 1); |
| 1359 | gen = btrfs_node_ptr_generation(parent, slot - 1); | 1361 | gen = btrfs_node_ptr_generation(parent, slot - 1); |
| 1360 | eb = btrfs_find_tree_block(root, block1, blocksize); | 1362 | eb = btrfs_find_tree_block(root, block1, blocksize); |
| 1361 | if (eb && btrfs_buffer_uptodate(eb, gen)) | 1363 | /* |
| 1364 | * if we get -eagain from btrfs_buffer_uptodate, we | ||
| 1365 | * don't want to return eagain here. That will loop | ||
| 1366 | * forever | ||
| 1367 | */ | ||
| 1368 | if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0) | ||
| 1362 | block1 = 0; | 1369 | block1 = 0; |
| 1363 | free_extent_buffer(eb); | 1370 | free_extent_buffer(eb); |
| 1364 | } | 1371 | } |
| @@ -1366,7 +1373,7 @@ static noinline int reada_for_balance(struct btrfs_root *root, | |||
| 1366 | block2 = btrfs_node_blockptr(parent, slot + 1); | 1373 | block2 = btrfs_node_blockptr(parent, slot + 1); |
| 1367 | gen = btrfs_node_ptr_generation(parent, slot + 1); | 1374 | gen = btrfs_node_ptr_generation(parent, slot + 1); |
| 1368 | eb = btrfs_find_tree_block(root, block2, blocksize); | 1375 | eb = btrfs_find_tree_block(root, block2, blocksize); |
| 1369 | if (eb && btrfs_buffer_uptodate(eb, gen)) | 1376 | if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0) |
| 1370 | block2 = 0; | 1377 | block2 = 0; |
| 1371 | free_extent_buffer(eb); | 1378 | free_extent_buffer(eb); |
| 1372 | } | 1379 | } |
| @@ -1504,8 +1511,9 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
| 1504 | 1511 | ||
| 1505 | tmp = btrfs_find_tree_block(root, blocknr, blocksize); | 1512 | tmp = btrfs_find_tree_block(root, blocknr, blocksize); |
| 1506 | if (tmp) { | 1513 | if (tmp) { |
| 1507 | if (btrfs_buffer_uptodate(tmp, 0)) { | 1514 | /* first we do an atomic uptodate check */ |
| 1508 | if (btrfs_buffer_uptodate(tmp, gen)) { | 1515 | if (btrfs_buffer_uptodate(tmp, 0, 1) > 0) { |
| 1516 | if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) { | ||
| 1509 | /* | 1517 | /* |
| 1510 | * we found an up to date block without | 1518 | * we found an up to date block without |
| 1511 | * sleeping, return | 1519 | * sleeping, return |
| @@ -1523,8 +1531,9 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
| 1523 | free_extent_buffer(tmp); | 1531 | free_extent_buffer(tmp); |
| 1524 | btrfs_set_path_blocking(p); | 1532 | btrfs_set_path_blocking(p); |
| 1525 | 1533 | ||
| 1534 | /* now we're allowed to do a blocking uptodate check */ | ||
| 1526 | tmp = read_tree_block(root, blocknr, blocksize, gen); | 1535 | tmp = read_tree_block(root, blocknr, blocksize, gen); |
| 1527 | if (tmp && btrfs_buffer_uptodate(tmp, gen)) { | 1536 | if (tmp && btrfs_buffer_uptodate(tmp, gen, 0) > 0) { |
| 1528 | *eb_ret = tmp; | 1537 | *eb_ret = tmp; |
| 1529 | return 0; | 1538 | return 0; |
| 1530 | } | 1539 | } |
| @@ -1559,7 +1568,7 @@ read_block_for_search(struct btrfs_trans_handle *trans, | |||
| 1559 | * and give up so that our caller doesn't loop forever | 1568 | * and give up so that our caller doesn't loop forever |
| 1560 | * on our EAGAINs. | 1569 | * on our EAGAINs. |
| 1561 | */ | 1570 | */ |
| 1562 | if (!btrfs_buffer_uptodate(tmp, 0)) | 1571 | if (!btrfs_buffer_uptodate(tmp, 0, 0)) |
| 1563 | ret = -EIO; | 1572 | ret = -EIO; |
| 1564 | free_extent_buffer(tmp); | 1573 | free_extent_buffer(tmp); |
| 1565 | } | 1574 | } |
| @@ -4043,7 +4052,7 @@ again: | |||
| 4043 | tmp = btrfs_find_tree_block(root, blockptr, | 4052 | tmp = btrfs_find_tree_block(root, blockptr, |
| 4044 | btrfs_level_size(root, level - 1)); | 4053 | btrfs_level_size(root, level - 1)); |
| 4045 | 4054 | ||
| 4046 | if (tmp && btrfs_buffer_uptodate(tmp, gen)) { | 4055 | if (tmp && btrfs_buffer_uptodate(tmp, gen, 1) > 0) { |
| 4047 | free_extent_buffer(tmp); | 4056 | free_extent_buffer(tmp); |
| 4048 | break; | 4057 | break; |
| 4049 | } | 4058 | } |
| @@ -4166,7 +4175,8 @@ next: | |||
| 4166 | struct extent_buffer *cur; | 4175 | struct extent_buffer *cur; |
| 4167 | cur = btrfs_find_tree_block(root, blockptr, | 4176 | cur = btrfs_find_tree_block(root, blockptr, |
| 4168 | btrfs_level_size(root, level - 1)); | 4177 | btrfs_level_size(root, level - 1)); |
| 4169 | if (!cur || !btrfs_buffer_uptodate(cur, gen)) { | 4178 | if (!cur || |
| 4179 | btrfs_buffer_uptodate(cur, gen, 1) <= 0) { | ||
| 4170 | slot++; | 4180 | slot++; |
| 4171 | if (cur) | 4181 | if (cur) |
| 4172 | free_extent_buffer(cur); | 4182 | free_extent_buffer(cur); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index d0c969beaad4..a7ffc88a7dbe 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -323,7 +323,8 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, | |||
| 323 | * in the wrong place. | 323 | * in the wrong place. |
| 324 | */ | 324 | */ |
| 325 | static int verify_parent_transid(struct extent_io_tree *io_tree, | 325 | static int verify_parent_transid(struct extent_io_tree *io_tree, |
| 326 | struct extent_buffer *eb, u64 parent_transid) | 326 | struct extent_buffer *eb, u64 parent_transid, |
| 327 | int atomic) | ||
| 327 | { | 328 | { |
| 328 | struct extent_state *cached_state = NULL; | 329 | struct extent_state *cached_state = NULL; |
| 329 | int ret; | 330 | int ret; |
| @@ -331,6 +332,9 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, | |||
| 331 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) | 332 | if (!parent_transid || btrfs_header_generation(eb) == parent_transid) |
| 332 | return 0; | 333 | return 0; |
| 333 | 334 | ||
| 335 | if (atomic) | ||
| 336 | return -EAGAIN; | ||
| 337 | |||
| 334 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, | 338 | lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1, |
| 335 | 0, &cached_state); | 339 | 0, &cached_state); |
| 336 | if (extent_buffer_uptodate(eb) && | 340 | if (extent_buffer_uptodate(eb) && |
| @@ -372,7 +376,8 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, | |||
| 372 | ret = read_extent_buffer_pages(io_tree, eb, start, | 376 | ret = read_extent_buffer_pages(io_tree, eb, start, |
| 373 | WAIT_COMPLETE, | 377 | WAIT_COMPLETE, |
| 374 | btree_get_extent, mirror_num); | 378 | btree_get_extent, mirror_num); |
| 375 | if (!ret && !verify_parent_transid(io_tree, eb, parent_transid)) | 379 | if (!ret && !verify_parent_transid(io_tree, eb, |
| 380 | parent_transid, 0)) | ||
| 376 | break; | 381 | break; |
| 377 | 382 | ||
| 378 | /* | 383 | /* |
| @@ -1202,7 +1207,7 @@ static int __must_check find_and_setup_root(struct btrfs_root *tree_root, | |||
| 1202 | root->commit_root = NULL; | 1207 | root->commit_root = NULL; |
| 1203 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), | 1208 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), |
| 1204 | blocksize, generation); | 1209 | blocksize, generation); |
| 1205 | if (!root->node || !btrfs_buffer_uptodate(root->node, generation)) { | 1210 | if (!root->node || !btrfs_buffer_uptodate(root->node, generation, 0)) { |
| 1206 | free_extent_buffer(root->node); | 1211 | free_extent_buffer(root->node); |
| 1207 | root->node = NULL; | 1212 | root->node = NULL; |
| 1208 | return -EIO; | 1213 | return -EIO; |
| @@ -3143,7 +3148,8 @@ int close_ctree(struct btrfs_root *root) | |||
| 3143 | return 0; | 3148 | return 0; |
| 3144 | } | 3149 | } |
| 3145 | 3150 | ||
| 3146 | int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid) | 3151 | int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, |
| 3152 | int atomic) | ||
| 3147 | { | 3153 | { |
| 3148 | int ret; | 3154 | int ret; |
| 3149 | struct inode *btree_inode = buf->pages[0]->mapping->host; | 3155 | struct inode *btree_inode = buf->pages[0]->mapping->host; |
| @@ -3153,7 +3159,9 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid) | |||
| 3153 | return ret; | 3159 | return ret; |
| 3154 | 3160 | ||
