blob: 115b157d508b80a2ed73becd224e9dec8b844df1 [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
34/**
35 * struct nilfs_btree_path - A path on which B-tree operations are executed
36 * @bp_bh: buffer head of node block
37 * @bp_sib_bh: buffer head of sibling node block
38 * @bp_index: index of child node
39 * @bp_oldreq: ptr end request for old ptr
40 * @bp_newreq: ptr alloc request for new ptr
41 * @bp_op: rebalance operation
42 */
43struct nilfs_btree_path {
44 struct buffer_head *bp_bh;
45 struct buffer_head *bp_sib_bh;
46 int bp_index;
47 union nilfs_bmap_ptr_req bp_oldreq;
48 union nilfs_bmap_ptr_req bp_newreq;
49 struct nilfs_btnode_chkey_ctxt bp_ctxt;
50 void (*bp_op)(struct nilfs_btree *, struct nilfs_btree_path *,
51 int, __u64 *, __u64 *);
52};
53
54/*
55 * B-tree path operations
56 */
57
58static struct kmem_cache *nilfs_btree_path_cache;
59
60int __init nilfs_btree_path_cache_init(void)
61{
62 nilfs_btree_path_cache =
63 kmem_cache_create("nilfs2_btree_path_cache",
64 sizeof(struct nilfs_btree_path) *
65 NILFS_BTREE_LEVEL_MAX, 0, 0, NULL);
66 return (nilfs_btree_path_cache != NULL) ? 0 : -ENOMEM;
67}
68
69void nilfs_btree_path_cache_destroy(void)
70{
71 kmem_cache_destroy(nilfs_btree_path_cache);
72}
73
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +090074static inline struct nilfs_btree_path *nilfs_btree_alloc_path(void)
Koji Sato17c76b02009-04-06 19:01:24 -070075{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +090076 return kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS);
Koji Sato17c76b02009-04-06 19:01:24 -070077}
78
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +090079static inline void nilfs_btree_free_path(struct nilfs_btree_path *path)
Koji Sato17c76b02009-04-06 19:01:24 -070080{
81 kmem_cache_free(nilfs_btree_path_cache, path);
82}
83
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +090084static void nilfs_btree_init_path(struct nilfs_btree_path *path)
Koji Sato17c76b02009-04-06 19:01:24 -070085{
86 int level;
87
88 for (level = NILFS_BTREE_LEVEL_DATA;
89 level < NILFS_BTREE_LEVEL_MAX;
90 level++) {
91 path[level].bp_bh = NULL;
92 path[level].bp_sib_bh = NULL;
93 path[level].bp_index = 0;
94 path[level].bp_oldreq.bpr_ptr = NILFS_BMAP_INVALID_PTR;
95 path[level].bp_newreq.bpr_ptr = NILFS_BMAP_INVALID_PTR;
96 path[level].bp_op = NULL;
97 }
98}
99
Ryusuke Konishi32189292009-08-15 01:54:59 +0900100static void nilfs_btree_release_path(struct nilfs_btree_path *path)
Koji Sato17c76b02009-04-06 19:01:24 -0700101{
102 int level;
103
Ryusuke Konishi32189292009-08-15 01:54:59 +0900104 for (level = NILFS_BTREE_LEVEL_DATA; level < NILFS_BTREE_LEVEL_MAX;
105 level++)
106 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700107}
108
Koji Sato17c76b02009-04-06 19:01:24 -0700109/*
110 * B-tree node operations
111 */
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900112static int nilfs_btree_get_block(const struct nilfs_btree *btree, __u64 ptr,
113 struct buffer_head **bhp)
114{
115 struct address_space *btnc =
116 &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
117 return nilfs_btnode_get(btnc, ptr, 0, bhp, 0);
118}
119
120static int nilfs_btree_get_new_block(const struct nilfs_btree *btree,
121 __u64 ptr, struct buffer_head **bhp)
122{
123 struct address_space *btnc =
124 &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
125 int ret;
126
127 ret = nilfs_btnode_get(btnc, ptr, 0, bhp, 1);
128 if (!ret)
129 set_buffer_nilfs_volatile(*bhp);
130 return ret;
131}
Koji Sato17c76b02009-04-06 19:01:24 -0700132
133static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900134nilfs_btree_node_get_flags(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700135{
136 return node->bn_flags;
137}
138
139static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900140nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags)
Koji Sato17c76b02009-04-06 19:01:24 -0700141{
142 node->bn_flags = flags;
143}
144
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900145static inline int nilfs_btree_node_root(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700146{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900147 return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT;
Koji Sato17c76b02009-04-06 19:01:24 -0700148}
149
150static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900151nilfs_btree_node_get_level(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700152{
153 return node->bn_level;
154}
155
156static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900157nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700158{
159 node->bn_level = level;
160}
161
162static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900163nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700164{
165 return le16_to_cpu(node->bn_nchildren);
166}
167
168static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900169nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren)
Koji Sato17c76b02009-04-06 19:01:24 -0700170{
171 node->bn_nchildren = cpu_to_le16(nchildren);
172}
173
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900174static inline int nilfs_btree_node_size(const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700175{
176 return 1 << btree->bt_bmap.b_inode->i_blkbits;
177}
178
179static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900180nilfs_btree_node_nchildren_min(const struct nilfs_btree_node *node,
181 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700182{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900183 return nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700184 NILFS_BTREE_ROOT_NCHILDREN_MIN :
185 NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree));
186}
187
188static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900189nilfs_btree_node_nchildren_max(const struct nilfs_btree_node *node,
190 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700191{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900192 return nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700193 NILFS_BTREE_ROOT_NCHILDREN_MAX :
194 NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree));
195}
196
197static inline __le64 *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900198nilfs_btree_node_dkeys(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700199{
200 return (__le64 *)((char *)(node + 1) +
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900201 (nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700202 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE));
203}
204
205static inline __le64 *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900206nilfs_btree_node_dptrs(const struct nilfs_btree_node *node,
207 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700208{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900209 return (__le64 *)(nilfs_btree_node_dkeys(node) +
210 nilfs_btree_node_nchildren_max(node, btree));
Koji Sato17c76b02009-04-06 19:01:24 -0700211}
212
213static inline __u64
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900214nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index)
Koji Sato17c76b02009-04-06 19:01:24 -0700215{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900216 return nilfs_bmap_dkey_to_key(*(nilfs_btree_node_dkeys(node) + index));
Koji Sato17c76b02009-04-06 19:01:24 -0700217}
218
219static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900220nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key)
Koji Sato17c76b02009-04-06 19:01:24 -0700221{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900222 *(nilfs_btree_node_dkeys(node) + index) = nilfs_bmap_key_to_dkey(key);
Koji Sato17c76b02009-04-06 19:01:24 -0700223}
224
225static inline __u64
226nilfs_btree_node_get_ptr(const struct nilfs_btree *btree,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900227 const struct nilfs_btree_node *node, int index)
Koji Sato17c76b02009-04-06 19:01:24 -0700228{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900229 return nilfs_bmap_dptr_to_ptr(*(nilfs_btree_node_dptrs(node, btree) +
Koji Sato17c76b02009-04-06 19:01:24 -0700230 index));
231}
232
233static inline void
234nilfs_btree_node_set_ptr(struct nilfs_btree *btree,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900235 struct nilfs_btree_node *node, int index, __u64 ptr)
Koji Sato17c76b02009-04-06 19:01:24 -0700236{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900237 *(nilfs_btree_node_dptrs(node, btree) + index) =
Koji Sato17c76b02009-04-06 19:01:24 -0700238 nilfs_bmap_ptr_to_dptr(ptr);
239}
240
241static void nilfs_btree_node_init(struct nilfs_btree *btree,
242 struct nilfs_btree_node *node,
243 int flags, int level, int nchildren,
244 const __u64 *keys, const __u64 *ptrs)
245{
246 __le64 *dkeys;
247 __le64 *dptrs;
248 int i;
249
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900250 nilfs_btree_node_set_flags(node, flags);
251 nilfs_btree_node_set_level(node, level);
252 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700253
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900254 dkeys = nilfs_btree_node_dkeys(node);
255 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700256 for (i = 0; i < nchildren; i++) {
257 dkeys[i] = nilfs_bmap_key_to_dkey(keys[i]);
258 dptrs[i] = nilfs_bmap_ptr_to_dptr(ptrs[i]);
259 }
260}
261
262/* Assume the buffer heads corresponding to left and right are locked. */
263static void nilfs_btree_node_move_left(struct nilfs_btree *btree,
264 struct nilfs_btree_node *left,
265 struct nilfs_btree_node *right,
266 int n)
267{
268 __le64 *ldkeys, *rdkeys;
269 __le64 *ldptrs, *rdptrs;
270 int lnchildren, rnchildren;
271
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900272 ldkeys = nilfs_btree_node_dkeys(left);
273 ldptrs = nilfs_btree_node_dptrs(left, btree);
274 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700275
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900276 rdkeys = nilfs_btree_node_dkeys(right);
277 rdptrs = nilfs_btree_node_dptrs(right, btree);
278 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700279
280 memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys));
281 memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs));
282 memmove(rdkeys, rdkeys + n, (rnchildren - n) * sizeof(*rdkeys));
283 memmove(rdptrs, rdptrs + n, (rnchildren - n) * sizeof(*rdptrs));
284
285 lnchildren += n;
286 rnchildren -= n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900287 nilfs_btree_node_set_nchildren(left, lnchildren);
288 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700289}
290
291/* Assume that the buffer heads corresponding to left and right are locked. */
292static void nilfs_btree_node_move_right(struct nilfs_btree *btree,
293 struct nilfs_btree_node *left,
294 struct nilfs_btree_node *right,
295 int n)
296{
297 __le64 *ldkeys, *rdkeys;
298 __le64 *ldptrs, *rdptrs;
299 int lnchildren, rnchildren;
300
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900301 ldkeys = nilfs_btree_node_dkeys(left);
302 ldptrs = nilfs_btree_node_dptrs(left, btree);
303 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700304
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900305 rdkeys = nilfs_btree_node_dkeys(right);
306 rdptrs = nilfs_btree_node_dptrs(right, btree);
307 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700308
309 memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys));
310 memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs));
311 memcpy(rdkeys, ldkeys + lnchildren - n, n * sizeof(*rdkeys));
312 memcpy(rdptrs, ldptrs + lnchildren - n, n * sizeof(*rdptrs));
313
314 lnchildren -= n;
315 rnchildren += n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900316 nilfs_btree_node_set_nchildren(left, lnchildren);
317 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700318}
319
320/* Assume that the buffer head corresponding to node is locked. */
321static void nilfs_btree_node_insert(struct nilfs_btree *btree,
322 struct nilfs_btree_node *node,
323 __u64 key, __u64 ptr, int index)
324{
325 __le64 *dkeys;
326 __le64 *dptrs;
327 int nchildren;
328
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900329 dkeys = nilfs_btree_node_dkeys(node);
330 dptrs = nilfs_btree_node_dptrs(node, btree);
331 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700332 if (index < nchildren) {
333 memmove(dkeys + index + 1, dkeys + index,
334 (nchildren - index) * sizeof(*dkeys));
335 memmove(dptrs + index + 1, dptrs + index,
336 (nchildren - index) * sizeof(*dptrs));
337 }
338 dkeys[index] = nilfs_bmap_key_to_dkey(key);
339 dptrs[index] = nilfs_bmap_ptr_to_dptr(ptr);
340 nchildren++;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900341 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700342}
343
344/* Assume that the buffer head corresponding to node is locked. */
345static void nilfs_btree_node_delete(struct nilfs_btree *btree,
346 struct nilfs_btree_node *node,
347 __u64 *keyp, __u64 *ptrp, int index)
348{
349 __u64 key;
350 __u64 ptr;
351 __le64 *dkeys;
352 __le64 *dptrs;
353 int nchildren;
354
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900355 dkeys = nilfs_btree_node_dkeys(node);
356 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700357 key = nilfs_bmap_dkey_to_key(dkeys[index]);
358 ptr = nilfs_bmap_dptr_to_ptr(dptrs[index]);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900359 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700360 if (keyp != NULL)
361 *keyp = key;
362 if (ptrp != NULL)
363 *ptrp = ptr;
364
365 if (index < nchildren - 1) {
366 memmove(dkeys + index, dkeys + index + 1,
367 (nchildren - index - 1) * sizeof(*dkeys));
368 memmove(dptrs + index, dptrs + index + 1,
369 (nchildren - index - 1) * sizeof(*dptrs));
370 }
371 nchildren--;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900372 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700373}
374
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900375static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node,
Koji Sato17c76b02009-04-06 19:01:24 -0700376 __u64 key, int *indexp)
377{
378 __u64 nkey;
379 int index, low, high, s;
380
381 /* binary search */
382 low = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900383 high = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700384 index = 0;
385 s = 0;
386 while (low <= high) {
387 index = (low + high) / 2;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900388 nkey = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700389 if (nkey == key) {
390 s = 0;
391 goto out;
392 } else if (nkey < key) {
393 low = index + 1;
394 s = -1;
395 } else {
396 high = index - 1;
397 s = 1;
398 }
399 }
400
401 /* adjust index */
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900402 if (nilfs_btree_node_get_level(node) > NILFS_BTREE_LEVEL_NODE_MIN) {
403 if (s > 0 && index > 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700404 index--;
405 } else if (s < 0)
406 index++;
407
408 out:
Koji Sato17c76b02009-04-06 19:01:24 -0700409 *indexp = index;
410
411 return s == 0;
412}
413
414static inline struct nilfs_btree_node *
415nilfs_btree_get_root(const struct nilfs_btree *btree)
416{
417 return (struct nilfs_btree_node *)btree->bt_bmap.b_u.u_data;
418}
419
420static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900421nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700422{
423 return (struct nilfs_btree_node *)path[level].bp_bh->b_data;
424}
425
426static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900427nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700428{
429 return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data;
430}
431
432static inline int nilfs_btree_height(const struct nilfs_btree *btree)
433{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900434 return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700435}
436
437static inline struct nilfs_btree_node *
438nilfs_btree_get_node(const struct nilfs_btree *btree,
439 const struct nilfs_btree_path *path,
440 int level)
441{
442 return (level == nilfs_btree_height(btree) - 1) ?
443 nilfs_btree_get_root(btree) :
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900444 nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700445}
446
447static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
448 struct nilfs_btree_path *path,
449 __u64 key, __u64 *ptrp, int minlevel)
450{
451 struct nilfs_btree_node *node;
452 __u64 ptr;
453 int level, index, found, ret;
454
Koji Sato17c76b02009-04-06 19:01:24 -0700455 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900456 level = nilfs_btree_node_get_level(node);
457 if (level < minlevel || nilfs_btree_node_get_nchildren(node) <= 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700458 return -ENOENT;
459
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900460 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700461 ptr = nilfs_btree_node_get_ptr(btree, node, index);
462 path[level].bp_bh = NULL;
463 path[level].bp_index = index;
464
465 for (level--; level >= minlevel; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900466 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700467 if (ret < 0)
468 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900469 node = nilfs_btree_get_nonroot_node(path, level);
470 BUG_ON(level != nilfs_btree_node_get_level(node));
Koji Sato17c76b02009-04-06 19:01:24 -0700471 if (!found)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900472 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700473 else
474 index = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900475 if (index < nilfs_btree_node_nchildren_max(node, btree))
Koji Sato17c76b02009-04-06 19:01:24 -0700476 ptr = nilfs_btree_node_get_ptr(btree, node, index);
477 else {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700478 WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN);
Koji Sato17c76b02009-04-06 19:01:24 -0700479 /* insert */
480 ptr = NILFS_BMAP_INVALID_PTR;
481 }
482 path[level].bp_index = index;
483 }
484 if (!found)
485 return -ENOENT;
486
487 if (ptrp != NULL)
488 *ptrp = ptr;
489
490 return 0;
491}
492
493static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree,
494 struct nilfs_btree_path *path,
495 __u64 *keyp, __u64 *ptrp)
496{
497 struct nilfs_btree_node *node;
498 __u64 ptr;
499 int index, level, ret;
500
501 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900502 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700503 if (index < 0)
504 return -ENOENT;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900505 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700506 ptr = nilfs_btree_node_get_ptr(btree, node, index);
507 path[level].bp_bh = NULL;
508 path[level].bp_index = index;
509
510 for (level--; level > 0; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900511 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700512 if (ret < 0)
513 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900514 node = nilfs_btree_get_nonroot_node(path, level);
515 BUG_ON(level != nilfs_btree_node_get_level(node));
516 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700517 ptr = nilfs_btree_node_get_ptr(btree, node, index);
518 path[level].bp_index = index;
519 }
520
521 if (keyp != NULL)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900522 *keyp = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700523 if (ptrp != NULL)
524 *ptrp = ptr;
525
526 return 0;
527}
528
529static int nilfs_btree_lookup(const struct nilfs_bmap *bmap,
530 __u64 key, int level, __u64 *ptrp)
531{
532 struct nilfs_btree *btree;
533 struct nilfs_btree_path *path;
534 __u64 ptr;
535 int ret;
536
537 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900538 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -0700539 if (path == NULL)
540 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900541 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -0700542
543 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
544
545 if (ptrp != NULL)
546 *ptrp = ptr;
547
Ryusuke Konishi32189292009-08-15 01:54:59 +0900548 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900549 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -0700550
551 return ret;
552}
553
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900554static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
555 __u64 key, __u64 *ptrp, unsigned maxblocks)
556{
557 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
558 struct nilfs_btree_path *path;
559 struct nilfs_btree_node *node;
560 struct inode *dat = NULL;
561 __u64 ptr, ptr2;
562 sector_t blocknr;
563 int level = NILFS_BTREE_LEVEL_NODE_MIN;
564 int ret, cnt, index, maxlevel;
565
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900566 path = nilfs_btree_alloc_path();
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900567 if (path == NULL)
568 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900569 nilfs_btree_init_path(path);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900570 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
571 if (ret < 0)
572 goto out;
573
574 if (NILFS_BMAP_USE_VBN(bmap)) {
575 dat = nilfs_bmap_get_dat(bmap);
576 ret = nilfs_dat_translate(dat, ptr, &blocknr);
577 if (ret < 0)
578 goto out;
579 ptr = blocknr;
580 }
581 cnt = 1;
582 if (cnt == maxblocks)
583 goto end;
584
585 maxlevel = nilfs_btree_height(btree) - 1;
586 node = nilfs_btree_get_node(btree, path, level);
587 index = path[level].bp_index + 1;
588 for (;;) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900589 while (index < nilfs_btree_node_get_nchildren(node)) {
590 if (nilfs_btree_node_get_key(node, index) !=
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900591 key + cnt)
592 goto end;
593 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
594 if (dat) {
595 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
596 if (ret < 0)
597 goto out;
598 ptr2 = blocknr;
599 }
600 if (ptr2 != ptr + cnt || ++cnt == maxblocks)
601 goto end;
602 index++;
603 continue;
604 }
605 if (level == maxlevel)
606 break;
607
608 /* look-up right sibling node */
609 node = nilfs_btree_get_node(btree, path, level + 1);
610 index = path[level + 1].bp_index + 1;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900611 if (index >= nilfs_btree_node_get_nchildren(node) ||
612 nilfs_btree_node_get_key(node, index) != key + cnt)
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900613 break;
614 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
615 path[level + 1].bp_index = index;
616
617 brelse(path[level].bp_bh);
618 path[level].bp_bh = NULL;
619 ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh);
620 if (ret < 0)
621 goto out;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900622 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900623 index = 0;
624 path[level].bp_index = index;
625 }
626 end:
627 *ptrp = ptr;
628 ret = cnt;
629 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +0900630 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900631 nilfs_btree_free_path(path);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900632 return ret;
633}
634
Koji Sato17c76b02009-04-06 19:01:24 -0700635static void nilfs_btree_promote_key(struct nilfs_btree *btree,
636 struct nilfs_btree_path *path,
637 int level, __u64 key)
638{
639 if (level < nilfs_btree_height(btree) - 1) {
640 do {
641 lock_buffer(path[level].bp_bh);
642 nilfs_btree_node_set_key(
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900643 nilfs_btree_get_nonroot_node(path, level),
Koji Sato17c76b02009-04-06 19:01:24 -0700644 path[level].bp_index, key);
645 if (!buffer_dirty(path[level].bp_bh))
646 nilfs_btnode_mark_dirty(path[level].bp_bh);
647 unlock_buffer(path[level].bp_bh);
648 } while ((path[level].bp_index == 0) &&
649 (++level < nilfs_btree_height(btree) - 1));
650 }
651
652 /* root */
653 if (level == nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900654 nilfs_btree_node_set_key(nilfs_btree_get_root(btree),
Koji Sato17c76b02009-04-06 19:01:24 -0700655 path[level].bp_index, key);
656 }
657}
658
659static void nilfs_btree_do_insert(struct nilfs_btree *btree,
660 struct nilfs_btree_path *path,
661 int level, __u64 *keyp, __u64 *ptrp)
662{
663 struct nilfs_btree_node *node;
664
665 if (level < nilfs_btree_height(btree) - 1) {
666 lock_buffer(path[level].bp_bh);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900667 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700668 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
669 path[level].bp_index);
670 if (!buffer_dirty(path[level].bp_bh))
671 nilfs_btnode_mark_dirty(path[level].bp_bh);
672 unlock_buffer(path[level].bp_bh);
673
674 if (path[level].bp_index == 0)
675 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900676 nilfs_btree_node_get_key(node,
677 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700678 } else {
679 node = nilfs_btree_get_root(btree);
680 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
681 path[level].bp_index);
682 }
683}
684
685static void nilfs_btree_carry_left(struct nilfs_btree *btree,
686 struct nilfs_btree_path *path,
687 int level, __u64 *keyp, __u64 *ptrp)
688{
689 struct nilfs_btree_node *node, *left;
690 int nchildren, lnchildren, n, move;
691
692 lock_buffer(path[level].bp_bh);
693 lock_buffer(path[level].bp_sib_bh);
694
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900695 node = nilfs_btree_get_nonroot_node(path, level);
696 left = nilfs_btree_get_sib_node(path, level);
697 nchildren = nilfs_btree_node_get_nchildren(node);
698 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700699 move = 0;
700
701 n = (nchildren + lnchildren + 1) / 2 - lnchildren;
702 if (n > path[level].bp_index) {
703 /* move insert point */
704 n--;
705 move = 1;
706 }
707
708 nilfs_btree_node_move_left(btree, left, node, n);
709
710 if (!buffer_dirty(path[level].bp_bh))
711 nilfs_btnode_mark_dirty(path[level].bp_bh);
712 if (!buffer_dirty(path[level].bp_sib_bh))
713 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
714
715 unlock_buffer(path[level].bp_bh);
716 unlock_buffer(path[level].bp_sib_bh);
717
718 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900719 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700720
721 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900722 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700723 path[level].bp_bh = path[level].bp_sib_bh;
724 path[level].bp_sib_bh = NULL;
725 path[level].bp_index += lnchildren;
726 path[level + 1].bp_index--;
727 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900728 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700729 path[level].bp_sib_bh = NULL;
730 path[level].bp_index -= n;
731 }
732
733 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
734}
735
736static void nilfs_btree_carry_right(struct nilfs_btree *btree,
737 struct nilfs_btree_path *path,
738 int level, __u64 *keyp, __u64 *ptrp)
739{
740 struct nilfs_btree_node *node, *right;
741 int nchildren, rnchildren, n, move;
742
743 lock_buffer(path[level].bp_bh);
744 lock_buffer(path[level].bp_sib_bh);
745
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900746 node = nilfs_btree_get_nonroot_node(path, level);
747 right = nilfs_btree_get_sib_node(path, level);
748 nchildren = nilfs_btree_node_get_nchildren(node);
749 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700750 move = 0;
751
752 n = (nchildren + rnchildren + 1) / 2 - rnchildren;
753 if (n > nchildren - path[level].bp_index) {
754 /* move insert point */
755 n--;
756 move = 1;
757 }
758
759 nilfs_btree_node_move_right(btree, node, right, n);
760
761 if (!buffer_dirty(path[level].bp_bh))
762 nilfs_btnode_mark_dirty(path[level].bp_bh);
763 if (!buffer_dirty(path[level].bp_sib_bh))
764 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
765
766 unlock_buffer(path[level].bp_bh);
767 unlock_buffer(path[level].bp_sib_bh);
768
769 path[level + 1].bp_index++;
770 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900771 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700772 path[level + 1].bp_index--;
773
774 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900775 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700776 path[level].bp_bh = path[level].bp_sib_bh;
777 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900778 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700779 path[level + 1].bp_index++;
780 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900781 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700782 path[level].bp_sib_bh = NULL;
783 }
784
785 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
786}
787
788static void nilfs_btree_split(struct nilfs_btree *btree,
789 struct nilfs_btree_path *path,
790 int level, __u64 *keyp, __u64 *ptrp)
791{
792 struct nilfs_btree_node *node, *right;
793 __u64 newkey;
794 __u64 newptr;
795 int nchildren, n, move;
796
797 lock_buffer(path[level].bp_bh);
798 lock_buffer(path[level].bp_sib_bh);
799
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900800 node = nilfs_btree_get_nonroot_node(path, level);
801 right = nilfs_btree_get_sib_node(path, level);
802 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700803 move = 0;
804
805 n = (nchildren + 1) / 2;
806 if (n > nchildren - path[level].bp_index) {
807 n--;
808 move = 1;
809 }
810
811 nilfs_btree_node_move_right(btree, node, right, n);
812
813 if (!buffer_dirty(path[level].bp_bh))
814 nilfs_btnode_mark_dirty(path[level].bp_bh);
815 if (!buffer_dirty(path[level].bp_sib_bh))
816 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
817
818 unlock_buffer(path[level].bp_bh);
819 unlock_buffer(path[level].bp_sib_bh);
820
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900821 newkey = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700822 newptr = path[level].bp_newreq.bpr_ptr;
823
824 if (move) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900825 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700826 nilfs_btree_node_insert(btree, right, *keyp, *ptrp,
827 path[level].bp_index);
828
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900829 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700830 *ptrp = path[level].bp_newreq.bpr_ptr;
831
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900832 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700833 path[level].bp_bh = path[level].bp_sib_bh;
834 path[level].bp_sib_bh = NULL;
835 } else {
836 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
837
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900838 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700839 *ptrp = path[level].bp_newreq.bpr_ptr;
840
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900841 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700842 path[level].bp_sib_bh = NULL;
843 }
844
845 path[level + 1].bp_index++;
846}
847
848static void nilfs_btree_grow(struct nilfs_btree *btree,
849 struct nilfs_btree_path *path,
850 int level, __u64 *keyp, __u64 *ptrp)
851{
852 struct nilfs_btree_node *root, *child;
853 int n;
854
855 lock_buffer(path[level].bp_sib_bh);
856
857 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900858 child = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700859
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900860 n = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -0700861
862 nilfs_btree_node_move_right(btree, root, child, n);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900863 nilfs_btree_node_set_level(root, level + 1);
Koji Sato17c76b02009-04-06 19:01:24 -0700864
865 if (!buffer_dirty(path[level].bp_sib_bh))
866 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
867
868 unlock_buffer(path[level].bp_sib_bh);
869
870 path[level].bp_bh = path[level].bp_sib_bh;
871 path[level].bp_sib_bh = NULL;
872
873 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
874
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900875 *keyp = nilfs_btree_node_get_key(child, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700876 *ptrp = path[level].bp_newreq.bpr_ptr;
877}
878
879static __u64 nilfs_btree_find_near(const struct nilfs_btree *btree,
880 const struct nilfs_btree_path *path)
881{
882 struct nilfs_btree_node *node;
883 int level;
884
885 if (path == NULL)
886 return NILFS_BMAP_INVALID_PTR;
887
888 /* left sibling */
889 level = NILFS_BTREE_LEVEL_NODE_MIN;
890 if (path[level].bp_index > 0) {
891 node = nilfs_btree_get_node(btree, path, level);
892 return nilfs_btree_node_get_ptr(btree, node,
893 path[level].bp_index - 1);
894 }
895
896 /* parent */
897 level = NILFS_BTREE_LEVEL_NODE_MIN + 1;
898 if (level <= nilfs_btree_height(btree) - 1) {
899 node = nilfs_btree_get_node(btree, path, level);
900 return nilfs_btree_node_get_ptr(btree, node,
901 path[level].bp_index);
902 }
903
904 return NILFS_BMAP_INVALID_PTR;
905}
906
907static __u64 nilfs_btree_find_target_v(const struct nilfs_btree *btree,
908 const struct nilfs_btree_path *path,
909 __u64 key)
910{
911 __u64 ptr;
912
913 ptr = nilfs_bmap_find_target_seq(&btree->bt_bmap, key);
914 if (ptr != NILFS_BMAP_INVALID_PTR)
915 /* sequential access */
916 return ptr;
917 else {
918 ptr = nilfs_btree_find_near(btree, path);
919 if (ptr != NILFS_BMAP_INVALID_PTR)
920 /* near */
921 return ptr;
922 }
923 /* block group */
924 return nilfs_bmap_find_target_in_group(&btree->bt_bmap);
925}
926
927static void nilfs_btree_set_target_v(struct nilfs_btree *btree, __u64 key,
928 __u64 ptr)
929{
930 btree->bt_bmap.b_last_allocated_key = key;
931 btree->bt_bmap.b_last_allocated_ptr = ptr;
932}
933
934static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
935 struct nilfs_btree_path *path,
936 int *levelp, __u64 key, __u64 ptr,
937 struct nilfs_bmap_stats *stats)
938{
939 struct buffer_head *bh;
940 struct nilfs_btree_node *node, *parent, *sib;
941 __u64 sibptr;
942 int pindex, level, ret;
943
944 stats->bs_nblocks = 0;
945 level = NILFS_BTREE_LEVEL_DATA;
946
947 /* allocate a new ptr for data block */
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +0900948 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap))
Koji Sato17c76b02009-04-06 19:01:24 -0700949 path[level].bp_newreq.bpr_ptr =
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +0900950 nilfs_btree_find_target_v(btree, path, key);
Koji Sato17c76b02009-04-06 19:01:24 -0700951
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900952 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
953 &path[level].bp_newreq);
Koji Sato17c76b02009-04-06 19:01:24 -0700954 if (ret < 0)
955 goto err_out_data;
956
957 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
958 level < nilfs_btree_height(btree) - 1;
959 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900960 node = nilfs_btree_get_nonroot_node(path, level);
961 if (nilfs_btree_node_get_nchildren(node) <
962 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700963 path[level].bp_op = nilfs_btree_do_insert;
964 stats->bs_nblocks++;
965 goto out;
966 }
967
968 parent = nilfs_btree_get_node(btree, path, level + 1);
969 pindex = path[level + 1].bp_index;
970
971 /* left sibling */
972 if (pindex > 0) {
973 sibptr = nilfs_btree_node_get_ptr(btree, parent,
974 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900975 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700976 if (ret < 0)
977 goto err_out_child_node;
978 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900979 if (nilfs_btree_node_get_nchildren(sib) <
980 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700981 path[level].bp_sib_bh = bh;
982 path[level].bp_op = nilfs_btree_carry_left;
983 stats->bs_nblocks++;
984 goto out;
985 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900986 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700987 }
988
989 /* right sibling */
990 if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900991 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -0700992 sibptr = nilfs_btree_node_get_ptr(btree, parent,
993 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900994 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700995 if (ret < 0)
996 goto err_out_child_node;
997 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900998 if (nilfs_btree_node_get_nchildren(sib) <
999 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001000 path[level].bp_sib_bh = bh;
1001 path[level].bp_op = nilfs_btree_carry_right;
1002 stats->bs_nblocks++;
1003 goto out;
1004 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001005 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001006 }
1007
1008 /* split */
1009 path[level].bp_newreq.bpr_ptr =
1010 path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001011 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
1012 &path[level].bp_newreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001013 if (ret < 0)
1014 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001015 ret = nilfs_btree_get_new_block(btree,
1016 path[level].bp_newreq.bpr_ptr,
1017 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001018 if (ret < 0)
1019 goto err_out_curr_node;
1020
1021 stats->bs_nblocks++;
1022
1023 lock_buffer(bh);
1024 nilfs_btree_node_init(btree,
1025 (struct nilfs_btree_node *)bh->b_data,
1026 0, level, 0, NULL, NULL);
1027 unlock_buffer(bh);
1028 path[level].bp_sib_bh = bh;
1029 path[level].bp_op = nilfs_btree_split;
1030 }
1031
1032 /* root */
1033 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001034 if (nilfs_btree_node_get_nchildren(node) <
1035 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001036 path[level].bp_op = nilfs_btree_do_insert;
1037 stats->bs_nblocks++;
1038 goto out;
1039 }
1040
1041 /* grow */
1042 path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001043 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
1044 &path[level].bp_newreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001045 if (ret < 0)
1046 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001047 ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
1048 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001049 if (ret < 0)
1050 goto err_out_curr_node;
1051
1052 lock_buffer(bh);
1053 nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data,
1054 0, level, 0, NULL, NULL);
1055 unlock_buffer(bh);
1056 path[level].bp_sib_bh = bh;
1057 path[level].bp_op = nilfs_btree_grow;
1058
1059 level++;
1060 path[level].bp_op = nilfs_btree_do_insert;
1061
1062 /* a newly-created node block and a data block are added */
1063 stats->bs_nblocks += 2;
1064
1065 /* success */
1066 out:
1067 *levelp = level;
1068 return ret;
1069
1070 /* error */
1071 err_out_curr_node:
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001072 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001073 err_out_child_node:
1074 for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001075 nilfs_btnode_delete(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001076 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap,
1077 &path[level].bp_newreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001078
1079 }
1080
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001081 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001082 err_out_data:
1083 *levelp = level;
1084 stats->bs_nblocks = 0;
1085 return ret;
1086}
1087
1088static void nilfs_btree_commit_insert(struct nilfs_btree *btree,
1089 struct nilfs_btree_path *path,
1090 int maxlevel, __u64 key, __u64 ptr)
1091{
1092 int level;
1093
1094 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1095 ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001096 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap))
1097 nilfs_btree_set_target_v(btree, key, ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001098
1099 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001100 nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap,
1101 &path[level - 1].bp_newreq);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001102 path[level].bp_op(btree, path, level, &key, &ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001103 }
1104
1105 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1106 nilfs_bmap_set_dirty(&btree->bt_bmap);
1107}
1108
1109static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
1110{
1111 struct nilfs_btree *btree;
1112 struct nilfs_btree_path *path;
1113 struct nilfs_bmap_stats stats;
1114 int level, ret;
1115
1116 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001117 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001118 if (path == NULL)
1119 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001120 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001121
1122 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1123 NILFS_BTREE_LEVEL_NODE_MIN);
1124 if (ret != -ENOENT) {
1125 if (ret == 0)
1126 ret = -EEXIST;
1127 goto out;
1128 }
1129
1130 ret = nilfs_btree_prepare_insert(btree, path, &level, key, ptr, &stats);
1131 if (ret < 0)
1132 goto out;
1133 nilfs_btree_commit_insert(btree, path, level, key, ptr);
1134 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1135
1136 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09001137 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001138 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001139 return ret;
1140}
1141
1142static void nilfs_btree_do_delete(struct nilfs_btree *btree,
1143 struct nilfs_btree_path *path,
1144 int level, __u64 *keyp, __u64 *ptrp)
1145{
1146 struct nilfs_btree_node *node;
1147
1148 if (level < nilfs_btree_height(btree) - 1) {
1149 lock_buffer(path[level].bp_bh);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001150 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001151 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1152 path[level].bp_index);
1153 if (!buffer_dirty(path[level].bp_bh))
1154 nilfs_btnode_mark_dirty(path[level].bp_bh);
1155 unlock_buffer(path[level].bp_bh);
1156 if (path[level].bp_index == 0)
1157 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001158 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001159 } else {
1160 node = nilfs_btree_get_root(btree);
1161 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1162 path[level].bp_index);
1163 }
1164}
1165
1166static void nilfs_btree_borrow_left(struct nilfs_btree *btree,
1167 struct nilfs_btree_path *path,
1168 int level, __u64 *keyp, __u64 *ptrp)
1169{
1170 struct nilfs_btree_node *node, *left;
1171 int nchildren, lnchildren, n;
1172
1173 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1174
1175 lock_buffer(path[level].bp_bh);
1176 lock_buffer(path[level].bp_sib_bh);
1177
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001178 node = nilfs_btree_get_nonroot_node(path, level);
1179 left = nilfs_btree_get_sib_node(path, level);
1180 nchildren = nilfs_btree_node_get_nchildren(node);
1181 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001182
1183 n = (nchildren + lnchildren) / 2 - nchildren;
1184
1185 nilfs_btree_node_move_right(btree, left, node, n);
1186
1187 if (!buffer_dirty(path[level].bp_bh))
1188 nilfs_btnode_mark_dirty(path[level].bp_bh);
1189 if (!buffer_dirty(path[level].bp_sib_bh))
1190 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1191
1192 unlock_buffer(path[level].bp_bh);
1193 unlock_buffer(path[level].bp_sib_bh);
1194
1195 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001196 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001197
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001198 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001199 path[level].bp_sib_bh = NULL;
1200 path[level].bp_index += n;
1201}
1202
1203static void nilfs_btree_borrow_right(struct nilfs_btree *btree,
1204 struct nilfs_btree_path *path,
1205 int level, __u64 *keyp, __u64 *ptrp)
1206{
1207 struct nilfs_btree_node *node, *right;
1208 int nchildren, rnchildren, n;
1209
1210 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1211
1212 lock_buffer(path[level].bp_bh);
1213 lock_buffer(path[level].bp_sib_bh);
1214
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001215 node = nilfs_btree_get_nonroot_node(path, level);
1216 right = nilfs_btree_get_sib_node(path, level);
1217 nchildren = nilfs_btree_node_get_nchildren(node);
1218 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001219
1220 n = (nchildren + rnchildren) / 2 - nchildren;
1221
1222 nilfs_btree_node_move_left(btree, node, right, n);
1223
1224 if (!buffer_dirty(path[level].bp_bh))
1225 nilfs_btnode_mark_dirty(path[level].bp_bh);
1226 if (!buffer_dirty(path[level].bp_sib_bh))
1227 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1228
1229 unlock_buffer(path[level].bp_bh);
1230 unlock_buffer(path[level].bp_sib_bh);
1231
1232 path[level + 1].bp_index++;
1233 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001234 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001235 path[level + 1].bp_index--;
1236
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001237 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001238 path[level].bp_sib_bh = NULL;
1239}
1240
1241static void nilfs_btree_concat_left(struct nilfs_btree *btree,
1242 struct nilfs_btree_path *path,
1243 int level, __u64 *keyp, __u64 *ptrp)
1244{
1245 struct nilfs_btree_node *node, *left;
1246 int n;
1247
1248 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1249
1250 lock_buffer(path[level].bp_bh);
1251 lock_buffer(path[level].bp_sib_bh);
1252
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001253 node = nilfs_btree_get_nonroot_node(path, level);
1254 left = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001255
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001256 n = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001257
1258 nilfs_btree_node_move_left(btree, left, node, n);
1259
1260 if (!buffer_dirty(path[level].bp_sib_bh))
1261 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1262
1263 unlock_buffer(path[level].bp_bh);
1264 unlock_buffer(path[level].bp_sib_bh);
1265
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001266 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001267 path[level].bp_bh = path[level].bp_sib_bh;
1268 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001269 path[level].bp_index += nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001270}
1271
1272static void nilfs_btree_concat_right(struct nilfs_btree *btree,
1273 struct nilfs_btree_path *path,
1274 int level, __u64 *keyp, __u64 *ptrp)
1275{
1276 struct nilfs_btree_node *node, *right;
1277 int n;
1278
1279 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1280
1281 lock_buffer(path[level].bp_bh);
1282 lock_buffer(path[level].bp_sib_bh);
1283
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001284 node = nilfs_btree_get_nonroot_node(path, level);
1285 right = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001286
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001287 n = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001288
1289 nilfs_btree_node_move_left(btree, node, right, n);
1290
1291 if (!buffer_dirty(path[level].bp_bh))
1292 nilfs_btnode_mark_dirty(path[level].bp_bh);
1293
1294 unlock_buffer(path[level].bp_bh);
1295 unlock_buffer(path[level].bp_sib_bh);
1296
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001297 nilfs_btnode_delete(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001298 path[level].bp_sib_bh = NULL;
1299 path[level + 1].bp_index++;
1300}
1301
1302static void nilfs_btree_shrink(struct nilfs_btree *btree,
1303 struct nilfs_btree_path *path,
1304 int level, __u64 *keyp, __u64 *ptrp)
1305{
1306 struct nilfs_btree_node *root, *child;
1307 int n;
1308
1309 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1310
1311 lock_buffer(path[level].bp_bh);
1312 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001313 child = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001314
1315 nilfs_btree_node_delete(btree, root, NULL, NULL, 0);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001316 nilfs_btree_node_set_level(root, level);
1317 n = nilfs_btree_node_get_nchildren(child);
Koji Sato17c76b02009-04-06 19:01:24 -07001318 nilfs_btree_node_move_left(btree, root, child, n);
1319 unlock_buffer(path[level].bp_bh);
1320
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001321 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001322 path[level].bp_bh = NULL;
1323}
1324
1325
1326static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
1327 struct nilfs_btree_path *path,
1328 int *levelp,
1329 struct nilfs_bmap_stats *stats)
1330{
1331 struct buffer_head *bh;
1332 struct nilfs_btree_node *node, *parent, *sib;
1333 __u64 sibptr;
1334 int pindex, level, ret;
1335
1336 ret = 0;
1337 stats->bs_nblocks = 0;
1338 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1339 level < nilfs_btree_height(btree) - 1;
1340 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001341 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001342 path[level].bp_oldreq.bpr_ptr =
1343 nilfs_btree_node_get_ptr(btree, node,
1344 path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001345 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
1346 &path[level].bp_oldreq);
1347 if (ret < 0)
1348 goto err_out_child_node;
Koji Sato17c76b02009-04-06 19:01:24 -07001349
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001350 if (nilfs_btree_node_get_nchildren(node) >
1351 nilfs_btree_node_nchildren_min(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001352 path[level].bp_op = nilfs_btree_do_delete;
1353 stats->bs_nblocks++;
1354 goto out;
1355 }
1356
1357 parent = nilfs_btree_get_node(btree, path, level + 1);
1358 pindex = path[level + 1].bp_index;
1359
1360 if (pindex > 0) {
1361 /* left sibling */
1362 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1363 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001364 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001365 if (ret < 0)
1366 goto err_out_curr_node;
1367 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001368 if (nilfs_btree_node_get_nchildren(sib) >
1369 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001370 path[level].bp_sib_bh = bh;
1371 path[level].bp_op = nilfs_btree_borrow_left;
1372 stats->bs_nblocks++;
1373 goto out;
1374 } else {
1375 path[level].bp_sib_bh = bh;
1376 path[level].bp_op = nilfs_btree_concat_left;
1377 stats->bs_nblocks++;
1378 /* continue; */
1379 }
1380 } else if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001381 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -07001382 /* right sibling */
1383 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1384 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001385 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001386 if (ret < 0)
1387 goto err_out_curr_node;
1388 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001389 if (nilfs_btree_node_get_nchildren(sib) >
1390 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001391 path[level].bp_sib_bh = bh;
1392 path[level].bp_op = nilfs_btree_borrow_right;
1393 stats->bs_nblocks++;
1394 goto out;
1395 } else {
1396 path[level].bp_sib_bh = bh;
1397 path[level].bp_op = nilfs_btree_concat_right;
1398 stats->bs_nblocks++;
1399 /* continue; */
1400 }
1401 } else {
1402 /* no siblings */
1403 /* the only child of the root node */
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001404 WARN_ON(level != nilfs_btree_height(btree) - 2);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001405 if (nilfs_btree_node_get_nchildren(node) - 1 <=
Koji Sato17c76b02009-04-06 19:01:24 -07001406 NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1407 path[level].bp_op = nilfs_btree_shrink;
1408 stats->bs_nblocks += 2;
1409 } else {
1410 path[level].bp_op = nilfs_btree_do_delete;
1411 stats->bs_nblocks++;
1412 }
1413
1414 goto out;
1415
1416 }
1417 }
1418
1419 node = nilfs_btree_get_root(btree);
1420 path[level].bp_oldreq.bpr_ptr =
1421 nilfs_btree_node_get_ptr(btree, node, path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001422
1423 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
1424 &path[level].bp_oldreq);
1425 if (ret < 0)
1426 goto err_out_child_node;
1427
Koji Sato17c76b02009-04-06 19:01:24 -07001428 /* child of the root node is deleted */
1429 path[level].bp_op = nilfs_btree_do_delete;
1430 stats->bs_nblocks++;
1431
1432 /* success */
1433 out:
1434 *levelp = level;
1435 return ret;
1436
1437 /* error */
1438 err_out_curr_node:
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001439 nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001440 err_out_child_node:
1441 for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001442 brelse(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001443 nilfs_bmap_abort_end_ptr(&btree->bt_bmap,
1444 &path[level].bp_oldreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001445 }
1446 *levelp = level;
1447 stats->bs_nblocks = 0;
1448 return ret;
1449}
1450
1451static void nilfs_btree_commit_delete(struct nilfs_btree *btree,
1452 struct nilfs_btree_path *path,
1453 int maxlevel)
1454{
1455 int level;
1456
1457 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001458 nilfs_bmap_commit_end_ptr(&btree->bt_bmap,
1459 &path[level].bp_oldreq);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001460 path[level].bp_op(btree, path, level, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001461 }
1462
1463 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1464 nilfs_bmap_set_dirty(&btree->bt_bmap);
1465}
1466
1467static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key)
1468
1469{
1470 struct nilfs_btree *btree;
1471 struct nilfs_btree_path *path;
1472 struct nilfs_bmap_stats stats;
1473 int level, ret;
1474
1475 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001476 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001477 if (path == NULL)
1478 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001479 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001480 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1481 NILFS_BTREE_LEVEL_NODE_MIN);
1482 if (ret < 0)
1483 goto out;
1484
1485 ret = nilfs_btree_prepare_delete(btree, path, &level, &stats);
1486 if (ret < 0)
1487 goto out;
1488 nilfs_btree_commit_delete(btree, path, level);
1489 nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks);
1490
1491out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09001492 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001493 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001494 return ret;
1495}
1496
1497static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp)
1498{
1499 struct nilfs_btree *btree;
1500 struct nilfs_btree_path *path;
1501 int ret;
1502
1503 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001504 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001505 if (path == NULL)
1506 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001507 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001508
1509 ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL);
1510
Ryusuke Konishi32189292009-08-15 01:54:59 +09001511 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001512 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001513
1514 return ret;
1515}
1516
1517static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key)
1518{
1519 struct buffer_head *bh;
1520 struct nilfs_btree *btree;
1521 struct nilfs_btree_node *root, *node;
1522 __u64 maxkey, nextmaxkey;
1523 __u64 ptr;
1524 int nchildren, ret;
1525
1526 btree = (struct nilfs_btree *)bmap;
1527 root = nilfs_btree_get_root(btree);
1528 switch (nilfs_btree_height(btree)) {
1529 case 2:
1530 bh = NULL;
1531 node = root;
1532 break;
1533 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001534 nchildren = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -07001535 if (nchildren > 1)
1536 return 0;
1537 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001538 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001539 if (ret < 0)
1540 return ret;
1541 node = (struct nilfs_btree_node *)bh->b_data;
1542 break;
1543 default:
1544 return 0;
1545 }
1546
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001547 nchildren = nilfs_btree_node_get_nchildren(node);
1548 maxkey = nilfs_btree_node_get_key(node, nchildren - 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001549 nextmaxkey = (nchildren > 1) ?
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001550 nilfs_btree_node_get_key(node, nchildren - 2) : 0;
Koji Sato17c76b02009-04-06 19:01:24 -07001551 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001552 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001553
Ryusuke Konishi30333422009-05-24 00:09:44 +09001554 return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
Koji Sato17c76b02009-04-06 19:01:24 -07001555}
1556
1557static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
1558 __u64 *keys, __u64 *ptrs, int nitems)
1559{
1560 struct buffer_head *bh;
1561 struct nilfs_btree *btree;
1562 struct nilfs_btree_node *node, *root;
1563 __le64 *dkeys;
1564 __le64 *dptrs;
1565 __u64 ptr;
1566 int nchildren, i, ret;
1567
1568 btree = (struct nilfs_btree *)bmap;
1569 root = nilfs_btree_get_root(btree);
1570 switch (nilfs_btree_height(btree)) {
1571 case 2:
1572 bh = NULL;
1573 node = root;
1574 break;
1575 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001576 nchildren = nilfs_btree_node_get_nchildren(root);
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001577 WARN_ON(nchildren > 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001578 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001579 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001580 if (ret < 0)
1581 return ret;
1582 node = (struct nilfs_btree_node *)bh->b_data;
1583 break;
1584 default:
1585 node = NULL;
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001586 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -07001587 }
1588
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001589 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001590 if (nchildren < nitems)
1591 nitems = nchildren;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001592 dkeys = nilfs_btree_node_dkeys(node);
1593 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001594 for (i = 0; i < nitems; i++) {
1595 keys[i] = nilfs_bmap_dkey_to_key(dkeys[i]);
1596 ptrs[i] = nilfs_bmap_dptr_to_ptr(dptrs[i]);
1597 }
1598
1599 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001600 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001601
1602 return nitems;
1603}
1604
1605static int
1606nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
1607 union nilfs_bmap_ptr_req *dreq,
1608 union nilfs_bmap_ptr_req *nreq,
1609 struct buffer_head **bhp,
1610 struct nilfs_bmap_stats *stats)
1611{
1612 struct buffer_head *bh;
1613 struct nilfs_btree *btree;
1614 int ret;
1615
1616 btree = (struct nilfs_btree *)bmap;
1617 stats->bs_nblocks = 0;
1618
1619 /* for data */
1620 /* cannot find near ptr */
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001621 if (NILFS_BMAP_USE_VBN(bmap))
1622 dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
1623
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001624 ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001625 if (ret < 0)
1626 return ret;
1627
1628 *bhp = NULL;
1629 stats->bs_nblocks++;
1630 if (nreq != NULL) {
1631 nreq->bpr_ptr = dreq->bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001632 ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001633 if (ret < 0)
1634 goto err_out_dreq;
1635
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001636 ret = nilfs_btree_get_new_block(btree, nreq->bpr_ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001637 if (ret < 0)
1638 goto err_out_nreq;
1639
1640 *bhp = bh;
1641 stats->bs_nblocks++;
1642 }
1643
1644 /* success */
1645 return 0;
1646
1647 /* error */
1648 err_out_nreq:
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001649 nilfs_bmap_abort_alloc_ptr(bmap, nreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001650 err_out_dreq:
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001651 nilfs_bmap_abort_alloc_ptr(bmap, dreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001652 stats->bs_nblocks = 0;
1653 return ret;
1654
1655}
1656
1657static void
1658nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
1659 __u64 key, __u64 ptr,
1660 const __u64 *keys, const __u64 *ptrs,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001661 int n,
Koji Sato17c76b02009-04-06 19:01:24 -07001662 union nilfs_bmap_ptr_req *dreq,
1663 union nilfs_bmap_ptr_req *nreq,
1664 struct buffer_head *bh)
1665{
1666 struct nilfs_btree *btree;
1667 struct nilfs_btree_node *node;
1668 __u64 tmpptr;
1669
1670 /* free resources */
1671 if (bmap->b_ops->bop_clear != NULL)
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001672 bmap->b_ops->bop_clear(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001673
1674 /* ptr must be a pointer to a buffer head. */
1675 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1676
1677 /* convert and insert */
1678 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi30333422009-05-24 00:09:44 +09001679 nilfs_btree_init(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001680 if (nreq != NULL) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001681 nilfs_bmap_commit_alloc_ptr(bmap, dreq);
1682 nilfs_bmap_commit_alloc_ptr(bmap, nreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001683
1684 /* create child node at level 1 */
1685 lock_buffer(bh);
1686 node = (struct nilfs_btree_node *)bh->b_data;
1687 nilfs_btree_node_init(btree, node, 0, 1, n, keys, ptrs);
1688 nilfs_btree_node_insert(btree, node,
1689 key, dreq->bpr_ptr, n);
1690 if (!buffer_dirty(bh))
1691 nilfs_btnode_mark_dirty(bh);
1692 if (!nilfs_bmap_dirty(bmap))
1693 nilfs_bmap_set_dirty(bmap);
1694
1695 unlock_buffer(bh);
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001696 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001697
1698 /* create root node at level 2 */
1699 node = nilfs_btree_get_root(btree);
1700 tmpptr = nreq->bpr_ptr;
1701 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1702 2, 1, &keys[0], &tmpptr);
1703 } else {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001704 nilfs_bmap_commit_alloc_ptr(bmap, dreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001705
1706 /* create root node at level 1 */
1707 node = nilfs_btree_get_root(btree);
1708 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1709 1, n, keys, ptrs);
1710 nilfs_btree_node_insert(btree, node,
1711 key, dreq->bpr_ptr, n);
1712 if (!nilfs_bmap_dirty(bmap))
1713 nilfs_bmap_set_dirty(bmap);
1714 }
1715
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001716 if (NILFS_BMAP_USE_VBN(bmap))
1717 nilfs_btree_set_target_v(btree, key, dreq->bpr_ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001718}
1719
1720/**
1721 * nilfs_btree_convert_and_insert -
1722 * @bmap:
1723 * @key:
1724 * @ptr:
1725 * @keys:
1726 * @ptrs:
1727 * @n:
Koji Sato17c76b02009-04-06 19:01:24 -07001728 */
1729int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap,
1730 __u64 key, __u64 ptr,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001731 const __u64 *keys, const __u64 *ptrs, int n)
Koji Sato17c76b02009-04-06 19:01:24 -07001732{
1733 struct buffer_head *bh;
1734 union nilfs_bmap_ptr_req dreq, nreq, *di, *ni;
1735 struct nilfs_bmap_stats stats;
1736 int ret;
1737
1738 if (n + 1 <= NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1739 di = &dreq;
1740 ni = NULL;
1741 } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX(
1742 1 << bmap->b_inode->i_blkbits)) {
1743 di = &dreq;
1744 ni = &nreq;
1745 } else {
1746 di = NULL;
1747 ni = NULL;
1748 BUG();
1749 }
1750
1751 ret = nilfs_btree_prepare_convert_and_insert(bmap, key, di, ni, &bh,
1752 &stats);
1753 if (ret < 0)
1754 return ret;
1755 nilfs_btree_commit_convert_and_insert(bmap, key, ptr, keys, ptrs, n,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001756 di, ni, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001757 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1758 return 0;
1759}
1760
1761static int nilfs_btree_propagate_p(struct nilfs_btree *btree,
1762 struct nilfs_btree_path *path,
1763 int level,
1764 struct buffer_head *bh)
1765{
1766 while ((++level < nilfs_btree_height(btree) - 1) &&
1767 !buffer_dirty(path[level].bp_bh))
1768 nilfs_btnode_mark_dirty(path[level].bp_bh);
1769
1770 return 0;
1771}
1772
1773static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
1774 struct nilfs_btree_path *path,
1775 int level)
1776{
1777 struct nilfs_btree_node *parent;
1778 int ret;
1779
1780 parent = nilfs_btree_get_node(btree, path, level + 1);
1781 path[level].bp_oldreq.bpr_ptr =
1782 nilfs_btree_node_get_ptr(btree, parent,
1783 path[level + 1].bp_index);
1784 path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001785 ret = nilfs_bmap_prepare_update_v(&btree->bt_bmap,
1786 &path[level].bp_oldreq,
1787 &path[level].bp_newreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001788 if (ret < 0)
1789 return ret;
1790
1791 if (buffer_nilfs_node(path[level].bp_bh)) {
1792 path[level].bp_ctxt.oldkey = path[level].bp_oldreq.bpr_ptr;
1793 path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr;
1794 path[level].bp_ctxt.bh = path[level].bp_bh;
1795 ret = nilfs_btnode_prepare_change_key(
1796 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1797 &path[level].bp_ctxt);
1798 if (ret < 0) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001799 nilfs_bmap_abort_update_v(&btree->bt_bmap,
1800 &path[level].bp_oldreq,
1801 &path[level].bp_newreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001802 return ret;
1803 }
1804 }
1805
1806 return 0;
1807}
1808
1809static void nilfs_btree_commit_update_v(struct nilfs_btree *btree,
1810 struct nilfs_btree_path *path,
1811 int level)
1812{
1813 struct nilfs_btree_node *parent;
1814
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001815 nilfs_bmap_commit_update_v(&btree->bt_bmap,
1816 &path[level].bp_oldreq,
1817 &path[level].bp_newreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001818
1819 if (buffer_nilfs_node(path[level].bp_bh)) {
1820 nilfs_btnode_commit_change_key(
1821 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1822 &path[level].bp_ctxt);
1823 path[level].bp_bh = path[level].bp_ctxt.bh;
1824 }
1825 set_buffer_nilfs_volatile(path[level].bp_bh);
1826
1827 parent = nilfs_btree_get_node(btree, path, level + 1);
1828 nilfs_btree_node_set_ptr(btree, parent, path[level + 1].bp_index,
1829 path[level].bp_newreq.bpr_ptr);
1830}
1831
1832static void nilfs_btree_abort_update_v(struct nilfs_btree *btree,
1833 struct nilfs_btree_path *path,
1834 int level)
1835{
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001836 nilfs_bmap_abort_update_v(&btree->bt_bmap,
1837 &path[level].bp_oldreq,
1838 &path[level].bp_newreq);
Koji Sato17c76b02009-04-06 19:01:24 -07001839 if (buffer_nilfs_node(path[level].bp_bh))
1840 nilfs_btnode_abort_change_key(
1841 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1842 &path[level].bp_ctxt);
1843}
1844
1845static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree,
1846 struct nilfs_btree_path *path,
1847 int minlevel,
1848 int *maxlevelp)
1849{
1850 int level, ret;
1851
1852 level = minlevel;
1853 if (!buffer_nilfs_volatile(path[level].bp_bh)) {
1854 ret = nilfs_btree_prepare_update_v(btree, path, level);
1855 if (ret < 0)
1856 return ret;
1857 }
1858 while ((++level < nilfs_btree_height(btree) - 1) &&
1859 !buffer_dirty(path[level].bp_bh)) {
1860
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001861 WARN_ON(buffer_nilfs_volatile(path[level].bp_bh));
Koji Sato17c76b02009-04-06 19:01:24 -07001862 ret = nilfs_btree_prepare_update_v(btree, path, level);
1863 if (ret < 0)
1864 goto out;
1865 }
1866
1867 /* success */
Koji Sato17c76b02009-04-06 19:01:24 -07001868 *maxlevelp = level - 1;
1869 return 0;
1870
1871 /* error */
1872 out:
1873 while (--level > minlevel)
1874 nilfs_btree_abort_update_v(btree, path, level);
1875 if (!buffer_nilfs_volatile(path[level].bp_bh))
1876 nilfs_btree_abort_update_v(btree, path, level);
1877 return ret;
1878}
1879
1880static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree,
1881 struct nilfs_btree_path *path,
1882 int minlevel,
1883 int maxlevel,
1884 struct buffer_head *bh)
1885{
1886 int level;
1887
1888 if (!buffer_nilfs_volatile(path[minlevel].bp_bh))
1889 nilfs_btree_commit_update_v(btree, path, minlevel);
1890
1891 for (level = minlevel + 1; level <= maxlevel; level++)
1892 nilfs_btree_commit_update_v(btree, path, level);
1893}
1894
1895static int nilfs_btree_propagate_v(struct nilfs_btree *btree,
1896 struct nilfs_btree_path *path,
1897 int level,
1898 struct buffer_head *bh)
1899{
1900 int maxlevel, ret;
1901 struct nilfs_btree_node *parent;
1902 __u64 ptr;
1903
1904 get_bh(bh);
1905 path[level].bp_bh = bh;
1906 ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel);
1907 if (ret < 0)
1908 goto out;
1909
1910 if (buffer_nilfs_volatile(path[level].bp_bh)) {
1911 parent = nilfs_btree_get_node(btree, path, level + 1);
1912 ptr = nilfs_btree_node_get_ptr(btree, parent,
1913 path[level + 1].bp_index);
1914 ret = nilfs_bmap_mark_dirty(&btree->bt_bmap, ptr);
1915 if (ret < 0)
1916 goto out;
1917 }
1918
1919 nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh);
1920
1921 out:
1922 brelse(path[level].bp_bh);
1923 path[level].bp_bh = NULL;
1924 return ret;
1925}
1926
1927static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
1928 struct buffer_head *bh)
1929{
1930 struct nilfs_btree *btree;
1931 struct nilfs_btree_path *path;
1932 struct nilfs_btree_node *node;
1933 __u64 key;
1934 int level, ret;
1935
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001936 WARN_ON(!buffer_dirty(bh));
Koji Sato17c76b02009-04-06 19:01:24 -07001937
1938 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001939 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001940 if (path == NULL)
1941 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001942 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001943
1944 if (buffer_nilfs_node(bh)) {
1945 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001946 key = nilfs_btree_node_get_key(node, 0);
1947 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001948 } else {
1949 key = nilfs_bmap_data_get_key(bmap, bh);
1950 level = NILFS_BTREE_LEVEL_DATA;
1951 }
1952
1953 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
1954 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001955 if (unlikely(ret == -ENOENT))
Koji Sato17c76b02009-04-06 19:01:24 -07001956 printk(KERN_CRIT "%s: key = %llu, level == %d\n",
1957 __func__, (unsigned long long)key, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001958 goto out;
1959 }
1960
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001961 ret = NILFS_BMAP_USE_VBN(bmap) ?
1962 nilfs_btree_propagate_v(btree, path, level, bh) :
1963 nilfs_btree_propagate_p(btree, path, level, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001964
1965 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09001966 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001967 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001968
1969 return ret;
1970}
1971
1972static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap,
1973 struct buffer_head *bh)
1974{
1975 return nilfs_bmap_mark_dirty(bmap, bh->b_blocknr);
1976}
1977
1978static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree,
1979 struct list_head *lists,
1980 struct buffer_head *bh)
1981{
1982 struct list_head *head;
1983 struct buffer_head *cbh;
1984 struct nilfs_btree_node *node, *cnode;
1985 __u64 key, ckey;
1986 int level;
1987
1988 get_bh(bh);
1989 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001990 key = nilfs_btree_node_get_key(node, 0);
1991 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001992 list_for_each(head, &lists[level]) {
1993 cbh = list_entry(head, struct buffer_head, b_assoc_buffers);
1994 cnode = (struct nilfs_btree_node *)cbh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001995 ckey = nilfs_btree_node_get_key(cnode, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07001996 if (key < ckey)
1997 break;
1998 }
1999 list_add_tail(&bh->b_assoc_buffers, head);
2000}
2001
2002static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *bmap,
2003 struct list_head *listp)
2004{
2005 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
2006 struct address_space *btcache = &NILFS_BMAP_I(bmap)->i_btnode_cache;
2007 struct list_head lists[NILFS_BTREE_LEVEL_MAX];
2008 struct pagevec pvec;
2009 struct buffer_head *bh, *head;
2010 pgoff_t index = 0;
2011 int level, i;
2012
2013 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
2014 level < NILFS_BTREE_LEVEL_MAX;
2015 level++)
2016 INIT_LIST_HEAD(&lists[level]);
2017
2018 pagevec_init(&pvec, 0);
2019
2020 while (pagevec_lookup_tag(&pvec, btcache, &index, PAGECACHE_TAG_DIRTY,
2021 PAGEVEC_SIZE)) {
2022 for (i = 0; i < pagevec_count(&pvec); i++) {
2023 bh = head = page_buffers(pvec.pages[i]);
2024 do {
2025 if (buffer_dirty(bh))
2026 nilfs_btree_add_dirty_buffer(btree,
2027 lists, bh);
2028 } while ((bh = bh->b_this_page) != head);
2029 }
2030 pagevec_release(&pvec);
2031 cond_resched();
2032 }
2033
2034 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
2035 level < NILFS_BTREE_LEVEL_MAX;
2036 level++)
2037 list_splice(&lists[level], listp->prev);
2038}
2039
2040static int nilfs_btree_assign_p(struct nilfs_btree *btree,
2041 struct nilfs_btree_path *path,
2042 int level,
2043 struct buffer_head **bh,
2044 sector_t blocknr,
2045 union nilfs_binfo *binfo)
2046{
2047 struct nilfs_btree_node *parent;
2048 __u64 key;
2049 __u64 ptr;
2050 int ret;
2051
2052 parent = nilfs_btree_get_node(btree, path, level + 1);
2053 ptr = nilfs_btree_node_get_ptr(btree, parent,
2054 path[level + 1].bp_index);
2055 if (buffer_nilfs_node(*bh)) {
2056 path[level].bp_ctxt.oldkey = ptr;
2057 path[level].bp_ctxt.newkey = blocknr;
2058 path[level].bp_ctxt.bh = *bh;
2059 ret = nilfs_btnode_prepare_change_key(
2060 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2061 &path[level].bp_ctxt);
2062 if (ret < 0)
2063 return ret;
2064 nilfs_btnode_commit_change_key(
2065 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2066 &path[level].bp_ctxt);
2067 *bh = path[level].bp_ctxt.bh;
2068 }
2069
2070 nilfs_btree_node_set_ptr(btree, parent,
2071 path[level + 1].bp_index, blocknr);
2072
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002073 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002074 /* on-disk format */
2075 binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2076 binfo->bi_dat.bi_level = level;
2077
2078 return 0;
2079}
2080
2081static int nilfs_btree_assign_v(struct nilfs_btree *btree,
2082 struct nilfs_btree_path *path,
2083 int level,
2084 struct buffer_head **bh,
2085 sector_t blocknr,
2086 union nilfs_binfo *binfo)
2087{
2088 struct nilfs_btree_node *parent;
2089 __u64 key;
2090 __u64 ptr;
2091 union nilfs_bmap_ptr_req req;
2092 int ret;
2093
2094 parent = nilfs_btree_get_node(btree, path, level + 1);
2095 ptr = nilfs_btree_node_get_ptr(btree, parent,
2096 path[level + 1].bp_index);
2097 req.bpr_ptr = ptr;
Ryusuke Konishid97a51a2009-05-03 21:43:01 +09002098 ret = nilfs_bmap_start_v(&btree->bt_bmap, &req, blocknr);
2099 if (unlikely(ret < 0))
Koji Sato17c76b02009-04-06 19:01:24 -07002100 return ret;
Koji Sato17c76b02009-04-06 19:01:24 -07002101
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002102 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002103 /* on-disk format */
2104 binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr);
2105 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2106
2107 return 0;
2108}
2109
2110static int nilfs_btree_assign(struct nilfs_bmap *bmap,
2111 struct buffer_head **bh,
2112 sector_t blocknr,
2113 union nilfs_binfo *binfo)
2114{
2115 struct nilfs_btree *btree;
2116 struct nilfs_btree_path *path;
2117 struct nilfs_btree_node *node;
2118 __u64 key;
2119 int level, ret;
2120
2121 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002122 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002123 if (path == NULL)
2124 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002125 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002126
2127 if (buffer_nilfs_node(*bh)) {
2128 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002129 key = nilfs_btree_node_get_key(node, 0);
2130 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07002131 } else {
2132 key = nilfs_bmap_data_get_key(bmap, *bh);
2133 level = NILFS_BTREE_LEVEL_DATA;
2134 }
2135
2136 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
2137 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002138 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002139 goto out;
2140 }
2141
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09002142 ret = NILFS_BMAP_USE_VBN(bmap) ?
2143 nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) :
2144 nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
Koji Sato17c76b02009-04-06 19:01:24 -07002145
2146 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09002147 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002148 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002149
2150 return ret;
2151}
2152
2153static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap,
2154 struct buffer_head **bh,
2155 sector_t blocknr,
2156 union nilfs_binfo *binfo)
2157{
2158 struct nilfs_btree *btree;
2159 struct nilfs_btree_node *node;
2160 __u64 key;
2161 int ret;
2162
2163 btree = (struct nilfs_btree *)bmap;
2164 ret = nilfs_bmap_move_v(bmap, (*bh)->b_blocknr, blocknr);
2165 if (ret < 0)
2166 return ret;
2167
2168 if (buffer_nilfs_node(*bh)) {
2169 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002170 key = nilfs_btree_node_get_key(node, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07002171 } else
2172 key = nilfs_bmap_data_get_key(bmap, *bh);
2173
2174 /* on-disk format */
2175 binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr);
2176 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2177
2178 return 0;
2179}
2180
2181static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
2182{
2183 struct buffer_head *bh;
2184 struct nilfs_btree *btree;
2185 struct nilfs_btree_path *path;
2186 __u64 ptr;
2187 int ret;
2188
2189 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002190 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002191 if (path == NULL)
2192 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002193 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002194
2195 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1);
2196 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002197 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002198 goto out;
2199 }
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09002200 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002201 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002202 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002203 goto out;
2204 }
2205
2206 if (!buffer_dirty(bh))
2207 nilfs_btnode_mark_dirty(bh);
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09002208 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002209 if (!nilfs_bmap_dirty(&btree->bt_bmap))
2210 nilfs_bmap_set_dirty(&btree->bt_bmap);
2211
2212 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09002213 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002214 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002215 return ret;
2216}
2217
2218static const struct nilfs_bmap_operations nilfs_btree_ops = {
2219 .bop_lookup = nilfs_btree_lookup,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002220 .bop_lookup_contig = nilfs_btree_lookup_contig,
Koji Sato17c76b02009-04-06 19:01:24 -07002221 .bop_insert = nilfs_btree_insert,
2222 .bop_delete = nilfs_btree_delete,
2223 .bop_clear = NULL,
2224
2225 .bop_propagate = nilfs_btree_propagate,
2226
2227 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2228
2229 .bop_assign = nilfs_btree_assign,
2230 .bop_mark = nilfs_btree_mark,
2231
2232 .bop_last_key = nilfs_btree_last_key,
2233 .bop_check_insert = NULL,
2234 .bop_check_delete = nilfs_btree_check_delete,
2235 .bop_gather_data = nilfs_btree_gather_data,
2236};
2237
2238static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
2239 .bop_lookup = NULL,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002240 .bop_lookup_contig = NULL,
Koji Sato17c76b02009-04-06 19:01:24 -07002241 .bop_insert = NULL,
2242 .bop_delete = NULL,
2243 .bop_clear = NULL,
2244
2245 .bop_propagate = nilfs_btree_propagate_gc,
2246
2247 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2248
2249 .bop_assign = nilfs_btree_assign_gc,
2250 .bop_mark = NULL,
2251
2252 .bop_last_key = NULL,
2253 .bop_check_insert = NULL,
2254 .bop_check_delete = NULL,
2255 .bop_gather_data = NULL,
2256};
2257
Ryusuke Konishi30333422009-05-24 00:09:44 +09002258int nilfs_btree_init(struct nilfs_bmap *bmap)
Koji Sato17c76b02009-04-06 19:01:24 -07002259{
Koji Sato17c76b02009-04-06 19:01:24 -07002260 bmap->b_ops = &nilfs_btree_ops;
Koji Sato17c76b02009-04-06 19:01:24 -07002261 return 0;
2262}
2263
2264void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
2265{
Koji Sato17c76b02009-04-06 19:01:24 -07002266 bmap->b_ops = &nilfs_btree_ops_gc;
2267}