blob: c9aab29ea1f64b14667724a168040c6d52b6c819 [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
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900447static inline int
448nilfs_btree_bad_node(struct nilfs_btree_node *node, int level)
449{
450 if (unlikely(nilfs_btree_node_get_level(node) != level)) {
451 dump_stack();
452 printk(KERN_CRIT "NILFS: btree level mismatch: %d != %d\n",
453 nilfs_btree_node_get_level(node), level);
454 return 1;
455 }
456 return 0;
457}
458
Koji Sato17c76b02009-04-06 19:01:24 -0700459static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
460 struct nilfs_btree_path *path,
461 __u64 key, __u64 *ptrp, int minlevel)
462{
463 struct nilfs_btree_node *node;
464 __u64 ptr;
465 int level, index, found, ret;
466
Koji Sato17c76b02009-04-06 19:01:24 -0700467 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900468 level = nilfs_btree_node_get_level(node);
469 if (level < minlevel || nilfs_btree_node_get_nchildren(node) <= 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700470 return -ENOENT;
471
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900472 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700473 ptr = nilfs_btree_node_get_ptr(btree, node, index);
474 path[level].bp_bh = NULL;
475 path[level].bp_index = index;
476
477 for (level--; level >= minlevel; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900478 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700479 if (ret < 0)
480 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900481 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900482 if (nilfs_btree_bad_node(node, level))
483 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -0700484 if (!found)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900485 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700486 else
487 index = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900488 if (index < nilfs_btree_node_nchildren_max(node, btree))
Koji Sato17c76b02009-04-06 19:01:24 -0700489 ptr = nilfs_btree_node_get_ptr(btree, node, index);
490 else {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700491 WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN);
Koji Sato17c76b02009-04-06 19:01:24 -0700492 /* insert */
493 ptr = NILFS_BMAP_INVALID_PTR;
494 }
495 path[level].bp_index = index;
496 }
497 if (!found)
498 return -ENOENT;
499
500 if (ptrp != NULL)
501 *ptrp = ptr;
502
503 return 0;
504}
505
506static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree,
507 struct nilfs_btree_path *path,
508 __u64 *keyp, __u64 *ptrp)
509{
510 struct nilfs_btree_node *node;
511 __u64 ptr;
512 int index, level, ret;
513
514 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900515 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700516 if (index < 0)
517 return -ENOENT;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900518 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700519 ptr = nilfs_btree_node_get_ptr(btree, node, index);
520 path[level].bp_bh = NULL;
521 path[level].bp_index = index;
522
523 for (level--; level > 0; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900524 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700525 if (ret < 0)
526 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900527 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900528 if (nilfs_btree_bad_node(node, level))
529 return -EINVAL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900530 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700531 ptr = nilfs_btree_node_get_ptr(btree, node, index);
532 path[level].bp_index = index;
533 }
534
535 if (keyp != NULL)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900536 *keyp = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700537 if (ptrp != NULL)
538 *ptrp = ptr;
539
540 return 0;
541}
542
543static int nilfs_btree_lookup(const struct nilfs_bmap *bmap,
544 __u64 key, int level, __u64 *ptrp)
545{
546 struct nilfs_btree *btree;
547 struct nilfs_btree_path *path;
548 __u64 ptr;
549 int ret;
550
551 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900552 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -0700553 if (path == NULL)
554 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900555 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -0700556
557 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
558
559 if (ptrp != NULL)
560 *ptrp = ptr;
561
Ryusuke Konishi32189292009-08-15 01:54:59 +0900562 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900563 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -0700564
565 return ret;
566}
567
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900568static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
569 __u64 key, __u64 *ptrp, unsigned maxblocks)
570{
571 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
572 struct nilfs_btree_path *path;
573 struct nilfs_btree_node *node;
574 struct inode *dat = NULL;
575 __u64 ptr, ptr2;
576 sector_t blocknr;
577 int level = NILFS_BTREE_LEVEL_NODE_MIN;
578 int ret, cnt, index, maxlevel;
579
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900580 path = nilfs_btree_alloc_path();
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900581 if (path == NULL)
582 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900583 nilfs_btree_init_path(path);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900584 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
585 if (ret < 0)
586 goto out;
587
588 if (NILFS_BMAP_USE_VBN(bmap)) {
589 dat = nilfs_bmap_get_dat(bmap);
590 ret = nilfs_dat_translate(dat, ptr, &blocknr);
591 if (ret < 0)
592 goto out;
593 ptr = blocknr;
594 }
595 cnt = 1;
596 if (cnt == maxblocks)
597 goto end;
598
599 maxlevel = nilfs_btree_height(btree) - 1;
600 node = nilfs_btree_get_node(btree, path, level);
601 index = path[level].bp_index + 1;
602 for (;;) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900603 while (index < nilfs_btree_node_get_nchildren(node)) {
604 if (nilfs_btree_node_get_key(node, index) !=
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900605 key + cnt)
606 goto end;
607 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
608 if (dat) {
609 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
610 if (ret < 0)
611 goto out;
612 ptr2 = blocknr;
613 }
614 if (ptr2 != ptr + cnt || ++cnt == maxblocks)
615 goto end;
616 index++;
617 continue;
618 }
619 if (level == maxlevel)
620 break;
621
622 /* look-up right sibling node */
623 node = nilfs_btree_get_node(btree, path, level + 1);
624 index = path[level + 1].bp_index + 1;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900625 if (index >= nilfs_btree_node_get_nchildren(node) ||
626 nilfs_btree_node_get_key(node, index) != key + cnt)
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900627 break;
628 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
629 path[level + 1].bp_index = index;
630
631 brelse(path[level].bp_bh);
632 path[level].bp_bh = NULL;
633 ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh);
634 if (ret < 0)
635 goto out;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900636 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900637 index = 0;
638 path[level].bp_index = index;
639 }
640 end:
641 *ptrp = ptr;
642 ret = cnt;
643 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +0900644 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900645 nilfs_btree_free_path(path);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900646 return ret;
647}
648
Koji Sato17c76b02009-04-06 19:01:24 -0700649static void nilfs_btree_promote_key(struct nilfs_btree *btree,
650 struct nilfs_btree_path *path,
651 int level, __u64 key)
652{
653 if (level < nilfs_btree_height(btree) - 1) {
654 do {
Koji Sato17c76b02009-04-06 19:01:24 -0700655 nilfs_btree_node_set_key(
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900656 nilfs_btree_get_nonroot_node(path, level),
Koji Sato17c76b02009-04-06 19:01:24 -0700657 path[level].bp_index, key);
658 if (!buffer_dirty(path[level].bp_bh))
659 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700660 } while ((path[level].bp_index == 0) &&
661 (++level < nilfs_btree_height(btree) - 1));
662 }
663
664 /* root */
665 if (level == nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900666 nilfs_btree_node_set_key(nilfs_btree_get_root(btree),
Koji Sato17c76b02009-04-06 19:01:24 -0700667 path[level].bp_index, key);
668 }
669}
670
671static void nilfs_btree_do_insert(struct nilfs_btree *btree,
672 struct nilfs_btree_path *path,
673 int level, __u64 *keyp, __u64 *ptrp)
674{
675 struct nilfs_btree_node *node;
676
677 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900678 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700679 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
680 path[level].bp_index);
681 if (!buffer_dirty(path[level].bp_bh))
682 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700683
684 if (path[level].bp_index == 0)
685 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900686 nilfs_btree_node_get_key(node,
687 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700688 } else {
689 node = nilfs_btree_get_root(btree);
690 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
691 path[level].bp_index);
692 }
693}
694
695static void nilfs_btree_carry_left(struct nilfs_btree *btree,
696 struct nilfs_btree_path *path,
697 int level, __u64 *keyp, __u64 *ptrp)
698{
699 struct nilfs_btree_node *node, *left;
700 int nchildren, lnchildren, n, move;
701
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900702 node = nilfs_btree_get_nonroot_node(path, level);
703 left = nilfs_btree_get_sib_node(path, level);
704 nchildren = nilfs_btree_node_get_nchildren(node);
705 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700706 move = 0;
707
708 n = (nchildren + lnchildren + 1) / 2 - lnchildren;
709 if (n > path[level].bp_index) {
710 /* move insert point */
711 n--;
712 move = 1;
713 }
714
715 nilfs_btree_node_move_left(btree, left, node, n);
716
717 if (!buffer_dirty(path[level].bp_bh))
718 nilfs_btnode_mark_dirty(path[level].bp_bh);
719 if (!buffer_dirty(path[level].bp_sib_bh))
720 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
721
Koji Sato17c76b02009-04-06 19:01:24 -0700722 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900723 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700724
725 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900726 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700727 path[level].bp_bh = path[level].bp_sib_bh;
728 path[level].bp_sib_bh = NULL;
729 path[level].bp_index += lnchildren;
730 path[level + 1].bp_index--;
731 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900732 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700733 path[level].bp_sib_bh = NULL;
734 path[level].bp_index -= n;
735 }
736
737 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
738}
739
740static void nilfs_btree_carry_right(struct nilfs_btree *btree,
741 struct nilfs_btree_path *path,
742 int level, __u64 *keyp, __u64 *ptrp)
743{
744 struct nilfs_btree_node *node, *right;
745 int nchildren, rnchildren, n, move;
746
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900747 node = nilfs_btree_get_nonroot_node(path, level);
748 right = nilfs_btree_get_sib_node(path, level);
749 nchildren = nilfs_btree_node_get_nchildren(node);
750 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700751 move = 0;
752
753 n = (nchildren + rnchildren + 1) / 2 - rnchildren;
754 if (n > nchildren - path[level].bp_index) {
755 /* move insert point */
756 n--;
757 move = 1;
758 }
759
760 nilfs_btree_node_move_right(btree, node, right, n);
761
762 if (!buffer_dirty(path[level].bp_bh))
763 nilfs_btnode_mark_dirty(path[level].bp_bh);
764 if (!buffer_dirty(path[level].bp_sib_bh))
765 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
766
Koji Sato17c76b02009-04-06 19:01:24 -0700767 path[level + 1].bp_index++;
768 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900769 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700770 path[level + 1].bp_index--;
771
772 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900773 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700774 path[level].bp_bh = path[level].bp_sib_bh;
775 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900776 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700777 path[level + 1].bp_index++;
778 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900779 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700780 path[level].bp_sib_bh = NULL;
781 }
782
783 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
784}
785
786static void nilfs_btree_split(struct nilfs_btree *btree,
787 struct nilfs_btree_path *path,
788 int level, __u64 *keyp, __u64 *ptrp)
789{
790 struct nilfs_btree_node *node, *right;
791 __u64 newkey;
792 __u64 newptr;
793 int nchildren, n, move;
794
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900795 node = nilfs_btree_get_nonroot_node(path, level);
796 right = nilfs_btree_get_sib_node(path, level);
797 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700798 move = 0;
799
800 n = (nchildren + 1) / 2;
801 if (n > nchildren - path[level].bp_index) {
802 n--;
803 move = 1;
804 }
805
806 nilfs_btree_node_move_right(btree, node, right, n);
807
808 if (!buffer_dirty(path[level].bp_bh))
809 nilfs_btnode_mark_dirty(path[level].bp_bh);
810 if (!buffer_dirty(path[level].bp_sib_bh))
811 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
812
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900813 newkey = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700814 newptr = path[level].bp_newreq.bpr_ptr;
815
816 if (move) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900817 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700818 nilfs_btree_node_insert(btree, right, *keyp, *ptrp,
819 path[level].bp_index);
820
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900821 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700822 *ptrp = path[level].bp_newreq.bpr_ptr;
823
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900824 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700825 path[level].bp_bh = path[level].bp_sib_bh;
826 path[level].bp_sib_bh = NULL;
827 } else {
828 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
829
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900830 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700831 *ptrp = path[level].bp_newreq.bpr_ptr;
832
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900833 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700834 path[level].bp_sib_bh = NULL;
835 }
836
837 path[level + 1].bp_index++;
838}
839
840static void nilfs_btree_grow(struct nilfs_btree *btree,
841 struct nilfs_btree_path *path,
842 int level, __u64 *keyp, __u64 *ptrp)
843{
844 struct nilfs_btree_node *root, *child;
845 int n;
846
Koji Sato17c76b02009-04-06 19:01:24 -0700847 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900848 child = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700849
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900850 n = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -0700851
852 nilfs_btree_node_move_right(btree, root, child, n);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900853 nilfs_btree_node_set_level(root, level + 1);
Koji Sato17c76b02009-04-06 19:01:24 -0700854
855 if (!buffer_dirty(path[level].bp_sib_bh))
856 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
857
Koji Sato17c76b02009-04-06 19:01:24 -0700858 path[level].bp_bh = path[level].bp_sib_bh;
859 path[level].bp_sib_bh = NULL;
860
861 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
862
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900863 *keyp = nilfs_btree_node_get_key(child, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700864 *ptrp = path[level].bp_newreq.bpr_ptr;
865}
866
867static __u64 nilfs_btree_find_near(const struct nilfs_btree *btree,
868 const struct nilfs_btree_path *path)
869{
870 struct nilfs_btree_node *node;
871 int level;
872
873 if (path == NULL)
874 return NILFS_BMAP_INVALID_PTR;
875
876 /* left sibling */
877 level = NILFS_BTREE_LEVEL_NODE_MIN;
878 if (path[level].bp_index > 0) {
879 node = nilfs_btree_get_node(btree, path, level);
880 return nilfs_btree_node_get_ptr(btree, node,
881 path[level].bp_index - 1);
882 }
883
884 /* parent */
885 level = NILFS_BTREE_LEVEL_NODE_MIN + 1;
886 if (level <= nilfs_btree_height(btree) - 1) {
887 node = nilfs_btree_get_node(btree, path, level);
888 return nilfs_btree_node_get_ptr(btree, node,
889 path[level].bp_index);
890 }
891
892 return NILFS_BMAP_INVALID_PTR;
893}
894
895static __u64 nilfs_btree_find_target_v(const struct nilfs_btree *btree,
896 const struct nilfs_btree_path *path,
897 __u64 key)
898{
899 __u64 ptr;
900
901 ptr = nilfs_bmap_find_target_seq(&btree->bt_bmap, key);
902 if (ptr != NILFS_BMAP_INVALID_PTR)
903 /* sequential access */
904 return ptr;
905 else {
906 ptr = nilfs_btree_find_near(btree, path);
907 if (ptr != NILFS_BMAP_INVALID_PTR)
908 /* near */
909 return ptr;
910 }
911 /* block group */
912 return nilfs_bmap_find_target_in_group(&btree->bt_bmap);
913}
914
915static void nilfs_btree_set_target_v(struct nilfs_btree *btree, __u64 key,
916 __u64 ptr)
917{
918 btree->bt_bmap.b_last_allocated_key = key;
919 btree->bt_bmap.b_last_allocated_ptr = ptr;
920}
921
922static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
923 struct nilfs_btree_path *path,
924 int *levelp, __u64 key, __u64 ptr,
925 struct nilfs_bmap_stats *stats)
926{
927 struct buffer_head *bh;
928 struct nilfs_btree_node *node, *parent, *sib;
929 __u64 sibptr;
930 int pindex, level, ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900931 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -0700932
933 stats->bs_nblocks = 0;
934 level = NILFS_BTREE_LEVEL_DATA;
935
936 /* allocate a new ptr for data block */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900937 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700938 path[level].bp_newreq.bpr_ptr =
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +0900939 nilfs_btree_find_target_v(btree, path, key);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900940 dat = nilfs_bmap_get_dat(&btree->bt_bmap);
941 }
Koji Sato17c76b02009-04-06 19:01:24 -0700942
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900943 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900944 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -0700945 if (ret < 0)
946 goto err_out_data;
947
948 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
949 level < nilfs_btree_height(btree) - 1;
950 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900951 node = nilfs_btree_get_nonroot_node(path, level);
952 if (nilfs_btree_node_get_nchildren(node) <
953 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700954 path[level].bp_op = nilfs_btree_do_insert;
955 stats->bs_nblocks++;
956 goto out;
957 }
958
959 parent = nilfs_btree_get_node(btree, path, level + 1);
960 pindex = path[level + 1].bp_index;
961
962 /* left sibling */
963 if (pindex > 0) {
964 sibptr = nilfs_btree_node_get_ptr(btree, parent,
965 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900966 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700967 if (ret < 0)
968 goto err_out_child_node;
969 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900970 if (nilfs_btree_node_get_nchildren(sib) <
971 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700972 path[level].bp_sib_bh = bh;
973 path[level].bp_op = nilfs_btree_carry_left;
974 stats->bs_nblocks++;
975 goto out;
976 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900977 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700978 }
979
980 /* right sibling */
981 if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900982 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -0700983 sibptr = nilfs_btree_node_get_ptr(btree, parent,
984 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900985 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700986 if (ret < 0)
987 goto err_out_child_node;
988 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900989 if (nilfs_btree_node_get_nchildren(sib) <
990 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700991 path[level].bp_sib_bh = bh;
992 path[level].bp_op = nilfs_btree_carry_right;
993 stats->bs_nblocks++;
994 goto out;
995 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900996 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700997 }
998
999 /* split */
1000 path[level].bp_newreq.bpr_ptr =
1001 path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001002 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001003 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001004 if (ret < 0)
1005 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001006 ret = nilfs_btree_get_new_block(btree,
1007 path[level].bp_newreq.bpr_ptr,
1008 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001009 if (ret < 0)
1010 goto err_out_curr_node;
1011
1012 stats->bs_nblocks++;
1013
Koji Sato17c76b02009-04-06 19:01:24 -07001014 nilfs_btree_node_init(btree,
1015 (struct nilfs_btree_node *)bh->b_data,
1016 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001017 path[level].bp_sib_bh = bh;
1018 path[level].bp_op = nilfs_btree_split;
1019 }
1020
1021 /* root */
1022 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001023 if (nilfs_btree_node_get_nchildren(node) <
1024 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001025 path[level].bp_op = nilfs_btree_do_insert;
1026 stats->bs_nblocks++;
1027 goto out;
1028 }
1029
1030 /* grow */
1031 path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001032 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001033 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001034 if (ret < 0)
1035 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001036 ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
1037 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001038 if (ret < 0)
1039 goto err_out_curr_node;
1040
Koji Sato17c76b02009-04-06 19:01:24 -07001041 nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data,
1042 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001043 path[level].bp_sib_bh = bh;
1044 path[level].bp_op = nilfs_btree_grow;
1045
1046 level++;
1047 path[level].bp_op = nilfs_btree_do_insert;
1048
1049 /* a newly-created node block and a data block are added */
1050 stats->bs_nblocks += 2;
1051
1052 /* success */
1053 out:
1054 *levelp = level;
1055 return ret;
1056
1057 /* error */
1058 err_out_curr_node:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001059 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
1060 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001061 err_out_child_node:
1062 for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001063 nilfs_btnode_delete(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001064 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001065 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001066
1067 }
1068
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001069 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
1070 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001071 err_out_data:
1072 *levelp = level;
1073 stats->bs_nblocks = 0;
1074 return ret;
1075}
1076
1077static void nilfs_btree_commit_insert(struct nilfs_btree *btree,
1078 struct nilfs_btree_path *path,
1079 int maxlevel, __u64 key, __u64 ptr)
1080{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001081 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001082 int level;
1083
1084 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1085 ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001086 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001087 nilfs_btree_set_target_v(btree, key, ptr);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001088 dat = nilfs_bmap_get_dat(&btree->bt_bmap);
1089 }
Koji Sato17c76b02009-04-06 19:01:24 -07001090
1091 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001092 nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001093 &path[level - 1].bp_newreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001094 path[level].bp_op(btree, path, level, &key, &ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001095 }
1096
1097 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1098 nilfs_bmap_set_dirty(&btree->bt_bmap);
1099}
1100
1101static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
1102{
1103 struct nilfs_btree *btree;
1104 struct nilfs_btree_path *path;
1105 struct nilfs_bmap_stats stats;
1106 int level, ret;
1107
1108 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001109 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001110 if (path == NULL)
1111 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001112 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001113
1114 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1115 NILFS_BTREE_LEVEL_NODE_MIN);
1116 if (ret != -ENOENT) {
1117 if (ret == 0)
1118 ret = -EEXIST;
1119 goto out;
1120 }
1121
1122 ret = nilfs_btree_prepare_insert(btree, path, &level, key, ptr, &stats);
1123 if (ret < 0)
1124 goto out;
1125 nilfs_btree_commit_insert(btree, path, level, key, ptr);
1126 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1127
1128 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09001129 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001130 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001131 return ret;
1132}
1133
1134static void nilfs_btree_do_delete(struct nilfs_btree *btree,
1135 struct nilfs_btree_path *path,
1136 int level, __u64 *keyp, __u64 *ptrp)
1137{
1138 struct nilfs_btree_node *node;
1139
1140 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001141 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001142 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1143 path[level].bp_index);
1144 if (!buffer_dirty(path[level].bp_bh))
1145 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001146 if (path[level].bp_index == 0)
1147 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001148 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001149 } else {
1150 node = nilfs_btree_get_root(btree);
1151 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1152 path[level].bp_index);
1153 }
1154}
1155
1156static void nilfs_btree_borrow_left(struct nilfs_btree *btree,
1157 struct nilfs_btree_path *path,
1158 int level, __u64 *keyp, __u64 *ptrp)
1159{
1160 struct nilfs_btree_node *node, *left;
1161 int nchildren, lnchildren, n;
1162
1163 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1164
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001165 node = nilfs_btree_get_nonroot_node(path, level);
1166 left = nilfs_btree_get_sib_node(path, level);
1167 nchildren = nilfs_btree_node_get_nchildren(node);
1168 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001169
1170 n = (nchildren + lnchildren) / 2 - nchildren;
1171
1172 nilfs_btree_node_move_right(btree, left, node, n);
1173
1174 if (!buffer_dirty(path[level].bp_bh))
1175 nilfs_btnode_mark_dirty(path[level].bp_bh);
1176 if (!buffer_dirty(path[level].bp_sib_bh))
1177 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1178
Koji Sato17c76b02009-04-06 19:01:24 -07001179 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001180 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001181
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001182 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001183 path[level].bp_sib_bh = NULL;
1184 path[level].bp_index += n;
1185}
1186
1187static void nilfs_btree_borrow_right(struct nilfs_btree *btree,
1188 struct nilfs_btree_path *path,
1189 int level, __u64 *keyp, __u64 *ptrp)
1190{
1191 struct nilfs_btree_node *node, *right;
1192 int nchildren, rnchildren, n;
1193
1194 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1195
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001196 node = nilfs_btree_get_nonroot_node(path, level);
1197 right = nilfs_btree_get_sib_node(path, level);
1198 nchildren = nilfs_btree_node_get_nchildren(node);
1199 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001200
1201 n = (nchildren + rnchildren) / 2 - nchildren;
1202
1203 nilfs_btree_node_move_left(btree, node, right, n);
1204
1205 if (!buffer_dirty(path[level].bp_bh))
1206 nilfs_btnode_mark_dirty(path[level].bp_bh);
1207 if (!buffer_dirty(path[level].bp_sib_bh))
1208 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1209
Koji Sato17c76b02009-04-06 19:01:24 -07001210 path[level + 1].bp_index++;
1211 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001212 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001213 path[level + 1].bp_index--;
1214
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001215 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001216 path[level].bp_sib_bh = NULL;
1217}
1218
1219static void nilfs_btree_concat_left(struct nilfs_btree *btree,
1220 struct nilfs_btree_path *path,
1221 int level, __u64 *keyp, __u64 *ptrp)
1222{
1223 struct nilfs_btree_node *node, *left;
1224 int n;
1225
1226 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1227
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001228 node = nilfs_btree_get_nonroot_node(path, level);
1229 left = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001230
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001231 n = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001232
1233 nilfs_btree_node_move_left(btree, left, node, n);
1234
1235 if (!buffer_dirty(path[level].bp_sib_bh))
1236 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1237
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001238 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001239 path[level].bp_bh = path[level].bp_sib_bh;
1240 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001241 path[level].bp_index += nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001242}
1243
1244static void nilfs_btree_concat_right(struct nilfs_btree *btree,
1245 struct nilfs_btree_path *path,
1246 int level, __u64 *keyp, __u64 *ptrp)
1247{
1248 struct nilfs_btree_node *node, *right;
1249 int n;
1250
1251 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1252
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001253 node = nilfs_btree_get_nonroot_node(path, level);
1254 right = 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(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001257
1258 nilfs_btree_node_move_left(btree, node, right, n);
1259
1260 if (!buffer_dirty(path[level].bp_bh))
1261 nilfs_btnode_mark_dirty(path[level].bp_bh);
1262
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001263 nilfs_btnode_delete(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001264 path[level].bp_sib_bh = NULL;
1265 path[level + 1].bp_index++;
1266}
1267
1268static void nilfs_btree_shrink(struct nilfs_btree *btree,
1269 struct nilfs_btree_path *path,
1270 int level, __u64 *keyp, __u64 *ptrp)
1271{
1272 struct nilfs_btree_node *root, *child;
1273 int n;
1274
1275 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1276
Koji Sato17c76b02009-04-06 19:01:24 -07001277 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001278 child = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001279
1280 nilfs_btree_node_delete(btree, root, NULL, NULL, 0);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001281 nilfs_btree_node_set_level(root, level);
1282 n = nilfs_btree_node_get_nchildren(child);
Koji Sato17c76b02009-04-06 19:01:24 -07001283 nilfs_btree_node_move_left(btree, root, child, n);
Koji Sato17c76b02009-04-06 19:01:24 -07001284
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001285 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001286 path[level].bp_bh = NULL;
1287}
1288
1289
1290static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
1291 struct nilfs_btree_path *path,
1292 int *levelp,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001293 struct nilfs_bmap_stats *stats,
1294 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001295{
1296 struct buffer_head *bh;
1297 struct nilfs_btree_node *node, *parent, *sib;
1298 __u64 sibptr;
1299 int pindex, level, ret;
1300
1301 ret = 0;
1302 stats->bs_nblocks = 0;
1303 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1304 level < nilfs_btree_height(btree) - 1;
1305 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001306 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001307 path[level].bp_oldreq.bpr_ptr =
1308 nilfs_btree_node_get_ptr(btree, node,
1309 path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001310 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001311 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001312 if (ret < 0)
1313 goto err_out_child_node;
Koji Sato17c76b02009-04-06 19:01:24 -07001314
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001315 if (nilfs_btree_node_get_nchildren(node) >
1316 nilfs_btree_node_nchildren_min(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001317 path[level].bp_op = nilfs_btree_do_delete;
1318 stats->bs_nblocks++;
1319 goto out;
1320 }
1321
1322 parent = nilfs_btree_get_node(btree, path, level + 1);
1323 pindex = path[level + 1].bp_index;
1324
1325 if (pindex > 0) {
1326 /* left sibling */
1327 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1328 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001329 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001330 if (ret < 0)
1331 goto err_out_curr_node;
1332 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001333 if (nilfs_btree_node_get_nchildren(sib) >
1334 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001335 path[level].bp_sib_bh = bh;
1336 path[level].bp_op = nilfs_btree_borrow_left;
1337 stats->bs_nblocks++;
1338 goto out;
1339 } else {
1340 path[level].bp_sib_bh = bh;
1341 path[level].bp_op = nilfs_btree_concat_left;
1342 stats->bs_nblocks++;
1343 /* continue; */
1344 }
1345 } else if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001346 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -07001347 /* right sibling */
1348 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1349 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001350 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001351 if (ret < 0)
1352 goto err_out_curr_node;
1353 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001354 if (nilfs_btree_node_get_nchildren(sib) >
1355 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001356 path[level].bp_sib_bh = bh;
1357 path[level].bp_op = nilfs_btree_borrow_right;
1358 stats->bs_nblocks++;
1359 goto out;
1360 } else {
1361 path[level].bp_sib_bh = bh;
1362 path[level].bp_op = nilfs_btree_concat_right;
1363 stats->bs_nblocks++;
1364 /* continue; */
1365 }
1366 } else {
1367 /* no siblings */
1368 /* the only child of the root node */
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001369 WARN_ON(level != nilfs_btree_height(btree) - 2);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001370 if (nilfs_btree_node_get_nchildren(node) - 1 <=
Koji Sato17c76b02009-04-06 19:01:24 -07001371 NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1372 path[level].bp_op = nilfs_btree_shrink;
1373 stats->bs_nblocks += 2;
1374 } else {
1375 path[level].bp_op = nilfs_btree_do_delete;
1376 stats->bs_nblocks++;
1377 }
1378
1379 goto out;
1380
1381 }
1382 }
1383
1384 node = nilfs_btree_get_root(btree);
1385 path[level].bp_oldreq.bpr_ptr =
1386 nilfs_btree_node_get_ptr(btree, node, path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001387
1388 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001389 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001390 if (ret < 0)
1391 goto err_out_child_node;
1392
Koji Sato17c76b02009-04-06 19:01:24 -07001393 /* child of the root node is deleted */
1394 path[level].bp_op = nilfs_btree_do_delete;
1395 stats->bs_nblocks++;
1396
1397 /* success */
1398 out:
1399 *levelp = level;
1400 return ret;
1401
1402 /* error */
1403 err_out_curr_node:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001404 nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001405 err_out_child_node:
1406 for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001407 brelse(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001408 nilfs_bmap_abort_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001409 &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001410 }
1411 *levelp = level;
1412 stats->bs_nblocks = 0;
1413 return ret;
1414}
1415
1416static void nilfs_btree_commit_delete(struct nilfs_btree *btree,
1417 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001418 int maxlevel, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001419{
1420 int level;
1421
1422 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001423 nilfs_bmap_commit_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001424 &path[level].bp_oldreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001425 path[level].bp_op(btree, path, level, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001426 }
1427
1428 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1429 nilfs_bmap_set_dirty(&btree->bt_bmap);
1430}
1431
1432static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key)
1433
1434{
1435 struct nilfs_btree *btree;
1436 struct nilfs_btree_path *path;
1437 struct nilfs_bmap_stats stats;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001438 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001439 int level, ret;
1440
1441 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001442 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001443 if (path == NULL)
1444 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001445 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001446 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1447 NILFS_BTREE_LEVEL_NODE_MIN);
1448 if (ret < 0)
1449 goto out;
1450
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001451
1452 dat = NILFS_BMAP_USE_VBN(&btree->bt_bmap) ?
1453 nilfs_bmap_get_dat(&btree->bt_bmap) : NULL;
1454
1455 ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001456 if (ret < 0)
1457 goto out;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001458 nilfs_btree_commit_delete(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001459 nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks);
1460
1461out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09001462 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001463 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001464 return ret;
1465}
1466
1467static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp)
1468{
1469 struct nilfs_btree *btree;
1470 struct nilfs_btree_path *path;
1471 int ret;
1472
1473 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001474 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001475 if (path == NULL)
1476 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001477 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001478
1479 ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL);
1480
Ryusuke Konishi32189292009-08-15 01:54:59 +09001481 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001482 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001483
1484 return ret;
1485}
1486
1487static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key)
1488{
1489 struct buffer_head *bh;
1490 struct nilfs_btree *btree;
1491 struct nilfs_btree_node *root, *node;
1492 __u64 maxkey, nextmaxkey;
1493 __u64 ptr;
1494 int nchildren, ret;
1495
1496 btree = (struct nilfs_btree *)bmap;
1497 root = nilfs_btree_get_root(btree);
1498 switch (nilfs_btree_height(btree)) {
1499 case 2:
1500 bh = NULL;
1501 node = root;
1502 break;
1503 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001504 nchildren = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -07001505 if (nchildren > 1)
1506 return 0;
1507 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001508 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001509 if (ret < 0)
1510 return ret;
1511 node = (struct nilfs_btree_node *)bh->b_data;
1512 break;
1513 default:
1514 return 0;
1515 }
1516
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001517 nchildren = nilfs_btree_node_get_nchildren(node);
1518 maxkey = nilfs_btree_node_get_key(node, nchildren - 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001519 nextmaxkey = (nchildren > 1) ?
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001520 nilfs_btree_node_get_key(node, nchildren - 2) : 0;
Koji Sato17c76b02009-04-06 19:01:24 -07001521 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001522 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001523
Ryusuke Konishi30333422009-05-24 00:09:44 +09001524 return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
Koji Sato17c76b02009-04-06 19:01:24 -07001525}
1526
1527static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
1528 __u64 *keys, __u64 *ptrs, int nitems)
1529{
1530 struct buffer_head *bh;
1531 struct nilfs_btree *btree;
1532 struct nilfs_btree_node *node, *root;
1533 __le64 *dkeys;
1534 __le64 *dptrs;
1535 __u64 ptr;
1536 int nchildren, i, ret;
1537
1538 btree = (struct nilfs_btree *)bmap;
1539 root = nilfs_btree_get_root(btree);
1540 switch (nilfs_btree_height(btree)) {
1541 case 2:
1542 bh = NULL;
1543 node = root;
1544 break;
1545 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001546 nchildren = nilfs_btree_node_get_nchildren(root);
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001547 WARN_ON(nchildren > 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001548 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001549 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001550 if (ret < 0)
1551 return ret;
1552 node = (struct nilfs_btree_node *)bh->b_data;
1553 break;
1554 default:
1555 node = NULL;
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001556 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -07001557 }
1558
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001559 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001560 if (nchildren < nitems)
1561 nitems = nchildren;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001562 dkeys = nilfs_btree_node_dkeys(node);
1563 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001564 for (i = 0; i < nitems; i++) {
1565 keys[i] = nilfs_bmap_dkey_to_key(dkeys[i]);
1566 ptrs[i] = nilfs_bmap_dptr_to_ptr(dptrs[i]);
1567 }
1568
1569 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001570 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001571
1572 return nitems;
1573}
1574
1575static int
1576nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
1577 union nilfs_bmap_ptr_req *dreq,
1578 union nilfs_bmap_ptr_req *nreq,
1579 struct buffer_head **bhp,
1580 struct nilfs_bmap_stats *stats)
1581{
1582 struct buffer_head *bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001583 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
1584 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001585 int ret;
1586
Koji Sato17c76b02009-04-06 19:01:24 -07001587 stats->bs_nblocks = 0;
1588
1589 /* for data */
1590 /* cannot find near ptr */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001591 if (NILFS_BMAP_USE_VBN(bmap)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001592 dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001593 dat = nilfs_bmap_get_dat(bmap);
1594 }
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001595
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001596 ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001597 if (ret < 0)
1598 return ret;
1599
1600 *bhp = NULL;
1601 stats->bs_nblocks++;
1602 if (nreq != NULL) {
1603 nreq->bpr_ptr = dreq->bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001604 ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001605 if (ret < 0)
1606 goto err_out_dreq;
1607
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001608 ret = nilfs_btree_get_new_block(btree, nreq->bpr_ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001609 if (ret < 0)
1610 goto err_out_nreq;
1611
1612 *bhp = bh;
1613 stats->bs_nblocks++;
1614 }
1615
1616 /* success */
1617 return 0;
1618
1619 /* error */
1620 err_out_nreq:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001621 nilfs_bmap_abort_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001622 err_out_dreq:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001623 nilfs_bmap_abort_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001624 stats->bs_nblocks = 0;
1625 return ret;
1626
1627}
1628
1629static void
1630nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
1631 __u64 key, __u64 ptr,
1632 const __u64 *keys, const __u64 *ptrs,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001633 int n,
Koji Sato17c76b02009-04-06 19:01:24 -07001634 union nilfs_bmap_ptr_req *dreq,
1635 union nilfs_bmap_ptr_req *nreq,
1636 struct buffer_head *bh)
1637{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001638 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
Koji Sato17c76b02009-04-06 19:01:24 -07001639 struct nilfs_btree_node *node;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001640 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001641 __u64 tmpptr;
1642
1643 /* free resources */
1644 if (bmap->b_ops->bop_clear != NULL)
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001645 bmap->b_ops->bop_clear(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001646
1647 /* ptr must be a pointer to a buffer head. */
1648 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1649
1650 /* convert and insert */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001651 dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL;
Ryusuke Konishi30333422009-05-24 00:09:44 +09001652 nilfs_btree_init(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001653 if (nreq != NULL) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001654 nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
1655 nilfs_bmap_commit_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001656
1657 /* create child node at level 1 */
Koji Sato17c76b02009-04-06 19:01:24 -07001658 node = (struct nilfs_btree_node *)bh->b_data;
1659 nilfs_btree_node_init(btree, node, 0, 1, n, keys, ptrs);
1660 nilfs_btree_node_insert(btree, node,
1661 key, dreq->bpr_ptr, n);
1662 if (!buffer_dirty(bh))
1663 nilfs_btnode_mark_dirty(bh);
1664 if (!nilfs_bmap_dirty(bmap))
1665 nilfs_bmap_set_dirty(bmap);
1666
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001667 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001668
1669 /* create root node at level 2 */
1670 node = nilfs_btree_get_root(btree);
1671 tmpptr = nreq->bpr_ptr;
1672 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1673 2, 1, &keys[0], &tmpptr);
1674 } else {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001675 nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001676
1677 /* create root node at level 1 */
1678 node = nilfs_btree_get_root(btree);
1679 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1680 1, n, keys, ptrs);
1681 nilfs_btree_node_insert(btree, node,
1682 key, dreq->bpr_ptr, n);
1683 if (!nilfs_bmap_dirty(bmap))
1684 nilfs_bmap_set_dirty(bmap);
1685 }
1686
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001687 if (NILFS_BMAP_USE_VBN(bmap))
1688 nilfs_btree_set_target_v(btree, key, dreq->bpr_ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001689}
1690
1691/**
1692 * nilfs_btree_convert_and_insert -
1693 * @bmap:
1694 * @key:
1695 * @ptr:
1696 * @keys:
1697 * @ptrs:
1698 * @n:
Koji Sato17c76b02009-04-06 19:01:24 -07001699 */
1700int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap,
1701 __u64 key, __u64 ptr,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001702 const __u64 *keys, const __u64 *ptrs, int n)
Koji Sato17c76b02009-04-06 19:01:24 -07001703{
1704 struct buffer_head *bh;
1705 union nilfs_bmap_ptr_req dreq, nreq, *di, *ni;
1706 struct nilfs_bmap_stats stats;
1707 int ret;
1708
1709 if (n + 1 <= NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1710 di = &dreq;
1711 ni = NULL;
1712 } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX(
1713 1 << bmap->b_inode->i_blkbits)) {
1714 di = &dreq;
1715 ni = &nreq;
1716 } else {
1717 di = NULL;
1718 ni = NULL;
1719 BUG();
1720 }
1721
1722 ret = nilfs_btree_prepare_convert_and_insert(bmap, key, di, ni, &bh,
1723 &stats);
1724 if (ret < 0)
1725 return ret;
1726 nilfs_btree_commit_convert_and_insert(bmap, key, ptr, keys, ptrs, n,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001727 di, ni, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001728 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1729 return 0;
1730}
1731
1732static int nilfs_btree_propagate_p(struct nilfs_btree *btree,
1733 struct nilfs_btree_path *path,
1734 int level,
1735 struct buffer_head *bh)
1736{
1737 while ((++level < nilfs_btree_height(btree) - 1) &&
1738 !buffer_dirty(path[level].bp_bh))
1739 nilfs_btnode_mark_dirty(path[level].bp_bh);
1740
1741 return 0;
1742}
1743
1744static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
1745 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001746 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001747{
1748 struct nilfs_btree_node *parent;
1749 int ret;
1750
1751 parent = nilfs_btree_get_node(btree, path, level + 1);
1752 path[level].bp_oldreq.bpr_ptr =
1753 nilfs_btree_node_get_ptr(btree, parent,
1754 path[level + 1].bp_index);
1755 path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001756 ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req,
1757 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001758 if (ret < 0)
1759 return ret;
1760
1761 if (buffer_nilfs_node(path[level].bp_bh)) {
1762 path[level].bp_ctxt.oldkey = path[level].bp_oldreq.bpr_ptr;
1763 path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr;
1764 path[level].bp_ctxt.bh = path[level].bp_bh;
1765 ret = nilfs_btnode_prepare_change_key(
1766 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1767 &path[level].bp_ctxt);
1768 if (ret < 0) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001769 nilfs_dat_abort_update(dat,
1770 &path[level].bp_oldreq.bpr_req,
1771 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001772 return ret;
1773 }
1774 }
1775
1776 return 0;
1777}
1778
1779static void nilfs_btree_commit_update_v(struct nilfs_btree *btree,
1780 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001781 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001782{
1783 struct nilfs_btree_node *parent;
1784
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001785 nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req,
1786 &path[level].bp_newreq.bpr_req,
1787 btree->bt_bmap.b_ptr_type == NILFS_BMAP_PTR_VS);
Koji Sato17c76b02009-04-06 19:01:24 -07001788
1789 if (buffer_nilfs_node(path[level].bp_bh)) {
1790 nilfs_btnode_commit_change_key(
1791 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1792 &path[level].bp_ctxt);
1793 path[level].bp_bh = path[level].bp_ctxt.bh;
1794 }
1795 set_buffer_nilfs_volatile(path[level].bp_bh);
1796
1797 parent = nilfs_btree_get_node(btree, path, level + 1);
1798 nilfs_btree_node_set_ptr(btree, parent, path[level + 1].bp_index,
1799 path[level].bp_newreq.bpr_ptr);
1800}
1801
1802static void nilfs_btree_abort_update_v(struct nilfs_btree *btree,
1803 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001804 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001805{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001806 nilfs_dat_abort_update(dat, &path[level].bp_oldreq.bpr_req,
1807 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001808 if (buffer_nilfs_node(path[level].bp_bh))
1809 nilfs_btnode_abort_change_key(
1810 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1811 &path[level].bp_ctxt);
1812}
1813
1814static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree,
1815 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001816 int minlevel, int *maxlevelp,
1817 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001818{
1819 int level, ret;
1820
1821 level = minlevel;
1822 if (!buffer_nilfs_volatile(path[level].bp_bh)) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001823 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001824 if (ret < 0)
1825 return ret;
1826 }
1827 while ((++level < nilfs_btree_height(btree) - 1) &&
1828 !buffer_dirty(path[level].bp_bh)) {
1829
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001830 WARN_ON(buffer_nilfs_volatile(path[level].bp_bh));
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001831 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001832 if (ret < 0)
1833 goto out;
1834 }
1835
1836 /* success */
Koji Sato17c76b02009-04-06 19:01:24 -07001837 *maxlevelp = level - 1;
1838 return 0;
1839
1840 /* error */
1841 out:
1842 while (--level > minlevel)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001843 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001844 if (!buffer_nilfs_volatile(path[level].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001845 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001846 return ret;
1847}
1848
1849static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree,
1850 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001851 int minlevel, int maxlevel,
1852 struct buffer_head *bh,
1853 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001854{
1855 int level;
1856
1857 if (!buffer_nilfs_volatile(path[minlevel].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001858 nilfs_btree_commit_update_v(btree, path, minlevel, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001859
1860 for (level = minlevel + 1; level <= maxlevel; level++)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001861 nilfs_btree_commit_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001862}
1863
1864static int nilfs_btree_propagate_v(struct nilfs_btree *btree,
1865 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001866 int level, struct buffer_head *bh)
Koji Sato17c76b02009-04-06 19:01:24 -07001867{
1868 int maxlevel, ret;
1869 struct nilfs_btree_node *parent;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001870 struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001871 __u64 ptr;
1872
1873 get_bh(bh);
1874 path[level].bp_bh = bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001875 ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel,
1876 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001877 if (ret < 0)
1878 goto out;
1879
1880 if (buffer_nilfs_volatile(path[level].bp_bh)) {
1881 parent = nilfs_btree_get_node(btree, path, level + 1);
1882 ptr = nilfs_btree_node_get_ptr(btree, parent,
1883 path[level + 1].bp_index);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001884 ret = nilfs_dat_mark_dirty(dat, ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001885 if (ret < 0)
1886 goto out;
1887 }
1888
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001889 nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001890
1891 out:
1892 brelse(path[level].bp_bh);
1893 path[level].bp_bh = NULL;
1894 return ret;
1895}
1896
1897static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
1898 struct buffer_head *bh)
1899{
1900 struct nilfs_btree *btree;
1901 struct nilfs_btree_path *path;
1902 struct nilfs_btree_node *node;
1903 __u64 key;
1904 int level, ret;
1905
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001906 WARN_ON(!buffer_dirty(bh));
Koji Sato17c76b02009-04-06 19:01:24 -07001907
1908 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001909 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001910 if (path == NULL)
1911 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001912 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001913
1914 if (buffer_nilfs_node(bh)) {
1915 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001916 key = nilfs_btree_node_get_key(node, 0);
1917 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001918 } else {
1919 key = nilfs_bmap_data_get_key(bmap, bh);
1920 level = NILFS_BTREE_LEVEL_DATA;
1921 }
1922
1923 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
1924 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001925 if (unlikely(ret == -ENOENT))
Koji Sato17c76b02009-04-06 19:01:24 -07001926 printk(KERN_CRIT "%s: key = %llu, level == %d\n",
1927 __func__, (unsigned long long)key, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001928 goto out;
1929 }
1930
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001931 ret = NILFS_BMAP_USE_VBN(bmap) ?
1932 nilfs_btree_propagate_v(btree, path, level, bh) :
1933 nilfs_btree_propagate_p(btree, path, level, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001934
1935 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09001936 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001937 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001938
1939 return ret;
1940}
1941
1942static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap,
1943 struct buffer_head *bh)
1944{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001945 return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), bh->b_blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07001946}
1947
1948static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree,
1949 struct list_head *lists,
1950 struct buffer_head *bh)
1951{
1952 struct list_head *head;
1953 struct buffer_head *cbh;
1954 struct nilfs_btree_node *node, *cnode;
1955 __u64 key, ckey;
1956 int level;
1957
1958 get_bh(bh);
1959 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001960 key = nilfs_btree_node_get_key(node, 0);
1961 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001962 list_for_each(head, &lists[level]) {
1963 cbh = list_entry(head, struct buffer_head, b_assoc_buffers);
1964 cnode = (struct nilfs_btree_node *)cbh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001965 ckey = nilfs_btree_node_get_key(cnode, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07001966 if (key < ckey)
1967 break;
1968 }
1969 list_add_tail(&bh->b_assoc_buffers, head);
1970}
1971
1972static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *bmap,
1973 struct list_head *listp)
1974{
1975 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
1976 struct address_space *btcache = &NILFS_BMAP_I(bmap)->i_btnode_cache;
1977 struct list_head lists[NILFS_BTREE_LEVEL_MAX];
1978 struct pagevec pvec;
1979 struct buffer_head *bh, *head;
1980 pgoff_t index = 0;
1981 int level, i;
1982
1983 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1984 level < NILFS_BTREE_LEVEL_MAX;
1985 level++)
1986 INIT_LIST_HEAD(&lists[level]);
1987
1988 pagevec_init(&pvec, 0);
1989
1990 while (pagevec_lookup_tag(&pvec, btcache, &index, PAGECACHE_TAG_DIRTY,
1991 PAGEVEC_SIZE)) {
1992 for (i = 0; i < pagevec_count(&pvec); i++) {
1993 bh = head = page_buffers(pvec.pages[i]);
1994 do {
1995 if (buffer_dirty(bh))
1996 nilfs_btree_add_dirty_buffer(btree,
1997 lists, bh);
1998 } while ((bh = bh->b_this_page) != head);
1999 }
2000 pagevec_release(&pvec);
2001 cond_resched();
2002 }
2003
2004 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
2005 level < NILFS_BTREE_LEVEL_MAX;
2006 level++)
2007 list_splice(&lists[level], listp->prev);
2008}
2009
2010static int nilfs_btree_assign_p(struct nilfs_btree *btree,
2011 struct nilfs_btree_path *path,
2012 int level,
2013 struct buffer_head **bh,
2014 sector_t blocknr,
2015 union nilfs_binfo *binfo)
2016{
2017 struct nilfs_btree_node *parent;
2018 __u64 key;
2019 __u64 ptr;
2020 int ret;
2021
2022 parent = nilfs_btree_get_node(btree, path, level + 1);
2023 ptr = nilfs_btree_node_get_ptr(btree, parent,
2024 path[level + 1].bp_index);
2025 if (buffer_nilfs_node(*bh)) {
2026 path[level].bp_ctxt.oldkey = ptr;
2027 path[level].bp_ctxt.newkey = blocknr;
2028 path[level].bp_ctxt.bh = *bh;
2029 ret = nilfs_btnode_prepare_change_key(
2030 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2031 &path[level].bp_ctxt);
2032 if (ret < 0)
2033 return ret;
2034 nilfs_btnode_commit_change_key(
2035 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2036 &path[level].bp_ctxt);
2037 *bh = path[level].bp_ctxt.bh;
2038 }
2039
2040 nilfs_btree_node_set_ptr(btree, parent,
2041 path[level + 1].bp_index, blocknr);
2042
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002043 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002044 /* on-disk format */
2045 binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2046 binfo->bi_dat.bi_level = level;
2047
2048 return 0;
2049}
2050
2051static int nilfs_btree_assign_v(struct nilfs_btree *btree,
2052 struct nilfs_btree_path *path,
2053 int level,
2054 struct buffer_head **bh,
2055 sector_t blocknr,
2056 union nilfs_binfo *binfo)
2057{
2058 struct nilfs_btree_node *parent;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002059 struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07002060 __u64 key;
2061 __u64 ptr;
2062 union nilfs_bmap_ptr_req req;
2063 int ret;
2064
2065 parent = nilfs_btree_get_node(btree, path, level + 1);
2066 ptr = nilfs_btree_node_get_ptr(btree, parent,
2067 path[level + 1].bp_index);
2068 req.bpr_ptr = ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002069 ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
2070 if (ret < 0)
Koji Sato17c76b02009-04-06 19:01:24 -07002071 return ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002072 nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002073
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002074 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002075 /* on-disk format */
2076 binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr);
2077 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2078
2079 return 0;
2080}
2081
2082static int nilfs_btree_assign(struct nilfs_bmap *bmap,
2083 struct buffer_head **bh,
2084 sector_t blocknr,
2085 union nilfs_binfo *binfo)
2086{
2087 struct nilfs_btree *btree;
2088 struct nilfs_btree_path *path;
2089 struct nilfs_btree_node *node;
2090 __u64 key;
2091 int level, ret;
2092
2093 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002094 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002095 if (path == NULL)
2096 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002097 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002098
2099 if (buffer_nilfs_node(*bh)) {
2100 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002101 key = nilfs_btree_node_get_key(node, 0);
2102 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07002103 } else {
2104 key = nilfs_bmap_data_get_key(bmap, *bh);
2105 level = NILFS_BTREE_LEVEL_DATA;
2106 }
2107
2108 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
2109 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002110 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002111 goto out;
2112 }
2113
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09002114 ret = NILFS_BMAP_USE_VBN(bmap) ?
2115 nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) :
2116 nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
Koji Sato17c76b02009-04-06 19:01:24 -07002117
2118 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09002119 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002120 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002121
2122 return ret;
2123}
2124
2125static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap,
2126 struct buffer_head **bh,
2127 sector_t blocknr,
2128 union nilfs_binfo *binfo)
2129{
Koji Sato17c76b02009-04-06 19:01:24 -07002130 struct nilfs_btree_node *node;
2131 __u64 key;
2132 int ret;
2133
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002134 ret = nilfs_dat_move(nilfs_bmap_get_dat(bmap), (*bh)->b_blocknr,
2135 blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002136 if (ret < 0)
2137 return ret;
2138
2139 if (buffer_nilfs_node(*bh)) {
2140 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002141 key = nilfs_btree_node_get_key(node, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07002142 } else
2143 key = nilfs_bmap_data_get_key(bmap, *bh);
2144
2145 /* on-disk format */
2146 binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr);
2147 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2148
2149 return 0;
2150}
2151
2152static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
2153{
2154 struct buffer_head *bh;
2155 struct nilfs_btree *btree;
2156 struct nilfs_btree_path *path;
2157 __u64 ptr;
2158 int ret;
2159
2160 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002161 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002162 if (path == NULL)
2163 return -ENOMEM;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002164 nilfs_btree_init_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002165
2166 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1);
2167 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002168 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002169 goto out;
2170 }
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09002171 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002172 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002173 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002174 goto out;
2175 }
2176
2177 if (!buffer_dirty(bh))
2178 nilfs_btnode_mark_dirty(bh);
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09002179 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002180 if (!nilfs_bmap_dirty(&btree->bt_bmap))
2181 nilfs_bmap_set_dirty(&btree->bt_bmap);
2182
2183 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09002184 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002185 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002186 return ret;
2187}
2188
2189static const struct nilfs_bmap_operations nilfs_btree_ops = {
2190 .bop_lookup = nilfs_btree_lookup,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002191 .bop_lookup_contig = nilfs_btree_lookup_contig,
Koji Sato17c76b02009-04-06 19:01:24 -07002192 .bop_insert = nilfs_btree_insert,
2193 .bop_delete = nilfs_btree_delete,
2194 .bop_clear = NULL,
2195
2196 .bop_propagate = nilfs_btree_propagate,
2197
2198 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2199
2200 .bop_assign = nilfs_btree_assign,
2201 .bop_mark = nilfs_btree_mark,
2202
2203 .bop_last_key = nilfs_btree_last_key,
2204 .bop_check_insert = NULL,
2205 .bop_check_delete = nilfs_btree_check_delete,
2206 .bop_gather_data = nilfs_btree_gather_data,
2207};
2208
2209static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
2210 .bop_lookup = NULL,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002211 .bop_lookup_contig = NULL,
Koji Sato17c76b02009-04-06 19:01:24 -07002212 .bop_insert = NULL,
2213 .bop_delete = NULL,
2214 .bop_clear = NULL,
2215
2216 .bop_propagate = nilfs_btree_propagate_gc,
2217
2218 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2219
2220 .bop_assign = nilfs_btree_assign_gc,
2221 .bop_mark = NULL,
2222
2223 .bop_last_key = NULL,
2224 .bop_check_insert = NULL,
2225 .bop_check_delete = NULL,
2226 .bop_gather_data = NULL,
2227};
2228
Ryusuke Konishi30333422009-05-24 00:09:44 +09002229int nilfs_btree_init(struct nilfs_bmap *bmap)
Koji Sato17c76b02009-04-06 19:01:24 -07002230{
Koji Sato17c76b02009-04-06 19:01:24 -07002231 bmap->b_ops = &nilfs_btree_ops;
Koji Sato17c76b02009-04-06 19:01:24 -07002232 return 0;
2233}
2234
2235void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
2236{
Koji Sato17c76b02009-04-06 19:01:24 -07002237 bmap->b_ops = &nilfs_btree_ops_gc;
2238}