blob: ecdbae19a766d914e7d68c005c14356455dc83af [file] [log] [blame]
Koji Sato17c76b02009-04-06 19:01:24 -07001/*
2 * btree.c - NILFS B-tree.
3 *
4 * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 * Written by Koji Sato <koji@osrg.net>.
21 */
22
23#include <linux/slab.h>
24#include <linux/string.h>
25#include <linux/errno.h>
26#include <linux/pagevec.h>
27#include "nilfs.h"
28#include "page.h"
29#include "btnode.h"
30#include "btree.h"
31#include "alloc.h"
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +090032#include "dat.h"
Koji Sato17c76b02009-04-06 19:01:24 -070033
Ryusuke Konishi957ed602015-02-27 15:51:56 -080034static void __nilfs_btree_init(struct nilfs_bmap *bmap);
35
Li Hongf9054402010-04-02 17:36:34 +080036static struct nilfs_btree_path *nilfs_btree_alloc_path(void)
Koji Sato17c76b02009-04-06 19:01:24 -070037{
Li Hongf9054402010-04-02 17:36:34 +080038 struct nilfs_btree_path *path;
39 int level = NILFS_BTREE_LEVEL_DATA;
Koji Sato17c76b02009-04-06 19:01:24 -070040
Li Hongf9054402010-04-02 17:36:34 +080041 path = kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS);
42 if (path == NULL)
43 goto out;
Koji Sato17c76b02009-04-06 19:01:24 -070044
Li Hongf9054402010-04-02 17:36:34 +080045 for (; level < NILFS_BTREE_LEVEL_MAX; level++) {
Koji Sato17c76b02009-04-06 19:01:24 -070046 path[level].bp_bh = NULL;
47 path[level].bp_sib_bh = NULL;
48 path[level].bp_index = 0;
49 path[level].bp_oldreq.bpr_ptr = NILFS_BMAP_INVALID_PTR;
50 path[level].bp_newreq.bpr_ptr = NILFS_BMAP_INVALID_PTR;
51 path[level].bp_op = NULL;
52 }
Li Hongf9054402010-04-02 17:36:34 +080053
54out:
55 return path;
56}
57
Li Hong73bb4882010-04-02 18:35:00 +080058static void nilfs_btree_free_path(struct nilfs_btree_path *path)
Li Hongf9054402010-04-02 17:36:34 +080059{
Li Hong73bb4882010-04-02 18:35:00 +080060 int level = NILFS_BTREE_LEVEL_DATA;
Koji Sato17c76b02009-04-06 19:01:24 -070061
Li Hong73bb4882010-04-02 18:35:00 +080062 for (; level < NILFS_BTREE_LEVEL_MAX; level++)
Ryusuke Konishi32189292009-08-15 01:54:59 +090063 brelse(path[level].bp_bh);
Li Hong73bb4882010-04-02 18:35:00 +080064
65 kmem_cache_free(nilfs_btree_path_cache, path);
Koji Sato17c76b02009-04-06 19:01:24 -070066}
67
Koji Sato17c76b02009-04-06 19:01:24 -070068/*
69 * B-tree node operations
70 */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +090071static int nilfs_btree_get_new_block(const struct nilfs_bmap *btree,
Ryusuke Konishif198dbb2009-05-22 01:07:13 +090072 __u64 ptr, struct buffer_head **bhp)
73{
Ryusuke Konishie7c274f2010-07-10 19:09:49 +090074 struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache;
Ryusuke Konishi45f49102009-11-13 16:25:19 +090075 struct buffer_head *bh;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +090076
Ryusuke Konishi45f49102009-11-13 16:25:19 +090077 bh = nilfs_btnode_create_block(btnc, ptr);
78 if (!bh)
79 return -ENOMEM;
80
81 set_buffer_nilfs_volatile(bh);
82 *bhp = bh;
83 return 0;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +090084}
Koji Sato17c76b02009-04-06 19:01:24 -070085
Ryusuke Konishi7c397a82010-07-13 23:33:55 +090086static int nilfs_btree_node_get_flags(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -070087{
88 return node->bn_flags;
89}
90
Ryusuke Konishi7c397a82010-07-13 23:33:55 +090091static void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +090092nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags)
Koji Sato17c76b02009-04-06 19:01:24 -070093{
94 node->bn_flags = flags;
95}
96
Ryusuke Konishi7c397a82010-07-13 23:33:55 +090097static int nilfs_btree_node_root(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -070098{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +090099 return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT;
Koji Sato17c76b02009-04-06 19:01:24 -0700100}
101
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900102static int nilfs_btree_node_get_level(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700103{
104 return node->bn_level;
105}
106
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900107static void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900108nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700109{
110 node->bn_level = level;
111}
112
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900113static int nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700114{
115 return le16_to_cpu(node->bn_nchildren);
116}
117
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900118static void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900119nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren)
Koji Sato17c76b02009-04-06 19:01:24 -0700120{
121 node->bn_nchildren = cpu_to_le16(nchildren);
122}
123
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900124static int nilfs_btree_node_size(const struct nilfs_bmap *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700125{
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900126 return 1 << btree->b_inode->i_blkbits;
Koji Sato17c76b02009-04-06 19:01:24 -0700127}
128
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900129static int nilfs_btree_nchildren_per_block(const struct nilfs_bmap *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700130{
Ryusuke Konishi5ad2686e92010-07-13 23:33:54 +0900131 return btree->b_nchildren_per_block;
Koji Sato17c76b02009-04-06 19:01:24 -0700132}
133
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900134static __le64 *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900135nilfs_btree_node_dkeys(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700136{
137 return (__le64 *)((char *)(node + 1) +
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900138 (nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700139 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE));
140}
141
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900142static __le64 *
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900143nilfs_btree_node_dptrs(const struct nilfs_btree_node *node, int ncmax)
Koji Sato17c76b02009-04-06 19:01:24 -0700144{
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900145 return (__le64 *)(nilfs_btree_node_dkeys(node) + ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -0700146}
147
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900148static __u64
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900149nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index)
Koji Sato17c76b02009-04-06 19:01:24 -0700150{
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900151 return le64_to_cpu(*(nilfs_btree_node_dkeys(node) + index));
Koji Sato17c76b02009-04-06 19:01:24 -0700152}
153
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900154static void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900155nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key)
Koji Sato17c76b02009-04-06 19:01:24 -0700156{
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900157 *(nilfs_btree_node_dkeys(node) + index) = cpu_to_le64(key);
Koji Sato17c76b02009-04-06 19:01:24 -0700158}
159
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900160static __u64
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900161nilfs_btree_node_get_ptr(const struct nilfs_btree_node *node, int index,
162 int ncmax)
Koji Sato17c76b02009-04-06 19:01:24 -0700163{
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900164 return le64_to_cpu(*(nilfs_btree_node_dptrs(node, ncmax) + index));
Koji Sato17c76b02009-04-06 19:01:24 -0700165}
166
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900167static void
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900168nilfs_btree_node_set_ptr(struct nilfs_btree_node *node, int index, __u64 ptr,
169 int ncmax)
Koji Sato17c76b02009-04-06 19:01:24 -0700170{
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900171 *(nilfs_btree_node_dptrs(node, ncmax) + index) = cpu_to_le64(ptr);
Koji Sato17c76b02009-04-06 19:01:24 -0700172}
173
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900174static void nilfs_btree_node_init(struct nilfs_btree_node *node, int flags,
175 int level, int nchildren, int ncmax,
Koji Sato17c76b02009-04-06 19:01:24 -0700176 const __u64 *keys, const __u64 *ptrs)
177{
178 __le64 *dkeys;
179 __le64 *dptrs;
180 int i;
181
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900182 nilfs_btree_node_set_flags(node, flags);
183 nilfs_btree_node_set_level(node, level);
184 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700185
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900186 dkeys = nilfs_btree_node_dkeys(node);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900187 dptrs = nilfs_btree_node_dptrs(node, ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -0700188 for (i = 0; i < nchildren; i++) {
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900189 dkeys[i] = cpu_to_le64(keys[i]);
190 dptrs[i] = cpu_to_le64(ptrs[i]);
Koji Sato17c76b02009-04-06 19:01:24 -0700191 }
192}
193
194/* Assume the buffer heads corresponding to left and right are locked. */
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900195static void nilfs_btree_node_move_left(struct nilfs_btree_node *left,
Koji Sato17c76b02009-04-06 19:01:24 -0700196 struct nilfs_btree_node *right,
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900197 int n, int lncmax, int rncmax)
Koji Sato17c76b02009-04-06 19:01:24 -0700198{
199 __le64 *ldkeys, *rdkeys;
200 __le64 *ldptrs, *rdptrs;
201 int lnchildren, rnchildren;
202
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900203 ldkeys = nilfs_btree_node_dkeys(left);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900204 ldptrs = nilfs_btree_node_dptrs(left, lncmax);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900205 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700206
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900207 rdkeys = nilfs_btree_node_dkeys(right);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900208 rdptrs = nilfs_btree_node_dptrs(right, rncmax);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900209 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700210
211 memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys));
212 memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs));
213 memmove(rdkeys, rdkeys + n, (rnchildren - n) * sizeof(*rdkeys));
214 memmove(rdptrs, rdptrs + n, (rnchildren - n) * sizeof(*rdptrs));
215
216 lnchildren += n;
217 rnchildren -= n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900218 nilfs_btree_node_set_nchildren(left, lnchildren);
219 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700220}
221
222/* Assume that the buffer heads corresponding to left and right are locked. */
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900223static void nilfs_btree_node_move_right(struct nilfs_btree_node *left,
Koji Sato17c76b02009-04-06 19:01:24 -0700224 struct nilfs_btree_node *right,
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900225 int n, int lncmax, int rncmax)
Koji Sato17c76b02009-04-06 19:01:24 -0700226{
227 __le64 *ldkeys, *rdkeys;
228 __le64 *ldptrs, *rdptrs;
229 int lnchildren, rnchildren;
230
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900231 ldkeys = nilfs_btree_node_dkeys(left);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900232 ldptrs = nilfs_btree_node_dptrs(left, lncmax);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900233 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700234
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900235 rdkeys = nilfs_btree_node_dkeys(right);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900236 rdptrs = nilfs_btree_node_dptrs(right, rncmax);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900237 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700238
239 memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys));
240 memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs));
241 memcpy(rdkeys, ldkeys + lnchildren - n, n * sizeof(*rdkeys));
242 memcpy(rdptrs, ldptrs + lnchildren - n, n * sizeof(*rdptrs));
243
244 lnchildren -= n;
245 rnchildren += n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900246 nilfs_btree_node_set_nchildren(left, lnchildren);
247 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700248}
249
250/* Assume that the buffer head corresponding to node is locked. */
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900251static void nilfs_btree_node_insert(struct nilfs_btree_node *node, int index,
252 __u64 key, __u64 ptr, int ncmax)
Koji Sato17c76b02009-04-06 19:01:24 -0700253{
254 __le64 *dkeys;
255 __le64 *dptrs;
256 int nchildren;
257
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900258 dkeys = nilfs_btree_node_dkeys(node);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900259 dptrs = nilfs_btree_node_dptrs(node, ncmax);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900260 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700261 if (index < nchildren) {
262 memmove(dkeys + index + 1, dkeys + index,
263 (nchildren - index) * sizeof(*dkeys));
264 memmove(dptrs + index + 1, dptrs + index,
265 (nchildren - index) * sizeof(*dptrs));
266 }
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900267 dkeys[index] = cpu_to_le64(key);
268 dptrs[index] = cpu_to_le64(ptr);
Koji Sato17c76b02009-04-06 19:01:24 -0700269 nchildren++;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900270 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700271}
272
273/* Assume that the buffer head corresponding to node is locked. */
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900274static void nilfs_btree_node_delete(struct nilfs_btree_node *node, int index,
275 __u64 *keyp, __u64 *ptrp, int ncmax)
Koji Sato17c76b02009-04-06 19:01:24 -0700276{
277 __u64 key;
278 __u64 ptr;
279 __le64 *dkeys;
280 __le64 *dptrs;
281 int nchildren;
282
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900283 dkeys = nilfs_btree_node_dkeys(node);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900284 dptrs = nilfs_btree_node_dptrs(node, ncmax);
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900285 key = le64_to_cpu(dkeys[index]);
286 ptr = le64_to_cpu(dptrs[index]);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900287 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700288 if (keyp != NULL)
289 *keyp = key;
290 if (ptrp != NULL)
291 *ptrp = ptr;
292
293 if (index < nchildren - 1) {
294 memmove(dkeys + index, dkeys + index + 1,
295 (nchildren - index - 1) * sizeof(*dkeys));
296 memmove(dptrs + index, dptrs + index + 1,
297 (nchildren - index - 1) * sizeof(*dptrs));
298 }
299 nchildren--;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900300 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700301}
302
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900303static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node,
Koji Sato17c76b02009-04-06 19:01:24 -0700304 __u64 key, int *indexp)
305{
306 __u64 nkey;
307 int index, low, high, s;
308
309 /* binary search */
310 low = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900311 high = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700312 index = 0;
313 s = 0;
314 while (low <= high) {
315 index = (low + high) / 2;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900316 nkey = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700317 if (nkey == key) {
318 s = 0;
319 goto out;
320 } else if (nkey < key) {
321 low = index + 1;
322 s = -1;
323 } else {
324 high = index - 1;
325 s = 1;
326 }
327 }
328
329 /* adjust index */
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900330 if (nilfs_btree_node_get_level(node) > NILFS_BTREE_LEVEL_NODE_MIN) {
331 if (s > 0 && index > 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700332 index--;
333 } else if (s < 0)
334 index++;
335
336 out:
Koji Sato17c76b02009-04-06 19:01:24 -0700337 *indexp = index;
338
339 return s == 0;
340}
341
Ryusuke Konishi1d5385b2010-07-16 23:52:40 +0900342/**
343 * nilfs_btree_node_broken - verify consistency of btree node
344 * @node: btree node block to be examined
345 * @size: node size (in bytes)
346 * @blocknr: block number
347 *
348 * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned.
349 */
350static int nilfs_btree_node_broken(const struct nilfs_btree_node *node,
351 size_t size, sector_t blocknr)
352{
353 int level, flags, nchildren;
354 int ret = 0;
355
356 level = nilfs_btree_node_get_level(node);
357 flags = nilfs_btree_node_get_flags(node);
358 nchildren = nilfs_btree_node_get_nchildren(node);
359
360 if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
361 level >= NILFS_BTREE_LEVEL_MAX ||
362 (flags & NILFS_BTREE_NODE_ROOT) ||
363 nchildren < 0 ||
364 nchildren > NILFS_BTREE_NODE_NCHILDREN_MAX(size))) {
365 printk(KERN_CRIT "NILFS: bad btree node (blocknr=%llu): "
366 "level = %d, flags = 0x%x, nchildren = %d\n",
367 (unsigned long long)blocknr, level, flags, nchildren);
368 ret = 1;
369 }
370 return ret;
371}
372
Ryusuke Konishi957ed602015-02-27 15:51:56 -0800373/**
374 * nilfs_btree_root_broken - verify consistency of btree root node
375 * @node: btree root node to be examined
376 * @ino: inode number
377 *
378 * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned.
379 */
380static int nilfs_btree_root_broken(const struct nilfs_btree_node *node,
381 unsigned long ino)
382{
383 int level, flags, nchildren;
384 int ret = 0;
385
386 level = nilfs_btree_node_get_level(node);
387 flags = nilfs_btree_node_get_flags(node);
388 nchildren = nilfs_btree_node_get_nchildren(node);
389
390 if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
391 level > NILFS_BTREE_LEVEL_MAX ||
392 nchildren < 0 ||
393 nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) {
394 pr_crit("NILFS: bad btree root (inode number=%lu): level = %d, flags = 0x%x, nchildren = %d\n",
395 ino, level, flags, nchildren);
396 ret = 1;
397 }
398 return ret;
399}
400
Ryusuke Konishi1d5385b2010-07-16 23:52:40 +0900401int nilfs_btree_broken_node_block(struct buffer_head *bh)
402{
Ryusuke Konishi4e13e662010-07-18 10:42:25 +0900403 int ret;
404
405 if (buffer_nilfs_checked(bh))
406 return 0;
407
408 ret = nilfs_btree_node_broken((struct nilfs_btree_node *)bh->b_data,
Ryusuke Konishi1d5385b2010-07-16 23:52:40 +0900409 bh->b_size, bh->b_blocknr);
Ryusuke Konishi4e13e662010-07-18 10:42:25 +0900410 if (likely(!ret))
411 set_buffer_nilfs_checked(bh);
412 return ret;
Ryusuke Konishi1d5385b2010-07-16 23:52:40 +0900413}
414
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900415static struct nilfs_btree_node *
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900416nilfs_btree_get_root(const struct nilfs_bmap *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700417{
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900418 return (struct nilfs_btree_node *)btree->b_u.u_data;
Koji Sato17c76b02009-04-06 19:01:24 -0700419}
420
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900421static struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900422nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700423{
424 return (struct nilfs_btree_node *)path[level].bp_bh->b_data;
425}
426
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900427static struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900428nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700429{
430 return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data;
431}
432
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900433static int nilfs_btree_height(const struct nilfs_bmap *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700434{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900435 return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700436}
437
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900438static struct nilfs_btree_node *
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900439nilfs_btree_get_node(const struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700440 const struct nilfs_btree_path *path,
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900441 int level, int *ncmaxp)
Koji Sato17c76b02009-04-06 19:01:24 -0700442{
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900443 struct nilfs_btree_node *node;
444
445 if (level == nilfs_btree_height(btree) - 1) {
446 node = nilfs_btree_get_root(btree);
447 *ncmaxp = NILFS_BTREE_ROOT_NCHILDREN_MAX;
448 } else {
449 node = nilfs_btree_get_nonroot_node(path, level);
450 *ncmaxp = nilfs_btree_nchildren_per_block(btree);
451 }
452 return node;
Koji Sato17c76b02009-04-06 19:01:24 -0700453}
454
Ryusuke Konishi7c397a82010-07-13 23:33:55 +0900455static int
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900456nilfs_btree_bad_node(struct nilfs_btree_node *node, int level)
457{
458 if (unlikely(nilfs_btree_node_get_level(node) != level)) {
459 dump_stack();
460 printk(KERN_CRIT "NILFS: btree level mismatch: %d != %d\n",
461 nilfs_btree_node_get_level(node), level);
462 return 1;
463 }
464 return 0;
465}
466
Ryusuke Konishi464ece82010-07-18 10:42:24 +0900467struct nilfs_btree_readahead_info {
468 struct nilfs_btree_node *node; /* parent node */
469 int max_ra_blocks; /* max nof blocks to read ahead */
470 int index; /* current index on the parent node */
471 int ncmax; /* nof children in the parent node */
472};
473
474static int __nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr,
475 struct buffer_head **bhp,
476 const struct nilfs_btree_readahead_info *ra)
477{
478 struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache;
479 struct buffer_head *bh, *ra_bh;
480 sector_t submit_ptr = 0;
481 int ret;
482
483 ret = nilfs_btnode_submit_block(btnc, ptr, 0, READ, &bh, &submit_ptr);
484 if (ret) {
485 if (ret != -EEXIST)
486 return ret;
487 goto out_check;
488 }
489
490 if (ra) {
491 int i, n;
492 __u64 ptr2;
493
494 /* read ahead sibling nodes */
495 for (n = ra->max_ra_blocks, i = ra->index + 1;
496 n > 0 && i < ra->ncmax; n--, i++) {
497 ptr2 = nilfs_btree_node_get_ptr(ra->node, i, ra->ncmax);
498
499 ret = nilfs_btnode_submit_block(btnc, ptr2, 0, READA,
500 &ra_bh, &submit_ptr);
501 if (likely(!ret || ret == -EEXIST))
502 brelse(ra_bh);
503 else if (ret != -EBUSY)
504 break;
505 if (!buffer_locked(bh))
506 goto out_no_wait;
507 }
508 }
509
510 wait_on_buffer(bh);
511
512 out_no_wait:
513 if (!buffer_uptodate(bh)) {
514 brelse(bh);
515 return -EIO;
516 }
517
518 out_check:
519 if (nilfs_btree_broken_node_block(bh)) {
520 clear_buffer_uptodate(bh);
521 brelse(bh);
522 return -EINVAL;
523 }
524
525 *bhp = bh;
526 return 0;
527}
528
529static int nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr,
530 struct buffer_head **bhp)
531{
532 return __nilfs_btree_get_block(btree, ptr, bhp, NULL);
533}
534
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900535static int nilfs_btree_do_lookup(const struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700536 struct nilfs_btree_path *path,
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +0900537 __u64 key, __u64 *ptrp, int minlevel,
538 int readahead)
Koji Sato17c76b02009-04-06 19:01:24 -0700539{
540 struct nilfs_btree_node *node;
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +0900541 struct nilfs_btree_readahead_info p, *ra;
Koji Sato17c76b02009-04-06 19:01:24 -0700542 __u64 ptr;
Ryusuke Konishiea64ab82010-07-13 23:33:52 +0900543 int level, index, found, ncmax, ret;
Koji Sato17c76b02009-04-06 19:01:24 -0700544
Koji Sato17c76b02009-04-06 19:01:24 -0700545 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900546 level = nilfs_btree_node_get_level(node);
547 if (level < minlevel || nilfs_btree_node_get_nchildren(node) <= 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700548 return -ENOENT;
549
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900550 found = nilfs_btree_node_lookup(node, key, &index);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900551 ptr = nilfs_btree_node_get_ptr(node, index,
552 NILFS_BTREE_ROOT_NCHILDREN_MAX);
Koji Sato17c76b02009-04-06 19:01:24 -0700553 path[level].bp_bh = NULL;
554 path[level].bp_index = index;
555
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900556 ncmax = nilfs_btree_nchildren_per_block(btree);
Ryusuke Konishiea64ab82010-07-13 23:33:52 +0900557
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +0900558 while (--level >= minlevel) {
559 ra = NULL;
560 if (level == NILFS_BTREE_LEVEL_NODE_MIN && readahead) {
561 p.node = nilfs_btree_get_node(btree, path, level + 1,
562 &p.ncmax);
563 p.index = index;
564 p.max_ra_blocks = 7;
565 ra = &p;
566 }
567 ret = __nilfs_btree_get_block(btree, ptr, &path[level].bp_bh,
568 ra);
Koji Sato17c76b02009-04-06 19:01:24 -0700569 if (ret < 0)
570 return ret;
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +0900571
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900572 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900573 if (nilfs_btree_bad_node(node, level))
574 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -0700575 if (!found)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900576 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700577 else
578 index = 0;
Ryusuke Konishiea64ab82010-07-13 23:33:52 +0900579 if (index < ncmax) {
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900580 ptr = nilfs_btree_node_get_ptr(node, index, ncmax);
Ryusuke Konishiea64ab82010-07-13 23:33:52 +0900581 } else {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700582 WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN);
Koji Sato17c76b02009-04-06 19:01:24 -0700583 /* insert */
584 ptr = NILFS_BMAP_INVALID_PTR;
585 }
586 path[level].bp_index = index;
587 }
588 if (!found)
589 return -ENOENT;
590
591 if (ptrp != NULL)
592 *ptrp = ptr;
593
594 return 0;
595}
596
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900597static int nilfs_btree_do_lookup_last(const struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700598 struct nilfs_btree_path *path,
599 __u64 *keyp, __u64 *ptrp)
600{
601 struct nilfs_btree_node *node;
602 __u64 ptr;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900603 int index, level, ncmax, ret;
Koji Sato17c76b02009-04-06 19:01:24 -0700604
605 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900606 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700607 if (index < 0)
608 return -ENOENT;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900609 level = nilfs_btree_node_get_level(node);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900610 ptr = nilfs_btree_node_get_ptr(node, index,
611 NILFS_BTREE_ROOT_NCHILDREN_MAX);
Koji Sato17c76b02009-04-06 19:01:24 -0700612 path[level].bp_bh = NULL;
613 path[level].bp_index = index;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900614 ncmax = nilfs_btree_nchildren_per_block(btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700615
616 for (level--; level > 0; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900617 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700618 if (ret < 0)
619 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900620 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900621 if (nilfs_btree_bad_node(node, level))
622 return -EINVAL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900623 index = nilfs_btree_node_get_nchildren(node) - 1;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900624 ptr = nilfs_btree_node_get_ptr(node, index, ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -0700625 path[level].bp_index = index;
626 }
627
628 if (keyp != NULL)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900629 *keyp = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700630 if (ptrp != NULL)
631 *ptrp = ptr;
632
633 return 0;
634}
635
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900636static int nilfs_btree_lookup(const struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700637 __u64 key, int level, __u64 *ptrp)
638{
Koji Sato17c76b02009-04-06 19:01:24 -0700639 struct nilfs_btree_path *path;
Koji Sato17c76b02009-04-06 19:01:24 -0700640 int ret;
641
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900642 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -0700643 if (path == NULL)
644 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -0700645
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +0900646 ret = nilfs_btree_do_lookup(btree, path, key, ptrp, level, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700647
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900648 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -0700649
650 return ret;
651}
652
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900653static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900654 __u64 key, __u64 *ptrp, unsigned maxblocks)
655{
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900656 struct nilfs_btree_path *path;
657 struct nilfs_btree_node *node;
658 struct inode *dat = NULL;
659 __u64 ptr, ptr2;
660 sector_t blocknr;
661 int level = NILFS_BTREE_LEVEL_NODE_MIN;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900662 int ret, cnt, index, maxlevel, ncmax;
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +0900663 struct nilfs_btree_readahead_info p;
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900664
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900665 path = nilfs_btree_alloc_path();
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900666 if (path == NULL)
667 return -ENOMEM;
Li Hongf9054402010-04-02 17:36:34 +0800668
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +0900669 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level, 1);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900670 if (ret < 0)
671 goto out;
672
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900673 if (NILFS_BMAP_USE_VBN(btree)) {
674 dat = nilfs_bmap_get_dat(btree);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900675 ret = nilfs_dat_translate(dat, ptr, &blocknr);
676 if (ret < 0)
677 goto out;
678 ptr = blocknr;
679 }
680 cnt = 1;
681 if (cnt == maxblocks)
682 goto end;
683
684 maxlevel = nilfs_btree_height(btree) - 1;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900685 node = nilfs_btree_get_node(btree, path, level, &ncmax);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900686 index = path[level].bp_index + 1;
687 for (;;) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900688 while (index < nilfs_btree_node_get_nchildren(node)) {
689 if (nilfs_btree_node_get_key(node, index) !=
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900690 key + cnt)
691 goto end;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900692 ptr2 = nilfs_btree_node_get_ptr(node, index, ncmax);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900693 if (dat) {
694 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
695 if (ret < 0)
696 goto out;
697 ptr2 = blocknr;
698 }
699 if (ptr2 != ptr + cnt || ++cnt == maxblocks)
700 goto end;
701 index++;
702 continue;
703 }
704 if (level == maxlevel)
705 break;
706
707 /* look-up right sibling node */
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +0900708 p.node = nilfs_btree_get_node(btree, path, level + 1, &p.ncmax);
709 p.index = path[level + 1].bp_index + 1;
710 p.max_ra_blocks = 7;
711 if (p.index >= nilfs_btree_node_get_nchildren(p.node) ||
712 nilfs_btree_node_get_key(p.node, p.index) != key + cnt)
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900713 break;
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +0900714 ptr2 = nilfs_btree_node_get_ptr(p.node, p.index, p.ncmax);
715 path[level + 1].bp_index = p.index;
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900716
717 brelse(path[level].bp_bh);
718 path[level].bp_bh = NULL;
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +0900719
720 ret = __nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh,
721 &p);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900722 if (ret < 0)
723 goto out;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900724 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900725 ncmax = nilfs_btree_nchildren_per_block(btree);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900726 index = 0;
727 path[level].bp_index = index;
728 }
729 end:
730 *ptrp = ptr;
731 ret = cnt;
732 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900733 nilfs_btree_free_path(path);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900734 return ret;
735}
736
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900737static void nilfs_btree_promote_key(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700738 struct nilfs_btree_path *path,
739 int level, __u64 key)
740{
741 if (level < nilfs_btree_height(btree) - 1) {
742 do {
Koji Sato17c76b02009-04-06 19:01:24 -0700743 nilfs_btree_node_set_key(
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900744 nilfs_btree_get_nonroot_node(path, level),
Koji Sato17c76b02009-04-06 19:01:24 -0700745 path[level].bp_index, key);
746 if (!buffer_dirty(path[level].bp_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +0900747 mark_buffer_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700748 } while ((path[level].bp_index == 0) &&
749 (++level < nilfs_btree_height(btree) - 1));
750 }
751
752 /* root */
753 if (level == nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900754 nilfs_btree_node_set_key(nilfs_btree_get_root(btree),
Koji Sato17c76b02009-04-06 19:01:24 -0700755 path[level].bp_index, key);
756 }
757}
758
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900759static void nilfs_btree_do_insert(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700760 struct nilfs_btree_path *path,
761 int level, __u64 *keyp, __u64 *ptrp)
762{
763 struct nilfs_btree_node *node;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900764 int ncblk;
Koji Sato17c76b02009-04-06 19:01:24 -0700765
766 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900767 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900768 ncblk = nilfs_btree_nchildren_per_block(btree);
769 nilfs_btree_node_insert(node, path[level].bp_index,
770 *keyp, *ptrp, ncblk);
Koji Sato17c76b02009-04-06 19:01:24 -0700771 if (!buffer_dirty(path[level].bp_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +0900772 mark_buffer_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700773
774 if (path[level].bp_index == 0)
775 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900776 nilfs_btree_node_get_key(node,
777 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700778 } else {
779 node = nilfs_btree_get_root(btree);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900780 nilfs_btree_node_insert(node, path[level].bp_index,
781 *keyp, *ptrp,
782 NILFS_BTREE_ROOT_NCHILDREN_MAX);
Koji Sato17c76b02009-04-06 19:01:24 -0700783 }
784}
785
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900786static void nilfs_btree_carry_left(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700787 struct nilfs_btree_path *path,
788 int level, __u64 *keyp, __u64 *ptrp)
789{
790 struct nilfs_btree_node *node, *left;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900791 int nchildren, lnchildren, n, move, ncblk;
Koji Sato17c76b02009-04-06 19:01:24 -0700792
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900793 node = nilfs_btree_get_nonroot_node(path, level);
794 left = nilfs_btree_get_sib_node(path, level);
795 nchildren = nilfs_btree_node_get_nchildren(node);
796 lnchildren = nilfs_btree_node_get_nchildren(left);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900797 ncblk = nilfs_btree_nchildren_per_block(btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700798 move = 0;
799
800 n = (nchildren + lnchildren + 1) / 2 - lnchildren;
801 if (n > path[level].bp_index) {
802 /* move insert point */
803 n--;
804 move = 1;
805 }
806
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900807 nilfs_btree_node_move_left(left, node, n, ncblk, ncblk);
Koji Sato17c76b02009-04-06 19:01:24 -0700808
809 if (!buffer_dirty(path[level].bp_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +0900810 mark_buffer_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700811 if (!buffer_dirty(path[level].bp_sib_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +0900812 mark_buffer_dirty(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700813
Koji Sato17c76b02009-04-06 19:01:24 -0700814 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900815 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700816
817 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900818 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700819 path[level].bp_bh = path[level].bp_sib_bh;
820 path[level].bp_sib_bh = NULL;
821 path[level].bp_index += lnchildren;
822 path[level + 1].bp_index--;
823 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900824 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700825 path[level].bp_sib_bh = NULL;
826 path[level].bp_index -= n;
827 }
828
829 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
830}
831
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900832static void nilfs_btree_carry_right(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700833 struct nilfs_btree_path *path,
834 int level, __u64 *keyp, __u64 *ptrp)
835{
836 struct nilfs_btree_node *node, *right;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900837 int nchildren, rnchildren, n, move, ncblk;
Koji Sato17c76b02009-04-06 19:01:24 -0700838
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900839 node = nilfs_btree_get_nonroot_node(path, level);
840 right = nilfs_btree_get_sib_node(path, level);
841 nchildren = nilfs_btree_node_get_nchildren(node);
842 rnchildren = nilfs_btree_node_get_nchildren(right);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900843 ncblk = nilfs_btree_nchildren_per_block(btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700844 move = 0;
845
846 n = (nchildren + rnchildren + 1) / 2 - rnchildren;
847 if (n > nchildren - path[level].bp_index) {
848 /* move insert point */
849 n--;
850 move = 1;
851 }
852
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900853 nilfs_btree_node_move_right(node, right, n, ncblk, ncblk);
Koji Sato17c76b02009-04-06 19:01:24 -0700854
855 if (!buffer_dirty(path[level].bp_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +0900856 mark_buffer_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700857 if (!buffer_dirty(path[level].bp_sib_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +0900858 mark_buffer_dirty(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700859
Koji Sato17c76b02009-04-06 19:01:24 -0700860 path[level + 1].bp_index++;
861 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900862 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700863 path[level + 1].bp_index--;
864
865 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900866 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700867 path[level].bp_bh = path[level].bp_sib_bh;
868 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900869 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700870 path[level + 1].bp_index++;
871 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900872 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700873 path[level].bp_sib_bh = NULL;
874 }
875
876 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
877}
878
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900879static void nilfs_btree_split(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700880 struct nilfs_btree_path *path,
881 int level, __u64 *keyp, __u64 *ptrp)
882{
883 struct nilfs_btree_node *node, *right;
884 __u64 newkey;
885 __u64 newptr;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900886 int nchildren, n, move, ncblk;
Koji Sato17c76b02009-04-06 19:01:24 -0700887
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900888 node = nilfs_btree_get_nonroot_node(path, level);
889 right = nilfs_btree_get_sib_node(path, level);
890 nchildren = nilfs_btree_node_get_nchildren(node);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900891 ncblk = nilfs_btree_nchildren_per_block(btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700892 move = 0;
893
894 n = (nchildren + 1) / 2;
895 if (n > nchildren - path[level].bp_index) {
896 n--;
897 move = 1;
898 }
899
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900900 nilfs_btree_node_move_right(node, right, n, ncblk, ncblk);
Koji Sato17c76b02009-04-06 19:01:24 -0700901
902 if (!buffer_dirty(path[level].bp_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +0900903 mark_buffer_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700904 if (!buffer_dirty(path[level].bp_sib_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +0900905 mark_buffer_dirty(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700906
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900907 newkey = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700908 newptr = path[level].bp_newreq.bpr_ptr;
909
910 if (move) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900911 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900912 nilfs_btree_node_insert(right, path[level].bp_index,
913 *keyp, *ptrp, ncblk);
Koji Sato17c76b02009-04-06 19:01:24 -0700914
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900915 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700916 *ptrp = path[level].bp_newreq.bpr_ptr;
917
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900918 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700919 path[level].bp_bh = path[level].bp_sib_bh;
920 path[level].bp_sib_bh = NULL;
921 } else {
922 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
923
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900924 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700925 *ptrp = path[level].bp_newreq.bpr_ptr;
926
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900927 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700928 path[level].bp_sib_bh = NULL;
929 }
930
931 path[level + 1].bp_index++;
932}
933
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900934static void nilfs_btree_grow(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700935 struct nilfs_btree_path *path,
936 int level, __u64 *keyp, __u64 *ptrp)
937{
938 struct nilfs_btree_node *root, *child;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900939 int n, ncblk;
Koji Sato17c76b02009-04-06 19:01:24 -0700940
Koji Sato17c76b02009-04-06 19:01:24 -0700941 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900942 child = nilfs_btree_get_sib_node(path, level);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900943 ncblk = nilfs_btree_nchildren_per_block(btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700944
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900945 n = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -0700946
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900947 nilfs_btree_node_move_right(root, child, n,
948 NILFS_BTREE_ROOT_NCHILDREN_MAX, ncblk);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900949 nilfs_btree_node_set_level(root, level + 1);
Koji Sato17c76b02009-04-06 19:01:24 -0700950
951 if (!buffer_dirty(path[level].bp_sib_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +0900952 mark_buffer_dirty(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700953
Koji Sato17c76b02009-04-06 19:01:24 -0700954 path[level].bp_bh = path[level].bp_sib_bh;
955 path[level].bp_sib_bh = NULL;
956
957 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
958
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900959 *keyp = nilfs_btree_node_get_key(child, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700960 *ptrp = path[level].bp_newreq.bpr_ptr;
961}
962
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900963static __u64 nilfs_btree_find_near(const struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700964 const struct nilfs_btree_path *path)
965{
966 struct nilfs_btree_node *node;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900967 int level, ncmax;
Koji Sato17c76b02009-04-06 19:01:24 -0700968
969 if (path == NULL)
970 return NILFS_BMAP_INVALID_PTR;
971
972 /* left sibling */
973 level = NILFS_BTREE_LEVEL_NODE_MIN;
974 if (path[level].bp_index > 0) {
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900975 node = nilfs_btree_get_node(btree, path, level, &ncmax);
976 return nilfs_btree_node_get_ptr(node,
977 path[level].bp_index - 1,
978 ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -0700979 }
980
981 /* parent */
982 level = NILFS_BTREE_LEVEL_NODE_MIN + 1;
983 if (level <= nilfs_btree_height(btree) - 1) {
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +0900984 node = nilfs_btree_get_node(btree, path, level, &ncmax);
985 return nilfs_btree_node_get_ptr(node, path[level].bp_index,
986 ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -0700987 }
988
989 return NILFS_BMAP_INVALID_PTR;
990}
991
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900992static __u64 nilfs_btree_find_target_v(const struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700993 const struct nilfs_btree_path *path,
994 __u64 key)
995{
996 __u64 ptr;
997
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900998 ptr = nilfs_bmap_find_target_seq(btree, key);
Koji Sato17c76b02009-04-06 19:01:24 -0700999 if (ptr != NILFS_BMAP_INVALID_PTR)
1000 /* sequential access */
1001 return ptr;
1002 else {
1003 ptr = nilfs_btree_find_near(btree, path);
1004 if (ptr != NILFS_BMAP_INVALID_PTR)
1005 /* near */
1006 return ptr;
1007 }
1008 /* block group */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001009 return nilfs_bmap_find_target_in_group(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001010}
1011
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001012static int nilfs_btree_prepare_insert(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001013 struct nilfs_btree_path *path,
1014 int *levelp, __u64 key, __u64 ptr,
1015 struct nilfs_bmap_stats *stats)
1016{
1017 struct buffer_head *bh;
1018 struct nilfs_btree_node *node, *parent, *sib;
1019 __u64 sibptr;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001020 int pindex, level, ncmax, ncblk, ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001021 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001022
1023 stats->bs_nblocks = 0;
1024 level = NILFS_BTREE_LEVEL_DATA;
1025
1026 /* allocate a new ptr for data block */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001027 if (NILFS_BMAP_USE_VBN(btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001028 path[level].bp_newreq.bpr_ptr =
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001029 nilfs_btree_find_target_v(btree, path, key);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001030 dat = nilfs_bmap_get_dat(btree);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001031 }
Koji Sato17c76b02009-04-06 19:01:24 -07001032
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001033 ret = nilfs_bmap_prepare_alloc_ptr(btree, &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001034 if (ret < 0)
1035 goto err_out_data;
1036
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001037 ncblk = nilfs_btree_nchildren_per_block(btree);
Ryusuke Konishiea64ab82010-07-13 23:33:52 +09001038
Koji Sato17c76b02009-04-06 19:01:24 -07001039 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1040 level < nilfs_btree_height(btree) - 1;
1041 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001042 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001043 if (nilfs_btree_node_get_nchildren(node) < ncblk) {
Koji Sato17c76b02009-04-06 19:01:24 -07001044 path[level].bp_op = nilfs_btree_do_insert;
1045 stats->bs_nblocks++;
1046 goto out;
1047 }
1048
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001049 parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -07001050 pindex = path[level + 1].bp_index;
1051
1052 /* left sibling */
1053 if (pindex > 0) {
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001054 sibptr = nilfs_btree_node_get_ptr(parent, pindex - 1,
1055 ncmax);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001056 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001057 if (ret < 0)
1058 goto err_out_child_node;
1059 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001060 if (nilfs_btree_node_get_nchildren(sib) < ncblk) {
Koji Sato17c76b02009-04-06 19:01:24 -07001061 path[level].bp_sib_bh = bh;
1062 path[level].bp_op = nilfs_btree_carry_left;
1063 stats->bs_nblocks++;
1064 goto out;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001065 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001066 brelse(bh);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001067 }
Koji Sato17c76b02009-04-06 19:01:24 -07001068 }
1069
1070 /* right sibling */
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001071 if (pindex < nilfs_btree_node_get_nchildren(parent) - 1) {
1072 sibptr = nilfs_btree_node_get_ptr(parent, pindex + 1,
1073 ncmax);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001074 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001075 if (ret < 0)
1076 goto err_out_child_node;
1077 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001078 if (nilfs_btree_node_get_nchildren(sib) < ncblk) {
Koji Sato17c76b02009-04-06 19:01:24 -07001079 path[level].bp_sib_bh = bh;
1080 path[level].bp_op = nilfs_btree_carry_right;
1081 stats->bs_nblocks++;
1082 goto out;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001083 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001084 brelse(bh);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001085 }
Koji Sato17c76b02009-04-06 19:01:24 -07001086 }
1087
1088 /* split */
1089 path[level].bp_newreq.bpr_ptr =
1090 path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001091 ret = nilfs_bmap_prepare_alloc_ptr(btree,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001092 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001093 if (ret < 0)
1094 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001095 ret = nilfs_btree_get_new_block(btree,
1096 path[level].bp_newreq.bpr_ptr,
1097 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001098 if (ret < 0)
1099 goto err_out_curr_node;
1100
1101 stats->bs_nblocks++;
1102
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001103 sib = (struct nilfs_btree_node *)bh->b_data;
1104 nilfs_btree_node_init(sib, 0, level, 0, ncblk, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001105 path[level].bp_sib_bh = bh;
1106 path[level].bp_op = nilfs_btree_split;
1107 }
1108
1109 /* root */
1110 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001111 if (nilfs_btree_node_get_nchildren(node) <
Ryusuke Konishiea64ab82010-07-13 23:33:52 +09001112 NILFS_BTREE_ROOT_NCHILDREN_MAX) {
Koji Sato17c76b02009-04-06 19:01:24 -07001113 path[level].bp_op = nilfs_btree_do_insert;
1114 stats->bs_nblocks++;
1115 goto out;
1116 }
1117
1118 /* grow */
1119 path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001120 ret = nilfs_bmap_prepare_alloc_ptr(btree, &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001121 if (ret < 0)
1122 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001123 ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
1124 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001125 if (ret < 0)
1126 goto err_out_curr_node;
1127
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001128 nilfs_btree_node_init((struct nilfs_btree_node *)bh->b_data,
1129 0, level, 0, ncblk, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001130 path[level].bp_sib_bh = bh;
1131 path[level].bp_op = nilfs_btree_grow;
1132
1133 level++;
1134 path[level].bp_op = nilfs_btree_do_insert;
1135
1136 /* a newly-created node block and a data block are added */
1137 stats->bs_nblocks += 2;
1138
1139 /* success */
1140 out:
1141 *levelp = level;
1142 return ret;
1143
1144 /* error */
1145 err_out_curr_node:
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001146 nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001147 err_out_child_node:
1148 for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001149 nilfs_btnode_delete(path[level].bp_sib_bh);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001150 nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001151
1152 }
1153
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001154 nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001155 err_out_data:
1156 *levelp = level;
1157 stats->bs_nblocks = 0;
1158 return ret;
1159}
1160
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001161static void nilfs_btree_commit_insert(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001162 struct nilfs_btree_path *path,
1163 int maxlevel, __u64 key, __u64 ptr)
1164{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001165 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001166 int level;
1167
1168 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1169 ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001170 if (NILFS_BMAP_USE_VBN(btree)) {
Ryusuke Konishidc935be2010-07-10 22:21:54 +09001171 nilfs_bmap_set_target_v(btree, key, ptr);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001172 dat = nilfs_bmap_get_dat(btree);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001173 }
Koji Sato17c76b02009-04-06 19:01:24 -07001174
1175 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001176 nilfs_bmap_commit_alloc_ptr(btree,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001177 &path[level - 1].bp_newreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001178 path[level].bp_op(btree, path, level, &key, &ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001179 }
1180
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001181 if (!nilfs_bmap_dirty(btree))
1182 nilfs_bmap_set_dirty(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001183}
1184
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001185static int nilfs_btree_insert(struct nilfs_bmap *btree, __u64 key, __u64 ptr)
Koji Sato17c76b02009-04-06 19:01:24 -07001186{
Koji Sato17c76b02009-04-06 19:01:24 -07001187 struct nilfs_btree_path *path;
1188 struct nilfs_bmap_stats stats;
1189 int level, ret;
1190
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001191 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001192 if (path == NULL)
1193 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001194
1195 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +09001196 NILFS_BTREE_LEVEL_NODE_MIN, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07001197 if (ret != -ENOENT) {
1198 if (ret == 0)
1199 ret = -EEXIST;
1200 goto out;
1201 }
1202
1203 ret = nilfs_btree_prepare_insert(btree, path, &level, key, ptr, &stats);
1204 if (ret < 0)
1205 goto out;
1206 nilfs_btree_commit_insert(btree, path, level, key, ptr);
Ryusuke Konishibe667372011-03-05 00:19:32 +09001207 nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks);
Koji Sato17c76b02009-04-06 19:01:24 -07001208
1209 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001210 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001211 return ret;
1212}
1213
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001214static void nilfs_btree_do_delete(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001215 struct nilfs_btree_path *path,
1216 int level, __u64 *keyp, __u64 *ptrp)
1217{
1218 struct nilfs_btree_node *node;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001219 int ncblk;
Koji Sato17c76b02009-04-06 19:01:24 -07001220
1221 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001222 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001223 ncblk = nilfs_btree_nchildren_per_block(btree);
1224 nilfs_btree_node_delete(node, path[level].bp_index,
1225 keyp, ptrp, ncblk);
Koji Sato17c76b02009-04-06 19:01:24 -07001226 if (!buffer_dirty(path[level].bp_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +09001227 mark_buffer_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001228 if (path[level].bp_index == 0)
1229 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001230 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001231 } else {
1232 node = nilfs_btree_get_root(btree);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001233 nilfs_btree_node_delete(node, path[level].bp_index,
1234 keyp, ptrp,
1235 NILFS_BTREE_ROOT_NCHILDREN_MAX);
Koji Sato17c76b02009-04-06 19:01:24 -07001236 }
1237}
1238
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001239static void nilfs_btree_borrow_left(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001240 struct nilfs_btree_path *path,
1241 int level, __u64 *keyp, __u64 *ptrp)
1242{
1243 struct nilfs_btree_node *node, *left;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001244 int nchildren, lnchildren, n, ncblk;
Koji Sato17c76b02009-04-06 19:01:24 -07001245
1246 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1247
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001248 node = nilfs_btree_get_nonroot_node(path, level);
1249 left = nilfs_btree_get_sib_node(path, level);
1250 nchildren = nilfs_btree_node_get_nchildren(node);
1251 lnchildren = nilfs_btree_node_get_nchildren(left);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001252 ncblk = nilfs_btree_nchildren_per_block(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001253
1254 n = (nchildren + lnchildren) / 2 - nchildren;
1255
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001256 nilfs_btree_node_move_right(left, node, n, ncblk, ncblk);
Koji Sato17c76b02009-04-06 19:01:24 -07001257
1258 if (!buffer_dirty(path[level].bp_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +09001259 mark_buffer_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001260 if (!buffer_dirty(path[level].bp_sib_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +09001261 mark_buffer_dirty(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001262
Koji Sato17c76b02009-04-06 19:01:24 -07001263 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001264 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001265
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001266 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001267 path[level].bp_sib_bh = NULL;
1268 path[level].bp_index += n;
1269}
1270
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001271static void nilfs_btree_borrow_right(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001272 struct nilfs_btree_path *path,
1273 int level, __u64 *keyp, __u64 *ptrp)
1274{
1275 struct nilfs_btree_node *node, *right;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001276 int nchildren, rnchildren, n, ncblk;
Koji Sato17c76b02009-04-06 19:01:24 -07001277
1278 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1279
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001280 node = nilfs_btree_get_nonroot_node(path, level);
1281 right = nilfs_btree_get_sib_node(path, level);
1282 nchildren = nilfs_btree_node_get_nchildren(node);
1283 rnchildren = nilfs_btree_node_get_nchildren(right);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001284 ncblk = nilfs_btree_nchildren_per_block(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001285
1286 n = (nchildren + rnchildren) / 2 - nchildren;
1287
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001288 nilfs_btree_node_move_left(node, right, n, ncblk, ncblk);
Koji Sato17c76b02009-04-06 19:01:24 -07001289
1290 if (!buffer_dirty(path[level].bp_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +09001291 mark_buffer_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001292 if (!buffer_dirty(path[level].bp_sib_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +09001293 mark_buffer_dirty(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001294
Koji Sato17c76b02009-04-06 19:01:24 -07001295 path[level + 1].bp_index++;
1296 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001297 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001298 path[level + 1].bp_index--;
1299
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001300 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001301 path[level].bp_sib_bh = NULL;
1302}
1303
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001304static void nilfs_btree_concat_left(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001305 struct nilfs_btree_path *path,
1306 int level, __u64 *keyp, __u64 *ptrp)
1307{
1308 struct nilfs_btree_node *node, *left;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001309 int n, ncblk;
Koji Sato17c76b02009-04-06 19:01:24 -07001310
1311 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1312
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001313 node = nilfs_btree_get_nonroot_node(path, level);
1314 left = nilfs_btree_get_sib_node(path, level);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001315 ncblk = nilfs_btree_nchildren_per_block(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001316
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001317 n = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001318
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001319 nilfs_btree_node_move_left(left, node, n, ncblk, ncblk);
Koji Sato17c76b02009-04-06 19:01:24 -07001320
1321 if (!buffer_dirty(path[level].bp_sib_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +09001322 mark_buffer_dirty(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001323
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001324 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001325 path[level].bp_bh = path[level].bp_sib_bh;
1326 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001327 path[level].bp_index += nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001328}
1329
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001330static void nilfs_btree_concat_right(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001331 struct nilfs_btree_path *path,
1332 int level, __u64 *keyp, __u64 *ptrp)
1333{
1334 struct nilfs_btree_node *node, *right;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001335 int n, ncblk;
Koji Sato17c76b02009-04-06 19:01:24 -07001336
1337 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1338
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001339 node = nilfs_btree_get_nonroot_node(path, level);
1340 right = nilfs_btree_get_sib_node(path, level);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001341 ncblk = nilfs_btree_nchildren_per_block(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001342
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001343 n = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001344
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001345 nilfs_btree_node_move_left(node, right, n, ncblk, ncblk);
Koji Sato17c76b02009-04-06 19:01:24 -07001346
1347 if (!buffer_dirty(path[level].bp_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +09001348 mark_buffer_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001349
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001350 nilfs_btnode_delete(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001351 path[level].bp_sib_bh = NULL;
1352 path[level + 1].bp_index++;
1353}
1354
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001355static void nilfs_btree_shrink(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001356 struct nilfs_btree_path *path,
1357 int level, __u64 *keyp, __u64 *ptrp)
1358{
1359 struct nilfs_btree_node *root, *child;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001360 int n, ncblk;
Koji Sato17c76b02009-04-06 19:01:24 -07001361
1362 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1363
Koji Sato17c76b02009-04-06 19:01:24 -07001364 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001365 child = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001366 ncblk = nilfs_btree_nchildren_per_block(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001367
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001368 nilfs_btree_node_delete(root, 0, NULL, NULL,
1369 NILFS_BTREE_ROOT_NCHILDREN_MAX);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001370 nilfs_btree_node_set_level(root, level);
1371 n = nilfs_btree_node_get_nchildren(child);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001372 nilfs_btree_node_move_left(root, child, n,
1373 NILFS_BTREE_ROOT_NCHILDREN_MAX, ncblk);
Koji Sato17c76b02009-04-06 19:01:24 -07001374
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001375 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001376 path[level].bp_bh = NULL;
1377}
1378
Ryusuke Konishid4099052011-05-25 23:00:27 +09001379static void nilfs_btree_nop(struct nilfs_bmap *btree,
1380 struct nilfs_btree_path *path,
1381 int level, __u64 *keyp, __u64 *ptrp)
1382{
1383}
Koji Sato17c76b02009-04-06 19:01:24 -07001384
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001385static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001386 struct nilfs_btree_path *path,
1387 int *levelp,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001388 struct nilfs_bmap_stats *stats,
1389 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001390{
1391 struct buffer_head *bh;
1392 struct nilfs_btree_node *node, *parent, *sib;
1393 __u64 sibptr;
Ryusuke Konishife744fd2011-05-25 23:00:27 +09001394 int pindex, dindex, level, ncmin, ncmax, ncblk, ret;
Koji Sato17c76b02009-04-06 19:01:24 -07001395
1396 ret = 0;
1397 stats->bs_nblocks = 0;
Ryusuke Konishiea64ab82010-07-13 23:33:52 +09001398 ncmin = NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree));
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001399 ncblk = nilfs_btree_nchildren_per_block(btree);
Ryusuke Konishiea64ab82010-07-13 23:33:52 +09001400
Ryusuke Konishife744fd2011-05-25 23:00:27 +09001401 for (level = NILFS_BTREE_LEVEL_NODE_MIN, dindex = path[level].bp_index;
Koji Sato17c76b02009-04-06 19:01:24 -07001402 level < nilfs_btree_height(btree) - 1;
1403 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001404 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001405 path[level].bp_oldreq.bpr_ptr =
Ryusuke Konishife744fd2011-05-25 23:00:27 +09001406 nilfs_btree_node_get_ptr(node, dindex, ncblk);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001407 ret = nilfs_bmap_prepare_end_ptr(btree,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001408 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001409 if (ret < 0)
1410 goto err_out_child_node;
Koji Sato17c76b02009-04-06 19:01:24 -07001411
Ryusuke Konishiea64ab82010-07-13 23:33:52 +09001412 if (nilfs_btree_node_get_nchildren(node) > ncmin) {
Koji Sato17c76b02009-04-06 19:01:24 -07001413 path[level].bp_op = nilfs_btree_do_delete;
1414 stats->bs_nblocks++;
1415 goto out;
1416 }
1417
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001418 parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -07001419 pindex = path[level + 1].bp_index;
Ryusuke Konishife744fd2011-05-25 23:00:27 +09001420 dindex = pindex;
Koji Sato17c76b02009-04-06 19:01:24 -07001421
1422 if (pindex > 0) {
1423 /* left sibling */
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001424 sibptr = nilfs_btree_node_get_ptr(parent, pindex - 1,
1425 ncmax);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001426 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001427 if (ret < 0)
1428 goto err_out_curr_node;
1429 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishiea64ab82010-07-13 23:33:52 +09001430 if (nilfs_btree_node_get_nchildren(sib) > ncmin) {
Koji Sato17c76b02009-04-06 19:01:24 -07001431 path[level].bp_sib_bh = bh;
1432 path[level].bp_op = nilfs_btree_borrow_left;
1433 stats->bs_nblocks++;
1434 goto out;
1435 } else {
1436 path[level].bp_sib_bh = bh;
1437 path[level].bp_op = nilfs_btree_concat_left;
1438 stats->bs_nblocks++;
1439 /* continue; */
1440 }
1441 } else if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001442 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -07001443 /* right sibling */
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001444 sibptr = nilfs_btree_node_get_ptr(parent, pindex + 1,
1445 ncmax);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001446 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001447 if (ret < 0)
1448 goto err_out_curr_node;
1449 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishiea64ab82010-07-13 23:33:52 +09001450 if (nilfs_btree_node_get_nchildren(sib) > ncmin) {
Koji Sato17c76b02009-04-06 19:01:24 -07001451 path[level].bp_sib_bh = bh;
1452 path[level].bp_op = nilfs_btree_borrow_right;
1453 stats->bs_nblocks++;
1454 goto out;
1455 } else {
1456 path[level].bp_sib_bh = bh;
1457 path[level].bp_op = nilfs_btree_concat_right;
1458 stats->bs_nblocks++;
Ryusuke Konishife744fd2011-05-25 23:00:27 +09001459 /*
1460 * When merging right sibling node
1461 * into the current node, pointer to
1462 * the right sibling node must be
1463 * terminated instead. The adjustment
1464 * below is required for that.
1465 */
1466 dindex = pindex + 1;
Koji Sato17c76b02009-04-06 19:01:24 -07001467 /* continue; */
1468 }
1469 } else {
1470 /* no siblings */
1471 /* the only child of the root node */
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001472 WARN_ON(level != nilfs_btree_height(btree) - 2);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001473 if (nilfs_btree_node_get_nchildren(node) - 1 <=
Koji Sato17c76b02009-04-06 19:01:24 -07001474 NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1475 path[level].bp_op = nilfs_btree_shrink;
1476 stats->bs_nblocks += 2;
Ryusuke Konishid4099052011-05-25 23:00:27 +09001477 level++;
1478 path[level].bp_op = nilfs_btree_nop;
1479 goto shrink_root_child;
Koji Sato17c76b02009-04-06 19:01:24 -07001480 } else {
1481 path[level].bp_op = nilfs_btree_do_delete;
1482 stats->bs_nblocks++;
Ryusuke Konishid4099052011-05-25 23:00:27 +09001483 goto out;
Koji Sato17c76b02009-04-06 19:01:24 -07001484 }
Koji Sato17c76b02009-04-06 19:01:24 -07001485 }
1486 }
1487
Ryusuke Konishid4099052011-05-25 23:00:27 +09001488 /* child of the root node is deleted */
1489 path[level].bp_op = nilfs_btree_do_delete;
1490 stats->bs_nblocks++;
1491
1492shrink_root_child:
Koji Sato17c76b02009-04-06 19:01:24 -07001493 node = nilfs_btree_get_root(btree);
1494 path[level].bp_oldreq.bpr_ptr =
Ryusuke Konishife744fd2011-05-25 23:00:27 +09001495 nilfs_btree_node_get_ptr(node, dindex,
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001496 NILFS_BTREE_ROOT_NCHILDREN_MAX);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001497
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001498 ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001499 if (ret < 0)
1500 goto err_out_child_node;
1501
Koji Sato17c76b02009-04-06 19:01:24 -07001502 /* success */
1503 out:
1504 *levelp = level;
1505 return ret;
1506
1507 /* error */
1508 err_out_curr_node:
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001509 nilfs_bmap_abort_end_ptr(btree, &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001510 err_out_child_node:
1511 for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001512 brelse(path[level].bp_sib_bh);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001513 nilfs_bmap_abort_end_ptr(btree, &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001514 }
1515 *levelp = level;
1516 stats->bs_nblocks = 0;
1517 return ret;
1518}
1519
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001520static void nilfs_btree_commit_delete(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001521 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001522 int maxlevel, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001523{
1524 int level;
1525
1526 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001527 nilfs_bmap_commit_end_ptr(btree, &path[level].bp_oldreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001528 path[level].bp_op(btree, path, level, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001529 }
1530
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001531 if (!nilfs_bmap_dirty(btree))
1532 nilfs_bmap_set_dirty(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001533}
1534
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001535static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key)
Koji Sato17c76b02009-04-06 19:01:24 -07001536
1537{
Koji Sato17c76b02009-04-06 19:01:24 -07001538 struct nilfs_btree_path *path;
1539 struct nilfs_bmap_stats stats;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001540 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001541 int level, ret;
1542
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001543 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001544 if (path == NULL)
1545 return -ENOMEM;
Li Hongf9054402010-04-02 17:36:34 +08001546
Koji Sato17c76b02009-04-06 19:01:24 -07001547 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +09001548 NILFS_BTREE_LEVEL_NODE_MIN, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07001549 if (ret < 0)
1550 goto out;
1551
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001552
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001553 dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001554
1555 ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001556 if (ret < 0)
1557 goto out;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001558 nilfs_btree_commit_delete(btree, path, level, dat);
Ryusuke Konishibe667372011-03-05 00:19:32 +09001559 nilfs_inode_sub_blocks(btree->b_inode, stats.bs_nblocks);
Koji Sato17c76b02009-04-06 19:01:24 -07001560
1561out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001562 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001563 return ret;
1564}
1565
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001566static int nilfs_btree_last_key(const struct nilfs_bmap *btree, __u64 *keyp)
Koji Sato17c76b02009-04-06 19:01:24 -07001567{
Koji Sato17c76b02009-04-06 19:01:24 -07001568 struct nilfs_btree_path *path;
1569 int ret;
1570
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001571 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001572 if (path == NULL)
1573 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001574
1575 ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL);
1576
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001577 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001578
1579 return ret;
1580}
1581
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001582static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key)
Koji Sato17c76b02009-04-06 19:01:24 -07001583{
1584 struct buffer_head *bh;
Koji Sato17c76b02009-04-06 19:01:24 -07001585 struct nilfs_btree_node *root, *node;
1586 __u64 maxkey, nextmaxkey;
1587 __u64 ptr;
1588 int nchildren, ret;
1589
Koji Sato17c76b02009-04-06 19:01:24 -07001590 root = nilfs_btree_get_root(btree);
1591 switch (nilfs_btree_height(btree)) {
1592 case 2:
1593 bh = NULL;
1594 node = root;
1595 break;
1596 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001597 nchildren = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -07001598 if (nchildren > 1)
1599 return 0;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001600 ptr = nilfs_btree_node_get_ptr(root, nchildren - 1,
1601 NILFS_BTREE_ROOT_NCHILDREN_MAX);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001602 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001603 if (ret < 0)
1604 return ret;
1605 node = (struct nilfs_btree_node *)bh->b_data;
1606 break;
1607 default:
1608 return 0;
1609 }
1610
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001611 nchildren = nilfs_btree_node_get_nchildren(node);
1612 maxkey = nilfs_btree_node_get_key(node, nchildren - 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001613 nextmaxkey = (nchildren > 1) ?
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001614 nilfs_btree_node_get_key(node, nchildren - 2) : 0;
Koji Sato17c76b02009-04-06 19:01:24 -07001615 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001616 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001617
Ryusuke Konishi30333422009-05-24 00:09:44 +09001618 return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
Koji Sato17c76b02009-04-06 19:01:24 -07001619}
1620
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001621static int nilfs_btree_gather_data(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001622 __u64 *keys, __u64 *ptrs, int nitems)
1623{
1624 struct buffer_head *bh;
Koji Sato17c76b02009-04-06 19:01:24 -07001625 struct nilfs_btree_node *node, *root;
1626 __le64 *dkeys;
1627 __le64 *dptrs;
1628 __u64 ptr;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001629 int nchildren, ncmax, i, ret;
Koji Sato17c76b02009-04-06 19:01:24 -07001630
Koji Sato17c76b02009-04-06 19:01:24 -07001631 root = nilfs_btree_get_root(btree);
1632 switch (nilfs_btree_height(btree)) {
1633 case 2:
1634 bh = NULL;
1635 node = root;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001636 ncmax = NILFS_BTREE_ROOT_NCHILDREN_MAX;
Koji Sato17c76b02009-04-06 19:01:24 -07001637 break;
1638 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001639 nchildren = nilfs_btree_node_get_nchildren(root);
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001640 WARN_ON(nchildren > 1);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001641 ptr = nilfs_btree_node_get_ptr(root, nchildren - 1,
1642 NILFS_BTREE_ROOT_NCHILDREN_MAX);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001643 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001644 if (ret < 0)
1645 return ret;
1646 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001647 ncmax = nilfs_btree_nchildren_per_block(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001648 break;
1649 default:
1650 node = NULL;
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001651 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -07001652 }
1653
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001654 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001655 if (nchildren < nitems)
1656 nitems = nchildren;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001657 dkeys = nilfs_btree_node_dkeys(node);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001658 dptrs = nilfs_btree_node_dptrs(node, ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -07001659 for (i = 0; i < nitems; i++) {
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +09001660 keys[i] = le64_to_cpu(dkeys[i]);
1661 ptrs[i] = le64_to_cpu(dptrs[i]);
Koji Sato17c76b02009-04-06 19:01:24 -07001662 }
1663
1664 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001665 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001666
1667 return nitems;
1668}
1669
1670static int
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001671nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *btree, __u64 key,
Koji Sato17c76b02009-04-06 19:01:24 -07001672 union nilfs_bmap_ptr_req *dreq,
1673 union nilfs_bmap_ptr_req *nreq,
1674 struct buffer_head **bhp,
1675 struct nilfs_bmap_stats *stats)
1676{
1677 struct buffer_head *bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001678 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001679 int ret;
1680
Koji Sato17c76b02009-04-06 19:01:24 -07001681 stats->bs_nblocks = 0;
1682
1683 /* for data */
1684 /* cannot find near ptr */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001685 if (NILFS_BMAP_USE_VBN(btree)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001686 dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001687 dat = nilfs_bmap_get_dat(btree);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001688 }
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001689
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001690 ret = nilfs_bmap_prepare_alloc_ptr(btree, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001691 if (ret < 0)
1692 return ret;
1693
1694 *bhp = NULL;
1695 stats->bs_nblocks++;
1696 if (nreq != NULL) {
1697 nreq->bpr_ptr = dreq->bpr_ptr + 1;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001698 ret = nilfs_bmap_prepare_alloc_ptr(btree, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001699 if (ret < 0)
1700 goto err_out_dreq;
1701
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001702 ret = nilfs_btree_get_new_block(btree, nreq->bpr_ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001703 if (ret < 0)
1704 goto err_out_nreq;
1705
1706 *bhp = bh;
1707 stats->bs_nblocks++;
1708 }
1709
1710 /* success */
1711 return 0;
1712
1713 /* error */
1714 err_out_nreq:
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001715 nilfs_bmap_abort_alloc_ptr(btree, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001716 err_out_dreq:
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001717 nilfs_bmap_abort_alloc_ptr(btree, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001718 stats->bs_nblocks = 0;
1719 return ret;
1720
1721}
1722
1723static void
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001724nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001725 __u64 key, __u64 ptr,
1726 const __u64 *keys, const __u64 *ptrs,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001727 int n,
Koji Sato17c76b02009-04-06 19:01:24 -07001728 union nilfs_bmap_ptr_req *dreq,
1729 union nilfs_bmap_ptr_req *nreq,
1730 struct buffer_head *bh)
1731{
Koji Sato17c76b02009-04-06 19:01:24 -07001732 struct nilfs_btree_node *node;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001733 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001734 __u64 tmpptr;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001735 int ncblk;
Koji Sato17c76b02009-04-06 19:01:24 -07001736
1737 /* free resources */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001738 if (btree->b_ops->bop_clear != NULL)
1739 btree->b_ops->bop_clear(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001740
1741 /* ptr must be a pointer to a buffer head. */
1742 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1743
1744 /* convert and insert */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001745 dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL;
Ryusuke Konishi957ed602015-02-27 15:51:56 -08001746 __nilfs_btree_init(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001747 if (nreq != NULL) {
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001748 nilfs_bmap_commit_alloc_ptr(btree, dreq, dat);
1749 nilfs_bmap_commit_alloc_ptr(btree, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001750
1751 /* create child node at level 1 */
Koji Sato17c76b02009-04-06 19:01:24 -07001752 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001753 ncblk = nilfs_btree_nchildren_per_block(btree);
1754 nilfs_btree_node_init(node, 0, 1, n, ncblk, keys, ptrs);
1755 nilfs_btree_node_insert(node, n, key, dreq->bpr_ptr, ncblk);
Koji Sato17c76b02009-04-06 19:01:24 -07001756 if (!buffer_dirty(bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +09001757 mark_buffer_dirty(bh);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001758 if (!nilfs_bmap_dirty(btree))
1759 nilfs_bmap_set_dirty(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001760
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001761 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001762
1763 /* create root node at level 2 */
1764 node = nilfs_btree_get_root(btree);
1765 tmpptr = nreq->bpr_ptr;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001766 nilfs_btree_node_init(node, NILFS_BTREE_NODE_ROOT, 2, 1,
1767 NILFS_BTREE_ROOT_NCHILDREN_MAX,
1768 &keys[0], &tmpptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001769 } else {
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001770 nilfs_bmap_commit_alloc_ptr(btree, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001771
1772 /* create root node at level 1 */
1773 node = nilfs_btree_get_root(btree);
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001774 nilfs_btree_node_init(node, NILFS_BTREE_NODE_ROOT, 1, n,
1775 NILFS_BTREE_ROOT_NCHILDREN_MAX,
1776 keys, ptrs);
1777 nilfs_btree_node_insert(node, n, key, dreq->bpr_ptr,
1778 NILFS_BTREE_ROOT_NCHILDREN_MAX);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001779 if (!nilfs_bmap_dirty(btree))
1780 nilfs_bmap_set_dirty(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001781 }
1782
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001783 if (NILFS_BMAP_USE_VBN(btree))
Ryusuke Konishidc935be2010-07-10 22:21:54 +09001784 nilfs_bmap_set_target_v(btree, key, dreq->bpr_ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001785}
1786
1787/**
1788 * nilfs_btree_convert_and_insert -
1789 * @bmap:
1790 * @key:
1791 * @ptr:
1792 * @keys:
1793 * @ptrs:
1794 * @n:
Koji Sato17c76b02009-04-06 19:01:24 -07001795 */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001796int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001797 __u64 key, __u64 ptr,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001798 const __u64 *keys, const __u64 *ptrs, int n)
Koji Sato17c76b02009-04-06 19:01:24 -07001799{
1800 struct buffer_head *bh;
1801 union nilfs_bmap_ptr_req dreq, nreq, *di, *ni;
1802 struct nilfs_bmap_stats stats;
1803 int ret;
1804
1805 if (n + 1 <= NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1806 di = &dreq;
1807 ni = NULL;
1808 } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX(
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001809 1 << btree->b_inode->i_blkbits)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001810 di = &dreq;
1811 ni = &nreq;
1812 } else {
1813 di = NULL;
1814 ni = NULL;
1815 BUG();
1816 }
1817
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001818 ret = nilfs_btree_prepare_convert_and_insert(btree, key, di, ni, &bh,
Koji Sato17c76b02009-04-06 19:01:24 -07001819 &stats);
1820 if (ret < 0)
1821 return ret;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001822 nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001823 di, ni, bh);
Ryusuke Konishibe667372011-03-05 00:19:32 +09001824 nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks);
Koji Sato17c76b02009-04-06 19:01:24 -07001825 return 0;
1826}
1827
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001828static int nilfs_btree_propagate_p(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001829 struct nilfs_btree_path *path,
1830 int level,
1831 struct buffer_head *bh)
1832{
1833 while ((++level < nilfs_btree_height(btree) - 1) &&
1834 !buffer_dirty(path[level].bp_bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +09001835 mark_buffer_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001836
1837 return 0;
1838}
1839
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001840static int nilfs_btree_prepare_update_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001841 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001842 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001843{
1844 struct nilfs_btree_node *parent;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001845 int ncmax, ret;
Koji Sato17c76b02009-04-06 19:01:24 -07001846
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001847 parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -07001848 path[level].bp_oldreq.bpr_ptr =
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001849 nilfs_btree_node_get_ptr(parent, path[level + 1].bp_index,
1850 ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -07001851 path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001852 ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req,
1853 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001854 if (ret < 0)
1855 return ret;
1856
1857 if (buffer_nilfs_node(path[level].bp_bh)) {
1858 path[level].bp_ctxt.oldkey = path[level].bp_oldreq.bpr_ptr;
1859 path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr;
1860 path[level].bp_ctxt.bh = path[level].bp_bh;
1861 ret = nilfs_btnode_prepare_change_key(
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001862 &NILFS_BMAP_I(btree)->i_btnode_cache,
Koji Sato17c76b02009-04-06 19:01:24 -07001863 &path[level].bp_ctxt);
1864 if (ret < 0) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001865 nilfs_dat_abort_update(dat,
1866 &path[level].bp_oldreq.bpr_req,
1867 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001868 return ret;
1869 }
1870 }
1871
1872 return 0;
1873}
1874
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001875static void nilfs_btree_commit_update_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001876 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001877 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001878{
1879 struct nilfs_btree_node *parent;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001880 int ncmax;
Koji Sato17c76b02009-04-06 19:01:24 -07001881
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001882 nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req,
1883 &path[level].bp_newreq.bpr_req,
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001884 btree->b_ptr_type == NILFS_BMAP_PTR_VS);
Koji Sato17c76b02009-04-06 19:01:24 -07001885
1886 if (buffer_nilfs_node(path[level].bp_bh)) {
1887 nilfs_btnode_commit_change_key(
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001888 &NILFS_BMAP_I(btree)->i_btnode_cache,
Koji Sato17c76b02009-04-06 19:01:24 -07001889 &path[level].bp_ctxt);
1890 path[level].bp_bh = path[level].bp_ctxt.bh;
1891 }
1892 set_buffer_nilfs_volatile(path[level].bp_bh);
1893
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001894 parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
1895 nilfs_btree_node_set_ptr(parent, path[level + 1].bp_index,
1896 path[level].bp_newreq.bpr_ptr, ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -07001897}
1898
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001899static void nilfs_btree_abort_update_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001900 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001901 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001902{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001903 nilfs_dat_abort_update(dat, &path[level].bp_oldreq.bpr_req,
1904 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001905 if (buffer_nilfs_node(path[level].bp_bh))
1906 nilfs_btnode_abort_change_key(
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001907 &NILFS_BMAP_I(btree)->i_btnode_cache,
Koji Sato17c76b02009-04-06 19:01:24 -07001908 &path[level].bp_ctxt);
1909}
1910
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001911static int nilfs_btree_prepare_propagate_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001912 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001913 int minlevel, int *maxlevelp,
1914 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001915{
1916 int level, ret;
1917
1918 level = minlevel;
1919 if (!buffer_nilfs_volatile(path[level].bp_bh)) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001920 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001921 if (ret < 0)
1922 return ret;
1923 }
1924 while ((++level < nilfs_btree_height(btree) - 1) &&
1925 !buffer_dirty(path[level].bp_bh)) {
1926
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001927 WARN_ON(buffer_nilfs_volatile(path[level].bp_bh));
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001928 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001929 if (ret < 0)
1930 goto out;
1931 }
1932
1933 /* success */
Koji Sato17c76b02009-04-06 19:01:24 -07001934 *maxlevelp = level - 1;
1935 return 0;
1936
1937 /* error */
1938 out:
1939 while (--level > minlevel)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001940 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001941 if (!buffer_nilfs_volatile(path[level].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001942 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001943 return ret;
1944}
1945
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001946static void nilfs_btree_commit_propagate_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001947 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001948 int minlevel, int maxlevel,
1949 struct buffer_head *bh,
1950 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001951{
1952 int level;
1953
1954 if (!buffer_nilfs_volatile(path[minlevel].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001955 nilfs_btree_commit_update_v(btree, path, minlevel, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001956
1957 for (level = minlevel + 1; level <= maxlevel; level++)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001958 nilfs_btree_commit_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001959}
1960
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001961static int nilfs_btree_propagate_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001962 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001963 int level, struct buffer_head *bh)
Koji Sato17c76b02009-04-06 19:01:24 -07001964{
Li Hong308f4412010-04-02 18:40:39 +08001965 int maxlevel = 0, ret;
Koji Sato17c76b02009-04-06 19:01:24 -07001966 struct nilfs_btree_node *parent;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001967 struct inode *dat = nilfs_bmap_get_dat(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001968 __u64 ptr;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001969 int ncmax;
Koji Sato17c76b02009-04-06 19:01:24 -07001970
1971 get_bh(bh);
1972 path[level].bp_bh = bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001973 ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel,
1974 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001975 if (ret < 0)
1976 goto out;
1977
1978 if (buffer_nilfs_volatile(path[level].bp_bh)) {
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09001979 parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
1980 ptr = nilfs_btree_node_get_ptr(parent,
1981 path[level + 1].bp_index,
1982 ncmax);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001983 ret = nilfs_dat_mark_dirty(dat, ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001984 if (ret < 0)
1985 goto out;
1986 }
1987
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001988 nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001989
1990 out:
1991 brelse(path[level].bp_bh);
1992 path[level].bp_bh = NULL;
1993 return ret;
1994}
1995
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001996static int nilfs_btree_propagate(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001997 struct buffer_head *bh)
1998{
Koji Sato17c76b02009-04-06 19:01:24 -07001999 struct nilfs_btree_path *path;
2000 struct nilfs_btree_node *node;
2001 __u64 key;
2002 int level, ret;
2003
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002004 WARN_ON(!buffer_dirty(bh));
Koji Sato17c76b02009-04-06 19:01:24 -07002005
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002006 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002007 if (path == NULL)
2008 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07002009
2010 if (buffer_nilfs_node(bh)) {
2011 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002012 key = nilfs_btree_node_get_key(node, 0);
2013 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07002014 } else {
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002015 key = nilfs_bmap_data_get_key(btree, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002016 level = NILFS_BTREE_LEVEL_DATA;
2017 }
2018
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +09002019 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07002020 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002021 if (unlikely(ret == -ENOENT))
Koji Sato17c76b02009-04-06 19:01:24 -07002022 printk(KERN_CRIT "%s: key = %llu, level == %d\n",
2023 __func__, (unsigned long long)key, level);
Koji Sato17c76b02009-04-06 19:01:24 -07002024 goto out;
2025 }
2026
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002027 ret = NILFS_BMAP_USE_VBN(btree) ?
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09002028 nilfs_btree_propagate_v(btree, path, level, bh) :
2029 nilfs_btree_propagate_p(btree, path, level, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002030
2031 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002032 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002033
2034 return ret;
2035}
2036
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002037static int nilfs_btree_propagate_gc(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07002038 struct buffer_head *bh)
2039{
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002040 return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(btree), bh->b_blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002041}
2042
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002043static void nilfs_btree_add_dirty_buffer(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07002044 struct list_head *lists,
2045 struct buffer_head *bh)
2046{
2047 struct list_head *head;
2048 struct buffer_head *cbh;
2049 struct nilfs_btree_node *node, *cnode;
2050 __u64 key, ckey;
2051 int level;
2052
2053 get_bh(bh);
2054 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002055 key = nilfs_btree_node_get_key(node, 0);
2056 level = nilfs_btree_node_get_level(node);
Ryusuke Konishicfa913a2010-07-07 17:19:54 +09002057 if (level < NILFS_BTREE_LEVEL_NODE_MIN ||
2058 level >= NILFS_BTREE_LEVEL_MAX) {
2059 dump_stack();
2060 printk(KERN_WARNING
2061 "%s: invalid btree level: %d (key=%llu, ino=%lu, "
2062 "blocknr=%llu)\n",
2063 __func__, level, (unsigned long long)key,
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002064 NILFS_BMAP_I(btree)->vfs_inode.i_ino,
Ryusuke Konishicfa913a2010-07-07 17:19:54 +09002065 (unsigned long long)bh->b_blocknr);
2066 return;
2067 }
2068
Koji Sato17c76b02009-04-06 19:01:24 -07002069 list_for_each(head, &lists[level]) {
2070 cbh = list_entry(head, struct buffer_head, b_assoc_buffers);
2071 cnode = (struct nilfs_btree_node *)cbh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002072 ckey = nilfs_btree_node_get_key(cnode, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07002073 if (key < ckey)
2074 break;
2075 }
2076 list_add_tail(&bh->b_assoc_buffers, head);
2077}
2078
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002079static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07002080 struct list_head *listp)
2081{
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002082 struct address_space *btcache = &NILFS_BMAP_I(btree)->i_btnode_cache;
Koji Sato17c76b02009-04-06 19:01:24 -07002083 struct list_head lists[NILFS_BTREE_LEVEL_MAX];
2084 struct pagevec pvec;
2085 struct buffer_head *bh, *head;
2086 pgoff_t index = 0;
2087 int level, i;
2088
2089 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
2090 level < NILFS_BTREE_LEVEL_MAX;
2091 level++)
2092 INIT_LIST_HEAD(&lists[level]);
2093
2094 pagevec_init(&pvec, 0);
2095
2096 while (pagevec_lookup_tag(&pvec, btcache, &index, PAGECACHE_TAG_DIRTY,
2097 PAGEVEC_SIZE)) {
2098 for (i = 0; i < pagevec_count(&pvec); i++) {
2099 bh = head = page_buffers(pvec.pages[i]);
2100 do {
2101 if (buffer_dirty(bh))
2102 nilfs_btree_add_dirty_buffer(btree,
2103 lists, bh);
2104 } while ((bh = bh->b_this_page) != head);
2105 }
2106 pagevec_release(&pvec);
2107 cond_resched();
2108 }
2109
2110 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
2111 level < NILFS_BTREE_LEVEL_MAX;
2112 level++)
Ryusuke Konishi0935db72009-11-29 02:39:11 +09002113 list_splice_tail(&lists[level], listp);
Koji Sato17c76b02009-04-06 19:01:24 -07002114}
2115
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002116static int nilfs_btree_assign_p(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07002117 struct nilfs_btree_path *path,
2118 int level,
2119 struct buffer_head **bh,
2120 sector_t blocknr,
2121 union nilfs_binfo *binfo)
2122{
2123 struct nilfs_btree_node *parent;
2124 __u64 key;
2125 __u64 ptr;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09002126 int ncmax, ret;
Koji Sato17c76b02009-04-06 19:01:24 -07002127
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09002128 parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
2129 ptr = nilfs_btree_node_get_ptr(parent, path[level + 1].bp_index,
2130 ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -07002131 if (buffer_nilfs_node(*bh)) {
2132 path[level].bp_ctxt.oldkey = ptr;
2133 path[level].bp_ctxt.newkey = blocknr;
2134 path[level].bp_ctxt.bh = *bh;
2135 ret = nilfs_btnode_prepare_change_key(
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002136 &NILFS_BMAP_I(btree)->i_btnode_cache,
Koji Sato17c76b02009-04-06 19:01:24 -07002137 &path[level].bp_ctxt);
2138 if (ret < 0)
2139 return ret;
2140 nilfs_btnode_commit_change_key(
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002141 &NILFS_BMAP_I(btree)->i_btnode_cache,
Koji Sato17c76b02009-04-06 19:01:24 -07002142 &path[level].bp_ctxt);
2143 *bh = path[level].bp_ctxt.bh;
2144 }
2145
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09002146 nilfs_btree_node_set_ptr(parent, path[level + 1].bp_index, blocknr,
2147 ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -07002148
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002149 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002150 /* on-disk format */
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +09002151 binfo->bi_dat.bi_blkoff = cpu_to_le64(key);
Koji Sato17c76b02009-04-06 19:01:24 -07002152 binfo->bi_dat.bi_level = level;
2153
2154 return 0;
2155}
2156
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002157static int nilfs_btree_assign_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07002158 struct nilfs_btree_path *path,
2159 int level,
2160 struct buffer_head **bh,
2161 sector_t blocknr,
2162 union nilfs_binfo *binfo)
2163{
2164 struct nilfs_btree_node *parent;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002165 struct inode *dat = nilfs_bmap_get_dat(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07002166 __u64 key;
2167 __u64 ptr;
2168 union nilfs_bmap_ptr_req req;
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09002169 int ncmax, ret;
Koji Sato17c76b02009-04-06 19:01:24 -07002170
Ryusuke Konishi9b7b2652010-07-13 23:33:53 +09002171 parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
2172 ptr = nilfs_btree_node_get_ptr(parent, path[level + 1].bp_index,
2173 ncmax);
Koji Sato17c76b02009-04-06 19:01:24 -07002174 req.bpr_ptr = ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002175 ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
2176 if (ret < 0)
Koji Sato17c76b02009-04-06 19:01:24 -07002177 return ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002178 nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002179
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002180 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002181 /* on-disk format */
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +09002182 binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr);
2183 binfo->bi_v.bi_blkoff = cpu_to_le64(key);
Koji Sato17c76b02009-04-06 19:01:24 -07002184
2185 return 0;
2186}
2187
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002188static int nilfs_btree_assign(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07002189 struct buffer_head **bh,
2190 sector_t blocknr,
2191 union nilfs_binfo *binfo)
2192{
Koji Sato17c76b02009-04-06 19:01:24 -07002193 struct nilfs_btree_path *path;
2194 struct nilfs_btree_node *node;
2195 __u64 key;
2196 int level, ret;
2197
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002198 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002199 if (path == NULL)
2200 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07002201
2202 if (buffer_nilfs_node(*bh)) {
2203 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002204 key = nilfs_btree_node_get_key(node, 0);
2205 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07002206 } else {
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002207 key = nilfs_bmap_data_get_key(btree, *bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002208 level = NILFS_BTREE_LEVEL_DATA;
2209 }
2210
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +09002211 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07002212 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002213 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002214 goto out;
2215 }
2216
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002217 ret = NILFS_BMAP_USE_VBN(btree) ?
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09002218 nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) :
2219 nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
Koji Sato17c76b02009-04-06 19:01:24 -07002220
2221 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002222 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002223
2224 return ret;
2225}
2226
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002227static int nilfs_btree_assign_gc(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07002228 struct buffer_head **bh,
2229 sector_t blocknr,
2230 union nilfs_binfo *binfo)
2231{
Koji Sato17c76b02009-04-06 19:01:24 -07002232 struct nilfs_btree_node *node;
2233 __u64 key;
2234 int ret;
2235
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002236 ret = nilfs_dat_move(nilfs_bmap_get_dat(btree), (*bh)->b_blocknr,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002237 blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002238 if (ret < 0)
2239 return ret;
2240
2241 if (buffer_nilfs_node(*bh)) {
2242 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002243 key = nilfs_btree_node_get_key(node, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07002244 } else
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002245 key = nilfs_bmap_data_get_key(btree, *bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002246
2247 /* on-disk format */
2248 binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr);
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +09002249 binfo->bi_v.bi_blkoff = cpu_to_le64(key);
Koji Sato17c76b02009-04-06 19:01:24 -07002250
2251 return 0;
2252}
2253
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002254static int nilfs_btree_mark(struct nilfs_bmap *btree, __u64 key, int level)
Koji Sato17c76b02009-04-06 19:01:24 -07002255{
2256 struct buffer_head *bh;
Koji Sato17c76b02009-04-06 19:01:24 -07002257 struct nilfs_btree_path *path;
2258 __u64 ptr;
2259 int ret;
2260
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002261 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002262 if (path == NULL)
2263 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07002264
Ryusuke Konishi03bdb5a2010-07-18 10:42:26 +09002265 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07002266 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002267 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002268 goto out;
2269 }
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09002270 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002271 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002272 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002273 goto out;
2274 }
2275
2276 if (!buffer_dirty(bh))
Ryusuke Konishi5fc7b142011-05-05 12:56:51 +09002277 mark_buffer_dirty(bh);
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09002278 brelse(bh);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002279 if (!nilfs_bmap_dirty(btree))
2280 nilfs_bmap_set_dirty(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07002281
2282 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002283 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002284 return ret;
2285}
2286
2287static const struct nilfs_bmap_operations nilfs_btree_ops = {
2288 .bop_lookup = nilfs_btree_lookup,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002289 .bop_lookup_contig = nilfs_btree_lookup_contig,
Koji Sato17c76b02009-04-06 19:01:24 -07002290 .bop_insert = nilfs_btree_insert,
2291 .bop_delete = nilfs_btree_delete,
2292 .bop_clear = NULL,
2293
2294 .bop_propagate = nilfs_btree_propagate,
2295
2296 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2297
2298 .bop_assign = nilfs_btree_assign,
2299 .bop_mark = nilfs_btree_mark,
2300
2301 .bop_last_key = nilfs_btree_last_key,
2302 .bop_check_insert = NULL,
2303 .bop_check_delete = nilfs_btree_check_delete,
2304 .bop_gather_data = nilfs_btree_gather_data,
2305};
2306
2307static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
2308 .bop_lookup = NULL,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002309 .bop_lookup_contig = NULL,
Koji Sato17c76b02009-04-06 19:01:24 -07002310 .bop_insert = NULL,
2311 .bop_delete = NULL,
2312 .bop_clear = NULL,
2313
2314 .bop_propagate = nilfs_btree_propagate_gc,
2315
2316 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2317
2318 .bop_assign = nilfs_btree_assign_gc,
2319 .bop_mark = NULL,
2320
2321 .bop_last_key = NULL,
2322 .bop_check_insert = NULL,
2323 .bop_check_delete = NULL,
2324 .bop_gather_data = NULL,
2325};
2326
Ryusuke Konishi957ed602015-02-27 15:51:56 -08002327static void __nilfs_btree_init(struct nilfs_bmap *bmap)
Koji Sato17c76b02009-04-06 19:01:24 -07002328{
Koji Sato17c76b02009-04-06 19:01:24 -07002329 bmap->b_ops = &nilfs_btree_ops;
Ryusuke Konishi5ad2686e92010-07-13 23:33:54 +09002330 bmap->b_nchildren_per_block =
2331 NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap));
Ryusuke Konishi957ed602015-02-27 15:51:56 -08002332}
2333
2334int nilfs_btree_init(struct nilfs_bmap *bmap)
2335{
2336 int ret = 0;
2337
2338 __nilfs_btree_init(bmap);
2339
2340 if (nilfs_btree_root_broken(nilfs_btree_get_root(bmap),
2341 bmap->b_inode->i_ino))
2342 ret = -EIO;
2343 return ret;
Koji Sato17c76b02009-04-06 19:01:24 -07002344}
2345
2346void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
2347{
Koji Sato17c76b02009-04-06 19:01:24 -07002348 bmap->b_ops = &nilfs_btree_ops_gc;
Ryusuke Konishi5ad2686e92010-07-13 23:33:54 +09002349 bmap->b_nchildren_per_block =
2350 NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap));
Koji Sato17c76b02009-04-06 19:01:24 -07002351}