diff options
| author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-07-17 21:42:24 -0400 |
|---|---|---|
| committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-07-22 21:02:15 -0400 |
| commit | 464ece88630d0fb715ca942eabb1da825046a534 (patch) | |
| tree | 254185629ce58cf314c5b22b846969a3c26984ed | |
| parent | 26dfdd8e29f28c08aa67861b3c83d0f3f7d30cee (diff) | |
nilfs2: add btree get block function with readahead option
This adds __nilfs_btree_get_block() function that can issue a series
of read-ahead requests for sibling btree nodes.
This read-ahead needs parent node block, so nilfs_btree_readahead_info
structure is added to pass the information that
__nilfs_btree_get_block() needs.
This also replaces the previous nilfs_btree_get_block() implementation
with a wrapper function of __nilfs_btree_get_block().
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
| -rw-r--r-- | fs/nilfs2/btree.c | 94 |
1 files changed, 68 insertions, 26 deletions
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index 4669389bf686..1b5321c0bcac 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c | |||
| @@ -66,32 +66,6 @@ static void nilfs_btree_free_path(struct nilfs_btree_path *path) | |||
| 66 | /* | 66 | /* |
| 67 | * B-tree node operations | 67 | * B-tree node operations |
| 68 | */ | 68 | */ |
| 69 | static int nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr, | ||
| 70 | struct buffer_head **bhp) | ||
| 71 | { | ||
| 72 | struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache; | ||
| 73 | struct buffer_head *bh; | ||
| 74 | sector_t pbn = 0; | ||
| 75 | int err; | ||
| 76 | |||
| 77 | err = nilfs_btnode_submit_block(btnc, ptr, pbn, READ, bhp, &pbn); | ||
| 78 | if (err) | ||
| 79 | return err == -EEXIST ? 0 : err; | ||
| 80 | |||
| 81 | bh = *bhp; | ||
| 82 | wait_on_buffer(bh); | ||
| 83 | if (!buffer_uptodate(bh)) { | ||
| 84 | brelse(bh); | ||
| 85 | return -EIO; | ||
| 86 | } | ||
| 87 | if (nilfs_btree_broken_node_block(bh)) { | ||
| 88 | clear_buffer_uptodate(bh); | ||
| 89 | brelse(bh); | ||
| 90 | return -EINVAL; | ||
| 91 | } | ||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | static int nilfs_btree_get_new_block(const struct nilfs_bmap *btree, | 69 | static int nilfs_btree_get_new_block(const struct nilfs_bmap *btree, |
| 96 | __u64 ptr, struct buffer_head **bhp) | 70 | __u64 ptr, struct buffer_head **bhp) |
| 97 | { | 71 | { |
| @@ -452,6 +426,74 @@ nilfs_btree_bad_node(struct nilfs_btree_node *node, int level) | |||
| 452 | return 0; | 426 | return 0; |
| 453 | } | 427 | } |
| 454 | 428 | ||
| 429 | struct nilfs_btree_readahead_info { | ||
| 430 | struct nilfs_btree_node *node; /* parent node */ | ||
| 431 | int max_ra_blocks; /* max nof blocks to read ahead */ | ||
| 432 | int index; /* current index on the parent node */ | ||
| 433 | int ncmax; /* nof children in the parent node */ | ||
| 434 | }; | ||
| 435 | |||
| 436 | static int __nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr, | ||
| 437 | struct buffer_head **bhp, | ||
| 438 | const struct nilfs_btree_readahead_info *ra) | ||
| 439 | { | ||
| 440 | struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache; | ||
| 441 | struct buffer_head *bh, *ra_bh; | ||
| 442 | sector_t submit_ptr = 0; | ||
| 443 | int ret; | ||
| 444 | |||
| 445 | ret = nilfs_btnode_submit_block(btnc, ptr, 0, READ, &bh, &submit_ptr); | ||
| 446 | if (ret) { | ||
| 447 | if (ret != -EEXIST) | ||
| 448 | return ret; | ||
| 449 | goto out_check; | ||
| 450 | } | ||
| 451 | |||
| 452 | if (ra) { | ||
| 453 | int i, n; | ||
| 454 | __u64 ptr2; | ||
| 455 | |||
| 456 | /* read ahead sibling nodes */ | ||
| 457 | for (n = ra->max_ra_blocks, i = ra->index + 1; | ||
| 458 | n > 0 && i < ra->ncmax; n--, i++) { | ||
| 459 | ptr2 = nilfs_btree_node_get_ptr(ra->node, i, ra->ncmax); | ||
| 460 | |||
| 461 | ret = nilfs_btnode_submit_block(btnc, ptr2, 0, READA, | ||
| 462 | &ra_bh, &submit_ptr); | ||
| 463 | if (likely(!ret || ret == -EEXIST)) | ||
| 464 | brelse(ra_bh); | ||
| 465 | else if (ret != -EBUSY) | ||
| 466 | break; | ||
| 467 | if (!buffer_locked(bh)) | ||
| 468 | goto out_no_wait; | ||
| 469 | } | ||
| 470 | } | ||
| 471 | |||
| 472 | wait_on_buffer(bh); | ||
| 473 | |||
| 474 | out_no_wait: | ||
| 475 | if (!buffer_uptodate(bh)) { | ||
| 476 | brelse(bh); | ||
| 477 | return -EIO; | ||
| 478 | } | ||
| 479 | |||
| 480 | out_check: | ||
| 481 | if (nilfs_btree_broken_node_block(bh)) { | ||
| 482 | clear_buffer_uptodate(bh); | ||
| 483 | brelse(bh); | ||
| 484 | return -EINVAL; | ||
| 485 | } | ||
| 486 | |||
| 487 | *bhp = bh; | ||
| 488 | return 0; | ||
| 489 | } | ||
| 490 | |||
| 491 | static int nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr, | ||
| 492 | struct buffer_head **bhp) | ||
| 493 | { | ||
| 494 | return __nilfs_btree_get_block(btree, ptr, bhp, NULL); | ||
| 495 | } | ||
| 496 | |||
| 455 | static int nilfs_btree_do_lookup(const struct nilfs_bmap *btree, | 497 | static int nilfs_btree_do_lookup(const struct nilfs_bmap *btree, |
| 456 | struct nilfs_btree_path *path, | 498 | struct nilfs_btree_path *path, |
| 457 | __u64 key, __u64 *ptrp, int minlevel) | 499 | __u64 key, __u64 *ptrp, int minlevel) |
