blob: 6c9ec566d000b4d120c00d4caa32c0252563aeb3 [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
Li Hongf9054402010-04-02 17:36:34 +080034static struct nilfs_btree_path *nilfs_btree_alloc_path(void)
Koji Sato17c76b02009-04-06 19:01:24 -070035{
Li Hongf9054402010-04-02 17:36:34 +080036 struct nilfs_btree_path *path;
37 int level = NILFS_BTREE_LEVEL_DATA;
Koji Sato17c76b02009-04-06 19:01:24 -070038
Li Hongf9054402010-04-02 17:36:34 +080039 path = kmem_cache_alloc(nilfs_btree_path_cache, GFP_NOFS);
40 if (path == NULL)
41 goto out;
Koji Sato17c76b02009-04-06 19:01:24 -070042
Li Hongf9054402010-04-02 17:36:34 +080043 for (; level < NILFS_BTREE_LEVEL_MAX; level++) {
Koji Sato17c76b02009-04-06 19:01:24 -070044 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 }
Li Hongf9054402010-04-02 17:36:34 +080051
52out:
53 return path;
54}
55
Li Hong73bb4882010-04-02 18:35:00 +080056static void nilfs_btree_free_path(struct nilfs_btree_path *path)
Li Hongf9054402010-04-02 17:36:34 +080057{
Li Hong73bb4882010-04-02 18:35:00 +080058 int level = NILFS_BTREE_LEVEL_DATA;
Koji Sato17c76b02009-04-06 19:01:24 -070059
Li Hong73bb4882010-04-02 18:35:00 +080060 for (; level < NILFS_BTREE_LEVEL_MAX; level++)
Ryusuke Konishi32189292009-08-15 01:54:59 +090061 brelse(path[level].bp_bh);
Li Hong73bb4882010-04-02 18:35:00 +080062
63 kmem_cache_free(nilfs_btree_path_cache, path);
Koji Sato17c76b02009-04-06 19:01:24 -070064}
65
Koji Sato17c76b02009-04-06 19:01:24 -070066/*
67 * B-tree node operations
68 */
Ryusuke Konishif198dbb2009-05-22 01:07:13 +090069static int nilfs_btree_get_block(const struct nilfs_btree *btree, __u64 ptr,
70 struct buffer_head **bhp)
71{
72 struct address_space *btnc =
73 &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
Ryusuke Konishi1d5385b2010-07-16 23:52:40 +090074 struct buffer_head *bh;
Ryusuke Konishi1376e932009-11-13 16:49:09 +090075 int err;
76
77 err = nilfs_btnode_submit_block(btnc, ptr, 0, bhp);
78 if (err)
79 return err == -EEXIST ? 0 : err;
80
Ryusuke Konishi1d5385b2010-07-16 23:52:40 +090081 bh = *bhp;
82 wait_on_buffer(bh);
83 if (!buffer_uptodate(bh)) {
84 brelse(bh);
Ryusuke Konishi1376e932009-11-13 16:49:09 +090085 return -EIO;
86 }
Ryusuke Konishi1d5385b2010-07-16 23:52:40 +090087 if (nilfs_btree_broken_node_block(bh)) {
88 clear_buffer_uptodate(bh);
89 brelse(bh);
90 return -EINVAL;
91 }
Ryusuke Konishi1376e932009-11-13 16:49:09 +090092 return 0;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +090093}
94
95static int nilfs_btree_get_new_block(const struct nilfs_btree *btree,
96 __u64 ptr, struct buffer_head **bhp)
97{
98 struct address_space *btnc =
99 &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
Ryusuke Konishi45f49102009-11-13 16:25:19 +0900100 struct buffer_head *bh;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900101
Ryusuke Konishi45f49102009-11-13 16:25:19 +0900102 bh = nilfs_btnode_create_block(btnc, ptr);
103 if (!bh)
104 return -ENOMEM;
105
106 set_buffer_nilfs_volatile(bh);
107 *bhp = bh;
108 return 0;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900109}
Koji Sato17c76b02009-04-06 19:01:24 -0700110
111static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900112nilfs_btree_node_get_flags(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700113{
114 return node->bn_flags;
115}
116
117static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900118nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags)
Koji Sato17c76b02009-04-06 19:01:24 -0700119{
120 node->bn_flags = flags;
121}
122
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900123static inline int nilfs_btree_node_root(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700124{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900125 return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT;
Koji Sato17c76b02009-04-06 19:01:24 -0700126}
127
128static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900129nilfs_btree_node_get_level(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700130{
131 return node->bn_level;
132}
133
134static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900135nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700136{
137 node->bn_level = level;
138}
139
140static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900141nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700142{
143 return le16_to_cpu(node->bn_nchildren);
144}
145
146static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900147nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren)
Koji Sato17c76b02009-04-06 19:01:24 -0700148{
149 node->bn_nchildren = cpu_to_le16(nchildren);
150}
151
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900152static inline int nilfs_btree_node_size(const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700153{
154 return 1 << btree->bt_bmap.b_inode->i_blkbits;
155}
156
157static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900158nilfs_btree_node_nchildren_min(const struct nilfs_btree_node *node,
159 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700160{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900161 return nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700162 NILFS_BTREE_ROOT_NCHILDREN_MIN :
163 NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree));
164}
165
166static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900167nilfs_btree_node_nchildren_max(const struct nilfs_btree_node *node,
168 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700169{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900170 return nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700171 NILFS_BTREE_ROOT_NCHILDREN_MAX :
172 NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree));
173}
174
175static inline __le64 *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900176nilfs_btree_node_dkeys(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700177{
178 return (__le64 *)((char *)(node + 1) +
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900179 (nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700180 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE));
181}
182
183static inline __le64 *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900184nilfs_btree_node_dptrs(const struct nilfs_btree_node *node,
185 const struct nilfs_btree *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700186{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900187 return (__le64 *)(nilfs_btree_node_dkeys(node) +
188 nilfs_btree_node_nchildren_max(node, btree));
Koji Sato17c76b02009-04-06 19:01:24 -0700189}
190
191static inline __u64
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900192nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index)
Koji Sato17c76b02009-04-06 19:01:24 -0700193{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900194 return nilfs_bmap_dkey_to_key(*(nilfs_btree_node_dkeys(node) + index));
Koji Sato17c76b02009-04-06 19:01:24 -0700195}
196
197static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900198nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key)
Koji Sato17c76b02009-04-06 19:01:24 -0700199{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900200 *(nilfs_btree_node_dkeys(node) + index) = nilfs_bmap_key_to_dkey(key);
Koji Sato17c76b02009-04-06 19:01:24 -0700201}
202
203static inline __u64
204nilfs_btree_node_get_ptr(const struct nilfs_btree *btree,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900205 const struct nilfs_btree_node *node, int index)
Koji Sato17c76b02009-04-06 19:01:24 -0700206{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900207 return nilfs_bmap_dptr_to_ptr(*(nilfs_btree_node_dptrs(node, btree) +
Koji Sato17c76b02009-04-06 19:01:24 -0700208 index));
209}
210
211static inline void
212nilfs_btree_node_set_ptr(struct nilfs_btree *btree,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900213 struct nilfs_btree_node *node, int index, __u64 ptr)
Koji Sato17c76b02009-04-06 19:01:24 -0700214{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900215 *(nilfs_btree_node_dptrs(node, btree) + index) =
Koji Sato17c76b02009-04-06 19:01:24 -0700216 nilfs_bmap_ptr_to_dptr(ptr);
217}
218
219static void nilfs_btree_node_init(struct nilfs_btree *btree,
220 struct nilfs_btree_node *node,
221 int flags, int level, int nchildren,
222 const __u64 *keys, const __u64 *ptrs)
223{
224 __le64 *dkeys;
225 __le64 *dptrs;
226 int i;
227
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900228 nilfs_btree_node_set_flags(node, flags);
229 nilfs_btree_node_set_level(node, level);
230 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700231
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900232 dkeys = nilfs_btree_node_dkeys(node);
233 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700234 for (i = 0; i < nchildren; i++) {
235 dkeys[i] = nilfs_bmap_key_to_dkey(keys[i]);
236 dptrs[i] = nilfs_bmap_ptr_to_dptr(ptrs[i]);
237 }
238}
239
240/* Assume the buffer heads corresponding to left and right are locked. */
241static void nilfs_btree_node_move_left(struct nilfs_btree *btree,
242 struct nilfs_btree_node *left,
243 struct nilfs_btree_node *right,
244 int n)
245{
246 __le64 *ldkeys, *rdkeys;
247 __le64 *ldptrs, *rdptrs;
248 int lnchildren, rnchildren;
249
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900250 ldkeys = nilfs_btree_node_dkeys(left);
251 ldptrs = nilfs_btree_node_dptrs(left, btree);
252 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700253
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900254 rdkeys = nilfs_btree_node_dkeys(right);
255 rdptrs = nilfs_btree_node_dptrs(right, btree);
256 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700257
258 memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys));
259 memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs));
260 memmove(rdkeys, rdkeys + n, (rnchildren - n) * sizeof(*rdkeys));
261 memmove(rdptrs, rdptrs + n, (rnchildren - n) * sizeof(*rdptrs));
262
263 lnchildren += n;
264 rnchildren -= n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900265 nilfs_btree_node_set_nchildren(left, lnchildren);
266 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700267}
268
269/* Assume that the buffer heads corresponding to left and right are locked. */
270static void nilfs_btree_node_move_right(struct nilfs_btree *btree,
271 struct nilfs_btree_node *left,
272 struct nilfs_btree_node *right,
273 int n)
274{
275 __le64 *ldkeys, *rdkeys;
276 __le64 *ldptrs, *rdptrs;
277 int lnchildren, rnchildren;
278
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900279 ldkeys = nilfs_btree_node_dkeys(left);
280 ldptrs = nilfs_btree_node_dptrs(left, btree);
281 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700282
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900283 rdkeys = nilfs_btree_node_dkeys(right);
284 rdptrs = nilfs_btree_node_dptrs(right, btree);
285 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700286
287 memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys));
288 memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs));
289 memcpy(rdkeys, ldkeys + lnchildren - n, n * sizeof(*rdkeys));
290 memcpy(rdptrs, ldptrs + lnchildren - n, n * sizeof(*rdptrs));
291
292 lnchildren -= n;
293 rnchildren += n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900294 nilfs_btree_node_set_nchildren(left, lnchildren);
295 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700296}
297
298/* Assume that the buffer head corresponding to node is locked. */
299static void nilfs_btree_node_insert(struct nilfs_btree *btree,
300 struct nilfs_btree_node *node,
301 __u64 key, __u64 ptr, int index)
302{
303 __le64 *dkeys;
304 __le64 *dptrs;
305 int nchildren;
306
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900307 dkeys = nilfs_btree_node_dkeys(node);
308 dptrs = nilfs_btree_node_dptrs(node, btree);
309 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700310 if (index < nchildren) {
311 memmove(dkeys + index + 1, dkeys + index,
312 (nchildren - index) * sizeof(*dkeys));
313 memmove(dptrs + index + 1, dptrs + index,
314 (nchildren - index) * sizeof(*dptrs));
315 }
316 dkeys[index] = nilfs_bmap_key_to_dkey(key);
317 dptrs[index] = nilfs_bmap_ptr_to_dptr(ptr);
318 nchildren++;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900319 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700320}
321
322/* Assume that the buffer head corresponding to node is locked. */
323static void nilfs_btree_node_delete(struct nilfs_btree *btree,
324 struct nilfs_btree_node *node,
325 __u64 *keyp, __u64 *ptrp, int index)
326{
327 __u64 key;
328 __u64 ptr;
329 __le64 *dkeys;
330 __le64 *dptrs;
331 int nchildren;
332
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900333 dkeys = nilfs_btree_node_dkeys(node);
334 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700335 key = nilfs_bmap_dkey_to_key(dkeys[index]);
336 ptr = nilfs_bmap_dptr_to_ptr(dptrs[index]);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900337 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700338 if (keyp != NULL)
339 *keyp = key;
340 if (ptrp != NULL)
341 *ptrp = ptr;
342
343 if (index < nchildren - 1) {
344 memmove(dkeys + index, dkeys + index + 1,
345 (nchildren - index - 1) * sizeof(*dkeys));
346 memmove(dptrs + index, dptrs + index + 1,
347 (nchildren - index - 1) * sizeof(*dptrs));
348 }
349 nchildren--;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900350 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700351}
352
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900353static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node,
Koji Sato17c76b02009-04-06 19:01:24 -0700354 __u64 key, int *indexp)
355{
356 __u64 nkey;
357 int index, low, high, s;
358
359 /* binary search */
360 low = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900361 high = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700362 index = 0;
363 s = 0;
364 while (low <= high) {
365 index = (low + high) / 2;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900366 nkey = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700367 if (nkey == key) {
368 s = 0;
369 goto out;
370 } else if (nkey < key) {
371 low = index + 1;
372 s = -1;
373 } else {
374 high = index - 1;
375 s = 1;
376 }
377 }
378
379 /* adjust index */
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900380 if (nilfs_btree_node_get_level(node) > NILFS_BTREE_LEVEL_NODE_MIN) {
381 if (s > 0 && index > 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700382 index--;
383 } else if (s < 0)
384 index++;
385
386 out:
Koji Sato17c76b02009-04-06 19:01:24 -0700387 *indexp = index;
388
389 return s == 0;
390}
391
Ryusuke Konishi1d5385b2010-07-16 23:52:40 +0900392/**
393 * nilfs_btree_node_broken - verify consistency of btree node
394 * @node: btree node block to be examined
395 * @size: node size (in bytes)
396 * @blocknr: block number
397 *
398 * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned.
399 */
400static int nilfs_btree_node_broken(const struct nilfs_btree_node *node,
401 size_t size, sector_t blocknr)
402{
403 int level, flags, nchildren;
404 int ret = 0;
405
406 level = nilfs_btree_node_get_level(node);
407 flags = nilfs_btree_node_get_flags(node);
408 nchildren = nilfs_btree_node_get_nchildren(node);
409
410 if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
411 level >= NILFS_BTREE_LEVEL_MAX ||
412 (flags & NILFS_BTREE_NODE_ROOT) ||
413 nchildren < 0 ||
414 nchildren > NILFS_BTREE_NODE_NCHILDREN_MAX(size))) {
415 printk(KERN_CRIT "NILFS: bad btree node (blocknr=%llu): "
416 "level = %d, flags = 0x%x, nchildren = %d\n",
417 (unsigned long long)blocknr, level, flags, nchildren);
418 ret = 1;
419 }
420 return ret;
421}
422
423int nilfs_btree_broken_node_block(struct buffer_head *bh)
424{
425 return nilfs_btree_node_broken((struct nilfs_btree_node *)bh->b_data,
426 bh->b_size, bh->b_blocknr);
427}
428
Koji Sato17c76b02009-04-06 19:01:24 -0700429static inline struct nilfs_btree_node *
430nilfs_btree_get_root(const struct nilfs_btree *btree)
431{
432 return (struct nilfs_btree_node *)btree->bt_bmap.b_u.u_data;
433}
434
435static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900436nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700437{
438 return (struct nilfs_btree_node *)path[level].bp_bh->b_data;
439}
440
441static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900442nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700443{
444 return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data;
445}
446
447static inline int nilfs_btree_height(const struct nilfs_btree *btree)
448{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900449 return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700450}
451
452static inline struct nilfs_btree_node *
453nilfs_btree_get_node(const struct nilfs_btree *btree,
454 const struct nilfs_btree_path *path,
455 int level)
456{
457 return (level == nilfs_btree_height(btree) - 1) ?
458 nilfs_btree_get_root(btree) :
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900459 nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700460}
461
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900462static inline int
463nilfs_btree_bad_node(struct nilfs_btree_node *node, int level)
464{
465 if (unlikely(nilfs_btree_node_get_level(node) != level)) {
466 dump_stack();
467 printk(KERN_CRIT "NILFS: btree level mismatch: %d != %d\n",
468 nilfs_btree_node_get_level(node), level);
469 return 1;
470 }
471 return 0;
472}
473
Koji Sato17c76b02009-04-06 19:01:24 -0700474static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
475 struct nilfs_btree_path *path,
476 __u64 key, __u64 *ptrp, int minlevel)
477{
478 struct nilfs_btree_node *node;
479 __u64 ptr;
480 int level, index, found, ret;
481
Koji Sato17c76b02009-04-06 19:01:24 -0700482 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900483 level = nilfs_btree_node_get_level(node);
484 if (level < minlevel || nilfs_btree_node_get_nchildren(node) <= 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700485 return -ENOENT;
486
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900487 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700488 ptr = nilfs_btree_node_get_ptr(btree, node, index);
489 path[level].bp_bh = NULL;
490 path[level].bp_index = index;
491
492 for (level--; level >= minlevel; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900493 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700494 if (ret < 0)
495 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900496 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900497 if (nilfs_btree_bad_node(node, level))
498 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -0700499 if (!found)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900500 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700501 else
502 index = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900503 if (index < nilfs_btree_node_nchildren_max(node, btree))
Koji Sato17c76b02009-04-06 19:01:24 -0700504 ptr = nilfs_btree_node_get_ptr(btree, node, index);
505 else {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700506 WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN);
Koji Sato17c76b02009-04-06 19:01:24 -0700507 /* insert */
508 ptr = NILFS_BMAP_INVALID_PTR;
509 }
510 path[level].bp_index = index;
511 }
512 if (!found)
513 return -ENOENT;
514
515 if (ptrp != NULL)
516 *ptrp = ptr;
517
518 return 0;
519}
520
521static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree,
522 struct nilfs_btree_path *path,
523 __u64 *keyp, __u64 *ptrp)
524{
525 struct nilfs_btree_node *node;
526 __u64 ptr;
527 int index, level, ret;
528
529 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900530 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700531 if (index < 0)
532 return -ENOENT;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900533 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700534 ptr = nilfs_btree_node_get_ptr(btree, node, index);
535 path[level].bp_bh = NULL;
536 path[level].bp_index = index;
537
538 for (level--; level > 0; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900539 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700540 if (ret < 0)
541 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900542 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900543 if (nilfs_btree_bad_node(node, level))
544 return -EINVAL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900545 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700546 ptr = nilfs_btree_node_get_ptr(btree, node, index);
547 path[level].bp_index = index;
548 }
549
550 if (keyp != NULL)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900551 *keyp = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700552 if (ptrp != NULL)
553 *ptrp = ptr;
554
555 return 0;
556}
557
558static int nilfs_btree_lookup(const struct nilfs_bmap *bmap,
559 __u64 key, int level, __u64 *ptrp)
560{
561 struct nilfs_btree *btree;
562 struct nilfs_btree_path *path;
563 __u64 ptr;
564 int ret;
565
566 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900567 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -0700568 if (path == NULL)
569 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -0700570
571 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
572
573 if (ptrp != NULL)
574 *ptrp = ptr;
575
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900576 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -0700577
578 return ret;
579}
580
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900581static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
582 __u64 key, __u64 *ptrp, unsigned maxblocks)
583{
584 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
585 struct nilfs_btree_path *path;
586 struct nilfs_btree_node *node;
587 struct inode *dat = NULL;
588 __u64 ptr, ptr2;
589 sector_t blocknr;
590 int level = NILFS_BTREE_LEVEL_NODE_MIN;
591 int ret, cnt, index, maxlevel;
592
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900593 path = nilfs_btree_alloc_path();
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900594 if (path == NULL)
595 return -ENOMEM;
Li Hongf9054402010-04-02 17:36:34 +0800596
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900597 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
598 if (ret < 0)
599 goto out;
600
601 if (NILFS_BMAP_USE_VBN(bmap)) {
602 dat = nilfs_bmap_get_dat(bmap);
603 ret = nilfs_dat_translate(dat, ptr, &blocknr);
604 if (ret < 0)
605 goto out;
606 ptr = blocknr;
607 }
608 cnt = 1;
609 if (cnt == maxblocks)
610 goto end;
611
612 maxlevel = nilfs_btree_height(btree) - 1;
613 node = nilfs_btree_get_node(btree, path, level);
614 index = path[level].bp_index + 1;
615 for (;;) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900616 while (index < nilfs_btree_node_get_nchildren(node)) {
617 if (nilfs_btree_node_get_key(node, index) !=
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900618 key + cnt)
619 goto end;
620 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
621 if (dat) {
622 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
623 if (ret < 0)
624 goto out;
625 ptr2 = blocknr;
626 }
627 if (ptr2 != ptr + cnt || ++cnt == maxblocks)
628 goto end;
629 index++;
630 continue;
631 }
632 if (level == maxlevel)
633 break;
634
635 /* look-up right sibling node */
636 node = nilfs_btree_get_node(btree, path, level + 1);
637 index = path[level + 1].bp_index + 1;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900638 if (index >= nilfs_btree_node_get_nchildren(node) ||
639 nilfs_btree_node_get_key(node, index) != key + cnt)
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900640 break;
641 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
642 path[level + 1].bp_index = index;
643
644 brelse(path[level].bp_bh);
645 path[level].bp_bh = NULL;
646 ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh);
647 if (ret < 0)
648 goto out;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900649 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900650 index = 0;
651 path[level].bp_index = index;
652 }
653 end:
654 *ptrp = ptr;
655 ret = cnt;
656 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900657 nilfs_btree_free_path(path);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900658 return ret;
659}
660
Koji Sato17c76b02009-04-06 19:01:24 -0700661static void nilfs_btree_promote_key(struct nilfs_btree *btree,
662 struct nilfs_btree_path *path,
663 int level, __u64 key)
664{
665 if (level < nilfs_btree_height(btree) - 1) {
666 do {
Koji Sato17c76b02009-04-06 19:01:24 -0700667 nilfs_btree_node_set_key(
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900668 nilfs_btree_get_nonroot_node(path, level),
Koji Sato17c76b02009-04-06 19:01:24 -0700669 path[level].bp_index, key);
670 if (!buffer_dirty(path[level].bp_bh))
671 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700672 } while ((path[level].bp_index == 0) &&
673 (++level < nilfs_btree_height(btree) - 1));
674 }
675
676 /* root */
677 if (level == nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900678 nilfs_btree_node_set_key(nilfs_btree_get_root(btree),
Koji Sato17c76b02009-04-06 19:01:24 -0700679 path[level].bp_index, key);
680 }
681}
682
683static void nilfs_btree_do_insert(struct nilfs_btree *btree,
684 struct nilfs_btree_path *path,
685 int level, __u64 *keyp, __u64 *ptrp)
686{
687 struct nilfs_btree_node *node;
688
689 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900690 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700691 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
692 path[level].bp_index);
693 if (!buffer_dirty(path[level].bp_bh))
694 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700695
696 if (path[level].bp_index == 0)
697 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900698 nilfs_btree_node_get_key(node,
699 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700700 } else {
701 node = nilfs_btree_get_root(btree);
702 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
703 path[level].bp_index);
704 }
705}
706
707static void nilfs_btree_carry_left(struct nilfs_btree *btree,
708 struct nilfs_btree_path *path,
709 int level, __u64 *keyp, __u64 *ptrp)
710{
711 struct nilfs_btree_node *node, *left;
712 int nchildren, lnchildren, n, move;
713
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900714 node = nilfs_btree_get_nonroot_node(path, level);
715 left = nilfs_btree_get_sib_node(path, level);
716 nchildren = nilfs_btree_node_get_nchildren(node);
717 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700718 move = 0;
719
720 n = (nchildren + lnchildren + 1) / 2 - lnchildren;
721 if (n > path[level].bp_index) {
722 /* move insert point */
723 n--;
724 move = 1;
725 }
726
727 nilfs_btree_node_move_left(btree, left, node, n);
728
729 if (!buffer_dirty(path[level].bp_bh))
730 nilfs_btnode_mark_dirty(path[level].bp_bh);
731 if (!buffer_dirty(path[level].bp_sib_bh))
732 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
733
Koji Sato17c76b02009-04-06 19:01:24 -0700734 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900735 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700736
737 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900738 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700739 path[level].bp_bh = path[level].bp_sib_bh;
740 path[level].bp_sib_bh = NULL;
741 path[level].bp_index += lnchildren;
742 path[level + 1].bp_index--;
743 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900744 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700745 path[level].bp_sib_bh = NULL;
746 path[level].bp_index -= n;
747 }
748
749 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
750}
751
752static void nilfs_btree_carry_right(struct nilfs_btree *btree,
753 struct nilfs_btree_path *path,
754 int level, __u64 *keyp, __u64 *ptrp)
755{
756 struct nilfs_btree_node *node, *right;
757 int nchildren, rnchildren, n, move;
758
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900759 node = nilfs_btree_get_nonroot_node(path, level);
760 right = nilfs_btree_get_sib_node(path, level);
761 nchildren = nilfs_btree_node_get_nchildren(node);
762 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700763 move = 0;
764
765 n = (nchildren + rnchildren + 1) / 2 - rnchildren;
766 if (n > nchildren - path[level].bp_index) {
767 /* move insert point */
768 n--;
769 move = 1;
770 }
771
772 nilfs_btree_node_move_right(btree, node, right, n);
773
774 if (!buffer_dirty(path[level].bp_bh))
775 nilfs_btnode_mark_dirty(path[level].bp_bh);
776 if (!buffer_dirty(path[level].bp_sib_bh))
777 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
778
Koji Sato17c76b02009-04-06 19:01:24 -0700779 path[level + 1].bp_index++;
780 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900781 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700782 path[level + 1].bp_index--;
783
784 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900785 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700786 path[level].bp_bh = path[level].bp_sib_bh;
787 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900788 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700789 path[level + 1].bp_index++;
790 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900791 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700792 path[level].bp_sib_bh = NULL;
793 }
794
795 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
796}
797
798static void nilfs_btree_split(struct nilfs_btree *btree,
799 struct nilfs_btree_path *path,
800 int level, __u64 *keyp, __u64 *ptrp)
801{
802 struct nilfs_btree_node *node, *right;
803 __u64 newkey;
804 __u64 newptr;
805 int nchildren, n, move;
806
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900807 node = nilfs_btree_get_nonroot_node(path, level);
808 right = nilfs_btree_get_sib_node(path, level);
809 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700810 move = 0;
811
812 n = (nchildren + 1) / 2;
813 if (n > nchildren - path[level].bp_index) {
814 n--;
815 move = 1;
816 }
817
818 nilfs_btree_node_move_right(btree, node, right, n);
819
820 if (!buffer_dirty(path[level].bp_bh))
821 nilfs_btnode_mark_dirty(path[level].bp_bh);
822 if (!buffer_dirty(path[level].bp_sib_bh))
823 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
824
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900825 newkey = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700826 newptr = path[level].bp_newreq.bpr_ptr;
827
828 if (move) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900829 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700830 nilfs_btree_node_insert(btree, right, *keyp, *ptrp,
831 path[level].bp_index);
832
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900833 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700834 *ptrp = path[level].bp_newreq.bpr_ptr;
835
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900836 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700837 path[level].bp_bh = path[level].bp_sib_bh;
838 path[level].bp_sib_bh = NULL;
839 } else {
840 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
841
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900842 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700843 *ptrp = path[level].bp_newreq.bpr_ptr;
844
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900845 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700846 path[level].bp_sib_bh = NULL;
847 }
848
849 path[level + 1].bp_index++;
850}
851
852static void nilfs_btree_grow(struct nilfs_btree *btree,
853 struct nilfs_btree_path *path,
854 int level, __u64 *keyp, __u64 *ptrp)
855{
856 struct nilfs_btree_node *root, *child;
857 int n;
858
Koji Sato17c76b02009-04-06 19:01:24 -0700859 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900860 child = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700861
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900862 n = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -0700863
864 nilfs_btree_node_move_right(btree, root, child, n);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900865 nilfs_btree_node_set_level(root, level + 1);
Koji Sato17c76b02009-04-06 19:01:24 -0700866
867 if (!buffer_dirty(path[level].bp_sib_bh))
868 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
869
Koji Sato17c76b02009-04-06 19:01:24 -0700870 path[level].bp_bh = path[level].bp_sib_bh;
871 path[level].bp_sib_bh = NULL;
872
873 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
874
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900875 *keyp = nilfs_btree_node_get_key(child, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700876 *ptrp = path[level].bp_newreq.bpr_ptr;
877}
878
879static __u64 nilfs_btree_find_near(const struct nilfs_btree *btree,
880 const struct nilfs_btree_path *path)
881{
882 struct nilfs_btree_node *node;
883 int level;
884
885 if (path == NULL)
886 return NILFS_BMAP_INVALID_PTR;
887
888 /* left sibling */
889 level = NILFS_BTREE_LEVEL_NODE_MIN;
890 if (path[level].bp_index > 0) {
891 node = nilfs_btree_get_node(btree, path, level);
892 return nilfs_btree_node_get_ptr(btree, node,
893 path[level].bp_index - 1);
894 }
895
896 /* parent */
897 level = NILFS_BTREE_LEVEL_NODE_MIN + 1;
898 if (level <= nilfs_btree_height(btree) - 1) {
899 node = nilfs_btree_get_node(btree, path, level);
900 return nilfs_btree_node_get_ptr(btree, node,
901 path[level].bp_index);
902 }
903
904 return NILFS_BMAP_INVALID_PTR;
905}
906
907static __u64 nilfs_btree_find_target_v(const struct nilfs_btree *btree,
908 const struct nilfs_btree_path *path,
909 __u64 key)
910{
911 __u64 ptr;
912
913 ptr = nilfs_bmap_find_target_seq(&btree->bt_bmap, key);
914 if (ptr != NILFS_BMAP_INVALID_PTR)
915 /* sequential access */
916 return ptr;
917 else {
918 ptr = nilfs_btree_find_near(btree, path);
919 if (ptr != NILFS_BMAP_INVALID_PTR)
920 /* near */
921 return ptr;
922 }
923 /* block group */
924 return nilfs_bmap_find_target_in_group(&btree->bt_bmap);
925}
926
927static void nilfs_btree_set_target_v(struct nilfs_btree *btree, __u64 key,
928 __u64 ptr)
929{
930 btree->bt_bmap.b_last_allocated_key = key;
931 btree->bt_bmap.b_last_allocated_ptr = ptr;
932}
933
934static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
935 struct nilfs_btree_path *path,
936 int *levelp, __u64 key, __u64 ptr,
937 struct nilfs_bmap_stats *stats)
938{
939 struct buffer_head *bh;
940 struct nilfs_btree_node *node, *parent, *sib;
941 __u64 sibptr;
942 int pindex, level, ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900943 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -0700944
945 stats->bs_nblocks = 0;
946 level = NILFS_BTREE_LEVEL_DATA;
947
948 /* allocate a new ptr for data block */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900949 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700950 path[level].bp_newreq.bpr_ptr =
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +0900951 nilfs_btree_find_target_v(btree, path, key);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900952 dat = nilfs_bmap_get_dat(&btree->bt_bmap);
953 }
Koji Sato17c76b02009-04-06 19:01:24 -0700954
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900955 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900956 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -0700957 if (ret < 0)
958 goto err_out_data;
959
960 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
961 level < nilfs_btree_height(btree) - 1;
962 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900963 node = nilfs_btree_get_nonroot_node(path, level);
964 if (nilfs_btree_node_get_nchildren(node) <
965 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700966 path[level].bp_op = nilfs_btree_do_insert;
967 stats->bs_nblocks++;
968 goto out;
969 }
970
971 parent = nilfs_btree_get_node(btree, path, level + 1);
972 pindex = path[level + 1].bp_index;
973
974 /* left sibling */
975 if (pindex > 0) {
976 sibptr = nilfs_btree_node_get_ptr(btree, parent,
977 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900978 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700979 if (ret < 0)
980 goto err_out_child_node;
981 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900982 if (nilfs_btree_node_get_nchildren(sib) <
983 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700984 path[level].bp_sib_bh = bh;
985 path[level].bp_op = nilfs_btree_carry_left;
986 stats->bs_nblocks++;
987 goto out;
988 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900989 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700990 }
991
992 /* right sibling */
993 if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900994 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -0700995 sibptr = nilfs_btree_node_get_ptr(btree, parent,
996 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900997 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700998 if (ret < 0)
999 goto err_out_child_node;
1000 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001001 if (nilfs_btree_node_get_nchildren(sib) <
1002 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001003 path[level].bp_sib_bh = bh;
1004 path[level].bp_op = nilfs_btree_carry_right;
1005 stats->bs_nblocks++;
1006 goto out;
1007 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001008 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001009 }
1010
1011 /* split */
1012 path[level].bp_newreq.bpr_ptr =
1013 path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001014 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001015 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001016 if (ret < 0)
1017 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001018 ret = nilfs_btree_get_new_block(btree,
1019 path[level].bp_newreq.bpr_ptr,
1020 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001021 if (ret < 0)
1022 goto err_out_curr_node;
1023
1024 stats->bs_nblocks++;
1025
Koji Sato17c76b02009-04-06 19:01:24 -07001026 nilfs_btree_node_init(btree,
1027 (struct nilfs_btree_node *)bh->b_data,
1028 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001029 path[level].bp_sib_bh = bh;
1030 path[level].bp_op = nilfs_btree_split;
1031 }
1032
1033 /* root */
1034 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001035 if (nilfs_btree_node_get_nchildren(node) <
1036 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001037 path[level].bp_op = nilfs_btree_do_insert;
1038 stats->bs_nblocks++;
1039 goto out;
1040 }
1041
1042 /* grow */
1043 path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001044 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001045 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001046 if (ret < 0)
1047 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001048 ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
1049 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001050 if (ret < 0)
1051 goto err_out_curr_node;
1052
Koji Sato17c76b02009-04-06 19:01:24 -07001053 nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data,
1054 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001055 path[level].bp_sib_bh = bh;
1056 path[level].bp_op = nilfs_btree_grow;
1057
1058 level++;
1059 path[level].bp_op = nilfs_btree_do_insert;
1060
1061 /* a newly-created node block and a data block are added */
1062 stats->bs_nblocks += 2;
1063
1064 /* success */
1065 out:
1066 *levelp = level;
1067 return ret;
1068
1069 /* error */
1070 err_out_curr_node:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001071 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
1072 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001073 err_out_child_node:
1074 for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001075 nilfs_btnode_delete(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001076 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001077 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001078
1079 }
1080
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001081 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
1082 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001083 err_out_data:
1084 *levelp = level;
1085 stats->bs_nblocks = 0;
1086 return ret;
1087}
1088
1089static void nilfs_btree_commit_insert(struct nilfs_btree *btree,
1090 struct nilfs_btree_path *path,
1091 int maxlevel, __u64 key, __u64 ptr)
1092{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001093 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001094 int level;
1095
1096 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1097 ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001098 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001099 nilfs_btree_set_target_v(btree, key, ptr);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001100 dat = nilfs_bmap_get_dat(&btree->bt_bmap);
1101 }
Koji Sato17c76b02009-04-06 19:01:24 -07001102
1103 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001104 nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001105 &path[level - 1].bp_newreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001106 path[level].bp_op(btree, path, level, &key, &ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001107 }
1108
1109 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1110 nilfs_bmap_set_dirty(&btree->bt_bmap);
1111}
1112
1113static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
1114{
1115 struct nilfs_btree *btree;
1116 struct nilfs_btree_path *path;
1117 struct nilfs_bmap_stats stats;
1118 int level, ret;
1119
1120 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001121 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001122 if (path == NULL)
1123 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001124
1125 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1126 NILFS_BTREE_LEVEL_NODE_MIN);
1127 if (ret != -ENOENT) {
1128 if (ret == 0)
1129 ret = -EEXIST;
1130 goto out;
1131 }
1132
1133 ret = nilfs_btree_prepare_insert(btree, path, &level, key, ptr, &stats);
1134 if (ret < 0)
1135 goto out;
1136 nilfs_btree_commit_insert(btree, path, level, key, ptr);
1137 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1138
1139 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001140 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001141 return ret;
1142}
1143
1144static void nilfs_btree_do_delete(struct nilfs_btree *btree,
1145 struct nilfs_btree_path *path,
1146 int level, __u64 *keyp, __u64 *ptrp)
1147{
1148 struct nilfs_btree_node *node;
1149
1150 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001151 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001152 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1153 path[level].bp_index);
1154 if (!buffer_dirty(path[level].bp_bh))
1155 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001156 if (path[level].bp_index == 0)
1157 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001158 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001159 } else {
1160 node = nilfs_btree_get_root(btree);
1161 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1162 path[level].bp_index);
1163 }
1164}
1165
1166static void nilfs_btree_borrow_left(struct nilfs_btree *btree,
1167 struct nilfs_btree_path *path,
1168 int level, __u64 *keyp, __u64 *ptrp)
1169{
1170 struct nilfs_btree_node *node, *left;
1171 int nchildren, lnchildren, n;
1172
1173 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1174
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001175 node = nilfs_btree_get_nonroot_node(path, level);
1176 left = nilfs_btree_get_sib_node(path, level);
1177 nchildren = nilfs_btree_node_get_nchildren(node);
1178 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001179
1180 n = (nchildren + lnchildren) / 2 - nchildren;
1181
1182 nilfs_btree_node_move_right(btree, left, node, n);
1183
1184 if (!buffer_dirty(path[level].bp_bh))
1185 nilfs_btnode_mark_dirty(path[level].bp_bh);
1186 if (!buffer_dirty(path[level].bp_sib_bh))
1187 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1188
Koji Sato17c76b02009-04-06 19:01:24 -07001189 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001190 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001191
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001192 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001193 path[level].bp_sib_bh = NULL;
1194 path[level].bp_index += n;
1195}
1196
1197static void nilfs_btree_borrow_right(struct nilfs_btree *btree,
1198 struct nilfs_btree_path *path,
1199 int level, __u64 *keyp, __u64 *ptrp)
1200{
1201 struct nilfs_btree_node *node, *right;
1202 int nchildren, rnchildren, n;
1203
1204 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1205
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001206 node = nilfs_btree_get_nonroot_node(path, level);
1207 right = nilfs_btree_get_sib_node(path, level);
1208 nchildren = nilfs_btree_node_get_nchildren(node);
1209 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001210
1211 n = (nchildren + rnchildren) / 2 - nchildren;
1212
1213 nilfs_btree_node_move_left(btree, node, right, n);
1214
1215 if (!buffer_dirty(path[level].bp_bh))
1216 nilfs_btnode_mark_dirty(path[level].bp_bh);
1217 if (!buffer_dirty(path[level].bp_sib_bh))
1218 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1219
Koji Sato17c76b02009-04-06 19:01:24 -07001220 path[level + 1].bp_index++;
1221 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001222 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001223 path[level + 1].bp_index--;
1224
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001225 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001226 path[level].bp_sib_bh = NULL;
1227}
1228
1229static void nilfs_btree_concat_left(struct nilfs_btree *btree,
1230 struct nilfs_btree_path *path,
1231 int level, __u64 *keyp, __u64 *ptrp)
1232{
1233 struct nilfs_btree_node *node, *left;
1234 int n;
1235
1236 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1237
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001238 node = nilfs_btree_get_nonroot_node(path, level);
1239 left = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001240
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001241 n = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001242
1243 nilfs_btree_node_move_left(btree, left, node, n);
1244
1245 if (!buffer_dirty(path[level].bp_sib_bh))
1246 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1247
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001248 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001249 path[level].bp_bh = path[level].bp_sib_bh;
1250 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001251 path[level].bp_index += nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001252}
1253
1254static void nilfs_btree_concat_right(struct nilfs_btree *btree,
1255 struct nilfs_btree_path *path,
1256 int level, __u64 *keyp, __u64 *ptrp)
1257{
1258 struct nilfs_btree_node *node, *right;
1259 int n;
1260
1261 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1262
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001263 node = nilfs_btree_get_nonroot_node(path, level);
1264 right = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001265
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001266 n = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001267
1268 nilfs_btree_node_move_left(btree, node, right, n);
1269
1270 if (!buffer_dirty(path[level].bp_bh))
1271 nilfs_btnode_mark_dirty(path[level].bp_bh);
1272
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001273 nilfs_btnode_delete(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001274 path[level].bp_sib_bh = NULL;
1275 path[level + 1].bp_index++;
1276}
1277
1278static void nilfs_btree_shrink(struct nilfs_btree *btree,
1279 struct nilfs_btree_path *path,
1280 int level, __u64 *keyp, __u64 *ptrp)
1281{
1282 struct nilfs_btree_node *root, *child;
1283 int n;
1284
1285 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1286
Koji Sato17c76b02009-04-06 19:01:24 -07001287 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001288 child = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001289
1290 nilfs_btree_node_delete(btree, root, NULL, NULL, 0);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001291 nilfs_btree_node_set_level(root, level);
1292 n = nilfs_btree_node_get_nchildren(child);
Koji Sato17c76b02009-04-06 19:01:24 -07001293 nilfs_btree_node_move_left(btree, root, child, n);
Koji Sato17c76b02009-04-06 19:01:24 -07001294
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001295 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001296 path[level].bp_bh = NULL;
1297}
1298
1299
1300static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
1301 struct nilfs_btree_path *path,
1302 int *levelp,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001303 struct nilfs_bmap_stats *stats,
1304 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001305{
1306 struct buffer_head *bh;
1307 struct nilfs_btree_node *node, *parent, *sib;
1308 __u64 sibptr;
1309 int pindex, level, ret;
1310
1311 ret = 0;
1312 stats->bs_nblocks = 0;
1313 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1314 level < nilfs_btree_height(btree) - 1;
1315 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001316 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001317 path[level].bp_oldreq.bpr_ptr =
1318 nilfs_btree_node_get_ptr(btree, node,
1319 path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001320 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001321 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001322 if (ret < 0)
1323 goto err_out_child_node;
Koji Sato17c76b02009-04-06 19:01:24 -07001324
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001325 if (nilfs_btree_node_get_nchildren(node) >
1326 nilfs_btree_node_nchildren_min(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001327 path[level].bp_op = nilfs_btree_do_delete;
1328 stats->bs_nblocks++;
1329 goto out;
1330 }
1331
1332 parent = nilfs_btree_get_node(btree, path, level + 1);
1333 pindex = path[level + 1].bp_index;
1334
1335 if (pindex > 0) {
1336 /* left sibling */
1337 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1338 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001339 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001340 if (ret < 0)
1341 goto err_out_curr_node;
1342 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001343 if (nilfs_btree_node_get_nchildren(sib) >
1344 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001345 path[level].bp_sib_bh = bh;
1346 path[level].bp_op = nilfs_btree_borrow_left;
1347 stats->bs_nblocks++;
1348 goto out;
1349 } else {
1350 path[level].bp_sib_bh = bh;
1351 path[level].bp_op = nilfs_btree_concat_left;
1352 stats->bs_nblocks++;
1353 /* continue; */
1354 }
1355 } else if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001356 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -07001357 /* right sibling */
1358 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1359 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001360 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001361 if (ret < 0)
1362 goto err_out_curr_node;
1363 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001364 if (nilfs_btree_node_get_nchildren(sib) >
1365 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001366 path[level].bp_sib_bh = bh;
1367 path[level].bp_op = nilfs_btree_borrow_right;
1368 stats->bs_nblocks++;
1369 goto out;
1370 } else {
1371 path[level].bp_sib_bh = bh;
1372 path[level].bp_op = nilfs_btree_concat_right;
1373 stats->bs_nblocks++;
1374 /* continue; */
1375 }
1376 } else {
1377 /* no siblings */
1378 /* the only child of the root node */
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001379 WARN_ON(level != nilfs_btree_height(btree) - 2);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001380 if (nilfs_btree_node_get_nchildren(node) - 1 <=
Koji Sato17c76b02009-04-06 19:01:24 -07001381 NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1382 path[level].bp_op = nilfs_btree_shrink;
1383 stats->bs_nblocks += 2;
1384 } else {
1385 path[level].bp_op = nilfs_btree_do_delete;
1386 stats->bs_nblocks++;
1387 }
1388
1389 goto out;
1390
1391 }
1392 }
1393
1394 node = nilfs_btree_get_root(btree);
1395 path[level].bp_oldreq.bpr_ptr =
1396 nilfs_btree_node_get_ptr(btree, node, path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001397
1398 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001399 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001400 if (ret < 0)
1401 goto err_out_child_node;
1402
Koji Sato17c76b02009-04-06 19:01:24 -07001403 /* child of the root node is deleted */
1404 path[level].bp_op = nilfs_btree_do_delete;
1405 stats->bs_nblocks++;
1406
1407 /* success */
1408 out:
1409 *levelp = level;
1410 return ret;
1411
1412 /* error */
1413 err_out_curr_node:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001414 nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001415 err_out_child_node:
1416 for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001417 brelse(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001418 nilfs_bmap_abort_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001419 &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001420 }
1421 *levelp = level;
1422 stats->bs_nblocks = 0;
1423 return ret;
1424}
1425
1426static void nilfs_btree_commit_delete(struct nilfs_btree *btree,
1427 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001428 int maxlevel, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001429{
1430 int level;
1431
1432 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001433 nilfs_bmap_commit_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001434 &path[level].bp_oldreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001435 path[level].bp_op(btree, path, level, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001436 }
1437
1438 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1439 nilfs_bmap_set_dirty(&btree->bt_bmap);
1440}
1441
1442static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key)
1443
1444{
1445 struct nilfs_btree *btree;
1446 struct nilfs_btree_path *path;
1447 struct nilfs_bmap_stats stats;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001448 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001449 int level, ret;
1450
1451 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001452 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001453 if (path == NULL)
1454 return -ENOMEM;
Li Hongf9054402010-04-02 17:36:34 +08001455
Koji Sato17c76b02009-04-06 19:01:24 -07001456 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1457 NILFS_BTREE_LEVEL_NODE_MIN);
1458 if (ret < 0)
1459 goto out;
1460
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001461
1462 dat = NILFS_BMAP_USE_VBN(&btree->bt_bmap) ?
1463 nilfs_bmap_get_dat(&btree->bt_bmap) : NULL;
1464
1465 ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001466 if (ret < 0)
1467 goto out;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001468 nilfs_btree_commit_delete(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001469 nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks);
1470
1471out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001472 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001473 return ret;
1474}
1475
1476static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp)
1477{
1478 struct nilfs_btree *btree;
1479 struct nilfs_btree_path *path;
1480 int ret;
1481
1482 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001483 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001484 if (path == NULL)
1485 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001486
1487 ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL);
1488
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001489 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001490
1491 return ret;
1492}
1493
1494static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key)
1495{
1496 struct buffer_head *bh;
1497 struct nilfs_btree *btree;
1498 struct nilfs_btree_node *root, *node;
1499 __u64 maxkey, nextmaxkey;
1500 __u64 ptr;
1501 int nchildren, ret;
1502
1503 btree = (struct nilfs_btree *)bmap;
1504 root = nilfs_btree_get_root(btree);
1505 switch (nilfs_btree_height(btree)) {
1506 case 2:
1507 bh = NULL;
1508 node = root;
1509 break;
1510 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001511 nchildren = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -07001512 if (nchildren > 1)
1513 return 0;
1514 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001515 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001516 if (ret < 0)
1517 return ret;
1518 node = (struct nilfs_btree_node *)bh->b_data;
1519 break;
1520 default:
1521 return 0;
1522 }
1523
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001524 nchildren = nilfs_btree_node_get_nchildren(node);
1525 maxkey = nilfs_btree_node_get_key(node, nchildren - 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001526 nextmaxkey = (nchildren > 1) ?
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001527 nilfs_btree_node_get_key(node, nchildren - 2) : 0;
Koji Sato17c76b02009-04-06 19:01:24 -07001528 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001529 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001530
Ryusuke Konishi30333422009-05-24 00:09:44 +09001531 return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
Koji Sato17c76b02009-04-06 19:01:24 -07001532}
1533
1534static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
1535 __u64 *keys, __u64 *ptrs, int nitems)
1536{
1537 struct buffer_head *bh;
1538 struct nilfs_btree *btree;
1539 struct nilfs_btree_node *node, *root;
1540 __le64 *dkeys;
1541 __le64 *dptrs;
1542 __u64 ptr;
1543 int nchildren, i, ret;
1544
1545 btree = (struct nilfs_btree *)bmap;
1546 root = nilfs_btree_get_root(btree);
1547 switch (nilfs_btree_height(btree)) {
1548 case 2:
1549 bh = NULL;
1550 node = root;
1551 break;
1552 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001553 nchildren = nilfs_btree_node_get_nchildren(root);
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001554 WARN_ON(nchildren > 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001555 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001556 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001557 if (ret < 0)
1558 return ret;
1559 node = (struct nilfs_btree_node *)bh->b_data;
1560 break;
1561 default:
1562 node = NULL;
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001563 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -07001564 }
1565
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001566 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001567 if (nchildren < nitems)
1568 nitems = nchildren;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001569 dkeys = nilfs_btree_node_dkeys(node);
1570 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001571 for (i = 0; i < nitems; i++) {
1572 keys[i] = nilfs_bmap_dkey_to_key(dkeys[i]);
1573 ptrs[i] = nilfs_bmap_dptr_to_ptr(dptrs[i]);
1574 }
1575
1576 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001577 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001578
1579 return nitems;
1580}
1581
1582static int
1583nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
1584 union nilfs_bmap_ptr_req *dreq,
1585 union nilfs_bmap_ptr_req *nreq,
1586 struct buffer_head **bhp,
1587 struct nilfs_bmap_stats *stats)
1588{
1589 struct buffer_head *bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001590 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
1591 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001592 int ret;
1593
Koji Sato17c76b02009-04-06 19:01:24 -07001594 stats->bs_nblocks = 0;
1595
1596 /* for data */
1597 /* cannot find near ptr */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001598 if (NILFS_BMAP_USE_VBN(bmap)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001599 dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001600 dat = nilfs_bmap_get_dat(bmap);
1601 }
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001602
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001603 ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001604 if (ret < 0)
1605 return ret;
1606
1607 *bhp = NULL;
1608 stats->bs_nblocks++;
1609 if (nreq != NULL) {
1610 nreq->bpr_ptr = dreq->bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001611 ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001612 if (ret < 0)
1613 goto err_out_dreq;
1614
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001615 ret = nilfs_btree_get_new_block(btree, nreq->bpr_ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001616 if (ret < 0)
1617 goto err_out_nreq;
1618
1619 *bhp = bh;
1620 stats->bs_nblocks++;
1621 }
1622
1623 /* success */
1624 return 0;
1625
1626 /* error */
1627 err_out_nreq:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001628 nilfs_bmap_abort_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001629 err_out_dreq:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001630 nilfs_bmap_abort_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001631 stats->bs_nblocks = 0;
1632 return ret;
1633
1634}
1635
1636static void
1637nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
1638 __u64 key, __u64 ptr,
1639 const __u64 *keys, const __u64 *ptrs,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001640 int n,
Koji Sato17c76b02009-04-06 19:01:24 -07001641 union nilfs_bmap_ptr_req *dreq,
1642 union nilfs_bmap_ptr_req *nreq,
1643 struct buffer_head *bh)
1644{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001645 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
Koji Sato17c76b02009-04-06 19:01:24 -07001646 struct nilfs_btree_node *node;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001647 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001648 __u64 tmpptr;
1649
1650 /* free resources */
1651 if (bmap->b_ops->bop_clear != NULL)
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001652 bmap->b_ops->bop_clear(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001653
1654 /* ptr must be a pointer to a buffer head. */
1655 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1656
1657 /* convert and insert */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001658 dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL;
Ryusuke Konishi30333422009-05-24 00:09:44 +09001659 nilfs_btree_init(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001660 if (nreq != NULL) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001661 nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
1662 nilfs_bmap_commit_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001663
1664 /* create child node at level 1 */
Koji Sato17c76b02009-04-06 19:01:24 -07001665 node = (struct nilfs_btree_node *)bh->b_data;
1666 nilfs_btree_node_init(btree, node, 0, 1, n, keys, ptrs);
1667 nilfs_btree_node_insert(btree, node,
1668 key, dreq->bpr_ptr, n);
1669 if (!buffer_dirty(bh))
1670 nilfs_btnode_mark_dirty(bh);
1671 if (!nilfs_bmap_dirty(bmap))
1672 nilfs_bmap_set_dirty(bmap);
1673
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001674 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001675
1676 /* create root node at level 2 */
1677 node = nilfs_btree_get_root(btree);
1678 tmpptr = nreq->bpr_ptr;
1679 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1680 2, 1, &keys[0], &tmpptr);
1681 } else {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001682 nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001683
1684 /* create root node at level 1 */
1685 node = nilfs_btree_get_root(btree);
1686 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1687 1, n, keys, ptrs);
1688 nilfs_btree_node_insert(btree, node,
1689 key, dreq->bpr_ptr, n);
1690 if (!nilfs_bmap_dirty(bmap))
1691 nilfs_bmap_set_dirty(bmap);
1692 }
1693
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001694 if (NILFS_BMAP_USE_VBN(bmap))
1695 nilfs_btree_set_target_v(btree, key, dreq->bpr_ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001696}
1697
1698/**
1699 * nilfs_btree_convert_and_insert -
1700 * @bmap:
1701 * @key:
1702 * @ptr:
1703 * @keys:
1704 * @ptrs:
1705 * @n:
Koji Sato17c76b02009-04-06 19:01:24 -07001706 */
1707int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap,
1708 __u64 key, __u64 ptr,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001709 const __u64 *keys, const __u64 *ptrs, int n)
Koji Sato17c76b02009-04-06 19:01:24 -07001710{
1711 struct buffer_head *bh;
1712 union nilfs_bmap_ptr_req dreq, nreq, *di, *ni;
1713 struct nilfs_bmap_stats stats;
1714 int ret;
1715
1716 if (n + 1 <= NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1717 di = &dreq;
1718 ni = NULL;
1719 } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX(
1720 1 << bmap->b_inode->i_blkbits)) {
1721 di = &dreq;
1722 ni = &nreq;
1723 } else {
1724 di = NULL;
1725 ni = NULL;
1726 BUG();
1727 }
1728
1729 ret = nilfs_btree_prepare_convert_and_insert(bmap, key, di, ni, &bh,
1730 &stats);
1731 if (ret < 0)
1732 return ret;
1733 nilfs_btree_commit_convert_and_insert(bmap, key, ptr, keys, ptrs, n,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001734 di, ni, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001735 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1736 return 0;
1737}
1738
1739static int nilfs_btree_propagate_p(struct nilfs_btree *btree,
1740 struct nilfs_btree_path *path,
1741 int level,
1742 struct buffer_head *bh)
1743{
1744 while ((++level < nilfs_btree_height(btree) - 1) &&
1745 !buffer_dirty(path[level].bp_bh))
1746 nilfs_btnode_mark_dirty(path[level].bp_bh);
1747
1748 return 0;
1749}
1750
1751static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
1752 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001753 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001754{
1755 struct nilfs_btree_node *parent;
1756 int ret;
1757
1758 parent = nilfs_btree_get_node(btree, path, level + 1);
1759 path[level].bp_oldreq.bpr_ptr =
1760 nilfs_btree_node_get_ptr(btree, parent,
1761 path[level + 1].bp_index);
1762 path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001763 ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req,
1764 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001765 if (ret < 0)
1766 return ret;
1767
1768 if (buffer_nilfs_node(path[level].bp_bh)) {
1769 path[level].bp_ctxt.oldkey = path[level].bp_oldreq.bpr_ptr;
1770 path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr;
1771 path[level].bp_ctxt.bh = path[level].bp_bh;
1772 ret = nilfs_btnode_prepare_change_key(
1773 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1774 &path[level].bp_ctxt);
1775 if (ret < 0) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001776 nilfs_dat_abort_update(dat,
1777 &path[level].bp_oldreq.bpr_req,
1778 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001779 return ret;
1780 }
1781 }
1782
1783 return 0;
1784}
1785
1786static void nilfs_btree_commit_update_v(struct nilfs_btree *btree,
1787 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001788 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001789{
1790 struct nilfs_btree_node *parent;
1791
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001792 nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req,
1793 &path[level].bp_newreq.bpr_req,
1794 btree->bt_bmap.b_ptr_type == NILFS_BMAP_PTR_VS);
Koji Sato17c76b02009-04-06 19:01:24 -07001795
1796 if (buffer_nilfs_node(path[level].bp_bh)) {
1797 nilfs_btnode_commit_change_key(
1798 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1799 &path[level].bp_ctxt);
1800 path[level].bp_bh = path[level].bp_ctxt.bh;
1801 }
1802 set_buffer_nilfs_volatile(path[level].bp_bh);
1803
1804 parent = nilfs_btree_get_node(btree, path, level + 1);
1805 nilfs_btree_node_set_ptr(btree, parent, path[level + 1].bp_index,
1806 path[level].bp_newreq.bpr_ptr);
1807}
1808
1809static void nilfs_btree_abort_update_v(struct nilfs_btree *btree,
1810 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001811 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001812{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001813 nilfs_dat_abort_update(dat, &path[level].bp_oldreq.bpr_req,
1814 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001815 if (buffer_nilfs_node(path[level].bp_bh))
1816 nilfs_btnode_abort_change_key(
1817 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1818 &path[level].bp_ctxt);
1819}
1820
1821static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree,
1822 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001823 int minlevel, int *maxlevelp,
1824 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001825{
1826 int level, ret;
1827
1828 level = minlevel;
1829 if (!buffer_nilfs_volatile(path[level].bp_bh)) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001830 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001831 if (ret < 0)
1832 return ret;
1833 }
1834 while ((++level < nilfs_btree_height(btree) - 1) &&
1835 !buffer_dirty(path[level].bp_bh)) {
1836
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001837 WARN_ON(buffer_nilfs_volatile(path[level].bp_bh));
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001838 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001839 if (ret < 0)
1840 goto out;
1841 }
1842
1843 /* success */
Koji Sato17c76b02009-04-06 19:01:24 -07001844 *maxlevelp = level - 1;
1845 return 0;
1846
1847 /* error */
1848 out:
1849 while (--level > minlevel)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001850 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001851 if (!buffer_nilfs_volatile(path[level].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001852 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001853 return ret;
1854}
1855
1856static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree,
1857 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001858 int minlevel, int maxlevel,
1859 struct buffer_head *bh,
1860 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001861{
1862 int level;
1863
1864 if (!buffer_nilfs_volatile(path[minlevel].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001865 nilfs_btree_commit_update_v(btree, path, minlevel, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001866
1867 for (level = minlevel + 1; level <= maxlevel; level++)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001868 nilfs_btree_commit_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001869}
1870
1871static int nilfs_btree_propagate_v(struct nilfs_btree *btree,
1872 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001873 int level, struct buffer_head *bh)
Koji Sato17c76b02009-04-06 19:01:24 -07001874{
Li Hong308f4412010-04-02 18:40:39 +08001875 int maxlevel = 0, ret;
Koji Sato17c76b02009-04-06 19:01:24 -07001876 struct nilfs_btree_node *parent;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001877 struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001878 __u64 ptr;
1879
1880 get_bh(bh);
1881 path[level].bp_bh = bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001882 ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel,
1883 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001884 if (ret < 0)
1885 goto out;
1886
1887 if (buffer_nilfs_volatile(path[level].bp_bh)) {
1888 parent = nilfs_btree_get_node(btree, path, level + 1);
1889 ptr = nilfs_btree_node_get_ptr(btree, parent,
1890 path[level + 1].bp_index);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001891 ret = nilfs_dat_mark_dirty(dat, ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001892 if (ret < 0)
1893 goto out;
1894 }
1895
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001896 nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001897
1898 out:
1899 brelse(path[level].bp_bh);
1900 path[level].bp_bh = NULL;
1901 return ret;
1902}
1903
1904static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
1905 struct buffer_head *bh)
1906{
1907 struct nilfs_btree *btree;
1908 struct nilfs_btree_path *path;
1909 struct nilfs_btree_node *node;
1910 __u64 key;
1911 int level, ret;
1912
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001913 WARN_ON(!buffer_dirty(bh));
Koji Sato17c76b02009-04-06 19:01:24 -07001914
1915 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001916 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001917 if (path == NULL)
1918 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001919
1920 if (buffer_nilfs_node(bh)) {
1921 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001922 key = nilfs_btree_node_get_key(node, 0);
1923 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001924 } else {
1925 key = nilfs_bmap_data_get_key(bmap, bh);
1926 level = NILFS_BTREE_LEVEL_DATA;
1927 }
1928
1929 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
1930 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001931 if (unlikely(ret == -ENOENT))
Koji Sato17c76b02009-04-06 19:01:24 -07001932 printk(KERN_CRIT "%s: key = %llu, level == %d\n",
1933 __func__, (unsigned long long)key, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001934 goto out;
1935 }
1936
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001937 ret = NILFS_BMAP_USE_VBN(bmap) ?
1938 nilfs_btree_propagate_v(btree, path, level, bh) :
1939 nilfs_btree_propagate_p(btree, path, level, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001940
1941 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001942 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001943
1944 return ret;
1945}
1946
1947static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap,
1948 struct buffer_head *bh)
1949{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001950 return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), bh->b_blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07001951}
1952
1953static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree,
1954 struct list_head *lists,
1955 struct buffer_head *bh)
1956{
1957 struct list_head *head;
1958 struct buffer_head *cbh;
1959 struct nilfs_btree_node *node, *cnode;
1960 __u64 key, ckey;
1961 int level;
1962
1963 get_bh(bh);
1964 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001965 key = nilfs_btree_node_get_key(node, 0);
1966 level = nilfs_btree_node_get_level(node);
Ryusuke Konishicfa913a2010-07-07 17:19:54 +09001967 if (level < NILFS_BTREE_LEVEL_NODE_MIN ||
1968 level >= NILFS_BTREE_LEVEL_MAX) {
1969 dump_stack();
1970 printk(KERN_WARNING
1971 "%s: invalid btree level: %d (key=%llu, ino=%lu, "
1972 "blocknr=%llu)\n",
1973 __func__, level, (unsigned long long)key,
1974 NILFS_BMAP_I(&btree->bt_bmap)->vfs_inode.i_ino,
1975 (unsigned long long)bh->b_blocknr);
1976 return;
1977 }
1978
Koji Sato17c76b02009-04-06 19:01:24 -07001979 list_for_each(head, &lists[level]) {
1980 cbh = list_entry(head, struct buffer_head, b_assoc_buffers);
1981 cnode = (struct nilfs_btree_node *)cbh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001982 ckey = nilfs_btree_node_get_key(cnode, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07001983 if (key < ckey)
1984 break;
1985 }
1986 list_add_tail(&bh->b_assoc_buffers, head);
1987}
1988
1989static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *bmap,
1990 struct list_head *listp)
1991{
1992 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
1993 struct address_space *btcache = &NILFS_BMAP_I(bmap)->i_btnode_cache;
1994 struct list_head lists[NILFS_BTREE_LEVEL_MAX];
1995 struct pagevec pvec;
1996 struct buffer_head *bh, *head;
1997 pgoff_t index = 0;
1998 int level, i;
1999
2000 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
2001 level < NILFS_BTREE_LEVEL_MAX;
2002 level++)
2003 INIT_LIST_HEAD(&lists[level]);
2004
2005 pagevec_init(&pvec, 0);
2006
2007 while (pagevec_lookup_tag(&pvec, btcache, &index, PAGECACHE_TAG_DIRTY,
2008 PAGEVEC_SIZE)) {
2009 for (i = 0; i < pagevec_count(&pvec); i++) {
2010 bh = head = page_buffers(pvec.pages[i]);
2011 do {
2012 if (buffer_dirty(bh))
2013 nilfs_btree_add_dirty_buffer(btree,
2014 lists, bh);
2015 } while ((bh = bh->b_this_page) != head);
2016 }
2017 pagevec_release(&pvec);
2018 cond_resched();
2019 }
2020
2021 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
2022 level < NILFS_BTREE_LEVEL_MAX;
2023 level++)
Ryusuke Konishi0935db72009-11-29 02:39:11 +09002024 list_splice_tail(&lists[level], listp);
Koji Sato17c76b02009-04-06 19:01:24 -07002025}
2026
2027static int nilfs_btree_assign_p(struct nilfs_btree *btree,
2028 struct nilfs_btree_path *path,
2029 int level,
2030 struct buffer_head **bh,
2031 sector_t blocknr,
2032 union nilfs_binfo *binfo)
2033{
2034 struct nilfs_btree_node *parent;
2035 __u64 key;
2036 __u64 ptr;
2037 int ret;
2038
2039 parent = nilfs_btree_get_node(btree, path, level + 1);
2040 ptr = nilfs_btree_node_get_ptr(btree, parent,
2041 path[level + 1].bp_index);
2042 if (buffer_nilfs_node(*bh)) {
2043 path[level].bp_ctxt.oldkey = ptr;
2044 path[level].bp_ctxt.newkey = blocknr;
2045 path[level].bp_ctxt.bh = *bh;
2046 ret = nilfs_btnode_prepare_change_key(
2047 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2048 &path[level].bp_ctxt);
2049 if (ret < 0)
2050 return ret;
2051 nilfs_btnode_commit_change_key(
2052 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2053 &path[level].bp_ctxt);
2054 *bh = path[level].bp_ctxt.bh;
2055 }
2056
2057 nilfs_btree_node_set_ptr(btree, parent,
2058 path[level + 1].bp_index, blocknr);
2059
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002060 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002061 /* on-disk format */
2062 binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2063 binfo->bi_dat.bi_level = level;
2064
2065 return 0;
2066}
2067
2068static int nilfs_btree_assign_v(struct nilfs_btree *btree,
2069 struct nilfs_btree_path *path,
2070 int level,
2071 struct buffer_head **bh,
2072 sector_t blocknr,
2073 union nilfs_binfo *binfo)
2074{
2075 struct nilfs_btree_node *parent;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002076 struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07002077 __u64 key;
2078 __u64 ptr;
2079 union nilfs_bmap_ptr_req req;
2080 int ret;
2081
2082 parent = nilfs_btree_get_node(btree, path, level + 1);
2083 ptr = nilfs_btree_node_get_ptr(btree, parent,
2084 path[level + 1].bp_index);
2085 req.bpr_ptr = ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002086 ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
2087 if (ret < 0)
Koji Sato17c76b02009-04-06 19:01:24 -07002088 return ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002089 nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002090
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002091 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002092 /* on-disk format */
2093 binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr);
2094 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2095
2096 return 0;
2097}
2098
2099static int nilfs_btree_assign(struct nilfs_bmap *bmap,
2100 struct buffer_head **bh,
2101 sector_t blocknr,
2102 union nilfs_binfo *binfo)
2103{
2104 struct nilfs_btree *btree;
2105 struct nilfs_btree_path *path;
2106 struct nilfs_btree_node *node;
2107 __u64 key;
2108 int level, ret;
2109
2110 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002111 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002112 if (path == NULL)
2113 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07002114
2115 if (buffer_nilfs_node(*bh)) {
2116 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002117 key = nilfs_btree_node_get_key(node, 0);
2118 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07002119 } else {
2120 key = nilfs_bmap_data_get_key(bmap, *bh);
2121 level = NILFS_BTREE_LEVEL_DATA;
2122 }
2123
2124 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
2125 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002126 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002127 goto out;
2128 }
2129
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09002130 ret = NILFS_BMAP_USE_VBN(bmap) ?
2131 nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) :
2132 nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
Koji Sato17c76b02009-04-06 19:01:24 -07002133
2134 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002135 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002136
2137 return ret;
2138}
2139
2140static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap,
2141 struct buffer_head **bh,
2142 sector_t blocknr,
2143 union nilfs_binfo *binfo)
2144{
Koji Sato17c76b02009-04-06 19:01:24 -07002145 struct nilfs_btree_node *node;
2146 __u64 key;
2147 int ret;
2148
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002149 ret = nilfs_dat_move(nilfs_bmap_get_dat(bmap), (*bh)->b_blocknr,
2150 blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002151 if (ret < 0)
2152 return ret;
2153
2154 if (buffer_nilfs_node(*bh)) {
2155 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002156 key = nilfs_btree_node_get_key(node, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07002157 } else
2158 key = nilfs_bmap_data_get_key(bmap, *bh);
2159
2160 /* on-disk format */
2161 binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr);
2162 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
2163
2164 return 0;
2165}
2166
2167static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
2168{
2169 struct buffer_head *bh;
2170 struct nilfs_btree *btree;
2171 struct nilfs_btree_path *path;
2172 __u64 ptr;
2173 int ret;
2174
2175 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002176 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002177 if (path == NULL)
2178 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07002179
2180 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1);
2181 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002182 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002183 goto out;
2184 }
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09002185 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002186 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002187 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002188 goto out;
2189 }
2190
2191 if (!buffer_dirty(bh))
2192 nilfs_btnode_mark_dirty(bh);
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09002193 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002194 if (!nilfs_bmap_dirty(&btree->bt_bmap))
2195 nilfs_bmap_set_dirty(&btree->bt_bmap);
2196
2197 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002198 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002199 return ret;
2200}
2201
2202static const struct nilfs_bmap_operations nilfs_btree_ops = {
2203 .bop_lookup = nilfs_btree_lookup,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002204 .bop_lookup_contig = nilfs_btree_lookup_contig,
Koji Sato17c76b02009-04-06 19:01:24 -07002205 .bop_insert = nilfs_btree_insert,
2206 .bop_delete = nilfs_btree_delete,
2207 .bop_clear = NULL,
2208
2209 .bop_propagate = nilfs_btree_propagate,
2210
2211 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2212
2213 .bop_assign = nilfs_btree_assign,
2214 .bop_mark = nilfs_btree_mark,
2215
2216 .bop_last_key = nilfs_btree_last_key,
2217 .bop_check_insert = NULL,
2218 .bop_check_delete = nilfs_btree_check_delete,
2219 .bop_gather_data = nilfs_btree_gather_data,
2220};
2221
2222static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
2223 .bop_lookup = NULL,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002224 .bop_lookup_contig = NULL,
Koji Sato17c76b02009-04-06 19:01:24 -07002225 .bop_insert = NULL,
2226 .bop_delete = NULL,
2227 .bop_clear = NULL,
2228
2229 .bop_propagate = nilfs_btree_propagate_gc,
2230
2231 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2232
2233 .bop_assign = nilfs_btree_assign_gc,
2234 .bop_mark = NULL,
2235
2236 .bop_last_key = NULL,
2237 .bop_check_insert = NULL,
2238 .bop_check_delete = NULL,
2239 .bop_gather_data = NULL,
2240};
2241
Ryusuke Konishi30333422009-05-24 00:09:44 +09002242int nilfs_btree_init(struct nilfs_bmap *bmap)
Koji Sato17c76b02009-04-06 19:01:24 -07002243{
Koji Sato17c76b02009-04-06 19:01:24 -07002244 bmap->b_ops = &nilfs_btree_ops;
Koji Sato17c76b02009-04-06 19:01:24 -07002245 return 0;
2246}
2247
2248void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
2249{
Koji Sato17c76b02009-04-06 19:01:24 -07002250 bmap->b_ops = &nilfs_btree_ops_gc;
2251}