]> bbs.cooldavid.org Git - net-next-2.6.git/blame - fs/nilfs2/btree.c
nilfs2: optimize calculation of min/max number of btree node children
[net-next-2.6.git] / fs / nilfs2 / btree.c
CommitLineData
17c76b01
KS
1/*
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"
c3a7abf0 32#include "dat.h"
17c76b01 33
f905440f 34static struct nilfs_btree_path *nilfs_btree_alloc_path(void)
17c76b01 35{
f905440f
LH
36 struct nilfs_btree_path *path;
37 int level = NILFS_BTREE_LEVEL_DATA;
17c76b01 38
f905440f
LH
39 path = kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS);
40 if (path == NULL)
41 goto out;
17c76b01 42
f905440f 43 for (; level < NILFS_BTREE_LEVEL_MAX; level++) {
17c76b01
KS
44 path[level].bp_bh = NULL;
45 path[level].bp_sib_bh = NULL;
46 path[level].bp_index = 0;
47 path[level].bp_oldreq.bpr_ptr = NILFS_BMAP_INVALID_PTR;
48 path[level].bp_newreq.bpr_ptr = NILFS_BMAP_INVALID_PTR;
49 path[level].bp_op = NULL;
50 }
f905440f
LH
51
52out:
53 return path;
54}
55
73bb4886 56static void nilfs_btree_free_path(struct nilfs_btree_path *path)
f905440f 57{
73bb4886 58 int level = NILFS_BTREE_LEVEL_DATA;
17c76b01 59
73bb4886 60 for (; level < NILFS_BTREE_LEVEL_MAX; level++)
3218929d 61 brelse(path[level].bp_bh);
73bb4886
LH
62
63 kmem_cache_free(nilfs_btree_path_cache, path);
17c76b01
KS
64}
65
17c76b01
KS
66/*
67 * B-tree node operations
68 */
e7c274f8 69static int nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr,
f198dbb9
RK
70 struct buffer_head **bhp)
71{
e7c274f8 72 struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache;
1d5385b9 73 struct buffer_head *bh;
1376e931
RK
74 int err;
75
76 err = nilfs_btnode_submit_block(btnc, ptr, 0, bhp);
77 if (err)
78 return err == -EEXIST ? 0 : err;
79
1d5385b9
RK
80 bh = *bhp;
81 wait_on_buffer(bh);
82 if (!buffer_uptodate(bh)) {
83 brelse(bh);
1376e931
RK
84 return -EIO;
85 }
1d5385b9
RK
86 if (nilfs_btree_broken_node_block(bh)) {
87 clear_buffer_uptodate(bh);
88 brelse(bh);
89 return -EINVAL;
90 }
1376e931 91 return 0;
f198dbb9
RK
92}
93
e7c274f8 94static int nilfs_btree_get_new_block(const struct nilfs_bmap *btree,
f198dbb9
RK
95 __u64 ptr, struct buffer_head **bhp)
96{
e7c274f8 97 struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache;
45f4910b 98 struct buffer_head *bh;
f198dbb9 99
45f4910b
RK
100 bh = nilfs_btnode_create_block(btnc, ptr);
101 if (!bh)
102 return -ENOMEM;
103
104 set_buffer_nilfs_volatile(bh);
105 *bhp = bh;
106 return 0;
f198dbb9 107}
17c76b01
KS
108
109static inline int
6d28f7ea 110nilfs_btree_node_get_flags(const struct nilfs_btree_node *node)
17c76b01
KS
111{
112 return node->bn_flags;
113}
114
115static inline void
6d28f7ea 116nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags)
17c76b01
KS
117{
118 node->bn_flags = flags;
119}
120
6d28f7ea 121static inline int nilfs_btree_node_root(const struct nilfs_btree_node *node)
17c76b01 122{
6d28f7ea 123 return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT;
17c76b01
KS
124}
125
126static inline int
6d28f7ea 127nilfs_btree_node_get_level(const struct nilfs_btree_node *node)
17c76b01
KS
128{
129 return node->bn_level;
130}
131
132static inline void
6d28f7ea 133nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level)
17c76b01
KS
134{
135 node->bn_level = level;
136}
137
138static inline int
6d28f7ea 139nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node)
17c76b01
KS
140{
141 return le16_to_cpu(node->bn_nchildren);
142}
143
144static inline void
6d28f7ea 145nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren)
17c76b01
KS
146{
147 node->bn_nchildren = cpu_to_le16(nchildren);
148}
149
e7c274f8 150static inline int nilfs_btree_node_size(const struct nilfs_bmap *btree)
17c76b01 151{
e7c274f8 152 return 1 << btree->b_inode->i_blkbits;
17c76b01
KS
153}
154
155static inline int
6d28f7ea 156nilfs_btree_node_nchildren_min(const struct nilfs_btree_node *node,
e7c274f8 157 const struct nilfs_bmap *btree)
17c76b01 158{
6d28f7ea 159 return nilfs_btree_node_root(node) ?
17c76b01
KS
160 NILFS_BTREE_ROOT_NCHILDREN_MIN :
161 NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree));
162}
163
164static inline int
6d28f7ea 165nilfs_btree_node_nchildren_max(const struct nilfs_btree_node *node,
e7c274f8 166 const struct nilfs_bmap *btree)
17c76b01 167{
6d28f7ea 168 return nilfs_btree_node_root(node) ?
17c76b01
KS
169 NILFS_BTREE_ROOT_NCHILDREN_MAX :
170 NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree));
171}
172
173static inline __le64 *
6d28f7ea 174nilfs_btree_node_dkeys(const struct nilfs_btree_node *node)
17c76b01
KS
175{
176 return (__le64 *)((char *)(node + 1) +
6d28f7ea 177 (nilfs_btree_node_root(node) ?
17c76b01
KS
178 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE));
179}
180
181static inline __le64 *
6d28f7ea 182nilfs_btree_node_dptrs(const struct nilfs_btree_node *node,
e7c274f8 183 const struct nilfs_bmap *btree)
17c76b01 184{
6d28f7ea
RK
185 return (__le64 *)(nilfs_btree_node_dkeys(node) +
186 nilfs_btree_node_nchildren_max(node, btree));
17c76b01
KS
187}
188
189static inline __u64
6d28f7ea 190nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index)
17c76b01 191{
25b8d7de 192 return le64_to_cpu(*(nilfs_btree_node_dkeys(node) + index));
17c76b01
KS
193}
194
195static inline void
6d28f7ea 196nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key)
17c76b01 197{
25b8d7de 198 *(nilfs_btree_node_dkeys(node) + index) = cpu_to_le64(key);
17c76b01
KS
199}
200
201static inline __u64
e7c274f8 202nilfs_btree_node_get_ptr(const struct nilfs_bmap *btree,
6d28f7ea 203 const struct nilfs_btree_node *node, int index)
17c76b01 204{
25b8d7de 205 return le64_to_cpu(*(nilfs_btree_node_dptrs(node, btree) + index));
17c76b01
KS
206}
207
208static inline void
e7c274f8 209nilfs_btree_node_set_ptr(struct nilfs_bmap *btree,
6d28f7ea 210 struct nilfs_btree_node *node, int index, __u64 ptr)
17c76b01 211{
25b8d7de 212 *(nilfs_btree_node_dptrs(node, btree) + index) = cpu_to_le64(ptr);
17c76b01
KS
213}
214
e7c274f8 215static void nilfs_btree_node_init(struct nilfs_bmap *btree,
17c76b01
KS
216 struct nilfs_btree_node *node,
217 int flags, int level, int nchildren,
218 const __u64 *keys, const __u64 *ptrs)
219{
220 __le64 *dkeys;
221 __le64 *dptrs;
222 int i;
223
6d28f7ea
RK
224 nilfs_btree_node_set_flags(node, flags);
225 nilfs_btree_node_set_level(node, level);
226 nilfs_btree_node_set_nchildren(node, nchildren);
17c76b01 227
6d28f7ea
RK
228 dkeys = nilfs_btree_node_dkeys(node);
229 dptrs = nilfs_btree_node_dptrs(node, btree);
17c76b01 230 for (i = 0; i < nchildren; i++) {
25b8d7de
RK
231 dkeys[i] = cpu_to_le64(keys[i]);
232 dptrs[i] = cpu_to_le64(ptrs[i]);
17c76b01
KS
233 }
234}
235
236/* Assume the buffer heads corresponding to left and right are locked. */
e7c274f8 237static void nilfs_btree_node_move_left(struct nilfs_bmap *btree,
17c76b01
KS
238 struct nilfs_btree_node *left,
239 struct nilfs_btree_node *right,
240 int n)
241{
242 __le64 *ldkeys, *rdkeys;
243 __le64 *ldptrs, *rdptrs;
244 int lnchildren, rnchildren;
245
6d28f7ea
RK
246 ldkeys = nilfs_btree_node_dkeys(left);
247 ldptrs = nilfs_btree_node_dptrs(left, btree);
248 lnchildren = nilfs_btree_node_get_nchildren(left);
17c76b01 249
6d28f7ea
RK
250 rdkeys = nilfs_btree_node_dkeys(right);
251 rdptrs = nilfs_btree_node_dptrs(right, btree);
252 rnchildren = nilfs_btree_node_get_nchildren(right);
17c76b01
KS
253
254 memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys));
255 memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs));
256 memmove(rdkeys, rdkeys + n, (rnchildren - n) * sizeof(*rdkeys));
257 memmove(rdptrs, rdptrs + n, (rnchildren - n) * sizeof(*rdptrs));
258
259 lnchildren += n;
260 rnchildren -= n;
6d28f7ea
RK
261 nilfs_btree_node_set_nchildren(left, lnchildren);
262 nilfs_btree_node_set_nchildren(right, rnchildren);
17c76b01
KS
263}
264
265/* Assume that the buffer heads corresponding to left and right are locked. */
e7c274f8 266static void nilfs_btree_node_move_right(struct nilfs_bmap *btree,
17c76b01
KS
267 struct nilfs_btree_node *left,
268 struct nilfs_btree_node *right,
269 int n)
270{
271 __le64 *ldkeys, *rdkeys;
272 __le64 *ldptrs, *rdptrs;
273 int lnchildren, rnchildren;
274
6d28f7ea
RK
275 ldkeys = nilfs_btree_node_dkeys(left);
276 ldptrs = nilfs_btree_node_dptrs(left, btree);
277 lnchildren = nilfs_btree_node_get_nchildren(left);
17c76b01 278
6d28f7ea
RK
279 rdkeys = nilfs_btree_node_dkeys(right);
280 rdptrs = nilfs_btree_node_dptrs(right, btree);
281 rnchildren = nilfs_btree_node_get_nchildren(right);
17c76b01
KS
282
283 memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys));
284 memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs));
285 memcpy(rdkeys, ldkeys + lnchildren - n, n * sizeof(*rdkeys));
286 memcpy(rdptrs, ldptrs + lnchildren - n, n * sizeof(*rdptrs));
287
288 lnchildren -= n;
289 rnchildren += n;
6d28f7ea
RK
290 nilfs_btree_node_set_nchildren(left, lnchildren);
291 nilfs_btree_node_set_nchildren(right, rnchildren);
17c76b01
KS
292}
293
294/* Assume that the buffer head corresponding to node is locked. */
e7c274f8 295static void nilfs_btree_node_insert(struct nilfs_bmap *btree,
17c76b01
KS
296 struct nilfs_btree_node *node,
297 __u64 key, __u64 ptr, int index)
298{
299 __le64 *dkeys;
300 __le64 *dptrs;
301 int nchildren;
302
6d28f7ea
RK
303 dkeys = nilfs_btree_node_dkeys(node);
304 dptrs = nilfs_btree_node_dptrs(node, btree);
305 nchildren = nilfs_btree_node_get_nchildren(node);
17c76b01
KS
306 if (index < nchildren) {
307 memmove(dkeys + index + 1, dkeys + index,
308 (nchildren - index) * sizeof(*dkeys));
309 memmove(dptrs + index + 1, dptrs + index,
310 (nchildren - index) * sizeof(*dptrs));
311 }
25b8d7de
RK
312 dkeys[index] = cpu_to_le64(key);
313 dptrs[index] = cpu_to_le64(ptr);
17c76b01 314 nchildren++;
6d28f7ea 315 nilfs_btree_node_set_nchildren(node, nchildren);
17c76b01
KS
316}
317
318/* Assume that the buffer head corresponding to node is locked. */
e7c274f8 319static void nilfs_btree_node_delete(struct nilfs_bmap *btree,
17c76b01
KS
320 struct nilfs_btree_node *node,
321 __u64 *keyp, __u64 *ptrp, int index)
322{
323 __u64 key;
324 __u64 ptr;
325 __le64 *dkeys;
326 __le64 *dptrs;
327 int nchildren;
328
6d28f7ea
RK
329 dkeys = nilfs_btree_node_dkeys(node);
330 dptrs = nilfs_btree_node_dptrs(node, btree);
25b8d7de
RK
331 key = le64_to_cpu(dkeys[index]);
332 ptr = le64_to_cpu(dptrs[index]);
6d28f7ea 333 nchildren = nilfs_btree_node_get_nchildren(node);
17c76b01
KS
334 if (keyp != NULL)
335 *keyp = key;
336 if (ptrp != NULL)
337 *ptrp = ptr;
338
339 if (index < nchildren - 1) {
340 memmove(dkeys + index, dkeys + index + 1,
341 (nchildren - index - 1) * sizeof(*dkeys));
342 memmove(dptrs + index, dptrs + index + 1,
343 (nchildren - index - 1) * sizeof(*dptrs));
344 }
345 nchildren--;
6d28f7ea 346 nilfs_btree_node_set_nchildren(node, nchildren);
17c76b01
KS
347}
348
6d28f7ea 349static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node,
17c76b01
KS
350 __u64 key, int *indexp)
351{
352 __u64 nkey;
353 int index, low, high, s;
354
355 /* binary search */
356 low = 0;
6d28f7ea 357 high = nilfs_btree_node_get_nchildren(node) - 1;
17c76b01
KS
358 index = 0;
359 s = 0;
360 while (low <= high) {
361 index = (low + high) / 2;
6d28f7ea 362 nkey = nilfs_btree_node_get_key(node, index);
17c76b01
KS
363 if (nkey == key) {
364 s = 0;
365 goto out;
366 } else if (nkey < key) {
367 low = index + 1;
368 s = -1;
369 } else {
370 high = index - 1;
371 s = 1;
372 }
373 }
374
375 /* adjust index */
6d28f7ea
RK
376 if (nilfs_btree_node_get_level(node) > NILFS_BTREE_LEVEL_NODE_MIN) {
377 if (s > 0 && index > 0)
17c76b01
KS
378 index--;
379 } else if (s < 0)
380 index++;
381
382 out:
17c76b01
KS
383 *indexp = index;
384
385 return s == 0;
386}
387
1d5385b9
RK
388/**
389 * nilfs_btree_node_broken - verify consistency of btree node
390 * @node: btree node block to be examined
391 * @size: node size (in bytes)
392 * @blocknr: block number
393 *
394 * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned.
395 */
396static int nilfs_btree_node_broken(const struct nilfs_btree_node *node,
397 size_t size, sector_t blocknr)
398{
399 int level, flags, nchildren;
400 int ret = 0;
401
402 level = nilfs_btree_node_get_level(node);
403 flags = nilfs_btree_node_get_flags(node);
404 nchildren = nilfs_btree_node_get_nchildren(node);
405
406 if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
407 level >= NILFS_BTREE_LEVEL_MAX ||
408 (flags & NILFS_BTREE_NODE_ROOT) ||
409 nchildren < 0 ||
410 nchildren > NILFS_BTREE_NODE_NCHILDREN_MAX(size))) {
411 printk(KERN_CRIT "NILFS: bad btree node (blocknr=%llu): "
412 "level = %d, flags = 0x%x, nchildren = %d\n",
413 (unsigned long long)blocknr, level, flags, nchildren);
414 ret = 1;
415 }
416 return ret;
417}
418
419int nilfs_btree_broken_node_block(struct buffer_head *bh)
420{
421 return nilfs_btree_node_broken((struct nilfs_btree_node *)bh->b_data,
422 bh->b_size, bh->b_blocknr);
423}
424
17c76b01 425static inline struct nilfs_btree_node *
e7c274f8 426nilfs_btree_get_root(const struct nilfs_bmap *btree)
17c76b01 427{
e7c274f8 428 return (struct nilfs_btree_node *)btree->b_u.u_data;
17c76b01
KS
429}
430
431static inline struct nilfs_btree_node *
6d28f7ea 432nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level)
17c76b01
KS
433{
434 return (struct nilfs_btree_node *)path[level].bp_bh->b_data;
435}
436
437static inline struct nilfs_btree_node *
6d28f7ea 438nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level)
17c76b01
KS
439{
440 return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data;
441}
442
e7c274f8 443static inline int nilfs_btree_height(const struct nilfs_bmap *btree)
17c76b01 444{
6d28f7ea 445 return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1;
17c76b01
KS
446}
447
448static inline struct nilfs_btree_node *
e7c274f8 449nilfs_btree_get_node(const struct nilfs_bmap *btree,
17c76b01
KS
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) :
6d28f7ea 455 nilfs_btree_get_nonroot_node(path, level);
17c76b01
KS
456}
457
9b945d53
RK
458static 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
e7c274f8 470static int nilfs_btree_do_lookup(const struct nilfs_bmap *btree,
17c76b01
KS
471 struct nilfs_btree_path *path,
472 __u64 key, __u64 *ptrp, int minlevel)
473{
474 struct nilfs_btree_node *node;
475 __u64 ptr;
ea64ab87 476 int level, index, found, ncmax, ret;
17c76b01 477
17c76b01 478 node = nilfs_btree_get_root(btree);
6d28f7ea
RK
479 level = nilfs_btree_node_get_level(node);
480 if (level < minlevel || nilfs_btree_node_get_nchildren(node) <= 0)
17c76b01
KS
481 return -ENOENT;
482
6d28f7ea 483 found = nilfs_btree_node_lookup(node, key, &index);
17c76b01
KS
484 ptr = nilfs_btree_node_get_ptr(btree, node, index);
485 path[level].bp_bh = NULL;
486 path[level].bp_index = index;
487
ea64ab87
RK
488 ncmax = NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree));
489
17c76b01 490 for (level--; level >= minlevel; level--) {
f198dbb9 491 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
17c76b01
KS
492 if (ret < 0)
493 return ret;
6d28f7ea 494 node = nilfs_btree_get_nonroot_node(path, level);
9b945d53
RK
495 if (nilfs_btree_bad_node(node, level))
496 return -EINVAL;
17c76b01 497 if (!found)
6d28f7ea 498 found = nilfs_btree_node_lookup(node, key, &index);
17c76b01
KS
499 else
500 index = 0;
ea64ab87 501 if (index < ncmax) {
17c76b01 502 ptr = nilfs_btree_node_get_ptr(btree, node, index);
ea64ab87 503 } else {
1f5abe7e 504 WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN);
17c76b01
KS
505 /* insert */
506 ptr = NILFS_BMAP_INVALID_PTR;
507 }
508 path[level].bp_index = index;
509 }
510 if (!found)
511 return -ENOENT;
512
513 if (ptrp != NULL)
514 *ptrp = ptr;
515
516 return 0;
517}
518
e7c274f8 519static int nilfs_btree_do_lookup_last(const struct nilfs_bmap *btree,
17c76b01
KS
520 struct nilfs_btree_path *path,
521 __u64 *keyp, __u64 *ptrp)
522{
523 struct nilfs_btree_node *node;
524 __u64 ptr;
525 int index, level, ret;
526
527 node = nilfs_btree_get_root(btree);
6d28f7ea 528 index = nilfs_btree_node_get_nchildren(node) - 1;
17c76b01
KS
529 if (index < 0)
530 return -ENOENT;
6d28f7ea 531 level = nilfs_btree_node_get_level(node);
17c76b01
KS
532 ptr = nilfs_btree_node_get_ptr(btree, node, index);
533 path[level].bp_bh = NULL;
534 path[level].bp_index = index;
535
536 for (level--; level > 0; level--) {
f198dbb9 537 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
17c76b01
KS
538 if (ret < 0)
539 return ret;
6d28f7ea 540 node = nilfs_btree_get_nonroot_node(path, level);
9b945d53
RK
541 if (nilfs_btree_bad_node(node, level))
542 return -EINVAL;
6d28f7ea 543 index = nilfs_btree_node_get_nchildren(node) - 1;
17c76b01
KS
544 ptr = nilfs_btree_node_get_ptr(btree, node, index);
545 path[level].bp_index = index;
546 }
547
548 if (keyp != NULL)
6d28f7ea 549 *keyp = nilfs_btree_node_get_key(node, index);
17c76b01
KS
550 if (ptrp != NULL)
551 *ptrp = ptr;
552
553 return 0;
554}
555
e7c274f8 556static int nilfs_btree_lookup(const struct nilfs_bmap *btree,
17c76b01
KS
557 __u64 key, int level, __u64 *ptrp)
558{
17c76b01 559 struct nilfs_btree_path *path;
17c76b01
KS
560 int ret;
561
6d28f7ea 562 path = nilfs_btree_alloc_path();
17c76b01
KS
563 if (path == NULL)
564 return -ENOMEM;
17c76b01 565
364ec2d7 566 ret = nilfs_btree_do_lookup(btree, path, key, ptrp, level);
17c76b01 567
6d28f7ea 568 nilfs_btree_free_path(path);
17c76b01
KS
569
570 return ret;
571}
572
e7c274f8 573static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree,
c3a7abf0
RK
574 __u64 key, __u64 *ptrp, unsigned maxblocks)
575{
c3a7abf0
RK
576 struct nilfs_btree_path *path;
577 struct nilfs_btree_node *node;
578 struct inode *dat = NULL;
579 __u64 ptr, ptr2;
580 sector_t blocknr;
581 int level = NILFS_BTREE_LEVEL_NODE_MIN;
582 int ret, cnt, index, maxlevel;
583
6d28f7ea 584 path = nilfs_btree_alloc_path();
c3a7abf0
RK
585 if (path == NULL)
586 return -ENOMEM;
f905440f 587
c3a7abf0
RK
588 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
589 if (ret < 0)
590 goto out;
591
e7c274f8
RK
592 if (NILFS_BMAP_USE_VBN(btree)) {
593 dat = nilfs_bmap_get_dat(btree);
c3a7abf0
RK
594 ret = nilfs_dat_translate(dat, ptr, &blocknr);
595 if (ret < 0)
596 goto out;
597 ptr = blocknr;
598 }
599 cnt = 1;
600 if (cnt == maxblocks)
601 goto end;
602
603 maxlevel = nilfs_btree_height(btree) - 1;
604 node = nilfs_btree_get_node(btree, path, level);
605 index = path[level].bp_index + 1;
606 for (;;) {
6d28f7ea
RK
607 while (index < nilfs_btree_node_get_nchildren(node)) {
608 if (nilfs_btree_node_get_key(node, index) !=
c3a7abf0
RK
609 key + cnt)
610 goto end;
611 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
612 if (dat) {
613 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
614 if (ret < 0)
615 goto out;
616 ptr2 = blocknr;
617 }
618 if (ptr2 != ptr + cnt || ++cnt == maxblocks)
619 goto end;
620 index++;
621 continue;
622 }
623 if (level == maxlevel)
624 break;
625
626 /* look-up right sibling node */
627 node = nilfs_btree_get_node(btree, path, level + 1);
628 index = path[level + 1].bp_index + 1;
6d28f7ea
RK
629 if (index >= nilfs_btree_node_get_nchildren(node) ||
630 nilfs_btree_node_get_key(node, index) != key + cnt)
c3a7abf0
RK
631 break;
632 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
633 path[level + 1].bp_index = index;
634
635 brelse(path[level].bp_bh);
636 path[level].bp_bh = NULL;
637 ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh);
638 if (ret < 0)
639 goto out;
6d28f7ea 640 node = nilfs_btree_get_nonroot_node(path, level);
c3a7abf0
RK
641 index = 0;
642 path[level].bp_index = index;
643 }
644 end:
645 *ptrp = ptr;
646 ret = cnt;
647 out:
6d28f7ea 648 nilfs_btree_free_path(path);
c3a7abf0
RK
649 return ret;
650}
651
e7c274f8 652static void nilfs_btree_promote_key(struct nilfs_bmap *btree,
17c76b01
KS
653 struct nilfs_btree_path *path,
654 int level, __u64 key)
655{
656 if (level < nilfs_btree_height(btree) - 1) {
657 do {
17c76b01 658 nilfs_btree_node_set_key(
6d28f7ea 659 nilfs_btree_get_nonroot_node(path, level),
17c76b01
KS
660 path[level].bp_index, key);
661 if (!buffer_dirty(path[level].bp_bh))
662 nilfs_btnode_mark_dirty(path[level].bp_bh);
17c76b01
KS
663 } while ((path[level].bp_index == 0) &&
664 (++level < nilfs_btree_height(btree) - 1));
665 }
666
667 /* root */
668 if (level == nilfs_btree_height(btree) - 1) {
6d28f7ea 669 nilfs_btree_node_set_key(nilfs_btree_get_root(btree),
17c76b01
KS
670 path[level].bp_index, key);
671 }
672}
673
e7c274f8 674static void nilfs_btree_do_insert(struct nilfs_bmap *btree,
17c76b01
KS
675 struct nilfs_btree_path *path,
676 int level, __u64 *keyp, __u64 *ptrp)
677{
678 struct nilfs_btree_node *node;
679
680 if (level < nilfs_btree_height(btree) - 1) {
6d28f7ea 681 node = nilfs_btree_get_nonroot_node(path, level);
17c76b01
KS
682 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
683 path[level].bp_index);
684 if (!buffer_dirty(path[level].bp_bh))
685 nilfs_btnode_mark_dirty(path[level].bp_bh);
17c76b01
KS
686
687 if (path[level].bp_index == 0)
688 nilfs_btree_promote_key(btree, path, level + 1,
6d28f7ea
RK
689 nilfs_btree_node_get_key(node,
690 0));
17c76b01
KS
691 } else {
692 node = nilfs_btree_get_root(btree);
693 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
694 path[level].bp_index);
695 }
696}
697
e7c274f8 698static void nilfs_btree_carry_left(struct nilfs_bmap *btree,
17c76b01
KS
699 struct nilfs_btree_path *path,
700 int level, __u64 *keyp, __u64 *ptrp)
701{
702 struct nilfs_btree_node *node, *left;
703 int nchildren, lnchildren, n, move;
704
6d28f7ea
RK
705 node = nilfs_btree_get_nonroot_node(path, level);
706 left = nilfs_btree_get_sib_node(path, level);
707 nchildren = nilfs_btree_node_get_nchildren(node);
708 lnchildren = nilfs_btree_node_get_nchildren(left);
17c76b01
KS
709 move = 0;
710
711 n = (nchildren + lnchildren + 1) / 2 - lnchildren;
712 if (n > path[level].bp_index) {
713 /* move insert point */
714 n--;
715 move = 1;
716 }
717
718 nilfs_btree_node_move_left(btree, left, node, n);
719
720 if (!buffer_dirty(path[level].bp_bh))
721 nilfs_btnode_mark_dirty(path[level].bp_bh);
722 if (!buffer_dirty(path[level].bp_sib_bh))
723 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
724
17c76b01 725 nilfs_btree_promote_key(btree, path, level + 1,
6d28f7ea 726 nilfs_btree_node_get_key(node, 0));
17c76b01
KS
727
728 if (move) {
087d01b4 729 brelse(path[level].bp_bh);
17c76b01
KS
730 path[level].bp_bh = path[level].bp_sib_bh;
731 path[level].bp_sib_bh = NULL;
732 path[level].bp_index += lnchildren;
733 path[level + 1].bp_index--;
734 } else {
087d01b4 735 brelse(path[level].bp_sib_bh);
17c76b01
KS
736 path[level].bp_sib_bh = NULL;
737 path[level].bp_index -= n;
738 }
739
740 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
741}
742
e7c274f8 743static void nilfs_btree_carry_right(struct nilfs_bmap *btree,
17c76b01
KS
744 struct nilfs_btree_path *path,
745 int level, __u64 *keyp, __u64 *ptrp)
746{
747 struct nilfs_btree_node *node, *right;
748 int nchildren, rnchildren, n, move;
749
6d28f7ea
RK
750 node = nilfs_btree_get_nonroot_node(path, level);
751 right = nilfs_btree_get_sib_node(path, level);
752 nchildren = nilfs_btree_node_get_nchildren(node);
753 rnchildren = nilfs_btree_node_get_nchildren(right);
17c76b01
KS
754 move = 0;
755
756 n = (nchildren + rnchildren + 1) / 2 - rnchildren;
757 if (n > nchildren - path[level].bp_index) {
758 /* move insert point */
759 n--;
760 move = 1;
761 }
762
763 nilfs_btree_node_move_right(btree, node, right, n);
764
765 if (!buffer_dirty(path[level].bp_bh))
766 nilfs_btnode_mark_dirty(path[level].bp_bh);
767 if (!buffer_dirty(path[level].bp_sib_bh))
768 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
769
17c76b01
KS
770 path[level + 1].bp_index++;
771 nilfs_btree_promote_key(btree, path, level + 1,
6d28f7ea 772 nilfs_btree_node_get_key(right, 0));
17c76b01
KS
773 path[level + 1].bp_index--;
774
775 if (move) {
087d01b4 776 brelse(path[level].bp_bh);
17c76b01
KS
777 path[level].bp_bh = path[level].bp_sib_bh;
778 path[level].bp_sib_bh = NULL;
6d28f7ea 779 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
17c76b01
KS
780 path[level + 1].bp_index++;
781 } else {
087d01b4 782 brelse(path[level].bp_sib_bh);
17c76b01
KS
783 path[level].bp_sib_bh = NULL;
784 }
785
786 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
787}
788
e7c274f8 789static void nilfs_btree_split(struct nilfs_bmap *btree,
17c76b01
KS
790 struct nilfs_btree_path *path,
791 int level, __u64 *keyp, __u64 *ptrp)
792{
793 struct nilfs_btree_node *node, *right;
794 __u64 newkey;
795 __u64 newptr;
796 int nchildren, n, move;
797
6d28f7ea
RK
798 node = nilfs_btree_get_nonroot_node(path, level);
799 right = nilfs_btree_get_sib_node(path, level);
800 nchildren = nilfs_btree_node_get_nchildren(node);
17c76b01
KS
801 move = 0;
802
803 n = (nchildren + 1) / 2;
804 if (n > nchildren - path[level].bp_index) {
805 n--;
806 move = 1;
807 }
808
809 nilfs_btree_node_move_right(btree, node, right, n);
810
811 if (!buffer_dirty(path[level].bp_bh))
812 nilfs_btnode_mark_dirty(path[level].bp_bh);
813 if (!buffer_dirty(path[level].bp_sib_bh))
814 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
815
6d28f7ea 816 newkey = nilfs_btree_node_get_key(right, 0);
17c76b01
KS
817 newptr = path[level].bp_newreq.bpr_ptr;
818
819 if (move) {
6d28f7ea 820 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
17c76b01
KS
821 nilfs_btree_node_insert(btree, right, *keyp, *ptrp,
822 path[level].bp_index);
823
6d28f7ea 824 *keyp = nilfs_btree_node_get_key(right, 0);
17c76b01
KS
825 *ptrp = path[level].bp_newreq.bpr_ptr;
826
087d01b4 827 brelse(path[level].bp_bh);
17c76b01
KS
828 path[level].bp_bh = path[level].bp_sib_bh;
829 path[level].bp_sib_bh = NULL;
830 } else {
831 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
832
6d28f7ea 833 *keyp = nilfs_btree_node_get_key(right, 0);
17c76b01
KS
834 *ptrp = path[level].bp_newreq.bpr_ptr;
835
087d01b4 836 brelse(path[level].bp_sib_bh);
17c76b01
KS
837 path[level].bp_sib_bh = NULL;
838 }
839
840 path[level + 1].bp_index++;
841}
842
e7c274f8 843static void nilfs_btree_grow(struct nilfs_bmap *btree,
17c76b01
KS
844 struct nilfs_btree_path *path,
845 int level, __u64 *keyp, __u64 *ptrp)
846{
847 struct nilfs_btree_node *root, *child;
848 int n;
849
17c76b01 850 root = nilfs_btree_get_root(btree);
6d28f7ea 851 child = nilfs_btree_get_sib_node(path, level);
17c76b01 852
6d28f7ea 853 n = nilfs_btree_node_get_nchildren(root);
17c76b01
KS
854
855 nilfs_btree_node_move_right(btree, root, child, n);
6d28f7ea 856 nilfs_btree_node_set_level(root, level + 1);
17c76b01
KS
857
858 if (!buffer_dirty(path[level].bp_sib_bh))
859 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
860
17c76b01
KS
861 path[level].bp_bh = path[level].bp_sib_bh;
862 path[level].bp_sib_bh = NULL;
863
864 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
865
6d28f7ea 866 *keyp = nilfs_btree_node_get_key(child, 0);
17c76b01
KS
867 *ptrp = path[level].bp_newreq.bpr_ptr;
868}
869
e7c274f8 870static __u64 nilfs_btree_find_near(const struct nilfs_bmap *btree,
17c76b01
KS
871 const struct nilfs_btree_path *path)
872{
873 struct nilfs_btree_node *node;
874 int level;
875
876 if (path == NULL)
877 return NILFS_BMAP_INVALID_PTR;
878
879 /* left sibling */
880 level = NILFS_BTREE_LEVEL_NODE_MIN;
881 if (path[level].bp_index > 0) {
882 node = nilfs_btree_get_node(btree, path, level);
883 return nilfs_btree_node_get_ptr(btree, node,
884 path[level].bp_index - 1);
885 }
886
887 /* parent */
888 level = NILFS_BTREE_LEVEL_NODE_MIN + 1;
889 if (level <= nilfs_btree_height(btree) - 1) {
890 node = nilfs_btree_get_node(btree, path, level);
891 return nilfs_btree_node_get_ptr(btree, node,
892 path[level].bp_index);
893 }
894
895 return NILFS_BMAP_INVALID_PTR;
896}
897
e7c274f8 898static __u64 nilfs_btree_find_target_v(const struct nilfs_bmap *btree,
17c76b01
KS
899 const struct nilfs_btree_path *path,
900 __u64 key)
901{
902 __u64 ptr;
903
e7c274f8 904 ptr = nilfs_bmap_find_target_seq(btree, key);
17c76b01
KS
905 if (ptr != NILFS_BMAP_INVALID_PTR)
906 /* sequential access */
907 return ptr;
908 else {
909 ptr = nilfs_btree_find_near(btree, path);
910 if (ptr != NILFS_BMAP_INVALID_PTR)
911 /* near */
912 return ptr;
913 }
914 /* block group */
e7c274f8 915 return nilfs_bmap_find_target_in_group(btree);
17c76b01
KS
916}
917
e7c274f8 918static int nilfs_btree_prepare_insert(struct nilfs_bmap *btree,
17c76b01
KS
919 struct nilfs_btree_path *path,
920 int *levelp, __u64 key, __u64 ptr,
921 struct nilfs_bmap_stats *stats)
922{
923 struct buffer_head *bh;
924 struct nilfs_btree_node *node, *parent, *sib;
925 __u64 sibptr;
ea64ab87 926 int pindex, level, ncmax, ret;
2e0c2c73 927 struct inode *dat = NULL;
17c76b01
KS
928
929 stats->bs_nblocks = 0;
930 level = NILFS_BTREE_LEVEL_DATA;
931
932 /* allocate a new ptr for data block */
e7c274f8 933 if (NILFS_BMAP_USE_VBN(btree)) {
17c76b01 934 path[level].bp_newreq.bpr_ptr =
7cde31d7 935 nilfs_btree_find_target_v(btree, path, key);
e7c274f8 936 dat = nilfs_bmap_get_dat(btree);
2e0c2c73 937 }
17c76b01 938
e7c274f8 939 ret = nilfs_bmap_prepare_alloc_ptr(btree, &path[level].bp_newreq, dat);
17c76b01
KS
940 if (ret < 0)
941 goto err_out_data;
942
ea64ab87
RK
943 ncmax = NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree));
944
17c76b01
KS
945 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
946 level < nilfs_btree_height(btree) - 1;
947 level++) {
6d28f7ea 948 node = nilfs_btree_get_nonroot_node(path, level);
ea64ab87 949 if (nilfs_btree_node_get_nchildren(node) < ncmax) {
17c76b01
KS
950 path[level].bp_op = nilfs_btree_do_insert;
951 stats->bs_nblocks++;
952 goto out;
953 }
954
955 parent = nilfs_btree_get_node(btree, path, level + 1);
956 pindex = path[level + 1].bp_index;
957
958 /* left sibling */
959 if (pindex > 0) {
960 sibptr = nilfs_btree_node_get_ptr(btree, parent,
961 pindex - 1);
f198dbb9 962 ret = nilfs_btree_get_block(btree, sibptr, &bh);
17c76b01
KS
963 if (ret < 0)
964 goto err_out_child_node;
965 sib = (struct nilfs_btree_node *)bh->b_data;
ea64ab87 966 if (nilfs_btree_node_get_nchildren(sib) < ncmax) {
17c76b01
KS
967 path[level].bp_sib_bh = bh;
968 path[level].bp_op = nilfs_btree_carry_left;
969 stats->bs_nblocks++;
970 goto out;
971 } else
087d01b4 972 brelse(bh);
17c76b01
KS
973 }
974
975 /* right sibling */
976 if (pindex <
6d28f7ea 977 nilfs_btree_node_get_nchildren(parent) - 1) {
17c76b01
KS
978 sibptr = nilfs_btree_node_get_ptr(btree, parent,
979 pindex + 1);
f198dbb9 980 ret = nilfs_btree_get_block(btree, sibptr, &bh);
17c76b01
KS
981 if (ret < 0)
982 goto err_out_child_node;
983 sib = (struct nilfs_btree_node *)bh->b_data;
ea64ab87 984 if (nilfs_btree_node_get_nchildren(sib) < ncmax) {
17c76b01
KS
985 path[level].bp_sib_bh = bh;
986 path[level].bp_op = nilfs_btree_carry_right;
987 stats->bs_nblocks++;
988 goto out;
989 } else
087d01b4 990 brelse(bh);
17c76b01
KS
991 }
992
993 /* split */
994 path[level].bp_newreq.bpr_ptr =
995 path[level - 1].bp_newreq.bpr_ptr + 1;
e7c274f8 996 ret = nilfs_bmap_prepare_alloc_ptr(btree,
2e0c2c73 997 &path[level].bp_newreq, dat);
17c76b01
KS
998 if (ret < 0)
999 goto err_out_child_node;
f198dbb9
RK
1000 ret = nilfs_btree_get_new_block(btree,
1001 path[level].bp_newreq.bpr_ptr,
1002 &bh);
17c76b01
KS
1003 if (ret < 0)
1004 goto err_out_curr_node;
1005
1006 stats->bs_nblocks++;
1007
17c76b01
KS
1008 nilfs_btree_node_init(btree,
1009 (struct nilfs_btree_node *)bh->b_data,
1010 0, level, 0, NULL, NULL);
17c76b01
KS
1011 path[level].bp_sib_bh = bh;
1012 path[level].bp_op = nilfs_btree_split;
1013 }
1014
1015 /* root */
1016 node = nilfs_btree_get_root(btree);
6d28f7ea 1017 if (nilfs_btree_node_get_nchildren(node) <
ea64ab87 1018 NILFS_BTREE_ROOT_NCHILDREN_MAX) {
17c76b01
KS
1019 path[level].bp_op = nilfs_btree_do_insert;
1020 stats->bs_nblocks++;
1021 goto out;
1022 }
1023
1024 /* grow */
1025 path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
e7c274f8 1026 ret = nilfs_bmap_prepare_alloc_ptr(btree, &path[level].bp_newreq, dat);
17c76b01
KS
1027 if (ret < 0)
1028 goto err_out_child_node;
f198dbb9
RK
1029 ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
1030 &bh);
17c76b01
KS
1031 if (ret < 0)
1032 goto err_out_curr_node;
1033
17c76b01
KS
1034 nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data,
1035 0, level, 0, NULL, NULL);
17c76b01
KS
1036 path[level].bp_sib_bh = bh;
1037 path[level].bp_op = nilfs_btree_grow;
1038
1039 level++;
1040 path[level].bp_op = nilfs_btree_do_insert;
1041
1042 /* a newly-created node block and a data block are added */
1043 stats->bs_nblocks += 2;
1044
1045 /* success */
1046 out:
1047 *levelp = level;
1048 return ret;
1049
1050 /* error */
1051 err_out_curr_node:
e7c274f8 1052 nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat);
17c76b01
KS
1053 err_out_child_node:
1054 for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
9f098900 1055 nilfs_btnode_delete(path[level].bp_sib_bh);
e7c274f8 1056 nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat);
17c76b01
KS
1057
1058 }
1059
e7c274f8 1060 nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat);
17c76b01
KS
1061 err_out_data:
1062 *levelp = level;
1063 stats->bs_nblocks = 0;
1064 return ret;
1065}
1066
e7c274f8 1067static void nilfs_btree_commit_insert(struct nilfs_bmap *btree,
17c76b01
KS
1068 struct nilfs_btree_path *path,
1069 int maxlevel, __u64 key, __u64 ptr)
1070{
2e0c2c73 1071 struct inode *dat = NULL;
17c76b01
KS
1072 int level;
1073
1074 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1075 ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
e7c274f8 1076 if (NILFS_BMAP_USE_VBN(btree)) {
dc935be2 1077 nilfs_bmap_set_target_v(btree, key, ptr);
e7c274f8 1078 dat = nilfs_bmap_get_dat(btree);
2e0c2c73 1079 }
17c76b01
KS
1080
1081 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
e7c274f8 1082 nilfs_bmap_commit_alloc_ptr(btree,
2e0c2c73 1083 &path[level - 1].bp_newreq, dat);
8acfbf09 1084 path[level].bp_op(btree, path, level, &key, &ptr);
17c76b01
KS
1085 }
1086
e7c274f8
RK
1087 if (!nilfs_bmap_dirty(btree))
1088 nilfs_bmap_set_dirty(btree);
17c76b01
KS
1089}
1090
e7c274f8 1091static int nilfs_btree_insert(struct nilfs_bmap *btree, __u64 key, __u64 ptr)
17c76b01 1092{
17c76b01
KS
1093 struct nilfs_btree_path *path;
1094 struct nilfs_bmap_stats stats;
1095 int level, ret;
1096
6d28f7ea 1097 path = nilfs_btree_alloc_path();
17c76b01
KS
1098 if (path == NULL)
1099 return -ENOMEM;
17c76b01
KS
1100
1101 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1102 NILFS_BTREE_LEVEL_NODE_MIN);
1103 if (ret != -ENOENT) {
1104 if (ret == 0)
1105 ret = -EEXIST;
1106 goto out;
1107 }
1108
1109 ret = nilfs_btree_prepare_insert(btree, path, &level, key, ptr, &stats);
1110 if (ret < 0)
1111 goto out;
1112 nilfs_btree_commit_insert(btree, path, level, key, ptr);
e7c274f8 1113 nilfs_bmap_add_blocks(btree, stats.bs_nblocks);
17c76b01
KS
1114
1115 out:
6d28f7ea 1116 nilfs_btree_free_path(path);
17c76b01
KS
1117 return ret;
1118}
1119
e7c274f8 1120static void nilfs_btree_do_delete(struct nilfs_bmap *btree,
17c76b01
KS
1121 struct nilfs_btree_path *path,
1122 int level, __u64 *keyp, __u64 *ptrp)
1123{
1124 struct nilfs_btree_node *node;
1125
1126 if (level < nilfs_btree_height(btree) - 1) {
6d28f7ea 1127 node = nilfs_btree_get_nonroot_node(path, level);
17c76b01
KS
1128 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1129 path[level].bp_index);
1130 if (!buffer_dirty(path[level].bp_bh))
1131 nilfs_btnode_mark_dirty(path[level].bp_bh);
17c76b01
KS
1132 if (path[level].bp_index == 0)
1133 nilfs_btree_promote_key(btree, path, level + 1,
6d28f7ea 1134 nilfs_btree_node_get_key(node, 0));
17c76b01
KS
1135 } else {
1136 node = nilfs_btree_get_root(btree);
1137 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1138 path[level].bp_index);
1139 }
1140}
1141
e7c274f8 1142static void nilfs_btree_borrow_left(struct nilfs_bmap *btree,
17c76b01
KS
1143 struct nilfs_btree_path *path,
1144 int level, __u64 *keyp, __u64 *ptrp)
1145{
1146 struct nilfs_btree_node *node, *left;
1147 int nchildren, lnchildren, n;
1148
1149 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1150
6d28f7ea
RK
1151 node = nilfs_btree_get_nonroot_node(path, level);
1152 left = nilfs_btree_get_sib_node(path, level);
1153 nchildren = nilfs_btree_node_get_nchildren(node);
1154 lnchildren = nilfs_btree_node_get_nchildren(left);
17c76b01
KS
1155
1156 n = (nchildren + lnchildren) / 2 - nchildren;
1157
1158 nilfs_btree_node_move_right(btree, left, node, n);
1159
1160 if (!buffer_dirty(path[level].bp_bh))
1161 nilfs_btnode_mark_dirty(path[level].bp_bh);
1162 if (!buffer_dirty(path[level].bp_sib_bh))
1163 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1164
17c76b01 1165 nilfs_btree_promote_key(btree, path, level + 1,
6d28f7ea 1166 nilfs_btree_node_get_key(node, 0));
17c76b01 1167
087d01b4 1168 brelse(path[level].bp_sib_bh);
17c76b01
KS
1169 path[level].bp_sib_bh = NULL;
1170 path[level].bp_index += n;
1171}
1172
e7c274f8 1173static void nilfs_btree_borrow_right(struct nilfs_bmap *btree,
17c76b01
KS
1174 struct nilfs_btree_path *path,
1175 int level, __u64 *keyp, __u64 *ptrp)
1176{
1177 struct nilfs_btree_node *node, *right;
1178 int nchildren, rnchildren, n;
1179
1180 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1181
6d28f7ea
RK
1182 node = nilfs_btree_get_nonroot_node(path, level);
1183 right = nilfs_btree_get_sib_node(path, level);
1184 nchildren = nilfs_btree_node_get_nchildren(node);
1185 rnchildren = nilfs_btree_node_get_nchildren(right);
17c76b01
KS
1186
1187 n = (nchildren + rnchildren) / 2 - nchildren;
1188
1189 nilfs_btree_node_move_left(btree, node, right, n);
1190
1191 if (!buffer_dirty(path[level].bp_bh))
1192 nilfs_btnode_mark_dirty(path[level].bp_bh);
1193 if (!buffer_dirty(path[level].bp_sib_bh))
1194 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1195
17c76b01
KS
1196 path[level + 1].bp_index++;
1197 nilfs_btree_promote_key(btree, path, level + 1,
6d28f7ea 1198 nilfs_btree_node_get_key(right, 0));
17c76b01
KS
1199 path[level + 1].bp_index--;
1200
087d01b4 1201 brelse(path[level].bp_sib_bh);
17c76b01
KS
1202 path[level].bp_sib_bh = NULL;
1203}
1204
e7c274f8 1205static void nilfs_btree_concat_left(struct nilfs_bmap *btree,
17c76b01
KS
1206 struct nilfs_btree_path *path,
1207 int level, __u64 *keyp, __u64 *ptrp)
1208{
1209 struct nilfs_btree_node *node, *left;
1210 int n;
1211
1212 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1213
6d28f7ea
RK
1214 node = nilfs_btree_get_nonroot_node(path, level);
1215 left = nilfs_btree_get_sib_node(path, level);
17c76b01 1216
6d28f7ea 1217 n = nilfs_btree_node_get_nchildren(node);
17c76b01
KS
1218
1219 nilfs_btree_node_move_left(btree, left, node, n);
1220
1221 if (!buffer_dirty(path[level].bp_sib_bh))
1222 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1223
9f098900 1224 nilfs_btnode_delete(path[level].bp_bh);
17c76b01
KS
1225 path[level].bp_bh = path[level].bp_sib_bh;
1226 path[level].bp_sib_bh = NULL;
6d28f7ea 1227 path[level].bp_index += nilfs_btree_node_get_nchildren(left);
17c76b01
KS
1228}
1229
e7c274f8 1230static void nilfs_btree_concat_right(struct nilfs_bmap *btree,
17c76b01
KS
1231 struct nilfs_btree_path *path,
1232 int level, __u64 *keyp, __u64 *ptrp)
1233{
1234 struct nilfs_btree_node *node, *right;
1235 int n;
1236
1237 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1238
6d28f7ea
RK
1239 node = nilfs_btree_get_nonroot_node(path, level);
1240 right = nilfs_btree_get_sib_node(path, level);
17c76b01 1241
6d28f7ea 1242 n = nilfs_btree_node_get_nchildren(right);
17c76b01
KS
1243
1244 nilfs_btree_node_move_left(btree, node, right, n);
1245
1246 if (!buffer_dirty(path[level].bp_bh))
1247 nilfs_btnode_mark_dirty(path[level].bp_bh);
1248
9f098900 1249 nilfs_btnode_delete(path[level].bp_sib_bh);
17c76b01
KS
1250 path[level].bp_sib_bh = NULL;
1251 path[level + 1].bp_index++;
1252}
1253
e7c274f8 1254static void nilfs_btree_shrink(struct nilfs_bmap *btree,
17c76b01
KS
1255 struct nilfs_btree_path *path,
1256 int level, __u64 *keyp, __u64 *ptrp)
1257{
1258 struct nilfs_btree_node *root, *child;
1259 int n;
1260
1261 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1262
17c76b01 1263 root = nilfs_btree_get_root(btree);
6d28f7ea 1264 child = nilfs_btree_get_nonroot_node(path, level);
17c76b01
KS
1265
1266 nilfs_btree_node_delete(btree, root, NULL, NULL, 0);
6d28f7ea
RK
1267 nilfs_btree_node_set_level(root, level);
1268 n = nilfs_btree_node_get_nchildren(child);
17c76b01 1269 nilfs_btree_node_move_left(btree, root, child, n);
17c76b01 1270
9f098900 1271 nilfs_btnode_delete(path[level].bp_bh);
17c76b01
KS
1272 path[level].bp_bh = NULL;
1273}
1274
1275
e7c274f8 1276static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree,
17c76b01
KS
1277 struct nilfs_btree_path *path,
1278 int *levelp,
2e0c2c73
RK
1279 struct nilfs_bmap_stats *stats,
1280 struct inode *dat)
17c76b01
KS
1281{
1282 struct buffer_head *bh;
1283 struct nilfs_btree_node *node, *parent, *sib;
1284 __u64 sibptr;
ea64ab87 1285 int pindex, level, ncmin, ret;
17c76b01
KS
1286
1287 ret = 0;
1288 stats->bs_nblocks = 0;
ea64ab87
RK
1289 ncmin = NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree));
1290
17c76b01
KS
1291 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1292 level < nilfs_btree_height(btree) - 1;
1293 level++) {
6d28f7ea 1294 node = nilfs_btree_get_nonroot_node(path, level);
17c76b01
KS
1295 path[level].bp_oldreq.bpr_ptr =
1296 nilfs_btree_node_get_ptr(btree, node,
1297 path[level].bp_index);
e7c274f8 1298 ret = nilfs_bmap_prepare_end_ptr(btree,
2e0c2c73 1299 &path[level].bp_oldreq, dat);
d4b96157
RK
1300 if (ret < 0)
1301 goto err_out_child_node;
17c76b01 1302
ea64ab87 1303 if (nilfs_btree_node_get_nchildren(node) > ncmin) {
17c76b01
KS
1304 path[level].bp_op = nilfs_btree_do_delete;
1305 stats->bs_nblocks++;
1306 goto out;
1307 }
1308
1309 parent = nilfs_btree_get_node(btree, path, level + 1);
1310 pindex = path[level + 1].bp_index;
1311
1312 if (pindex > 0) {
1313 /* left sibling */
1314 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1315 pindex - 1);
f198dbb9 1316 ret = nilfs_btree_get_block(btree, sibptr, &bh);
17c76b01
KS
1317 if (ret < 0)
1318 goto err_out_curr_node;
1319 sib = (struct nilfs_btree_node *)bh->b_data;
ea64ab87 1320 if (nilfs_btree_node_get_nchildren(sib) > ncmin) {
17c76b01
KS
1321 path[level].bp_sib_bh = bh;
1322 path[level].bp_op = nilfs_btree_borrow_left;
1323 stats->bs_nblocks++;
1324 goto out;
1325 } else {
1326 path[level].bp_sib_bh = bh;
1327 path[level].bp_op = nilfs_btree_concat_left;
1328 stats->bs_nblocks++;
1329 /* continue; */
1330 }
1331 } else if (pindex <
6d28f7ea 1332 nilfs_btree_node_get_nchildren(parent) - 1) {
17c76b01
KS
1333 /* right sibling */
1334 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1335 pindex + 1);
f198dbb9 1336 ret = nilfs_btree_get_block(btree, sibptr, &bh);
17c76b01
KS
1337 if (ret < 0)
1338 goto err_out_curr_node;
1339 sib = (struct nilfs_btree_node *)bh->b_data;
ea64ab87 1340 if (nilfs_btree_node_get_nchildren(sib) > ncmin) {
17c76b01
KS
1341 path[level].bp_sib_bh = bh;
1342 path[level].bp_op = nilfs_btree_borrow_right;
1343 stats->bs_nblocks++;
1344 goto out;
1345 } else {
1346 path[level].bp_sib_bh = bh;
1347 path[level].bp_op = nilfs_btree_concat_right;
1348 stats->bs_nblocks++;
1349 /* continue; */
1350 }
1351 } else {
1352 /* no siblings */
1353 /* the only child of the root node */
1f5abe7e 1354 WARN_ON(level != nilfs_btree_height(btree) - 2);
6d28f7ea 1355 if (nilfs_btree_node_get_nchildren(node) - 1 <=
17c76b01
KS
1356 NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1357 path[level].bp_op = nilfs_btree_shrink;
1358 stats->bs_nblocks += 2;
1359 } else {
1360 path[level].bp_op = nilfs_btree_do_delete;
1361 stats->bs_nblocks++;
1362 }
1363
1364 goto out;
1365
1366 }
1367 }
1368
1369 node = nilfs_btree_get_root(btree);
1370 path[level].bp_oldreq.bpr_ptr =
1371 nilfs_btree_node_get_ptr(btree, node, path[level].bp_index);
d4b96157 1372
e7c274f8 1373 ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat);
d4b96157
RK
1374 if (ret < 0)
1375 goto err_out_child_node;
1376
17c76b01
KS
1377 /* child of the root node is deleted */
1378 path[level].bp_op = nilfs_btree_do_delete;
1379 stats->bs_nblocks++;
1380
1381 /* success */
1382 out:
1383 *levelp = level;
1384 return ret;
1385
1386 /* error */
1387 err_out_curr_node:
e7c274f8 1388 nilfs_bmap_abort_end_ptr(btree, &path[level].bp_oldreq, dat);
17c76b01
KS
1389 err_out_child_node:
1390 for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
087d01b4 1391 brelse(path[level].bp_sib_bh);
e7c274f8 1392 nilfs_bmap_abort_end_ptr(btree, &path[level].bp_oldreq, dat);
17c76b01
KS
1393 }
1394 *levelp = level;
1395 stats->bs_nblocks = 0;
1396 return ret;
1397}
1398
e7c274f8 1399static void nilfs_btree_commit_delete(struct nilfs_bmap *btree,
17c76b01 1400 struct nilfs_btree_path *path,
2e0c2c73 1401 int maxlevel, struct inode *dat)
17c76b01
KS
1402{
1403 int level;
1404
1405 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
e7c274f8 1406 nilfs_bmap_commit_end_ptr(btree, &path[level].bp_oldreq, dat);
8acfbf09 1407 path[level].bp_op(btree, path, level, NULL, NULL);
17c76b01
KS
1408 }
1409
e7c274f8
RK
1410 if (!nilfs_bmap_dirty(btree))
1411 nilfs_bmap_set_dirty(btree);
17c76b01
KS
1412}
1413
e7c274f8 1414static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key)
17c76b01
KS
1415
1416{
17c76b01
KS
1417 struct nilfs_btree_path *path;
1418 struct nilfs_bmap_stats stats;
2e0c2c73 1419 struct inode *dat;
17c76b01
KS
1420 int level, ret;
1421
6d28f7ea 1422 path = nilfs_btree_alloc_path();
17c76b01
KS
1423 if (path == NULL)
1424 return -ENOMEM;
f905440f 1425
17c76b01
KS
1426 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1427 NILFS_BTREE_LEVEL_NODE_MIN);
1428 if (ret < 0)
1429 goto out;
1430
2e0c2c73 1431
e7c274f8 1432 dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL;
2e0c2c73
RK
1433
1434 ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat);
17c76b01
KS
1435 if (ret < 0)
1436 goto out;
2e0c2c73 1437 nilfs_btree_commit_delete(btree, path, level, dat);
e7c274f8 1438 nilfs_bmap_sub_blocks(btree, stats.bs_nblocks);
17c76b01
KS
1439
1440out:
6d28f7ea 1441 nilfs_btree_free_path(path);
17c76b01
KS
1442 return ret;
1443}
1444
e7c274f8 1445static int nilfs_btree_last_key(const struct nilfs_bmap *btree, __u64 *keyp)
17c76b01 1446{
17c76b01
KS
1447 struct nilfs_btree_path *path;
1448 int ret;
1449
6d28f7ea 1450 path = nilfs_btree_alloc_path();
17c76b01
KS
1451 if (path == NULL)
1452 return -ENOMEM;
17c76b01
KS
1453
1454 ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL);
1455
6d28f7ea 1456 nilfs_btree_free_path(path);
17c76b01
KS
1457
1458 return ret;
1459}
1460
e7c274f8 1461static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key)
17c76b01
KS
1462{
1463 struct buffer_head *bh;
17c76b01
KS
1464 struct nilfs_btree_node *root, *node;
1465 __u64 maxkey, nextmaxkey;
1466 __u64 ptr;
1467 int nchildren, ret;
1468
17c76b01
KS
1469 root = nilfs_btree_get_root(btree);
1470 switch (nilfs_btree_height(btree)) {
1471 case 2:
1472 bh = NULL;
1473 node = root;
1474 break;
1475 case 3:
6d28f7ea 1476 nchildren = nilfs_btree_node_get_nchildren(root);
17c76b01
KS
1477 if (nchildren > 1)
1478 return 0;
1479 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
f198dbb9 1480 ret = nilfs_btree_get_block(btree, ptr, &bh);
17c76b01
KS
1481 if (ret < 0)
1482 return ret;
1483 node = (struct nilfs_btree_node *)bh->b_data;
1484 break;
1485 default:
1486 return 0;
1487 }
1488
6d28f7ea
RK
1489 nchildren = nilfs_btree_node_get_nchildren(node);
1490 maxkey = nilfs_btree_node_get_key(node, nchildren - 1);
17c76b01 1491 nextmaxkey = (nchildren > 1) ?
6d28f7ea 1492 nilfs_btree_node_get_key(node, nchildren - 2) : 0;
17c76b01 1493 if (bh != NULL)
087d01b4 1494 brelse(bh);
17c76b01 1495
3033342a 1496 return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
17c76b01
KS
1497}
1498
e7c274f8 1499static int nilfs_btree_gather_data(struct nilfs_bmap *btree,
17c76b01
KS
1500 __u64 *keys, __u64 *ptrs, int nitems)
1501{
1502 struct buffer_head *bh;
17c76b01
KS
1503 struct nilfs_btree_node *node, *root;
1504 __le64 *dkeys;
1505 __le64 *dptrs;
1506 __u64 ptr;
1507 int nchildren, i, ret;
1508
17c76b01
KS
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:
6d28f7ea 1516 nchildren = nilfs_btree_node_get_nchildren(root);
1f5abe7e 1517 WARN_ON(nchildren > 1);
17c76b01 1518 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
f198dbb9 1519 ret = nilfs_btree_get_block(btree, ptr, &bh);
17c76b01
KS
1520 if (ret < 0)
1521 return ret;
1522 node = (struct nilfs_btree_node *)bh->b_data;
1523 break;
1524 default:
1525 node = NULL;
1f5abe7e 1526 return -EINVAL;
17c76b01
KS
1527 }
1528
6d28f7ea 1529 nchildren = nilfs_btree_node_get_nchildren(node);
17c76b01
KS
1530 if (nchildren < nitems)
1531 nitems = nchildren;
6d28f7ea
RK
1532 dkeys = nilfs_btree_node_dkeys(node);
1533 dptrs = nilfs_btree_node_dptrs(node, btree);
17c76b01 1534 for (i = 0; i < nitems; i++) {
25b8d7de
RK
1535 keys[i] = le64_to_cpu(dkeys[i]);
1536 ptrs[i] = le64_to_cpu(dptrs[i]);
17c76b01
KS
1537 }
1538
1539 if (bh != NULL)
087d01b4 1540 brelse(bh);
17c76b01
KS
1541
1542 return nitems;
1543}
1544
1545static int
e7c274f8 1546nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *btree, __u64 key,
17c76b01
KS
1547 union nilfs_bmap_ptr_req *dreq,
1548 union nilfs_bmap_ptr_req *nreq,
1549 struct buffer_head **bhp,
1550 struct nilfs_bmap_stats *stats)
1551{
1552 struct buffer_head *bh;
2e0c2c73 1553 struct inode *dat = NULL;
17c76b01
KS
1554 int ret;
1555
17c76b01
KS
1556 stats->bs_nblocks = 0;
1557
1558 /* for data */
1559 /* cannot find near ptr */
e7c274f8 1560 if (NILFS_BMAP_USE_VBN(btree)) {
7cde31d7 1561 dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
e7c274f8 1562 dat = nilfs_bmap_get_dat(btree);
2e0c2c73 1563 }
7cde31d7 1564
e7c274f8 1565 ret = nilfs_bmap_prepare_alloc_ptr(btree, dreq, dat);
17c76b01
KS
1566 if (ret < 0)
1567 return ret;
1568
1569 *bhp = NULL;
1570 stats->bs_nblocks++;
1571 if (nreq != NULL) {
1572 nreq->bpr_ptr = dreq->bpr_ptr + 1;
e7c274f8 1573 ret = nilfs_bmap_prepare_alloc_ptr(btree, nreq, dat);
17c76b01
KS
1574 if (ret < 0)
1575 goto err_out_dreq;
1576
f198dbb9 1577 ret = nilfs_btree_get_new_block(btree, nreq->bpr_ptr, &bh);
17c76b01
KS
1578 if (ret < 0)
1579 goto err_out_nreq;
1580
1581 *bhp = bh;
1582 stats->bs_nblocks++;
1583 }
1584
1585 /* success */
1586 return 0;
1587
1588 /* error */
1589 err_out_nreq:
e7c274f8 1590 nilfs_bmap_abort_alloc_ptr(btree, nreq, dat);
17c76b01 1591 err_out_dreq:
e7c274f8 1592 nilfs_bmap_abort_alloc_ptr(btree, dreq, dat);
17c76b01
KS
1593 stats->bs_nblocks = 0;
1594 return ret;
1595
1596}
1597
1598static void
e7c274f8 1599nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *btree,
17c76b01
KS
1600 __u64 key, __u64 ptr,
1601 const __u64 *keys, const __u64 *ptrs,
3033342a 1602 int n,
17c76b01
KS
1603 union nilfs_bmap_ptr_req *dreq,
1604 union nilfs_bmap_ptr_req *nreq,
1605 struct buffer_head *bh)
1606{
17c76b01 1607 struct nilfs_btree_node *node;
2e0c2c73 1608 struct inode *dat;
17c76b01
KS
1609 __u64 tmpptr;
1610
1611 /* free resources */
e7c274f8
RK
1612 if (btree->b_ops->bop_clear != NULL)
1613 btree->b_ops->bop_clear(btree);
17c76b01
KS
1614
1615 /* ptr must be a pointer to a buffer head. */
1616 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1617
1618 /* convert and insert */
e7c274f8
RK
1619 dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL;
1620 nilfs_btree_init(btree);
17c76b01 1621 if (nreq != NULL) {
e7c274f8
RK
1622 nilfs_bmap_commit_alloc_ptr(btree, dreq, dat);
1623 nilfs_bmap_commit_alloc_ptr(btree, nreq, dat);
17c76b01
KS
1624
1625 /* create child node at level 1 */
17c76b01
KS
1626 node = (struct nilfs_btree_node *)bh->b_data;
1627 nilfs_btree_node_init(btree, node, 0, 1, n, keys, ptrs);
e7c274f8 1628 nilfs_btree_node_insert(btree, node, key, dreq->bpr_ptr, n);
17c76b01
KS
1629 if (!buffer_dirty(bh))
1630 nilfs_btnode_mark_dirty(bh);
e7c274f8
RK
1631 if (!nilfs_bmap_dirty(btree))
1632 nilfs_bmap_set_dirty(btree);
17c76b01 1633
087d01b4 1634 brelse(bh);
17c76b01
KS
1635
1636 /* create root node at level 2 */
1637 node = nilfs_btree_get_root(btree);
1638 tmpptr = nreq->bpr_ptr;
1639 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1640 2, 1, &keys[0], &tmpptr);
1641 } else {
e7c274f8 1642 nilfs_bmap_commit_alloc_ptr(btree, dreq, dat);
17c76b01
KS
1643
1644 /* create root node at level 1 */
1645 node = nilfs_btree_get_root(btree);
1646 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1647 1, n, keys, ptrs);
e7c274f8
RK
1648 nilfs_btree_node_insert(btree, node, key, dreq->bpr_ptr, n);
1649 if (!nilfs_bmap_dirty(btree))
1650 nilfs_bmap_set_dirty(btree);
17c76b01
KS
1651 }
1652
e7c274f8 1653 if (NILFS_BMAP_USE_VBN(btree))
dc935be2 1654 nilfs_bmap_set_target_v(btree, key, dreq->bpr_ptr);
17c76b01
KS
1655}
1656
1657/**
1658 * nilfs_btree_convert_and_insert -
1659 * @bmap:
1660 * @key:
1661 * @ptr:
1662 * @keys:
1663 * @ptrs:
1664 * @n:
17c76b01 1665 */
e7c274f8 1666int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree,
17c76b01 1667 __u64 key, __u64 ptr,
3033342a 1668 const __u64 *keys, const __u64 *ptrs, int n)
17c76b01
KS
1669{
1670 struct buffer_head *bh;
1671 union nilfs_bmap_ptr_req dreq, nreq, *di, *ni;
1672 struct nilfs_bmap_stats stats;
1673 int ret;
1674
1675 if (n + 1 <= NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1676 di = &dreq;
1677 ni = NULL;
1678 } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX(
e7c274f8 1679 1 << btree->b_inode->i_blkbits)) {
17c76b01
KS
1680 di = &dreq;
1681 ni = &nreq;
1682 } else {
1683 di = NULL;
1684 ni = NULL;
1685 BUG();
1686 }
1687
e7c274f8 1688 ret = nilfs_btree_prepare_convert_and_insert(btree, key, di, ni, &bh,
17c76b01
KS
1689 &stats);
1690 if (ret < 0)
1691 return ret;
e7c274f8 1692 nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n,
3033342a 1693 di, ni, bh);
e7c274f8 1694 nilfs_bmap_add_blocks(btree, stats.bs_nblocks);
17c76b01
KS
1695 return 0;
1696}
1697
e7c274f8 1698static int nilfs_btree_propagate_p(struct nilfs_bmap *btree,
17c76b01
KS
1699 struct nilfs_btree_path *path,
1700 int level,
1701 struct buffer_head *bh)
1702{
1703 while ((++level < nilfs_btree_height(btree) - 1) &&
1704 !buffer_dirty(path[level].bp_bh))
1705 nilfs_btnode_mark_dirty(path[level].bp_bh);
1706
1707 return 0;
1708}
1709
e7c274f8 1710static int nilfs_btree_prepare_update_v(struct nilfs_bmap *btree,
17c76b01 1711 struct nilfs_btree_path *path,
2e0c2c73 1712 int level, struct inode *dat)
17c76b01
KS
1713{
1714 struct nilfs_btree_node *parent;
1715 int ret;
1716
1717 parent = nilfs_btree_get_node(btree, path, level + 1);
1718 path[level].bp_oldreq.bpr_ptr =
1719 nilfs_btree_node_get_ptr(btree, parent,
1720 path[level + 1].bp_index);
1721 path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
2e0c2c73
RK
1722 ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req,
1723 &path[level].bp_newreq.bpr_req);
17c76b01
KS
1724 if (ret < 0)
1725 return ret;
1726
1727 if (buffer_nilfs_node(path[level].bp_bh)) {
1728 path[level].bp_ctxt.oldkey = path[level].bp_oldreq.bpr_ptr;
1729 path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr;
1730 path[level].bp_ctxt.bh = path[level].bp_bh;
1731 ret = nilfs_btnode_prepare_change_key(
e7c274f8 1732 &NILFS_BMAP_I(btree)->i_btnode_cache,
17c76b01
KS
1733 &path[level].bp_ctxt);
1734 if (ret < 0) {
2e0c2c73
RK
1735 nilfs_dat_abort_update(dat,
1736 &path[level].bp_oldreq.bpr_req,
1737 &path[level].bp_newreq.bpr_req);
17c76b01
KS
1738 return ret;
1739 }
1740 }
1741
1742 return 0;
1743}
1744
e7c274f8 1745static void nilfs_btree_commit_update_v(struct nilfs_bmap *btree,
17c76b01 1746 struct nilfs_btree_path *path,
2e0c2c73 1747 int level, struct inode *dat)
17c76b01
KS
1748{
1749 struct nilfs_btree_node *parent;
1750
2e0c2c73
RK
1751 nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req,
1752 &path[level].bp_newreq.bpr_req,
e7c274f8 1753 btree->b_ptr_type == NILFS_BMAP_PTR_VS);
17c76b01
KS
1754
1755 if (buffer_nilfs_node(path[level].bp_bh)) {
1756 nilfs_btnode_commit_change_key(
e7c274f8 1757 &NILFS_BMAP_I(btree)->i_btnode_cache,
17c76b01
KS
1758 &path[level].bp_ctxt);
1759 path[level].bp_bh = path[level].bp_ctxt.bh;
1760 }
1761 set_buffer_nilfs_volatile(path[level].bp_bh);
1762
1763 parent = nilfs_btree_get_node(btree, path, level + 1);
1764 nilfs_btree_node_set_ptr(btree, parent, path[level + 1].bp_index,
1765 path[level].bp_newreq.bpr_ptr);
1766}
1767
e7c274f8 1768static void nilfs_btree_abort_update_v(struct nilfs_bmap *btree,
17c76b01 1769 struct nilfs_btree_path *path,
2e0c2c73 1770 int level, struct inode *dat)
17c76b01 1771{
2e0c2c73
RK
1772 nilfs_dat_abort_update(dat, &path[level].bp_oldreq.bpr_req,
1773 &path[level].bp_newreq.bpr_req);
17c76b01
KS
1774 if (buffer_nilfs_node(path[level].bp_bh))
1775 nilfs_btnode_abort_change_key(
e7c274f8 1776 &NILFS_BMAP_I(btree)->i_btnode_cache,
17c76b01
KS
1777 &path[level].bp_ctxt);
1778}
1779
e7c274f8 1780static int nilfs_btree_prepare_propagate_v(struct nilfs_bmap *btree,
17c76b01 1781 struct nilfs_btree_path *path,
2e0c2c73
RK
1782 int minlevel, int *maxlevelp,
1783 struct inode *dat)
17c76b01
KS
1784{
1785 int level, ret;
1786
1787 level = minlevel;
1788 if (!buffer_nilfs_volatile(path[level].bp_bh)) {
2e0c2c73 1789 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
17c76b01
KS
1790 if (ret < 0)
1791 return ret;
1792 }
1793 while ((++level < nilfs_btree_height(btree) - 1) &&
1794 !buffer_dirty(path[level].bp_bh)) {
1795
1f5abe7e 1796 WARN_ON(buffer_nilfs_volatile(path[level].bp_bh));
2e0c2c73 1797 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
17c76b01
KS
1798 if (ret < 0)
1799 goto out;
1800 }
1801
1802 /* success */
17c76b01
KS
1803 *maxlevelp = level - 1;
1804 return 0;
1805
1806 /* error */
1807 out:
1808 while (--level > minlevel)
2e0c2c73 1809 nilfs_btree_abort_update_v(btree, path, level, dat);
17c76b01 1810 if (!buffer_nilfs_volatile(path[level].bp_bh))
2e0c2c73 1811 nilfs_btree_abort_update_v(btree, path, level, dat);
17c76b01
KS
1812 return ret;
1813}
1814
e7c274f8 1815static void nilfs_btree_commit_propagate_v(struct nilfs_bmap *btree,
17c76b01 1816 struct nilfs_btree_path *path,
2e0c2c73
RK
1817 int minlevel, int maxlevel,
1818 struct buffer_head *bh,
1819 struct inode *dat)
17c76b01
KS
1820{
1821 int level;
1822
1823 if (!buffer_nilfs_volatile(path[minlevel].bp_bh))
2e0c2c73 1824 nilfs_btree_commit_update_v(btree, path, minlevel, dat);
17c76b01
KS
1825
1826 for (level = minlevel + 1; level <= maxlevel; level++)
2e0c2c73 1827 nilfs_btree_commit_update_v(btree, path, level, dat);
17c76b01
KS
1828}
1829
e7c274f8 1830static int nilfs_btree_propagate_v(struct nilfs_bmap *btree,
17c76b01 1831 struct nilfs_btree_path *path,
2e0c2c73 1832 int level, struct buffer_head *bh)
17c76b01 1833{
308f4419 1834 int maxlevel = 0, ret;
17c76b01 1835 struct nilfs_btree_node *parent;
e7c274f8 1836 struct inode *dat = nilfs_bmap_get_dat(btree);
17c76b01
KS
1837 __u64 ptr;
1838
1839 get_bh(bh);
1840 path[level].bp_bh = bh;
2e0c2c73
RK
1841 ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel,
1842 dat);
17c76b01
KS
1843 if (ret < 0)
1844 goto out;
1845
1846 if (buffer_nilfs_volatile(path[level].bp_bh)) {
1847 parent = nilfs_btree_get_node(btree, path, level + 1);
1848 ptr = nilfs_btree_node_get_ptr(btree, parent,
1849 path[level + 1].bp_index);
2e0c2c73 1850 ret = nilfs_dat_mark_dirty(dat, ptr);
17c76b01
KS
1851 if (ret < 0)
1852 goto out;
1853 }
1854
2e0c2c73 1855 nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh, dat);
17c76b01
KS
1856
1857 out:
1858 brelse(path[level].bp_bh);
1859 path[level].bp_bh = NULL;
1860 return ret;
1861}
1862
e7c274f8 1863static int nilfs_btree_propagate(struct nilfs_bmap *btree,
17c76b01
KS
1864 struct buffer_head *bh)
1865{
17c76b01
KS
1866 struct nilfs_btree_path *path;
1867 struct nilfs_btree_node *node;
1868 __u64 key;
1869 int level, ret;
1870
1f5abe7e 1871 WARN_ON(!buffer_dirty(bh));
17c76b01 1872
6d28f7ea 1873 path = nilfs_btree_alloc_path();
17c76b01
KS
1874 if (path == NULL)
1875 return -ENOMEM;
17c76b01
KS
1876
1877 if (buffer_nilfs_node(bh)) {
1878 node = (struct nilfs_btree_node *)bh->b_data;
6d28f7ea
RK
1879 key = nilfs_btree_node_get_key(node, 0);
1880 level = nilfs_btree_node_get_level(node);
17c76b01 1881 } else {
e7c274f8 1882 key = nilfs_bmap_data_get_key(btree, bh);
17c76b01
KS
1883 level = NILFS_BTREE_LEVEL_DATA;
1884 }
1885
1886 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
1887 if (ret < 0) {
1f5abe7e 1888 if (unlikely(ret == -ENOENT))
17c76b01
KS
1889 printk(KERN_CRIT "%s: key = %llu, level == %d\n",
1890 __func__, (unsigned long long)key, level);
17c76b01
KS
1891 goto out;
1892 }
1893
e7c274f8 1894 ret = NILFS_BMAP_USE_VBN(btree) ?
7cde31d7
RK
1895 nilfs_btree_propagate_v(btree, path, level, bh) :
1896 nilfs_btree_propagate_p(btree, path, level, bh);
17c76b01
KS
1897
1898 out:
6d28f7ea 1899 nilfs_btree_free_path(path);
17c76b01
KS
1900
1901 return ret;
1902}
1903
e7c274f8 1904static int nilfs_btree_propagate_gc(struct nilfs_bmap *btree,
17c76b01
KS
1905 struct buffer_head *bh)
1906{
e7c274f8 1907 return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(btree), bh->b_blocknr);
17c76b01
KS
1908}
1909
e7c274f8 1910static void nilfs_btree_add_dirty_buffer(struct nilfs_bmap *btree,
17c76b01
KS
1911 struct list_head *lists,
1912 struct buffer_head *bh)
1913{
1914 struct list_head *head;
1915 struct buffer_head *cbh;
1916 struct nilfs_btree_node *node, *cnode;
1917 __u64 key, ckey;
1918 int level;
1919
1920 get_bh(bh);
1921 node = (struct nilfs_btree_node *)bh->b_data;
6d28f7ea
RK
1922 key = nilfs_btree_node_get_key(node, 0);
1923 level = nilfs_btree_node_get_level(node);
cfa913a5
RK
1924 if (level < NILFS_BTREE_LEVEL_NODE_MIN ||
1925 level >= NILFS_BTREE_LEVEL_MAX) {
1926 dump_stack();
1927 printk(KERN_WARNING
1928 "%s: invalid btree level: %d (key=%llu, ino=%lu, "
1929 "blocknr=%llu)\n",
1930 __func__, level, (unsigned long long)key,
e7c274f8 1931 NILFS_BMAP_I(btree)->vfs_inode.i_ino,
cfa913a5
RK
1932 (unsigned long long)bh->b_blocknr);
1933 return;
1934 }
1935
17c76b01
KS
1936 list_for_each(head, &lists[level]) {
1937 cbh = list_entry(head, struct buffer_head, b_assoc_buffers);
1938 cnode = (struct nilfs_btree_node *)cbh->b_data;
6d28f7ea 1939 ckey = nilfs_btree_node_get_key(cnode, 0);
17c76b01
KS
1940 if (key < ckey)
1941 break;
1942 }
1943 list_add_tail(&bh->b_assoc_buffers, head);
1944}
1945
e7c274f8 1946static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *btree,
17c76b01
KS
1947 struct list_head *listp)
1948{
e7c274f8 1949 struct address_space *btcache = &NILFS_BMAP_I(btree)->i_btnode_cache;
17c76b01
KS
1950 struct list_head lists[NILFS_BTREE_LEVEL_MAX];
1951 struct pagevec pvec;
1952 struct buffer_head *bh, *head;
1953 pgoff_t index = 0;
1954 int level, i;
1955
1956 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1957 level < NILFS_BTREE_LEVEL_MAX;
1958 level++)
1959 INIT_LIST_HEAD(&lists[level]);
1960
1961 pagevec_init(&pvec, 0);
1962
1963 while (pagevec_lookup_tag(&pvec, btcache, &index, PAGECACHE_TAG_DIRTY,
1964 PAGEVEC_SIZE)) {
1965 for (i = 0; i < pagevec_count(&pvec); i++) {
1966 bh = head = page_buffers(pvec.pages[i]);
1967 do {
1968 if (buffer_dirty(bh))
1969 nilfs_btree_add_dirty_buffer(btree,
1970 lists, bh);
1971 } while ((bh = bh->b_this_page) != head);
1972 }
1973 pagevec_release(&pvec);
1974 cond_resched();
1975 }
1976
1977 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1978 level < NILFS_BTREE_LEVEL_MAX;
1979 level++)
0935db74 1980 list_splice_tail(&lists[level], listp);
17c76b01
KS
1981}
1982
e7c274f8 1983static int nilfs_btree_assign_p(struct nilfs_bmap *btree,
17c76b01
KS
1984 struct nilfs_btree_path *path,
1985 int level,
1986 struct buffer_head **bh,
1987 sector_t blocknr,
1988 union nilfs_binfo *binfo)
1989{
1990 struct nilfs_btree_node *parent;
1991 __u64 key;
1992 __u64 ptr;
1993 int ret;
1994
1995 parent = nilfs_btree_get_node(btree, path, level + 1);
1996 ptr = nilfs_btree_node_get_ptr(btree, parent,
1997 path[level + 1].bp_index);
1998 if (buffer_nilfs_node(*bh)) {
1999 path[level].bp_ctxt.oldkey = ptr;
2000 path[level].bp_ctxt.newkey = blocknr;
2001 path[level].bp_ctxt.bh = *bh;
2002 ret = nilfs_btnode_prepare_change_key(
e7c274f8 2003 &NILFS_BMAP_I(btree)->i_btnode_cache,
17c76b01
KS
2004 &path[level].bp_ctxt);
2005 if (ret < 0)
2006 return ret;
2007 nilfs_btnode_commit_change_key(
e7c274f8 2008 &NILFS_BMAP_I(btree)->i_btnode_cache,
17c76b01
KS
2009 &path[level].bp_ctxt);
2010 *bh = path[level].bp_ctxt.bh;
2011 }
2012
2013 nilfs_btree_node_set_ptr(btree, parent,
2014 path[level + 1].bp_index, blocknr);
2015
6d28f7ea 2016 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
17c76b01 2017 /* on-disk format */
25b8d7de 2018 binfo->bi_dat.bi_blkoff = cpu_to_le64(key);
17c76b01
KS
2019 binfo->bi_dat.bi_level = level;
2020
2021 return 0;
2022}
2023
e7c274f8 2024static int nilfs_btree_assign_v(struct nilfs_bmap *btree,
17c76b01
KS
2025 struct nilfs_btree_path *path,
2026 int level,
2027 struct buffer_head **bh,
2028 sector_t blocknr,
2029 union nilfs_binfo *binfo)
2030{
2031 struct nilfs_btree_node *parent;
e7c274f8 2032 struct inode *dat = nilfs_bmap_get_dat(btree);
17c76b01
KS
2033 __u64 key;
2034 __u64 ptr;
2035 union nilfs_bmap_ptr_req req;
2036 int ret;
2037
2038 parent = nilfs_btree_get_node(btree, path, level + 1);
e7c274f8 2039 ptr = nilfs_btree_node_get_ptr(btree, parent, path[level + 1].bp_index);
17c76b01 2040 req.bpr_ptr = ptr;
2e0c2c73
RK
2041 ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
2042 if (ret < 0)
17c76b01 2043 return ret;
2e0c2c73 2044 nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
17c76b01 2045
6d28f7ea 2046 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
17c76b01 2047 /* on-disk format */
25b8d7de
RK
2048 binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr);
2049 binfo->bi_v.bi_blkoff = cpu_to_le64(key);
17c76b01
KS
2050
2051 return 0;
2052}
2053
e7c274f8 2054static int nilfs_btree_assign(struct nilfs_bmap *btree,
17c76b01
KS
2055 struct buffer_head **bh,
2056 sector_t blocknr,
2057 union nilfs_binfo *binfo)
2058{
17c76b01
KS
2059 struct nilfs_btree_path *path;
2060 struct nilfs_btree_node *node;
2061 __u64 key;
2062 int level, ret;
2063
6d28f7ea 2064 path = nilfs_btree_alloc_path();
17c76b01
KS
2065 if (path == NULL)
2066 return -ENOMEM;
17c76b01
KS
2067
2068 if (buffer_nilfs_node(*bh)) {
2069 node = (struct nilfs_btree_node *)(*bh)->b_data;
6d28f7ea
RK
2070 key = nilfs_btree_node_get_key(node, 0);
2071 level = nilfs_btree_node_get_level(node);
17c76b01 2072 } else {
e7c274f8 2073 key = nilfs_bmap_data_get_key(btree, *bh);
17c76b01
KS
2074 level = NILFS_BTREE_LEVEL_DATA;
2075 }
2076
2077 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
2078 if (ret < 0) {
1f5abe7e 2079 WARN_ON(ret == -ENOENT);
17c76b01
KS
2080 goto out;
2081 }
2082
e7c274f8 2083 ret = NILFS_BMAP_USE_VBN(btree) ?
7cde31d7
RK
2084 nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) :
2085 nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
17c76b01
KS
2086
2087 out:
6d28f7ea 2088 nilfs_btree_free_path(path);
17c76b01
KS
2089
2090 return ret;
2091}
2092
e7c274f8 2093static int nilfs_btree_assign_gc(struct nilfs_bmap *btree,
17c76b01
KS
2094 struct buffer_head **bh,
2095 sector_t blocknr,
2096 union nilfs_binfo *binfo)
2097{
17c76b01
KS
2098 struct nilfs_btree_node *node;
2099 __u64 key;
2100 int ret;
2101
e7c274f8 2102 ret = nilfs_dat_move(nilfs_bmap_get_dat(btree), (*bh)->b_blocknr,
2e0c2c73 2103 blocknr);
17c76b01
KS
2104 if (ret < 0)
2105 return ret;
2106
2107 if (buffer_nilfs_node(*bh)) {
2108 node = (struct nilfs_btree_node *)(*bh)->b_data;
6d28f7ea 2109 key = nilfs_btree_node_get_key(node, 0);
17c76b01 2110 } else
e7c274f8 2111 key = nilfs_bmap_data_get_key(btree, *bh);
17c76b01
KS
2112
2113 /* on-disk format */
2114 binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr);
25b8d7de 2115 binfo->bi_v.bi_blkoff = cpu_to_le64(key);
17c76b01
KS
2116
2117 return 0;
2118}
2119
e7c274f8 2120static int nilfs_btree_mark(struct nilfs_bmap *btree, __u64 key, int level)
17c76b01
KS
2121{
2122 struct buffer_head *bh;
17c76b01
KS
2123 struct nilfs_btree_path *path;
2124 __u64 ptr;
2125 int ret;
2126
6d28f7ea 2127 path = nilfs_btree_alloc_path();
17c76b01
KS
2128 if (path == NULL)
2129 return -ENOMEM;
17c76b01
KS
2130
2131 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1);
2132 if (ret < 0) {
1f5abe7e 2133 WARN_ON(ret == -ENOENT);
17c76b01
KS
2134 goto out;
2135 }
f198dbb9 2136 ret = nilfs_btree_get_block(btree, ptr, &bh);
17c76b01 2137 if (ret < 0) {
1f5abe7e 2138 WARN_ON(ret == -ENOENT);
17c76b01
KS
2139 goto out;
2140 }
2141
2142 if (!buffer_dirty(bh))
2143 nilfs_btnode_mark_dirty(bh);
087d01b4 2144 brelse(bh);
e7c274f8
RK
2145 if (!nilfs_bmap_dirty(btree))
2146 nilfs_bmap_set_dirty(btree);
17c76b01
KS
2147
2148 out:
6d28f7ea 2149 nilfs_btree_free_path(path);
17c76b01
KS
2150 return ret;
2151}
2152
2153static const struct nilfs_bmap_operations nilfs_btree_ops = {
2154 .bop_lookup = nilfs_btree_lookup,
c3a7abf0 2155 .bop_lookup_contig = nilfs_btree_lookup_contig,
17c76b01
KS
2156 .bop_insert = nilfs_btree_insert,
2157 .bop_delete = nilfs_btree_delete,
2158 .bop_clear = NULL,
2159
2160 .bop_propagate = nilfs_btree_propagate,
2161
2162 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2163
2164 .bop_assign = nilfs_btree_assign,
2165 .bop_mark = nilfs_btree_mark,
2166
2167 .bop_last_key = nilfs_btree_last_key,
2168 .bop_check_insert = NULL,
2169 .bop_check_delete = nilfs_btree_check_delete,
2170 .bop_gather_data = nilfs_btree_gather_data,
2171};
2172
2173static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
2174 .bop_lookup = NULL,
c3a7abf0 2175 .bop_lookup_contig = NULL,
17c76b01
KS
2176 .bop_insert = NULL,
2177 .bop_delete = NULL,
2178 .bop_clear = NULL,
2179
2180 .bop_propagate = nilfs_btree_propagate_gc,
2181
2182 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2183
2184 .bop_assign = nilfs_btree_assign_gc,
2185 .bop_mark = NULL,
2186
2187 .bop_last_key = NULL,
2188 .bop_check_insert = NULL,
2189 .bop_check_delete = NULL,
2190 .bop_gather_data = NULL,
2191};
2192
3033342a 2193int nilfs_btree_init(struct nilfs_bmap *bmap)
17c76b01 2194{
17c76b01 2195 bmap->b_ops = &nilfs_btree_ops;
17c76b01
KS
2196 return 0;
2197}
2198
2199void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
2200{
17c76b01
KS
2201 bmap->b_ops = &nilfs_btree_ops_gc;
2202}