aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2015-04-16 15:46:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-17 09:04:03 -0400
commit5b20384fb32cc3f93857f44fb84736d6d62a9917 (patch)
treef6ab08afbf9777142c63d447a1f0e6b02df08679
parent3568a13f4089aac90b3763a2b6c293cd2b638ec1 (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.c31
-rw-r--r--fs/nilfs2/bmap.h5
-rw-r--r--fs/nilfs2/btree.c63
-rw-r--r--fs/nilfs2/direct.c17
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 */
210int 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
192int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp) 223int 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 *);
155int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned); 157int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned);
156int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec); 158int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec);
157int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key); 159int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key);
160int nilfs_bmap_seek_key(struct nilfs_bmap *bmap, __u64 start, __u64 *keyp);
158int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp); 161int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp);
159int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key); 162int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key);
160void nilfs_bmap_clear(struct nilfs_bmap *); 163void 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 */
646static 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
636static int nilfs_btree_lookup(const struct nilfs_bmap *btree, 674static 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
1604static 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
1566static int nilfs_btree_last_key(const struct nilfs_bmap *btree, __u64 *keyp) 1625static 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
176static 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
176static int nilfs_direct_last_key(const struct nilfs_bmap *direct, __u64 *keyp) 191static 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,