diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2015-04-16 15:46:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-17 09:04:03 -0400 |
commit | 5b20384fb32cc3f93857f44fb84736d6d62a9917 (patch) | |
tree | f6ab08afbf9777142c63d447a1f0e6b02df08679 | |
parent | 3568a13f4089aac90b3763a2b6c293cd2b638ec1 (diff) |
nilfs2: add bmap function to seek a valid key
Add a new bmap function, nilfs_bmap_seek_key(), which seeks a valid
entry and returns its key starting from a given key. This function
can be used to skip hole blocks efficiently.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/nilfs2/bmap.c | 31 | ||||
-rw-r--r-- | fs/nilfs2/bmap.h | 5 | ||||
-rw-r--r-- | fs/nilfs2/btree.c | 63 | ||||
-rw-r--r-- | fs/nilfs2/direct.c | 17 |
4 files changed, 115 insertions, 1 deletions
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index c82f4361c1f9..27f75bcbeb30 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c | |||
@@ -189,6 +189,37 @@ static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key) | |||
189 | return bmap->b_ops->bop_delete(bmap, key); | 189 | return bmap->b_ops->bop_delete(bmap, key); |
190 | } | 190 | } |
191 | 191 | ||
192 | /** | ||
193 | * nilfs_bmap_seek_key - seek a valid entry and return its key | ||
194 | * @bmap: bmap struct | ||
195 | * @start: start key number | ||
196 | * @keyp: place to store valid key | ||
197 | * | ||
198 | * Description: nilfs_bmap_seek_key() seeks a valid key on @bmap | ||
199 | * starting from @start, and stores it to @keyp if found. | ||
200 | * | ||
201 | * Return Value: On success, 0 is returned. On error, one of the following | ||
202 | * negative error codes is returned. | ||
203 | * | ||
204 | * %-EIO - I/O error. | ||
205 | * | ||
206 | * %-ENOMEM - Insufficient amount of memory available. | ||
207 | * | ||
208 | * %-ENOENT - No valid entry was found | ||
209 | */ | ||
210 | int nilfs_bmap_seek_key(struct nilfs_bmap *bmap, __u64 start, __u64 *keyp) | ||
211 | { | ||
212 | int ret; | ||
213 | |||
214 | down_read(&bmap->b_sem); | ||
215 | ret = bmap->b_ops->bop_seek_key(bmap, start, keyp); | ||
216 | up_read(&bmap->b_sem); | ||
217 | |||
218 | if (ret < 0) | ||
219 | ret = nilfs_bmap_convert_error(bmap, __func__, ret); | ||
220 | return ret; | ||
221 | } | ||
222 | |||
192 | int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp) | 223 | int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp) |
193 | { | 224 | { |
194 | int ret; | 225 | int ret; |
diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h index 9230d3335001..bfa817ce40b3 100644 --- a/fs/nilfs2/bmap.h +++ b/fs/nilfs2/bmap.h | |||
@@ -76,8 +76,10 @@ struct nilfs_bmap_operations { | |||
76 | union nilfs_binfo *); | 76 | union nilfs_binfo *); |
77 | int (*bop_mark)(struct nilfs_bmap *, __u64, int); | 77 | int (*bop_mark)(struct nilfs_bmap *, __u64, int); |
78 | 78 | ||
79 | /* The following functions are internal use only. */ | 79 | int (*bop_seek_key)(const struct nilfs_bmap *, __u64, __u64 *); |
80 | int (*bop_last_key)(const struct nilfs_bmap *, __u64 *); | 80 | int (*bop_last_key)(const struct nilfs_bmap *, __u64 *); |
81 | |||
82 | /* The following functions are internal use only. */ | ||
81 | int (*bop_check_insert)(const struct nilfs_bmap *, __u64); | 83 | int (*bop_check_insert)(const struct nilfs_bmap *, __u64); |
82 | int (*bop_check_delete)(struct nilfs_bmap *, __u64); | 84 | int (*bop_check_delete)(struct nilfs_bmap *, __u64); |
83 | int (*bop_gather_data)(struct nilfs_bmap *, __u64 *, __u64 *, int); | 85 | int (*bop_gather_data)(struct nilfs_bmap *, __u64 *, __u64 *, int); |
@@ -155,6 +157,7 @@ void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *); | |||
155 | int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned); | 157 | int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned); |
156 | int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec); | 158 | int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec); |
157 | int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key); | 159 | int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key); |
160 | int nilfs_bmap_seek_key(struct nilfs_bmap *bmap, __u64 start, __u64 *keyp); | ||
158 | int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp); | 161 | int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp); |
159 | int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key); | 162 | int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key); |
160 | void nilfs_bmap_clear(struct nilfs_bmap *); | 163 | void nilfs_bmap_clear(struct nilfs_bmap *); |
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index ecdbae19a766..059f37137f9a 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c | |||
@@ -633,6 +633,44 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_bmap *btree, | |||
633 | return 0; | 633 | return 0; |
634 | } | 634 | } |
635 | 635 | ||
636 | /** | ||
637 | * nilfs_btree_get_next_key - get next valid key from btree path array | ||
638 | * @btree: bmap struct of btree | ||
639 | * @path: array of nilfs_btree_path struct | ||
640 | * @minlevel: start level | ||
641 | * @nextkey: place to store the next valid key | ||
642 | * | ||
643 | * Return Value: If a next key was found, 0 is returned. Otherwise, | ||
644 | * -ENOENT is returned. | ||
645 | */ | ||
646 | static int nilfs_btree_get_next_key(const struct nilfs_bmap *btree, | ||
647 | const struct nilfs_btree_path *path, | ||
648 | int minlevel, __u64 *nextkey) | ||
649 | { | ||
650 | struct nilfs_btree_node *node; | ||
651 | int maxlevel = nilfs_btree_height(btree) - 1; | ||
652 | int index, next_adj, level; | ||
653 | |||
654 | /* Next index is already set to bp_index for leaf nodes. */ | ||
655 | next_adj = 0; | ||
656 | for (level = minlevel; level <= maxlevel; level++) { | ||
657 | if (level == maxlevel) | ||
658 | node = nilfs_btree_get_root(btree); | ||
659 | else | ||
660 | node = nilfs_btree_get_nonroot_node(path, level); | ||
661 | |||
662 | index = path[level].bp_index + next_adj; | ||
663 | if (index < nilfs_btree_node_get_nchildren(node)) { | ||
664 | /* Next key is in this node */ | ||
665 | *nextkey = nilfs_btree_node_get_key(node, index); | ||
666 | return 0; | ||
667 | } | ||
668 | /* For non-leaf nodes, next index is stored at bp_index + 1. */ | ||
669 | next_adj = 1; | ||
670 | } | ||
671 | return -ENOENT; | ||
672 | } | ||
673 | |||
636 | static int nilfs_btree_lookup(const struct nilfs_bmap *btree, | 674 | static int nilfs_btree_lookup(const struct nilfs_bmap *btree, |
637 | __u64 key, int level, __u64 *ptrp) | 675 | __u64 key, int level, __u64 *ptrp) |
638 | { | 676 | { |
@@ -1563,6 +1601,27 @@ out: | |||
1563 | return ret; | 1601 | return ret; |
1564 | } | 1602 | } |
1565 | 1603 | ||
1604 | static int nilfs_btree_seek_key(const struct nilfs_bmap *btree, __u64 start, | ||
1605 | __u64 *keyp) | ||
1606 | { | ||
1607 | struct nilfs_btree_path *path; | ||
1608 | const int minlevel = NILFS_BTREE_LEVEL_NODE_MIN; | ||
1609 | int ret; | ||
1610 | |||
1611 | path = nilfs_btree_alloc_path(); | ||
1612 | if (!path) | ||
1613 | return -ENOMEM; | ||
1614 | |||
1615 | ret = nilfs_btree_do_lookup(btree, path, start, NULL, minlevel, 0); | ||
1616 | if (!ret) | ||
1617 | *keyp = start; | ||
1618 | else if (ret == -ENOENT) | ||
1619 | ret = nilfs_btree_get_next_key(btree, path, minlevel, keyp); | ||
1620 | |||
1621 | nilfs_btree_free_path(path); | ||
1622 | return ret; | ||
1623 | } | ||
1624 | |||
1566 | static int nilfs_btree_last_key(const struct nilfs_bmap *btree, __u64 *keyp) | 1625 | static int nilfs_btree_last_key(const struct nilfs_bmap *btree, __u64 *keyp) |
1567 | { | 1626 | { |
1568 | struct nilfs_btree_path *path; | 1627 | struct nilfs_btree_path *path; |
@@ -2298,7 +2357,9 @@ static const struct nilfs_bmap_operations nilfs_btree_ops = { | |||
2298 | .bop_assign = nilfs_btree_assign, | 2357 | .bop_assign = nilfs_btree_assign, |
2299 | .bop_mark = nilfs_btree_mark, | 2358 | .bop_mark = nilfs_btree_mark, |
2300 | 2359 | ||
2360 | .bop_seek_key = nilfs_btree_seek_key, | ||
2301 | .bop_last_key = nilfs_btree_last_key, | 2361 | .bop_last_key = nilfs_btree_last_key, |
2362 | |||
2302 | .bop_check_insert = NULL, | 2363 | .bop_check_insert = NULL, |
2303 | .bop_check_delete = nilfs_btree_check_delete, | 2364 | .bop_check_delete = nilfs_btree_check_delete, |
2304 | .bop_gather_data = nilfs_btree_gather_data, | 2365 | .bop_gather_data = nilfs_btree_gather_data, |
@@ -2318,7 +2379,9 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = { | |||
2318 | .bop_assign = nilfs_btree_assign_gc, | 2379 | .bop_assign = nilfs_btree_assign_gc, |
2319 | .bop_mark = NULL, | 2380 | .bop_mark = NULL, |
2320 | 2381 | ||
2382 | .bop_seek_key = NULL, | ||
2321 | .bop_last_key = NULL, | 2383 | .bop_last_key = NULL, |
2384 | |||
2322 | .bop_check_insert = NULL, | 2385 | .bop_check_insert = NULL, |
2323 | .bop_check_delete = NULL, | 2386 | .bop_check_delete = NULL, |
2324 | .bop_gather_data = NULL, | 2387 | .bop_gather_data = NULL, |
diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c index 82f4865e86dd..ebf89fd8ac1a 100644 --- a/fs/nilfs2/direct.c +++ b/fs/nilfs2/direct.c | |||
@@ -173,6 +173,21 @@ static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) | |||
173 | return ret; | 173 | return ret; |
174 | } | 174 | } |
175 | 175 | ||
176 | static int nilfs_direct_seek_key(const struct nilfs_bmap *direct, __u64 start, | ||
177 | __u64 *keyp) | ||
178 | { | ||
179 | __u64 key; | ||
180 | |||
181 | for (key = start; key <= NILFS_DIRECT_KEY_MAX; key++) { | ||
182 | if (nilfs_direct_get_ptr(direct, key) != | ||
183 | NILFS_BMAP_INVALID_PTR) { | ||
184 | *keyp = key; | ||
185 | return 0; | ||
186 | } | ||
187 | } | ||
188 | return -ENOENT; | ||
189 | } | ||
190 | |||
176 | static int nilfs_direct_last_key(const struct nilfs_bmap *direct, __u64 *keyp) | 191 | static int nilfs_direct_last_key(const struct nilfs_bmap *direct, __u64 *keyp) |
177 | { | 192 | { |
178 | __u64 key, lastkey; | 193 | __u64 key, lastkey; |
@@ -355,7 +370,9 @@ static const struct nilfs_bmap_operations nilfs_direct_ops = { | |||
355 | .bop_assign = nilfs_direct_assign, | 370 | .bop_assign = nilfs_direct_assign, |
356 | .bop_mark = NULL, | 371 | .bop_mark = NULL, |
357 | 372 | ||
373 | .bop_seek_key = nilfs_direct_seek_key, | ||
358 | .bop_last_key = nilfs_direct_last_key, | 374 | .bop_last_key = nilfs_direct_last_key, |
375 | |||
359 | .bop_check_insert = nilfs_direct_check_insert, | 376 | .bop_check_insert = nilfs_direct_check_insert, |
360 | .bop_check_delete = NULL, | 377 | .bop_check_delete = NULL, |
361 | .bop_gather_data = nilfs_direct_gather_data, | 378 | .bop_gather_data = nilfs_direct_gather_data, |