blob: dcd4e1c4deaa9e59052d2ab271d2e1dd8fcd2a11 [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
Li Hong73bb4882010-04-02 18:35:00 +080096static void nilfs_btree_free_path(struct nilfs_btree_path *path)
Li Hongf9054402010-04-02 17:36:34 +080097{
Li Hong73bb4882010-04-02 18:35:00 +080098 int level = NILFS_BTREE_LEVEL_DATA;
Koji Sato17c76b02009-04-06 19:01:24 -070099
Li Hong73bb4882010-04-02 18:35:00 +0800100 for (; level < NILFS_BTREE_LEVEL_MAX; level++)
Ryusuke Konishi32189292009-08-15 01:54:59 +0900101 brelse(path[level].bp_bh);
Li Hong73bb4882010-04-02 18:35:00 +0800102
103 kmem_cache_free(nilfs_btree_path_cache, path);
Koji Sato17c76b02009-04-06 19:01:24 -0700104}
105
Koji Sato17c76b02009-04-06 19:01:24 -0700106/*
107 * B-tree node operations
108 */
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900109static int nilfs_btree_get_block(const struct nilfs_btree *btree, __u64 ptr,
110 struct buffer_head **bhp)
111{
112 struct address_space *btnc =
113 &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
Ryusuke Konishi1376e932009-11-13 16:49:09 +0900114 int err;
115
116 err = nilfs_btnode_submit_block(btnc, ptr, 0, bhp);
117 if (err)
118 return err == -EEXIST ? 0 : err;
119
120 wait_on_buffer(*bhp);
121 if (!buffer_uptodate(*bhp)) {
122 brelse(*bhp);
123 return -EIO;
124 }
125 return 0;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900126}
127
128static int nilfs_btree_get_new_block(const struct nilfs_btree *btree,
129 __u64 ptr, struct buffer_head **bhp)
130{
131 struct address_space *btnc =
132 &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
Ryusuke Konishi45f49102009-11-13 16:25:19 +0900133 struct buffer_head *bh;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900134
Ryusuke Konishi45f49102009-11-13 16:25:19 +0900135 bh = nilfs_btnode_create_block(btnc, ptr);
136 if (!bh)
137 return -ENOMEM;
138
139 set_buffer_nilfs_volatile(bh);
140 *bhp = bh;
141 return 0;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900142}
Koji Sato17c76b02009-04-06 19:01:24 -0700143
144static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900145nilfs_btree_node_get_flags(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700146{
147 return node->bn_flags;
148}
149
150static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900151nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags)
Koji Sato17c76b02009-04-06 19:01:24 -0700152{
153 node->bn_flags = flags;
154}
155
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900156static inline int nilfs_btree_node_root(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700157{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900158 return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT;
Koji Sato17c76b02009-04-06 19:01:24 -0700159}
160
161static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900162nilfs_btree_node_get_level(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700163{
164 return node->bn_level;
165}
166
167static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900168nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700169{
170 node->bn_level = level;
171}
172
173static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900174nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700175{
176 return le16_to_cpu(node->bn_nchildren);
177}
178
179static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900180nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren)
Koji Sato17c76b02009-04-06 19:01:24 -0700181{
182 node->bn_nchildren = cpu_to_le16(nchildren);
183}
184
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900185static inline int nilfs_btree_node_size(const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700186{
187 return 1 << btree->bt_bmap.b_inode->i_blkbits;
188}
189
190static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900191nilfs_btree_node_nchildren_min(const struct nilfs_btree_node *node,
192 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700193{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900194 return nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700195 NILFS_BTREE_ROOT_NCHILDREN_MIN :
196 NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree));
197}
198
199static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900200nilfs_btree_node_nchildren_max(const struct nilfs_btree_node *node,
201 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700202{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900203 return nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700204 NILFS_BTREE_ROOT_NCHILDREN_MAX :
205 NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree));
206}
207
208static inline __le64 *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900209nilfs_btree_node_dkeys(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700210{
211 return (__le64 *)((char *)(node + 1) +
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900212 (nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700213 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE));
214}
215
216static inline __le64 *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900217nilfs_btree_node_dptrs(const struct nilfs_btree_node *node,
218 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700219{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900220 return (__le64 *)(nilfs_btree_node_dkeys(node) +
221 nilfs_btree_node_nchildren_max(node, btree));
Koji Sato17c76b02009-04-06 19:01:24 -0700222}
223
224static inline __u64
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900225nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index)
Koji Sato17c76b02009-04-06 19:01:24 -0700226{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900227 return nilfs_bmap_dkey_to_key(*(nilfs_btree_node_dkeys(node) + index));
Koji Sato17c76b02009-04-06 19:01:24 -0700228}
229
230static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900231nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key)
Koji Sato17c76b02009-04-06 19:01:24 -0700232{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900233 *(nilfs_btree_node_dkeys(node) + index) = nilfs_bmap_key_to_dkey(key);
Koji Sato17c76b02009-04-06 19:01:24 -0700234}
235
236static inline __u64
237nilfs_btree_node_get_ptr(const struct nilfs_btree *btree,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900238 const struct nilfs_btree_node *node, int index)
Koji Sato17c76b02009-04-06 19:01:24 -0700239{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900240 return nilfs_bmap_dptr_to_ptr(*(nilfs_btree_node_dptrs(node, btree) +
Koji Sato17c76b02009-04-06 19:01:24 -0700241 index));
242}
243
244static inline void
245nilfs_btree_node_set_ptr(struct nilfs_btree *btree,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900246 struct nilfs_btree_node *node, int index, __u64 ptr)
Koji Sato17c76b02009-04-06 19:01:24 -0700247{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900248 *(nilfs_btree_node_dptrs(node, btree) + index) =
Koji Sato17c76b02009-04-06 19:01:24 -0700249 nilfs_bmap_ptr_to_dptr(ptr);
250}
251
252static void nilfs_btree_node_init(struct nilfs_btree *btree,
253 struct nilfs_btree_node *node,
254 int flags, int level, int nchildren,
255 const __u64 *keys, const __u64 *ptrs)
256{
257 __le64 *dkeys;
258 __le64 *dptrs;
259 int i;
260
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900261 nilfs_btree_node_set_flags(node, flags);
262 nilfs_btree_node_set_level(node, level);
263 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700264
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900265 dkeys = nilfs_btree_node_dkeys(node);
266 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700267 for (i = 0; i < nchildren; i++) {
268 dkeys[i] = nilfs_bmap_key_to_dkey(keys[i]);
269 dptrs[i] = nilfs_bmap_ptr_to_dptr(ptrs[i]);
270 }
271}
272
273/* Assume the buffer heads corresponding to left and right are locked. */
274static void nilfs_btree_node_move_left(struct nilfs_btree *btree,
275 struct nilfs_btree_node *left,
276 struct nilfs_btree_node *right,
277 int n)
278{
279 __le64 *ldkeys, *rdkeys;
280 __le64 *ldptrs, *rdptrs;
281 int lnchildren, rnchildren;
282
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900283 ldkeys = nilfs_btree_node_dkeys(left);
284 ldptrs = nilfs_btree_node_dptrs(left, btree);
285 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700286
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900287 rdkeys = nilfs_btree_node_dkeys(right);
288 rdptrs = nilfs_btree_node_dptrs(right, btree);
289 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700290
291 memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys));
292 memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs));
293 memmove(rdkeys, rdkeys + n, (rnchildren - n) * sizeof(*rdkeys));
294 memmove(rdptrs, rdptrs + n, (rnchildren - n) * sizeof(*rdptrs));
295
296 lnchildren += n;
297 rnchildren -= n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900298 nilfs_btree_node_set_nchildren(left, lnchildren);
299 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700300}
301
302/* Assume that the buffer heads corresponding to left and right are locked. */
303static void nilfs_btree_node_move_right(struct nilfs_btree *btree,
304 struct nilfs_btree_node *left,
305 struct nilfs_btree_node *right,
306 int n)
307{
308 __le64 *ldkeys, *rdkeys;
309 __le64 *ldptrs, *rdptrs;
310 int lnchildren, rnchildren;
311
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900312 ldkeys = nilfs_btree_node_dkeys(left);
313 ldptrs = nilfs_btree_node_dptrs(left, btree);
314 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700315
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900316 rdkeys = nilfs_btree_node_dkeys(right);
317 rdptrs = nilfs_btree_node_dptrs(right, btree);
318 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700319
320 memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys));
321 memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs));
322 memcpy(rdkeys, ldkeys + lnchildren - n, n * sizeof(*rdkeys));
323 memcpy(rdptrs, ldptrs + lnchildren - n, n * sizeof(*rdptrs));
324
325 lnchildren -= n;
326 rnchildren += n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900327 nilfs_btree_node_set_nchildren(left, lnchildren);
328 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700329}
330
331/* Assume that the buffer head corresponding to node is locked. */
332static void nilfs_btree_node_insert(struct nilfs_btree *btree,
333 struct nilfs_btree_node *node,
334 __u64 key, __u64 ptr, int index)
335{
336 __le64 *dkeys;
337 __le64 *dptrs;
338 int nchildren;
339
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900340 dkeys = nilfs_btree_node_dkeys(node);
341 dptrs = nilfs_btree_node_dptrs(node, btree);
342 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700343 if (index < nchildren) {
344 memmove(dkeys + index + 1, dkeys + index,
345 (nchildren - index) * sizeof(*dkeys));
346 memmove(dptrs + index + 1, dptrs + index,
347 (nchildren - index) * sizeof(*dptrs));
348 }
349 dkeys[index] = nilfs_bmap_key_to_dkey(key);
350 dptrs[index] = nilfs_bmap_ptr_to_dptr(ptr);
351 nchildren++;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900352 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700353}
354
355/* Assume that the buffer head corresponding to node is locked. */
356static void nilfs_btree_node_delete(struct nilfs_btree *btree,
357 struct nilfs_btree_node *node,
358 __u64 *keyp, __u64 *ptrp, int index)
359{
360 __u64 key;
361 __u64 ptr;
362 __le64 *dkeys;
363 __le64 *dptrs;
364 int nchildren;
365
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900366 dkeys = nilfs_btree_node_dkeys(node);
367 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700368 key = nilfs_bmap_dkey_to_key(dkeys[index]);
369 ptr = nilfs_bmap_dptr_to_ptr(dptrs[index]);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900370 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700371 if (keyp != NULL)
372 *keyp = key;
373 if (ptrp != NULL)
374 *ptrp = ptr;
375
376 if (index < nchildren - 1) {
377 memmove(dkeys + index, dkeys + index + 1,
378 (nchildren - index - 1) * sizeof(*dkeys));
379 memmove(dptrs + index, dptrs + index + 1,
380 (nchildren - index - 1) * sizeof(*dptrs));
381 }
382 nchildren--;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900383 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700384}
385
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900386static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node,
Koji Sato17c76b02009-04-06 19:01:24 -0700387 __u64 key, int *indexp)
388{
389 __u64 nkey;
390 int index, low, high, s;
391
392 /* binary search */
393 low = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900394 high = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700395 index = 0;
396 s = 0;
397 while (low <= high) {
398 index = (low + high) / 2;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900399 nkey = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700400 if (nkey == key) {
401 s = 0;
402 goto out;
403 } else if (nkey < key) {
404 low = index + 1;
405 s = -1;
406 } else {
407 high = index - 1;
408 s = 1;
409 }
410 }
411
412 /* adjust index */
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900413 if (nilfs_btree_node_get_level(node) > NILFS_BTREE_LEVEL_NODE_MIN) {
414 if (s > 0 && index > 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700415 index--;
416 } else if (s < 0)
417 index++;
418
419 out:
Koji Sato17c76b02009-04-06 19:01:24 -0700420 *indexp = index;
421
422 return s == 0;
423}
424
425static inline struct nilfs_btree_node *
426nilfs_btree_get_root(const struct nilfs_btree *btree)
427{
428 return (struct nilfs_btree_node *)btree->bt_bmap.b_u.u_data;
429}
430
431static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900432nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700433{
434 return (struct nilfs_btree_node *)path[level].bp_bh->b_data;
435}
436
437static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900438nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700439{
440 return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data;
441}
442
443static inline int nilfs_btree_height(const struct nilfs_btree *btree)
444{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900445 return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700446}
447
448static inline struct nilfs_btree_node *
449nilfs_btree_get_node(const struct nilfs_btree *btree,
450 const struct nilfs_btree_path *path,
451 int level)
452{
453 return (level == nilfs_btree_height(btree) - 1) ?
454 nilfs_btree_get_root(btree) :
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900455 nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700456}
457
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900458static inline int
459nilfs_btree_bad_node(struct nilfs_btree_node *node, int level)
460{
461 if (unlikely(nilfs_btree_node_get_level(node) != level)) {
462 dump_stack();
463 printk(KERN_CRIT "NILFS: btree level mismatch: %d != %d\n",
464 nilfs_btree_node_get_level(node), level);
465 return 1;
466 }
467 return 0;
468}
469
Koji Sato17c76b02009-04-06 19:01:24 -0700470static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
471 struct nilfs_btree_path *path,
472 __u64 key, __u64 *ptrp, int minlevel)
473{
474 struct nilfs_btree_node *node;
475 __u64 ptr;
476 int level, index, found, ret;
477
Koji Sato17c76b02009-04-06 19:01:24 -0700478 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900479 level = nilfs_btree_node_get_level(node);
480 if (level < minlevel || nilfs_btree_node_get_nchildren(node) <= 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700481 return -ENOENT;
482
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900483 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700484 ptr = nilfs_btree_node_get_ptr(btree, node, index);
485 path[level].bp_bh = NULL;
486 path[level].bp_index = index;
487
488 for (level--; level >= minlevel; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900489 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700490 if (ret < 0)
491 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900492 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900493 if (nilfs_btree_bad_node(node, level))
494 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -0700495 if (!found)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900496 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700497 else
498 index = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900499 if (index < nilfs_btree_node_nchildren_max(node, btree))
Koji Sato17c76b02009-04-06 19:01:24 -0700500 ptr = nilfs_btree_node_get_ptr(btree, node, index);
501 else {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700502 WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN);
Koji Sato17c76b02009-04-06 19:01:24 -0700503 /* insert */
504 ptr = NILFS_BMAP_INVALID_PTR;
505 }
506 path[level].bp_index = index;
507 }
508 if (!found)
509 return -ENOENT;
510
511 if (ptrp != NULL)
512 *ptrp = ptr;
513
514 return 0;
515}
516
517static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree,
518 struct nilfs_btree_path *path,
519 __u64 *keyp, __u64 *ptrp)
520{
521 struct nilfs_btree_node *node;
522 __u64 ptr;
523 int index, level, ret;
524
525 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900526 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700527 if (index < 0)
528 return -ENOENT;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900529 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700530 ptr = nilfs_btree_node_get_ptr(btree, node, index);
531 path[level].bp_bh = NULL;
532 path[level].bp_index = index;
533
534 for (level--; level > 0; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900535 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700536 if (ret < 0)
537 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900538 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900539 if (nilfs_btree_bad_node(node, level))
540 return -EINVAL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900541 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700542 ptr = nilfs_btree_node_get_ptr(btree, node, index);
543 path[level].bp_index = index;
544 }
545
546 if (keyp != NULL)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900547 *keyp = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700548 if (ptrp != NULL)
549 *ptrp = ptr;
550
551 return 0;
552}
553
554static int nilfs_btree_lookup(const struct nilfs_bmap *bmap,
555 __u64 key, int level, __u64 *ptrp)
556{
557 struct nilfs_btree *btree;
558 struct nilfs_btree_path *path;
559 __u64 ptr;
560 int ret;
561
562 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900563 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -0700564 if (path == NULL)
565 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -0700566
567 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
568
569 if (ptrp != NULL)
570 *ptrp = ptr;
571
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900572 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -0700573
574 return ret;
575}
576
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900577static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
578 __u64 key, __u64 *ptrp, unsigned maxblocks)
579{
580 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
581 struct nilfs_btree_path *path;
582 struct nilfs_btree_node *node;
583 struct inode *dat = NULL;
584 __u64 ptr, ptr2;
585 sector_t blocknr;
586 int level = NILFS_BTREE_LEVEL_NODE_MIN;
587 int ret, cnt, index, maxlevel;
588
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900589 path = nilfs_btree_alloc_path();
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900590 if (path == NULL)
591 return -ENOMEM;
Li Hongf9054402010-04-02 17:36:34 +0800592
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900593 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
594 if (ret < 0)
595 goto out;
596
597 if (NILFS_BMAP_USE_VBN(bmap)) {
598 dat = nilfs_bmap_get_dat(bmap);
599 ret = nilfs_dat_translate(dat, ptr, &blocknr);
600 if (ret < 0)
601 goto out;
602 ptr = blocknr;
603 }
604 cnt = 1;
605 if (cnt == maxblocks)
606 goto end;
607
608 maxlevel = nilfs_btree_height(btree) - 1;
609 node = nilfs_btree_get_node(btree, path, level);
610 index = path[level].bp_index + 1;
611 for (;;) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900612 while (index < nilfs_btree_node_get_nchildren(node)) {
613 if (nilfs_btree_node_get_key(node, index) !=
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900614 key + cnt)
615 goto end;
616 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
617 if (dat) {
618 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
619 if (ret < 0)
620 goto out;
621 ptr2 = blocknr;
622 }
623 if (ptr2 != ptr + cnt || ++cnt == maxblocks)
624 goto end;
625 index++;
626 continue;
627 }
628 if (level == maxlevel)
629 break;
630
631 /* look-up right sibling node */
632 node = nilfs_btree_get_node(btree, path, level + 1);
633 index = path[level + 1].bp_index + 1;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900634 if (index >= nilfs_btree_node_get_nchildren(node) ||
635 nilfs_btree_node_get_key(node, index) != key + cnt)
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900636 break;
637 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
638 path[level + 1].bp_index = index;
639
640 brelse(path[level].bp_bh);
641 path[level].bp_bh = NULL;
642 ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh);
643 if (ret < 0)
644 goto out;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900645 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900646 index = 0;
647 path[level].bp_index = index;
648 }
649 end:
650 *ptrp = ptr;
651 ret = cnt;
652 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900653 nilfs_btree_free_path(path);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900654 return ret;
655}
656
Koji Sato17c76b02009-04-06 19:01:24 -0700657static void nilfs_btree_promote_key(struct nilfs_btree *btree,
658 struct nilfs_btree_path *path,
659 int level, __u64 key)
660{
661 if (level < nilfs_btree_height(btree) - 1) {
662 do {
Koji Sato17c76b02009-04-06 19:01:24 -0700663 nilfs_btree_node_set_key(
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900664 nilfs_btree_get_nonroot_node(path, level),
Koji Sato17c76b02009-04-06 19:01:24 -0700665 path[level].bp_index, key);
666 if (!buffer_dirty(path[level].bp_bh))
667 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700668 } while ((path[level].bp_index == 0) &&
669 (++level < nilfs_btree_height(btree) - 1));
670 }
671
672 /* root */
673 if (level == nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900674 nilfs_btree_node_set_key(nilfs_btree_get_root(btree),
Koji Sato17c76b02009-04-06 19:01:24 -0700675 path[level].bp_index, key);
676 }
677}
678
679static void nilfs_btree_do_insert(struct nilfs_btree *btree,
680 struct nilfs_btree_path *path,
681 int level, __u64 *keyp, __u64 *ptrp)
682{
683 struct nilfs_btree_node *node;
684
685 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900686 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700687 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
688 path[level].bp_index);
689 if (!buffer_dirty(path[level].bp_bh))
690 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700691
692 if (path[level].bp_index == 0)
693 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900694 nilfs_btree_node_get_key(node,
695 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700696 } else {
697 node = nilfs_btree_get_root(btree);
698 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
699 path[level].bp_index);
700 }
701}
702
703static void nilfs_btree_carry_left(struct nilfs_btree *btree,
704 struct nilfs_btree_path *path,
705 int level, __u64 *keyp, __u64 *ptrp)
706{
707 struct nilfs_btree_node *node, *left;
708 int nchildren, lnchildren, n, move;
709
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900710 node = nilfs_btree_get_nonroot_node(path, level);
711 left = nilfs_btree_get_sib_node(path, level);
712 nchildren = nilfs_btree_node_get_nchildren(node);
713 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700714 move = 0;
715
716 n = (nchildren + lnchildren + 1) / 2 - lnchildren;
717 if (n > path[level].bp_index) {
718 /* move insert point */
719 n--;
720 move = 1;
721 }
722
723 nilfs_btree_node_move_left(btree, left, node, n);
724
725 if (!buffer_dirty(path[level].bp_bh))
726 nilfs_btnode_mark_dirty(path[level].bp_bh);
727 if (!buffer_dirty(path[level].bp_sib_bh))
728 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
729
Koji Sato17c76b02009-04-06 19:01:24 -0700730 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900731 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700732
733 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900734 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700735 path[level].bp_bh = path[level].bp_sib_bh;
736 path[level].bp_sib_bh = NULL;
737 path[level].bp_index += lnchildren;
738 path[level + 1].bp_index--;
739 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900740 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700741 path[level].bp_sib_bh = NULL;
742 path[level].bp_index -= n;
743 }
744
745 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
746}
747
748static void nilfs_btree_carry_right(struct nilfs_btree *btree,
749 struct nilfs_btree_path *path,
750 int level, __u64 *keyp, __u64 *ptrp)
751{
752 struct nilfs_btree_node *node, *right;
753 int nchildren, rnchildren, n, move;
754
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900755 node = nilfs_btree_get_nonroot_node(path, level);
756 right = nilfs_btree_get_sib_node(path, level);
757 nchildren = nilfs_btree_node_get_nchildren(node);
758 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700759 move = 0;
760
761 n = (nchildren + rnchildren + 1) / 2 - rnchildren;
762 if (n > nchildren - path[level].bp_index) {
763 /* move insert point */
764 n--;
765 move = 1;
766 }
767
768 nilfs_btree_node_move_right(btree, node, right, n);
769
770 if (!buffer_dirty(path[level].bp_bh))
771 nilfs_btnode_mark_dirty(path[level].bp_bh);
772 if (!buffer_dirty(path[level].bp_sib_bh))
773 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
774
Koji Sato17c76b02009-04-06 19:01:24 -0700775 path[level + 1].bp_index++;
776 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900777 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700778 path[level + 1].bp_index--;
779
780 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900781 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700782 path[level].bp_bh = path[level].bp_sib_bh;
783 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900784 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700785 path[level + 1].bp_index++;
786 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900787 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700788 path[level].bp_sib_bh = NULL;
789 }
790
791 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
792}
793
794static void nilfs_btree_split(struct nilfs_btree *btree,
795 struct nilfs_btree_path *path,
796 int level, __u64 *keyp, __u64 *ptrp)
797{
798 struct nilfs_btree_node *node, *right;
799 __u64 newkey;
800 __u64 newptr;
801 int nchildren, n, move;
802
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900803 node = nilfs_btree_get_nonroot_node(path, level);
804 right = nilfs_btree_get_sib_node(path, level);
805 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700806 move = 0;
807
808 n = (nchildren + 1) / 2;
809 if (n > nchildren - path[level].bp_index) {
810 n--;
811 move = 1;
812 }
813
814 nilfs_btree_node_move_right(btree, node, right, n);
815
816 if (!buffer_dirty(path[level].bp_bh))
817 nilfs_btnode_mark_dirty(path[level].bp_bh);
818 if (!buffer_dirty(path[level].bp_sib_bh))
819 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
820
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900821 newkey = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700822 newptr = path[level].bp_newreq.bpr_ptr;
823
824 if (move) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900825 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700826 nilfs_btree_node_insert(btree, right, *keyp, *ptrp,
827 path[level].bp_index);
828
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900829 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700830 *ptrp = path[level].bp_newreq.bpr_ptr;
831
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900832 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700833 path[level].bp_bh = path[level].bp_sib_bh;
834 path[level].bp_sib_bh = NULL;
835 } else {
836 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
837
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900838 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700839 *ptrp = path[level].bp_newreq.bpr_ptr;
840
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900841 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700842 path[level].bp_sib_bh = NULL;
843 }
844
845 path[level + 1].bp_index++;
846}
847
848static void nilfs_btree_grow(struct nilfs_btree *btree,
849 struct nilfs_btree_path *path,
850 int level, __u64 *keyp, __u64 *ptrp)
851{
852 struct nilfs_btree_node *root, *child;
853 int n;
854
Koji Sato17c76b02009-04-06 19:01:24 -0700855 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900856 child = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700857
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900858 n = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -0700859
860 nilfs_btree_node_move_right(btree, root, child, n);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900861 nilfs_btree_node_set_level(root, level + 1);
Koji Sato17c76b02009-04-06 19:01:24 -0700862
863 if (!buffer_dirty(path[level].bp_sib_bh))
864 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
865
Koji Sato17c76b02009-04-06 19:01:24 -0700866 path[level].bp_bh = path[level].bp_sib_bh;
867 path[level].bp_sib_bh = NULL;
868
869 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
870
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900871 *keyp = nilfs_btree_node_get_key(child, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700872 *ptrp = path[level].bp_newreq.bpr_ptr;
873}
874
875static __u64 nilfs_btree_find_near(const struct nilfs_btree *btree,
876 const struct nilfs_btree_path *path)
877{
878 struct nilfs_btree_node *node;
879 int level;
880
881 if (path == NULL)
882 return NILFS_BMAP_INVALID_PTR;
883
884 /* left sibling */
885 level = NILFS_BTREE_LEVEL_NODE_MIN;
886 if (path[level].bp_index > 0) {
887 node = nilfs_btree_get_node(btree, path, level);
888 return nilfs_btree_node_get_ptr(btree, node,
889 path[level].bp_index - 1);
890 }
891
892 /* parent */
893 level = NILFS_BTREE_LEVEL_NODE_MIN + 1;
894 if (level <= nilfs_btree_height(btree) - 1) {
895 node = nilfs_btree_get_node(btree, path, level);
896 return nilfs_btree_node_get_ptr(btree, node,
897 path[level].bp_index);
898 }
899
900 return NILFS_BMAP_INVALID_PTR;
901}
902
903static __u64 nilfs_btree_find_target_v(const struct nilfs_btree *btree,
904 const struct nilfs_btree_path *path,
905 __u64 key)
906{
907 __u64 ptr;
908
909 ptr = nilfs_bmap_find_target_seq(&btree->bt_bmap, key);
910 if (ptr != NILFS_BMAP_INVALID_PTR)
911 /* sequential access */
912 return ptr;
913 else {
914 ptr = nilfs_btree_find_near(btree, path);
915 if (ptr != NILFS_BMAP_INVALID_PTR)
916 /* near */
917 return ptr;
918 }
919 /* block group */
920 return nilfs_bmap_find_target_in_group(&btree->bt_bmap);
921}
922
923static void nilfs_btree_set_target_v(struct nilfs_btree *btree, __u64 key,
924 __u64 ptr)
925{
926 btree->bt_bmap.b_last_allocated_key = key;
927 btree->bt_bmap.b_last_allocated_ptr = ptr;
928}
929
930static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
931 struct nilfs_btree_path *path,
932 int *levelp, __u64 key, __u64 ptr,
933 struct nilfs_bmap_stats *stats)
934{
935 struct buffer_head *bh;
936 struct nilfs_btree_node *node, *parent, *sib;
937 __u64 sibptr;
938 int pindex, level, ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900939 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -0700940
941 stats->bs_nblocks = 0;
942 level = NILFS_BTREE_LEVEL_DATA;
943
944 /* allocate a new ptr for data block */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900945 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700946 path[level].bp_newreq.bpr_ptr =
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +0900947 nilfs_btree_find_target_v(btree, path, key);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900948 dat = nilfs_bmap_get_dat(&btree->bt_bmap);
949 }
Koji Sato17c76b02009-04-06 19:01:24 -0700950
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900951 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900952 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -0700953 if (ret < 0)
954 goto err_out_data;
955
956 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
957 level < nilfs_btree_height(btree) - 1;
958 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900959 node = nilfs_btree_get_nonroot_node(path, level);
960 if (nilfs_btree_node_get_nchildren(node) <
961 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700962 path[level].bp_op = nilfs_btree_do_insert;
963 stats->bs_nblocks++;
964 goto out;
965 }
966
967 parent = nilfs_btree_get_node(btree, path, level + 1);
968 pindex = path[level + 1].bp_index;
969
970 /* left sibling */
971 if (pindex > 0) {
972 sibptr = nilfs_btree_node_get_ptr(btree, parent,
973 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900974 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700975 if (ret < 0)
976 goto err_out_child_node;
977 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900978 if (nilfs_btree_node_get_nchildren(sib) <
979 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700980 path[level].bp_sib_bh = bh;
981 path[level].bp_op = nilfs_btree_carry_left;
982 stats->bs_nblocks++;
983 goto out;
984 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900985 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700986 }
987
988 /* right sibling */
989 if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900990 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -0700991 sibptr = nilfs_btree_node_get_ptr(btree, parent,
992 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900993 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700994 if (ret < 0)
995 goto err_out_child_node;
996 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900997 if (nilfs_btree_node_get_nchildren(sib) <
998 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700999 path[level].bp_sib_bh = bh;
1000 path[level].bp_op = nilfs_btree_carry_right;
1001 stats->bs_nblocks++;
1002 goto out;
1003 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001004 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001005 }
1006
1007 /* split */
1008 path[level].bp_newreq.bpr_ptr =
1009 path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001010 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001011 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001012 if (ret < 0)
1013 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001014 ret = nilfs_btree_get_new_block(btree,
1015 path[level].bp_newreq.bpr_ptr,
1016 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001017 if (ret < 0)
1018 goto err_out_curr_node;
1019
1020 stats->bs_nblocks++;
1021
Koji Sato17c76b02009-04-06 19:01:24 -07001022 nilfs_btree_node_init(btree,
1023 (struct nilfs_btree_node *)bh->b_data,
1024 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001025 path[level].bp_sib_bh = bh;
1026 path[level].bp_op = nilfs_btree_split;
1027 }
1028
1029 /* root */
1030 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001031 if (nilfs_btree_node_get_nchildren(node) <
1032 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001033 path[level].bp_op = nilfs_btree_do_insert;
1034 stats->bs_nblocks++;
1035 goto out;
1036 }
1037
1038 /* grow */
1039 path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001040 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001041 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001042 if (ret < 0)
1043 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001044 ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
1045 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001046 if (ret < 0)
1047 goto err_out_curr_node;
1048
Koji Sato17c76b02009-04-06 19:01:24 -07001049 nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data,
1050 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001051 path[level].bp_sib_bh = bh;
1052 path[level].bp_op = nilfs_btree_grow;
1053
1054 level++;
1055 path[level].bp_op = nilfs_btree_do_insert;
1056
1057 /* a newly-created node block and a data block are added */
1058 stats->bs_nblocks += 2;
1059
1060 /* success */
1061 out:
1062 *levelp = level;
1063 return ret;
1064
1065 /* error */
1066 err_out_curr_node:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001067 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
1068 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001069 err_out_child_node:
1070 for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001071 nilfs_btnode_delete(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001072 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001073 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001074
1075 }
1076
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001077 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
1078 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001079 err_out_data:
1080 *levelp = level;
1081 stats->bs_nblocks = 0;
1082 return ret;
1083}
1084
1085static void nilfs_btree_commit_insert(struct nilfs_btree *btree,
1086 struct nilfs_btree_path *path,
1087 int maxlevel, __u64 key, __u64 ptr)
1088{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001089 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001090 int level;
1091
1092 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1093 ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001094 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001095 nilfs_btree_set_target_v(btree, key, ptr);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001096 dat = nilfs_bmap_get_dat(&btree->bt_bmap);
1097 }
Koji Sato17c76b02009-04-06 19:01:24 -07001098
1099 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001100 nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001101 &path[level - 1].bp_newreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001102 path[level].bp_op(btree, path, level, &key, &ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001103 }
1104
1105 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1106 nilfs_bmap_set_dirty(&btree->bt_bmap);
1107}
1108
1109static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
1110{
1111 struct nilfs_btree *btree;
1112 struct nilfs_btree_path *path;
1113 struct nilfs_bmap_stats stats;
1114 int level, ret;
1115
1116 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001117 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001118 if (path == NULL)
1119 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001120
1121 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1122 NILFS_BTREE_LEVEL_NODE_MIN);
1123 if (ret != -ENOENT) {
1124 if (ret == 0)
1125 ret = -EEXIST;
1126 goto out;
1127 }
1128
1129 ret = nilfs_btree_prepare_insert(btree, path, &level, key, ptr, &stats);
1130 if (ret < 0)
1131 goto out;
1132 nilfs_btree_commit_insert(btree, path, level, key, ptr);
1133 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1134
1135 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001136 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001137 return ret;
1138}
1139
1140static void nilfs_btree_do_delete(struct nilfs_btree *btree,
1141 struct nilfs_btree_path *path,
1142 int level, __u64 *keyp, __u64 *ptrp)
1143{
1144 struct nilfs_btree_node *node;
1145
1146 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001147 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001148 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1149 path[level].bp_index);
1150 if (!buffer_dirty(path[level].bp_bh))
1151 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001152 if (path[level].bp_index == 0)
1153 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001154 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001155 } else {
1156 node = nilfs_btree_get_root(btree);
1157 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1158 path[level].bp_index);
1159 }
1160}
1161
1162static void nilfs_btree_borrow_left(struct nilfs_btree *btree,
1163 struct nilfs_btree_path *path,
1164 int level, __u64 *keyp, __u64 *ptrp)
1165{
1166 struct nilfs_btree_node *node, *left;
1167 int nchildren, lnchildren, n;
1168
1169 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1170
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001171 node = nilfs_btree_get_nonroot_node(path, level);
1172 left = nilfs_btree_get_sib_node(path, level);
1173 nchildren = nilfs_btree_node_get_nchildren(node);
1174 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001175
1176 n = (nchildren + lnchildren) / 2 - nchildren;
1177
1178 nilfs_btree_node_move_right(btree, left, node, n);
1179
1180 if (!buffer_dirty(path[level].bp_bh))
1181 nilfs_btnode_mark_dirty(path[level].bp_bh);
1182 if (!buffer_dirty(path[level].bp_sib_bh))
1183 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1184
Koji Sato17c76b02009-04-06 19:01:24 -07001185 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001186 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001187
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001188 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001189 path[level].bp_sib_bh = NULL;
1190 path[level].bp_index += n;
1191}
1192
1193static void nilfs_btree_borrow_right(struct nilfs_btree *btree,
1194 struct nilfs_btree_path *path,
1195 int level, __u64 *keyp, __u64 *ptrp)
1196{
1197 struct nilfs_btree_node *node, *right;
1198 int nchildren, rnchildren, n;
1199
1200 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1201
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001202 node = nilfs_btree_get_nonroot_node(path, level);
1203 right = nilfs_btree_get_sib_node(path, level);
1204 nchildren = nilfs_btree_node_get_nchildren(node);
1205 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001206
1207 n = (nchildren + rnchildren) / 2 - nchildren;
1208
1209 nilfs_btree_node_move_left(btree, node, right, n);
1210
1211 if (!buffer_dirty(path[level].bp_bh))
1212 nilfs_btnode_mark_dirty(path[level].bp_bh);
1213 if (!buffer_dirty(path[level].bp_sib_bh))
1214 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1215
Koji Sato17c76b02009-04-06 19:01:24 -07001216 path[level + 1].bp_index++;
1217 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001218 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001219 path[level + 1].bp_index--;
1220
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001221 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001222 path[level].bp_sib_bh = NULL;
1223}
1224
1225static void nilfs_btree_concat_left(struct nilfs_btree *btree,
1226 struct nilfs_btree_path *path,
1227 int level, __u64 *keyp, __u64 *ptrp)
1228{
1229 struct nilfs_btree_node *node, *left;
1230 int n;
1231
1232 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1233
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001234 node = nilfs_btree_get_nonroot_node(path, level);
1235 left = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001236
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001237 n = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001238
1239 nilfs_btree_node_move_left(btree, left, node, n);
1240
1241 if (!buffer_dirty(path[level].bp_sib_bh))
1242 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1243
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001244 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001245 path[level].bp_bh = path[level].bp_sib_bh;
1246 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001247 path[level].bp_index += nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001248}
1249
1250static void nilfs_btree_concat_right(struct nilfs_btree *btree,
1251 struct nilfs_btree_path *path,
1252 int level, __u64 *keyp, __u64 *ptrp)
1253{
1254 struct nilfs_btree_node *node, *right;
1255 int n;
1256
1257 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1258
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001259 node = nilfs_btree_get_nonroot_node(path, level);
1260 right = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001261
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001262 n = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001263
1264 nilfs_btree_node_move_left(btree, node, right, n);
1265
1266 if (!buffer_dirty(path[level].bp_bh))
1267 nilfs_btnode_mark_dirty(path[level].bp_bh);
1268
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001269 nilfs_btnode_delete(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001270 path[level].bp_sib_bh = NULL;
1271 path[level + 1].bp_index++;
1272}
1273
1274static void nilfs_btree_shrink(struct nilfs_btree *btree,
1275 struct nilfs_btree_path *path,
1276 int level, __u64 *keyp, __u64 *ptrp)
1277{
1278 struct nilfs_btree_node *root, *child;
1279 int n;
1280
1281 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1282
Koji Sato17c76b02009-04-06 19:01:24 -07001283 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001284 child = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001285
1286 nilfs_btree_node_delete(btree, root, NULL, NULL, 0);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001287 nilfs_btree_node_set_level(root, level);
1288 n = nilfs_btree_node_get_nchildren(child);
Koji Sato17c76b02009-04-06 19:01:24 -07001289 nilfs_btree_node_move_left(btree, root, child, n);
Koji Sato17c76b02009-04-06 19:01:24 -07001290
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001291 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001292 path[level].bp_bh = NULL;
1293}
1294
1295
1296static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
1297 struct nilfs_btree_path *path,
1298 int *levelp,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001299 struct nilfs_bmap_stats *stats,
1300 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001301{
1302 struct buffer_head *bh;
1303 struct nilfs_btree_node *node, *parent, *sib;
1304 __u64 sibptr;
1305 int pindex, level, ret;
1306
1307 ret = 0;
1308 stats->bs_nblocks = 0;
1309 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1310 level < nilfs_btree_height(btree) - 1;
1311 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001312 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001313 path[level].bp_oldreq.bpr_ptr =
1314 nilfs_btree_node_get_ptr(btree, node,
1315 path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001316 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001317 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001318 if (ret < 0)
1319 goto err_out_child_node;
Koji Sato17c76b02009-04-06 19:01:24 -07001320
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001321 if (nilfs_btree_node_get_nchildren(node) >
1322 nilfs_btree_node_nchildren_min(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001323 path[level].bp_op = nilfs_btree_do_delete;
1324 stats->bs_nblocks++;
1325 goto out;
1326 }
1327
1328 parent = nilfs_btree_get_node(btree, path, level + 1);
1329 pindex = path[level + 1].bp_index;
1330
1331 if (pindex > 0) {
1332 /* left sibling */
1333 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1334 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001335 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001336 if (ret < 0)
1337 goto err_out_curr_node;
1338 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001339 if (nilfs_btree_node_get_nchildren(sib) >
1340 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001341 path[level].bp_sib_bh = bh;
1342 path[level].bp_op = nilfs_btree_borrow_left;
1343 stats->bs_nblocks++;
1344 goto out;
1345 } else {
1346 path[level].bp_sib_bh = bh;
1347 path[level].bp_op = nilfs_btree_concat_left;
1348 stats->bs_nblocks++;
1349 /* continue; */
1350 }
1351 } else if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001352 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -07001353 /* right sibling */
1354 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1355 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001356 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001357 if (ret < 0)
1358 goto err_out_curr_node;
1359 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001360 if (nilfs_btree_node_get_nchildren(sib) >
1361 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001362 path[level].bp_sib_bh = bh;
1363 path[level].bp_op = nilfs_btree_borrow_right;
1364 stats->bs_nblocks++;
1365 goto out;
1366 } else {
1367 path[level].bp_sib_bh = bh;
1368 path[level].bp_op = nilfs_btree_concat_right;
1369 stats->bs_nblocks++;
1370 /* continue; */
1371 }
1372 } else {
1373 /* no siblings */
1374 /* the only child of the root node */
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001375 WARN_ON(level != nilfs_btree_height(btree) - 2);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001376 if (nilfs_btree_node_get_nchildren(node) - 1 <=
Koji Sato17c76b02009-04-06 19:01:24 -07001377 NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1378 path[level].bp_op = nilfs_btree_shrink;
1379 stats->bs_nblocks += 2;
1380 } else {
1381 path[level].bp_op = nilfs_btree_do_delete;
1382 stats->bs_nblocks++;
1383 }
1384
1385 goto out;
1386
1387 }
1388 }
1389
1390 node = nilfs_btree_get_root(btree);
1391 path[level].bp_oldreq.bpr_ptr =
1392 nilfs_btree_node_get_ptr(btree, node, path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001393
1394 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001395 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001396 if (ret < 0)
1397 goto err_out_child_node;
1398
Koji Sato17c76b02009-04-06 19:01:24 -07001399 /* child of the root node is deleted */
1400 path[level].bp_op = nilfs_btree_do_delete;
1401 stats->bs_nblocks++;
1402
1403 /* success */
1404 out:
1405 *levelp = level;
1406 return ret;
1407
1408 /* error */
1409 err_out_curr_node:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001410 nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001411 err_out_child_node:
1412 for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001413 brelse(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001414 nilfs_bmap_abort_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001415 &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001416 }
1417 *levelp = level;
1418 stats->bs_nblocks = 0;
1419 return ret;
1420}
1421
1422static void nilfs_btree_commit_delete(struct nilfs_btree *btree,
1423 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001424 int maxlevel, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001425{
1426 int level;
1427
1428 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001429 nilfs_bmap_commit_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001430 &path[level].bp_oldreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001431 path[level].bp_op(btree, path, level, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001432 }
1433
1434 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1435 nilfs_bmap_set_dirty(&btree->bt_bmap);
1436}
1437
1438static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key)
1439
1440{
1441 struct nilfs_btree *btree;
1442 struct nilfs_btree_path *path;
1443 struct nilfs_bmap_stats stats;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001444 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001445 int level, ret;
1446
1447 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001448 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001449 if (path == NULL)
1450 return -ENOMEM;
Li Hongf9054402010-04-02 17:36:34 +08001451
Koji Sato17c76b02009-04-06 19:01:24 -07001452 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1453 NILFS_BTREE_LEVEL_NODE_MIN);
1454 if (ret < 0)
1455 goto out;
1456
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001457
1458 dat = NILFS_BMAP_USE_VBN(&btree->bt_bmap) ?
1459 nilfs_bmap_get_dat(&btree->bt_bmap) : NULL;
1460
1461 ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001462 if (ret < 0)
1463 goto out;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001464 nilfs_btree_commit_delete(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001465 nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks);
1466
1467out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001468 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001469 return ret;
1470}
1471
1472static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp)
1473{
1474 struct nilfs_btree *btree;
1475 struct nilfs_btree_path *path;
1476 int ret;
1477
1478 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001479 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001480 if (path == NULL)
1481 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001482
1483 ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL);
1484
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001485 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001486
1487 return ret;
1488}
1489
1490static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key)
1491{
1492 struct buffer_head *bh;
1493 struct nilfs_btree *btree;
1494 struct nilfs_btree_node *root, *node;
1495 __u64 maxkey, nextmaxkey;
1496 __u64 ptr;
1497 int nchildren, ret;
1498
1499 btree = (struct nilfs_btree *)bmap;
1500 root = nilfs_btree_get_root(btree);
1501 switch (nilfs_btree_height(btree)) {
1502 case 2:
1503 bh = NULL;
1504 node = root;
1505 break;
1506 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001507 nchildren = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -07001508 if (nchildren > 1)
1509 return 0;
1510 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001511 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001512 if (ret < 0)
1513 return ret;
1514 node = (struct nilfs_btree_node *)bh->b_data;
1515 break;
1516 default:
1517 return 0;
1518 }
1519
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001520 nchildren = nilfs_btree_node_get_nchildren(node);
1521 maxkey = nilfs_btree_node_get_key(node, nchildren - 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001522 nextmaxkey = (nchildren > 1) ?
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001523 nilfs_btree_node_get_key(node, nchildren - 2) : 0;
Koji Sato17c76b02009-04-06 19:01:24 -07001524 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001525 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001526
Ryusuke Konishi30333422009-05-24 00:09:44 +09001527 return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
Koji Sato17c76b02009-04-06 19:01:24 -07001528}
1529
1530static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
1531 __u64 *keys, __u64 *ptrs, int nitems)
1532{
1533 struct buffer_head *bh;
1534 struct nilfs_btree *btree;
1535 struct nilfs_btree_node *node, *root;
1536 __le64 *dkeys;
1537 __le64 *dptrs;
1538 __u64 ptr;
1539 int nchildren, i, ret;
1540
1541 btree = (struct nilfs_btree *)bmap;
1542 root = nilfs_btree_get_root(btree);
1543 switch (nilfs_btree_height(btree)) {
1544 case 2:
1545 bh = NULL;
1546 node = root;
1547 break;
1548 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001549 nchildren = nilfs_btree_node_get_nchildren(root);
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001550 WARN_ON(nchildren > 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001551 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001552 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001553 if (ret < 0)
1554 return ret;
1555 node = (struct nilfs_btree_node *)bh->b_data;
1556 break;
1557 default:
1558 node = NULL;
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001559 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -07001560 }
1561
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001562 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001563 if (nchildren < nitems)
1564 nitems = nchildren;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001565 dkeys = nilfs_btree_node_dkeys(node);
1566 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001567 for (i = 0; i < nitems; i++) {
1568 keys[i] = nilfs_bmap_dkey_to_key(dkeys[i]);
1569 ptrs[i] = nilfs_bmap_dptr_to_ptr(dptrs[i]);
1570 }
1571
1572 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001573 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001574
1575 return nitems;
1576}
1577
1578static int
1579nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
1580 union nilfs_bmap_ptr_req *dreq,
1581 union nilfs_bmap_ptr_req *nreq,
1582 struct buffer_head **bhp,
1583 struct nilfs_bmap_stats *stats)
1584{
1585 struct buffer_head *bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001586 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
1587 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001588 int ret;
1589
Koji Sato17c76b02009-04-06 19:01:24 -07001590 stats->bs_nblocks = 0;
1591
1592 /* for data */
1593 /* cannot find near ptr */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001594 if (NILFS_BMAP_USE_VBN(bmap)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001595 dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001596 dat = nilfs_bmap_get_dat(bmap);
1597 }
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001598
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001599 ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001600 if (ret < 0)
1601 return ret;
1602
1603 *bhp = NULL;
1604 stats->bs_nblocks++;
1605 if (nreq != NULL) {
1606 nreq->bpr_ptr = dreq->bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001607 ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001608 if (ret < 0)
1609 goto err_out_dreq;
1610
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001611 ret = nilfs_btree_get_new_block(btree, nreq->bpr_ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001612 if (ret < 0)
1613 goto err_out_nreq;
1614
1615 *bhp = bh;
1616 stats->bs_nblocks++;
1617 }
1618
1619 /* success */
1620 return 0;
1621
1622 /* error */
1623 err_out_nreq:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001624 nilfs_bmap_abort_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001625 err_out_dreq:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001626 nilfs_bmap_abort_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001627 stats->bs_nblocks = 0;
1628 return ret;
1629
1630}
1631
1632static void
1633nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
1634 __u64 key, __u64 ptr,
1635 const __u64 *keys, const __u64 *ptrs,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001636 int n,
Koji Sato17c76b02009-04-06 19:01:24 -07001637 union nilfs_bmap_ptr_req *dreq,
1638 union nilfs_bmap_ptr_req *nreq,
1639 struct buffer_head *bh)
1640{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001641 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
Koji Sato17c76b02009-04-06 19:01:24 -07001642 struct nilfs_btree_node *node;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001643 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001644 __u64 tmpptr;
1645
1646 /* free resources */
1647 if (bmap->b_ops->bop_clear != NULL)
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001648 bmap->b_ops->bop_clear(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001649
1650 /* ptr must be a pointer to a buffer head. */
1651 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1652
1653 /* convert and insert */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001654 dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL;
Ryusuke Konishi30333422009-05-24 00:09:44 +09001655 nilfs_btree_init(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001656 if (nreq != NULL) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001657 nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
1658 nilfs_bmap_commit_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001659
1660 /* create child node at level 1 */
Koji Sato17c76b02009-04-06 19:01:24 -07001661 node = (struct nilfs_btree_node *)bh->b_data;
1662 nilfs_btree_node_init(btree, node, 0, 1, n, keys, ptrs);
1663 nilfs_btree_node_insert(btree, node,
1664 key, dreq->bpr_ptr, n);
1665 if (!buffer_dirty(bh))
1666 nilfs_btnode_mark_dirty(bh);
1667 if (!nilfs_bmap_dirty(bmap))
1668 nilfs_bmap_set_dirty(bmap);
1669
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001670 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001671
1672 /* create root node at level 2 */
1673 node = nilfs_btree_get_root(btree);
1674 tmpptr = nreq->bpr_ptr;
1675 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1676 2, 1, &keys[0], &tmpptr);
1677 } else {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001678 nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001679
1680 /* create root node at level 1 */
1681 node = nilfs_btree_get_root(btree);
1682 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1683 1, n, keys, ptrs);
1684 nilfs_btree_node_insert(btree, node,
1685 key, dreq->bpr_ptr, n);
1686 if (!nilfs_bmap_dirty(bmap))
1687 nilfs_bmap_set_dirty(bmap);
1688 }
1689
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001690 if (NILFS_BMAP_USE_VBN(bmap))
1691 nilfs_btree_set_target_v(btree, key, dreq->bpr_ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001692}
1693
1694/**
1695 * nilfs_btree_convert_and_insert -
1696 * @bmap:
1697 * @key:
1698 * @ptr:
1699 * @keys:
1700 * @ptrs:
1701 * @n:
Koji Sato17c76b02009-04-06 19:01:24 -07001702 */
1703int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap,
1704 __u64 key, __u64 ptr,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001705 const __u64 *keys, const __u64 *ptrs, int n)
Koji Sato17c76b02009-04-06 19:01:24 -07001706{
1707 struct buffer_head *bh;
1708 union nilfs_bmap_ptr_req dreq, nreq, *di, *ni;
1709 struct nilfs_bmap_stats stats;
1710 int ret;
1711
1712 if (n + 1 <= NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1713 di = &dreq;
1714 ni = NULL;
1715 } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX(
1716 1 << bmap->b_inode->i_blkbits)) {
1717 di = &dreq;
1718 ni = &nreq;
1719 } else {
1720 di = NULL;
1721 ni = NULL;
1722 BUG();
1723 }
1724
1725 ret = nilfs_btree_prepare_convert_and_insert(bmap, key, di, ni, &bh,
1726 &stats);
1727 if (ret < 0)
1728 return ret;
1729 nilfs_btree_commit_convert_and_insert(bmap, key, ptr, keys, ptrs, n,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001730 di, ni, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001731 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1732 return 0;
1733}
1734
1735static int nilfs_btree_propagate_p(struct nilfs_btree *btree,
1736 struct nilfs_btree_path *path,
1737 int level,
1738 struct buffer_head *bh)
1739{
1740 while ((++level < nilfs_btree_height(btree) - 1) &&
1741 !buffer_dirty(path[level].bp_bh))
1742 nilfs_btnode_mark_dirty(path[level].bp_bh);
1743
1744 return 0;
1745}
1746
1747static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
1748 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001749 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001750{
1751 struct nilfs_btree_node *parent;
1752 int ret;
1753
1754 parent = nilfs_btree_get_node(btree, path, level + 1);
1755 path[level].bp_oldreq.bpr_ptr =
1756 nilfs_btree_node_get_ptr(btree, parent,
1757 path[level + 1].bp_index);
1758 path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001759 ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req,
1760 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001761 if (ret < 0)
1762 return ret;
1763
1764 if (buffer_nilfs_node(path[level].bp_bh)) {
1765 path[level].bp_ctxt.oldkey = path[level].bp_oldreq.bpr_ptr;
1766 path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr;
1767 path[level].bp_ctxt.bh = path[level].bp_bh;
1768 ret = nilfs_btnode_prepare_change_key(
1769 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1770 &path[level].bp_ctxt);
1771 if (ret < 0) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001772 nilfs_dat_abort_update(dat,
1773 &path[level].bp_oldreq.bpr_req,
1774 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001775 return ret;
1776 }
1777 }
1778
1779 return 0;
1780}
1781
1782static void nilfs_btree_commit_update_v(struct nilfs_btree *btree,
1783 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001784 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001785{
1786 struct nilfs_btree_node *parent;
1787
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001788 nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req,
1789 &path[level].bp_newreq.bpr_req,
1790 btree->bt_bmap.b_ptr_type == NILFS_BMAP_PTR_VS);
Koji Sato17c76b02009-04-06 19:01:24 -07001791
1792 if (buffer_nilfs_node(path[level].bp_bh)) {
1793 nilfs_btnode_commit_change_key(
1794 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1795 &path[level].bp_ctxt);
1796 path[level].bp_bh = path[level].bp_ctxt.bh;
1797 }
1798 set_buffer_nilfs_volatile(path[level].bp_bh);
1799
1800 parent = nilfs_btree_get_node(btree, path, level + 1);
1801 nilfs_btree_node_set_ptr(btree, parent, path[level + 1].bp_index,
1802 path[level].bp_newreq.bpr_ptr);
1803}
1804
1805static void nilfs_btree_abort_update_v(struct nilfs_btree *btree,
1806 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001807 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001808{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001809 nilfs_dat_abort_update(dat, &path[level].bp_oldreq.bpr_req,
1810 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001811 if (buffer_nilfs_node(path[level].bp_bh))
1812 nilfs_btnode_abort_change_key(
1813 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1814 &path[level].bp_ctxt);
1815}
1816
1817static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree,
1818 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001819 int minlevel, int *maxlevelp,
1820 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001821{
1822 int level, ret;
1823
1824 level = minlevel;
1825 if (!buffer_nilfs_volatile(path[level].bp_bh)) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001826 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001827 if (ret < 0)
1828 return ret;
1829 }
1830 while ((++level < nilfs_btree_height(btree) - 1) &&
1831 !buffer_dirty(path[level].bp_bh)) {
1832
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001833 WARN_ON(buffer_nilfs_volatile(path[level].bp_bh));
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001834 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001835 if (ret < 0)
1836 goto out;
1837 }
1838
1839 /* success */
Koji Sato17c76b02009-04-06 19:01:24 -07001840 *maxlevelp = level - 1;
1841 return 0;
1842
1843 /* error */
1844 out:
1845 while (--level > minlevel)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001846 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001847 if (!buffer_nilfs_volatile(path[level].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001848 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001849 return ret;
1850}
1851
1852static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree,
1853 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001854 int minlevel, int maxlevel,
1855 struct buffer_head *bh,
1856 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001857{
1858 int level;
1859
1860 if (!buffer_nilfs_volatile(path[minlevel].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001861 nilfs_btree_commit_update_v(btree, path, minlevel, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001862
1863 for (level = minlevel + 1; level <= maxlevel; level++)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001864 nilfs_btree_commit_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001865}
1866
1867static int nilfs_btree_propagate_v(struct nilfs_btree *btree,
1868 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001869 int level, struct buffer_head *bh)
Koji Sato17c76b02009-04-06 19:01:24 -07001870{
Li Hong308f4412010-04-02 18:40:39 +08001871 int maxlevel = 0, ret;
Koji Sato17c76b02009-04-06 19:01:24 -07001872 struct nilfs_btree_node *parent;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001873 struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001874 __u64 ptr;
1875
1876 get_bh(bh);
1877 path[level].bp_bh = bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001878 ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel,
1879 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001880 if (ret < 0)
1881 goto out;
1882
1883 if (buffer_nilfs_volatile(path[level].bp_bh)) {
1884 parent = nilfs_btree_get_node(btree, path, level + 1);
1885 ptr = nilfs_btree_node_get_ptr(btree, parent,
1886 path[level + 1].bp_index);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001887 ret = nilfs_dat_mark_dirty(dat, ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001888 if (ret < 0)
1889 goto out;
1890 }
1891
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001892 nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001893
1894 out:
1895 brelse(path[level].bp_bh);
1896 path[level].bp_bh = NULL;
1897 return ret;
1898}
1899
1900static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
1901 struct buffer_head *bh)
1902{
1903 struct nilfs_btree *btree;
1904 struct nilfs_btree_path *path;
1905 struct nilfs_btree_node *node;
1906 __u64 key;
1907 int level, ret;
1908
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001909 WARN_ON(!buffer_dirty(bh));
Koji Sato17c76b02009-04-06 19:01:24 -07001910
1911 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001912 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001913 if (path == NULL)
1914 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001915
1916 if (buffer_nilfs_node(bh)) {
1917 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001918 key = nilfs_btree_node_get_key(node, 0);
1919 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001920 } else {
1921 key = nilfs_bmap_data_get_key(bmap, bh);
1922 level = NILFS_BTREE_LEVEL_DATA;
1923 }
1924
1925 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
1926 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001927 if (unlikely(ret == -ENOENT))
Koji Sato17c76b02009-04-06 19:01:24 -07001928 printk(KERN_CRIT "%s: key = %llu, level == %d\n",
1929 __func__, (unsigned long long)key, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001930 goto out;
1931 }
1932
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001933 ret = NILFS_BMAP_USE_VBN(bmap) ?
1934 nilfs_btree_propagate_v(btree, path, level, bh) :
1935 nilfs_btree_propagate_p(btree, path, level, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001936
1937 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001938 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001939
1940 return ret;
1941}
1942
1943static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap,
1944 struct buffer_head *bh)
1945{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001946 return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), bh->b_blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07001947}
1948
1949static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree,
1950 struct list_head *lists,
1951 struct buffer_head *bh)
1952{
1953 struct list_head *head;
1954 struct buffer_head *cbh;
1955 struct nilfs_btree_node *node, *cnode;
1956 __u64 key, ckey;
1957 int level;
1958
1959 get_bh(bh);
1960 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001961 key = nilfs_btree_node_get_key(node, 0);
1962 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001963 list_for_each(head, &lists[level]) {
1964 cbh = list_entry(head, struct buffer_head, b_assoc_buffers);
1965 cnode = (struct nilfs_btree_node *)cbh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001966 ckey = nilfs_btree_node_get_key(cnode, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07001967 if (key < ckey)
1968 break;
1969 }
1970 list_add_tail(&bh->b_assoc_buffers, head);
1971}
1972
1973static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *bmap,
1974 struct list_head *listp)
1975{
1976 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
1977 struct address_space *btcache = &NILFS_BMAP_I(bmap)->i_btnode_cache;
1978 struct list_head lists[NILFS_BTREE_LEVEL_MAX];
1979 struct pagevec pvec;
1980 struct buffer_head *bh, *head;
1981 pgoff_t index = 0;
1982 int level, i;
1983
1984 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1985 level < NILFS_BTREE_LEVEL_MAX;
1986 level++)
1987 INIT_LIST_HEAD(&lists[level]);
1988
1989 pagevec_init(&pvec, 0);
1990
1991 while (pagevec_lookup_tag(&pvec, btcache, &index, PAGECACHE_TAG_DIRTY,
1992 PAGEVEC_SIZE)) {
1993 for (i = 0; i < pagevec_count(&pvec); i++) {
1994 bh = head = page_buffers(pvec.pages[i]);
1995 do {
1996 if (buffer_dirty(bh))
1997 nilfs_btree_add_dirty_buffer(btree,
1998 lists, bh);
1999 } while ((bh = bh->b_this_page) != head);
2000 }
2001 pagevec_release(&pvec);
2002 cond_resched();
2003 }
2004
2005 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
2006 level < NILFS_BTREE_LEVEL_MAX;
2007 level++)
Ryusuke Konishi0935db72009-11-29 02:39:11 +09002008 list_splice_tail(&lists[level], listp);
Koji Sato17c76b02009-04-06 19:01:24 -07002009}
2010
2011static int nilfs_btree_assign_p(struct nilfs_btree *btree,
2012 struct nilfs_btree_path *path,
2013 int level,
2014 struct buffer_head **bh,
2015 sector_t blocknr,
2016 union nilfs_binfo *binfo)
2017{
2018 struct nilfs_btree_node *parent;
2019 __u64 key;
2020 __u64 ptr;
2021 int ret;
2022
2023 parent = nilfs_btree_get_node(btree, path, level + 1);
2024 ptr = nilfs_btree_node_get_ptr(btree, parent,
2025 path[level + 1].bp_index);
2026 if (buffer_nilfs_node(*bh)) {
2027 path[level].bp_ctxt.oldkey = ptr;
2028 path[level].bp_ctxt.newkey = blocknr;
2029 path[level].bp_ctxt.bh = *bh;
2030 ret = nilfs_btnode_prepare_change_key(
2031 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2032 &path[level].bp_ctxt);
2033 if (ret < 0)
2034 return ret;
2035 nilfs_btnode_commit_change_key(
2036 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2037 &path[level].bp_ctxt);
2038 *bh = path[level].bp_ctxt.bh;
2039 }
2040
2041 nilfs_btree_node_set_ptr(btree, parent,
2042 path[level + 1].bp_index, blocknr);
2043
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002044 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002045 /* on-disk format */
2046 binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2047 binfo->bi_dat.bi_level = level;
2048
2049 return 0;
2050}
2051
2052static int nilfs_btree_assign_v(struct nilfs_btree *btree,
2053 struct nilfs_btree_path *path,
2054 int level,
2055 struct buffer_head **bh,
2056 sector_t blocknr,
2057 union nilfs_binfo *binfo)
2058{
2059 struct nilfs_btree_node *parent;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002060 struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07002061 __u64 key;
2062 __u64 ptr;
2063 union nilfs_bmap_ptr_req req;
2064 int ret;
2065
2066 parent = nilfs_btree_get_node(btree, path, level + 1);
2067 ptr = nilfs_btree_node_get_ptr(btree, parent,
2068 path[level + 1].bp_index);
2069 req.bpr_ptr = ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002070 ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
2071 if (ret < 0)
Koji Sato17c76b02009-04-06 19:01:24 -07002072 return ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002073 nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002074
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002075 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002076 /* on-disk format */
2077 binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr);
2078 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2079
2080 return 0;
2081}
2082
2083static int nilfs_btree_assign(struct nilfs_bmap *bmap,
2084 struct buffer_head **bh,
2085 sector_t blocknr,
2086 union nilfs_binfo *binfo)
2087{
2088 struct nilfs_btree *btree;
2089 struct nilfs_btree_path *path;
2090 struct nilfs_btree_node *node;
2091 __u64 key;
2092 int level, ret;
2093
2094 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002095 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002096 if (path == NULL)
2097 return -ENOMEM;
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 Konishi6d28f7e2009-08-15 01:14:10 +09002119 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002120
2121 return ret;
2122}
2123
2124static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap,
2125 struct buffer_head **bh,
2126 sector_t blocknr,
2127 union nilfs_binfo *binfo)
2128{
Koji Sato17c76b02009-04-06 19:01:24 -07002129 struct nilfs_btree_node *node;
2130 __u64 key;
2131 int ret;
2132
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002133 ret = nilfs_dat_move(nilfs_bmap_get_dat(bmap), (*bh)->b_blocknr,
2134 blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002135 if (ret < 0)
2136 return ret;
2137
2138 if (buffer_nilfs_node(*bh)) {
2139 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002140 key = nilfs_btree_node_get_key(node, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07002141 } else
2142 key = nilfs_bmap_data_get_key(bmap, *bh);
2143
2144 /* on-disk format */
2145 binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr);
2146 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2147
2148 return 0;
2149}
2150
2151static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
2152{
2153 struct buffer_head *bh;
2154 struct nilfs_btree *btree;
2155 struct nilfs_btree_path *path;
2156 __u64 ptr;
2157 int ret;
2158
2159 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002160 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002161 if (path == NULL)
2162 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07002163
2164 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1);
2165 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002166 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002167 goto out;
2168 }
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09002169 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002170 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002171 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002172 goto out;
2173 }
2174
2175 if (!buffer_dirty(bh))
2176 nilfs_btnode_mark_dirty(bh);
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09002177 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002178 if (!nilfs_bmap_dirty(&btree->bt_bmap))
2179 nilfs_bmap_set_dirty(&btree->bt_bmap);
2180
2181 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002182 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002183 return ret;
2184}
2185
2186static const struct nilfs_bmap_operations nilfs_btree_ops = {
2187 .bop_lookup = nilfs_btree_lookup,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002188 .bop_lookup_contig = nilfs_btree_lookup_contig,
Koji Sato17c76b02009-04-06 19:01:24 -07002189 .bop_insert = nilfs_btree_insert,
2190 .bop_delete = nilfs_btree_delete,
2191 .bop_clear = NULL,
2192
2193 .bop_propagate = nilfs_btree_propagate,
2194
2195 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2196
2197 .bop_assign = nilfs_btree_assign,
2198 .bop_mark = nilfs_btree_mark,
2199
2200 .bop_last_key = nilfs_btree_last_key,
2201 .bop_check_insert = NULL,
2202 .bop_check_delete = nilfs_btree_check_delete,
2203 .bop_gather_data = nilfs_btree_gather_data,
2204};
2205
2206static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
2207 .bop_lookup = NULL,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002208 .bop_lookup_contig = NULL,
Koji Sato17c76b02009-04-06 19:01:24 -07002209 .bop_insert = NULL,
2210 .bop_delete = NULL,
2211 .bop_clear = NULL,
2212
2213 .bop_propagate = nilfs_btree_propagate_gc,
2214
2215 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2216
2217 .bop_assign = nilfs_btree_assign_gc,
2218 .bop_mark = NULL,
2219
2220 .bop_last_key = NULL,
2221 .bop_check_insert = NULL,
2222 .bop_check_delete = NULL,
2223 .bop_gather_data = NULL,
2224};
2225
Ryusuke Konishi30333422009-05-24 00:09:44 +09002226int nilfs_btree_init(struct nilfs_bmap *bmap)
Koji Sato17c76b02009-04-06 19:01:24 -07002227{
Koji Sato17c76b02009-04-06 19:01:24 -07002228 bmap->b_ops = &nilfs_btree_ops;
Koji Sato17c76b02009-04-06 19:01:24 -07002229 return 0;
2230}
2231
2232void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
2233{
Koji Sato17c76b02009-04-06 19:01:24 -07002234 bmap->b_ops = &nilfs_btree_ops_gc;
2235}