blob: f479849874652b49d5e359d8a6201131f0d15d1f [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
Li Hongf9054402010-04-02 17:36:34 +080074static struct nilfs_btree_path *nilfs_btree_alloc_path(void)
Koji Sato17c76b02009-04-06 19:01:24 -070075{
Li Hongf9054402010-04-02 17:36:34 +080076 struct nilfs_btree_path *path;
77 int level = NILFS_BTREE_LEVEL_DATA;
Koji Sato17c76b02009-04-06 19:01:24 -070078
Li Hongf9054402010-04-02 17:36:34 +080079 path = kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS);
80 if (path == NULL)
81 goto out;
Koji Sato17c76b02009-04-06 19:01:24 -070082
Li Hongf9054402010-04-02 17:36:34 +080083 for (; level < NILFS_BTREE_LEVEL_MAX; level++) {
Koji Sato17c76b02009-04-06 19:01:24 -070084 path[level].bp_bh = NULL;
85 path[level].bp_sib_bh = NULL;
86 path[level].bp_index = 0;
87 path[level].bp_oldreq.bpr_ptr = NILFS_BMAP_INVALID_PTR;
88 path[level].bp_newreq.bpr_ptr = NILFS_BMAP_INVALID_PTR;
89 path[level].bp_op = NULL;
90 }
Li Hongf9054402010-04-02 17:36:34 +080091
92out:
93 return path;
94}
95
96static inline void nilfs_btree_free_path(struct nilfs_btree_path *path)
97{
98 kmem_cache_free(nilfs_btree_path_cache, path);
Koji Sato17c76b02009-04-06 19:01:24 -070099}
100
Ryusuke Konishi32189292009-08-15 01:54:59 +0900101static void nilfs_btree_release_path(struct nilfs_btree_path *path)
Koji Sato17c76b02009-04-06 19:01:24 -0700102{
103 int level;
104
Ryusuke Konishi32189292009-08-15 01:54:59 +0900105 for (level = NILFS_BTREE_LEVEL_DATA; level < NILFS_BTREE_LEVEL_MAX;
106 level++)
107 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700108}
109
Koji Sato17c76b02009-04-06 19:01:24 -0700110/*
111 * B-tree node operations
112 */
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900113static int nilfs_btree_get_block(const struct nilfs_btree *btree, __u64 ptr,
114 struct buffer_head **bhp)
115{
116 struct address_space *btnc =
117 &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
Ryusuke Konishi1376e932009-11-13 16:49:09 +0900118 int err;
119
120 err = nilfs_btnode_submit_block(btnc, ptr, 0, bhp);
121 if (err)
122 return err == -EEXIST ? 0 : err;
123
124 wait_on_buffer(*bhp);
125 if (!buffer_uptodate(*bhp)) {
126 brelse(*bhp);
127 return -EIO;
128 }
129 return 0;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900130}
131
132static int nilfs_btree_get_new_block(const struct nilfs_btree *btree,
133 __u64 ptr, struct buffer_head **bhp)
134{
135 struct address_space *btnc =
136 &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
Ryusuke Konishi45f49102009-11-13 16:25:19 +0900137 struct buffer_head *bh;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900138
Ryusuke Konishi45f49102009-11-13 16:25:19 +0900139 bh = nilfs_btnode_create_block(btnc, ptr);
140 if (!bh)
141 return -ENOMEM;
142
143 set_buffer_nilfs_volatile(bh);
144 *bhp = bh;
145 return 0;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900146}
Koji Sato17c76b02009-04-06 19:01:24 -0700147
148static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900149nilfs_btree_node_get_flags(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700150{
151 return node->bn_flags;
152}
153
154static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900155nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags)
Koji Sato17c76b02009-04-06 19:01:24 -0700156{
157 node->bn_flags = flags;
158}
159
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900160static inline int nilfs_btree_node_root(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700161{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900162 return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT;
Koji Sato17c76b02009-04-06 19:01:24 -0700163}
164
165static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900166nilfs_btree_node_get_level(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700167{
168 return node->bn_level;
169}
170
171static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900172nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700173{
174 node->bn_level = level;
175}
176
177static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900178nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700179{
180 return le16_to_cpu(node->bn_nchildren);
181}
182
183static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900184nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren)
Koji Sato17c76b02009-04-06 19:01:24 -0700185{
186 node->bn_nchildren = cpu_to_le16(nchildren);
187}
188
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900189static inline int nilfs_btree_node_size(const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700190{
191 return 1 << btree->bt_bmap.b_inode->i_blkbits;
192}
193
194static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900195nilfs_btree_node_nchildren_min(const struct nilfs_btree_node *node,
196 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700197{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900198 return nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700199 NILFS_BTREE_ROOT_NCHILDREN_MIN :
200 NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree));
201}
202
203static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900204nilfs_btree_node_nchildren_max(const struct nilfs_btree_node *node,
205 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700206{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900207 return nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700208 NILFS_BTREE_ROOT_NCHILDREN_MAX :
209 NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree));
210}
211
212static inline __le64 *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900213nilfs_btree_node_dkeys(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700214{
215 return (__le64 *)((char *)(node + 1) +
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900216 (nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700217 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE));
218}
219
220static inline __le64 *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900221nilfs_btree_node_dptrs(const struct nilfs_btree_node *node,
222 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700223{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900224 return (__le64 *)(nilfs_btree_node_dkeys(node) +
225 nilfs_btree_node_nchildren_max(node, btree));
Koji Sato17c76b02009-04-06 19:01:24 -0700226}
227
228static inline __u64
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900229nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index)
Koji Sato17c76b02009-04-06 19:01:24 -0700230{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900231 return nilfs_bmap_dkey_to_key(*(nilfs_btree_node_dkeys(node) + index));
Koji Sato17c76b02009-04-06 19:01:24 -0700232}
233
234static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900235nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key)
Koji Sato17c76b02009-04-06 19:01:24 -0700236{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900237 *(nilfs_btree_node_dkeys(node) + index) = nilfs_bmap_key_to_dkey(key);
Koji Sato17c76b02009-04-06 19:01:24 -0700238}
239
240static inline __u64
241nilfs_btree_node_get_ptr(const struct nilfs_btree *btree,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900242 const struct nilfs_btree_node *node, int index)
Koji Sato17c76b02009-04-06 19:01:24 -0700243{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900244 return nilfs_bmap_dptr_to_ptr(*(nilfs_btree_node_dptrs(node, btree) +
Koji Sato17c76b02009-04-06 19:01:24 -0700245 index));
246}
247
248static inline void
249nilfs_btree_node_set_ptr(struct nilfs_btree *btree,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900250 struct nilfs_btree_node *node, int index, __u64 ptr)
Koji Sato17c76b02009-04-06 19:01:24 -0700251{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900252 *(nilfs_btree_node_dptrs(node, btree) + index) =
Koji Sato17c76b02009-04-06 19:01:24 -0700253 nilfs_bmap_ptr_to_dptr(ptr);
254}
255
256static void nilfs_btree_node_init(struct nilfs_btree *btree,
257 struct nilfs_btree_node *node,
258 int flags, int level, int nchildren,
259 const __u64 *keys, const __u64 *ptrs)
260{
261 __le64 *dkeys;
262 __le64 *dptrs;
263 int i;
264
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900265 nilfs_btree_node_set_flags(node, flags);
266 nilfs_btree_node_set_level(node, level);
267 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700268
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900269 dkeys = nilfs_btree_node_dkeys(node);
270 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700271 for (i = 0; i < nchildren; i++) {
272 dkeys[i] = nilfs_bmap_key_to_dkey(keys[i]);
273 dptrs[i] = nilfs_bmap_ptr_to_dptr(ptrs[i]);
274 }
275}
276
277/* Assume the buffer heads corresponding to left and right are locked. */
278static void nilfs_btree_node_move_left(struct nilfs_btree *btree,
279 struct nilfs_btree_node *left,
280 struct nilfs_btree_node *right,
281 int n)
282{
283 __le64 *ldkeys, *rdkeys;
284 __le64 *ldptrs, *rdptrs;
285 int lnchildren, rnchildren;
286
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900287 ldkeys = nilfs_btree_node_dkeys(left);
288 ldptrs = nilfs_btree_node_dptrs(left, btree);
289 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700290
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900291 rdkeys = nilfs_btree_node_dkeys(right);
292 rdptrs = nilfs_btree_node_dptrs(right, btree);
293 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700294
295 memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys));
296 memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs));
297 memmove(rdkeys, rdkeys + n, (rnchildren - n) * sizeof(*rdkeys));
298 memmove(rdptrs, rdptrs + n, (rnchildren - n) * sizeof(*rdptrs));
299
300 lnchildren += n;
301 rnchildren -= n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900302 nilfs_btree_node_set_nchildren(left, lnchildren);
303 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700304}
305
306/* Assume that the buffer heads corresponding to left and right are locked. */
307static void nilfs_btree_node_move_right(struct nilfs_btree *btree,
308 struct nilfs_btree_node *left,
309 struct nilfs_btree_node *right,
310 int n)
311{
312 __le64 *ldkeys, *rdkeys;
313 __le64 *ldptrs, *rdptrs;
314 int lnchildren, rnchildren;
315
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900316 ldkeys = nilfs_btree_node_dkeys(left);
317 ldptrs = nilfs_btree_node_dptrs(left, btree);
318 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700319
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900320 rdkeys = nilfs_btree_node_dkeys(right);
321 rdptrs = nilfs_btree_node_dptrs(right, btree);
322 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700323
324 memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys));
325 memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs));
326 memcpy(rdkeys, ldkeys + lnchildren - n, n * sizeof(*rdkeys));
327 memcpy(rdptrs, ldptrs + lnchildren - n, n * sizeof(*rdptrs));
328
329 lnchildren -= n;
330 rnchildren += n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900331 nilfs_btree_node_set_nchildren(left, lnchildren);
332 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700333}
334
335/* Assume that the buffer head corresponding to node is locked. */
336static void nilfs_btree_node_insert(struct nilfs_btree *btree,
337 struct nilfs_btree_node *node,
338 __u64 key, __u64 ptr, int index)
339{
340 __le64 *dkeys;
341 __le64 *dptrs;
342 int nchildren;
343
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900344 dkeys = nilfs_btree_node_dkeys(node);
345 dptrs = nilfs_btree_node_dptrs(node, btree);
346 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700347 if (index < nchildren) {
348 memmove(dkeys + index + 1, dkeys + index,
349 (nchildren - index) * sizeof(*dkeys));
350 memmove(dptrs + index + 1, dptrs + index,
351 (nchildren - index) * sizeof(*dptrs));
352 }
353 dkeys[index] = nilfs_bmap_key_to_dkey(key);
354 dptrs[index] = nilfs_bmap_ptr_to_dptr(ptr);
355 nchildren++;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900356 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700357}
358
359/* Assume that the buffer head corresponding to node is locked. */
360static void nilfs_btree_node_delete(struct nilfs_btree *btree,
361 struct nilfs_btree_node *node,
362 __u64 *keyp, __u64 *ptrp, int index)
363{
364 __u64 key;
365 __u64 ptr;
366 __le64 *dkeys;
367 __le64 *dptrs;
368 int nchildren;
369
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900370 dkeys = nilfs_btree_node_dkeys(node);
371 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700372 key = nilfs_bmap_dkey_to_key(dkeys[index]);
373 ptr = nilfs_bmap_dptr_to_ptr(dptrs[index]);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900374 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700375 if (keyp != NULL)
376 *keyp = key;
377 if (ptrp != NULL)
378 *ptrp = ptr;
379
380 if (index < nchildren - 1) {
381 memmove(dkeys + index, dkeys + index + 1,
382 (nchildren - index - 1) * sizeof(*dkeys));
383 memmove(dptrs + index, dptrs + index + 1,
384 (nchildren - index - 1) * sizeof(*dptrs));
385 }
386 nchildren--;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900387 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700388}
389
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900390static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node,
Koji Sato17c76b02009-04-06 19:01:24 -0700391 __u64 key, int *indexp)
392{
393 __u64 nkey;
394 int index, low, high, s;
395
396 /* binary search */
397 low = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900398 high = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700399 index = 0;
400 s = 0;
401 while (low <= high) {
402 index = (low + high) / 2;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900403 nkey = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700404 if (nkey == key) {
405 s = 0;
406 goto out;
407 } else if (nkey < key) {
408 low = index + 1;
409 s = -1;
410 } else {
411 high = index - 1;
412 s = 1;
413 }
414 }
415
416 /* adjust index */
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900417 if (nilfs_btree_node_get_level(node) > NILFS_BTREE_LEVEL_NODE_MIN) {
418 if (s > 0 && index > 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700419 index--;
420 } else if (s < 0)
421 index++;
422
423 out:
Koji Sato17c76b02009-04-06 19:01:24 -0700424 *indexp = index;
425
426 return s == 0;
427}
428
429static inline struct nilfs_btree_node *
430nilfs_btree_get_root(const struct nilfs_btree *btree)
431{
432 return (struct nilfs_btree_node *)btree->bt_bmap.b_u.u_data;
433}
434
435static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900436nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700437{
438 return (struct nilfs_btree_node *)path[level].bp_bh->b_data;
439}
440
441static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900442nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700443{
444 return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data;
445}
446
447static inline int nilfs_btree_height(const struct nilfs_btree *btree)
448{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900449 return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700450}
451
452static inline struct nilfs_btree_node *
453nilfs_btree_get_node(const struct nilfs_btree *btree,
454 const struct nilfs_btree_path *path,
455 int level)
456{
457 return (level == nilfs_btree_height(btree) - 1) ?
458 nilfs_btree_get_root(btree) :
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900459 nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700460}
461
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900462static inline int
463nilfs_btree_bad_node(struct nilfs_btree_node *node, int level)
464{
465 if (unlikely(nilfs_btree_node_get_level(node) != level)) {
466 dump_stack();
467 printk(KERN_CRIT "NILFS: btree level mismatch: %d != %d\n",
468 nilfs_btree_node_get_level(node), level);
469 return 1;
470 }
471 return 0;
472}
473
Koji Sato17c76b02009-04-06 19:01:24 -0700474static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
475 struct nilfs_btree_path *path,
476 __u64 key, __u64 *ptrp, int minlevel)
477{
478 struct nilfs_btree_node *node;
479 __u64 ptr;
480 int level, index, found, ret;
481
Koji Sato17c76b02009-04-06 19:01:24 -0700482 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900483 level = nilfs_btree_node_get_level(node);
484 if (level < minlevel || nilfs_btree_node_get_nchildren(node) <= 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700485 return -ENOENT;
486
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900487 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700488 ptr = nilfs_btree_node_get_ptr(btree, node, index);
489 path[level].bp_bh = NULL;
490 path[level].bp_index = index;
491
492 for (level--; level >= minlevel; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900493 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700494 if (ret < 0)
495 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900496 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900497 if (nilfs_btree_bad_node(node, level))
498 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -0700499 if (!found)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900500 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700501 else
502 index = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900503 if (index < nilfs_btree_node_nchildren_max(node, btree))
Koji Sato17c76b02009-04-06 19:01:24 -0700504 ptr = nilfs_btree_node_get_ptr(btree, node, index);
505 else {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700506 WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN);
Koji Sato17c76b02009-04-06 19:01:24 -0700507 /* insert */
508 ptr = NILFS_BMAP_INVALID_PTR;
509 }
510 path[level].bp_index = index;
511 }
512 if (!found)
513 return -ENOENT;
514
515 if (ptrp != NULL)
516 *ptrp = ptr;
517
518 return 0;
519}
520
521static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree,
522 struct nilfs_btree_path *path,
523 __u64 *keyp, __u64 *ptrp)
524{
525 struct nilfs_btree_node *node;
526 __u64 ptr;
527 int index, level, ret;
528
529 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900530 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700531 if (index < 0)
532 return -ENOENT;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900533 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700534 ptr = nilfs_btree_node_get_ptr(btree, node, index);
535 path[level].bp_bh = NULL;
536 path[level].bp_index = index;
537
538 for (level--; level > 0; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900539 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700540 if (ret < 0)
541 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900542 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900543 if (nilfs_btree_bad_node(node, level))
544 return -EINVAL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900545 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700546 ptr = nilfs_btree_node_get_ptr(btree, node, index);
547 path[level].bp_index = index;
548 }
549
550 if (keyp != NULL)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900551 *keyp = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700552 if (ptrp != NULL)
553 *ptrp = ptr;
554
555 return 0;
556}
557
558static int nilfs_btree_lookup(const struct nilfs_bmap *bmap,
559 __u64 key, int level, __u64 *ptrp)
560{
561 struct nilfs_btree *btree;
562 struct nilfs_btree_path *path;
563 __u64 ptr;
564 int ret;
565
566 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900567 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -0700568 if (path == NULL)
569 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -0700570
571 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
572
573 if (ptrp != NULL)
574 *ptrp = ptr;
575
Ryusuke Konishi32189292009-08-15 01:54:59 +0900576 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900577 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -0700578
579 return ret;
580}
581
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900582static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
583 __u64 key, __u64 *ptrp, unsigned maxblocks)
584{
585 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
586 struct nilfs_btree_path *path;
587 struct nilfs_btree_node *node;
588 struct inode *dat = NULL;
589 __u64 ptr, ptr2;
590 sector_t blocknr;
591 int level = NILFS_BTREE_LEVEL_NODE_MIN;
592 int ret, cnt, index, maxlevel;
593
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900594 path = nilfs_btree_alloc_path();
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900595 if (path == NULL)
596 return -ENOMEM;
Li Hongf9054402010-04-02 17:36:34 +0800597
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900598 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
599 if (ret < 0)
600 goto out;
601
602 if (NILFS_BMAP_USE_VBN(bmap)) {
603 dat = nilfs_bmap_get_dat(bmap);
604 ret = nilfs_dat_translate(dat, ptr, &blocknr);
605 if (ret < 0)
606 goto out;
607 ptr = blocknr;
608 }
609 cnt = 1;
610 if (cnt == maxblocks)
611 goto end;
612
613 maxlevel = nilfs_btree_height(btree) - 1;
614 node = nilfs_btree_get_node(btree, path, level);
615 index = path[level].bp_index + 1;
616 for (;;) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900617 while (index < nilfs_btree_node_get_nchildren(node)) {
618 if (nilfs_btree_node_get_key(node, index) !=
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900619 key + cnt)
620 goto end;
621 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
622 if (dat) {
623 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
624 if (ret < 0)
625 goto out;
626 ptr2 = blocknr;
627 }
628 if (ptr2 != ptr + cnt || ++cnt == maxblocks)
629 goto end;
630 index++;
631 continue;
632 }
633 if (level == maxlevel)
634 break;
635
636 /* look-up right sibling node */
637 node = nilfs_btree_get_node(btree, path, level + 1);
638 index = path[level + 1].bp_index + 1;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900639 if (index >= nilfs_btree_node_get_nchildren(node) ||
640 nilfs_btree_node_get_key(node, index) != key + cnt)
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900641 break;
642 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
643 path[level + 1].bp_index = index;
644
645 brelse(path[level].bp_bh);
646 path[level].bp_bh = NULL;
647 ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh);
648 if (ret < 0)
649 goto out;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900650 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900651 index = 0;
652 path[level].bp_index = index;
653 }
654 end:
655 *ptrp = ptr;
656 ret = cnt;
657 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +0900658 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900659 nilfs_btree_free_path(path);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900660 return ret;
661}
662
Koji Sato17c76b02009-04-06 19:01:24 -0700663static void nilfs_btree_promote_key(struct nilfs_btree *btree,
664 struct nilfs_btree_path *path,
665 int level, __u64 key)
666{
667 if (level < nilfs_btree_height(btree) - 1) {
668 do {
Koji Sato17c76b02009-04-06 19:01:24 -0700669 nilfs_btree_node_set_key(
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900670 nilfs_btree_get_nonroot_node(path, level),
Koji Sato17c76b02009-04-06 19:01:24 -0700671 path[level].bp_index, key);
672 if (!buffer_dirty(path[level].bp_bh))
673 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700674 } while ((path[level].bp_index == 0) &&
675 (++level < nilfs_btree_height(btree) - 1));
676 }
677
678 /* root */
679 if (level == nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900680 nilfs_btree_node_set_key(nilfs_btree_get_root(btree),
Koji Sato17c76b02009-04-06 19:01:24 -0700681 path[level].bp_index, key);
682 }
683}
684
685static void nilfs_btree_do_insert(struct nilfs_btree *btree,
686 struct nilfs_btree_path *path,
687 int level, __u64 *keyp, __u64 *ptrp)
688{
689 struct nilfs_btree_node *node;
690
691 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900692 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700693 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
694 path[level].bp_index);
695 if (!buffer_dirty(path[level].bp_bh))
696 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700697
698 if (path[level].bp_index == 0)
699 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900700 nilfs_btree_node_get_key(node,
701 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700702 } else {
703 node = nilfs_btree_get_root(btree);
704 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
705 path[level].bp_index);
706 }
707}
708
709static void nilfs_btree_carry_left(struct nilfs_btree *btree,
710 struct nilfs_btree_path *path,
711 int level, __u64 *keyp, __u64 *ptrp)
712{
713 struct nilfs_btree_node *node, *left;
714 int nchildren, lnchildren, n, move;
715
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900716 node = nilfs_btree_get_nonroot_node(path, level);
717 left = nilfs_btree_get_sib_node(path, level);
718 nchildren = nilfs_btree_node_get_nchildren(node);
719 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700720 move = 0;
721
722 n = (nchildren + lnchildren + 1) / 2 - lnchildren;
723 if (n > path[level].bp_index) {
724 /* move insert point */
725 n--;
726 move = 1;
727 }
728
729 nilfs_btree_node_move_left(btree, left, node, n);
730
731 if (!buffer_dirty(path[level].bp_bh))
732 nilfs_btnode_mark_dirty(path[level].bp_bh);
733 if (!buffer_dirty(path[level].bp_sib_bh))
734 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
735
Koji Sato17c76b02009-04-06 19:01:24 -0700736 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900737 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700738
739 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900740 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700741 path[level].bp_bh = path[level].bp_sib_bh;
742 path[level].bp_sib_bh = NULL;
743 path[level].bp_index += lnchildren;
744 path[level + 1].bp_index--;
745 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900746 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700747 path[level].bp_sib_bh = NULL;
748 path[level].bp_index -= n;
749 }
750
751 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
752}
753
754static void nilfs_btree_carry_right(struct nilfs_btree *btree,
755 struct nilfs_btree_path *path,
756 int level, __u64 *keyp, __u64 *ptrp)
757{
758 struct nilfs_btree_node *node, *right;
759 int nchildren, rnchildren, n, move;
760
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900761 node = nilfs_btree_get_nonroot_node(path, level);
762 right = nilfs_btree_get_sib_node(path, level);
763 nchildren = nilfs_btree_node_get_nchildren(node);
764 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700765 move = 0;
766
767 n = (nchildren + rnchildren + 1) / 2 - rnchildren;
768 if (n > nchildren - path[level].bp_index) {
769 /* move insert point */
770 n--;
771 move = 1;
772 }
773
774 nilfs_btree_node_move_right(btree, node, right, n);
775
776 if (!buffer_dirty(path[level].bp_bh))
777 nilfs_btnode_mark_dirty(path[level].bp_bh);
778 if (!buffer_dirty(path[level].bp_sib_bh))
779 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
780
Koji Sato17c76b02009-04-06 19:01:24 -0700781 path[level + 1].bp_index++;
782 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900783 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700784 path[level + 1].bp_index--;
785
786 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900787 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700788 path[level].bp_bh = path[level].bp_sib_bh;
789 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900790 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700791 path[level + 1].bp_index++;
792 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900793 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700794 path[level].bp_sib_bh = NULL;
795 }
796
797 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
798}
799
800static void nilfs_btree_split(struct nilfs_btree *btree,
801 struct nilfs_btree_path *path,
802 int level, __u64 *keyp, __u64 *ptrp)
803{
804 struct nilfs_btree_node *node, *right;
805 __u64 newkey;
806 __u64 newptr;
807 int nchildren, n, move;
808
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900809 node = nilfs_btree_get_nonroot_node(path, level);
810 right = nilfs_btree_get_sib_node(path, level);
811 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700812 move = 0;
813
814 n = (nchildren + 1) / 2;
815 if (n > nchildren - path[level].bp_index) {
816 n--;
817 move = 1;
818 }
819
820 nilfs_btree_node_move_right(btree, node, right, n);
821
822 if (!buffer_dirty(path[level].bp_bh))
823 nilfs_btnode_mark_dirty(path[level].bp_bh);
824 if (!buffer_dirty(path[level].bp_sib_bh))
825 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
826
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900827 newkey = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700828 newptr = path[level].bp_newreq.bpr_ptr;
829
830 if (move) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900831 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700832 nilfs_btree_node_insert(btree, right, *keyp, *ptrp,
833 path[level].bp_index);
834
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900835 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700836 *ptrp = path[level].bp_newreq.bpr_ptr;
837
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900838 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700839 path[level].bp_bh = path[level].bp_sib_bh;
840 path[level].bp_sib_bh = NULL;
841 } else {
842 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
843
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900844 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700845 *ptrp = path[level].bp_newreq.bpr_ptr;
846
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900847 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700848 path[level].bp_sib_bh = NULL;
849 }
850
851 path[level + 1].bp_index++;
852}
853
854static void nilfs_btree_grow(struct nilfs_btree *btree,
855 struct nilfs_btree_path *path,
856 int level, __u64 *keyp, __u64 *ptrp)
857{
858 struct nilfs_btree_node *root, *child;
859 int n;
860
Koji Sato17c76b02009-04-06 19:01:24 -0700861 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900862 child = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700863
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900864 n = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -0700865
866 nilfs_btree_node_move_right(btree, root, child, n);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900867 nilfs_btree_node_set_level(root, level + 1);
Koji Sato17c76b02009-04-06 19:01:24 -0700868
869 if (!buffer_dirty(path[level].bp_sib_bh))
870 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
871
Koji Sato17c76b02009-04-06 19:01:24 -0700872 path[level].bp_bh = path[level].bp_sib_bh;
873 path[level].bp_sib_bh = NULL;
874
875 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
876
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900877 *keyp = nilfs_btree_node_get_key(child, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700878 *ptrp = path[level].bp_newreq.bpr_ptr;
879}
880
881static __u64 nilfs_btree_find_near(const struct nilfs_btree *btree,
882 const struct nilfs_btree_path *path)
883{
884 struct nilfs_btree_node *node;
885 int level;
886
887 if (path == NULL)
888 return NILFS_BMAP_INVALID_PTR;
889
890 /* left sibling */
891 level = NILFS_BTREE_LEVEL_NODE_MIN;
892 if (path[level].bp_index > 0) {
893 node = nilfs_btree_get_node(btree, path, level);
894 return nilfs_btree_node_get_ptr(btree, node,
895 path[level].bp_index - 1);
896 }
897
898 /* parent */
899 level = NILFS_BTREE_LEVEL_NODE_MIN + 1;
900 if (level <= nilfs_btree_height(btree) - 1) {
901 node = nilfs_btree_get_node(btree, path, level);
902 return nilfs_btree_node_get_ptr(btree, node,
903 path[level].bp_index);
904 }
905
906 return NILFS_BMAP_INVALID_PTR;
907}
908
909static __u64 nilfs_btree_find_target_v(const struct nilfs_btree *btree,
910 const struct nilfs_btree_path *path,
911 __u64 key)
912{
913 __u64 ptr;
914
915 ptr = nilfs_bmap_find_target_seq(&btree->bt_bmap, key);
916 if (ptr != NILFS_BMAP_INVALID_PTR)
917 /* sequential access */
918 return ptr;
919 else {
920 ptr = nilfs_btree_find_near(btree, path);
921 if (ptr != NILFS_BMAP_INVALID_PTR)
922 /* near */
923 return ptr;
924 }
925 /* block group */
926 return nilfs_bmap_find_target_in_group(&btree->bt_bmap);
927}
928
929static void nilfs_btree_set_target_v(struct nilfs_btree *btree, __u64 key,
930 __u64 ptr)
931{
932 btree->bt_bmap.b_last_allocated_key = key;
933 btree->bt_bmap.b_last_allocated_ptr = ptr;
934}
935
936static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
937 struct nilfs_btree_path *path,
938 int *levelp, __u64 key, __u64 ptr,
939 struct nilfs_bmap_stats *stats)
940{
941 struct buffer_head *bh;
942 struct nilfs_btree_node *node, *parent, *sib;
943 __u64 sibptr;
944 int pindex, level, ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900945 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -0700946
947 stats->bs_nblocks = 0;
948 level = NILFS_BTREE_LEVEL_DATA;
949
950 /* allocate a new ptr for data block */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900951 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700952 path[level].bp_newreq.bpr_ptr =
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +0900953 nilfs_btree_find_target_v(btree, path, key);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900954 dat = nilfs_bmap_get_dat(&btree->bt_bmap);
955 }
Koji Sato17c76b02009-04-06 19:01:24 -0700956
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900957 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900958 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -0700959 if (ret < 0)
960 goto err_out_data;
961
962 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
963 level < nilfs_btree_height(btree) - 1;
964 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900965 node = nilfs_btree_get_nonroot_node(path, level);
966 if (nilfs_btree_node_get_nchildren(node) <
967 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700968 path[level].bp_op = nilfs_btree_do_insert;
969 stats->bs_nblocks++;
970 goto out;
971 }
972
973 parent = nilfs_btree_get_node(btree, path, level + 1);
974 pindex = path[level + 1].bp_index;
975
976 /* left sibling */
977 if (pindex > 0) {
978 sibptr = nilfs_btree_node_get_ptr(btree, parent,
979 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900980 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700981 if (ret < 0)
982 goto err_out_child_node;
983 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900984 if (nilfs_btree_node_get_nchildren(sib) <
985 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700986 path[level].bp_sib_bh = bh;
987 path[level].bp_op = nilfs_btree_carry_left;
988 stats->bs_nblocks++;
989 goto out;
990 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900991 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700992 }
993
994 /* right sibling */
995 if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900996 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -0700997 sibptr = nilfs_btree_node_get_ptr(btree, parent,
998 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900999 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001000 if (ret < 0)
1001 goto err_out_child_node;
1002 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001003 if (nilfs_btree_node_get_nchildren(sib) <
1004 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001005 path[level].bp_sib_bh = bh;
1006 path[level].bp_op = nilfs_btree_carry_right;
1007 stats->bs_nblocks++;
1008 goto out;
1009 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001010 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001011 }
1012
1013 /* split */
1014 path[level].bp_newreq.bpr_ptr =
1015 path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001016 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001017 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001018 if (ret < 0)
1019 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001020 ret = nilfs_btree_get_new_block(btree,
1021 path[level].bp_newreq.bpr_ptr,
1022 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001023 if (ret < 0)
1024 goto err_out_curr_node;
1025
1026 stats->bs_nblocks++;
1027
Koji Sato17c76b02009-04-06 19:01:24 -07001028 nilfs_btree_node_init(btree,
1029 (struct nilfs_btree_node *)bh->b_data,
1030 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001031 path[level].bp_sib_bh = bh;
1032 path[level].bp_op = nilfs_btree_split;
1033 }
1034
1035 /* root */
1036 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001037 if (nilfs_btree_node_get_nchildren(node) <
1038 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001039 path[level].bp_op = nilfs_btree_do_insert;
1040 stats->bs_nblocks++;
1041 goto out;
1042 }
1043
1044 /* grow */
1045 path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001046 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001047 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001048 if (ret < 0)
1049 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001050 ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
1051 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001052 if (ret < 0)
1053 goto err_out_curr_node;
1054
Koji Sato17c76b02009-04-06 19:01:24 -07001055 nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data,
1056 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001057 path[level].bp_sib_bh = bh;
1058 path[level].bp_op = nilfs_btree_grow;
1059
1060 level++;
1061 path[level].bp_op = nilfs_btree_do_insert;
1062
1063 /* a newly-created node block and a data block are added */
1064 stats->bs_nblocks += 2;
1065
1066 /* success */
1067 out:
1068 *levelp = level;
1069 return ret;
1070
1071 /* error */
1072 err_out_curr_node:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001073 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
1074 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001075 err_out_child_node:
1076 for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001077 nilfs_btnode_delete(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001078 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001079 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001080
1081 }
1082
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001083 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
1084 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001085 err_out_data:
1086 *levelp = level;
1087 stats->bs_nblocks = 0;
1088 return ret;
1089}
1090
1091static void nilfs_btree_commit_insert(struct nilfs_btree *btree,
1092 struct nilfs_btree_path *path,
1093 int maxlevel, __u64 key, __u64 ptr)
1094{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001095 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001096 int level;
1097
1098 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1099 ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001100 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001101 nilfs_btree_set_target_v(btree, key, ptr);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001102 dat = nilfs_bmap_get_dat(&btree->bt_bmap);
1103 }
Koji Sato17c76b02009-04-06 19:01:24 -07001104
1105 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001106 nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001107 &path[level - 1].bp_newreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001108 path[level].bp_op(btree, path, level, &key, &ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001109 }
1110
1111 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1112 nilfs_bmap_set_dirty(&btree->bt_bmap);
1113}
1114
1115static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
1116{
1117 struct nilfs_btree *btree;
1118 struct nilfs_btree_path *path;
1119 struct nilfs_bmap_stats stats;
1120 int level, ret;
1121
1122 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001123 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001124 if (path == NULL)
1125 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001126
1127 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1128 NILFS_BTREE_LEVEL_NODE_MIN);
1129 if (ret != -ENOENT) {
1130 if (ret == 0)
1131 ret = -EEXIST;
1132 goto out;
1133 }
1134
1135 ret = nilfs_btree_prepare_insert(btree, path, &level, key, ptr, &stats);
1136 if (ret < 0)
1137 goto out;
1138 nilfs_btree_commit_insert(btree, path, level, key, ptr);
1139 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1140
1141 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09001142 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001143 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001144 return ret;
1145}
1146
1147static void nilfs_btree_do_delete(struct nilfs_btree *btree,
1148 struct nilfs_btree_path *path,
1149 int level, __u64 *keyp, __u64 *ptrp)
1150{
1151 struct nilfs_btree_node *node;
1152
1153 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001154 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001155 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1156 path[level].bp_index);
1157 if (!buffer_dirty(path[level].bp_bh))
1158 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001159 if (path[level].bp_index == 0)
1160 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001161 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001162 } else {
1163 node = nilfs_btree_get_root(btree);
1164 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1165 path[level].bp_index);
1166 }
1167}
1168
1169static void nilfs_btree_borrow_left(struct nilfs_btree *btree,
1170 struct nilfs_btree_path *path,
1171 int level, __u64 *keyp, __u64 *ptrp)
1172{
1173 struct nilfs_btree_node *node, *left;
1174 int nchildren, lnchildren, n;
1175
1176 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1177
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001178 node = nilfs_btree_get_nonroot_node(path, level);
1179 left = nilfs_btree_get_sib_node(path, level);
1180 nchildren = nilfs_btree_node_get_nchildren(node);
1181 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001182
1183 n = (nchildren + lnchildren) / 2 - nchildren;
1184
1185 nilfs_btree_node_move_right(btree, left, node, n);
1186
1187 if (!buffer_dirty(path[level].bp_bh))
1188 nilfs_btnode_mark_dirty(path[level].bp_bh);
1189 if (!buffer_dirty(path[level].bp_sib_bh))
1190 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1191
Koji Sato17c76b02009-04-06 19:01:24 -07001192 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001193 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001194
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001195 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001196 path[level].bp_sib_bh = NULL;
1197 path[level].bp_index += n;
1198}
1199
1200static void nilfs_btree_borrow_right(struct nilfs_btree *btree,
1201 struct nilfs_btree_path *path,
1202 int level, __u64 *keyp, __u64 *ptrp)
1203{
1204 struct nilfs_btree_node *node, *right;
1205 int nchildren, rnchildren, n;
1206
1207 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1208
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001209 node = nilfs_btree_get_nonroot_node(path, level);
1210 right = nilfs_btree_get_sib_node(path, level);
1211 nchildren = nilfs_btree_node_get_nchildren(node);
1212 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001213
1214 n = (nchildren + rnchildren) / 2 - nchildren;
1215
1216 nilfs_btree_node_move_left(btree, node, right, n);
1217
1218 if (!buffer_dirty(path[level].bp_bh))
1219 nilfs_btnode_mark_dirty(path[level].bp_bh);
1220 if (!buffer_dirty(path[level].bp_sib_bh))
1221 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1222
Koji Sato17c76b02009-04-06 19:01:24 -07001223 path[level + 1].bp_index++;
1224 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001225 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001226 path[level + 1].bp_index--;
1227
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001228 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001229 path[level].bp_sib_bh = NULL;
1230}
1231
1232static void nilfs_btree_concat_left(struct nilfs_btree *btree,
1233 struct nilfs_btree_path *path,
1234 int level, __u64 *keyp, __u64 *ptrp)
1235{
1236 struct nilfs_btree_node *node, *left;
1237 int n;
1238
1239 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1240
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001241 node = nilfs_btree_get_nonroot_node(path, level);
1242 left = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001243
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001244 n = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001245
1246 nilfs_btree_node_move_left(btree, left, node, n);
1247
1248 if (!buffer_dirty(path[level].bp_sib_bh))
1249 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1250
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001251 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001252 path[level].bp_bh = path[level].bp_sib_bh;
1253 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001254 path[level].bp_index += nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001255}
1256
1257static void nilfs_btree_concat_right(struct nilfs_btree *btree,
1258 struct nilfs_btree_path *path,
1259 int level, __u64 *keyp, __u64 *ptrp)
1260{
1261 struct nilfs_btree_node *node, *right;
1262 int n;
1263
1264 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1265
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001266 node = nilfs_btree_get_nonroot_node(path, level);
1267 right = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001268
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001269 n = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001270
1271 nilfs_btree_node_move_left(btree, node, right, n);
1272
1273 if (!buffer_dirty(path[level].bp_bh))
1274 nilfs_btnode_mark_dirty(path[level].bp_bh);
1275
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001276 nilfs_btnode_delete(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001277 path[level].bp_sib_bh = NULL;
1278 path[level + 1].bp_index++;
1279}
1280
1281static void nilfs_btree_shrink(struct nilfs_btree *btree,
1282 struct nilfs_btree_path *path,
1283 int level, __u64 *keyp, __u64 *ptrp)
1284{
1285 struct nilfs_btree_node *root, *child;
1286 int n;
1287
1288 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1289
Koji Sato17c76b02009-04-06 19:01:24 -07001290 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001291 child = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001292
1293 nilfs_btree_node_delete(btree, root, NULL, NULL, 0);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001294 nilfs_btree_node_set_level(root, level);
1295 n = nilfs_btree_node_get_nchildren(child);
Koji Sato17c76b02009-04-06 19:01:24 -07001296 nilfs_btree_node_move_left(btree, root, child, n);
Koji Sato17c76b02009-04-06 19:01:24 -07001297
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001298 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001299 path[level].bp_bh = NULL;
1300}
1301
1302
1303static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
1304 struct nilfs_btree_path *path,
1305 int *levelp,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001306 struct nilfs_bmap_stats *stats,
1307 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001308{
1309 struct buffer_head *bh;
1310 struct nilfs_btree_node *node, *parent, *sib;
1311 __u64 sibptr;
1312 int pindex, level, ret;
1313
1314 ret = 0;
1315 stats->bs_nblocks = 0;
1316 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1317 level < nilfs_btree_height(btree) - 1;
1318 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001319 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001320 path[level].bp_oldreq.bpr_ptr =
1321 nilfs_btree_node_get_ptr(btree, node,
1322 path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001323 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001324 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001325 if (ret < 0)
1326 goto err_out_child_node;
Koji Sato17c76b02009-04-06 19:01:24 -07001327
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001328 if (nilfs_btree_node_get_nchildren(node) >
1329 nilfs_btree_node_nchildren_min(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001330 path[level].bp_op = nilfs_btree_do_delete;
1331 stats->bs_nblocks++;
1332 goto out;
1333 }
1334
1335 parent = nilfs_btree_get_node(btree, path, level + 1);
1336 pindex = path[level + 1].bp_index;
1337
1338 if (pindex > 0) {
1339 /* left sibling */
1340 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1341 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001342 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001343 if (ret < 0)
1344 goto err_out_curr_node;
1345 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001346 if (nilfs_btree_node_get_nchildren(sib) >
1347 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001348 path[level].bp_sib_bh = bh;
1349 path[level].bp_op = nilfs_btree_borrow_left;
1350 stats->bs_nblocks++;
1351 goto out;
1352 } else {
1353 path[level].bp_sib_bh = bh;
1354 path[level].bp_op = nilfs_btree_concat_left;
1355 stats->bs_nblocks++;
1356 /* continue; */
1357 }
1358 } else if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001359 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -07001360 /* right sibling */
1361 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1362 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001363 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001364 if (ret < 0)
1365 goto err_out_curr_node;
1366 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001367 if (nilfs_btree_node_get_nchildren(sib) >
1368 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001369 path[level].bp_sib_bh = bh;
1370 path[level].bp_op = nilfs_btree_borrow_right;
1371 stats->bs_nblocks++;
1372 goto out;
1373 } else {
1374 path[level].bp_sib_bh = bh;
1375 path[level].bp_op = nilfs_btree_concat_right;
1376 stats->bs_nblocks++;
1377 /* continue; */
1378 }
1379 } else {
1380 /* no siblings */
1381 /* the only child of the root node */
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001382 WARN_ON(level != nilfs_btree_height(btree) - 2);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001383 if (nilfs_btree_node_get_nchildren(node) - 1 <=
Koji Sato17c76b02009-04-06 19:01:24 -07001384 NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1385 path[level].bp_op = nilfs_btree_shrink;
1386 stats->bs_nblocks += 2;
1387 } else {
1388 path[level].bp_op = nilfs_btree_do_delete;
1389 stats->bs_nblocks++;
1390 }
1391
1392 goto out;
1393
1394 }
1395 }
1396
1397 node = nilfs_btree_get_root(btree);
1398 path[level].bp_oldreq.bpr_ptr =
1399 nilfs_btree_node_get_ptr(btree, node, path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001400
1401 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001402 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001403 if (ret < 0)
1404 goto err_out_child_node;
1405
Koji Sato17c76b02009-04-06 19:01:24 -07001406 /* child of the root node is deleted */
1407 path[level].bp_op = nilfs_btree_do_delete;
1408 stats->bs_nblocks++;
1409
1410 /* success */
1411 out:
1412 *levelp = level;
1413 return ret;
1414
1415 /* error */
1416 err_out_curr_node:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001417 nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001418 err_out_child_node:
1419 for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001420 brelse(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001421 nilfs_bmap_abort_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001422 &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001423 }
1424 *levelp = level;
1425 stats->bs_nblocks = 0;
1426 return ret;
1427}
1428
1429static void nilfs_btree_commit_delete(struct nilfs_btree *btree,
1430 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001431 int maxlevel, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001432{
1433 int level;
1434
1435 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001436 nilfs_bmap_commit_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001437 &path[level].bp_oldreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001438 path[level].bp_op(btree, path, level, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001439 }
1440
1441 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1442 nilfs_bmap_set_dirty(&btree->bt_bmap);
1443}
1444
1445static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key)
1446
1447{
1448 struct nilfs_btree *btree;
1449 struct nilfs_btree_path *path;
1450 struct nilfs_bmap_stats stats;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001451 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001452 int level, ret;
1453
1454 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001455 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001456 if (path == NULL)
1457 return -ENOMEM;
Li Hongf9054402010-04-02 17:36:34 +08001458
Koji Sato17c76b02009-04-06 19:01:24 -07001459 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1460 NILFS_BTREE_LEVEL_NODE_MIN);
1461 if (ret < 0)
1462 goto out;
1463
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001464
1465 dat = NILFS_BMAP_USE_VBN(&btree->bt_bmap) ?
1466 nilfs_bmap_get_dat(&btree->bt_bmap) : NULL;
1467
1468 ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001469 if (ret < 0)
1470 goto out;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001471 nilfs_btree_commit_delete(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001472 nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks);
1473
1474out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09001475 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001476 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001477 return ret;
1478}
1479
1480static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp)
1481{
1482 struct nilfs_btree *btree;
1483 struct nilfs_btree_path *path;
1484 int ret;
1485
1486 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001487 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001488 if (path == NULL)
1489 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001490
1491 ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL);
1492
Ryusuke Konishi32189292009-08-15 01:54:59 +09001493 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001494 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001495
1496 return ret;
1497}
1498
1499static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key)
1500{
1501 struct buffer_head *bh;
1502 struct nilfs_btree *btree;
1503 struct nilfs_btree_node *root, *node;
1504 __u64 maxkey, nextmaxkey;
1505 __u64 ptr;
1506 int nchildren, ret;
1507
1508 btree = (struct nilfs_btree *)bmap;
1509 root = nilfs_btree_get_root(btree);
1510 switch (nilfs_btree_height(btree)) {
1511 case 2:
1512 bh = NULL;
1513 node = root;
1514 break;
1515 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001516 nchildren = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -07001517 if (nchildren > 1)
1518 return 0;
1519 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001520 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001521 if (ret < 0)
1522 return ret;
1523 node = (struct nilfs_btree_node *)bh->b_data;
1524 break;
1525 default:
1526 return 0;
1527 }
1528
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001529 nchildren = nilfs_btree_node_get_nchildren(node);
1530 maxkey = nilfs_btree_node_get_key(node, nchildren - 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001531 nextmaxkey = (nchildren > 1) ?
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001532 nilfs_btree_node_get_key(node, nchildren - 2) : 0;
Koji Sato17c76b02009-04-06 19:01:24 -07001533 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001534 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001535
Ryusuke Konishi30333422009-05-24 00:09:44 +09001536 return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
Koji Sato17c76b02009-04-06 19:01:24 -07001537}
1538
1539static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
1540 __u64 *keys, __u64 *ptrs, int nitems)
1541{
1542 struct buffer_head *bh;
1543 struct nilfs_btree *btree;
1544 struct nilfs_btree_node *node, *root;
1545 __le64 *dkeys;
1546 __le64 *dptrs;
1547 __u64 ptr;
1548 int nchildren, i, ret;
1549
1550 btree = (struct nilfs_btree *)bmap;
1551 root = nilfs_btree_get_root(btree);
1552 switch (nilfs_btree_height(btree)) {
1553 case 2:
1554 bh = NULL;
1555 node = root;
1556 break;
1557 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001558 nchildren = nilfs_btree_node_get_nchildren(root);
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001559 WARN_ON(nchildren > 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001560 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001561 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001562 if (ret < 0)
1563 return ret;
1564 node = (struct nilfs_btree_node *)bh->b_data;
1565 break;
1566 default:
1567 node = NULL;
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001568 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -07001569 }
1570
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001571 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001572 if (nchildren < nitems)
1573 nitems = nchildren;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001574 dkeys = nilfs_btree_node_dkeys(node);
1575 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001576 for (i = 0; i < nitems; i++) {
1577 keys[i] = nilfs_bmap_dkey_to_key(dkeys[i]);
1578 ptrs[i] = nilfs_bmap_dptr_to_ptr(dptrs[i]);
1579 }
1580
1581 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001582 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001583
1584 return nitems;
1585}
1586
1587static int
1588nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
1589 union nilfs_bmap_ptr_req *dreq,
1590 union nilfs_bmap_ptr_req *nreq,
1591 struct buffer_head **bhp,
1592 struct nilfs_bmap_stats *stats)
1593{
1594 struct buffer_head *bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001595 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
1596 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001597 int ret;
1598
Koji Sato17c76b02009-04-06 19:01:24 -07001599 stats->bs_nblocks = 0;
1600
1601 /* for data */
1602 /* cannot find near ptr */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001603 if (NILFS_BMAP_USE_VBN(bmap)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001604 dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001605 dat = nilfs_bmap_get_dat(bmap);
1606 }
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001607
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001608 ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001609 if (ret < 0)
1610 return ret;
1611
1612 *bhp = NULL;
1613 stats->bs_nblocks++;
1614 if (nreq != NULL) {
1615 nreq->bpr_ptr = dreq->bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001616 ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001617 if (ret < 0)
1618 goto err_out_dreq;
1619
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001620 ret = nilfs_btree_get_new_block(btree, nreq->bpr_ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001621 if (ret < 0)
1622 goto err_out_nreq;
1623
1624 *bhp = bh;
1625 stats->bs_nblocks++;
1626 }
1627
1628 /* success */
1629 return 0;
1630
1631 /* error */
1632 err_out_nreq:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001633 nilfs_bmap_abort_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001634 err_out_dreq:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001635 nilfs_bmap_abort_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001636 stats->bs_nblocks = 0;
1637 return ret;
1638
1639}
1640
1641static void
1642nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
1643 __u64 key, __u64 ptr,
1644 const __u64 *keys, const __u64 *ptrs,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001645 int n,
Koji Sato17c76b02009-04-06 19:01:24 -07001646 union nilfs_bmap_ptr_req *dreq,
1647 union nilfs_bmap_ptr_req *nreq,
1648 struct buffer_head *bh)
1649{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001650 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
Koji Sato17c76b02009-04-06 19:01:24 -07001651 struct nilfs_btree_node *node;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001652 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001653 __u64 tmpptr;
1654
1655 /* free resources */
1656 if (bmap->b_ops->bop_clear != NULL)
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001657 bmap->b_ops->bop_clear(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001658
1659 /* ptr must be a pointer to a buffer head. */
1660 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1661
1662 /* convert and insert */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001663 dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL;
Ryusuke Konishi30333422009-05-24 00:09:44 +09001664 nilfs_btree_init(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001665 if (nreq != NULL) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001666 nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
1667 nilfs_bmap_commit_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001668
1669 /* create child node at level 1 */
Koji Sato17c76b02009-04-06 19:01:24 -07001670 node = (struct nilfs_btree_node *)bh->b_data;
1671 nilfs_btree_node_init(btree, node, 0, 1, n, keys, ptrs);
1672 nilfs_btree_node_insert(btree, node,
1673 key, dreq->bpr_ptr, n);
1674 if (!buffer_dirty(bh))
1675 nilfs_btnode_mark_dirty(bh);
1676 if (!nilfs_bmap_dirty(bmap))
1677 nilfs_bmap_set_dirty(bmap);
1678
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001679 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001680
1681 /* create root node at level 2 */
1682 node = nilfs_btree_get_root(btree);
1683 tmpptr = nreq->bpr_ptr;
1684 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1685 2, 1, &keys[0], &tmpptr);
1686 } else {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001687 nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001688
1689 /* create root node at level 1 */
1690 node = nilfs_btree_get_root(btree);
1691 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1692 1, n, keys, ptrs);
1693 nilfs_btree_node_insert(btree, node,
1694 key, dreq->bpr_ptr, n);
1695 if (!nilfs_bmap_dirty(bmap))
1696 nilfs_bmap_set_dirty(bmap);
1697 }
1698
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001699 if (NILFS_BMAP_USE_VBN(bmap))
1700 nilfs_btree_set_target_v(btree, key, dreq->bpr_ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001701}
1702
1703/**
1704 * nilfs_btree_convert_and_insert -
1705 * @bmap:
1706 * @key:
1707 * @ptr:
1708 * @keys:
1709 * @ptrs:
1710 * @n:
Koji Sato17c76b02009-04-06 19:01:24 -07001711 */
1712int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap,
1713 __u64 key, __u64 ptr,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001714 const __u64 *keys, const __u64 *ptrs, int n)
Koji Sato17c76b02009-04-06 19:01:24 -07001715{
1716 struct buffer_head *bh;
1717 union nilfs_bmap_ptr_req dreq, nreq, *di, *ni;
1718 struct nilfs_bmap_stats stats;
1719 int ret;
1720
1721 if (n + 1 <= NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1722 di = &dreq;
1723 ni = NULL;
1724 } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX(
1725 1 << bmap->b_inode->i_blkbits)) {
1726 di = &dreq;
1727 ni = &nreq;
1728 } else {
1729 di = NULL;
1730 ni = NULL;
1731 BUG();
1732 }
1733
1734 ret = nilfs_btree_prepare_convert_and_insert(bmap, key, di, ni, &bh,
1735 &stats);
1736 if (ret < 0)
1737 return ret;
1738 nilfs_btree_commit_convert_and_insert(bmap, key, ptr, keys, ptrs, n,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001739 di, ni, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001740 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1741 return 0;
1742}
1743
1744static int nilfs_btree_propagate_p(struct nilfs_btree *btree,
1745 struct nilfs_btree_path *path,
1746 int level,
1747 struct buffer_head *bh)
1748{
1749 while ((++level < nilfs_btree_height(btree) - 1) &&
1750 !buffer_dirty(path[level].bp_bh))
1751 nilfs_btnode_mark_dirty(path[level].bp_bh);
1752
1753 return 0;
1754}
1755
1756static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
1757 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001758 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001759{
1760 struct nilfs_btree_node *parent;
1761 int ret;
1762
1763 parent = nilfs_btree_get_node(btree, path, level + 1);
1764 path[level].bp_oldreq.bpr_ptr =
1765 nilfs_btree_node_get_ptr(btree, parent,
1766 path[level + 1].bp_index);
1767 path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001768 ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req,
1769 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001770 if (ret < 0)
1771 return ret;
1772
1773 if (buffer_nilfs_node(path[level].bp_bh)) {
1774 path[level].bp_ctxt.oldkey = path[level].bp_oldreq.bpr_ptr;
1775 path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr;
1776 path[level].bp_ctxt.bh = path[level].bp_bh;
1777 ret = nilfs_btnode_prepare_change_key(
1778 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1779 &path[level].bp_ctxt);
1780 if (ret < 0) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001781 nilfs_dat_abort_update(dat,
1782 &path[level].bp_oldreq.bpr_req,
1783 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001784 return ret;
1785 }
1786 }
1787
1788 return 0;
1789}
1790
1791static void nilfs_btree_commit_update_v(struct nilfs_btree *btree,
1792 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001793 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001794{
1795 struct nilfs_btree_node *parent;
1796
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001797 nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req,
1798 &path[level].bp_newreq.bpr_req,
1799 btree->bt_bmap.b_ptr_type == NILFS_BMAP_PTR_VS);
Koji Sato17c76b02009-04-06 19:01:24 -07001800
1801 if (buffer_nilfs_node(path[level].bp_bh)) {
1802 nilfs_btnode_commit_change_key(
1803 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1804 &path[level].bp_ctxt);
1805 path[level].bp_bh = path[level].bp_ctxt.bh;
1806 }
1807 set_buffer_nilfs_volatile(path[level].bp_bh);
1808
1809 parent = nilfs_btree_get_node(btree, path, level + 1);
1810 nilfs_btree_node_set_ptr(btree, parent, path[level + 1].bp_index,
1811 path[level].bp_newreq.bpr_ptr);
1812}
1813
1814static void nilfs_btree_abort_update_v(struct nilfs_btree *btree,
1815 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001816 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001817{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001818 nilfs_dat_abort_update(dat, &path[level].bp_oldreq.bpr_req,
1819 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001820 if (buffer_nilfs_node(path[level].bp_bh))
1821 nilfs_btnode_abort_change_key(
1822 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1823 &path[level].bp_ctxt);
1824}
1825
1826static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree,
1827 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001828 int minlevel, int *maxlevelp,
1829 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001830{
1831 int level, ret;
1832
1833 level = minlevel;
1834 if (!buffer_nilfs_volatile(path[level].bp_bh)) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001835 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001836 if (ret < 0)
1837 return ret;
1838 }
1839 while ((++level < nilfs_btree_height(btree) - 1) &&
1840 !buffer_dirty(path[level].bp_bh)) {
1841
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001842 WARN_ON(buffer_nilfs_volatile(path[level].bp_bh));
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001843 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001844 if (ret < 0)
1845 goto out;
1846 }
1847
1848 /* success */
Koji Sato17c76b02009-04-06 19:01:24 -07001849 *maxlevelp = level - 1;
1850 return 0;
1851
1852 /* error */
1853 out:
1854 while (--level > minlevel)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001855 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001856 if (!buffer_nilfs_volatile(path[level].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001857 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001858 return ret;
1859}
1860
1861static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree,
1862 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001863 int minlevel, int maxlevel,
1864 struct buffer_head *bh,
1865 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001866{
1867 int level;
1868
1869 if (!buffer_nilfs_volatile(path[minlevel].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001870 nilfs_btree_commit_update_v(btree, path, minlevel, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001871
1872 for (level = minlevel + 1; level <= maxlevel; level++)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001873 nilfs_btree_commit_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001874}
1875
1876static int nilfs_btree_propagate_v(struct nilfs_btree *btree,
1877 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001878 int level, struct buffer_head *bh)
Koji Sato17c76b02009-04-06 19:01:24 -07001879{
Li Hong308f4412010-04-02 18:40:39 +08001880 int maxlevel = 0, ret;
Koji Sato17c76b02009-04-06 19:01:24 -07001881 struct nilfs_btree_node *parent;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001882 struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001883 __u64 ptr;
1884
1885 get_bh(bh);
1886 path[level].bp_bh = bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001887 ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel,
1888 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001889 if (ret < 0)
1890 goto out;
1891
1892 if (buffer_nilfs_volatile(path[level].bp_bh)) {
1893 parent = nilfs_btree_get_node(btree, path, level + 1);
1894 ptr = nilfs_btree_node_get_ptr(btree, parent,
1895 path[level + 1].bp_index);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001896 ret = nilfs_dat_mark_dirty(dat, ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001897 if (ret < 0)
1898 goto out;
1899 }
1900
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001901 nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001902
1903 out:
1904 brelse(path[level].bp_bh);
1905 path[level].bp_bh = NULL;
1906 return ret;
1907}
1908
1909static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
1910 struct buffer_head *bh)
1911{
1912 struct nilfs_btree *btree;
1913 struct nilfs_btree_path *path;
1914 struct nilfs_btree_node *node;
1915 __u64 key;
1916 int level, ret;
1917
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001918 WARN_ON(!buffer_dirty(bh));
Koji Sato17c76b02009-04-06 19:01:24 -07001919
1920 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001921 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001922 if (path == NULL)
1923 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001924
1925 if (buffer_nilfs_node(bh)) {
1926 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001927 key = nilfs_btree_node_get_key(node, 0);
1928 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001929 } else {
1930 key = nilfs_bmap_data_get_key(bmap, bh);
1931 level = NILFS_BTREE_LEVEL_DATA;
1932 }
1933
1934 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
1935 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001936 if (unlikely(ret == -ENOENT))
Koji Sato17c76b02009-04-06 19:01:24 -07001937 printk(KERN_CRIT "%s: key = %llu, level == %d\n",
1938 __func__, (unsigned long long)key, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001939 goto out;
1940 }
1941
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001942 ret = NILFS_BMAP_USE_VBN(bmap) ?
1943 nilfs_btree_propagate_v(btree, path, level, bh) :
1944 nilfs_btree_propagate_p(btree, path, level, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001945
1946 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09001947 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001948 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001949
1950 return ret;
1951}
1952
1953static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap,
1954 struct buffer_head *bh)
1955{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001956 return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), bh->b_blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07001957}
1958
1959static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree,
1960 struct list_head *lists,
1961 struct buffer_head *bh)
1962{
1963 struct list_head *head;
1964 struct buffer_head *cbh;
1965 struct nilfs_btree_node *node, *cnode;
1966 __u64 key, ckey;
1967 int level;
1968
1969 get_bh(bh);
1970 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001971 key = nilfs_btree_node_get_key(node, 0);
1972 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001973 list_for_each(head, &lists[level]) {
1974 cbh = list_entry(head, struct buffer_head, b_assoc_buffers);
1975 cnode = (struct nilfs_btree_node *)cbh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001976 ckey = nilfs_btree_node_get_key(cnode, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07001977 if (key < ckey)
1978 break;
1979 }
1980 list_add_tail(&bh->b_assoc_buffers, head);
1981}
1982
1983static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *bmap,
1984 struct list_head *listp)
1985{
1986 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
1987 struct address_space *btcache = &NILFS_BMAP_I(bmap)->i_btnode_cache;
1988 struct list_head lists[NILFS_BTREE_LEVEL_MAX];
1989 struct pagevec pvec;
1990 struct buffer_head *bh, *head;
1991 pgoff_t index = 0;
1992 int level, i;
1993
1994 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1995 level < NILFS_BTREE_LEVEL_MAX;
1996 level++)
1997 INIT_LIST_HEAD(&lists[level]);
1998
1999 pagevec_init(&pvec, 0);
2000
2001 while (pagevec_lookup_tag(&pvec, btcache, &index, PAGECACHE_TAG_DIRTY,
2002 PAGEVEC_SIZE)) {
2003 for (i = 0; i < pagevec_count(&pvec); i++) {
2004 bh = head = page_buffers(pvec.pages[i]);
2005 do {
2006 if (buffer_dirty(bh))
2007 nilfs_btree_add_dirty_buffer(btree,
2008 lists, bh);
2009 } while ((bh = bh->b_this_page) != head);
2010 }
2011 pagevec_release(&pvec);
2012 cond_resched();
2013 }
2014
2015 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
2016 level < NILFS_BTREE_LEVEL_MAX;
2017 level++)
Ryusuke Konishi0935db72009-11-29 02:39:11 +09002018 list_splice_tail(&lists[level], listp);
Koji Sato17c76b02009-04-06 19:01:24 -07002019}
2020
2021static int nilfs_btree_assign_p(struct nilfs_btree *btree,
2022 struct nilfs_btree_path *path,
2023 int level,
2024 struct buffer_head **bh,
2025 sector_t blocknr,
2026 union nilfs_binfo *binfo)
2027{
2028 struct nilfs_btree_node *parent;
2029 __u64 key;
2030 __u64 ptr;
2031 int ret;
2032
2033 parent = nilfs_btree_get_node(btree, path, level + 1);
2034 ptr = nilfs_btree_node_get_ptr(btree, parent,
2035 path[level + 1].bp_index);
2036 if (buffer_nilfs_node(*bh)) {
2037 path[level].bp_ctxt.oldkey = ptr;
2038 path[level].bp_ctxt.newkey = blocknr;
2039 path[level].bp_ctxt.bh = *bh;
2040 ret = nilfs_btnode_prepare_change_key(
2041 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2042 &path[level].bp_ctxt);
2043 if (ret < 0)
2044 return ret;
2045 nilfs_btnode_commit_change_key(
2046 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2047 &path[level].bp_ctxt);
2048 *bh = path[level].bp_ctxt.bh;
2049 }
2050
2051 nilfs_btree_node_set_ptr(btree, parent,
2052 path[level + 1].bp_index, blocknr);
2053
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002054 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002055 /* on-disk format */
2056 binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2057 binfo->bi_dat.bi_level = level;
2058
2059 return 0;
2060}
2061
2062static int nilfs_btree_assign_v(struct nilfs_btree *btree,
2063 struct nilfs_btree_path *path,
2064 int level,
2065 struct buffer_head **bh,
2066 sector_t blocknr,
2067 union nilfs_binfo *binfo)
2068{
2069 struct nilfs_btree_node *parent;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002070 struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07002071 __u64 key;
2072 __u64 ptr;
2073 union nilfs_bmap_ptr_req req;
2074 int ret;
2075
2076 parent = nilfs_btree_get_node(btree, path, level + 1);
2077 ptr = nilfs_btree_node_get_ptr(btree, parent,
2078 path[level + 1].bp_index);
2079 req.bpr_ptr = ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002080 ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
2081 if (ret < 0)
Koji Sato17c76b02009-04-06 19:01:24 -07002082 return ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002083 nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002084
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002085 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002086 /* on-disk format */
2087 binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr);
2088 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2089
2090 return 0;
2091}
2092
2093static int nilfs_btree_assign(struct nilfs_bmap *bmap,
2094 struct buffer_head **bh,
2095 sector_t blocknr,
2096 union nilfs_binfo *binfo)
2097{
2098 struct nilfs_btree *btree;
2099 struct nilfs_btree_path *path;
2100 struct nilfs_btree_node *node;
2101 __u64 key;
2102 int level, ret;
2103
2104 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002105 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002106 if (path == NULL)
2107 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07002108
2109 if (buffer_nilfs_node(*bh)) {
2110 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002111 key = nilfs_btree_node_get_key(node, 0);
2112 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07002113 } else {
2114 key = nilfs_bmap_data_get_key(bmap, *bh);
2115 level = NILFS_BTREE_LEVEL_DATA;
2116 }
2117
2118 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
2119 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002120 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002121 goto out;
2122 }
2123
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09002124 ret = NILFS_BMAP_USE_VBN(bmap) ?
2125 nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) :
2126 nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
Koji Sato17c76b02009-04-06 19:01:24 -07002127
2128 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09002129 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002130 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002131
2132 return ret;
2133}
2134
2135static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap,
2136 struct buffer_head **bh,
2137 sector_t blocknr,
2138 union nilfs_binfo *binfo)
2139{
Koji Sato17c76b02009-04-06 19:01:24 -07002140 struct nilfs_btree_node *node;
2141 __u64 key;
2142 int ret;
2143
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002144 ret = nilfs_dat_move(nilfs_bmap_get_dat(bmap), (*bh)->b_blocknr,
2145 blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002146 if (ret < 0)
2147 return ret;
2148
2149 if (buffer_nilfs_node(*bh)) {
2150 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002151 key = nilfs_btree_node_get_key(node, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07002152 } else
2153 key = nilfs_bmap_data_get_key(bmap, *bh);
2154
2155 /* on-disk format */
2156 binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr);
2157 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2158
2159 return 0;
2160}
2161
2162static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
2163{
2164 struct buffer_head *bh;
2165 struct nilfs_btree *btree;
2166 struct nilfs_btree_path *path;
2167 __u64 ptr;
2168 int ret;
2169
2170 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002171 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002172 if (path == NULL)
2173 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07002174
2175 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1);
2176 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002177 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002178 goto out;
2179 }
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09002180 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002181 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002182 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002183 goto out;
2184 }
2185
2186 if (!buffer_dirty(bh))
2187 nilfs_btnode_mark_dirty(bh);
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09002188 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002189 if (!nilfs_bmap_dirty(&btree->bt_bmap))
2190 nilfs_bmap_set_dirty(&btree->bt_bmap);
2191
2192 out:
Ryusuke Konishi32189292009-08-15 01:54:59 +09002193 nilfs_btree_release_path(path);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002194 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002195 return ret;
2196}
2197
2198static const struct nilfs_bmap_operations nilfs_btree_ops = {
2199 .bop_lookup = nilfs_btree_lookup,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002200 .bop_lookup_contig = nilfs_btree_lookup_contig,
Koji Sato17c76b02009-04-06 19:01:24 -07002201 .bop_insert = nilfs_btree_insert,
2202 .bop_delete = nilfs_btree_delete,
2203 .bop_clear = NULL,
2204
2205 .bop_propagate = nilfs_btree_propagate,
2206
2207 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2208
2209 .bop_assign = nilfs_btree_assign,
2210 .bop_mark = nilfs_btree_mark,
2211
2212 .bop_last_key = nilfs_btree_last_key,
2213 .bop_check_insert = NULL,
2214 .bop_check_delete = nilfs_btree_check_delete,
2215 .bop_gather_data = nilfs_btree_gather_data,
2216};
2217
2218static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
2219 .bop_lookup = NULL,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002220 .bop_lookup_contig = NULL,
Koji Sato17c76b02009-04-06 19:01:24 -07002221 .bop_insert = NULL,
2222 .bop_delete = NULL,
2223 .bop_clear = NULL,
2224
2225 .bop_propagate = nilfs_btree_propagate_gc,
2226
2227 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2228
2229 .bop_assign = nilfs_btree_assign_gc,
2230 .bop_mark = NULL,
2231
2232 .bop_last_key = NULL,
2233 .bop_check_insert = NULL,
2234 .bop_check_delete = NULL,
2235 .bop_gather_data = NULL,
2236};
2237
Ryusuke Konishi30333422009-05-24 00:09:44 +09002238int nilfs_btree_init(struct nilfs_bmap *bmap)
Koji Sato17c76b02009-04-06 19:01:24 -07002239{
Koji Sato17c76b02009-04-06 19:01:24 -07002240 bmap->b_ops = &nilfs_btree_ops;
Koji Sato17c76b02009-04-06 19:01:24 -07002241 return 0;
2242}
2243
2244void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
2245{
Koji Sato17c76b02009-04-06 19:01:24 -07002246 bmap->b_ops = &nilfs_btree_ops_gc;
2247}