blob: 7b0cc4fe9f0dedafa521a352b597265288187d92 [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;
Ryusuke Konishi45f49102009-11-13 16:25:19 +0900125 struct buffer_head *bh;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900126
Ryusuke Konishi45f49102009-11-13 16:25:19 +0900127 bh = nilfs_btnode_create_block(btnc, ptr);
128 if (!bh)
129 return -ENOMEM;
130
131 set_buffer_nilfs_volatile(bh);
132 *bhp = bh;
133 return 0;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900134}
Koji Sato17c76b02009-04-06 19:01:24 -0700135
136static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900137nilfs_btree_node_get_flags(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700138{
139 return node->bn_flags;
140}
141
142static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900143nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags)
Koji Sato17c76b02009-04-06 19:01:24 -0700144{
145 node->bn_flags = flags;
146}
147
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900148static inline int nilfs_btree_node_root(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700149{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900150 return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT;
Koji Sato17c76b02009-04-06 19:01:24 -0700151}
152
153static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900154nilfs_btree_node_get_level(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700155{
156 return node->bn_level;
157}
158
159static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900160nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700161{
162 node->bn_level = level;
163}
164
165static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900166nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700167{
168 return le16_to_cpu(node->bn_nchildren);
169}
170
171static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900172nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren)
Koji Sato17c76b02009-04-06 19:01:24 -0700173{
174 node->bn_nchildren = cpu_to_le16(nchildren);
175}
176
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900177static inline int nilfs_btree_node_size(const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700178{
179 return 1 << btree->bt_bmap.b_inode->i_blkbits;
180}
181
182static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900183nilfs_btree_node_nchildren_min(const struct nilfs_btree_node *node,
184 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700185{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900186 return nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700187 NILFS_BTREE_ROOT_NCHILDREN_MIN :
188 NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree));
189}
190
191static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900192nilfs_btree_node_nchildren_max(const struct nilfs_btree_node *node,
193 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700194{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900195 return nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700196 NILFS_BTREE_ROOT_NCHILDREN_MAX :
197 NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree));
198}
199
200static inline __le64 *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900201nilfs_btree_node_dkeys(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700202{
203 return (__le64 *)((char *)(node + 1) +
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900204 (nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700205 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE));
206}
207
208static inline __le64 *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900209nilfs_btree_node_dptrs(const struct nilfs_btree_node *node,
210 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700211{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900212 return (__le64 *)(nilfs_btree_node_dkeys(node) +
213 nilfs_btree_node_nchildren_max(node, btree));
Koji Sato17c76b02009-04-06 19:01:24 -0700214}
215
216static inline __u64
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900217nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index)
Koji Sato17c76b02009-04-06 19:01:24 -0700218{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900219 return nilfs_bmap_dkey_to_key(*(nilfs_btree_node_dkeys(node) + index));
Koji Sato17c76b02009-04-06 19:01:24 -0700220}
221
222static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900223nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key)
Koji Sato17c76b02009-04-06 19:01:24 -0700224{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900225 *(nilfs_btree_node_dkeys(node) + index) = nilfs_bmap_key_to_dkey(key);
Koji Sato17c76b02009-04-06 19:01:24 -0700226}
227
228static inline __u64
229nilfs_btree_node_get_ptr(const struct nilfs_btree *btree,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900230 const struct nilfs_btree_node *node, int index)
Koji Sato17c76b02009-04-06 19:01:24 -0700231{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900232 return nilfs_bmap_dptr_to_ptr(*(nilfs_btree_node_dptrs(node, btree) +
Koji Sato17c76b02009-04-06 19:01:24 -0700233 index));
234}
235
236static inline void
237nilfs_btree_node_set_ptr(struct nilfs_btree *btree,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900238 struct nilfs_btree_node *node, int index, __u64 ptr)
Koji Sato17c76b02009-04-06 19:01:24 -0700239{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900240 *(nilfs_btree_node_dptrs(node, btree) + index) =
Koji Sato17c76b02009-04-06 19:01:24 -0700241 nilfs_bmap_ptr_to_dptr(ptr);
242}
243
244static void nilfs_btree_node_init(struct nilfs_btree *btree,
245 struct nilfs_btree_node *node,
246 int flags, int level, int nchildren,
247 const __u64 *keys, const __u64 *ptrs)
248{
249 __le64 *dkeys;
250 __le64 *dptrs;
251 int i;
252
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900253 nilfs_btree_node_set_flags(node, flags);
254 nilfs_btree_node_set_level(node, level);
255 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700256
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900257 dkeys = nilfs_btree_node_dkeys(node);
258 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700259 for (i = 0; i < nchildren; i++) {
260 dkeys[i] = nilfs_bmap_key_to_dkey(keys[i]);
261 dptrs[i] = nilfs_bmap_ptr_to_dptr(ptrs[i]);
262 }
263}
264
265/* Assume the buffer heads corresponding to left and right are locked. */
266static void nilfs_btree_node_move_left(struct nilfs_btree *btree,
267 struct nilfs_btree_node *left,
268 struct nilfs_btree_node *right,
269 int n)
270{
271 __le64 *ldkeys, *rdkeys;
272 __le64 *ldptrs, *rdptrs;
273 int lnchildren, rnchildren;
274
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900275 ldkeys = nilfs_btree_node_dkeys(left);
276 ldptrs = nilfs_btree_node_dptrs(left, btree);
277 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700278
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900279 rdkeys = nilfs_btree_node_dkeys(right);
280 rdptrs = nilfs_btree_node_dptrs(right, btree);
281 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700282
283 memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys));
284 memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs));
285 memmove(rdkeys, rdkeys + n, (rnchildren - n) * sizeof(*rdkeys));
286 memmove(rdptrs, rdptrs + n, (rnchildren - n) * sizeof(*rdptrs));
287
288 lnchildren += n;
289 rnchildren -= n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900290 nilfs_btree_node_set_nchildren(left, lnchildren);
291 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700292}
293
294/* Assume that the buffer heads corresponding to left and right are locked. */
295static void nilfs_btree_node_move_right(struct nilfs_btree *btree,
296 struct nilfs_btree_node *left,
297 struct nilfs_btree_node *right,
298 int n)
299{
300 __le64 *ldkeys, *rdkeys;
301 __le64 *ldptrs, *rdptrs;
302 int lnchildren, rnchildren;
303
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900304 ldkeys = nilfs_btree_node_dkeys(left);
305 ldptrs = nilfs_btree_node_dptrs(left, btree);
306 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700307
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900308 rdkeys = nilfs_btree_node_dkeys(right);
309 rdptrs = nilfs_btree_node_dptrs(right, btree);
310 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700311
312 memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys));
313 memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs));
314 memcpy(rdkeys, ldkeys + lnchildren - n, n * sizeof(*rdkeys));
315 memcpy(rdptrs, ldptrs + lnchildren - n, n * sizeof(*rdptrs));
316
317 lnchildren -= n;
318 rnchildren += n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900319 nilfs_btree_node_set_nchildren(left, lnchildren);
320 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700321}
322
323/* Assume that the buffer head corresponding to node is locked. */
324static void nilfs_btree_node_insert(struct nilfs_btree *btree,
325 struct nilfs_btree_node *node,
326 __u64 key, __u64 ptr, int index)
327{
328 __le64 *dkeys;
329 __le64 *dptrs;
330 int nchildren;
331
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900332 dkeys = nilfs_btree_node_dkeys(node);
333 dptrs = nilfs_btree_node_dptrs(node, btree);
334 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700335 if (index < nchildren) {
336 memmove(dkeys + index + 1, dkeys + index,
337 (nchildren - index) * sizeof(*dkeys));
338 memmove(dptrs + index + 1, dptrs + index,
339 (nchildren - index) * sizeof(*dptrs));
340 }
341 dkeys[index] = nilfs_bmap_key_to_dkey(key);
342 dptrs[index] = nilfs_bmap_ptr_to_dptr(ptr);
343 nchildren++;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900344 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700345}
346
347/* Assume that the buffer head corresponding to node is locked. */
348static void nilfs_btree_node_delete(struct nilfs_btree *btree,
349 struct nilfs_btree_node *node,
350 __u64 *keyp, __u64 *ptrp, int index)
351{
352 __u64 key;
353 __u64 ptr;
354 __le64 *dkeys;
355 __le64 *dptrs;
356 int nchildren;
357
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900358 dkeys = nilfs_btree_node_dkeys(node);
359 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700360 key = nilfs_bmap_dkey_to_key(dkeys[index]);
361 ptr = nilfs_bmap_dptr_to_ptr(dptrs[index]);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900362 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700363 if (keyp != NULL)
364 *keyp = key;
365 if (ptrp != NULL)
366 *ptrp = ptr;
367
368 if (index < nchildren - 1) {
369 memmove(dkeys + index, dkeys + index + 1,
370 (nchildren - index - 1) * sizeof(*dkeys));
371 memmove(dptrs + index, dptrs + index + 1,
372 (nchildren - index - 1) * sizeof(*dptrs));
373 }
374 nchildren--;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900375 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700376}
377
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900378static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node,
Koji Sato17c76b02009-04-06 19:01:24 -0700379 __u64 key, int *indexp)
380{
381 __u64 nkey;
382 int index, low, high, s;
383
384 /* binary search */
385 low = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900386 high = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700387 index = 0;
388 s = 0;
389 while (low <= high) {
390 index = (low + high) / 2;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900391 nkey = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700392 if (nkey == key) {
393 s = 0;
394 goto out;
395 } else if (nkey < key) {
396 low = index + 1;
397 s = -1;
398 } else {
399 high = index - 1;
400 s = 1;
401 }
402 }
403
404 /* adjust index */
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900405 if (nilfs_btree_node_get_level(node) > NILFS_BTREE_LEVEL_NODE_MIN) {
406 if (s > 0 && index > 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700407 index--;
408 } else if (s < 0)
409 index++;
410
411 out:
Koji Sato17c76b02009-04-06 19:01:24 -0700412 *indexp = index;
413
414 return s == 0;
415}
416
417static inline struct nilfs_btree_node *
418nilfs_btree_get_root(const struct nilfs_btree *btree)
419{
420 return (struct nilfs_btree_node *)btree->bt_bmap.b_u.u_data;
421}
422
423static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900424nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700425{
426 return (struct nilfs_btree_node *)path[level].bp_bh->b_data;
427}
428
429static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900430nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700431{
432 return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data;
433}
434
435static inline int nilfs_btree_height(const struct nilfs_btree *btree)
436{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900437 return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700438}
439
440static inline struct nilfs_btree_node *
441nilfs_btree_get_node(const struct nilfs_btree *btree,
442 const struct nilfs_btree_path *path,
443 int level)
444{
445 return (level == nilfs_btree_height(btree) - 1) ?
446 nilfs_btree_get_root(btree) :
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900447 nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700448}
449
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900450static inline int
451nilfs_btree_bad_node(struct nilfs_btree_node *node, int level)
452{
453 if (unlikely(nilfs_btree_node_get_level(node) != level)) {
454 dump_stack();
455 printk(KERN_CRIT "NILFS: btree level mismatch: %d != %d\n",
456 nilfs_btree_node_get_level(node), level);
457 return 1;
458 }
459 return 0;
460}
461
Koji Sato17c76b02009-04-06 19:01:24 -0700462static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
463 struct nilfs_btree_path *path,
464 __u64 key, __u64 *ptrp, int minlevel)
465{
466 struct nilfs_btree_node *node;
467 __u64 ptr;
468 int level, index, found, ret;
469
Koji Sato17c76b02009-04-06 19:01:24 -0700470 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900471 level = nilfs_btree_node_get_level(node);
472 if (level < minlevel || nilfs_btree_node_get_nchildren(node) <= 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700473 return -ENOENT;
474
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900475 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700476 ptr = nilfs_btree_node_get_ptr(btree, node, index);
477 path[level].bp_bh = NULL;
478 path[level].bp_index = index;
479
480 for (level--; level >= minlevel; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900481 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700482 if (ret < 0)
483 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900484 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900485 if (nilfs_btree_bad_node(node, level))
486 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -0700487 if (!found)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900488 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700489 else
490 index = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900491 if (index < nilfs_btree_node_nchildren_max(node, btree))
Koji Sato17c76b02009-04-06 19:01:24 -0700492 ptr = nilfs_btree_node_get_ptr(btree, node, index);
493 else {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700494 WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN);
Koji Sato17c76b02009-04-06 19:01:24 -0700495 /* insert */
496 ptr = NILFS_BMAP_INVALID_PTR;
497 }
498 path[level].bp_index = index;
499 }
500 if (!found)
501 return -ENOENT;
502
503 if (ptrp != NULL)
504 *ptrp = ptr;
505
506 return 0;
507}
508
509static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree,
510 struct nilfs_btree_path *path,
511 __u64 *keyp, __u64 *ptrp)
512{
513 struct nilfs_btree_node *node;
514 __u64 ptr;
515 int index, level, ret;
516
517 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900518 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700519 if (index < 0)
520 return -ENOENT;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900521 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700522 ptr = nilfs_btree_node_get_ptr(btree, node, index);
523 path[level].bp_bh = NULL;
524 path[level].bp_index = index;
525
526 for (level--; level > 0; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900527 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700528 if (ret < 0)
529 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900530 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900531 if (nilfs_btree_bad_node(node, level))
532 return -EINVAL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900533 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700534 ptr = nilfs_btree_node_get_ptr(btree, node, index);
535 path[level].bp_index = index;
536 }
537
538 if (keyp != NULL)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900539 *keyp = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700540 if (ptrp != NULL)
541 *ptrp = ptr;
542
543 return 0;
544}
545
546static int nilfs_btree_lookup(const struct nilfs_bmap *bmap,
547 __u64 key, int level, __u64 *ptrp)
548{
549 struct nilfs_btree *btree;
550 struct nilfs_btree_path *path;
551 __u64 ptr;
552 int ret;
553
554 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900555 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -0700556 if (path == NULL)
557 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900558 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -0700559
560 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
561
562 if (ptrp != NULL)
563 *ptrp = ptr;
564
Ryusuke Konishi32189292009-08-15 01:54:59 +0900565 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900566 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -0700567
568 return ret;
569}
570
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900571static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
572 __u64 key, __u64 *ptrp, unsigned maxblocks)
573{
574 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
575 struct nilfs_btree_path *path;
576 struct nilfs_btree_node *node;
577 struct inode *dat = NULL;
578 __u64 ptr, ptr2;
579 sector_t blocknr;
580 int level = NILFS_BTREE_LEVEL_NODE_MIN;
581 int ret, cnt, index, maxlevel;
582
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900583 path = nilfs_btree_alloc_path();
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900584 if (path == NULL)
585 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900586 nilfs_btree_init_path(path);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900587 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
588 if (ret < 0)
589 goto out;
590
591 if (NILFS_BMAP_USE_VBN(bmap)) {
592 dat = nilfs_bmap_get_dat(bmap);
593 ret = nilfs_dat_translate(dat, ptr, &blocknr);
594 if (ret < 0)
595 goto out;
596 ptr = blocknr;
597 }
598 cnt = 1;
599 if (cnt == maxblocks)
600 goto end;
601
602 maxlevel = nilfs_btree_height(btree) - 1;
603 node = nilfs_btree_get_node(btree, path, level);
604 index = path[level].bp_index + 1;
605 for (;;) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900606 while (index < nilfs_btree_node_get_nchildren(node)) {
607 if (nilfs_btree_node_get_key(node, index) !=
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900608 key + cnt)
609 goto end;
610 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
611 if (dat) {
612 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
613 if (ret < 0)
614 goto out;
615 ptr2 = blocknr;
616 }
617 if (ptr2 != ptr + cnt || ++cnt == maxblocks)
618 goto end;
619 index++;
620 continue;
621 }
622 if (level == maxlevel)
623 break;
624
625 /* look-up right sibling node */
626 node = nilfs_btree_get_node(btree, path, level + 1);
627 index = path[level + 1].bp_index + 1;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900628 if (index >= nilfs_btree_node_get_nchildren(node) ||
629 nilfs_btree_node_get_key(node, index) != key + cnt)
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900630 break;
631 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
632 path[level + 1].bp_index = index;
633
634 brelse(path[level].bp_bh);
635 path[level].bp_bh = NULL;
636 ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh);
637 if (ret < 0)
638 goto out;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900639 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900640 index = 0;
641 path[level].bp_index = index;
642 }
643 end:
644 *ptrp = ptr;
645 ret = cnt;
646 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +0900647 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900648 nilfs_btree_free_path(path);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900649 return ret;
650}
651
Koji Sato17c76b02009-04-06 19:01:24 -0700652static void nilfs_btree_promote_key(struct nilfs_btree *btree,
653 struct nilfs_btree_path *path,
654 int level, __u64 key)
655{
656 if (level < nilfs_btree_height(btree) - 1) {
657 do {
Koji Sato17c76b02009-04-06 19:01:24 -0700658 nilfs_btree_node_set_key(
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900659 nilfs_btree_get_nonroot_node(path, level),
Koji Sato17c76b02009-04-06 19:01:24 -0700660 path[level].bp_index, key);
661 if (!buffer_dirty(path[level].bp_bh))
662 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700663 } while ((path[level].bp_index == 0) &&
664 (++level < nilfs_btree_height(btree) - 1));
665 }
666
667 /* root */
668 if (level == nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900669 nilfs_btree_node_set_key(nilfs_btree_get_root(btree),
Koji Sato17c76b02009-04-06 19:01:24 -0700670 path[level].bp_index, key);
671 }
672}
673
674static void nilfs_btree_do_insert(struct nilfs_btree *btree,
675 struct nilfs_btree_path *path,
676 int level, __u64 *keyp, __u64 *ptrp)
677{
678 struct nilfs_btree_node *node;
679
680 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900681 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700682 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
683 path[level].bp_index);
684 if (!buffer_dirty(path[level].bp_bh))
685 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700686
687 if (path[level].bp_index == 0)
688 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900689 nilfs_btree_node_get_key(node,
690 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700691 } else {
692 node = nilfs_btree_get_root(btree);
693 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
694 path[level].bp_index);
695 }
696}
697
698static void nilfs_btree_carry_left(struct nilfs_btree *btree,
699 struct nilfs_btree_path *path,
700 int level, __u64 *keyp, __u64 *ptrp)
701{
702 struct nilfs_btree_node *node, *left;
703 int nchildren, lnchildren, n, move;
704
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900705 node = nilfs_btree_get_nonroot_node(path, level);
706 left = nilfs_btree_get_sib_node(path, level);
707 nchildren = nilfs_btree_node_get_nchildren(node);
708 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700709 move = 0;
710
711 n = (nchildren + lnchildren + 1) / 2 - lnchildren;
712 if (n > path[level].bp_index) {
713 /* move insert point */
714 n--;
715 move = 1;
716 }
717
718 nilfs_btree_node_move_left(btree, left, node, n);
719
720 if (!buffer_dirty(path[level].bp_bh))
721 nilfs_btnode_mark_dirty(path[level].bp_bh);
722 if (!buffer_dirty(path[level].bp_sib_bh))
723 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
724
Koji Sato17c76b02009-04-06 19:01:24 -0700725 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900726 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700727
728 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900729 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700730 path[level].bp_bh = path[level].bp_sib_bh;
731 path[level].bp_sib_bh = NULL;
732 path[level].bp_index += lnchildren;
733 path[level + 1].bp_index--;
734 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900735 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700736 path[level].bp_sib_bh = NULL;
737 path[level].bp_index -= n;
738 }
739
740 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
741}
742
743static void nilfs_btree_carry_right(struct nilfs_btree *btree,
744 struct nilfs_btree_path *path,
745 int level, __u64 *keyp, __u64 *ptrp)
746{
747 struct nilfs_btree_node *node, *right;
748 int nchildren, rnchildren, n, move;
749
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900750 node = nilfs_btree_get_nonroot_node(path, level);
751 right = nilfs_btree_get_sib_node(path, level);
752 nchildren = nilfs_btree_node_get_nchildren(node);
753 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700754 move = 0;
755
756 n = (nchildren + rnchildren + 1) / 2 - rnchildren;
757 if (n > nchildren - path[level].bp_index) {
758 /* move insert point */
759 n--;
760 move = 1;
761 }
762
763 nilfs_btree_node_move_right(btree, node, right, n);
764
765 if (!buffer_dirty(path[level].bp_bh))
766 nilfs_btnode_mark_dirty(path[level].bp_bh);
767 if (!buffer_dirty(path[level].bp_sib_bh))
768 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
769
Koji Sato17c76b02009-04-06 19:01:24 -0700770 path[level + 1].bp_index++;
771 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900772 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700773 path[level + 1].bp_index--;
774
775 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900776 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700777 path[level].bp_bh = path[level].bp_sib_bh;
778 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900779 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700780 path[level + 1].bp_index++;
781 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900782 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700783 path[level].bp_sib_bh = NULL;
784 }
785
786 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
787}
788
789static void nilfs_btree_split(struct nilfs_btree *btree,
790 struct nilfs_btree_path *path,
791 int level, __u64 *keyp, __u64 *ptrp)
792{
793 struct nilfs_btree_node *node, *right;
794 __u64 newkey;
795 __u64 newptr;
796 int nchildren, n, move;
797
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900798 node = nilfs_btree_get_nonroot_node(path, level);
799 right = nilfs_btree_get_sib_node(path, level);
800 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700801 move = 0;
802
803 n = (nchildren + 1) / 2;
804 if (n > nchildren - path[level].bp_index) {
805 n--;
806 move = 1;
807 }
808
809 nilfs_btree_node_move_right(btree, node, right, n);
810
811 if (!buffer_dirty(path[level].bp_bh))
812 nilfs_btnode_mark_dirty(path[level].bp_bh);
813 if (!buffer_dirty(path[level].bp_sib_bh))
814 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
815
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900816 newkey = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700817 newptr = path[level].bp_newreq.bpr_ptr;
818
819 if (move) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900820 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700821 nilfs_btree_node_insert(btree, right, *keyp, *ptrp,
822 path[level].bp_index);
823
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900824 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700825 *ptrp = path[level].bp_newreq.bpr_ptr;
826
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900827 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700828 path[level].bp_bh = path[level].bp_sib_bh;
829 path[level].bp_sib_bh = NULL;
830 } else {
831 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
832
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900833 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700834 *ptrp = path[level].bp_newreq.bpr_ptr;
835
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900836 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700837 path[level].bp_sib_bh = NULL;
838 }
839
840 path[level + 1].bp_index++;
841}
842
843static void nilfs_btree_grow(struct nilfs_btree *btree,
844 struct nilfs_btree_path *path,
845 int level, __u64 *keyp, __u64 *ptrp)
846{
847 struct nilfs_btree_node *root, *child;
848 int n;
849
Koji Sato17c76b02009-04-06 19:01:24 -0700850 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900851 child = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700852
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900853 n = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -0700854
855 nilfs_btree_node_move_right(btree, root, child, n);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900856 nilfs_btree_node_set_level(root, level + 1);
Koji Sato17c76b02009-04-06 19:01:24 -0700857
858 if (!buffer_dirty(path[level].bp_sib_bh))
859 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
860
Koji Sato17c76b02009-04-06 19:01:24 -0700861 path[level].bp_bh = path[level].bp_sib_bh;
862 path[level].bp_sib_bh = NULL;
863
864 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
865
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900866 *keyp = nilfs_btree_node_get_key(child, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700867 *ptrp = path[level].bp_newreq.bpr_ptr;
868}
869
870static __u64 nilfs_btree_find_near(const struct nilfs_btree *btree,
871 const struct nilfs_btree_path *path)
872{
873 struct nilfs_btree_node *node;
874 int level;
875
876 if (path == NULL)
877 return NILFS_BMAP_INVALID_PTR;
878
879 /* left sibling */
880 level = NILFS_BTREE_LEVEL_NODE_MIN;
881 if (path[level].bp_index > 0) {
882 node = nilfs_btree_get_node(btree, path, level);
883 return nilfs_btree_node_get_ptr(btree, node,
884 path[level].bp_index - 1);
885 }
886
887 /* parent */
888 level = NILFS_BTREE_LEVEL_NODE_MIN + 1;
889 if (level <= nilfs_btree_height(btree) - 1) {
890 node = nilfs_btree_get_node(btree, path, level);
891 return nilfs_btree_node_get_ptr(btree, node,
892 path[level].bp_index);
893 }
894
895 return NILFS_BMAP_INVALID_PTR;
896}
897
898static __u64 nilfs_btree_find_target_v(const struct nilfs_btree *btree,
899 const struct nilfs_btree_path *path,
900 __u64 key)
901{
902 __u64 ptr;
903
904 ptr = nilfs_bmap_find_target_seq(&btree->bt_bmap, key);
905 if (ptr != NILFS_BMAP_INVALID_PTR)
906 /* sequential access */
907 return ptr;
908 else {
909 ptr = nilfs_btree_find_near(btree, path);
910 if (ptr != NILFS_BMAP_INVALID_PTR)
911 /* near */
912 return ptr;
913 }
914 /* block group */
915 return nilfs_bmap_find_target_in_group(&btree->bt_bmap);
916}
917
918static void nilfs_btree_set_target_v(struct nilfs_btree *btree, __u64 key,
919 __u64 ptr)
920{
921 btree->bt_bmap.b_last_allocated_key = key;
922 btree->bt_bmap.b_last_allocated_ptr = ptr;
923}
924
925static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
926 struct nilfs_btree_path *path,
927 int *levelp, __u64 key, __u64 ptr,
928 struct nilfs_bmap_stats *stats)
929{
930 struct buffer_head *bh;
931 struct nilfs_btree_node *node, *parent, *sib;
932 __u64 sibptr;
933 int pindex, level, ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900934 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -0700935
936 stats->bs_nblocks = 0;
937 level = NILFS_BTREE_LEVEL_DATA;
938
939 /* allocate a new ptr for data block */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900940 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700941 path[level].bp_newreq.bpr_ptr =
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +0900942 nilfs_btree_find_target_v(btree, path, key);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900943 dat = nilfs_bmap_get_dat(&btree->bt_bmap);
944 }
Koji Sato17c76b02009-04-06 19:01:24 -0700945
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900946 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900947 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -0700948 if (ret < 0)
949 goto err_out_data;
950
951 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
952 level < nilfs_btree_height(btree) - 1;
953 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900954 node = nilfs_btree_get_nonroot_node(path, level);
955 if (nilfs_btree_node_get_nchildren(node) <
956 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700957 path[level].bp_op = nilfs_btree_do_insert;
958 stats->bs_nblocks++;
959 goto out;
960 }
961
962 parent = nilfs_btree_get_node(btree, path, level + 1);
963 pindex = path[level + 1].bp_index;
964
965 /* left sibling */
966 if (pindex > 0) {
967 sibptr = nilfs_btree_node_get_ptr(btree, parent,
968 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900969 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700970 if (ret < 0)
971 goto err_out_child_node;
972 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900973 if (nilfs_btree_node_get_nchildren(sib) <
974 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700975 path[level].bp_sib_bh = bh;
976 path[level].bp_op = nilfs_btree_carry_left;
977 stats->bs_nblocks++;
978 goto out;
979 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900980 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700981 }
982
983 /* right sibling */
984 if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900985 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -0700986 sibptr = nilfs_btree_node_get_ptr(btree, parent,
987 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900988 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700989 if (ret < 0)
990 goto err_out_child_node;
991 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900992 if (nilfs_btree_node_get_nchildren(sib) <
993 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700994 path[level].bp_sib_bh = bh;
995 path[level].bp_op = nilfs_btree_carry_right;
996 stats->bs_nblocks++;
997 goto out;
998 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900999 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001000 }
1001
1002 /* split */
1003 path[level].bp_newreq.bpr_ptr =
1004 path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001005 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001006 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001007 if (ret < 0)
1008 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001009 ret = nilfs_btree_get_new_block(btree,
1010 path[level].bp_newreq.bpr_ptr,
1011 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001012 if (ret < 0)
1013 goto err_out_curr_node;
1014
1015 stats->bs_nblocks++;
1016
Koji Sato17c76b02009-04-06 19:01:24 -07001017 nilfs_btree_node_init(btree,
1018 (struct nilfs_btree_node *)bh->b_data,
1019 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001020 path[level].bp_sib_bh = bh;
1021 path[level].bp_op = nilfs_btree_split;
1022 }
1023
1024 /* root */
1025 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001026 if (nilfs_btree_node_get_nchildren(node) <
1027 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001028 path[level].bp_op = nilfs_btree_do_insert;
1029 stats->bs_nblocks++;
1030 goto out;
1031 }
1032
1033 /* grow */
1034 path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001035 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001036 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001037 if (ret < 0)
1038 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001039 ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
1040 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001041 if (ret < 0)
1042 goto err_out_curr_node;
1043
Koji Sato17c76b02009-04-06 19:01:24 -07001044 nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data,
1045 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001046 path[level].bp_sib_bh = bh;
1047 path[level].bp_op = nilfs_btree_grow;
1048
1049 level++;
1050 path[level].bp_op = nilfs_btree_do_insert;
1051
1052 /* a newly-created node block and a data block are added */
1053 stats->bs_nblocks += 2;
1054
1055 /* success */
1056 out:
1057 *levelp = level;
1058 return ret;
1059
1060 /* error */
1061 err_out_curr_node:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001062 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
1063 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001064 err_out_child_node:
1065 for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001066 nilfs_btnode_delete(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001067 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001068 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001069
1070 }
1071
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001072 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
1073 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001074 err_out_data:
1075 *levelp = level;
1076 stats->bs_nblocks = 0;
1077 return ret;
1078}
1079
1080static void nilfs_btree_commit_insert(struct nilfs_btree *btree,
1081 struct nilfs_btree_path *path,
1082 int maxlevel, __u64 key, __u64 ptr)
1083{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001084 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001085 int level;
1086
1087 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1088 ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001089 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001090 nilfs_btree_set_target_v(btree, key, ptr);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001091 dat = nilfs_bmap_get_dat(&btree->bt_bmap);
1092 }
Koji Sato17c76b02009-04-06 19:01:24 -07001093
1094 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001095 nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001096 &path[level - 1].bp_newreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001097 path[level].bp_op(btree, path, level, &key, &ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001098 }
1099
1100 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1101 nilfs_bmap_set_dirty(&btree->bt_bmap);
1102}
1103
1104static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
1105{
1106 struct nilfs_btree *btree;
1107 struct nilfs_btree_path *path;
1108 struct nilfs_bmap_stats stats;
1109 int level, ret;
1110
1111 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001112 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001113 if (path == NULL)
1114 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001115 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001116
1117 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1118 NILFS_BTREE_LEVEL_NODE_MIN);
1119 if (ret != -ENOENT) {
1120 if (ret == 0)
1121 ret = -EEXIST;
1122 goto out;
1123 }
1124
1125 ret = nilfs_btree_prepare_insert(btree, path, &level, key, ptr, &stats);
1126 if (ret < 0)
1127 goto out;
1128 nilfs_btree_commit_insert(btree, path, level, key, ptr);
1129 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1130
1131 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09001132 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001133 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001134 return ret;
1135}
1136
1137static void nilfs_btree_do_delete(struct nilfs_btree *btree,
1138 struct nilfs_btree_path *path,
1139 int level, __u64 *keyp, __u64 *ptrp)
1140{
1141 struct nilfs_btree_node *node;
1142
1143 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001144 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001145 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1146 path[level].bp_index);
1147 if (!buffer_dirty(path[level].bp_bh))
1148 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001149 if (path[level].bp_index == 0)
1150 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001151 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001152 } else {
1153 node = nilfs_btree_get_root(btree);
1154 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1155 path[level].bp_index);
1156 }
1157}
1158
1159static void nilfs_btree_borrow_left(struct nilfs_btree *btree,
1160 struct nilfs_btree_path *path,
1161 int level, __u64 *keyp, __u64 *ptrp)
1162{
1163 struct nilfs_btree_node *node, *left;
1164 int nchildren, lnchildren, n;
1165
1166 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1167
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001168 node = nilfs_btree_get_nonroot_node(path, level);
1169 left = nilfs_btree_get_sib_node(path, level);
1170 nchildren = nilfs_btree_node_get_nchildren(node);
1171 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001172
1173 n = (nchildren + lnchildren) / 2 - nchildren;
1174
1175 nilfs_btree_node_move_right(btree, left, node, n);
1176
1177 if (!buffer_dirty(path[level].bp_bh))
1178 nilfs_btnode_mark_dirty(path[level].bp_bh);
1179 if (!buffer_dirty(path[level].bp_sib_bh))
1180 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1181
Koji Sato17c76b02009-04-06 19:01:24 -07001182 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001183 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001184
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001185 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001186 path[level].bp_sib_bh = NULL;
1187 path[level].bp_index += n;
1188}
1189
1190static void nilfs_btree_borrow_right(struct nilfs_btree *btree,
1191 struct nilfs_btree_path *path,
1192 int level, __u64 *keyp, __u64 *ptrp)
1193{
1194 struct nilfs_btree_node *node, *right;
1195 int nchildren, rnchildren, n;
1196
1197 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1198
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001199 node = nilfs_btree_get_nonroot_node(path, level);
1200 right = nilfs_btree_get_sib_node(path, level);
1201 nchildren = nilfs_btree_node_get_nchildren(node);
1202 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001203
1204 n = (nchildren + rnchildren) / 2 - nchildren;
1205
1206 nilfs_btree_node_move_left(btree, node, right, n);
1207
1208 if (!buffer_dirty(path[level].bp_bh))
1209 nilfs_btnode_mark_dirty(path[level].bp_bh);
1210 if (!buffer_dirty(path[level].bp_sib_bh))
1211 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1212
Koji Sato17c76b02009-04-06 19:01:24 -07001213 path[level + 1].bp_index++;
1214 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001215 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001216 path[level + 1].bp_index--;
1217
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001218 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001219 path[level].bp_sib_bh = NULL;
1220}
1221
1222static void nilfs_btree_concat_left(struct nilfs_btree *btree,
1223 struct nilfs_btree_path *path,
1224 int level, __u64 *keyp, __u64 *ptrp)
1225{
1226 struct nilfs_btree_node *node, *left;
1227 int n;
1228
1229 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1230
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001231 node = nilfs_btree_get_nonroot_node(path, level);
1232 left = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001233
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001234 n = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001235
1236 nilfs_btree_node_move_left(btree, left, node, n);
1237
1238 if (!buffer_dirty(path[level].bp_sib_bh))
1239 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1240
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001241 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001242 path[level].bp_bh = path[level].bp_sib_bh;
1243 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001244 path[level].bp_index += nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001245}
1246
1247static void nilfs_btree_concat_right(struct nilfs_btree *btree,
1248 struct nilfs_btree_path *path,
1249 int level, __u64 *keyp, __u64 *ptrp)
1250{
1251 struct nilfs_btree_node *node, *right;
1252 int n;
1253
1254 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1255
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001256 node = nilfs_btree_get_nonroot_node(path, level);
1257 right = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001258
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001259 n = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001260
1261 nilfs_btree_node_move_left(btree, node, right, n);
1262
1263 if (!buffer_dirty(path[level].bp_bh))
1264 nilfs_btnode_mark_dirty(path[level].bp_bh);
1265
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001266 nilfs_btnode_delete(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001267 path[level].bp_sib_bh = NULL;
1268 path[level + 1].bp_index++;
1269}
1270
1271static void nilfs_btree_shrink(struct nilfs_btree *btree,
1272 struct nilfs_btree_path *path,
1273 int level, __u64 *keyp, __u64 *ptrp)
1274{
1275 struct nilfs_btree_node *root, *child;
1276 int n;
1277
1278 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1279
Koji Sato17c76b02009-04-06 19:01:24 -07001280 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001281 child = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001282
1283 nilfs_btree_node_delete(btree, root, NULL, NULL, 0);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001284 nilfs_btree_node_set_level(root, level);
1285 n = nilfs_btree_node_get_nchildren(child);
Koji Sato17c76b02009-04-06 19:01:24 -07001286 nilfs_btree_node_move_left(btree, root, child, n);
Koji Sato17c76b02009-04-06 19:01:24 -07001287
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001288 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001289 path[level].bp_bh = NULL;
1290}
1291
1292
1293static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
1294 struct nilfs_btree_path *path,
1295 int *levelp,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001296 struct nilfs_bmap_stats *stats,
1297 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001298{
1299 struct buffer_head *bh;
1300 struct nilfs_btree_node *node, *parent, *sib;
1301 __u64 sibptr;
1302 int pindex, level, ret;
1303
1304 ret = 0;
1305 stats->bs_nblocks = 0;
1306 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1307 level < nilfs_btree_height(btree) - 1;
1308 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001309 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001310 path[level].bp_oldreq.bpr_ptr =
1311 nilfs_btree_node_get_ptr(btree, node,
1312 path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001313 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001314 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001315 if (ret < 0)
1316 goto err_out_child_node;
Koji Sato17c76b02009-04-06 19:01:24 -07001317
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001318 if (nilfs_btree_node_get_nchildren(node) >
1319 nilfs_btree_node_nchildren_min(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001320 path[level].bp_op = nilfs_btree_do_delete;
1321 stats->bs_nblocks++;
1322 goto out;
1323 }
1324
1325 parent = nilfs_btree_get_node(btree, path, level + 1);
1326 pindex = path[level + 1].bp_index;
1327
1328 if (pindex > 0) {
1329 /* left sibling */
1330 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1331 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001332 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001333 if (ret < 0)
1334 goto err_out_curr_node;
1335 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001336 if (nilfs_btree_node_get_nchildren(sib) >
1337 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001338 path[level].bp_sib_bh = bh;
1339 path[level].bp_op = nilfs_btree_borrow_left;
1340 stats->bs_nblocks++;
1341 goto out;
1342 } else {
1343 path[level].bp_sib_bh = bh;
1344 path[level].bp_op = nilfs_btree_concat_left;
1345 stats->bs_nblocks++;
1346 /* continue; */
1347 }
1348 } else if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001349 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -07001350 /* right sibling */
1351 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1352 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001353 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001354 if (ret < 0)
1355 goto err_out_curr_node;
1356 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001357 if (nilfs_btree_node_get_nchildren(sib) >
1358 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001359 path[level].bp_sib_bh = bh;
1360 path[level].bp_op = nilfs_btree_borrow_right;
1361 stats->bs_nblocks++;
1362 goto out;
1363 } else {
1364 path[level].bp_sib_bh = bh;
1365 path[level].bp_op = nilfs_btree_concat_right;
1366 stats->bs_nblocks++;
1367 /* continue; */
1368 }
1369 } else {
1370 /* no siblings */
1371 /* the only child of the root node */
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001372 WARN_ON(level != nilfs_btree_height(btree) - 2);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001373 if (nilfs_btree_node_get_nchildren(node) - 1 <=
Koji Sato17c76b02009-04-06 19:01:24 -07001374 NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1375 path[level].bp_op = nilfs_btree_shrink;
1376 stats->bs_nblocks += 2;
1377 } else {
1378 path[level].bp_op = nilfs_btree_do_delete;
1379 stats->bs_nblocks++;
1380 }
1381
1382 goto out;
1383
1384 }
1385 }
1386
1387 node = nilfs_btree_get_root(btree);
1388 path[level].bp_oldreq.bpr_ptr =
1389 nilfs_btree_node_get_ptr(btree, node, path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001390
1391 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001392 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001393 if (ret < 0)
1394 goto err_out_child_node;
1395
Koji Sato17c76b02009-04-06 19:01:24 -07001396 /* child of the root node is deleted */
1397 path[level].bp_op = nilfs_btree_do_delete;
1398 stats->bs_nblocks++;
1399
1400 /* success */
1401 out:
1402 *levelp = level;
1403 return ret;
1404
1405 /* error */
1406 err_out_curr_node:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001407 nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001408 err_out_child_node:
1409 for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001410 brelse(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001411 nilfs_bmap_abort_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001412 &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001413 }
1414 *levelp = level;
1415 stats->bs_nblocks = 0;
1416 return ret;
1417}
1418
1419static void nilfs_btree_commit_delete(struct nilfs_btree *btree,
1420 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001421 int maxlevel, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001422{
1423 int level;
1424
1425 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001426 nilfs_bmap_commit_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001427 &path[level].bp_oldreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001428 path[level].bp_op(btree, path, level, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001429 }
1430
1431 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1432 nilfs_bmap_set_dirty(&btree->bt_bmap);
1433}
1434
1435static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key)
1436
1437{
1438 struct nilfs_btree *btree;
1439 struct nilfs_btree_path *path;
1440 struct nilfs_bmap_stats stats;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001441 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001442 int level, ret;
1443
1444 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001445 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001446 if (path == NULL)
1447 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001448 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001449 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1450 NILFS_BTREE_LEVEL_NODE_MIN);
1451 if (ret < 0)
1452 goto out;
1453
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001454
1455 dat = NILFS_BMAP_USE_VBN(&btree->bt_bmap) ?
1456 nilfs_bmap_get_dat(&btree->bt_bmap) : NULL;
1457
1458 ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001459 if (ret < 0)
1460 goto out;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001461 nilfs_btree_commit_delete(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001462 nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks);
1463
1464out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09001465 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001466 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001467 return ret;
1468}
1469
1470static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp)
1471{
1472 struct nilfs_btree *btree;
1473 struct nilfs_btree_path *path;
1474 int ret;
1475
1476 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001477 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001478 if (path == NULL)
1479 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001480 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001481
1482 ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL);
1483
Ryusuke Konishi32189292009-08-15 01:54:59 +09001484 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001485 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001486
1487 return ret;
1488}
1489
1490static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key)
1491{
1492 struct buffer_head *bh;
1493 struct nilfs_btree *btree;
1494 struct nilfs_btree_node *root, *node;
1495 __u64 maxkey, nextmaxkey;
1496 __u64 ptr;
1497 int nchildren, ret;
1498
1499 btree = (struct nilfs_btree *)bmap;
1500 root = nilfs_btree_get_root(btree);
1501 switch (nilfs_btree_height(btree)) {
1502 case 2:
1503 bh = NULL;
1504 node = root;
1505 break;
1506 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001507 nchildren = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -07001508 if (nchildren > 1)
1509 return 0;
1510 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001511 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001512 if (ret < 0)
1513 return ret;
1514 node = (struct nilfs_btree_node *)bh->b_data;
1515 break;
1516 default:
1517 return 0;
1518 }
1519
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001520 nchildren = nilfs_btree_node_get_nchildren(node);
1521 maxkey = nilfs_btree_node_get_key(node, nchildren - 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001522 nextmaxkey = (nchildren > 1) ?
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001523 nilfs_btree_node_get_key(node, nchildren - 2) : 0;
Koji Sato17c76b02009-04-06 19:01:24 -07001524 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001525 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001526
Ryusuke Konishi30333422009-05-24 00:09:44 +09001527 return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
Koji Sato17c76b02009-04-06 19:01:24 -07001528}
1529
1530static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
1531 __u64 *keys, __u64 *ptrs, int nitems)
1532{
1533 struct buffer_head *bh;
1534 struct nilfs_btree *btree;
1535 struct nilfs_btree_node *node, *root;
1536 __le64 *dkeys;
1537 __le64 *dptrs;
1538 __u64 ptr;
1539 int nchildren, i, ret;
1540
1541 btree = (struct nilfs_btree *)bmap;
1542 root = nilfs_btree_get_root(btree);
1543 switch (nilfs_btree_height(btree)) {
1544 case 2:
1545 bh = NULL;
1546 node = root;
1547 break;
1548 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001549 nchildren = nilfs_btree_node_get_nchildren(root);
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001550 WARN_ON(nchildren > 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001551 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001552 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001553 if (ret < 0)
1554 return ret;
1555 node = (struct nilfs_btree_node *)bh->b_data;
1556 break;
1557 default:
1558 node = NULL;
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001559 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -07001560 }
1561
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001562 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001563 if (nchildren < nitems)
1564 nitems = nchildren;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001565 dkeys = nilfs_btree_node_dkeys(node);
1566 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001567 for (i = 0; i < nitems; i++) {
1568 keys[i] = nilfs_bmap_dkey_to_key(dkeys[i]);
1569 ptrs[i] = nilfs_bmap_dptr_to_ptr(dptrs[i]);
1570 }
1571
1572 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001573 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001574
1575 return nitems;
1576}
1577
1578static int
1579nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
1580 union nilfs_bmap_ptr_req *dreq,
1581 union nilfs_bmap_ptr_req *nreq,
1582 struct buffer_head **bhp,
1583 struct nilfs_bmap_stats *stats)
1584{
1585 struct buffer_head *bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001586 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
1587 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001588 int ret;
1589
Koji Sato17c76b02009-04-06 19:01:24 -07001590 stats->bs_nblocks = 0;
1591
1592 /* for data */
1593 /* cannot find near ptr */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001594 if (NILFS_BMAP_USE_VBN(bmap)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001595 dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001596 dat = nilfs_bmap_get_dat(bmap);
1597 }
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001598
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001599 ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001600 if (ret < 0)
1601 return ret;
1602
1603 *bhp = NULL;
1604 stats->bs_nblocks++;
1605 if (nreq != NULL) {
1606 nreq->bpr_ptr = dreq->bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001607 ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001608 if (ret < 0)
1609 goto err_out_dreq;
1610
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001611 ret = nilfs_btree_get_new_block(btree, nreq->bpr_ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001612 if (ret < 0)
1613 goto err_out_nreq;
1614
1615 *bhp = bh;
1616 stats->bs_nblocks++;
1617 }
1618
1619 /* success */
1620 return 0;
1621
1622 /* error */
1623 err_out_nreq:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001624 nilfs_bmap_abort_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001625 err_out_dreq:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001626 nilfs_bmap_abort_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001627 stats->bs_nblocks = 0;
1628 return ret;
1629
1630}
1631
1632static void
1633nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
1634 __u64 key, __u64 ptr,
1635 const __u64 *keys, const __u64 *ptrs,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001636 int n,
Koji Sato17c76b02009-04-06 19:01:24 -07001637 union nilfs_bmap_ptr_req *dreq,
1638 union nilfs_bmap_ptr_req *nreq,
1639 struct buffer_head *bh)
1640{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001641 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
Koji Sato17c76b02009-04-06 19:01:24 -07001642 struct nilfs_btree_node *node;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001643 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001644 __u64 tmpptr;
1645
1646 /* free resources */
1647 if (bmap->b_ops->bop_clear != NULL)
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001648 bmap->b_ops->bop_clear(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001649
1650 /* ptr must be a pointer to a buffer head. */
1651 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1652
1653 /* convert and insert */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001654 dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL;
Ryusuke Konishi30333422009-05-24 00:09:44 +09001655 nilfs_btree_init(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001656 if (nreq != NULL) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001657 nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
1658 nilfs_bmap_commit_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001659
1660 /* create child node at level 1 */
Koji Sato17c76b02009-04-06 19:01:24 -07001661 node = (struct nilfs_btree_node *)bh->b_data;
1662 nilfs_btree_node_init(btree, node, 0, 1, n, keys, ptrs);
1663 nilfs_btree_node_insert(btree, node,
1664 key, dreq->bpr_ptr, n);
1665 if (!buffer_dirty(bh))
1666 nilfs_btnode_mark_dirty(bh);
1667 if (!nilfs_bmap_dirty(bmap))
1668 nilfs_bmap_set_dirty(bmap);
1669
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001670 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001671
1672 /* create root node at level 2 */
1673 node = nilfs_btree_get_root(btree);
1674 tmpptr = nreq->bpr_ptr;
1675 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1676 2, 1, &keys[0], &tmpptr);
1677 } else {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001678 nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001679
1680 /* create root node at level 1 */
1681 node = nilfs_btree_get_root(btree);
1682 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1683 1, n, keys, ptrs);
1684 nilfs_btree_node_insert(btree, node,
1685 key, dreq->bpr_ptr, n);
1686 if (!nilfs_bmap_dirty(bmap))
1687 nilfs_bmap_set_dirty(bmap);
1688 }
1689
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001690 if (NILFS_BMAP_USE_VBN(bmap))
1691 nilfs_btree_set_target_v(btree, key, dreq->bpr_ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001692}
1693
1694/**
1695 * nilfs_btree_convert_and_insert -
1696 * @bmap:
1697 * @key:
1698 * @ptr:
1699 * @keys:
1700 * @ptrs:
1701 * @n:
Koji Sato17c76b02009-04-06 19:01:24 -07001702 */
1703int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap,
1704 __u64 key, __u64 ptr,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001705 const __u64 *keys, const __u64 *ptrs, int n)
Koji Sato17c76b02009-04-06 19:01:24 -07001706{
1707 struct buffer_head *bh;
1708 union nilfs_bmap_ptr_req dreq, nreq, *di, *ni;
1709 struct nilfs_bmap_stats stats;
1710 int ret;
1711
1712 if (n + 1 <= NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1713 di = &dreq;
1714 ni = NULL;
1715 } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX(
1716 1 << bmap->b_inode->i_blkbits)) {
1717 di = &dreq;
1718 ni = &nreq;
1719 } else {
1720 di = NULL;
1721 ni = NULL;
1722 BUG();
1723 }
1724
1725 ret = nilfs_btree_prepare_convert_and_insert(bmap, key, di, ni, &bh,
1726 &stats);
1727 if (ret < 0)
1728 return ret;
1729 nilfs_btree_commit_convert_and_insert(bmap, key, ptr, keys, ptrs, n,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001730 di, ni, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001731 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1732 return 0;
1733}
1734
1735static int nilfs_btree_propagate_p(struct nilfs_btree *btree,
1736 struct nilfs_btree_path *path,
1737 int level,
1738 struct buffer_head *bh)
1739{
1740 while ((++level < nilfs_btree_height(btree) - 1) &&
1741 !buffer_dirty(path[level].bp_bh))
1742 nilfs_btnode_mark_dirty(path[level].bp_bh);
1743
1744 return 0;
1745}
1746
1747static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
1748 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001749 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001750{
1751 struct nilfs_btree_node *parent;
1752 int ret;
1753
1754 parent = nilfs_btree_get_node(btree, path, level + 1);
1755 path[level].bp_oldreq.bpr_ptr =
1756 nilfs_btree_node_get_ptr(btree, parent,
1757 path[level + 1].bp_index);
1758 path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001759 ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req,
1760 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001761 if (ret < 0)
1762 return ret;
1763
1764 if (buffer_nilfs_node(path[level].bp_bh)) {
1765 path[level].bp_ctxt.oldkey = path[level].bp_oldreq.bpr_ptr;
1766 path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr;
1767 path[level].bp_ctxt.bh = path[level].bp_bh;
1768 ret = nilfs_btnode_prepare_change_key(
1769 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1770 &path[level].bp_ctxt);
1771 if (ret < 0) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001772 nilfs_dat_abort_update(dat,
1773 &path[level].bp_oldreq.bpr_req,
1774 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001775 return ret;
1776 }
1777 }
1778
1779 return 0;
1780}
1781
1782static void nilfs_btree_commit_update_v(struct nilfs_btree *btree,
1783 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001784 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001785{
1786 struct nilfs_btree_node *parent;
1787
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001788 nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req,
1789 &path[level].bp_newreq.bpr_req,
1790 btree->bt_bmap.b_ptr_type == NILFS_BMAP_PTR_VS);
Koji Sato17c76b02009-04-06 19:01:24 -07001791
1792 if (buffer_nilfs_node(path[level].bp_bh)) {
1793 nilfs_btnode_commit_change_key(
1794 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1795 &path[level].bp_ctxt);
1796 path[level].bp_bh = path[level].bp_ctxt.bh;
1797 }
1798 set_buffer_nilfs_volatile(path[level].bp_bh);
1799
1800 parent = nilfs_btree_get_node(btree, path, level + 1);
1801 nilfs_btree_node_set_ptr(btree, parent, path[level + 1].bp_index,
1802 path[level].bp_newreq.bpr_ptr);
1803}
1804
1805static void nilfs_btree_abort_update_v(struct nilfs_btree *btree,
1806 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001807 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001808{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001809 nilfs_dat_abort_update(dat, &path[level].bp_oldreq.bpr_req,
1810 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001811 if (buffer_nilfs_node(path[level].bp_bh))
1812 nilfs_btnode_abort_change_key(
1813 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1814 &path[level].bp_ctxt);
1815}
1816
1817static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree,
1818 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001819 int minlevel, int *maxlevelp,
1820 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001821{
1822 int level, ret;
1823
1824 level = minlevel;
1825 if (!buffer_nilfs_volatile(path[level].bp_bh)) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001826 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001827 if (ret < 0)
1828 return ret;
1829 }
1830 while ((++level < nilfs_btree_height(btree) - 1) &&
1831 !buffer_dirty(path[level].bp_bh)) {
1832
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001833 WARN_ON(buffer_nilfs_volatile(path[level].bp_bh));
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001834 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001835 if (ret < 0)
1836 goto out;
1837 }
1838
1839 /* success */
Koji Sato17c76b02009-04-06 19:01:24 -07001840 *maxlevelp = level - 1;
1841 return 0;
1842
1843 /* error */
1844 out:
1845 while (--level > minlevel)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001846 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001847 if (!buffer_nilfs_volatile(path[level].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001848 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001849 return ret;
1850}
1851
1852static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree,
1853 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001854 int minlevel, int maxlevel,
1855 struct buffer_head *bh,
1856 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001857{
1858 int level;
1859
1860 if (!buffer_nilfs_volatile(path[minlevel].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001861 nilfs_btree_commit_update_v(btree, path, minlevel, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001862
1863 for (level = minlevel + 1; level <= maxlevel; level++)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001864 nilfs_btree_commit_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001865}
1866
1867static int nilfs_btree_propagate_v(struct nilfs_btree *btree,
1868 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001869 int level, struct buffer_head *bh)
Koji Sato17c76b02009-04-06 19:01:24 -07001870{
1871 int maxlevel, ret;
1872 struct nilfs_btree_node *parent;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001873 struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001874 __u64 ptr;
1875
1876 get_bh(bh);
1877 path[level].bp_bh = bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001878 ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel,
1879 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001880 if (ret < 0)
1881 goto out;
1882
1883 if (buffer_nilfs_volatile(path[level].bp_bh)) {
1884 parent = nilfs_btree_get_node(btree, path, level + 1);
1885 ptr = nilfs_btree_node_get_ptr(btree, parent,
1886 path[level + 1].bp_index);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001887 ret = nilfs_dat_mark_dirty(dat, ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001888 if (ret < 0)
1889 goto out;
1890 }
1891
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001892 nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001893
1894 out:
1895 brelse(path[level].bp_bh);
1896 path[level].bp_bh = NULL;
1897 return ret;
1898}
1899
1900static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
1901 struct buffer_head *bh)
1902{
1903 struct nilfs_btree *btree;
1904 struct nilfs_btree_path *path;
1905 struct nilfs_btree_node *node;
1906 __u64 key;
1907 int level, ret;
1908
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001909 WARN_ON(!buffer_dirty(bh));
Koji Sato17c76b02009-04-06 19:01:24 -07001910
1911 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001912 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001913 if (path == NULL)
1914 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001915 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001916
1917 if (buffer_nilfs_node(bh)) {
1918 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001919 key = nilfs_btree_node_get_key(node, 0);
1920 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001921 } else {
1922 key = nilfs_bmap_data_get_key(bmap, bh);
1923 level = NILFS_BTREE_LEVEL_DATA;
1924 }
1925
1926 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
1927 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001928 if (unlikely(ret == -ENOENT))
Koji Sato17c76b02009-04-06 19:01:24 -07001929 printk(KERN_CRIT "%s: key = %llu, level == %d\n",
1930 __func__, (unsigned long long)key, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001931 goto out;
1932 }
1933
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001934 ret = NILFS_BMAP_USE_VBN(bmap) ?
1935 nilfs_btree_propagate_v(btree, path, level, bh) :
1936 nilfs_btree_propagate_p(btree, path, level, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001937
1938 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09001939 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001940 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001941
1942 return ret;
1943}
1944
1945static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap,
1946 struct buffer_head *bh)
1947{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001948 return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), bh->b_blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07001949}
1950
1951static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree,
1952 struct list_head *lists,
1953 struct buffer_head *bh)
1954{
1955 struct list_head *head;
1956 struct buffer_head *cbh;
1957 struct nilfs_btree_node *node, *cnode;
1958 __u64 key, ckey;
1959 int level;
1960
1961 get_bh(bh);
1962 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001963 key = nilfs_btree_node_get_key(node, 0);
1964 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001965 list_for_each(head, &lists[level]) {
1966 cbh = list_entry(head, struct buffer_head, b_assoc_buffers);
1967 cnode = (struct nilfs_btree_node *)cbh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001968 ckey = nilfs_btree_node_get_key(cnode, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07001969 if (key < ckey)
1970 break;
1971 }
1972 list_add_tail(&bh->b_assoc_buffers, head);
1973}
1974
1975static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *bmap,
1976 struct list_head *listp)
1977{
1978 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
1979 struct address_space *btcache = &NILFS_BMAP_I(bmap)->i_btnode_cache;
1980 struct list_head lists[NILFS_BTREE_LEVEL_MAX];
1981 struct pagevec pvec;
1982 struct buffer_head *bh, *head;
1983 pgoff_t index = 0;
1984 int level, i;
1985
1986 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1987 level < NILFS_BTREE_LEVEL_MAX;
1988 level++)
1989 INIT_LIST_HEAD(&lists[level]);
1990
1991 pagevec_init(&pvec, 0);
1992
1993 while (pagevec_lookup_tag(&pvec, btcache, &index, PAGECACHE_TAG_DIRTY,
1994 PAGEVEC_SIZE)) {
1995 for (i = 0; i < pagevec_count(&pvec); i++) {
1996 bh = head = page_buffers(pvec.pages[i]);
1997 do {
1998 if (buffer_dirty(bh))
1999 nilfs_btree_add_dirty_buffer(btree,
2000 lists, bh);
2001 } while ((bh = bh->b_this_page) != head);
2002 }
2003 pagevec_release(&pvec);
2004 cond_resched();
2005 }
2006
2007 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
2008 level < NILFS_BTREE_LEVEL_MAX;
2009 level++)
2010 list_splice(&lists[level], listp->prev);
2011}
2012
2013static int nilfs_btree_assign_p(struct nilfs_btree *btree,
2014 struct nilfs_btree_path *path,
2015 int level,
2016 struct buffer_head **bh,
2017 sector_t blocknr,
2018 union nilfs_binfo *binfo)
2019{
2020 struct nilfs_btree_node *parent;
2021 __u64 key;
2022 __u64 ptr;
2023 int ret;
2024
2025 parent = nilfs_btree_get_node(btree, path, level + 1);
2026 ptr = nilfs_btree_node_get_ptr(btree, parent,
2027 path[level + 1].bp_index);
2028 if (buffer_nilfs_node(*bh)) {
2029 path[level].bp_ctxt.oldkey = ptr;
2030 path[level].bp_ctxt.newkey = blocknr;
2031 path[level].bp_ctxt.bh = *bh;
2032 ret = nilfs_btnode_prepare_change_key(
2033 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2034 &path[level].bp_ctxt);
2035 if (ret < 0)
2036 return ret;
2037 nilfs_btnode_commit_change_key(
2038 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2039 &path[level].bp_ctxt);
2040 *bh = path[level].bp_ctxt.bh;
2041 }
2042
2043 nilfs_btree_node_set_ptr(btree, parent,
2044 path[level + 1].bp_index, blocknr);
2045
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002046 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002047 /* on-disk format */
2048 binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2049 binfo->bi_dat.bi_level = level;
2050
2051 return 0;
2052}
2053
2054static int nilfs_btree_assign_v(struct nilfs_btree *btree,
2055 struct nilfs_btree_path *path,
2056 int level,
2057 struct buffer_head **bh,
2058 sector_t blocknr,
2059 union nilfs_binfo *binfo)
2060{
2061 struct nilfs_btree_node *parent;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002062 struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07002063 __u64 key;
2064 __u64 ptr;
2065 union nilfs_bmap_ptr_req req;
2066 int ret;
2067
2068 parent = nilfs_btree_get_node(btree, path, level + 1);
2069 ptr = nilfs_btree_node_get_ptr(btree, parent,
2070 path[level + 1].bp_index);
2071 req.bpr_ptr = ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002072 ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
2073 if (ret < 0)
Koji Sato17c76b02009-04-06 19:01:24 -07002074 return ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002075 nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002076
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002077 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002078 /* on-disk format */
2079 binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr);
2080 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2081
2082 return 0;
2083}
2084
2085static int nilfs_btree_assign(struct nilfs_bmap *bmap,
2086 struct buffer_head **bh,
2087 sector_t blocknr,
2088 union nilfs_binfo *binfo)
2089{
2090 struct nilfs_btree *btree;
2091 struct nilfs_btree_path *path;
2092 struct nilfs_btree_node *node;
2093 __u64 key;
2094 int level, ret;
2095
2096 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002097 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002098 if (path == NULL)
2099 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002100 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002101
2102 if (buffer_nilfs_node(*bh)) {
2103 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002104 key = nilfs_btree_node_get_key(node, 0);
2105 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07002106 } else {
2107 key = nilfs_bmap_data_get_key(bmap, *bh);
2108 level = NILFS_BTREE_LEVEL_DATA;
2109 }
2110
2111 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
2112 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002113 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002114 goto out;
2115 }
2116
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09002117 ret = NILFS_BMAP_USE_VBN(bmap) ?
2118 nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) :
2119 nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
Koji Sato17c76b02009-04-06 19:01:24 -07002120
2121 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09002122 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002123 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002124
2125 return ret;
2126}
2127
2128static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap,
2129 struct buffer_head **bh,
2130 sector_t blocknr,
2131 union nilfs_binfo *binfo)
2132{
Koji Sato17c76b02009-04-06 19:01:24 -07002133 struct nilfs_btree_node *node;
2134 __u64 key;
2135 int ret;
2136
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002137 ret = nilfs_dat_move(nilfs_bmap_get_dat(bmap), (*bh)->b_blocknr,
2138 blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002139 if (ret < 0)
2140 return ret;
2141
2142 if (buffer_nilfs_node(*bh)) {
2143 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002144 key = nilfs_btree_node_get_key(node, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07002145 } else
2146 key = nilfs_bmap_data_get_key(bmap, *bh);
2147
2148 /* on-disk format */
2149 binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr);
2150 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2151
2152 return 0;
2153}
2154
2155static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
2156{
2157 struct buffer_head *bh;
2158 struct nilfs_btree *btree;
2159 struct nilfs_btree_path *path;
2160 __u64 ptr;
2161 int ret;
2162
2163 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002164 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002165 if (path == NULL)
2166 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002167 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002168
2169 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1);
2170 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002171 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002172 goto out;
2173 }
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09002174 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002175 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002176 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002177 goto out;
2178 }
2179
2180 if (!buffer_dirty(bh))
2181 nilfs_btnode_mark_dirty(bh);
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09002182 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002183 if (!nilfs_bmap_dirty(&btree->bt_bmap))
2184 nilfs_bmap_set_dirty(&btree->bt_bmap);
2185
2186 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09002187 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002188 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002189 return ret;
2190}
2191
2192static const struct nilfs_bmap_operations nilfs_btree_ops = {
2193 .bop_lookup = nilfs_btree_lookup,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002194 .bop_lookup_contig = nilfs_btree_lookup_contig,
Koji Sato17c76b02009-04-06 19:01:24 -07002195 .bop_insert = nilfs_btree_insert,
2196 .bop_delete = nilfs_btree_delete,
2197 .bop_clear = NULL,
2198
2199 .bop_propagate = nilfs_btree_propagate,
2200
2201 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2202
2203 .bop_assign = nilfs_btree_assign,
2204 .bop_mark = nilfs_btree_mark,
2205
2206 .bop_last_key = nilfs_btree_last_key,
2207 .bop_check_insert = NULL,
2208 .bop_check_delete = nilfs_btree_check_delete,
2209 .bop_gather_data = nilfs_btree_gather_data,
2210};
2211
2212static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
2213 .bop_lookup = NULL,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002214 .bop_lookup_contig = NULL,
Koji Sato17c76b02009-04-06 19:01:24 -07002215 .bop_insert = NULL,
2216 .bop_delete = NULL,
2217 .bop_clear = NULL,
2218
2219 .bop_propagate = nilfs_btree_propagate_gc,
2220
2221 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2222
2223 .bop_assign = nilfs_btree_assign_gc,
2224 .bop_mark = NULL,
2225
2226 .bop_last_key = NULL,
2227 .bop_check_insert = NULL,
2228 .bop_check_delete = NULL,
2229 .bop_gather_data = NULL,
2230};
2231
Ryusuke Konishi30333422009-05-24 00:09:44 +09002232int nilfs_btree_init(struct nilfs_bmap *bmap)
Koji Sato17c76b02009-04-06 19:01:24 -07002233{
Koji Sato17c76b02009-04-06 19:01:24 -07002234 bmap->b_ops = &nilfs_btree_ops;
Koji Sato17c76b02009-04-06 19:01:24 -07002235 return 0;
2236}
2237
2238void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
2239{
Koji Sato17c76b02009-04-06 19:01:24 -07002240 bmap->b_ops = &nilfs_btree_ops_gc;
2241}