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 /fs | |
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>
Diffstat (limited to 'fs')
-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) |