History

Btrfs: avoid sleeping in verify_parent_transid while atomic

verify_parent_transid needs to lock the extent range to make sure no IO is underway, and so it can safely clear the uptodate bits if our checks fail. But, a few callers are using it with spinlocks held. Most of the time, the generation numbers are going to match, and we don't want to switch to a blocking lock just for the error case. This adds an atomic flag to verify_parent_transid, and changes it to return EAGAIN if it needs to block to properly verifiy things.

Chris Mason committed 14 years ago

Commit b9fab911 parent ea9947b5 files · +34 −17Browse files

Unified · Split

5 files
  1. fs/btrfs/ctree.c +17 −9
  2. fs/btrfs/disk-io.c +13 −5
  3. fs/btrfs/disk-io.h +2 −1
  4. fs/btrfs/extent-tree.c +1 −1
  5. fs/btrfs/tree-log.c +1 −1
fs/btrfs/ctree.c+17−9
@@ -725,7 +725,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, · 724 unmodified lines
725725
726726 cur = btrfs_find_tree_block(root, blocknr, blocksize);
727727 if (cur)
728− uptodate = btrfs_buffer_uptodate(cur, gen);
728+ uptodate = btrfs_buffer_uptodate(cur, gen, 0);
729729 else
730730 uptodate = 0;
731731 if (!cur || !uptodate) {
@@ -1360,7 +1360,12 @@ static noinline int reada_for_balance(struct btrfs_root *root, · 628 unmodified lines
13601360 block1 = btrfs_node_blockptr(parent, slot - 1);
13611361 gen = btrfs_node_ptr_generation(parent, slot - 1);
13621362 eb = btrfs_find_tree_block(root, block1, blocksize);
1363− 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)
13641369 block1 = 0;
13651370 free_extent_buffer(eb);
13661371 }
@@ -1368,7 +1373,7 @@ static noinline int reada_for_balance(struct btrfs_root *root, · 1 unmodified line
13681373 block2 = btrfs_node_blockptr(parent, slot + 1);
13691374 gen = btrfs_node_ptr_generation(parent, slot + 1);
13701375 eb = btrfs_find_tree_block(root, block2, blocksize);
1371− if (eb && btrfs_buffer_uptodate(eb, gen))
1376+ if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0)
13721377 block2 = 0;
13731378 free_extent_buffer(eb);
13741379 }
@@ -1506,8 +1511,9 @@ read_block_for_search(struct btrfs_trans_handle *trans, · 131 unmodified lines
15061511
15071512 tmp = btrfs_find_tree_block(root, blocknr, blocksize);
15081513 if (tmp) {
1509− if (btrfs_buffer_uptodate(tmp, 0)) {
1510− if (btrfs_buffer_uptodate(tmp, gen)) {
1514+ /* first we do an atomic uptodate check */
1515+ if (btrfs_buffer_uptodate(tmp, 0, 1) > 0) {
1516+ if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) {
15111517 /*
15121518 * we found an up to date block without
15131519 * sleeping, return
@@ -1525,8 +1531,9 @@ read_block_for_search(struct btrfs_trans_handle *trans, · 11 unmodified lines
15251531 free_extent_buffer(tmp);
15261532 btrfs_set_path_blocking(p);
15271533
1534+ /* now we're allowed to do a blocking uptodate check */
15281535 tmp = read_tree_block(root, blocknr, blocksize, gen);
1529− if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
1536+ if (tmp && btrfs_buffer_uptodate(tmp, gen, 0) > 0) {
15301537 *eb_ret = tmp;
15311538 return 0;
15321539 }
@@ -1561,7 +1568,7 @@ read_block_for_search(struct btrfs_trans_handle *trans, · 28 unmodified lines
15611568 * and give up so that our caller doesn't loop forever
15621569 * on our EAGAINs.
15631570 */
1564− if (!btrfs_buffer_uptodate(tmp, 0))
1571+ if (!btrfs_buffer_uptodate(tmp, 0, 0))
15651572 ret = -EIO;
15661573 free_extent_buffer(tmp);
15671574 }
@@ -4045,7 +4052,7 @@ again: · 2477 unmodified lines
40454052 tmp = btrfs_find_tree_block(root, blockptr,
40464053 btrfs_level_size(root, level - 1));
40474054
4048− if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
4055+ if (tmp && btrfs_buffer_uptodate(tmp, gen, 1) > 0) {
40494056 free_extent_buffer(tmp);
40504057 break;
40514058 }
@@ -4168,7 +4175,8 @@ next: · 116 unmodified lines
41684175 struct extent_buffer *cur;
41694176 cur = btrfs_find_tree_block(root, blockptr,
41704177 btrfs_level_size(root, level - 1));
4171− if (!cur || !btrfs_buffer_uptodate(cur, gen)) {
4178+ if (!cur ||
4179+ btrfs_buffer_uptodate(cur, gen, 1) <= 0) {
41724180 slot++;
41734181 if (cur)
41744182 free_extent_buffer(cur);
fs/btrfs/disk-io.c+13−5
@@ -323,7 +323,8 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf, · 322 unmodified lines
323323 * in the wrong place.
324324 */
325325 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)
327328 {
328329 struct extent_state *cached_state = NULL;
329330 int ret;
@@ -331,6 +332,9 @@ static int verify_parent_transid(struct extent_io_tree *io_tree, · 1 unmodified line
331332 if (!parent_transid || btrfs_header_generation(eb) == parent_transid)
332333 return 0;
333334
335+ if (atomic)
336+ return -EAGAIN;
337+
334338 lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1,
335339 0, &cached_state);
336340 if (extent_buffer_uptodate(eb) &&
@@ -372,7 +376,8 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, · 35 unmodified lines
372376 ret = read_extent_buffer_pages(io_tree, eb, start,
373377 WAIT_COMPLETE,
374378 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))
376381 break;
377382
378383 /*
@@ -1202,7 +1207,7 @@ static int __must_check find_and_setup_root(struct btrfs_root *tree_root, · 823 unmodified lines
12021207 root->commit_root = NULL;
12031208 root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
12041209 blocksize, generation);
1205− if (!root->node || !btrfs_buffer_uptodate(root->node, generation)) {
1210+ if (!root->node || !btrfs_buffer_uptodate(root->node, generation, 0)) {
12061211 free_extent_buffer(root->node);
12071212 root->node = NULL;
12081213 return -EIO;
@@ -3143,7 +3148,8 @@ int close_ctree(struct btrfs_root *root) · 1934 unmodified lines
31433148 return 0;
31443149 }
31453150
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)
31473153 {
31483154 int ret;
31493155 struct inode *btree_inode = buf->pages[0]->mapping->host;
@@ -3153,7 +3159,9 @@ int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid) · 3 unmodified lines
31533159 return ret;
31543160
31553161 ret = verify_parent_transid(&BTRFS_I(btree_inode)->io_tree, buf,
3156− parent_transid);
3162+ parent_transid, atomic);
3163+ if (ret == -EAGAIN)
3164+ return ret;
31573165 return !ret;
31583166 }
31593167
fs/btrfs/disk-io.h+2−1
@@ -66,7 +66,8 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); · 65 unmodified lines
6666 void __btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr);
6767 void btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root);
6868 void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
69−int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid);
69+int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,
70+ int atomic);
7071 int btrfs_set_buffer_uptodate(struct extent_buffer *buf);
7172 int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid);
7273 u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len);
fs/btrfs/extent-tree.c+1−1
@@ -6568,7 +6568,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, · 6567 unmodified lines
65686568 goto skip;
65696569 }
65706570
6571− if (!btrfs_buffer_uptodate(next, generation)) {
6571+ if (!btrfs_buffer_uptodate(next, generation, 0)) {
65726572 btrfs_tree_unlock(next);
65736573 free_extent_buffer(next);
65746574 next = NULL;
fs/btrfs/tree-log.c+1−1
@@ -279,7 +279,7 @@ static int process_one_buffer(struct btrfs_root *log, · 278 unmodified lines
279279 log->fs_info->extent_root,
280280 eb->start, eb->len);
281281
282− if (btrfs_buffer_uptodate(eb, gen)) {
282+ if (btrfs_buffer_uptodate(eb, gen, 0)) {
283283 if (wc->write)
284284 btrfs_write_tree_block(eb);
285285 if (wc->wait)