1ae98043fSRyusuke Konishi // SPDX-License-Identifier: GPL-2.0+
217c76b01SKoji Sato /*
394ee1d91SRyusuke Konishi * NILFS B-tree.
417c76b01SKoji Sato *
517c76b01SKoji Sato * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
617c76b01SKoji Sato *
74b420ab4SRyusuke Konishi * Written by Koji Sato.
817c76b01SKoji Sato */
917c76b01SKoji Sato
1017c76b01SKoji Sato #include <linux/slab.h>
1117c76b01SKoji Sato #include <linux/string.h>
1217c76b01SKoji Sato #include <linux/errno.h>
1317c76b01SKoji Sato #include <linux/pagevec.h>
1417c76b01SKoji Sato #include "nilfs.h"
1517c76b01SKoji Sato #include "page.h"
1617c76b01SKoji Sato #include "btnode.h"
1717c76b01SKoji Sato #include "btree.h"
1817c76b01SKoji Sato #include "alloc.h"
19c3a7abf0SRyusuke Konishi #include "dat.h"
2017c76b01SKoji Sato
21957ed60bSRyusuke Konishi static void __nilfs_btree_init(struct nilfs_bmap *bmap);
22957ed60bSRyusuke Konishi
nilfs_btree_alloc_path(void)23f905440fSLi Hong static struct nilfs_btree_path *nilfs_btree_alloc_path(void)
2417c76b01SKoji Sato {
25f905440fSLi Hong struct nilfs_btree_path *path;
26f905440fSLi Hong int level = NILFS_BTREE_LEVEL_DATA;
2717c76b01SKoji Sato
28f905440fSLi Hong path = kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS);
29f905440fSLi Hong if (path == NULL)
30f905440fSLi Hong goto out;
3117c76b01SKoji Sato
32f905440fSLi Hong for (; level < NILFS_BTREE_LEVEL_MAX; level++) {
3317c76b01SKoji Sato path[level].bp_bh = NULL;
3417c76b01SKoji Sato path[level].bp_sib_bh = NULL;
3517c76b01SKoji Sato path[level].bp_index = 0;
3617c76b01SKoji Sato path[level].bp_oldreq.bpr_ptr = NILFS_BMAP_INVALID_PTR;
3717c76b01SKoji Sato path[level].bp_newreq.bpr_ptr = NILFS_BMAP_INVALID_PTR;
3817c76b01SKoji Sato path[level].bp_op = NULL;
3917c76b01SKoji Sato }
40f905440fSLi Hong
41f905440fSLi Hong out:
42f905440fSLi Hong return path;
43f905440fSLi Hong }
44f905440fSLi Hong
nilfs_btree_free_path(struct nilfs_btree_path * path)4573bb4886SLi Hong static void nilfs_btree_free_path(struct nilfs_btree_path *path)
46f905440fSLi Hong {
4773bb4886SLi Hong int level = NILFS_BTREE_LEVEL_DATA;
4817c76b01SKoji Sato
4973bb4886SLi Hong for (; level < NILFS_BTREE_LEVEL_MAX; level++)
50087d01b4SRyusuke Konishi brelse(path[level].bp_bh);
5173bb4886SLi Hong
5273bb4886SLi Hong kmem_cache_free(nilfs_btree_path_cache, path);
5317c76b01SKoji Sato }
5417c76b01SKoji Sato
5517c76b01SKoji Sato /*
5617c76b01SKoji Sato * B-tree node operations
5717c76b01SKoji Sato */
nilfs_btree_get_new_block(const struct nilfs_bmap * btree,__u64 ptr,struct buffer_head ** bhp)58e7c274f8SRyusuke Konishi static int nilfs_btree_get_new_block(const struct nilfs_bmap *btree,
59f198dbb9SRyusuke Konishi __u64 ptr, struct buffer_head **bhp)
60f198dbb9SRyusuke Konishi {
61e897be17SRyusuke Konishi struct inode *btnc_inode = NILFS_BMAP_I(btree)->i_assoc_inode;
62e897be17SRyusuke Konishi struct address_space *btnc = btnc_inode->i_mapping;
6345f4910bSRyusuke Konishi struct buffer_head *bh;
64f198dbb9SRyusuke Konishi
6545f4910bSRyusuke Konishi bh = nilfs_btnode_create_block(btnc, ptr);
66be56dfc9SRyusuke Konishi if (IS_ERR(bh))
67be56dfc9SRyusuke Konishi return PTR_ERR(bh);
6845f4910bSRyusuke Konishi
6945f4910bSRyusuke Konishi set_buffer_nilfs_volatile(bh);
7045f4910bSRyusuke Konishi *bhp = bh;
7145f4910bSRyusuke Konishi return 0;
72f198dbb9SRyusuke Konishi }
7317c76b01SKoji Sato
nilfs_btree_node_get_flags(const struct nilfs_btree_node * node)747c397a81SRyusuke Konishi static int nilfs_btree_node_get_flags(const struct nilfs_btree_node *node)
7517c76b01SKoji Sato {
7617c76b01SKoji Sato return node->bn_flags;
7717c76b01SKoji Sato }
7817c76b01SKoji Sato
797c397a81SRyusuke Konishi static void
nilfs_btree_node_set_flags(struct nilfs_btree_node * node,int flags)806d28f7eaSRyusuke Konishi nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags)
8117c76b01SKoji Sato {
8217c76b01SKoji Sato node->bn_flags = flags;
8317c76b01SKoji Sato }
8417c76b01SKoji Sato
nilfs_btree_node_root(const struct nilfs_btree_node * node)857c397a81SRyusuke Konishi static int nilfs_btree_node_root(const struct nilfs_btree_node *node)
8617c76b01SKoji Sato {
876d28f7eaSRyusuke Konishi return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT;
8817c76b01SKoji Sato }
8917c76b01SKoji Sato
nilfs_btree_node_get_level(const struct nilfs_btree_node * node)907c397a81SRyusuke Konishi static int nilfs_btree_node_get_level(const struct nilfs_btree_node *node)
9117c76b01SKoji Sato {
9217c76b01SKoji Sato return node->bn_level;
9317c76b01SKoji Sato }
9417c76b01SKoji Sato
957c397a81SRyusuke Konishi static void
nilfs_btree_node_set_level(struct nilfs_btree_node * node,int level)966d28f7eaSRyusuke Konishi nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level)
9717c76b01SKoji Sato {
9817c76b01SKoji Sato node->bn_level = level;
9917c76b01SKoji Sato }
10017c76b01SKoji Sato
nilfs_btree_node_get_nchildren(const struct nilfs_btree_node * node)1017c397a81SRyusuke Konishi static int nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node)
10217c76b01SKoji Sato {
10317c76b01SKoji Sato return le16_to_cpu(node->bn_nchildren);
10417c76b01SKoji Sato }
10517c76b01SKoji Sato
1067c397a81SRyusuke Konishi static void
nilfs_btree_node_set_nchildren(struct nilfs_btree_node * node,int nchildren)1076d28f7eaSRyusuke Konishi nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren)
10817c76b01SKoji Sato {
10917c76b01SKoji Sato node->bn_nchildren = cpu_to_le16(nchildren);
11017c76b01SKoji Sato }
11117c76b01SKoji Sato
nilfs_btree_node_size(const struct nilfs_bmap * btree)1127c397a81SRyusuke Konishi static int nilfs_btree_node_size(const struct nilfs_bmap *btree)
11317c76b01SKoji Sato {
114f3048d17SGeliang Tang return i_blocksize(btree->b_inode);
11517c76b01SKoji Sato }
11617c76b01SKoji Sato
nilfs_btree_nchildren_per_block(const struct nilfs_bmap * btree)1179b7b265cSRyusuke Konishi static int nilfs_btree_nchildren_per_block(const struct nilfs_bmap *btree)
11817c76b01SKoji Sato {
1195ad2686eSRyusuke Konishi return btree->b_nchildren_per_block;
12017c76b01SKoji Sato }
12117c76b01SKoji Sato
1227c397a81SRyusuke Konishi static __le64 *
nilfs_btree_node_dkeys(const struct nilfs_btree_node * node)1236d28f7eaSRyusuke Konishi nilfs_btree_node_dkeys(const struct nilfs_btree_node *node)
12417c76b01SKoji Sato {
12517c76b01SKoji Sato return (__le64 *)((char *)(node + 1) +
1266d28f7eaSRyusuke Konishi (nilfs_btree_node_root(node) ?
12717c76b01SKoji Sato 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE));
12817c76b01SKoji Sato }
12917c76b01SKoji Sato
1307c397a81SRyusuke Konishi static __le64 *
nilfs_btree_node_dptrs(const struct nilfs_btree_node * node,int ncmax)1319b7b265cSRyusuke Konishi nilfs_btree_node_dptrs(const struct nilfs_btree_node *node, int ncmax)
13217c76b01SKoji Sato {
1339b7b265cSRyusuke Konishi return (__le64 *)(nilfs_btree_node_dkeys(node) + ncmax);
13417c76b01SKoji Sato }
13517c76b01SKoji Sato
1367c397a81SRyusuke Konishi static __u64
nilfs_btree_node_get_key(const struct nilfs_btree_node * node,int index)1376d28f7eaSRyusuke Konishi nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index)
13817c76b01SKoji Sato {
13925b8d7deSRyusuke Konishi return le64_to_cpu(*(nilfs_btree_node_dkeys(node) + index));
14017c76b01SKoji Sato }
14117c76b01SKoji Sato
1427c397a81SRyusuke Konishi static void
nilfs_btree_node_set_key(struct nilfs_btree_node * node,int index,__u64 key)1436d28f7eaSRyusuke Konishi nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key)
14417c76b01SKoji Sato {
14525b8d7deSRyusuke Konishi *(nilfs_btree_node_dkeys(node) + index) = cpu_to_le64(key);
14617c76b01SKoji Sato }
14717c76b01SKoji Sato
1487c397a81SRyusuke Konishi static __u64
nilfs_btree_node_get_ptr(const struct nilfs_btree_node * node,int index,int ncmax)1499b7b265cSRyusuke Konishi nilfs_btree_node_get_ptr(const struct nilfs_btree_node *node, int index,
1509b7b265cSRyusuke Konishi int ncmax)
15117c76b01SKoji Sato {
1529b7b265cSRyusuke Konishi return le64_to_cpu(*(nilfs_btree_node_dptrs(node, ncmax) + index));
15317c76b01SKoji Sato }
15417c76b01SKoji Sato
1557c397a81SRyusuke Konishi static void
nilfs_btree_node_set_ptr(struct nilfs_btree_node * node,int index,__u64 ptr,int ncmax)1569b7b265cSRyusuke Konishi nilfs_btree_node_set_ptr(struct nilfs_btree_node *node, int index, __u64 ptr,
1579b7b265cSRyusuke Konishi int ncmax)
15817c76b01SKoji Sato {
1599b7b265cSRyusuke Konishi *(nilfs_btree_node_dptrs(node, ncmax) + index) = cpu_to_le64(ptr);
16017c76b01SKoji Sato }
16117c76b01SKoji Sato
nilfs_btree_node_init(struct nilfs_btree_node * node,int flags,int level,int nchildren,int ncmax,const __u64 * keys,const __u64 * ptrs)1629b7b265cSRyusuke Konishi static void nilfs_btree_node_init(struct nilfs_btree_node *node, int flags,
1639b7b265cSRyusuke Konishi int level, int nchildren, int ncmax,
16417c76b01SKoji Sato const __u64 *keys, const __u64 *ptrs)
16517c76b01SKoji Sato {
16617c76b01SKoji Sato __le64 *dkeys;
16717c76b01SKoji Sato __le64 *dptrs;
16817c76b01SKoji Sato int i;
16917c76b01SKoji Sato
1706d28f7eaSRyusuke Konishi nilfs_btree_node_set_flags(node, flags);
1716d28f7eaSRyusuke Konishi nilfs_btree_node_set_level(node, level);
1726d28f7eaSRyusuke Konishi nilfs_btree_node_set_nchildren(node, nchildren);
17317c76b01SKoji Sato
1746d28f7eaSRyusuke Konishi dkeys = nilfs_btree_node_dkeys(node);
1759b7b265cSRyusuke Konishi dptrs = nilfs_btree_node_dptrs(node, ncmax);
17617c76b01SKoji Sato for (i = 0; i < nchildren; i++) {
17725b8d7deSRyusuke Konishi dkeys[i] = cpu_to_le64(keys[i]);
17825b8d7deSRyusuke Konishi dptrs[i] = cpu_to_le64(ptrs[i]);
17917c76b01SKoji Sato }
18017c76b01SKoji Sato }
18117c76b01SKoji Sato
18217c76b01SKoji Sato /* Assume the buffer heads corresponding to left and right are locked. */
nilfs_btree_node_move_left(struct nilfs_btree_node * left,struct nilfs_btree_node * right,int n,int lncmax,int rncmax)1839b7b265cSRyusuke Konishi static void nilfs_btree_node_move_left(struct nilfs_btree_node *left,
18417c76b01SKoji Sato struct nilfs_btree_node *right,
1859b7b265cSRyusuke Konishi int n, int lncmax, int rncmax)
18617c76b01SKoji Sato {
18717c76b01SKoji Sato __le64 *ldkeys, *rdkeys;
18817c76b01SKoji Sato __le64 *ldptrs, *rdptrs;
18917c76b01SKoji Sato int lnchildren, rnchildren;
19017c76b01SKoji Sato
1916d28f7eaSRyusuke Konishi ldkeys = nilfs_btree_node_dkeys(left);
1929b7b265cSRyusuke Konishi ldptrs = nilfs_btree_node_dptrs(left, lncmax);
1936d28f7eaSRyusuke Konishi lnchildren = nilfs_btree_node_get_nchildren(left);
19417c76b01SKoji Sato
1956d28f7eaSRyusuke Konishi rdkeys = nilfs_btree_node_dkeys(right);
1969b7b265cSRyusuke Konishi rdptrs = nilfs_btree_node_dptrs(right, rncmax);
1976d28f7eaSRyusuke Konishi rnchildren = nilfs_btree_node_get_nchildren(right);
19817c76b01SKoji Sato
19917c76b01SKoji Sato memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys));
20017c76b01SKoji Sato memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs));
20117c76b01SKoji Sato memmove(rdkeys, rdkeys + n, (rnchildren - n) * sizeof(*rdkeys));
20217c76b01SKoji Sato memmove(rdptrs, rdptrs + n, (rnchildren - n) * sizeof(*rdptrs));
20317c76b01SKoji Sato
20417c76b01SKoji Sato lnchildren += n;
20517c76b01SKoji Sato rnchildren -= n;
2066d28f7eaSRyusuke Konishi nilfs_btree_node_set_nchildren(left, lnchildren);
2076d28f7eaSRyusuke Konishi nilfs_btree_node_set_nchildren(right, rnchildren);
20817c76b01SKoji Sato }
20917c76b01SKoji Sato
21017c76b01SKoji Sato /* Assume that the buffer heads corresponding to left and right are locked. */
nilfs_btree_node_move_right(struct nilfs_btree_node * left,struct nilfs_btree_node * right,int n,int lncmax,int rncmax)2119b7b265cSRyusuke Konishi static void nilfs_btree_node_move_right(struct nilfs_btree_node *left,
21217c76b01SKoji Sato struct nilfs_btree_node *right,
2139b7b265cSRyusuke Konishi int n, int lncmax, int rncmax)
21417c76b01SKoji Sato {
21517c76b01SKoji Sato __le64 *ldkeys, *rdkeys;
21617c76b01SKoji Sato __le64 *ldptrs, *rdptrs;
21717c76b01SKoji Sato int lnchildren, rnchildren;
21817c76b01SKoji Sato
2196d28f7eaSRyusuke Konishi ldkeys = nilfs_btree_node_dkeys(left);
2209b7b265cSRyusuke Konishi ldptrs = nilfs_btree_node_dptrs(left, lncmax);
2216d28f7eaSRyusuke Konishi lnchildren = nilfs_btree_node_get_nchildren(left);
22217c76b01SKoji Sato
2236d28f7eaSRyusuke Konishi rdkeys = nilfs_btree_node_dkeys(right);
2249b7b265cSRyusuke Konishi rdptrs = nilfs_btree_node_dptrs(right, rncmax);
2256d28f7eaSRyusuke Konishi rnchildren = nilfs_btree_node_get_nchildren(right);
22617c76b01SKoji Sato
22717c76b01SKoji Sato memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys));
22817c76b01SKoji Sato memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs));
22917c76b01SKoji Sato memcpy(rdkeys, ldkeys + lnchildren - n, n * sizeof(*rdkeys));
23017c76b01SKoji Sato memcpy(rdptrs, ldptrs + lnchildren - n, n * sizeof(*rdptrs));
23117c76b01SKoji Sato
23217c76b01SKoji Sato lnchildren -= n;
23317c76b01SKoji Sato rnchildren += n;
2346d28f7eaSRyusuke Konishi nilfs_btree_node_set_nchildren(left, lnchildren);
2356d28f7eaSRyusuke Konishi nilfs_btree_node_set_nchildren(right, rnchildren);
23617c76b01SKoji Sato }
23717c76b01SKoji Sato
23817c76b01SKoji Sato /* Assume that the buffer head corresponding to node is locked. */
nilfs_btree_node_insert(struct nilfs_btree_node * node,int index,__u64 key,__u64 ptr,int ncmax)2399b7b265cSRyusuke Konishi static void nilfs_btree_node_insert(struct nilfs_btree_node *node, int index,
2409b7b265cSRyusuke Konishi __u64 key, __u64 ptr, int ncmax)
24117c76b01SKoji Sato {
24217c76b01SKoji Sato __le64 *dkeys;
24317c76b01SKoji Sato __le64 *dptrs;
24417c76b01SKoji Sato int nchildren;
24517c76b01SKoji Sato
2466d28f7eaSRyusuke Konishi dkeys = nilfs_btree_node_dkeys(node);
2479b7b265cSRyusuke Konishi dptrs = nilfs_btree_node_dptrs(node, ncmax);
2486d28f7eaSRyusuke Konishi nchildren = nilfs_btree_node_get_nchildren(node);
24917c76b01SKoji Sato if (index < nchildren) {
25017c76b01SKoji Sato memmove(dkeys + index + 1, dkeys + index,
25117c76b01SKoji Sato (nchildren - index) * sizeof(*dkeys));
25217c76b01SKoji Sato memmove(dptrs + index + 1, dptrs + index,
25317c76b01SKoji Sato (nchildren - index) * sizeof(*dptrs));
25417c76b01SKoji Sato }
25525b8d7deSRyusuke Konishi dkeys[index] = cpu_to_le64(key);
25625b8d7deSRyusuke Konishi dptrs[index] = cpu_to_le64(ptr);
25717c76b01SKoji Sato nchildren++;
2586d28f7eaSRyusuke Konishi nilfs_btree_node_set_nchildren(node, nchildren);
25917c76b01SKoji Sato }
26017c76b01SKoji Sato
26117c76b01SKoji Sato /* Assume that the buffer head corresponding to node is locked. */
nilfs_btree_node_delete(struct nilfs_btree_node * node,int index,__u64 * keyp,__u64 * ptrp,int ncmax)2629b7b265cSRyusuke Konishi static void nilfs_btree_node_delete(struct nilfs_btree_node *node, int index,
2639b7b265cSRyusuke Konishi __u64 *keyp, __u64 *ptrp, int ncmax)
26417c76b01SKoji Sato {
26517c76b01SKoji Sato __u64 key;
26617c76b01SKoji Sato __u64 ptr;
26717c76b01SKoji Sato __le64 *dkeys;
26817c76b01SKoji Sato __le64 *dptrs;
26917c76b01SKoji Sato int nchildren;
27017c76b01SKoji Sato
2716d28f7eaSRyusuke Konishi dkeys = nilfs_btree_node_dkeys(node);
2729b7b265cSRyusuke Konishi dptrs = nilfs_btree_node_dptrs(node, ncmax);
27325b8d7deSRyusuke Konishi key = le64_to_cpu(dkeys[index]);
27425b8d7deSRyusuke Konishi ptr = le64_to_cpu(dptrs[index]);
2756d28f7eaSRyusuke Konishi nchildren = nilfs_btree_node_get_nchildren(node);
27617c76b01SKoji Sato if (keyp != NULL)
27717c76b01SKoji Sato *keyp = key;
27817c76b01SKoji Sato if (ptrp != NULL)
27917c76b01SKoji Sato *ptrp = ptr;
28017c76b01SKoji Sato
28117c76b01SKoji Sato if (index < nchildren - 1) {
28217c76b01SKoji Sato memmove(dkeys + index, dkeys + index + 1,
28317c76b01SKoji Sato (nchildren - index - 1) * sizeof(*dkeys));
28417c76b01SKoji Sato memmove(dptrs + index, dptrs + index + 1,
28517c76b01SKoji Sato (nchildren - index - 1) * sizeof(*dptrs));
28617c76b01SKoji Sato }
28717c76b01SKoji Sato nchildren--;
2886d28f7eaSRyusuke Konishi nilfs_btree_node_set_nchildren(node, nchildren);
28917c76b01SKoji Sato }
29017c76b01SKoji Sato
nilfs_btree_node_lookup(const struct nilfs_btree_node * node,__u64 key,int * indexp)2916d28f7eaSRyusuke Konishi static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node,
29217c76b01SKoji Sato __u64 key, int *indexp)
29317c76b01SKoji Sato {
29417c76b01SKoji Sato __u64 nkey;
29517c76b01SKoji Sato int index, low, high, s;
29617c76b01SKoji Sato
29717c76b01SKoji Sato /* binary search */
29817c76b01SKoji Sato low = 0;
2996d28f7eaSRyusuke Konishi high = nilfs_btree_node_get_nchildren(node) - 1;
30017c76b01SKoji Sato index = 0;
30117c76b01SKoji Sato s = 0;
30217c76b01SKoji Sato while (low <= high) {
30317c76b01SKoji Sato index = (low + high) / 2;
3046d28f7eaSRyusuke Konishi nkey = nilfs_btree_node_get_key(node, index);
30517c76b01SKoji Sato if (nkey == key) {
30617c76b01SKoji Sato s = 0;
30717c76b01SKoji Sato goto out;
30817c76b01SKoji Sato } else if (nkey < key) {
30917c76b01SKoji Sato low = index + 1;
31017c76b01SKoji Sato s = -1;
31117c76b01SKoji Sato } else {
31217c76b01SKoji Sato high = index - 1;
31317c76b01SKoji Sato s = 1;
31417c76b01SKoji Sato }
31517c76b01SKoji Sato }
31617c76b01SKoji Sato
31717c76b01SKoji Sato /* adjust index */
3186d28f7eaSRyusuke Konishi if (nilfs_btree_node_get_level(node) > NILFS_BTREE_LEVEL_NODE_MIN) {
3196d28f7eaSRyusuke Konishi if (s > 0 && index > 0)
32017c76b01SKoji Sato index--;
32117c76b01SKoji Sato } else if (s < 0)
32217c76b01SKoji Sato index++;
32317c76b01SKoji Sato
32417c76b01SKoji Sato out:
32517c76b01SKoji Sato *indexp = index;
32617c76b01SKoji Sato
32717c76b01SKoji Sato return s == 0;
32817c76b01SKoji Sato }
32917c76b01SKoji Sato
3301d5385b9SRyusuke Konishi /**
3311d5385b9SRyusuke Konishi * nilfs_btree_node_broken - verify consistency of btree node
3321d5385b9SRyusuke Konishi * @node: btree node block to be examined
3331d5385b9SRyusuke Konishi * @size: node size (in bytes)
334feee880fSRyusuke Konishi * @inode: host inode of btree
3351d5385b9SRyusuke Konishi * @blocknr: block number
3361d5385b9SRyusuke Konishi *
3371d5385b9SRyusuke Konishi * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned.
3381d5385b9SRyusuke Konishi */
nilfs_btree_node_broken(const struct nilfs_btree_node * node,size_t size,struct inode * inode,sector_t blocknr)3391d5385b9SRyusuke Konishi static int nilfs_btree_node_broken(const struct nilfs_btree_node *node,
340feee880fSRyusuke Konishi size_t size, struct inode *inode,
341feee880fSRyusuke Konishi sector_t blocknr)
3421d5385b9SRyusuke Konishi {
3431d5385b9SRyusuke Konishi int level, flags, nchildren;
3441d5385b9SRyusuke Konishi int ret = 0;
3451d5385b9SRyusuke Konishi
3461d5385b9SRyusuke Konishi level = nilfs_btree_node_get_level(node);
3471d5385b9SRyusuke Konishi flags = nilfs_btree_node_get_flags(node);
3481d5385b9SRyusuke Konishi nchildren = nilfs_btree_node_get_nchildren(node);
3491d5385b9SRyusuke Konishi
3501d5385b9SRyusuke Konishi if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
3511d5385b9SRyusuke Konishi level >= NILFS_BTREE_LEVEL_MAX ||
3521d5385b9SRyusuke Konishi (flags & NILFS_BTREE_NODE_ROOT) ||
3530f28b3b5SRyusuke Konishi nchildren <= 0 ||
3541d5385b9SRyusuke Konishi nchildren > NILFS_BTREE_NODE_NCHILDREN_MAX(size))) {
355a1d0747aSJoe Perches nilfs_crit(inode->i_sb,
356feee880fSRyusuke Konishi "bad btree node (ino=%lu, blocknr=%llu): level = %d, flags = 0x%x, nchildren = %d",
357feee880fSRyusuke Konishi inode->i_ino, (unsigned long long)blocknr, level,
358feee880fSRyusuke Konishi flags, nchildren);
3591d5385b9SRyusuke Konishi ret = 1;
3601d5385b9SRyusuke Konishi }
3611d5385b9SRyusuke Konishi return ret;
3621d5385b9SRyusuke Konishi }
3631d5385b9SRyusuke Konishi
364957ed60bSRyusuke Konishi /**
365957ed60bSRyusuke Konishi * nilfs_btree_root_broken - verify consistency of btree root node
366957ed60bSRyusuke Konishi * @node: btree root node to be examined
367feee880fSRyusuke Konishi * @inode: host inode of btree
368957ed60bSRyusuke Konishi *
369957ed60bSRyusuke Konishi * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned.
370957ed60bSRyusuke Konishi */
nilfs_btree_root_broken(const struct nilfs_btree_node * node,struct inode * inode)371957ed60bSRyusuke Konishi static int nilfs_btree_root_broken(const struct nilfs_btree_node *node,
372feee880fSRyusuke Konishi struct inode *inode)
373957ed60bSRyusuke Konishi {
374957ed60bSRyusuke Konishi int level, flags, nchildren;
375957ed60bSRyusuke Konishi int ret = 0;
376957ed60bSRyusuke Konishi
377957ed60bSRyusuke Konishi level = nilfs_btree_node_get_level(node);
378957ed60bSRyusuke Konishi flags = nilfs_btree_node_get_flags(node);
379957ed60bSRyusuke Konishi nchildren = nilfs_btree_node_get_nchildren(node);
380957ed60bSRyusuke Konishi
381957ed60bSRyusuke Konishi if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
382d8fd150fSRyusuke Konishi level >= NILFS_BTREE_LEVEL_MAX ||
383957ed60bSRyusuke Konishi nchildren < 0 ||
38421839b6fSRyusuke Konishi nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX ||
38521839b6fSRyusuke Konishi (nchildren == 0 && level > NILFS_BTREE_LEVEL_NODE_MIN))) {
386a1d0747aSJoe Perches nilfs_crit(inode->i_sb,
387feee880fSRyusuke Konishi "bad btree root (ino=%lu): level = %d, flags = 0x%x, nchildren = %d",
388feee880fSRyusuke Konishi inode->i_ino, level, flags, nchildren);
389957ed60bSRyusuke Konishi ret = 1;
390957ed60bSRyusuke Konishi }
391957ed60bSRyusuke Konishi return ret;
392957ed60bSRyusuke Konishi }
393957ed60bSRyusuke Konishi
nilfs_btree_broken_node_block(struct buffer_head * bh)3941d5385b9SRyusuke Konishi int nilfs_btree_broken_node_block(struct buffer_head *bh)
3951d5385b9SRyusuke Konishi {
396feee880fSRyusuke Konishi struct inode *inode;
3974e13e66bSRyusuke Konishi int ret;
3984e13e66bSRyusuke Konishi
3994e13e66bSRyusuke Konishi if (buffer_nilfs_checked(bh))
4004e13e66bSRyusuke Konishi return 0;
4014e13e66bSRyusuke Konishi
4026ad4cd7fSMatthew Wilcox (Oracle) inode = bh->b_folio->mapping->host;
4034e13e66bSRyusuke Konishi ret = nilfs_btree_node_broken((struct nilfs_btree_node *)bh->b_data,
404feee880fSRyusuke Konishi bh->b_size, inode, bh->b_blocknr);
4054e13e66bSRyusuke Konishi if (likely(!ret))
4064e13e66bSRyusuke Konishi set_buffer_nilfs_checked(bh);
4074e13e66bSRyusuke Konishi return ret;
4081d5385b9SRyusuke Konishi }
4091d5385b9SRyusuke Konishi
4107c397a81SRyusuke Konishi static struct nilfs_btree_node *
nilfs_btree_get_root(const struct nilfs_bmap * btree)411e7c274f8SRyusuke Konishi nilfs_btree_get_root(const struct nilfs_bmap *btree)
41217c76b01SKoji Sato {
413e7c274f8SRyusuke Konishi return (struct nilfs_btree_node *)btree->b_u.u_data;
41417c76b01SKoji Sato }
41517c76b01SKoji Sato
4167c397a81SRyusuke Konishi static struct nilfs_btree_node *
nilfs_btree_get_nonroot_node(const struct nilfs_btree_path * path,int level)4176d28f7eaSRyusuke Konishi nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level)
41817c76b01SKoji Sato {
41917c76b01SKoji Sato return (struct nilfs_btree_node *)path[level].bp_bh->b_data;
42017c76b01SKoji Sato }
42117c76b01SKoji Sato
4227c397a81SRyusuke Konishi static struct nilfs_btree_node *
nilfs_btree_get_sib_node(const struct nilfs_btree_path * path,int level)4236d28f7eaSRyusuke Konishi nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level)
42417c76b01SKoji Sato {
42517c76b01SKoji Sato return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data;
42617c76b01SKoji Sato }
42717c76b01SKoji Sato
nilfs_btree_height(const struct nilfs_bmap * btree)4287c397a81SRyusuke Konishi static int nilfs_btree_height(const struct nilfs_bmap *btree)
42917c76b01SKoji Sato {
4306d28f7eaSRyusuke Konishi return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1;
43117c76b01SKoji Sato }
43217c76b01SKoji Sato
4339b7b265cSRyusuke Konishi static struct nilfs_btree_node *
nilfs_btree_get_node(const struct nilfs_bmap * btree,const struct nilfs_btree_path * path,int level,int * ncmaxp)434e7c274f8SRyusuke Konishi nilfs_btree_get_node(const struct nilfs_bmap *btree,
43517c76b01SKoji Sato const struct nilfs_btree_path *path,
4369b7b265cSRyusuke Konishi int level, int *ncmaxp)
43717c76b01SKoji Sato {
4389b7b265cSRyusuke Konishi struct nilfs_btree_node *node;
4399b7b265cSRyusuke Konishi
4409b7b265cSRyusuke Konishi if (level == nilfs_btree_height(btree) - 1) {
4419b7b265cSRyusuke Konishi node = nilfs_btree_get_root(btree);
4429b7b265cSRyusuke Konishi *ncmaxp = NILFS_BTREE_ROOT_NCHILDREN_MAX;
4439b7b265cSRyusuke Konishi } else {
4449b7b265cSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
4459b7b265cSRyusuke Konishi *ncmaxp = nilfs_btree_nchildren_per_block(btree);
4469b7b265cSRyusuke Konishi }
4479b7b265cSRyusuke Konishi return node;
44817c76b01SKoji Sato }
44917c76b01SKoji Sato
nilfs_btree_bad_node(const struct nilfs_bmap * btree,struct nilfs_btree_node * node,int level)450feee880fSRyusuke Konishi static int nilfs_btree_bad_node(const struct nilfs_bmap *btree,
451feee880fSRyusuke Konishi struct nilfs_btree_node *node, int level)
4529b945d53SRyusuke Konishi {
4539b945d53SRyusuke Konishi if (unlikely(nilfs_btree_node_get_level(node) != level)) {
4549b945d53SRyusuke Konishi dump_stack();
455a1d0747aSJoe Perches nilfs_crit(btree->b_inode->i_sb,
456feee880fSRyusuke Konishi "btree level mismatch (ino=%lu): %d != %d",
457feee880fSRyusuke Konishi btree->b_inode->i_ino,
4589b945d53SRyusuke Konishi nilfs_btree_node_get_level(node), level);
4599b945d53SRyusuke Konishi return 1;
4609b945d53SRyusuke Konishi }
4619b945d53SRyusuke Konishi return 0;
4629b945d53SRyusuke Konishi }
4639b945d53SRyusuke Konishi
464464ece88SRyusuke Konishi struct nilfs_btree_readahead_info {
465464ece88SRyusuke Konishi struct nilfs_btree_node *node; /* parent node */
466464ece88SRyusuke Konishi int max_ra_blocks; /* max nof blocks to read ahead */
467464ece88SRyusuke Konishi int index; /* current index on the parent node */
468464ece88SRyusuke Konishi int ncmax; /* nof children in the parent node */
469464ece88SRyusuke Konishi };
470464ece88SRyusuke Konishi
__nilfs_btree_get_block(const struct nilfs_bmap * btree,__u64 ptr,struct buffer_head ** bhp,const struct nilfs_btree_readahead_info * ra)471464ece88SRyusuke Konishi static int __nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr,
472464ece88SRyusuke Konishi struct buffer_head **bhp,
473464ece88SRyusuke Konishi const struct nilfs_btree_readahead_info *ra)
474464ece88SRyusuke Konishi {
475e897be17SRyusuke Konishi struct inode *btnc_inode = NILFS_BMAP_I(btree)->i_assoc_inode;
476e897be17SRyusuke Konishi struct address_space *btnc = btnc_inode->i_mapping;
477464ece88SRyusuke Konishi struct buffer_head *bh, *ra_bh;
478464ece88SRyusuke Konishi sector_t submit_ptr = 0;
479464ece88SRyusuke Konishi int ret;
480464ece88SRyusuke Konishi
481ed451259SBart Van Assche ret = nilfs_btnode_submit_block(btnc, ptr, 0, REQ_OP_READ, &bh,
4822a222ca9SMike Christie &submit_ptr);
483464ece88SRyusuke Konishi if (ret) {
4847633355eSRyusuke Konishi if (likely(ret == -EEXIST))
485464ece88SRyusuke Konishi goto out_check;
4867633355eSRyusuke Konishi if (ret == -ENOENT) {
4877633355eSRyusuke Konishi /*
4887633355eSRyusuke Konishi * Block address translation failed due to invalid
4897633355eSRyusuke Konishi * value of 'ptr'. In this case, return internal code
4907633355eSRyusuke Konishi * -EINVAL (broken bmap) to notify bmap layer of fatal
4917633355eSRyusuke Konishi * metadata corruption.
4927633355eSRyusuke Konishi */
4937633355eSRyusuke Konishi ret = -EINVAL;
4947633355eSRyusuke Konishi }
4957633355eSRyusuke Konishi return ret;
496464ece88SRyusuke Konishi }
497464ece88SRyusuke Konishi
498464ece88SRyusuke Konishi if (ra) {
499464ece88SRyusuke Konishi int i, n;
500464ece88SRyusuke Konishi __u64 ptr2;
501464ece88SRyusuke Konishi
502464ece88SRyusuke Konishi /* read ahead sibling nodes */
503464ece88SRyusuke Konishi for (n = ra->max_ra_blocks, i = ra->index + 1;
504464ece88SRyusuke Konishi n > 0 && i < ra->ncmax; n--, i++) {
505464ece88SRyusuke Konishi ptr2 = nilfs_btree_node_get_ptr(ra->node, i, ra->ncmax);
506464ece88SRyusuke Konishi
5072a222ca9SMike Christie ret = nilfs_btnode_submit_block(btnc, ptr2, 0,
508ed451259SBart Van Assche REQ_OP_READ | REQ_RAHEAD,
509464ece88SRyusuke Konishi &ra_bh, &submit_ptr);
510464ece88SRyusuke Konishi if (likely(!ret || ret == -EEXIST))
511464ece88SRyusuke Konishi brelse(ra_bh);
512464ece88SRyusuke Konishi else if (ret != -EBUSY)
513464ece88SRyusuke Konishi break;
514464ece88SRyusuke Konishi if (!buffer_locked(bh))
515464ece88SRyusuke Konishi goto out_no_wait;
516464ece88SRyusuke Konishi }
517464ece88SRyusuke Konishi }
518464ece88SRyusuke Konishi
519464ece88SRyusuke Konishi wait_on_buffer(bh);
520464ece88SRyusuke Konishi
521464ece88SRyusuke Konishi out_no_wait:
522464ece88SRyusuke Konishi if (!buffer_uptodate(bh)) {
523a1d0747aSJoe Perches nilfs_err(btree->b_inode->i_sb,
52439a9dccaSRyusuke Konishi "I/O error reading b-tree node block (ino=%lu, blocknr=%llu)",
52539a9dccaSRyusuke Konishi btree->b_inode->i_ino, (unsigned long long)ptr);
526464ece88SRyusuke Konishi brelse(bh);
527464ece88SRyusuke Konishi return -EIO;
528464ece88SRyusuke Konishi }
529464ece88SRyusuke Konishi
530464ece88SRyusuke Konishi out_check:
531464ece88SRyusuke Konishi if (nilfs_btree_broken_node_block(bh)) {
532464ece88SRyusuke Konishi clear_buffer_uptodate(bh);
533464ece88SRyusuke Konishi brelse(bh);
534464ece88SRyusuke Konishi return -EINVAL;
535464ece88SRyusuke Konishi }
536464ece88SRyusuke Konishi
537464ece88SRyusuke Konishi *bhp = bh;
538464ece88SRyusuke Konishi return 0;
539464ece88SRyusuke Konishi }
540464ece88SRyusuke Konishi
nilfs_btree_get_block(const struct nilfs_bmap * btree,__u64 ptr,struct buffer_head ** bhp)541464ece88SRyusuke Konishi static int nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr,
542464ece88SRyusuke Konishi struct buffer_head **bhp)
543464ece88SRyusuke Konishi {
544464ece88SRyusuke Konishi return __nilfs_btree_get_block(btree, ptr, bhp, NULL);
545464ece88SRyusuke Konishi }
546464ece88SRyusuke Konishi
nilfs_btree_do_lookup(const struct nilfs_bmap * btree,struct nilfs_btree_path * path,__u64 key,__u64 * ptrp,int minlevel,int readahead)547e7c274f8SRyusuke Konishi static int nilfs_btree_do_lookup(const struct nilfs_bmap *btree,
54817c76b01SKoji Sato struct nilfs_btree_path *path,
54903bdb5acSRyusuke Konishi __u64 key, __u64 *ptrp, int minlevel,
55003bdb5acSRyusuke Konishi int readahead)
55117c76b01SKoji Sato {
55217c76b01SKoji Sato struct nilfs_btree_node *node;
55303bdb5acSRyusuke Konishi struct nilfs_btree_readahead_info p, *ra;
55417c76b01SKoji Sato __u64 ptr;
555ea64ab87SRyusuke Konishi int level, index, found, ncmax, ret;
55617c76b01SKoji Sato
55717c76b01SKoji Sato node = nilfs_btree_get_root(btree);
5586d28f7eaSRyusuke Konishi level = nilfs_btree_node_get_level(node);
5596d28f7eaSRyusuke Konishi if (level < minlevel || nilfs_btree_node_get_nchildren(node) <= 0)
56017c76b01SKoji Sato return -ENOENT;
56117c76b01SKoji Sato
5626d28f7eaSRyusuke Konishi found = nilfs_btree_node_lookup(node, key, &index);
5639b7b265cSRyusuke Konishi ptr = nilfs_btree_node_get_ptr(node, index,
5649b7b265cSRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX);
56517c76b01SKoji Sato path[level].bp_bh = NULL;
56617c76b01SKoji Sato path[level].bp_index = index;
56717c76b01SKoji Sato
5689b7b265cSRyusuke Konishi ncmax = nilfs_btree_nchildren_per_block(btree);
569ea64ab87SRyusuke Konishi
57003bdb5acSRyusuke Konishi while (--level >= minlevel) {
57103bdb5acSRyusuke Konishi ra = NULL;
57203bdb5acSRyusuke Konishi if (level == NILFS_BTREE_LEVEL_NODE_MIN && readahead) {
57303bdb5acSRyusuke Konishi p.node = nilfs_btree_get_node(btree, path, level + 1,
57403bdb5acSRyusuke Konishi &p.ncmax);
57503bdb5acSRyusuke Konishi p.index = index;
57603bdb5acSRyusuke Konishi p.max_ra_blocks = 7;
57703bdb5acSRyusuke Konishi ra = &p;
57803bdb5acSRyusuke Konishi }
57903bdb5acSRyusuke Konishi ret = __nilfs_btree_get_block(btree, ptr, &path[level].bp_bh,
58003bdb5acSRyusuke Konishi ra);
58117c76b01SKoji Sato if (ret < 0)
58217c76b01SKoji Sato return ret;
58303bdb5acSRyusuke Konishi
5846d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
585feee880fSRyusuke Konishi if (nilfs_btree_bad_node(btree, node, level))
5869b945d53SRyusuke Konishi return -EINVAL;
58717c76b01SKoji Sato if (!found)
5886d28f7eaSRyusuke Konishi found = nilfs_btree_node_lookup(node, key, &index);
58917c76b01SKoji Sato else
59017c76b01SKoji Sato index = 0;
591ea64ab87SRyusuke Konishi if (index < ncmax) {
5929b7b265cSRyusuke Konishi ptr = nilfs_btree_node_get_ptr(node, index, ncmax);
593ea64ab87SRyusuke Konishi } else {
5941f5abe7eSRyusuke Konishi WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN);
59517c76b01SKoji Sato /* insert */
59617c76b01SKoji Sato ptr = NILFS_BMAP_INVALID_PTR;
59717c76b01SKoji Sato }
59817c76b01SKoji Sato path[level].bp_index = index;
59917c76b01SKoji Sato }
60017c76b01SKoji Sato if (!found)
60117c76b01SKoji Sato return -ENOENT;
60217c76b01SKoji Sato
60317c76b01SKoji Sato if (ptrp != NULL)
60417c76b01SKoji Sato *ptrp = ptr;
60517c76b01SKoji Sato
60617c76b01SKoji Sato return 0;
60717c76b01SKoji Sato }
60817c76b01SKoji Sato
nilfs_btree_do_lookup_last(const struct nilfs_bmap * btree,struct nilfs_btree_path * path,__u64 * keyp,__u64 * ptrp)609e7c274f8SRyusuke Konishi static int nilfs_btree_do_lookup_last(const struct nilfs_bmap *btree,
61017c76b01SKoji Sato struct nilfs_btree_path *path,
61117c76b01SKoji Sato __u64 *keyp, __u64 *ptrp)
61217c76b01SKoji Sato {
61317c76b01SKoji Sato struct nilfs_btree_node *node;
61417c76b01SKoji Sato __u64 ptr;
6159b7b265cSRyusuke Konishi int index, level, ncmax, ret;
61617c76b01SKoji Sato
61717c76b01SKoji Sato node = nilfs_btree_get_root(btree);
6186d28f7eaSRyusuke Konishi index = nilfs_btree_node_get_nchildren(node) - 1;
61917c76b01SKoji Sato if (index < 0)
62017c76b01SKoji Sato return -ENOENT;
6216d28f7eaSRyusuke Konishi level = nilfs_btree_node_get_level(node);
6229b7b265cSRyusuke Konishi ptr = nilfs_btree_node_get_ptr(node, index,
6239b7b265cSRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX);
62417c76b01SKoji Sato path[level].bp_bh = NULL;
62517c76b01SKoji Sato path[level].bp_index = index;
6269b7b265cSRyusuke Konishi ncmax = nilfs_btree_nchildren_per_block(btree);
62717c76b01SKoji Sato
62817c76b01SKoji Sato for (level--; level > 0; level--) {
629f198dbb9SRyusuke Konishi ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
63017c76b01SKoji Sato if (ret < 0)
63117c76b01SKoji Sato return ret;
6326d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
633feee880fSRyusuke Konishi if (nilfs_btree_bad_node(btree, node, level))
6349b945d53SRyusuke Konishi return -EINVAL;
6356d28f7eaSRyusuke Konishi index = nilfs_btree_node_get_nchildren(node) - 1;
6369b7b265cSRyusuke Konishi ptr = nilfs_btree_node_get_ptr(node, index, ncmax);
63717c76b01SKoji Sato path[level].bp_index = index;
63817c76b01SKoji Sato }
63917c76b01SKoji Sato
64017c76b01SKoji Sato if (keyp != NULL)
6416d28f7eaSRyusuke Konishi *keyp = nilfs_btree_node_get_key(node, index);
64217c76b01SKoji Sato if (ptrp != NULL)
64317c76b01SKoji Sato *ptrp = ptr;
64417c76b01SKoji Sato
64517c76b01SKoji Sato return 0;
64617c76b01SKoji Sato }
64717c76b01SKoji Sato
6485b20384fSRyusuke Konishi /**
6495b20384fSRyusuke Konishi * nilfs_btree_get_next_key - get next valid key from btree path array
6505b20384fSRyusuke Konishi * @btree: bmap struct of btree
6515b20384fSRyusuke Konishi * @path: array of nilfs_btree_path struct
6525b20384fSRyusuke Konishi * @minlevel: start level
6535b20384fSRyusuke Konishi * @nextkey: place to store the next valid key
6545b20384fSRyusuke Konishi *
6555b20384fSRyusuke Konishi * Return Value: If a next key was found, 0 is returned. Otherwise,
6565b20384fSRyusuke Konishi * -ENOENT is returned.
6575b20384fSRyusuke Konishi */
nilfs_btree_get_next_key(const struct nilfs_bmap * btree,const struct nilfs_btree_path * path,int minlevel,__u64 * nextkey)6585b20384fSRyusuke Konishi static int nilfs_btree_get_next_key(const struct nilfs_bmap *btree,
6595b20384fSRyusuke Konishi const struct nilfs_btree_path *path,
6605b20384fSRyusuke Konishi int minlevel, __u64 *nextkey)
6615b20384fSRyusuke Konishi {
6625b20384fSRyusuke Konishi struct nilfs_btree_node *node;
6635b20384fSRyusuke Konishi int maxlevel = nilfs_btree_height(btree) - 1;
6645b20384fSRyusuke Konishi int index, next_adj, level;
6655b20384fSRyusuke Konishi
6665b20384fSRyusuke Konishi /* Next index is already set to bp_index for leaf nodes. */
6675b20384fSRyusuke Konishi next_adj = 0;
6685b20384fSRyusuke Konishi for (level = minlevel; level <= maxlevel; level++) {
6695b20384fSRyusuke Konishi if (level == maxlevel)
6705b20384fSRyusuke Konishi node = nilfs_btree_get_root(btree);
6715b20384fSRyusuke Konishi else
6725b20384fSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
6735b20384fSRyusuke Konishi
6745b20384fSRyusuke Konishi index = path[level].bp_index + next_adj;
6755b20384fSRyusuke Konishi if (index < nilfs_btree_node_get_nchildren(node)) {
6765b20384fSRyusuke Konishi /* Next key is in this node */
6775b20384fSRyusuke Konishi *nextkey = nilfs_btree_node_get_key(node, index);
6785b20384fSRyusuke Konishi return 0;
6795b20384fSRyusuke Konishi }
6805b20384fSRyusuke Konishi /* For non-leaf nodes, next index is stored at bp_index + 1. */
6815b20384fSRyusuke Konishi next_adj = 1;
6825b20384fSRyusuke Konishi }
6835b20384fSRyusuke Konishi return -ENOENT;
6845b20384fSRyusuke Konishi }
6855b20384fSRyusuke Konishi
nilfs_btree_lookup(const struct nilfs_bmap * btree,__u64 key,int level,__u64 * ptrp)686e7c274f8SRyusuke Konishi static int nilfs_btree_lookup(const struct nilfs_bmap *btree,
68717c76b01SKoji Sato __u64 key, int level, __u64 *ptrp)
68817c76b01SKoji Sato {
68917c76b01SKoji Sato struct nilfs_btree_path *path;
69017c76b01SKoji Sato int ret;
69117c76b01SKoji Sato
6926d28f7eaSRyusuke Konishi path = nilfs_btree_alloc_path();
69317c76b01SKoji Sato if (path == NULL)
69417c76b01SKoji Sato return -ENOMEM;
69517c76b01SKoji Sato
69603bdb5acSRyusuke Konishi ret = nilfs_btree_do_lookup(btree, path, key, ptrp, level, 0);
69717c76b01SKoji Sato
6986d28f7eaSRyusuke Konishi nilfs_btree_free_path(path);
69917c76b01SKoji Sato
70017c76b01SKoji Sato return ret;
70117c76b01SKoji Sato }
70217c76b01SKoji Sato
nilfs_btree_lookup_contig(const struct nilfs_bmap * btree,__u64 key,__u64 * ptrp,unsigned int maxblocks)703e7c274f8SRyusuke Konishi static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree,
7040c6c44cbSRyusuke Konishi __u64 key, __u64 *ptrp,
7050c6c44cbSRyusuke Konishi unsigned int maxblocks)
706c3a7abf0SRyusuke Konishi {
707c3a7abf0SRyusuke Konishi struct nilfs_btree_path *path;
708c3a7abf0SRyusuke Konishi struct nilfs_btree_node *node;
709c3a7abf0SRyusuke Konishi struct inode *dat = NULL;
710c3a7abf0SRyusuke Konishi __u64 ptr, ptr2;
711c3a7abf0SRyusuke Konishi sector_t blocknr;
712c3a7abf0SRyusuke Konishi int level = NILFS_BTREE_LEVEL_NODE_MIN;
7139b7b265cSRyusuke Konishi int ret, cnt, index, maxlevel, ncmax;
71403bdb5acSRyusuke Konishi struct nilfs_btree_readahead_info p;
715c3a7abf0SRyusuke Konishi
7166d28f7eaSRyusuke Konishi path = nilfs_btree_alloc_path();
717c3a7abf0SRyusuke Konishi if (path == NULL)
718c3a7abf0SRyusuke Konishi return -ENOMEM;
719f905440fSLi Hong
72003bdb5acSRyusuke Konishi ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level, 1);
721c3a7abf0SRyusuke Konishi if (ret < 0)
722c3a7abf0SRyusuke Konishi goto out;
723c3a7abf0SRyusuke Konishi
724e7c274f8SRyusuke Konishi if (NILFS_BMAP_USE_VBN(btree)) {
725e7c274f8SRyusuke Konishi dat = nilfs_bmap_get_dat(btree);
726c3a7abf0SRyusuke Konishi ret = nilfs_dat_translate(dat, ptr, &blocknr);
727c3a7abf0SRyusuke Konishi if (ret < 0)
728f69e8139SRyusuke Konishi goto dat_error;
729c3a7abf0SRyusuke Konishi ptr = blocknr;
730c3a7abf0SRyusuke Konishi }
731c3a7abf0SRyusuke Konishi cnt = 1;
732c3a7abf0SRyusuke Konishi if (cnt == maxblocks)
733c3a7abf0SRyusuke Konishi goto end;
734c3a7abf0SRyusuke Konishi
735c3a7abf0SRyusuke Konishi maxlevel = nilfs_btree_height(btree) - 1;
7369b7b265cSRyusuke Konishi node = nilfs_btree_get_node(btree, path, level, &ncmax);
737c3a7abf0SRyusuke Konishi index = path[level].bp_index + 1;
738c3a7abf0SRyusuke Konishi for (;;) {
7396d28f7eaSRyusuke Konishi while (index < nilfs_btree_node_get_nchildren(node)) {
7406d28f7eaSRyusuke Konishi if (nilfs_btree_node_get_key(node, index) !=
741c3a7abf0SRyusuke Konishi key + cnt)
742c3a7abf0SRyusuke Konishi goto end;
7439b7b265cSRyusuke Konishi ptr2 = nilfs_btree_node_get_ptr(node, index, ncmax);
744c3a7abf0SRyusuke Konishi if (dat) {
745c3a7abf0SRyusuke Konishi ret = nilfs_dat_translate(dat, ptr2, &blocknr);
746c3a7abf0SRyusuke Konishi if (ret < 0)
747f69e8139SRyusuke Konishi goto dat_error;
748c3a7abf0SRyusuke Konishi ptr2 = blocknr;
749c3a7abf0SRyusuke Konishi }
750c3a7abf0SRyusuke Konishi if (ptr2 != ptr + cnt || ++cnt == maxblocks)
751c3a7abf0SRyusuke Konishi goto end;
752c3a7abf0SRyusuke Konishi index++;
753c3a7abf0SRyusuke Konishi }
754c3a7abf0SRyusuke Konishi if (level == maxlevel)
755c3a7abf0SRyusuke Konishi break;
756c3a7abf0SRyusuke Konishi
757c3a7abf0SRyusuke Konishi /* look-up right sibling node */
75803bdb5acSRyusuke Konishi p.node = nilfs_btree_get_node(btree, path, level + 1, &p.ncmax);
75903bdb5acSRyusuke Konishi p.index = path[level + 1].bp_index + 1;
76003bdb5acSRyusuke Konishi p.max_ra_blocks = 7;
76103bdb5acSRyusuke Konishi if (p.index >= nilfs_btree_node_get_nchildren(p.node) ||
76203bdb5acSRyusuke Konishi nilfs_btree_node_get_key(p.node, p.index) != key + cnt)
763c3a7abf0SRyusuke Konishi break;
76403bdb5acSRyusuke Konishi ptr2 = nilfs_btree_node_get_ptr(p.node, p.index, p.ncmax);
76503bdb5acSRyusuke Konishi path[level + 1].bp_index = p.index;
766c3a7abf0SRyusuke Konishi
767c3a7abf0SRyusuke Konishi brelse(path[level].bp_bh);
768c3a7abf0SRyusuke Konishi path[level].bp_bh = NULL;
76903bdb5acSRyusuke Konishi
77003bdb5acSRyusuke Konishi ret = __nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh,
77103bdb5acSRyusuke Konishi &p);
772c3a7abf0SRyusuke Konishi if (ret < 0)
773c3a7abf0SRyusuke Konishi goto out;
7746d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
7759b7b265cSRyusuke Konishi ncmax = nilfs_btree_nchildren_per_block(btree);
776c3a7abf0SRyusuke Konishi index = 0;
777c3a7abf0SRyusuke Konishi path[level].bp_index = index;
778c3a7abf0SRyusuke Konishi }
779c3a7abf0SRyusuke Konishi end:
780c3a7abf0SRyusuke Konishi *ptrp = ptr;
781c3a7abf0SRyusuke Konishi ret = cnt;
782c3a7abf0SRyusuke Konishi out:
7836d28f7eaSRyusuke Konishi nilfs_btree_free_path(path);
784c3a7abf0SRyusuke Konishi return ret;
785f69e8139SRyusuke Konishi
786f69e8139SRyusuke Konishi dat_error:
787f69e8139SRyusuke Konishi if (ret == -ENOENT)
788f69e8139SRyusuke Konishi ret = -EINVAL; /* Notify bmap layer of metadata corruption */
789f69e8139SRyusuke Konishi goto out;
790c3a7abf0SRyusuke Konishi }
791c3a7abf0SRyusuke Konishi
nilfs_btree_promote_key(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,__u64 key)792e7c274f8SRyusuke Konishi static void nilfs_btree_promote_key(struct nilfs_bmap *btree,
79317c76b01SKoji Sato struct nilfs_btree_path *path,
79417c76b01SKoji Sato int level, __u64 key)
79517c76b01SKoji Sato {
79617c76b01SKoji Sato if (level < nilfs_btree_height(btree) - 1) {
79717c76b01SKoji Sato do {
79817c76b01SKoji Sato nilfs_btree_node_set_key(
7996d28f7eaSRyusuke Konishi nilfs_btree_get_nonroot_node(path, level),
80017c76b01SKoji Sato path[level].bp_index, key);
80117c76b01SKoji Sato if (!buffer_dirty(path[level].bp_bh))
8025fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_bh);
80317c76b01SKoji Sato } while ((path[level].bp_index == 0) &&
80417c76b01SKoji Sato (++level < nilfs_btree_height(btree) - 1));
80517c76b01SKoji Sato }
80617c76b01SKoji Sato
80717c76b01SKoji Sato /* root */
80817c76b01SKoji Sato if (level == nilfs_btree_height(btree) - 1) {
8096d28f7eaSRyusuke Konishi nilfs_btree_node_set_key(nilfs_btree_get_root(btree),
81017c76b01SKoji Sato path[level].bp_index, key);
81117c76b01SKoji Sato }
81217c76b01SKoji Sato }
81317c76b01SKoji Sato
nilfs_btree_do_insert(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,__u64 * keyp,__u64 * ptrp)814e7c274f8SRyusuke Konishi static void nilfs_btree_do_insert(struct nilfs_bmap *btree,
81517c76b01SKoji Sato struct nilfs_btree_path *path,
81617c76b01SKoji Sato int level, __u64 *keyp, __u64 *ptrp)
81717c76b01SKoji Sato {
81817c76b01SKoji Sato struct nilfs_btree_node *node;
8199b7b265cSRyusuke Konishi int ncblk;
82017c76b01SKoji Sato
82117c76b01SKoji Sato if (level < nilfs_btree_height(btree) - 1) {
8226d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
8239b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
8249b7b265cSRyusuke Konishi nilfs_btree_node_insert(node, path[level].bp_index,
8259b7b265cSRyusuke Konishi *keyp, *ptrp, ncblk);
82617c76b01SKoji Sato if (!buffer_dirty(path[level].bp_bh))
8275fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_bh);
82817c76b01SKoji Sato
82917c76b01SKoji Sato if (path[level].bp_index == 0)
83017c76b01SKoji Sato nilfs_btree_promote_key(btree, path, level + 1,
8316d28f7eaSRyusuke Konishi nilfs_btree_node_get_key(node,
8326d28f7eaSRyusuke Konishi 0));
83317c76b01SKoji Sato } else {
83417c76b01SKoji Sato node = nilfs_btree_get_root(btree);
8359b7b265cSRyusuke Konishi nilfs_btree_node_insert(node, path[level].bp_index,
8369b7b265cSRyusuke Konishi *keyp, *ptrp,
8379b7b265cSRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX);
83817c76b01SKoji Sato }
83917c76b01SKoji Sato }
84017c76b01SKoji Sato
nilfs_btree_carry_left(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,__u64 * keyp,__u64 * ptrp)841e7c274f8SRyusuke Konishi static void nilfs_btree_carry_left(struct nilfs_bmap *btree,
84217c76b01SKoji Sato struct nilfs_btree_path *path,
84317c76b01SKoji Sato int level, __u64 *keyp, __u64 *ptrp)
84417c76b01SKoji Sato {
84517c76b01SKoji Sato struct nilfs_btree_node *node, *left;
8469b7b265cSRyusuke Konishi int nchildren, lnchildren, n, move, ncblk;
84717c76b01SKoji Sato
8486d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
8496d28f7eaSRyusuke Konishi left = nilfs_btree_get_sib_node(path, level);
8506d28f7eaSRyusuke Konishi nchildren = nilfs_btree_node_get_nchildren(node);
8516d28f7eaSRyusuke Konishi lnchildren = nilfs_btree_node_get_nchildren(left);
8529b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
85317c76b01SKoji Sato move = 0;
85417c76b01SKoji Sato
85517c76b01SKoji Sato n = (nchildren + lnchildren + 1) / 2 - lnchildren;
85617c76b01SKoji Sato if (n > path[level].bp_index) {
85717c76b01SKoji Sato /* move insert point */
85817c76b01SKoji Sato n--;
85917c76b01SKoji Sato move = 1;
86017c76b01SKoji Sato }
86117c76b01SKoji Sato
8629b7b265cSRyusuke Konishi nilfs_btree_node_move_left(left, node, n, ncblk, ncblk);
86317c76b01SKoji Sato
86417c76b01SKoji Sato if (!buffer_dirty(path[level].bp_bh))
8655fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_bh);
86617c76b01SKoji Sato if (!buffer_dirty(path[level].bp_sib_bh))
8675fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_sib_bh);
86817c76b01SKoji Sato
86917c76b01SKoji Sato nilfs_btree_promote_key(btree, path, level + 1,
8706d28f7eaSRyusuke Konishi nilfs_btree_node_get_key(node, 0));
87117c76b01SKoji Sato
87217c76b01SKoji Sato if (move) {
873087d01b4SRyusuke Konishi brelse(path[level].bp_bh);
87417c76b01SKoji Sato path[level].bp_bh = path[level].bp_sib_bh;
87517c76b01SKoji Sato path[level].bp_sib_bh = NULL;
87617c76b01SKoji Sato path[level].bp_index += lnchildren;
87717c76b01SKoji Sato path[level + 1].bp_index--;
87817c76b01SKoji Sato } else {
879087d01b4SRyusuke Konishi brelse(path[level].bp_sib_bh);
88017c76b01SKoji Sato path[level].bp_sib_bh = NULL;
88117c76b01SKoji Sato path[level].bp_index -= n;
88217c76b01SKoji Sato }
88317c76b01SKoji Sato
88417c76b01SKoji Sato nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
88517c76b01SKoji Sato }
88617c76b01SKoji Sato
nilfs_btree_carry_right(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,__u64 * keyp,__u64 * ptrp)887e7c274f8SRyusuke Konishi static void nilfs_btree_carry_right(struct nilfs_bmap *btree,
88817c76b01SKoji Sato struct nilfs_btree_path *path,
88917c76b01SKoji Sato int level, __u64 *keyp, __u64 *ptrp)
89017c76b01SKoji Sato {
89117c76b01SKoji Sato struct nilfs_btree_node *node, *right;
8929b7b265cSRyusuke Konishi int nchildren, rnchildren, n, move, ncblk;
89317c76b01SKoji Sato
8946d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
8956d28f7eaSRyusuke Konishi right = nilfs_btree_get_sib_node(path, level);
8966d28f7eaSRyusuke Konishi nchildren = nilfs_btree_node_get_nchildren(node);
8976d28f7eaSRyusuke Konishi rnchildren = nilfs_btree_node_get_nchildren(right);
8989b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
89917c76b01SKoji Sato move = 0;
90017c76b01SKoji Sato
90117c76b01SKoji Sato n = (nchildren + rnchildren + 1) / 2 - rnchildren;
90217c76b01SKoji Sato if (n > nchildren - path[level].bp_index) {
90317c76b01SKoji Sato /* move insert point */
90417c76b01SKoji Sato n--;
90517c76b01SKoji Sato move = 1;
90617c76b01SKoji Sato }
90717c76b01SKoji Sato
9089b7b265cSRyusuke Konishi nilfs_btree_node_move_right(node, right, n, ncblk, ncblk);
90917c76b01SKoji Sato
91017c76b01SKoji Sato if (!buffer_dirty(path[level].bp_bh))
9115fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_bh);
91217c76b01SKoji Sato if (!buffer_dirty(path[level].bp_sib_bh))
9135fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_sib_bh);
91417c76b01SKoji Sato
91517c76b01SKoji Sato path[level + 1].bp_index++;
91617c76b01SKoji Sato nilfs_btree_promote_key(btree, path, level + 1,
9176d28f7eaSRyusuke Konishi nilfs_btree_node_get_key(right, 0));
91817c76b01SKoji Sato path[level + 1].bp_index--;
91917c76b01SKoji Sato
92017c76b01SKoji Sato if (move) {
921087d01b4SRyusuke Konishi brelse(path[level].bp_bh);
92217c76b01SKoji Sato path[level].bp_bh = path[level].bp_sib_bh;
92317c76b01SKoji Sato path[level].bp_sib_bh = NULL;
9246d28f7eaSRyusuke Konishi path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
92517c76b01SKoji Sato path[level + 1].bp_index++;
92617c76b01SKoji Sato } else {
927087d01b4SRyusuke Konishi brelse(path[level].bp_sib_bh);
92817c76b01SKoji Sato path[level].bp_sib_bh = NULL;
92917c76b01SKoji Sato }
93017c76b01SKoji Sato
93117c76b01SKoji Sato nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
93217c76b01SKoji Sato }
93317c76b01SKoji Sato
nilfs_btree_split(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,__u64 * keyp,__u64 * ptrp)934e7c274f8SRyusuke Konishi static void nilfs_btree_split(struct nilfs_bmap *btree,
93517c76b01SKoji Sato struct nilfs_btree_path *path,
93617c76b01SKoji Sato int level, __u64 *keyp, __u64 *ptrp)
93717c76b01SKoji Sato {
93817c76b01SKoji Sato struct nilfs_btree_node *node, *right;
9399b7b265cSRyusuke Konishi int nchildren, n, move, ncblk;
94017c76b01SKoji Sato
9416d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
9426d28f7eaSRyusuke Konishi right = nilfs_btree_get_sib_node(path, level);
9436d28f7eaSRyusuke Konishi nchildren = nilfs_btree_node_get_nchildren(node);
9449b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
94517c76b01SKoji Sato move = 0;
94617c76b01SKoji Sato
94717c76b01SKoji Sato n = (nchildren + 1) / 2;
94817c76b01SKoji Sato if (n > nchildren - path[level].bp_index) {
94917c76b01SKoji Sato n--;
95017c76b01SKoji Sato move = 1;
95117c76b01SKoji Sato }
95217c76b01SKoji Sato
9539b7b265cSRyusuke Konishi nilfs_btree_node_move_right(node, right, n, ncblk, ncblk);
95417c76b01SKoji Sato
95517c76b01SKoji Sato if (!buffer_dirty(path[level].bp_bh))
9565fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_bh);
95717c76b01SKoji Sato if (!buffer_dirty(path[level].bp_sib_bh))
9585fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_sib_bh);
95917c76b01SKoji Sato
96017c76b01SKoji Sato if (move) {
9616d28f7eaSRyusuke Konishi path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
9629b7b265cSRyusuke Konishi nilfs_btree_node_insert(right, path[level].bp_index,
9639b7b265cSRyusuke Konishi *keyp, *ptrp, ncblk);
96417c76b01SKoji Sato
9656d28f7eaSRyusuke Konishi *keyp = nilfs_btree_node_get_key(right, 0);
96617c76b01SKoji Sato *ptrp = path[level].bp_newreq.bpr_ptr;
96717c76b01SKoji Sato
968087d01b4SRyusuke Konishi brelse(path[level].bp_bh);
96917c76b01SKoji Sato path[level].bp_bh = path[level].bp_sib_bh;
97017c76b01SKoji Sato path[level].bp_sib_bh = NULL;
97117c76b01SKoji Sato } else {
97217c76b01SKoji Sato nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
97317c76b01SKoji Sato
9746d28f7eaSRyusuke Konishi *keyp = nilfs_btree_node_get_key(right, 0);
97517c76b01SKoji Sato *ptrp = path[level].bp_newreq.bpr_ptr;
97617c76b01SKoji Sato
977087d01b4SRyusuke Konishi brelse(path[level].bp_sib_bh);
97817c76b01SKoji Sato path[level].bp_sib_bh = NULL;
97917c76b01SKoji Sato }
98017c76b01SKoji Sato
98117c76b01SKoji Sato path[level + 1].bp_index++;
98217c76b01SKoji Sato }
98317c76b01SKoji Sato
nilfs_btree_grow(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,__u64 * keyp,__u64 * ptrp)984e7c274f8SRyusuke Konishi static void nilfs_btree_grow(struct nilfs_bmap *btree,
98517c76b01SKoji Sato struct nilfs_btree_path *path,
98617c76b01SKoji Sato int level, __u64 *keyp, __u64 *ptrp)
98717c76b01SKoji Sato {
98817c76b01SKoji Sato struct nilfs_btree_node *root, *child;
9899b7b265cSRyusuke Konishi int n, ncblk;
99017c76b01SKoji Sato
99117c76b01SKoji Sato root = nilfs_btree_get_root(btree);
9926d28f7eaSRyusuke Konishi child = nilfs_btree_get_sib_node(path, level);
9939b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
99417c76b01SKoji Sato
9956d28f7eaSRyusuke Konishi n = nilfs_btree_node_get_nchildren(root);
99617c76b01SKoji Sato
9979b7b265cSRyusuke Konishi nilfs_btree_node_move_right(root, child, n,
9989b7b265cSRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX, ncblk);
9996d28f7eaSRyusuke Konishi nilfs_btree_node_set_level(root, level + 1);
100017c76b01SKoji Sato
100117c76b01SKoji Sato if (!buffer_dirty(path[level].bp_sib_bh))
10025fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_sib_bh);
100317c76b01SKoji Sato
100417c76b01SKoji Sato path[level].bp_bh = path[level].bp_sib_bh;
100517c76b01SKoji Sato path[level].bp_sib_bh = NULL;
100617c76b01SKoji Sato
100717c76b01SKoji Sato nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
100817c76b01SKoji Sato
10096d28f7eaSRyusuke Konishi *keyp = nilfs_btree_node_get_key(child, 0);
101017c76b01SKoji Sato *ptrp = path[level].bp_newreq.bpr_ptr;
101117c76b01SKoji Sato }
101217c76b01SKoji Sato
nilfs_btree_find_near(const struct nilfs_bmap * btree,const struct nilfs_btree_path * path)1013e7c274f8SRyusuke Konishi static __u64 nilfs_btree_find_near(const struct nilfs_bmap *btree,
101417c76b01SKoji Sato const struct nilfs_btree_path *path)
101517c76b01SKoji Sato {
101617c76b01SKoji Sato struct nilfs_btree_node *node;
10179b7b265cSRyusuke Konishi int level, ncmax;
101817c76b01SKoji Sato
101917c76b01SKoji Sato if (path == NULL)
102017c76b01SKoji Sato return NILFS_BMAP_INVALID_PTR;
102117c76b01SKoji Sato
102217c76b01SKoji Sato /* left sibling */
102317c76b01SKoji Sato level = NILFS_BTREE_LEVEL_NODE_MIN;
102417c76b01SKoji Sato if (path[level].bp_index > 0) {
10259b7b265cSRyusuke Konishi node = nilfs_btree_get_node(btree, path, level, &ncmax);
10269b7b265cSRyusuke Konishi return nilfs_btree_node_get_ptr(node,
10279b7b265cSRyusuke Konishi path[level].bp_index - 1,
10289b7b265cSRyusuke Konishi ncmax);
102917c76b01SKoji Sato }
103017c76b01SKoji Sato
103117c76b01SKoji Sato /* parent */
103217c76b01SKoji Sato level = NILFS_BTREE_LEVEL_NODE_MIN + 1;
103317c76b01SKoji Sato if (level <= nilfs_btree_height(btree) - 1) {
10349b7b265cSRyusuke Konishi node = nilfs_btree_get_node(btree, path, level, &ncmax);
10359b7b265cSRyusuke Konishi return nilfs_btree_node_get_ptr(node, path[level].bp_index,
10369b7b265cSRyusuke Konishi ncmax);
103717c76b01SKoji Sato }
103817c76b01SKoji Sato
103917c76b01SKoji Sato return NILFS_BMAP_INVALID_PTR;
104017c76b01SKoji Sato }
104117c76b01SKoji Sato
nilfs_btree_find_target_v(const struct nilfs_bmap * btree,const struct nilfs_btree_path * path,__u64 key)1042e7c274f8SRyusuke Konishi static __u64 nilfs_btree_find_target_v(const struct nilfs_bmap *btree,
104317c76b01SKoji Sato const struct nilfs_btree_path *path,
104417c76b01SKoji Sato __u64 key)
104517c76b01SKoji Sato {
104617c76b01SKoji Sato __u64 ptr;
104717c76b01SKoji Sato
1048e7c274f8SRyusuke Konishi ptr = nilfs_bmap_find_target_seq(btree, key);
104917c76b01SKoji Sato if (ptr != NILFS_BMAP_INVALID_PTR)
105017c76b01SKoji Sato /* sequential access */
105117c76b01SKoji Sato return ptr;
10527f00184eSRyusuke Konishi
105317c76b01SKoji Sato ptr = nilfs_btree_find_near(btree, path);
105417c76b01SKoji Sato if (ptr != NILFS_BMAP_INVALID_PTR)
105517c76b01SKoji Sato /* near */
105617c76b01SKoji Sato return ptr;
10577f00184eSRyusuke Konishi
105817c76b01SKoji Sato /* block group */
1059e7c274f8SRyusuke Konishi return nilfs_bmap_find_target_in_group(btree);
106017c76b01SKoji Sato }
106117c76b01SKoji Sato
nilfs_btree_prepare_insert(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int * levelp,__u64 key,__u64 ptr,struct nilfs_bmap_stats * stats)1062e7c274f8SRyusuke Konishi static int nilfs_btree_prepare_insert(struct nilfs_bmap *btree,
106317c76b01SKoji Sato struct nilfs_btree_path *path,
106417c76b01SKoji Sato int *levelp, __u64 key, __u64 ptr,
106517c76b01SKoji Sato struct nilfs_bmap_stats *stats)
106617c76b01SKoji Sato {
106717c76b01SKoji Sato struct buffer_head *bh;
106817c76b01SKoji Sato struct nilfs_btree_node *node, *parent, *sib;
106917c76b01SKoji Sato __u64 sibptr;
10709b7b265cSRyusuke Konishi int pindex, level, ncmax, ncblk, ret;
10712e0c2c73SRyusuke Konishi struct inode *dat = NULL;
107217c76b01SKoji Sato
107317c76b01SKoji Sato stats->bs_nblocks = 0;
107417c76b01SKoji Sato level = NILFS_BTREE_LEVEL_DATA;
107517c76b01SKoji Sato
107617c76b01SKoji Sato /* allocate a new ptr for data block */
1077e7c274f8SRyusuke Konishi if (NILFS_BMAP_USE_VBN(btree)) {
107817c76b01SKoji Sato path[level].bp_newreq.bpr_ptr =
10797cde31d7SRyusuke Konishi nilfs_btree_find_target_v(btree, path, key);
1080e7c274f8SRyusuke Konishi dat = nilfs_bmap_get_dat(btree);
10812e0c2c73SRyusuke Konishi }
108217c76b01SKoji Sato
1083e7c274f8SRyusuke Konishi ret = nilfs_bmap_prepare_alloc_ptr(btree, &path[level].bp_newreq, dat);
108417c76b01SKoji Sato if (ret < 0)
108517c76b01SKoji Sato goto err_out_data;
108617c76b01SKoji Sato
10879b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
1088ea64ab87SRyusuke Konishi
108917c76b01SKoji Sato for (level = NILFS_BTREE_LEVEL_NODE_MIN;
109017c76b01SKoji Sato level < nilfs_btree_height(btree) - 1;
109117c76b01SKoji Sato level++) {
10926d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
10939b7b265cSRyusuke Konishi if (nilfs_btree_node_get_nchildren(node) < ncblk) {
109417c76b01SKoji Sato path[level].bp_op = nilfs_btree_do_insert;
109517c76b01SKoji Sato stats->bs_nblocks++;
109617c76b01SKoji Sato goto out;
109717c76b01SKoji Sato }
109817c76b01SKoji Sato
10999b7b265cSRyusuke Konishi parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
110017c76b01SKoji Sato pindex = path[level + 1].bp_index;
110117c76b01SKoji Sato
110217c76b01SKoji Sato /* left sibling */
110317c76b01SKoji Sato if (pindex > 0) {
11049b7b265cSRyusuke Konishi sibptr = nilfs_btree_node_get_ptr(parent, pindex - 1,
11059b7b265cSRyusuke Konishi ncmax);
1106f198dbb9SRyusuke Konishi ret = nilfs_btree_get_block(btree, sibptr, &bh);
110717c76b01SKoji Sato if (ret < 0)
110817c76b01SKoji Sato goto err_out_child_node;
110917c76b01SKoji Sato sib = (struct nilfs_btree_node *)bh->b_data;
11109b7b265cSRyusuke Konishi if (nilfs_btree_node_get_nchildren(sib) < ncblk) {
111117c76b01SKoji Sato path[level].bp_sib_bh = bh;
111217c76b01SKoji Sato path[level].bp_op = nilfs_btree_carry_left;
111317c76b01SKoji Sato stats->bs_nblocks++;
111417c76b01SKoji Sato goto out;
11159b7b265cSRyusuke Konishi } else {
1116087d01b4SRyusuke Konishi brelse(bh);
111717c76b01SKoji Sato }
11189b7b265cSRyusuke Konishi }
111917c76b01SKoji Sato
112017c76b01SKoji Sato /* right sibling */
11219b7b265cSRyusuke Konishi if (pindex < nilfs_btree_node_get_nchildren(parent) - 1) {
11229b7b265cSRyusuke Konishi sibptr = nilfs_btree_node_get_ptr(parent, pindex + 1,
11239b7b265cSRyusuke Konishi ncmax);
1124f198dbb9SRyusuke Konishi ret = nilfs_btree_get_block(btree, sibptr, &bh);
112517c76b01SKoji Sato if (ret < 0)
112617c76b01SKoji Sato goto err_out_child_node;
112717c76b01SKoji Sato sib = (struct nilfs_btree_node *)bh->b_data;
11289b7b265cSRyusuke Konishi if (nilfs_btree_node_get_nchildren(sib) < ncblk) {
112917c76b01SKoji Sato path[level].bp_sib_bh = bh;
113017c76b01SKoji Sato path[level].bp_op = nilfs_btree_carry_right;
113117c76b01SKoji Sato stats->bs_nblocks++;
113217c76b01SKoji Sato goto out;
11339b7b265cSRyusuke Konishi } else {
1134087d01b4SRyusuke Konishi brelse(bh);
113517c76b01SKoji Sato }
11369b7b265cSRyusuke Konishi }
113717c76b01SKoji Sato
113817c76b01SKoji Sato /* split */
113917c76b01SKoji Sato path[level].bp_newreq.bpr_ptr =
114017c76b01SKoji Sato path[level - 1].bp_newreq.bpr_ptr + 1;
1141e7c274f8SRyusuke Konishi ret = nilfs_bmap_prepare_alloc_ptr(btree,
11422e0c2c73SRyusuke Konishi &path[level].bp_newreq, dat);
114317c76b01SKoji Sato if (ret < 0)
114417c76b01SKoji Sato goto err_out_child_node;
1145f198dbb9SRyusuke Konishi ret = nilfs_btree_get_new_block(btree,
114617c76b01SKoji Sato path[level].bp_newreq.bpr_ptr,
114717c76b01SKoji Sato &bh);
114817c76b01SKoji Sato if (ret < 0)
114917c76b01SKoji Sato goto err_out_curr_node;
115017c76b01SKoji Sato
115117c76b01SKoji Sato stats->bs_nblocks++;
115217c76b01SKoji Sato
11539b7b265cSRyusuke Konishi sib = (struct nilfs_btree_node *)bh->b_data;
11549b7b265cSRyusuke Konishi nilfs_btree_node_init(sib, 0, level, 0, ncblk, NULL, NULL);
115517c76b01SKoji Sato path[level].bp_sib_bh = bh;
115617c76b01SKoji Sato path[level].bp_op = nilfs_btree_split;
115717c76b01SKoji Sato }
115817c76b01SKoji Sato
115917c76b01SKoji Sato /* root */
116017c76b01SKoji Sato node = nilfs_btree_get_root(btree);
11616d28f7eaSRyusuke Konishi if (nilfs_btree_node_get_nchildren(node) <
1162ea64ab87SRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX) {
116317c76b01SKoji Sato path[level].bp_op = nilfs_btree_do_insert;
116417c76b01SKoji Sato stats->bs_nblocks++;
116517c76b01SKoji Sato goto out;
116617c76b01SKoji Sato }
116717c76b01SKoji Sato
116817c76b01SKoji Sato /* grow */
116917c76b01SKoji Sato path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
1170e7c274f8SRyusuke Konishi ret = nilfs_bmap_prepare_alloc_ptr(btree, &path[level].bp_newreq, dat);
117117c76b01SKoji Sato if (ret < 0)
117217c76b01SKoji Sato goto err_out_child_node;
1173f198dbb9SRyusuke Konishi ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
1174f198dbb9SRyusuke Konishi &bh);
117517c76b01SKoji Sato if (ret < 0)
117617c76b01SKoji Sato goto err_out_curr_node;
117717c76b01SKoji Sato
11789b7b265cSRyusuke Konishi nilfs_btree_node_init((struct nilfs_btree_node *)bh->b_data,
11799b7b265cSRyusuke Konishi 0, level, 0, ncblk, NULL, NULL);
118017c76b01SKoji Sato path[level].bp_sib_bh = bh;
118117c76b01SKoji Sato path[level].bp_op = nilfs_btree_grow;
118217c76b01SKoji Sato
118317c76b01SKoji Sato level++;
118417c76b01SKoji Sato path[level].bp_op = nilfs_btree_do_insert;
118517c76b01SKoji Sato
118617c76b01SKoji Sato /* a newly-created node block and a data block are added */
118717c76b01SKoji Sato stats->bs_nblocks += 2;
118817c76b01SKoji Sato
118917c76b01SKoji Sato /* success */
119017c76b01SKoji Sato out:
119117c76b01SKoji Sato *levelp = level;
119217c76b01SKoji Sato return ret;
119317c76b01SKoji Sato
119417c76b01SKoji Sato /* error */
119517c76b01SKoji Sato err_out_curr_node:
1196e7c274f8SRyusuke Konishi nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat);
119717c76b01SKoji Sato err_out_child_node:
119817c76b01SKoji Sato for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
11999f098900SRyusuke Konishi nilfs_btnode_delete(path[level].bp_sib_bh);
1200e7c274f8SRyusuke Konishi nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat);
120117c76b01SKoji Sato
120217c76b01SKoji Sato }
120317c76b01SKoji Sato
1204e7c274f8SRyusuke Konishi nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat);
120517c76b01SKoji Sato err_out_data:
120617c76b01SKoji Sato *levelp = level;
120717c76b01SKoji Sato stats->bs_nblocks = 0;
120817c76b01SKoji Sato return ret;
120917c76b01SKoji Sato }
121017c76b01SKoji Sato
nilfs_btree_commit_insert(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int maxlevel,__u64 key,__u64 ptr)1211e7c274f8SRyusuke Konishi static void nilfs_btree_commit_insert(struct nilfs_bmap *btree,
121217c76b01SKoji Sato struct nilfs_btree_path *path,
121317c76b01SKoji Sato int maxlevel, __u64 key, __u64 ptr)
121417c76b01SKoji Sato {
12152e0c2c73SRyusuke Konishi struct inode *dat = NULL;
121617c76b01SKoji Sato int level;
121717c76b01SKoji Sato
121817c76b01SKoji Sato set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
121917c76b01SKoji Sato ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
1220e7c274f8SRyusuke Konishi if (NILFS_BMAP_USE_VBN(btree)) {
1221dc935be2SRyusuke Konishi nilfs_bmap_set_target_v(btree, key, ptr);
1222e7c274f8SRyusuke Konishi dat = nilfs_bmap_get_dat(btree);
12232e0c2c73SRyusuke Konishi }
122417c76b01SKoji Sato
122517c76b01SKoji Sato for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
1226e7c274f8SRyusuke Konishi nilfs_bmap_commit_alloc_ptr(btree,
12272e0c2c73SRyusuke Konishi &path[level - 1].bp_newreq, dat);
12288acfbf09SPekka Enberg path[level].bp_op(btree, path, level, &key, &ptr);
122917c76b01SKoji Sato }
123017c76b01SKoji Sato
1231e7c274f8SRyusuke Konishi if (!nilfs_bmap_dirty(btree))
1232e7c274f8SRyusuke Konishi nilfs_bmap_set_dirty(btree);
123317c76b01SKoji Sato }
123417c76b01SKoji Sato
nilfs_btree_insert(struct nilfs_bmap * btree,__u64 key,__u64 ptr)1235e7c274f8SRyusuke Konishi static int nilfs_btree_insert(struct nilfs_bmap *btree, __u64 key, __u64 ptr)
123617c76b01SKoji Sato {
123717c76b01SKoji Sato struct nilfs_btree_path *path;
123817c76b01SKoji Sato struct nilfs_bmap_stats stats;
123917c76b01SKoji Sato int level, ret;
124017c76b01SKoji Sato
12416d28f7eaSRyusuke Konishi path = nilfs_btree_alloc_path();
124217c76b01SKoji Sato if (path == NULL)
124317c76b01SKoji Sato return -ENOMEM;
124417c76b01SKoji Sato
124517c76b01SKoji Sato ret = nilfs_btree_do_lookup(btree, path, key, NULL,
124603bdb5acSRyusuke Konishi NILFS_BTREE_LEVEL_NODE_MIN, 0);
124717c76b01SKoji Sato if (ret != -ENOENT) {
124817c76b01SKoji Sato if (ret == 0)
124917c76b01SKoji Sato ret = -EEXIST;
125017c76b01SKoji Sato goto out;
125117c76b01SKoji Sato }
125217c76b01SKoji Sato
125317c76b01SKoji Sato ret = nilfs_btree_prepare_insert(btree, path, &level, key, ptr, &stats);
125417c76b01SKoji Sato if (ret < 0)
125517c76b01SKoji Sato goto out;
125617c76b01SKoji Sato nilfs_btree_commit_insert(btree, path, level, key, ptr);
1257be667377SRyusuke Konishi nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks);
125817c76b01SKoji Sato
125917c76b01SKoji Sato out:
12606d28f7eaSRyusuke Konishi nilfs_btree_free_path(path);
126117c76b01SKoji Sato return ret;
126217c76b01SKoji Sato }
126317c76b01SKoji Sato
nilfs_btree_do_delete(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,__u64 * keyp,__u64 * ptrp)1264e7c274f8SRyusuke Konishi static void nilfs_btree_do_delete(struct nilfs_bmap *btree,
126517c76b01SKoji Sato struct nilfs_btree_path *path,
126617c76b01SKoji Sato int level, __u64 *keyp, __u64 *ptrp)
126717c76b01SKoji Sato {
126817c76b01SKoji Sato struct nilfs_btree_node *node;
12699b7b265cSRyusuke Konishi int ncblk;
127017c76b01SKoji Sato
127117c76b01SKoji Sato if (level < nilfs_btree_height(btree) - 1) {
12726d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
12739b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
12749b7b265cSRyusuke Konishi nilfs_btree_node_delete(node, path[level].bp_index,
12759b7b265cSRyusuke Konishi keyp, ptrp, ncblk);
127617c76b01SKoji Sato if (!buffer_dirty(path[level].bp_bh))
12775fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_bh);
127817c76b01SKoji Sato if (path[level].bp_index == 0)
127917c76b01SKoji Sato nilfs_btree_promote_key(btree, path, level + 1,
12806d28f7eaSRyusuke Konishi nilfs_btree_node_get_key(node, 0));
128117c76b01SKoji Sato } else {
128217c76b01SKoji Sato node = nilfs_btree_get_root(btree);
12839b7b265cSRyusuke Konishi nilfs_btree_node_delete(node, path[level].bp_index,
12849b7b265cSRyusuke Konishi keyp, ptrp,
12859b7b265cSRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX);
128617c76b01SKoji Sato }
128717c76b01SKoji Sato }
128817c76b01SKoji Sato
nilfs_btree_borrow_left(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,__u64 * keyp,__u64 * ptrp)1289e7c274f8SRyusuke Konishi static void nilfs_btree_borrow_left(struct nilfs_bmap *btree,
129017c76b01SKoji Sato struct nilfs_btree_path *path,
129117c76b01SKoji Sato int level, __u64 *keyp, __u64 *ptrp)
129217c76b01SKoji Sato {
129317c76b01SKoji Sato struct nilfs_btree_node *node, *left;
12949b7b265cSRyusuke Konishi int nchildren, lnchildren, n, ncblk;
129517c76b01SKoji Sato
129617c76b01SKoji Sato nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
129717c76b01SKoji Sato
12986d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
12996d28f7eaSRyusuke Konishi left = nilfs_btree_get_sib_node(path, level);
13006d28f7eaSRyusuke Konishi nchildren = nilfs_btree_node_get_nchildren(node);
13016d28f7eaSRyusuke Konishi lnchildren = nilfs_btree_node_get_nchildren(left);
13029b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
130317c76b01SKoji Sato
130417c76b01SKoji Sato n = (nchildren + lnchildren) / 2 - nchildren;
130517c76b01SKoji Sato
13069b7b265cSRyusuke Konishi nilfs_btree_node_move_right(left, node, n, ncblk, ncblk);
130717c76b01SKoji Sato
130817c76b01SKoji Sato if (!buffer_dirty(path[level].bp_bh))
13095fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_bh);
131017c76b01SKoji Sato if (!buffer_dirty(path[level].bp_sib_bh))
13115fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_sib_bh);
131217c76b01SKoji Sato
131317c76b01SKoji Sato nilfs_btree_promote_key(btree, path, level + 1,
13146d28f7eaSRyusuke Konishi nilfs_btree_node_get_key(node, 0));
131517c76b01SKoji Sato
1316087d01b4SRyusuke Konishi brelse(path[level].bp_sib_bh);
131717c76b01SKoji Sato path[level].bp_sib_bh = NULL;
131817c76b01SKoji Sato path[level].bp_index += n;
131917c76b01SKoji Sato }
132017c76b01SKoji Sato
nilfs_btree_borrow_right(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,__u64 * keyp,__u64 * ptrp)1321e7c274f8SRyusuke Konishi static void nilfs_btree_borrow_right(struct nilfs_bmap *btree,
132217c76b01SKoji Sato struct nilfs_btree_path *path,
132317c76b01SKoji Sato int level, __u64 *keyp, __u64 *ptrp)
132417c76b01SKoji Sato {
132517c76b01SKoji Sato struct nilfs_btree_node *node, *right;
13269b7b265cSRyusuke Konishi int nchildren, rnchildren, n, ncblk;
132717c76b01SKoji Sato
132817c76b01SKoji Sato nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
132917c76b01SKoji Sato
13306d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
13316d28f7eaSRyusuke Konishi right = nilfs_btree_get_sib_node(path, level);
13326d28f7eaSRyusuke Konishi nchildren = nilfs_btree_node_get_nchildren(node);
13336d28f7eaSRyusuke Konishi rnchildren = nilfs_btree_node_get_nchildren(right);
13349b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
133517c76b01SKoji Sato
133617c76b01SKoji Sato n = (nchildren + rnchildren) / 2 - nchildren;
133717c76b01SKoji Sato
13389b7b265cSRyusuke Konishi nilfs_btree_node_move_left(node, right, n, ncblk, ncblk);
133917c76b01SKoji Sato
134017c76b01SKoji Sato if (!buffer_dirty(path[level].bp_bh))
13415fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_bh);
134217c76b01SKoji Sato if (!buffer_dirty(path[level].bp_sib_bh))
13435fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_sib_bh);
134417c76b01SKoji Sato
134517c76b01SKoji Sato path[level + 1].bp_index++;
134617c76b01SKoji Sato nilfs_btree_promote_key(btree, path, level + 1,
13476d28f7eaSRyusuke Konishi nilfs_btree_node_get_key(right, 0));
134817c76b01SKoji Sato path[level + 1].bp_index--;
134917c76b01SKoji Sato
1350087d01b4SRyusuke Konishi brelse(path[level].bp_sib_bh);
135117c76b01SKoji Sato path[level].bp_sib_bh = NULL;
135217c76b01SKoji Sato }
135317c76b01SKoji Sato
nilfs_btree_concat_left(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,__u64 * keyp,__u64 * ptrp)1354e7c274f8SRyusuke Konishi static void nilfs_btree_concat_left(struct nilfs_bmap *btree,
135517c76b01SKoji Sato struct nilfs_btree_path *path,
135617c76b01SKoji Sato int level, __u64 *keyp, __u64 *ptrp)
135717c76b01SKoji Sato {
135817c76b01SKoji Sato struct nilfs_btree_node *node, *left;
13599b7b265cSRyusuke Konishi int n, ncblk;
136017c76b01SKoji Sato
136117c76b01SKoji Sato nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
136217c76b01SKoji Sato
13636d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
13646d28f7eaSRyusuke Konishi left = nilfs_btree_get_sib_node(path, level);
13659b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
136617c76b01SKoji Sato
13676d28f7eaSRyusuke Konishi n = nilfs_btree_node_get_nchildren(node);
136817c76b01SKoji Sato
13699b7b265cSRyusuke Konishi nilfs_btree_node_move_left(left, node, n, ncblk, ncblk);
137017c76b01SKoji Sato
137117c76b01SKoji Sato if (!buffer_dirty(path[level].bp_sib_bh))
13725fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_sib_bh);
137317c76b01SKoji Sato
13749f098900SRyusuke Konishi nilfs_btnode_delete(path[level].bp_bh);
137517c76b01SKoji Sato path[level].bp_bh = path[level].bp_sib_bh;
137617c76b01SKoji Sato path[level].bp_sib_bh = NULL;
13776d28f7eaSRyusuke Konishi path[level].bp_index += nilfs_btree_node_get_nchildren(left);
137817c76b01SKoji Sato }
137917c76b01SKoji Sato
nilfs_btree_concat_right(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,__u64 * keyp,__u64 * ptrp)1380e7c274f8SRyusuke Konishi static void nilfs_btree_concat_right(struct nilfs_bmap *btree,
138117c76b01SKoji Sato struct nilfs_btree_path *path,
138217c76b01SKoji Sato int level, __u64 *keyp, __u64 *ptrp)
138317c76b01SKoji Sato {
138417c76b01SKoji Sato struct nilfs_btree_node *node, *right;
13859b7b265cSRyusuke Konishi int n, ncblk;
138617c76b01SKoji Sato
138717c76b01SKoji Sato nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
138817c76b01SKoji Sato
13896d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
13906d28f7eaSRyusuke Konishi right = nilfs_btree_get_sib_node(path, level);
13919b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
139217c76b01SKoji Sato
13936d28f7eaSRyusuke Konishi n = nilfs_btree_node_get_nchildren(right);
139417c76b01SKoji Sato
13959b7b265cSRyusuke Konishi nilfs_btree_node_move_left(node, right, n, ncblk, ncblk);
139617c76b01SKoji Sato
139717c76b01SKoji Sato if (!buffer_dirty(path[level].bp_bh))
13985fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_bh);
139917c76b01SKoji Sato
14009f098900SRyusuke Konishi nilfs_btnode_delete(path[level].bp_sib_bh);
140117c76b01SKoji Sato path[level].bp_sib_bh = NULL;
140217c76b01SKoji Sato path[level + 1].bp_index++;
140317c76b01SKoji Sato }
140417c76b01SKoji Sato
nilfs_btree_shrink(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,__u64 * keyp,__u64 * ptrp)1405e7c274f8SRyusuke Konishi static void nilfs_btree_shrink(struct nilfs_bmap *btree,
140617c76b01SKoji Sato struct nilfs_btree_path *path,
140717c76b01SKoji Sato int level, __u64 *keyp, __u64 *ptrp)
140817c76b01SKoji Sato {
140917c76b01SKoji Sato struct nilfs_btree_node *root, *child;
14109b7b265cSRyusuke Konishi int n, ncblk;
141117c76b01SKoji Sato
141217c76b01SKoji Sato nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
141317c76b01SKoji Sato
141417c76b01SKoji Sato root = nilfs_btree_get_root(btree);
14156d28f7eaSRyusuke Konishi child = nilfs_btree_get_nonroot_node(path, level);
14169b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
141717c76b01SKoji Sato
14189b7b265cSRyusuke Konishi nilfs_btree_node_delete(root, 0, NULL, NULL,
14199b7b265cSRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX);
14206d28f7eaSRyusuke Konishi nilfs_btree_node_set_level(root, level);
14216d28f7eaSRyusuke Konishi n = nilfs_btree_node_get_nchildren(child);
14229b7b265cSRyusuke Konishi nilfs_btree_node_move_left(root, child, n,
14239b7b265cSRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX, ncblk);
142417c76b01SKoji Sato
14259f098900SRyusuke Konishi nilfs_btnode_delete(path[level].bp_bh);
142617c76b01SKoji Sato path[level].bp_bh = NULL;
142717c76b01SKoji Sato }
142817c76b01SKoji Sato
nilfs_btree_nop(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,__u64 * keyp,__u64 * ptrp)1429d4099053SRyusuke Konishi static void nilfs_btree_nop(struct nilfs_bmap *btree,
1430d4099053SRyusuke Konishi struct nilfs_btree_path *path,
1431d4099053SRyusuke Konishi int level, __u64 *keyp, __u64 *ptrp)
1432d4099053SRyusuke Konishi {
1433d4099053SRyusuke Konishi }
143417c76b01SKoji Sato
nilfs_btree_prepare_delete(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int * levelp,struct nilfs_bmap_stats * stats,struct inode * dat)1435e7c274f8SRyusuke Konishi static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree,
143617c76b01SKoji Sato struct nilfs_btree_path *path,
143717c76b01SKoji Sato int *levelp,
14382e0c2c73SRyusuke Konishi struct nilfs_bmap_stats *stats,
14392e0c2c73SRyusuke Konishi struct inode *dat)
144017c76b01SKoji Sato {
144117c76b01SKoji Sato struct buffer_head *bh;
144217c76b01SKoji Sato struct nilfs_btree_node *node, *parent, *sib;
144317c76b01SKoji Sato __u64 sibptr;
1444fe744fdbSRyusuke Konishi int pindex, dindex, level, ncmin, ncmax, ncblk, ret;
144517c76b01SKoji Sato
144617c76b01SKoji Sato ret = 0;
144717c76b01SKoji Sato stats->bs_nblocks = 0;
1448ea64ab87SRyusuke Konishi ncmin = NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree));
14499b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
1450ea64ab87SRyusuke Konishi
1451fe744fdbSRyusuke Konishi for (level = NILFS_BTREE_LEVEL_NODE_MIN, dindex = path[level].bp_index;
145217c76b01SKoji Sato level < nilfs_btree_height(btree) - 1;
145317c76b01SKoji Sato level++) {
14546d28f7eaSRyusuke Konishi node = nilfs_btree_get_nonroot_node(path, level);
145517c76b01SKoji Sato path[level].bp_oldreq.bpr_ptr =
1456fe744fdbSRyusuke Konishi nilfs_btree_node_get_ptr(node, dindex, ncblk);
1457e7c274f8SRyusuke Konishi ret = nilfs_bmap_prepare_end_ptr(btree,
14582e0c2c73SRyusuke Konishi &path[level].bp_oldreq, dat);
145917c76b01SKoji Sato if (ret < 0)
146017c76b01SKoji Sato goto err_out_child_node;
146117c76b01SKoji Sato
1462ea64ab87SRyusuke Konishi if (nilfs_btree_node_get_nchildren(node) > ncmin) {
146317c76b01SKoji Sato path[level].bp_op = nilfs_btree_do_delete;
146417c76b01SKoji Sato stats->bs_nblocks++;
146517c76b01SKoji Sato goto out;
146617c76b01SKoji Sato }
146717c76b01SKoji Sato
14689b7b265cSRyusuke Konishi parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
146917c76b01SKoji Sato pindex = path[level + 1].bp_index;
1470fe744fdbSRyusuke Konishi dindex = pindex;
147117c76b01SKoji Sato
147217c76b01SKoji Sato if (pindex > 0) {
147317c76b01SKoji Sato /* left sibling */
14749b7b265cSRyusuke Konishi sibptr = nilfs_btree_node_get_ptr(parent, pindex - 1,
14759b7b265cSRyusuke Konishi ncmax);
1476f198dbb9SRyusuke Konishi ret = nilfs_btree_get_block(btree, sibptr, &bh);
147717c76b01SKoji Sato if (ret < 0)
147817c76b01SKoji Sato goto err_out_curr_node;
147917c76b01SKoji Sato sib = (struct nilfs_btree_node *)bh->b_data;
1480ea64ab87SRyusuke Konishi if (nilfs_btree_node_get_nchildren(sib) > ncmin) {
148117c76b01SKoji Sato path[level].bp_sib_bh = bh;
148217c76b01SKoji Sato path[level].bp_op = nilfs_btree_borrow_left;
148317c76b01SKoji Sato stats->bs_nblocks++;
148417c76b01SKoji Sato goto out;
148517c76b01SKoji Sato } else {
148617c76b01SKoji Sato path[level].bp_sib_bh = bh;
148717c76b01SKoji Sato path[level].bp_op = nilfs_btree_concat_left;
148817c76b01SKoji Sato stats->bs_nblocks++;
148917c76b01SKoji Sato /* continue; */
149017c76b01SKoji Sato }
149117c76b01SKoji Sato } else if (pindex <
14926d28f7eaSRyusuke Konishi nilfs_btree_node_get_nchildren(parent) - 1) {
149317c76b01SKoji Sato /* right sibling */
14949b7b265cSRyusuke Konishi sibptr = nilfs_btree_node_get_ptr(parent, pindex + 1,
14959b7b265cSRyusuke Konishi ncmax);
1496f198dbb9SRyusuke Konishi ret = nilfs_btree_get_block(btree, sibptr, &bh);
149717c76b01SKoji Sato if (ret < 0)
149817c76b01SKoji Sato goto err_out_curr_node;
149917c76b01SKoji Sato sib = (struct nilfs_btree_node *)bh->b_data;
1500ea64ab87SRyusuke Konishi if (nilfs_btree_node_get_nchildren(sib) > ncmin) {
150117c76b01SKoji Sato path[level].bp_sib_bh = bh;
150217c76b01SKoji Sato path[level].bp_op = nilfs_btree_borrow_right;
150317c76b01SKoji Sato stats->bs_nblocks++;
150417c76b01SKoji Sato goto out;
150517c76b01SKoji Sato } else {
150617c76b01SKoji Sato path[level].bp_sib_bh = bh;
150717c76b01SKoji Sato path[level].bp_op = nilfs_btree_concat_right;
150817c76b01SKoji Sato stats->bs_nblocks++;
1509fe744fdbSRyusuke Konishi /*
1510fe744fdbSRyusuke Konishi * When merging right sibling node
1511fe744fdbSRyusuke Konishi * into the current node, pointer to
1512fe744fdbSRyusuke Konishi * the right sibling node must be
1513fe744fdbSRyusuke Konishi * terminated instead. The adjustment
1514fe744fdbSRyusuke Konishi * below is required for that.
1515fe744fdbSRyusuke Konishi */
1516fe744fdbSRyusuke Konishi dindex = pindex + 1;
151717c76b01SKoji Sato /* continue; */
151817c76b01SKoji Sato }
151917c76b01SKoji Sato } else {
152017c76b01SKoji Sato /* no siblings */
152117c76b01SKoji Sato /* the only child of the root node */
15221f5abe7eSRyusuke Konishi WARN_ON(level != nilfs_btree_height(btree) - 2);
15236d28f7eaSRyusuke Konishi if (nilfs_btree_node_get_nchildren(node) - 1 <=
152417c76b01SKoji Sato NILFS_BTREE_ROOT_NCHILDREN_MAX) {
152517c76b01SKoji Sato path[level].bp_op = nilfs_btree_shrink;
152617c76b01SKoji Sato stats->bs_nblocks += 2;
1527d4099053SRyusuke Konishi level++;
1528d4099053SRyusuke Konishi path[level].bp_op = nilfs_btree_nop;
1529d4099053SRyusuke Konishi goto shrink_root_child;
153017c76b01SKoji Sato } else {
153117c76b01SKoji Sato path[level].bp_op = nilfs_btree_do_delete;
153217c76b01SKoji Sato stats->bs_nblocks++;
153317c76b01SKoji Sato goto out;
1534d4099053SRyusuke Konishi }
153517c76b01SKoji Sato }
153617c76b01SKoji Sato }
153717c76b01SKoji Sato
1538d4099053SRyusuke Konishi /* child of the root node is deleted */
1539d4099053SRyusuke Konishi path[level].bp_op = nilfs_btree_do_delete;
1540d4099053SRyusuke Konishi stats->bs_nblocks++;
1541d4099053SRyusuke Konishi
1542d4099053SRyusuke Konishi shrink_root_child:
154317c76b01SKoji Sato node = nilfs_btree_get_root(btree);
154417c76b01SKoji Sato path[level].bp_oldreq.bpr_ptr =
1545fe744fdbSRyusuke Konishi nilfs_btree_node_get_ptr(node, dindex,
15469b7b265cSRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX);
1547d4b96157SRyusuke Konishi
1548e7c274f8SRyusuke Konishi ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat);
154917c76b01SKoji Sato if (ret < 0)
155017c76b01SKoji Sato goto err_out_child_node;
1551d4b96157SRyusuke Konishi
155217c76b01SKoji Sato /* success */
155317c76b01SKoji Sato out:
155417c76b01SKoji Sato *levelp = level;
155517c76b01SKoji Sato return ret;
155617c76b01SKoji Sato
155717c76b01SKoji Sato /* error */
155817c76b01SKoji Sato err_out_curr_node:
1559e7c274f8SRyusuke Konishi nilfs_bmap_abort_end_ptr(btree, &path[level].bp_oldreq, dat);
156017c76b01SKoji Sato err_out_child_node:
156117c76b01SKoji Sato for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
1562087d01b4SRyusuke Konishi brelse(path[level].bp_sib_bh);
1563e7c274f8SRyusuke Konishi nilfs_bmap_abort_end_ptr(btree, &path[level].bp_oldreq, dat);
156417c76b01SKoji Sato }
156517c76b01SKoji Sato *levelp = level;
156617c76b01SKoji Sato stats->bs_nblocks = 0;
156717c76b01SKoji Sato return ret;
156817c76b01SKoji Sato }
156917c76b01SKoji Sato
nilfs_btree_commit_delete(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int maxlevel,struct inode * dat)1570e7c274f8SRyusuke Konishi static void nilfs_btree_commit_delete(struct nilfs_bmap *btree,
157117c76b01SKoji Sato struct nilfs_btree_path *path,
15722e0c2c73SRyusuke Konishi int maxlevel, struct inode *dat)
157317c76b01SKoji Sato {
157417c76b01SKoji Sato int level;
157517c76b01SKoji Sato
157617c76b01SKoji Sato for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
1577e7c274f8SRyusuke Konishi nilfs_bmap_commit_end_ptr(btree, &path[level].bp_oldreq, dat);
15788acfbf09SPekka Enberg path[level].bp_op(btree, path, level, NULL, NULL);
157917c76b01SKoji Sato }
158017c76b01SKoji Sato
1581e7c274f8SRyusuke Konishi if (!nilfs_bmap_dirty(btree))
1582e7c274f8SRyusuke Konishi nilfs_bmap_set_dirty(btree);
158317c76b01SKoji Sato }
158417c76b01SKoji Sato
nilfs_btree_delete(struct nilfs_bmap * btree,__u64 key)1585e7c274f8SRyusuke Konishi static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key)
158617c76b01SKoji Sato
158717c76b01SKoji Sato {
158817c76b01SKoji Sato struct nilfs_btree_path *path;
158917c76b01SKoji Sato struct nilfs_bmap_stats stats;
15902e0c2c73SRyusuke Konishi struct inode *dat;
159117c76b01SKoji Sato int level, ret;
159217c76b01SKoji Sato
15936d28f7eaSRyusuke Konishi path = nilfs_btree_alloc_path();
159417c76b01SKoji Sato if (path == NULL)
159517c76b01SKoji Sato return -ENOMEM;
1596f905440fSLi Hong
159717c76b01SKoji Sato ret = nilfs_btree_do_lookup(btree, path, key, NULL,
159803bdb5acSRyusuke Konishi NILFS_BTREE_LEVEL_NODE_MIN, 0);
159917c76b01SKoji Sato if (ret < 0)
160017c76b01SKoji Sato goto out;
160117c76b01SKoji Sato
16022e0c2c73SRyusuke Konishi
1603e7c274f8SRyusuke Konishi dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL;
16042e0c2c73SRyusuke Konishi
16052e0c2c73SRyusuke Konishi ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat);
160617c76b01SKoji Sato if (ret < 0)
160717c76b01SKoji Sato goto out;
16082e0c2c73SRyusuke Konishi nilfs_btree_commit_delete(btree, path, level, dat);
1609be667377SRyusuke Konishi nilfs_inode_sub_blocks(btree->b_inode, stats.bs_nblocks);
161017c76b01SKoji Sato
161117c76b01SKoji Sato out:
16126d28f7eaSRyusuke Konishi nilfs_btree_free_path(path);
161317c76b01SKoji Sato return ret;
161417c76b01SKoji Sato }
161517c76b01SKoji Sato
nilfs_btree_seek_key(const struct nilfs_bmap * btree,__u64 start,__u64 * keyp)16165b20384fSRyusuke Konishi static int nilfs_btree_seek_key(const struct nilfs_bmap *btree, __u64 start,
16175b20384fSRyusuke Konishi __u64 *keyp)
16185b20384fSRyusuke Konishi {
16195b20384fSRyusuke Konishi struct nilfs_btree_path *path;
16205b20384fSRyusuke Konishi const int minlevel = NILFS_BTREE_LEVEL_NODE_MIN;
16215b20384fSRyusuke Konishi int ret;
16225b20384fSRyusuke Konishi
16235b20384fSRyusuke Konishi path = nilfs_btree_alloc_path();
16245b20384fSRyusuke Konishi if (!path)
16255b20384fSRyusuke Konishi return -ENOMEM;
16265b20384fSRyusuke Konishi
16275b20384fSRyusuke Konishi ret = nilfs_btree_do_lookup(btree, path, start, NULL, minlevel, 0);
16285b20384fSRyusuke Konishi if (!ret)
16295b20384fSRyusuke Konishi *keyp = start;
16305b20384fSRyusuke Konishi else if (ret == -ENOENT)
16315b20384fSRyusuke Konishi ret = nilfs_btree_get_next_key(btree, path, minlevel, keyp);
16325b20384fSRyusuke Konishi
16335b20384fSRyusuke Konishi nilfs_btree_free_path(path);
16345b20384fSRyusuke Konishi return ret;
16355b20384fSRyusuke Konishi }
16365b20384fSRyusuke Konishi
nilfs_btree_last_key(const struct nilfs_bmap * btree,__u64 * keyp)1637e7c274f8SRyusuke Konishi static int nilfs_btree_last_key(const struct nilfs_bmap *btree, __u64 *keyp)
163817c76b01SKoji Sato {
163917c76b01SKoji Sato struct nilfs_btree_path *path;
164017c76b01SKoji Sato int ret;
164117c76b01SKoji Sato
16426d28f7eaSRyusuke Konishi path = nilfs_btree_alloc_path();
164317c76b01SKoji Sato if (path == NULL)
164417c76b01SKoji Sato return -ENOMEM;
164517c76b01SKoji Sato
164617c76b01SKoji Sato ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL);
164717c76b01SKoji Sato
16486d28f7eaSRyusuke Konishi nilfs_btree_free_path(path);
164917c76b01SKoji Sato
165017c76b01SKoji Sato return ret;
165117c76b01SKoji Sato }
165217c76b01SKoji Sato
nilfs_btree_check_delete(struct nilfs_bmap * btree,__u64 key)1653e7c274f8SRyusuke Konishi static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key)
165417c76b01SKoji Sato {
165517c76b01SKoji Sato struct buffer_head *bh;
165617c76b01SKoji Sato struct nilfs_btree_node *root, *node;
165717c76b01SKoji Sato __u64 maxkey, nextmaxkey;
165817c76b01SKoji Sato __u64 ptr;
165917c76b01SKoji Sato int nchildren, ret;
166017c76b01SKoji Sato
166117c76b01SKoji Sato root = nilfs_btree_get_root(btree);
1662*257f9e51SRyusuke Konishi nchildren = nilfs_btree_node_get_nchildren(root);
1663*257f9e51SRyusuke Konishi if (unlikely(nchildren == 0))
1664*257f9e51SRyusuke Konishi return 0;
1665*257f9e51SRyusuke Konishi
166617c76b01SKoji Sato switch (nilfs_btree_height(btree)) {
166717c76b01SKoji Sato case 2:
166817c76b01SKoji Sato bh = NULL;
166917c76b01SKoji Sato node = root;
167017c76b01SKoji Sato break;
167117c76b01SKoji Sato case 3:
167217c76b01SKoji Sato if (nchildren > 1)
167317c76b01SKoji Sato return 0;
16749b7b265cSRyusuke Konishi ptr = nilfs_btree_node_get_ptr(root, nchildren - 1,
16759b7b265cSRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX);
1676f198dbb9SRyusuke Konishi ret = nilfs_btree_get_block(btree, ptr, &bh);
167717c76b01SKoji Sato if (ret < 0)
167817c76b01SKoji Sato return ret;
167917c76b01SKoji Sato node = (struct nilfs_btree_node *)bh->b_data;
1680*257f9e51SRyusuke Konishi nchildren = nilfs_btree_node_get_nchildren(node);
168117c76b01SKoji Sato break;
168217c76b01SKoji Sato default:
168317c76b01SKoji Sato return 0;
168417c76b01SKoji Sato }
168517c76b01SKoji Sato
16866d28f7eaSRyusuke Konishi maxkey = nilfs_btree_node_get_key(node, nchildren - 1);
168717c76b01SKoji Sato nextmaxkey = (nchildren > 1) ?
16886d28f7eaSRyusuke Konishi nilfs_btree_node_get_key(node, nchildren - 2) : 0;
1689087d01b4SRyusuke Konishi brelse(bh);
169017c76b01SKoji Sato
16913033342aSRyusuke Konishi return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
169217c76b01SKoji Sato }
169317c76b01SKoji Sato
nilfs_btree_gather_data(struct nilfs_bmap * btree,__u64 * keys,__u64 * ptrs,int nitems)1694e7c274f8SRyusuke Konishi static int nilfs_btree_gather_data(struct nilfs_bmap *btree,
169517c76b01SKoji Sato __u64 *keys, __u64 *ptrs, int nitems)
169617c76b01SKoji Sato {
169717c76b01SKoji Sato struct buffer_head *bh;
169817c76b01SKoji Sato struct nilfs_btree_node *node, *root;
169917c76b01SKoji Sato __le64 *dkeys;
170017c76b01SKoji Sato __le64 *dptrs;
170117c76b01SKoji Sato __u64 ptr;
17029b7b265cSRyusuke Konishi int nchildren, ncmax, i, ret;
170317c76b01SKoji Sato
170417c76b01SKoji Sato root = nilfs_btree_get_root(btree);
170517c76b01SKoji Sato switch (nilfs_btree_height(btree)) {
170617c76b01SKoji Sato case 2:
170717c76b01SKoji Sato bh = NULL;
170817c76b01SKoji Sato node = root;
17099b7b265cSRyusuke Konishi ncmax = NILFS_BTREE_ROOT_NCHILDREN_MAX;
171017c76b01SKoji Sato break;
171117c76b01SKoji Sato case 3:
17126d28f7eaSRyusuke Konishi nchildren = nilfs_btree_node_get_nchildren(root);
17131f5abe7eSRyusuke Konishi WARN_ON(nchildren > 1);
17149b7b265cSRyusuke Konishi ptr = nilfs_btree_node_get_ptr(root, nchildren - 1,
17159b7b265cSRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX);
1716f198dbb9SRyusuke Konishi ret = nilfs_btree_get_block(btree, ptr, &bh);
171717c76b01SKoji Sato if (ret < 0)
171817c76b01SKoji Sato return ret;
171917c76b01SKoji Sato node = (struct nilfs_btree_node *)bh->b_data;
17209b7b265cSRyusuke Konishi ncmax = nilfs_btree_nchildren_per_block(btree);
172117c76b01SKoji Sato break;
172217c76b01SKoji Sato default:
172317c76b01SKoji Sato node = NULL;
17241f5abe7eSRyusuke Konishi return -EINVAL;
172517c76b01SKoji Sato }
172617c76b01SKoji Sato
17276d28f7eaSRyusuke Konishi nchildren = nilfs_btree_node_get_nchildren(node);
172817c76b01SKoji Sato if (nchildren < nitems)
172917c76b01SKoji Sato nitems = nchildren;
17306d28f7eaSRyusuke Konishi dkeys = nilfs_btree_node_dkeys(node);
17319b7b265cSRyusuke Konishi dptrs = nilfs_btree_node_dptrs(node, ncmax);
173217c76b01SKoji Sato for (i = 0; i < nitems; i++) {
173325b8d7deSRyusuke Konishi keys[i] = le64_to_cpu(dkeys[i]);
173425b8d7deSRyusuke Konishi ptrs[i] = le64_to_cpu(dptrs[i]);
173517c76b01SKoji Sato }
173617c76b01SKoji Sato
1737087d01b4SRyusuke Konishi brelse(bh);
173817c76b01SKoji Sato
173917c76b01SKoji Sato return nitems;
174017c76b01SKoji Sato }
174117c76b01SKoji Sato
174217c76b01SKoji Sato static int
nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap * btree,__u64 key,union nilfs_bmap_ptr_req * dreq,union nilfs_bmap_ptr_req * nreq,struct buffer_head ** bhp,struct nilfs_bmap_stats * stats)1743e7c274f8SRyusuke Konishi nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *btree, __u64 key,
174417c76b01SKoji Sato union nilfs_bmap_ptr_req *dreq,
174517c76b01SKoji Sato union nilfs_bmap_ptr_req *nreq,
174617c76b01SKoji Sato struct buffer_head **bhp,
174717c76b01SKoji Sato struct nilfs_bmap_stats *stats)
174817c76b01SKoji Sato {
174917c76b01SKoji Sato struct buffer_head *bh;
17502e0c2c73SRyusuke Konishi struct inode *dat = NULL;
175117c76b01SKoji Sato int ret;
175217c76b01SKoji Sato
175317c76b01SKoji Sato stats->bs_nblocks = 0;
175417c76b01SKoji Sato
175517c76b01SKoji Sato /* for data */
175617c76b01SKoji Sato /* cannot find near ptr */
1757e7c274f8SRyusuke Konishi if (NILFS_BMAP_USE_VBN(btree)) {
17587cde31d7SRyusuke Konishi dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
1759e7c274f8SRyusuke Konishi dat = nilfs_bmap_get_dat(btree);
17602e0c2c73SRyusuke Konishi }
17617cde31d7SRyusuke Konishi
1762e897be17SRyusuke Konishi ret = nilfs_attach_btree_node_cache(&NILFS_BMAP_I(btree)->vfs_inode);
1763e897be17SRyusuke Konishi if (ret < 0)
1764e897be17SRyusuke Konishi return ret;
1765e897be17SRyusuke Konishi
1766e7c274f8SRyusuke Konishi ret = nilfs_bmap_prepare_alloc_ptr(btree, dreq, dat);
176717c76b01SKoji Sato if (ret < 0)
176817c76b01SKoji Sato return ret;
176917c76b01SKoji Sato
177017c76b01SKoji Sato *bhp = NULL;
177117c76b01SKoji Sato stats->bs_nblocks++;
177217c76b01SKoji Sato if (nreq != NULL) {
177317c76b01SKoji Sato nreq->bpr_ptr = dreq->bpr_ptr + 1;
1774e7c274f8SRyusuke Konishi ret = nilfs_bmap_prepare_alloc_ptr(btree, nreq, dat);
177517c76b01SKoji Sato if (ret < 0)
177617c76b01SKoji Sato goto err_out_dreq;
177717c76b01SKoji Sato
1778f198dbb9SRyusuke Konishi ret = nilfs_btree_get_new_block(btree, nreq->bpr_ptr, &bh);
177917c76b01SKoji Sato if (ret < 0)
178017c76b01SKoji Sato goto err_out_nreq;
178117c76b01SKoji Sato
178217c76b01SKoji Sato *bhp = bh;
178317c76b01SKoji Sato stats->bs_nblocks++;
178417c76b01SKoji Sato }
178517c76b01SKoji Sato
178617c76b01SKoji Sato /* success */
178717c76b01SKoji Sato return 0;
178817c76b01SKoji Sato
178917c76b01SKoji Sato /* error */
179017c76b01SKoji Sato err_out_nreq:
1791e7c274f8SRyusuke Konishi nilfs_bmap_abort_alloc_ptr(btree, nreq, dat);
179217c76b01SKoji Sato err_out_dreq:
1793e7c274f8SRyusuke Konishi nilfs_bmap_abort_alloc_ptr(btree, dreq, dat);
179417c76b01SKoji Sato stats->bs_nblocks = 0;
179517c76b01SKoji Sato return ret;
179617c76b01SKoji Sato
179717c76b01SKoji Sato }
179817c76b01SKoji Sato
179917c76b01SKoji Sato static void
nilfs_btree_commit_convert_and_insert(struct nilfs_bmap * btree,__u64 key,__u64 ptr,const __u64 * keys,const __u64 * ptrs,int n,union nilfs_bmap_ptr_req * dreq,union nilfs_bmap_ptr_req * nreq,struct buffer_head * bh)1800e7c274f8SRyusuke Konishi nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *btree,
180117c76b01SKoji Sato __u64 key, __u64 ptr,
180217c76b01SKoji Sato const __u64 *keys, const __u64 *ptrs,
18033033342aSRyusuke Konishi int n,
180417c76b01SKoji Sato union nilfs_bmap_ptr_req *dreq,
180517c76b01SKoji Sato union nilfs_bmap_ptr_req *nreq,
180617c76b01SKoji Sato struct buffer_head *bh)
180717c76b01SKoji Sato {
180817c76b01SKoji Sato struct nilfs_btree_node *node;
18092e0c2c73SRyusuke Konishi struct inode *dat;
181017c76b01SKoji Sato __u64 tmpptr;
18119b7b265cSRyusuke Konishi int ncblk;
181217c76b01SKoji Sato
181317c76b01SKoji Sato /* free resources */
1814e7c274f8SRyusuke Konishi if (btree->b_ops->bop_clear != NULL)
1815e7c274f8SRyusuke Konishi btree->b_ops->bop_clear(btree);
181617c76b01SKoji Sato
181717c76b01SKoji Sato /* ptr must be a pointer to a buffer head. */
181817c76b01SKoji Sato set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
181917c76b01SKoji Sato
182017c76b01SKoji Sato /* convert and insert */
1821e7c274f8SRyusuke Konishi dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL;
1822957ed60bSRyusuke Konishi __nilfs_btree_init(btree);
182317c76b01SKoji Sato if (nreq != NULL) {
1824e7c274f8SRyusuke Konishi nilfs_bmap_commit_alloc_ptr(btree, dreq, dat);
1825e7c274f8SRyusuke Konishi nilfs_bmap_commit_alloc_ptr(btree, nreq, dat);
182617c76b01SKoji Sato
182717c76b01SKoji Sato /* create child node at level 1 */
182817c76b01SKoji Sato node = (struct nilfs_btree_node *)bh->b_data;
18299b7b265cSRyusuke Konishi ncblk = nilfs_btree_nchildren_per_block(btree);
18309b7b265cSRyusuke Konishi nilfs_btree_node_init(node, 0, 1, n, ncblk, keys, ptrs);
18319b7b265cSRyusuke Konishi nilfs_btree_node_insert(node, n, key, dreq->bpr_ptr, ncblk);
183217c76b01SKoji Sato if (!buffer_dirty(bh))
18335fc7b141SRyusuke Konishi mark_buffer_dirty(bh);
1834e7c274f8SRyusuke Konishi if (!nilfs_bmap_dirty(btree))
1835e7c274f8SRyusuke Konishi nilfs_bmap_set_dirty(btree);
183617c76b01SKoji Sato
1837087d01b4SRyusuke Konishi brelse(bh);
183817c76b01SKoji Sato
183917c76b01SKoji Sato /* create root node at level 2 */
184017c76b01SKoji Sato node = nilfs_btree_get_root(btree);
184117c76b01SKoji Sato tmpptr = nreq->bpr_ptr;
18429b7b265cSRyusuke Konishi nilfs_btree_node_init(node, NILFS_BTREE_NODE_ROOT, 2, 1,
18439b7b265cSRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX,
18449b7b265cSRyusuke Konishi &keys[0], &tmpptr);
184517c76b01SKoji Sato } else {
1846e7c274f8SRyusuke Konishi nilfs_bmap_commit_alloc_ptr(btree, dreq, dat);
184717c76b01SKoji Sato
184817c76b01SKoji Sato /* create root node at level 1 */
184917c76b01SKoji Sato node = nilfs_btree_get_root(btree);
18509b7b265cSRyusuke Konishi nilfs_btree_node_init(node, NILFS_BTREE_NODE_ROOT, 1, n,
18519b7b265cSRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX,
18529b7b265cSRyusuke Konishi keys, ptrs);
18539b7b265cSRyusuke Konishi nilfs_btree_node_insert(node, n, key, dreq->bpr_ptr,
18549b7b265cSRyusuke Konishi NILFS_BTREE_ROOT_NCHILDREN_MAX);
1855e7c274f8SRyusuke Konishi if (!nilfs_bmap_dirty(btree))
1856e7c274f8SRyusuke Konishi nilfs_bmap_set_dirty(btree);
185717c76b01SKoji Sato }
185817c76b01SKoji Sato
1859e7c274f8SRyusuke Konishi if (NILFS_BMAP_USE_VBN(btree))
1860dc935be2SRyusuke Konishi nilfs_bmap_set_target_v(btree, key, dreq->bpr_ptr);
186117c76b01SKoji Sato }
186217c76b01SKoji Sato
186317c76b01SKoji Sato /**
186417c76b01SKoji Sato * nilfs_btree_convert_and_insert -
186517c76b01SKoji Sato * @bmap:
186617c76b01SKoji Sato * @key:
186717c76b01SKoji Sato * @ptr:
186817c76b01SKoji Sato * @keys:
186917c76b01SKoji Sato * @ptrs:
187017c76b01SKoji Sato * @n:
187117c76b01SKoji Sato */
nilfs_btree_convert_and_insert(struct nilfs_bmap * btree,__u64 key,__u64 ptr,const __u64 * keys,const __u64 * ptrs,int n)1872e7c274f8SRyusuke Konishi int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree,
187317c76b01SKoji Sato __u64 key, __u64 ptr,
18743033342aSRyusuke Konishi const __u64 *keys, const __u64 *ptrs, int n)
187517c76b01SKoji Sato {
18764f05028fSRyusuke Konishi struct buffer_head *bh = NULL;
187717c76b01SKoji Sato union nilfs_bmap_ptr_req dreq, nreq, *di, *ni;
187817c76b01SKoji Sato struct nilfs_bmap_stats stats;
187917c76b01SKoji Sato int ret;
188017c76b01SKoji Sato
188117c76b01SKoji Sato if (n + 1 <= NILFS_BTREE_ROOT_NCHILDREN_MAX) {
188217c76b01SKoji Sato di = &dreq;
188317c76b01SKoji Sato ni = NULL;
188417c76b01SKoji Sato } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX(
18851508ddc3SGeliang Tang nilfs_btree_node_size(btree))) {
188617c76b01SKoji Sato di = &dreq;
188717c76b01SKoji Sato ni = &nreq;
188817c76b01SKoji Sato } else {
188917c76b01SKoji Sato di = NULL;
189017c76b01SKoji Sato ni = NULL;
189117c76b01SKoji Sato BUG();
189217c76b01SKoji Sato }
189317c76b01SKoji Sato
1894e7c274f8SRyusuke Konishi ret = nilfs_btree_prepare_convert_and_insert(btree, key, di, ni, &bh,
189517c76b01SKoji Sato &stats);
189617c76b01SKoji Sato if (ret < 0)
189717c76b01SKoji Sato return ret;
1898e7c274f8SRyusuke Konishi nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n,
18993033342aSRyusuke Konishi di, ni, bh);
1900be667377SRyusuke Konishi nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks);
190117c76b01SKoji Sato return 0;
190217c76b01SKoji Sato }
190317c76b01SKoji Sato
nilfs_btree_propagate_p(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,struct buffer_head * bh)1904e7c274f8SRyusuke Konishi static int nilfs_btree_propagate_p(struct nilfs_bmap *btree,
190517c76b01SKoji Sato struct nilfs_btree_path *path,
190617c76b01SKoji Sato int level,
190717c76b01SKoji Sato struct buffer_head *bh)
190817c76b01SKoji Sato {
190917c76b01SKoji Sato while ((++level < nilfs_btree_height(btree) - 1) &&
191017c76b01SKoji Sato !buffer_dirty(path[level].bp_bh))
19115fc7b141SRyusuke Konishi mark_buffer_dirty(path[level].bp_bh);
191217c76b01SKoji Sato
191317c76b01SKoji Sato return 0;
191417c76b01SKoji Sato }
191517c76b01SKoji Sato
nilfs_btree_prepare_update_v(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,struct inode * dat)1916e7c274f8SRyusuke Konishi static int nilfs_btree_prepare_update_v(struct nilfs_bmap *btree,
191717c76b01SKoji Sato struct nilfs_btree_path *path,
19182e0c2c73SRyusuke Konishi int level, struct inode *dat)
191917c76b01SKoji Sato {
192017c76b01SKoji Sato struct nilfs_btree_node *parent;
19219b7b265cSRyusuke Konishi int ncmax, ret;
192217c76b01SKoji Sato
19239b7b265cSRyusuke Konishi parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
192417c76b01SKoji Sato path[level].bp_oldreq.bpr_ptr =
19259b7b265cSRyusuke Konishi nilfs_btree_node_get_ptr(parent, path[level + 1].bp_index,
19269b7b265cSRyusuke Konishi ncmax);
192717c76b01SKoji Sato path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
19282e0c2c73SRyusuke Konishi ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req,
19292e0c2c73SRyusuke Konishi &path[level].bp_newreq.bpr_req);
193017c76b01SKoji Sato if (ret < 0)
193117c76b01SKoji Sato return ret;
193217c76b01SKoji Sato
193317c76b01SKoji Sato if (buffer_nilfs_node(path[level].bp_bh)) {
193417c76b01SKoji Sato path[level].bp_ctxt.oldkey = path[level].bp_oldreq.bpr_ptr;
193517c76b01SKoji Sato path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr;
193617c76b01SKoji Sato path[level].bp_ctxt.bh = path[level].bp_bh;
193717c76b01SKoji Sato ret = nilfs_btnode_prepare_change_key(
1938e897be17SRyusuke Konishi NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping,
193917c76b01SKoji Sato &path[level].bp_ctxt);
194017c76b01SKoji Sato if (ret < 0) {
19412e0c2c73SRyusuke Konishi nilfs_dat_abort_update(dat,
19422e0c2c73SRyusuke Konishi &path[level].bp_oldreq.bpr_req,
19432e0c2c73SRyusuke Konishi &path[level].bp_newreq.bpr_req);
194417c76b01SKoji Sato return ret;
194517c76b01SKoji Sato }
194617c76b01SKoji Sato }
194717c76b01SKoji Sato
194817c76b01SKoji Sato return 0;
194917c76b01SKoji Sato }
195017c76b01SKoji Sato
nilfs_btree_commit_update_v(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,struct inode * dat)1951e7c274f8SRyusuke Konishi static void nilfs_btree_commit_update_v(struct nilfs_bmap *btree,
195217c76b01SKoji Sato struct nilfs_btree_path *path,
19532e0c2c73SRyusuke Konishi int level, struct inode *dat)
195417c76b01SKoji Sato {
195517c76b01SKoji Sato struct nilfs_btree_node *parent;
19569b7b265cSRyusuke Konishi int ncmax;
195717c76b01SKoji Sato
19582e0c2c73SRyusuke Konishi nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req,
19592e0c2c73SRyusuke Konishi &path[level].bp_newreq.bpr_req,
1960e7c274f8SRyusuke Konishi btree->b_ptr_type == NILFS_BMAP_PTR_VS);
196117c76b01SKoji Sato
196217c76b01SKoji Sato if (buffer_nilfs_node(path[level].bp_bh)) {
196317c76b01SKoji Sato nilfs_btnode_commit_change_key(
1964e897be17SRyusuke Konishi NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping,
196517c76b01SKoji Sato &path[level].bp_ctxt);
196617c76b01SKoji Sato path[level].bp_bh = path[level].bp_ctxt.bh;
196717c76b01SKoji Sato }
196817c76b01SKoji Sato set_buffer_nilfs_volatile(path[level].bp_bh);
196917c76b01SKoji Sato
19709b7b265cSRyusuke Konishi parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
19719b7b265cSRyusuke Konishi nilfs_btree_node_set_ptr(parent, path[level + 1].bp_index,
19729b7b265cSRyusuke Konishi path[level].bp_newreq.bpr_ptr, ncmax);
197317c76b01SKoji Sato }
197417c76b01SKoji Sato
nilfs_btree_abort_update_v(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,struct inode * dat)1975e7c274f8SRyusuke Konishi static void nilfs_btree_abort_update_v(struct nilfs_bmap *btree,
197617c76b01SKoji Sato struct nilfs_btree_path *path,
19772e0c2c73SRyusuke Konishi int level, struct inode *dat)
197817c76b01SKoji Sato {
19792e0c2c73SRyusuke Konishi nilfs_dat_abort_update(dat, &path[level].bp_oldreq.bpr_req,
19802e0c2c73SRyusuke Konishi &path[level].bp_newreq.bpr_req);
198117c76b01SKoji Sato if (buffer_nilfs_node(path[level].bp_bh))
198217c76b01SKoji Sato nilfs_btnode_abort_change_key(
1983e897be17SRyusuke Konishi NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping,
198417c76b01SKoji Sato &path[level].bp_ctxt);
198517c76b01SKoji Sato }
198617c76b01SKoji Sato
nilfs_btree_prepare_propagate_v(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int minlevel,int * maxlevelp,struct inode * dat)1987e7c274f8SRyusuke Konishi static int nilfs_btree_prepare_propagate_v(struct nilfs_bmap *btree,
198817c76b01SKoji Sato struct nilfs_btree_path *path,
19892e0c2c73SRyusuke Konishi int minlevel, int *maxlevelp,
19902e0c2c73SRyusuke Konishi struct inode *dat)
199117c76b01SKoji Sato {
199217c76b01SKoji Sato int level, ret;
199317c76b01SKoji Sato
199417c76b01SKoji Sato level = minlevel;
199517c76b01SKoji Sato if (!buffer_nilfs_volatile(path[level].bp_bh)) {
19962e0c2c73SRyusuke Konishi ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
199717c76b01SKoji Sato if (ret < 0)
199817c76b01SKoji Sato return ret;
199917c76b01SKoji Sato }
200017c76b01SKoji Sato while ((++level < nilfs_btree_height(btree) - 1) &&
200117c76b01SKoji Sato !buffer_dirty(path[level].bp_bh)) {
200217c76b01SKoji Sato
20031f5abe7eSRyusuke Konishi WARN_ON(buffer_nilfs_volatile(path[level].bp_bh));
20042e0c2c73SRyusuke Konishi ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
200517c76b01SKoji Sato if (ret < 0)
200617c76b01SKoji Sato goto out;
200717c76b01SKoji Sato }
200817c76b01SKoji Sato
200917c76b01SKoji Sato /* success */
201017c76b01SKoji Sato *maxlevelp = level - 1;
201117c76b01SKoji Sato return 0;
201217c76b01SKoji Sato
201317c76b01SKoji Sato /* error */
201417c76b01SKoji Sato out:
201517c76b01SKoji Sato while (--level > minlevel)
20162e0c2c73SRyusuke Konishi nilfs_btree_abort_update_v(btree, path, level, dat);
201717c76b01SKoji Sato if (!buffer_nilfs_volatile(path[level].bp_bh))
20182e0c2c73SRyusuke Konishi nilfs_btree_abort_update_v(btree, path, level, dat);
201917c76b01SKoji Sato return ret;
202017c76b01SKoji Sato }
202117c76b01SKoji Sato
nilfs_btree_commit_propagate_v(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int minlevel,int maxlevel,struct buffer_head * bh,struct inode * dat)2022e7c274f8SRyusuke Konishi static void nilfs_btree_commit_propagate_v(struct nilfs_bmap *btree,
202317c76b01SKoji Sato struct nilfs_btree_path *path,
20242e0c2c73SRyusuke Konishi int minlevel, int maxlevel,
20252e0c2c73SRyusuke Konishi struct buffer_head *bh,
20262e0c2c73SRyusuke Konishi struct inode *dat)
202717c76b01SKoji Sato {
202817c76b01SKoji Sato int level;
202917c76b01SKoji Sato
203017c76b01SKoji Sato if (!buffer_nilfs_volatile(path[minlevel].bp_bh))
20312e0c2c73SRyusuke Konishi nilfs_btree_commit_update_v(btree, path, minlevel, dat);
203217c76b01SKoji Sato
203317c76b01SKoji Sato for (level = minlevel + 1; level <= maxlevel; level++)
20342e0c2c73SRyusuke Konishi nilfs_btree_commit_update_v(btree, path, level, dat);
203517c76b01SKoji Sato }
203617c76b01SKoji Sato
nilfs_btree_propagate_v(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,struct buffer_head * bh)2037e7c274f8SRyusuke Konishi static int nilfs_btree_propagate_v(struct nilfs_bmap *btree,
203817c76b01SKoji Sato struct nilfs_btree_path *path,
20392e0c2c73SRyusuke Konishi int level, struct buffer_head *bh)
204017c76b01SKoji Sato {
2041308f4419SLi Hong int maxlevel = 0, ret;
204217c76b01SKoji Sato struct nilfs_btree_node *parent;
2043e7c274f8SRyusuke Konishi struct inode *dat = nilfs_bmap_get_dat(btree);
204417c76b01SKoji Sato __u64 ptr;
20459b7b265cSRyusuke Konishi int ncmax;
204617c76b01SKoji Sato
204717c76b01SKoji Sato get_bh(bh);
204817c76b01SKoji Sato path[level].bp_bh = bh;
20492e0c2c73SRyusuke Konishi ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel,
20502e0c2c73SRyusuke Konishi dat);
205117c76b01SKoji Sato if (ret < 0)
205217c76b01SKoji Sato goto out;
205317c76b01SKoji Sato
205417c76b01SKoji Sato if (buffer_nilfs_volatile(path[level].bp_bh)) {
20559b7b265cSRyusuke Konishi parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
20569b7b265cSRyusuke Konishi ptr = nilfs_btree_node_get_ptr(parent,
20579b7b265cSRyusuke Konishi path[level + 1].bp_index,
20589b7b265cSRyusuke Konishi ncmax);
20592e0c2c73SRyusuke Konishi ret = nilfs_dat_mark_dirty(dat, ptr);
206017c76b01SKoji Sato if (ret < 0)
206117c76b01SKoji Sato goto out;
206217c76b01SKoji Sato }
206317c76b01SKoji Sato
20642e0c2c73SRyusuke Konishi nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh, dat);
206517c76b01SKoji Sato
206617c76b01SKoji Sato out:
206717c76b01SKoji Sato brelse(path[level].bp_bh);
206817c76b01SKoji Sato path[level].bp_bh = NULL;
206917c76b01SKoji Sato return ret;
207017c76b01SKoji Sato }
207117c76b01SKoji Sato
nilfs_btree_propagate(struct nilfs_bmap * btree,struct buffer_head * bh)2072e7c274f8SRyusuke Konishi static int nilfs_btree_propagate(struct nilfs_bmap *btree,
207317c76b01SKoji Sato struct buffer_head *bh)
207417c76b01SKoji Sato {
207517c76b01SKoji Sato struct nilfs_btree_path *path;
207617c76b01SKoji Sato struct nilfs_btree_node *node;
207717c76b01SKoji Sato __u64 key;
207817c76b01SKoji Sato int level, ret;
207917c76b01SKoji Sato
20801f5abe7eSRyusuke Konishi WARN_ON(!buffer_dirty(bh));
208117c76b01SKoji Sato
20826d28f7eaSRyusuke Konishi path = nilfs_btree_alloc_path();
208317c76b01SKoji Sato if (path == NULL)
208417c76b01SKoji Sato return -ENOMEM;
208517c76b01SKoji Sato
208617c76b01SKoji Sato if (buffer_nilfs_node(bh)) {
208717c76b01SKoji Sato node = (struct nilfs_btree_node *)bh->b_data;
20886d28f7eaSRyusuke Konishi key = nilfs_btree_node_get_key(node, 0);
20896d28f7eaSRyusuke Konishi level = nilfs_btree_node_get_level(node);
209017c76b01SKoji Sato } else {
2091e7c274f8SRyusuke Konishi key = nilfs_bmap_data_get_key(btree, bh);
209217c76b01SKoji Sato level = NILFS_BTREE_LEVEL_DATA;
209317c76b01SKoji Sato }
209417c76b01SKoji Sato
209503bdb5acSRyusuke Konishi ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1, 0);
209617c76b01SKoji Sato if (ret < 0) {
20971f5abe7eSRyusuke Konishi if (unlikely(ret == -ENOENT))
2098a1d0747aSJoe Perches nilfs_crit(btree->b_inode->i_sb,
2099feee880fSRyusuke Konishi "writing node/leaf block does not appear in b-tree (ino=%lu) at key=%llu, level=%d",
2100feee880fSRyusuke Konishi btree->b_inode->i_ino,
2101feee880fSRyusuke Konishi (unsigned long long)key, level);
210217c76b01SKoji Sato goto out;
210317c76b01SKoji Sato }
210417c76b01SKoji Sato
2105e7c274f8SRyusuke Konishi ret = NILFS_BMAP_USE_VBN(btree) ?
21067cde31d7SRyusuke Konishi nilfs_btree_propagate_v(btree, path, level, bh) :
21077cde31d7SRyusuke Konishi nilfs_btree_propagate_p(btree, path, level, bh);
210817c76b01SKoji Sato
210917c76b01SKoji Sato out:
21106d28f7eaSRyusuke Konishi nilfs_btree_free_path(path);
211117c76b01SKoji Sato
211217c76b01SKoji Sato return ret;
211317c76b01SKoji Sato }
211417c76b01SKoji Sato
nilfs_btree_propagate_gc(struct nilfs_bmap * btree,struct buffer_head * bh)2115e7c274f8SRyusuke Konishi static int nilfs_btree_propagate_gc(struct nilfs_bmap *btree,
211617c76b01SKoji Sato struct buffer_head *bh)
211717c76b01SKoji Sato {
2118e7c274f8SRyusuke Konishi return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(btree), bh->b_blocknr);
211917c76b01SKoji Sato }
212017c76b01SKoji Sato
nilfs_btree_add_dirty_buffer(struct nilfs_bmap * btree,struct list_head * lists,struct buffer_head * bh)2121e7c274f8SRyusuke Konishi static void nilfs_btree_add_dirty_buffer(struct nilfs_bmap *btree,
212217c76b01SKoji Sato struct list_head *lists,
212317c76b01SKoji Sato struct buffer_head *bh)
212417c76b01SKoji Sato {
212517c76b01SKoji Sato struct list_head *head;
212617c76b01SKoji Sato struct buffer_head *cbh;
212717c76b01SKoji Sato struct nilfs_btree_node *node, *cnode;
212817c76b01SKoji Sato __u64 key, ckey;
212917c76b01SKoji Sato int level;
213017c76b01SKoji Sato
213117c76b01SKoji Sato get_bh(bh);
213217c76b01SKoji Sato node = (struct nilfs_btree_node *)bh->b_data;
21336d28f7eaSRyusuke Konishi key = nilfs_btree_node_get_key(node, 0);
21346d28f7eaSRyusuke Konishi level = nilfs_btree_node_get_level(node);
2135cfa913a5SRyusuke Konishi if (level < NILFS_BTREE_LEVEL_NODE_MIN ||
2136cfa913a5SRyusuke Konishi level >= NILFS_BTREE_LEVEL_MAX) {
2137cfa913a5SRyusuke Konishi dump_stack();
2138a1d0747aSJoe Perches nilfs_warn(btree->b_inode->i_sb,
2139feee880fSRyusuke Konishi "invalid btree level: %d (key=%llu, ino=%lu, blocknr=%llu)",
2140feee880fSRyusuke Konishi level, (unsigned long long)key,
2141feee880fSRyusuke Konishi btree->b_inode->i_ino,
2142cfa913a5SRyusuke Konishi (unsigned long long)bh->b_blocknr);
2143cfa913a5SRyusuke Konishi return;
2144cfa913a5SRyusuke Konishi }
2145cfa913a5SRyusuke Konishi
214617c76b01SKoji Sato list_for_each(head, &lists[level]) {
214717c76b01SKoji Sato cbh = list_entry(head, struct buffer_head, b_assoc_buffers);
214817c76b01SKoji Sato cnode = (struct nilfs_btree_node *)cbh->b_data;
21496d28f7eaSRyusuke Konishi ckey = nilfs_btree_node_get_key(cnode, 0);
215017c76b01SKoji Sato if (key < ckey)
215117c76b01SKoji Sato break;
215217c76b01SKoji Sato }
215317c76b01SKoji Sato list_add_tail(&bh->b_assoc_buffers, head);
215417c76b01SKoji Sato }
215517c76b01SKoji Sato
nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap * btree,struct list_head * listp)2156e7c274f8SRyusuke Konishi static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *btree,
215717c76b01SKoji Sato struct list_head *listp)
215817c76b01SKoji Sato {
2159e897be17SRyusuke Konishi struct inode *btnc_inode = NILFS_BMAP_I(btree)->i_assoc_inode;
2160e897be17SRyusuke Konishi struct address_space *btcache = btnc_inode->i_mapping;
216117c76b01SKoji Sato struct list_head lists[NILFS_BTREE_LEVEL_MAX];
216241f3f3b5SVishal Moola (Oracle) struct folio_batch fbatch;
216317c76b01SKoji Sato struct buffer_head *bh, *head;
216417c76b01SKoji Sato pgoff_t index = 0;
216517c76b01SKoji Sato int level, i;
216617c76b01SKoji Sato
216717c76b01SKoji Sato for (level = NILFS_BTREE_LEVEL_NODE_MIN;
216817c76b01SKoji Sato level < NILFS_BTREE_LEVEL_MAX;
216917c76b01SKoji Sato level++)
217017c76b01SKoji Sato INIT_LIST_HEAD(&lists[level]);
217117c76b01SKoji Sato
217241f3f3b5SVishal Moola (Oracle) folio_batch_init(&fbatch);
217317c76b01SKoji Sato
217441f3f3b5SVishal Moola (Oracle) while (filemap_get_folios_tag(btcache, &index, (pgoff_t)-1,
217541f3f3b5SVishal Moola (Oracle) PAGECACHE_TAG_DIRTY, &fbatch)) {
217641f3f3b5SVishal Moola (Oracle) for (i = 0; i < folio_batch_count(&fbatch); i++) {
217741f3f3b5SVishal Moola (Oracle) bh = head = folio_buffers(fbatch.folios[i]);
217817c76b01SKoji Sato do {
217917c76b01SKoji Sato if (buffer_dirty(bh))
218017c76b01SKoji Sato nilfs_btree_add_dirty_buffer(btree,
218117c76b01SKoji Sato lists, bh);
218217c76b01SKoji Sato } while ((bh = bh->b_this_page) != head);
218317c76b01SKoji Sato }
218441f3f3b5SVishal Moola (Oracle) folio_batch_release(&fbatch);
218517c76b01SKoji Sato cond_resched();
218617c76b01SKoji Sato }
218717c76b01SKoji Sato
218817c76b01SKoji Sato for (level = NILFS_BTREE_LEVEL_NODE_MIN;
218917c76b01SKoji Sato level < NILFS_BTREE_LEVEL_MAX;
219017c76b01SKoji Sato level++)
21910935db74SRyusuke Konishi list_splice_tail(&lists[level], listp);
219217c76b01SKoji Sato }
219317c76b01SKoji Sato
nilfs_btree_assign_p(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,struct buffer_head ** bh,sector_t blocknr,union nilfs_binfo * binfo)2194e7c274f8SRyusuke Konishi static int nilfs_btree_assign_p(struct nilfs_bmap *btree,
219517c76b01SKoji Sato struct nilfs_btree_path *path,
219617c76b01SKoji Sato int level,
219717c76b01SKoji Sato struct buffer_head **bh,
219817c76b01SKoji Sato sector_t blocknr,
219917c76b01SKoji Sato union nilfs_binfo *binfo)
220017c76b01SKoji Sato {
220117c76b01SKoji Sato struct nilfs_btree_node *parent;
220217c76b01SKoji Sato __u64 key;
220317c76b01SKoji Sato __u64 ptr;
22049b7b265cSRyusuke Konishi int ncmax, ret;
220517c76b01SKoji Sato
22069b7b265cSRyusuke Konishi parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
22079b7b265cSRyusuke Konishi ptr = nilfs_btree_node_get_ptr(parent, path[level + 1].bp_index,
22089b7b265cSRyusuke Konishi ncmax);
220917c76b01SKoji Sato if (buffer_nilfs_node(*bh)) {
221017c76b01SKoji Sato path[level].bp_ctxt.oldkey = ptr;
221117c76b01SKoji Sato path[level].bp_ctxt.newkey = blocknr;
221217c76b01SKoji Sato path[level].bp_ctxt.bh = *bh;
221317c76b01SKoji Sato ret = nilfs_btnode_prepare_change_key(
2214e897be17SRyusuke Konishi NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping,
221517c76b01SKoji Sato &path[level].bp_ctxt);
221617c76b01SKoji Sato if (ret < 0)
221717c76b01SKoji Sato return ret;
221817c76b01SKoji Sato nilfs_btnode_commit_change_key(
2219e897be17SRyusuke Konishi NILFS_BMAP_I(btree)->i_assoc_inode->i_mapping,
222017c76b01SKoji Sato &path[level].bp_ctxt);
222117c76b01SKoji Sato *bh = path[level].bp_ctxt.bh;
222217c76b01SKoji Sato }
222317c76b01SKoji Sato
22249b7b265cSRyusuke Konishi nilfs_btree_node_set_ptr(parent, path[level + 1].bp_index, blocknr,
22259b7b265cSRyusuke Konishi ncmax);
222617c76b01SKoji Sato
22276d28f7eaSRyusuke Konishi key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
222817c76b01SKoji Sato /* on-disk format */
222925b8d7deSRyusuke Konishi binfo->bi_dat.bi_blkoff = cpu_to_le64(key);
223017c76b01SKoji Sato binfo->bi_dat.bi_level = level;
223173970316STetsuo Handa memset(binfo->bi_dat.bi_pad, 0, sizeof(binfo->bi_dat.bi_pad));
223217c76b01SKoji Sato
223317c76b01SKoji Sato return 0;
223417c76b01SKoji Sato }
223517c76b01SKoji Sato
nilfs_btree_assign_v(struct nilfs_bmap * btree,struct nilfs_btree_path * path,int level,struct buffer_head ** bh,sector_t blocknr,union nilfs_binfo * binfo)2236e7c274f8SRyusuke Konishi static int nilfs_btree_assign_v(struct nilfs_bmap *btree,
223717c76b01SKoji Sato struct nilfs_btree_path *path,
223817c76b01SKoji Sato int level,
223917c76b01SKoji Sato struct buffer_head **bh,
224017c76b01SKoji Sato sector_t blocknr,
224117c76b01SKoji Sato union nilfs_binfo *binfo)
224217c76b01SKoji Sato {
224317c76b01SKoji Sato struct nilfs_btree_node *parent;
2244e7c274f8SRyusuke Konishi struct inode *dat = nilfs_bmap_get_dat(btree);
224517c76b01SKoji Sato __u64 key;
224617c76b01SKoji Sato __u64 ptr;
224717c76b01SKoji Sato union nilfs_bmap_ptr_req req;
22489b7b265cSRyusuke Konishi int ncmax, ret;
224917c76b01SKoji Sato
22509b7b265cSRyusuke Konishi parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
22519b7b265cSRyusuke Konishi ptr = nilfs_btree_node_get_ptr(parent, path[level + 1].bp_index,
22529b7b265cSRyusuke Konishi ncmax);
225317c76b01SKoji Sato req.bpr_ptr = ptr;
22542e0c2c73SRyusuke Konishi ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
22552e0c2c73SRyusuke Konishi if (ret < 0)
225617c76b01SKoji Sato return ret;
22572e0c2c73SRyusuke Konishi nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
225817c76b01SKoji Sato
22596d28f7eaSRyusuke Konishi key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
226017c76b01SKoji Sato /* on-disk format */
226125b8d7deSRyusuke Konishi binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr);
226225b8d7deSRyusuke Konishi binfo->bi_v.bi_blkoff = cpu_to_le64(key);
226317c76b01SKoji Sato
226417c76b01SKoji Sato return 0;
226517c76b01SKoji Sato }
226617c76b01SKoji Sato
nilfs_btree_assign(struct nilfs_bmap * btree,struct buffer_head ** bh,sector_t blocknr,union nilfs_binfo * binfo)2267e7c274f8SRyusuke Konishi static int nilfs_btree_assign(struct nilfs_bmap *btree,
226817c76b01SKoji Sato struct buffer_head **bh,
226917c76b01SKoji Sato sector_t blocknr,
227017c76b01SKoji Sato union nilfs_binfo *binfo)
227117c76b01SKoji Sato {
227217c76b01SKoji Sato struct nilfs_btree_path *path;
227317c76b01SKoji Sato struct nilfs_btree_node *node;
227417c76b01SKoji Sato __u64 key;
227517c76b01SKoji Sato int level, ret;
227617c76b01SKoji Sato
22776d28f7eaSRyusuke Konishi path = nilfs_btree_alloc_path();
227817c76b01SKoji Sato if (path == NULL)
227917c76b01SKoji Sato return -ENOMEM;
228017c76b01SKoji Sato
228117c76b01SKoji Sato if (buffer_nilfs_node(*bh)) {
228217c76b01SKoji Sato node = (struct nilfs_btree_node *)(*bh)->b_data;
22836d28f7eaSRyusuke Konishi key = nilfs_btree_node_get_key(node, 0);
22846d28f7eaSRyusuke Konishi level = nilfs_btree_node_get_level(node);
228517c76b01SKoji Sato } else {
2286e7c274f8SRyusuke Konishi key = nilfs_bmap_data_get_key(btree, *bh);
228717c76b01SKoji Sato level = NILFS_BTREE_LEVEL_DATA;
228817c76b01SKoji Sato }
228917c76b01SKoji Sato
229003bdb5acSRyusuke Konishi ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1, 0);
229117c76b01SKoji Sato if (ret < 0) {
22921f5abe7eSRyusuke Konishi WARN_ON(ret == -ENOENT);
229317c76b01SKoji Sato goto out;
229417c76b01SKoji Sato }
229517c76b01SKoji Sato
2296e7c274f8SRyusuke Konishi ret = NILFS_BMAP_USE_VBN(btree) ?
22977cde31d7SRyusuke Konishi nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) :
22987cde31d7SRyusuke Konishi nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
229917c76b01SKoji Sato
230017c76b01SKoji Sato out:
23016d28f7eaSRyusuke Konishi nilfs_btree_free_path(path);
230217c76b01SKoji Sato
230317c76b01SKoji Sato return ret;
230417c76b01SKoji Sato }
230517c76b01SKoji Sato
nilfs_btree_assign_gc(struct nilfs_bmap * btree,struct buffer_head ** bh,sector_t blocknr,union nilfs_binfo * binfo)2306e7c274f8SRyusuke Konishi static int nilfs_btree_assign_gc(struct nilfs_bmap *btree,
230717c76b01SKoji Sato struct buffer_head **bh,
230817c76b01SKoji Sato sector_t blocknr,
230917c76b01SKoji Sato union nilfs_binfo *binfo)
231017c76b01SKoji Sato {
231117c76b01SKoji Sato struct nilfs_btree_node *node;
231217c76b01SKoji Sato __u64 key;
231317c76b01SKoji Sato int ret;
231417c76b01SKoji Sato
2315e7c274f8SRyusuke Konishi ret = nilfs_dat_move(nilfs_bmap_get_dat(btree), (*bh)->b_blocknr,
23162e0c2c73SRyusuke Konishi blocknr);
231717c76b01SKoji Sato if (ret < 0)
231817c76b01SKoji Sato return ret;
231917c76b01SKoji Sato
232017c76b01SKoji Sato if (buffer_nilfs_node(*bh)) {
232117c76b01SKoji Sato node = (struct nilfs_btree_node *)(*bh)->b_data;
23226d28f7eaSRyusuke Konishi key = nilfs_btree_node_get_key(node, 0);
232317c76b01SKoji Sato } else
2324e7c274f8SRyusuke Konishi key = nilfs_bmap_data_get_key(btree, *bh);
232517c76b01SKoji Sato
232617c76b01SKoji Sato /* on-disk format */
232717c76b01SKoji Sato binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr);
232825b8d7deSRyusuke Konishi binfo->bi_v.bi_blkoff = cpu_to_le64(key);
232917c76b01SKoji Sato
233017c76b01SKoji Sato return 0;
233117c76b01SKoji Sato }
233217c76b01SKoji Sato
nilfs_btree_mark(struct nilfs_bmap * btree,__u64 key,int level)2333e7c274f8SRyusuke Konishi static int nilfs_btree_mark(struct nilfs_bmap *btree, __u64 key, int level)
233417c76b01SKoji Sato {
233517c76b01SKoji Sato struct buffer_head *bh;
233617c76b01SKoji Sato struct nilfs_btree_path *path;
233717c76b01SKoji Sato __u64 ptr;
233817c76b01SKoji Sato int ret;
233917c76b01SKoji Sato
23406d28f7eaSRyusuke Konishi path = nilfs_btree_alloc_path();
234117c76b01SKoji Sato if (path == NULL)
234217c76b01SKoji Sato return -ENOMEM;
234317c76b01SKoji Sato
234403bdb5acSRyusuke Konishi ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1, 0);
234517c76b01SKoji Sato if (ret < 0) {
23461f5abe7eSRyusuke Konishi WARN_ON(ret == -ENOENT);
234717c76b01SKoji Sato goto out;
234817c76b01SKoji Sato }
2349f198dbb9SRyusuke Konishi ret = nilfs_btree_get_block(btree, ptr, &bh);
235017c76b01SKoji Sato if (ret < 0) {
23511f5abe7eSRyusuke Konishi WARN_ON(ret == -ENOENT);
235217c76b01SKoji Sato goto out;
235317c76b01SKoji Sato }
235417c76b01SKoji Sato
235517c76b01SKoji Sato if (!buffer_dirty(bh))
23565fc7b141SRyusuke Konishi mark_buffer_dirty(bh);
2357087d01b4SRyusuke Konishi brelse(bh);
2358e7c274f8SRyusuke Konishi if (!nilfs_bmap_dirty(btree))
2359e7c274f8SRyusuke Konishi nilfs_bmap_set_dirty(btree);
236017c76b01SKoji Sato
236117c76b01SKoji Sato out:
23626d28f7eaSRyusuke Konishi nilfs_btree_free_path(path);
236317c76b01SKoji Sato return ret;
236417c76b01SKoji Sato }
236517c76b01SKoji Sato
236617c76b01SKoji Sato static const struct nilfs_bmap_operations nilfs_btree_ops = {
236717c76b01SKoji Sato .bop_lookup = nilfs_btree_lookup,
2368c3a7abf0SRyusuke Konishi .bop_lookup_contig = nilfs_btree_lookup_contig,
236917c76b01SKoji Sato .bop_insert = nilfs_btree_insert,
237017c76b01SKoji Sato .bop_delete = nilfs_btree_delete,
237117c76b01SKoji Sato .bop_clear = NULL,
237217c76b01SKoji Sato
237317c76b01SKoji Sato .bop_propagate = nilfs_btree_propagate,
237417c76b01SKoji Sato
237517c76b01SKoji Sato .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
237617c76b01SKoji Sato
237717c76b01SKoji Sato .bop_assign = nilfs_btree_assign,
237817c76b01SKoji Sato .bop_mark = nilfs_btree_mark,
237917c76b01SKoji Sato
23805b20384fSRyusuke Konishi .bop_seek_key = nilfs_btree_seek_key,
238117c76b01SKoji Sato .bop_last_key = nilfs_btree_last_key,
23825b20384fSRyusuke Konishi
238317c76b01SKoji Sato .bop_check_insert = NULL,
238417c76b01SKoji Sato .bop_check_delete = nilfs_btree_check_delete,
238517c76b01SKoji Sato .bop_gather_data = nilfs_btree_gather_data,
238617c76b01SKoji Sato };
238717c76b01SKoji Sato
238817c76b01SKoji Sato static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
238917c76b01SKoji Sato .bop_lookup = NULL,
2390c3a7abf0SRyusuke Konishi .bop_lookup_contig = NULL,
239117c76b01SKoji Sato .bop_insert = NULL,
239217c76b01SKoji Sato .bop_delete = NULL,
239317c76b01SKoji Sato .bop_clear = NULL,
239417c76b01SKoji Sato
239517c76b01SKoji Sato .bop_propagate = nilfs_btree_propagate_gc,
239617c76b01SKoji Sato
239717c76b01SKoji Sato .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
239817c76b01SKoji Sato
239917c76b01SKoji Sato .bop_assign = nilfs_btree_assign_gc,
240017c76b01SKoji Sato .bop_mark = NULL,
240117c76b01SKoji Sato
24025b20384fSRyusuke Konishi .bop_seek_key = NULL,
240317c76b01SKoji Sato .bop_last_key = NULL,
24045b20384fSRyusuke Konishi
240517c76b01SKoji Sato .bop_check_insert = NULL,
240617c76b01SKoji Sato .bop_check_delete = NULL,
240717c76b01SKoji Sato .bop_gather_data = NULL,
240817c76b01SKoji Sato };
240917c76b01SKoji Sato
__nilfs_btree_init(struct nilfs_bmap * bmap)2410957ed60bSRyusuke Konishi static void __nilfs_btree_init(struct nilfs_bmap *bmap)
241117c76b01SKoji Sato {
241217c76b01SKoji Sato bmap->b_ops = &nilfs_btree_ops;
24135ad2686eSRyusuke Konishi bmap->b_nchildren_per_block =
24145ad2686eSRyusuke Konishi NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap));
2415957ed60bSRyusuke Konishi }
2416957ed60bSRyusuke Konishi
nilfs_btree_init(struct nilfs_bmap * bmap)2417957ed60bSRyusuke Konishi int nilfs_btree_init(struct nilfs_bmap *bmap)
2418957ed60bSRyusuke Konishi {
2419957ed60bSRyusuke Konishi int ret = 0;
2420957ed60bSRyusuke Konishi
2421957ed60bSRyusuke Konishi __nilfs_btree_init(bmap);
2422957ed60bSRyusuke Konishi
2423feee880fSRyusuke Konishi if (nilfs_btree_root_broken(nilfs_btree_get_root(bmap), bmap->b_inode))
2424957ed60bSRyusuke Konishi ret = -EIO;
2425e897be17SRyusuke Konishi else
2426e897be17SRyusuke Konishi ret = nilfs_attach_btree_node_cache(
2427e897be17SRyusuke Konishi &NILFS_BMAP_I(bmap)->vfs_inode);
2428e897be17SRyusuke Konishi
2429957ed60bSRyusuke Konishi return ret;
243017c76b01SKoji Sato }
243117c76b01SKoji Sato
nilfs_btree_init_gc(struct nilfs_bmap * bmap)243217c76b01SKoji Sato void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
243317c76b01SKoji Sato {
243417c76b01SKoji Sato bmap->b_ops = &nilfs_btree_ops_gc;
24355ad2686eSRyusuke Konishi bmap->b_nchildren_per_block =
24365ad2686eSRyusuke Konishi NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap));
243717c76b01SKoji Sato }
2438