diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2009-05-24 13:47:14 -0400 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2009-06-10 10:41:12 -0400 |
commit | c3a7abf06ce719a51139e62a034590be99abbc2c (patch) | |
tree | 14d61bbd8c34d1b1c7997c9afad79158b7af2914 | |
parent | fa032744ad41de1b0a1807e7c379c6196e72ad80 (diff) |
nilfs2: support contiguous lookup of blocks
Although get_block() callback function can return extent of contiguous
blocks with bh->b_size, nilfs_get_block() function did not support
this feature.
This adds contiguous lookup feature to the block mapping codes of
nilfs, and allows the nilfs_get_blocks() function to return the extent
information by applying the feature.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
-rw-r--r-- | fs/nilfs2/bmap.c | 12 | ||||
-rw-r--r-- | fs/nilfs2/bmap.h | 4 | ||||
-rw-r--r-- | fs/nilfs2/btree.c | 84 | ||||
-rw-r--r-- | fs/nilfs2/direct.c | 43 | ||||
-rw-r--r-- | fs/nilfs2/inode.c | 15 |
5 files changed, 150 insertions, 8 deletions
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 51824c764294..36df60b6d8a4 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include "dat.h" | 31 | #include "dat.h" |
32 | #include "alloc.h" | 32 | #include "alloc.h" |
33 | 33 | ||
34 | static struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap) | 34 | struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap) |
35 | { | 35 | { |
36 | return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode)); | 36 | return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode)); |
37 | } | 37 | } |
@@ -58,6 +58,16 @@ int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level, | |||
58 | return ret; | 58 | return ret; |
59 | } | 59 | } |
60 | 60 | ||
61 | int nilfs_bmap_lookup_contig(struct nilfs_bmap *bmap, __u64 key, __u64 *ptrp, | ||
62 | unsigned maxblocks) | ||
63 | { | ||
64 | int ret; | ||
65 | |||
66 | down_read(&bmap->b_sem); | ||
67 | ret = bmap->b_ops->bop_lookup_contig(bmap, key, ptrp, maxblocks); | ||
68 | up_read(&bmap->b_sem); | ||
69 | return ret; | ||
70 | } | ||
61 | 71 | ||
62 | /** | 72 | /** |
63 | * nilfs_bmap_lookup - find a record | 73 | * nilfs_bmap_lookup - find a record |
diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h index 47f5b74713c0..b2890cdcef12 100644 --- a/fs/nilfs2/bmap.h +++ b/fs/nilfs2/bmap.h | |||
@@ -64,6 +64,8 @@ struct nilfs_bmap_stats { | |||
64 | */ | 64 | */ |
65 | struct nilfs_bmap_operations { | 65 | struct nilfs_bmap_operations { |
66 | int (*bop_lookup)(const struct nilfs_bmap *, __u64, int, __u64 *); | 66 | int (*bop_lookup)(const struct nilfs_bmap *, __u64, int, __u64 *); |
67 | int (*bop_lookup_contig)(const struct nilfs_bmap *, __u64, __u64 *, | ||
68 | unsigned); | ||
67 | int (*bop_insert)(struct nilfs_bmap *, __u64, __u64); | 69 | int (*bop_insert)(struct nilfs_bmap *, __u64, __u64); |
68 | int (*bop_delete)(struct nilfs_bmap *, __u64); | 70 | int (*bop_delete)(struct nilfs_bmap *, __u64); |
69 | void (*bop_clear)(struct nilfs_bmap *); | 71 | void (*bop_clear)(struct nilfs_bmap *); |
@@ -140,6 +142,7 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *); | |||
140 | int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *); | 142 | int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *); |
141 | void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *); | 143 | void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *); |
142 | int nilfs_bmap_lookup(struct nilfs_bmap *, unsigned long, unsigned long *); | 144 | int nilfs_bmap_lookup(struct nilfs_bmap *, unsigned long, unsigned long *); |
145 | int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned); | ||
143 | int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long); | 146 | int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long); |
144 | int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long); | 147 | int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long); |
145 | int nilfs_bmap_last_key(struct nilfs_bmap *, unsigned long *); | 148 | int nilfs_bmap_last_key(struct nilfs_bmap *, unsigned long *); |
@@ -160,6 +163,7 @@ void nilfs_bmap_commit_gcdat(struct nilfs_bmap *, struct nilfs_bmap *); | |||
160 | /* | 163 | /* |
161 | * Internal use only | 164 | * Internal use only |
162 | */ | 165 | */ |
166 | struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *); | ||
163 | int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *, | 167 | int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *, |
164 | union nilfs_bmap_ptr_req *); | 168 | union nilfs_bmap_ptr_req *); |
165 | void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *, | 169 | void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *, |
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index 24395e6d29d0..aa412724b64e 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "btnode.h" | 29 | #include "btnode.h" |
30 | #include "btree.h" | 30 | #include "btree.h" |
31 | #include "alloc.h" | 31 | #include "alloc.h" |
32 | #include "dat.h" | ||
32 | 33 | ||
33 | /** | 34 | /** |
34 | * struct nilfs_btree_path - A path on which B-tree operations are executed | 35 | * struct nilfs_btree_path - A path on which B-tree operations are executed |
@@ -595,6 +596,87 @@ static int nilfs_btree_lookup(const struct nilfs_bmap *bmap, | |||
595 | return ret; | 596 | return ret; |
596 | } | 597 | } |
597 | 598 | ||
599 | static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | ||
600 | __u64 key, __u64 *ptrp, unsigned maxblocks) | ||
601 | { | ||
602 | struct nilfs_btree *btree = (struct nilfs_btree *)bmap; | ||
603 | struct nilfs_btree_path *path; | ||
604 | struct nilfs_btree_node *node; | ||
605 | struct inode *dat = NULL; | ||
606 | __u64 ptr, ptr2; | ||
607 | sector_t blocknr; | ||
608 | int level = NILFS_BTREE_LEVEL_NODE_MIN; | ||
609 | int ret, cnt, index, maxlevel; | ||
610 | |||
611 | path = nilfs_btree_alloc_path(btree); | ||
612 | if (path == NULL) | ||
613 | return -ENOMEM; | ||
614 | nilfs_btree_init_path(btree, path); | ||
615 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); | ||
616 | if (ret < 0) | ||
617 | goto out; | ||
618 | |||
619 | if (NILFS_BMAP_USE_VBN(bmap)) { | ||
620 | dat = nilfs_bmap_get_dat(bmap); | ||
621 | ret = nilfs_dat_translate(dat, ptr, &blocknr); | ||
622 | if (ret < 0) | ||
623 | goto out; | ||
624 | ptr = blocknr; | ||
625 | } | ||
626 | cnt = 1; | ||
627 | if (cnt == maxblocks) | ||
628 | goto end; | ||
629 | |||
630 | maxlevel = nilfs_btree_height(btree) - 1; | ||
631 | node = nilfs_btree_get_node(btree, path, level); | ||
632 | index = path[level].bp_index + 1; | ||
633 | for (;;) { | ||
634 | while (index < nilfs_btree_node_get_nchildren(btree, node)) { | ||
635 | if (nilfs_btree_node_get_key(btree, node, index) != | ||
636 | key + cnt) | ||
637 | goto end; | ||
638 | ptr2 = nilfs_btree_node_get_ptr(btree, node, index); | ||
639 | if (dat) { | ||
640 | ret = nilfs_dat_translate(dat, ptr2, &blocknr); | ||
641 | if (ret < 0) | ||
642 | goto out; | ||
643 | ptr2 = blocknr; | ||
644 | } | ||
645 | if (ptr2 != ptr + cnt || ++cnt == maxblocks) | ||
646 | goto end; | ||
647 | index++; | ||
648 | continue; | ||
649 | } | ||
650 | if (level == maxlevel) | ||
651 | break; | ||
652 | |||
653 | /* look-up right sibling node */ | ||
654 | node = nilfs_btree_get_node(btree, path, level + 1); | ||
655 | index = path[level + 1].bp_index + 1; | ||
656 | if (index >= nilfs_btree_node_get_nchildren(btree, node) || | ||
657 | nilfs_btree_node_get_key(btree, node, index) != key + cnt) | ||
658 | break; | ||
659 | ptr2 = nilfs_btree_node_get_ptr(btree, node, index); | ||
660 | path[level + 1].bp_index = index; | ||
661 | |||
662 | brelse(path[level].bp_bh); | ||
663 | path[level].bp_bh = NULL; | ||
664 | ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh); | ||
665 | if (ret < 0) | ||
666 | goto out; | ||
667 | node = nilfs_btree_get_nonroot_node(btree, path, level); | ||
668 | index = 0; | ||
669 | path[level].bp_index = index; | ||
670 | } | ||
671 | end: | ||
672 | *ptrp = ptr; | ||
673 | ret = cnt; | ||
674 | out: | ||
675 | nilfs_btree_clear_path(btree, path); | ||
676 | nilfs_btree_free_path(btree, path); | ||
677 | return ret; | ||
678 | } | ||
679 | |||
598 | static void nilfs_btree_promote_key(struct nilfs_btree *btree, | 680 | static void nilfs_btree_promote_key(struct nilfs_btree *btree, |
599 | struct nilfs_btree_path *path, | 681 | struct nilfs_btree_path *path, |
600 | int level, __u64 key) | 682 | int level, __u64 key) |
@@ -2187,6 +2269,7 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level) | |||
2187 | 2269 | ||
2188 | static const struct nilfs_bmap_operations nilfs_btree_ops = { | 2270 | static const struct nilfs_bmap_operations nilfs_btree_ops = { |
2189 | .bop_lookup = nilfs_btree_lookup, | 2271 | .bop_lookup = nilfs_btree_lookup, |
2272 | .bop_lookup_contig = nilfs_btree_lookup_contig, | ||
2190 | .bop_insert = nilfs_btree_insert, | 2273 | .bop_insert = nilfs_btree_insert, |
2191 | .bop_delete = nilfs_btree_delete, | 2274 | .bop_delete = nilfs_btree_delete, |
2192 | .bop_clear = NULL, | 2275 | .bop_clear = NULL, |
@@ -2206,6 +2289,7 @@ static const struct nilfs_bmap_operations nilfs_btree_ops = { | |||
2206 | 2289 | ||
2207 | static const struct nilfs_bmap_operations nilfs_btree_ops_gc = { | 2290 | static const struct nilfs_bmap_operations nilfs_btree_ops_gc = { |
2208 | .bop_lookup = NULL, | 2291 | .bop_lookup = NULL, |
2292 | .bop_lookup_contig = NULL, | ||
2209 | .bop_insert = NULL, | 2293 | .bop_insert = NULL, |
2210 | .bop_delete = NULL, | 2294 | .bop_delete = NULL, |
2211 | .bop_clear = NULL, | 2295 | .bop_clear = NULL, |
diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c index 33467adf094b..342d9765df8d 100644 --- a/fs/nilfs2/direct.c +++ b/fs/nilfs2/direct.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "page.h" | 25 | #include "page.h" |
26 | #include "direct.h" | 26 | #include "direct.h" |
27 | #include "alloc.h" | 27 | #include "alloc.h" |
28 | #include "dat.h" | ||
28 | 29 | ||
29 | static inline __le64 *nilfs_direct_dptrs(const struct nilfs_direct *direct) | 30 | static inline __le64 *nilfs_direct_dptrs(const struct nilfs_direct *direct) |
30 | { | 31 | { |
@@ -62,6 +63,47 @@ static int nilfs_direct_lookup(const struct nilfs_bmap *bmap, | |||
62 | return 0; | 63 | return 0; |
63 | } | 64 | } |
64 | 65 | ||
66 | static int nilfs_direct_lookup_contig(const struct nilfs_bmap *bmap, | ||
67 | __u64 key, __u64 *ptrp, | ||
68 | unsigned maxblocks) | ||
69 | { | ||
70 | struct nilfs_direct *direct = (struct nilfs_direct *)bmap; | ||
71 | struct inode *dat = NULL; | ||
72 | __u64 ptr, ptr2; | ||
73 | sector_t blocknr; | ||
74 | int ret, cnt; | ||
75 | |||
76 | if (key > NILFS_DIRECT_KEY_MAX || | ||
77 | (ptr = nilfs_direct_get_ptr(direct, key)) == | ||
78 | NILFS_BMAP_INVALID_PTR) | ||
79 | return -ENOENT; | ||
80 | |||
81 | if (NILFS_BMAP_USE_VBN(bmap)) { | ||
82 | dat = nilfs_bmap_get_dat(bmap); | ||
83 | ret = nilfs_dat_translate(dat, ptr, &blocknr); | ||
84 | if (ret < 0) | ||
85 | return ret; | ||
86 | ptr = blocknr; | ||
87 | } | ||
88 | |||
89 | maxblocks = min_t(unsigned, maxblocks, NILFS_DIRECT_KEY_MAX - key + 1); | ||
90 | for (cnt = 1; cnt < maxblocks && | ||
91 | (ptr2 = nilfs_direct_get_ptr(direct, key + cnt)) != | ||
92 | NILFS_BMAP_INVALID_PTR; | ||
93 | cnt++) { | ||
94 | if (dat) { | ||
95 | ret = nilfs_dat_translate(dat, ptr2, &blocknr); | ||
96 | if (ret < 0) | ||
97 | return ret; | ||
98 | ptr2 = blocknr; | ||
99 | } | ||
100 | if (ptr2 != ptr + cnt) | ||
101 | break; | ||
102 | } | ||
103 | *ptrp = ptr; | ||
104 | return cnt; | ||
105 | } | ||
106 | |||
65 | static __u64 | 107 | static __u64 |
66 | nilfs_direct_find_target_v(const struct nilfs_direct *direct, __u64 key) | 108 | nilfs_direct_find_target_v(const struct nilfs_direct *direct, __u64 key) |
67 | { | 109 | { |
@@ -367,6 +409,7 @@ static int nilfs_direct_assign(struct nilfs_bmap *bmap, | |||
367 | 409 | ||
368 | static const struct nilfs_bmap_operations nilfs_direct_ops = { | 410 | static const struct nilfs_bmap_operations nilfs_direct_ops = { |
369 | .bop_lookup = nilfs_direct_lookup, | 411 | .bop_lookup = nilfs_direct_lookup, |
412 | .bop_lookup_contig = nilfs_direct_lookup_contig, | ||
370 | .bop_insert = nilfs_direct_insert, | 413 | .bop_insert = nilfs_direct_insert, |
371 | .bop_delete = nilfs_direct_delete, | 414 | .bop_delete = nilfs_direct_delete, |
372 | .bop_clear = NULL, | 415 | .bop_clear = NULL, |
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index f25fd4b895bc..2696d6b513b7 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
@@ -43,22 +43,23 @@ | |||
43 | * | 43 | * |
44 | * This function does not issue actual read request of the specified data | 44 | * This function does not issue actual read request of the specified data |
45 | * block. It is done by VFS. | 45 | * block. It is done by VFS. |
46 | * Bulk read for direct-io is not supported yet. (should be supported) | ||
47 | */ | 46 | */ |
48 | int nilfs_get_block(struct inode *inode, sector_t blkoff, | 47 | int nilfs_get_block(struct inode *inode, sector_t blkoff, |
49 | struct buffer_head *bh_result, int create) | 48 | struct buffer_head *bh_result, int create) |
50 | { | 49 | { |
51 | struct nilfs_inode_info *ii = NILFS_I(inode); | 50 | struct nilfs_inode_info *ii = NILFS_I(inode); |
52 | unsigned long blknum = 0; | 51 | __u64 blknum = 0; |
53 | int err = 0, ret; | 52 | int err = 0, ret; |
54 | struct inode *dat = nilfs_dat_inode(NILFS_I_NILFS(inode)); | 53 | struct inode *dat = nilfs_dat_inode(NILFS_I_NILFS(inode)); |
54 | unsigned maxblocks = bh_result->b_size >> inode->i_blkbits; | ||
55 | 55 | ||
56 | /* This exclusion control is a workaround; should be revised */ | 56 | down_read(&NILFS_MDT(dat)->mi_sem); |
57 | down_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ | 57 | ret = nilfs_bmap_lookup_contig(ii->i_bmap, blkoff, &blknum, maxblocks); |
58 | ret = nilfs_bmap_lookup(ii->i_bmap, (unsigned long)blkoff, &blknum); | 58 | up_read(&NILFS_MDT(dat)->mi_sem); |
59 | up_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ | 59 | if (ret >= 0) { /* found */ |
60 | if (ret == 0) { /* found */ | ||
61 | map_bh(bh_result, inode->i_sb, blknum); | 60 | map_bh(bh_result, inode->i_sb, blknum); |
61 | if (ret > 0) | ||
62 | bh_result->b_size = (ret << inode->i_blkbits); | ||
62 | goto out; | 63 | goto out; |
63 | } | 64 | } |
64 | /* data block was not found */ | 65 | /* data block was not found */ |