blob: b2347f79307245febe8ee58996c43a150fc6131c [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 Konishi25b8d7d2010-07-10 16:50:41 +0900194 return le64_to_cpu(*(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 Konishi25b8d7d2010-07-10 16:50:41 +0900200 *(nilfs_btree_node_dkeys(node) + index) = cpu_to_le64(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 Konishi25b8d7d2010-07-10 16:50:41 +0900207 return le64_to_cpu(*(nilfs_btree_node_dptrs(node, btree) + index));
Koji Sato17c76b02009-04-06 19:01:24 -0700208}
209
210static inline void
211nilfs_btree_node_set_ptr(struct nilfs_btree *btree,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900212 struct nilfs_btree_node *node, int index, __u64 ptr)
Koji Sato17c76b02009-04-06 19:01:24 -0700213{
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900214 *(nilfs_btree_node_dptrs(node, btree) + index) = cpu_to_le64(ptr);
Koji Sato17c76b02009-04-06 19:01:24 -0700215}
216
217static void nilfs_btree_node_init(struct nilfs_btree *btree,
218 struct nilfs_btree_node *node,
219 int flags, int level, int nchildren,
220 const __u64 *keys, const __u64 *ptrs)
221{
222 __le64 *dkeys;
223 __le64 *dptrs;
224 int i;
225
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900226 nilfs_btree_node_set_flags(node, flags);
227 nilfs_btree_node_set_level(node, level);
228 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700229
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900230 dkeys = nilfs_btree_node_dkeys(node);
231 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700232 for (i = 0; i < nchildren; i++) {
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900233 dkeys[i] = cpu_to_le64(keys[i]);
234 dptrs[i] = cpu_to_le64(ptrs[i]);
Koji Sato17c76b02009-04-06 19:01:24 -0700235 }
236}
237
238/* Assume the buffer heads corresponding to left and right are locked. */
239static void nilfs_btree_node_move_left(struct nilfs_btree *btree,
240 struct nilfs_btree_node *left,
241 struct nilfs_btree_node *right,
242 int n)
243{
244 __le64 *ldkeys, *rdkeys;
245 __le64 *ldptrs, *rdptrs;
246 int lnchildren, rnchildren;
247
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900248 ldkeys = nilfs_btree_node_dkeys(left);
249 ldptrs = nilfs_btree_node_dptrs(left, btree);
250 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700251
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900252 rdkeys = nilfs_btree_node_dkeys(right);
253 rdptrs = nilfs_btree_node_dptrs(right, btree);
254 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700255
256 memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys));
257 memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs));
258 memmove(rdkeys, rdkeys + n, (rnchildren - n) * sizeof(*rdkeys));
259 memmove(rdptrs, rdptrs + n, (rnchildren - n) * sizeof(*rdptrs));
260
261 lnchildren += n;
262 rnchildren -= n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900263 nilfs_btree_node_set_nchildren(left, lnchildren);
264 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700265}
266
267/* Assume that the buffer heads corresponding to left and right are locked. */
268static void nilfs_btree_node_move_right(struct nilfs_btree *btree,
269 struct nilfs_btree_node *left,
270 struct nilfs_btree_node *right,
271 int n)
272{
273 __le64 *ldkeys, *rdkeys;
274 __le64 *ldptrs, *rdptrs;
275 int lnchildren, rnchildren;
276
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900277 ldkeys = nilfs_btree_node_dkeys(left);
278 ldptrs = nilfs_btree_node_dptrs(left, btree);
279 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700280
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900281 rdkeys = nilfs_btree_node_dkeys(right);
282 rdptrs = nilfs_btree_node_dptrs(right, btree);
283 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700284
285 memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys));
286 memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs));
287 memcpy(rdkeys, ldkeys + lnchildren - n, n * sizeof(*rdkeys));
288 memcpy(rdptrs, ldptrs + lnchildren - n, n * sizeof(*rdptrs));
289
290 lnchildren -= n;
291 rnchildren += n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900292 nilfs_btree_node_set_nchildren(left, lnchildren);
293 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700294}
295
296/* Assume that the buffer head corresponding to node is locked. */
297static void nilfs_btree_node_insert(struct nilfs_btree *btree,
298 struct nilfs_btree_node *node,
299 __u64 key, __u64 ptr, int index)
300{
301 __le64 *dkeys;
302 __le64 *dptrs;
303 int nchildren;
304
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900305 dkeys = nilfs_btree_node_dkeys(node);
306 dptrs = nilfs_btree_node_dptrs(node, btree);
307 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700308 if (index < nchildren) {
309 memmove(dkeys + index + 1, dkeys + index,
310 (nchildren - index) * sizeof(*dkeys));
311 memmove(dptrs + index + 1, dptrs + index,
312 (nchildren - index) * sizeof(*dptrs));
313 }
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900314 dkeys[index] = cpu_to_le64(key);
315 dptrs[index] = cpu_to_le64(ptr);
Koji Sato17c76b02009-04-06 19:01:24 -0700316 nchildren++;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900317 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700318}
319
320/* Assume that the buffer head corresponding to node is locked. */
321static void nilfs_btree_node_delete(struct nilfs_btree *btree,
322 struct nilfs_btree_node *node,
323 __u64 *keyp, __u64 *ptrp, int index)
324{
325 __u64 key;
326 __u64 ptr;
327 __le64 *dkeys;
328 __le64 *dptrs;
329 int nchildren;
330
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900331 dkeys = nilfs_btree_node_dkeys(node);
332 dptrs = nilfs_btree_node_dptrs(node, btree);
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900333 key = le64_to_cpu(dkeys[index]);
334 ptr = le64_to_cpu(dptrs[index]);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900335 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700336 if (keyp != NULL)
337 *keyp = key;
338 if (ptrp != NULL)
339 *ptrp = ptr;
340
341 if (index < nchildren - 1) {
342 memmove(dkeys + index, dkeys + index + 1,
343 (nchildren - index - 1) * sizeof(*dkeys));
344 memmove(dptrs + index, dptrs + index + 1,
345 (nchildren - index - 1) * sizeof(*dptrs));
346 }
347 nchildren--;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900348 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700349}
350
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900351static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node,
Koji Sato17c76b02009-04-06 19:01:24 -0700352 __u64 key, int *indexp)
353{
354 __u64 nkey;
355 int index, low, high, s;
356
357 /* binary search */
358 low = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900359 high = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700360 index = 0;
361 s = 0;
362 while (low <= high) {
363 index = (low + high) / 2;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900364 nkey = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700365 if (nkey == key) {
366 s = 0;
367 goto out;
368 } else if (nkey < key) {
369 low = index + 1;
370 s = -1;
371 } else {
372 high = index - 1;
373 s = 1;
374 }
375 }
376
377 /* adjust index */
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900378 if (nilfs_btree_node_get_level(node) > NILFS_BTREE_LEVEL_NODE_MIN) {
379 if (s > 0 && index > 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700380 index--;
381 } else if (s < 0)
382 index++;
383
384 out:
Koji Sato17c76b02009-04-06 19:01:24 -0700385 *indexp = index;
386
387 return s == 0;
388}
389
Ryusuke Konishi1d5385b2010-07-16 23:52:40 +0900390/**
391 * nilfs_btree_node_broken - verify consistency of btree node
392 * @node: btree node block to be examined
393 * @size: node size (in bytes)
394 * @blocknr: block number
395 *
396 * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned.
397 */
398static int nilfs_btree_node_broken(const struct nilfs_btree_node *node,
399 size_t size, sector_t blocknr)
400{
401 int level, flags, nchildren;
402 int ret = 0;
403
404 level = nilfs_btree_node_get_level(node);
405 flags = nilfs_btree_node_get_flags(node);
406 nchildren = nilfs_btree_node_get_nchildren(node);
407
408 if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
409 level >= NILFS_BTREE_LEVEL_MAX ||
410 (flags & NILFS_BTREE_NODE_ROOT) ||
411 nchildren < 0 ||
412 nchildren > NILFS_BTREE_NODE_NCHILDREN_MAX(size))) {
413 printk(KERN_CRIT "NILFS: bad btree node (blocknr=%llu): "
414 "level = %d, flags = 0x%x, nchildren = %d\n",
415 (unsigned long long)blocknr, level, flags, nchildren);
416 ret = 1;
417 }
418 return ret;
419}
420
421int nilfs_btree_broken_node_block(struct buffer_head *bh)
422{
423 return nilfs_btree_node_broken((struct nilfs_btree_node *)bh->b_data,
424 bh->b_size, bh->b_blocknr);
425}
426
Koji Sato17c76b02009-04-06 19:01:24 -0700427static inline struct nilfs_btree_node *
428nilfs_btree_get_root(const struct nilfs_btree *btree)
429{
430 return (struct nilfs_btree_node *)btree->bt_bmap.b_u.u_data;
431}
432
433static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900434nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700435{
436 return (struct nilfs_btree_node *)path[level].bp_bh->b_data;
437}
438
439static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900440nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700441{
442 return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data;
443}
444
445static inline int nilfs_btree_height(const struct nilfs_btree *btree)
446{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900447 return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700448}
449
450static inline struct nilfs_btree_node *
451nilfs_btree_get_node(const struct nilfs_btree *btree,
452 const struct nilfs_btree_path *path,
453 int level)
454{
455 return (level == nilfs_btree_height(btree) - 1) ?
456 nilfs_btree_get_root(btree) :
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900457 nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700458}
459
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900460static inline int
461nilfs_btree_bad_node(struct nilfs_btree_node *node, int level)
462{
463 if (unlikely(nilfs_btree_node_get_level(node) != level)) {
464 dump_stack();
465 printk(KERN_CRIT "NILFS: btree level mismatch: %d != %d\n",
466 nilfs_btree_node_get_level(node), level);
467 return 1;
468 }
469 return 0;
470}
471
Koji Sato17c76b02009-04-06 19:01:24 -0700472static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
473 struct nilfs_btree_path *path,
474 __u64 key, __u64 *ptrp, int minlevel)
475{
476 struct nilfs_btree_node *node;
477 __u64 ptr;
478 int level, index, found, ret;
479
Koji Sato17c76b02009-04-06 19:01:24 -0700480 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900481 level = nilfs_btree_node_get_level(node);
482 if (level < minlevel || nilfs_btree_node_get_nchildren(node) <= 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700483 return -ENOENT;
484
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900485 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700486 ptr = nilfs_btree_node_get_ptr(btree, node, index);
487 path[level].bp_bh = NULL;
488 path[level].bp_index = index;
489
490 for (level--; level >= minlevel; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900491 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700492 if (ret < 0)
493 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900494 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900495 if (nilfs_btree_bad_node(node, level))
496 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -0700497 if (!found)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900498 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700499 else
500 index = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900501 if (index < nilfs_btree_node_nchildren_max(node, btree))
Koji Sato17c76b02009-04-06 19:01:24 -0700502 ptr = nilfs_btree_node_get_ptr(btree, node, index);
503 else {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700504 WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN);
Koji Sato17c76b02009-04-06 19:01:24 -0700505 /* 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
519static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree,
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);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900528 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700529 if (index < 0)
530 return -ENOENT;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900531 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700532 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--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900537 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700538 if (ret < 0)
539 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900540 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900541 if (nilfs_btree_bad_node(node, level))
542 return -EINVAL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900543 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700544 ptr = nilfs_btree_node_get_ptr(btree, node, index);
545 path[level].bp_index = index;
546 }
547
548 if (keyp != NULL)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900549 *keyp = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700550 if (ptrp != NULL)
551 *ptrp = ptr;
552
553 return 0;
554}
555
556static int nilfs_btree_lookup(const struct nilfs_bmap *bmap,
557 __u64 key, int level, __u64 *ptrp)
558{
559 struct nilfs_btree *btree;
560 struct nilfs_btree_path *path;
561 __u64 ptr;
562 int ret;
563
564 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900565 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -0700566 if (path == NULL)
567 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -0700568
569 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
570
571 if (ptrp != NULL)
572 *ptrp = ptr;
573
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900574 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -0700575
576 return ret;
577}
578
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900579static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
580 __u64 key, __u64 *ptrp, unsigned maxblocks)
581{
582 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
583 struct nilfs_btree_path *path;
584 struct nilfs_btree_node *node;
585 struct inode *dat = NULL;
586 __u64 ptr, ptr2;
587 sector_t blocknr;
588 int level = NILFS_BTREE_LEVEL_NODE_MIN;
589 int ret, cnt, index, maxlevel;
590
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900591 path = nilfs_btree_alloc_path();
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900592 if (path == NULL)
593 return -ENOMEM;
Li Hongf9054402010-04-02 17:36:34 +0800594
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900595 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
596 if (ret < 0)
597 goto out;
598
599 if (NILFS_BMAP_USE_VBN(bmap)) {
600 dat = nilfs_bmap_get_dat(bmap);
601 ret = nilfs_dat_translate(dat, ptr, &blocknr);
602 if (ret < 0)
603 goto out;
604 ptr = blocknr;
605 }
606 cnt = 1;
607 if (cnt == maxblocks)
608 goto end;
609
610 maxlevel = nilfs_btree_height(btree) - 1;
611 node = nilfs_btree_get_node(btree, path, level);
612 index = path[level].bp_index + 1;
613 for (;;) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900614 while (index < nilfs_btree_node_get_nchildren(node)) {
615 if (nilfs_btree_node_get_key(node, index) !=
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900616 key + cnt)
617 goto end;
618 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
619 if (dat) {
620 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
621 if (ret < 0)
622 goto out;
623 ptr2 = blocknr;
624 }
625 if (ptr2 != ptr + cnt || ++cnt == maxblocks)
626 goto end;
627 index++;
628 continue;
629 }
630 if (level == maxlevel)
631 break;
632
633 /* look-up right sibling node */
634 node = nilfs_btree_get_node(btree, path, level + 1);
635 index = path[level + 1].bp_index + 1;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900636 if (index >= nilfs_btree_node_get_nchildren(node) ||
637 nilfs_btree_node_get_key(node, index) != key + cnt)
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900638 break;
639 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
640 path[level + 1].bp_index = index;
641
642 brelse(path[level].bp_bh);
643 path[level].bp_bh = NULL;
644 ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh);
645 if (ret < 0)
646 goto out;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900647 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900648 index = 0;
649 path[level].bp_index = index;
650 }
651 end:
652 *ptrp = ptr;
653 ret = cnt;
654 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900655 nilfs_btree_free_path(path);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900656 return ret;
657}
658
Koji Sato17c76b02009-04-06 19:01:24 -0700659static void nilfs_btree_promote_key(struct nilfs_btree *btree,
660 struct nilfs_btree_path *path,
661 int level, __u64 key)
662{
663 if (level < nilfs_btree_height(btree) - 1) {
664 do {
Koji Sato17c76b02009-04-06 19:01:24 -0700665 nilfs_btree_node_set_key(
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900666 nilfs_btree_get_nonroot_node(path, level),
Koji Sato17c76b02009-04-06 19:01:24 -0700667 path[level].bp_index, key);
668 if (!buffer_dirty(path[level].bp_bh))
669 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700670 } while ((path[level].bp_index == 0) &&
671 (++level < nilfs_btree_height(btree) - 1));
672 }
673
674 /* root */
675 if (level == nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900676 nilfs_btree_node_set_key(nilfs_btree_get_root(btree),
Koji Sato17c76b02009-04-06 19:01:24 -0700677 path[level].bp_index, key);
678 }
679}
680
681static void nilfs_btree_do_insert(struct nilfs_btree *btree,
682 struct nilfs_btree_path *path,
683 int level, __u64 *keyp, __u64 *ptrp)
684{
685 struct nilfs_btree_node *node;
686
687 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900688 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700689 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
690 path[level].bp_index);
691 if (!buffer_dirty(path[level].bp_bh))
692 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700693
694 if (path[level].bp_index == 0)
695 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900696 nilfs_btree_node_get_key(node,
697 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700698 } else {
699 node = nilfs_btree_get_root(btree);
700 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
701 path[level].bp_index);
702 }
703}
704
705static void nilfs_btree_carry_left(struct nilfs_btree *btree,
706 struct nilfs_btree_path *path,
707 int level, __u64 *keyp, __u64 *ptrp)
708{
709 struct nilfs_btree_node *node, *left;
710 int nchildren, lnchildren, n, move;
711
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900712 node = nilfs_btree_get_nonroot_node(path, level);
713 left = nilfs_btree_get_sib_node(path, level);
714 nchildren = nilfs_btree_node_get_nchildren(node);
715 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700716 move = 0;
717
718 n = (nchildren + lnchildren + 1) / 2 - lnchildren;
719 if (n > path[level].bp_index) {
720 /* move insert point */
721 n--;
722 move = 1;
723 }
724
725 nilfs_btree_node_move_left(btree, left, node, n);
726
727 if (!buffer_dirty(path[level].bp_bh))
728 nilfs_btnode_mark_dirty(path[level].bp_bh);
729 if (!buffer_dirty(path[level].bp_sib_bh))
730 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
731
Koji Sato17c76b02009-04-06 19:01:24 -0700732 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900733 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700734
735 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900736 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700737 path[level].bp_bh = path[level].bp_sib_bh;
738 path[level].bp_sib_bh = NULL;
739 path[level].bp_index += lnchildren;
740 path[level + 1].bp_index--;
741 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900742 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700743 path[level].bp_sib_bh = NULL;
744 path[level].bp_index -= n;
745 }
746
747 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
748}
749
750static void nilfs_btree_carry_right(struct nilfs_btree *btree,
751 struct nilfs_btree_path *path,
752 int level, __u64 *keyp, __u64 *ptrp)
753{
754 struct nilfs_btree_node *node, *right;
755 int nchildren, rnchildren, n, move;
756
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900757 node = nilfs_btree_get_nonroot_node(path, level);
758 right = nilfs_btree_get_sib_node(path, level);
759 nchildren = nilfs_btree_node_get_nchildren(node);
760 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700761 move = 0;
762
763 n = (nchildren + rnchildren + 1) / 2 - rnchildren;
764 if (n > nchildren - path[level].bp_index) {
765 /* move insert point */
766 n--;
767 move = 1;
768 }
769
770 nilfs_btree_node_move_right(btree, node, right, n);
771
772 if (!buffer_dirty(path[level].bp_bh))
773 nilfs_btnode_mark_dirty(path[level].bp_bh);
774 if (!buffer_dirty(path[level].bp_sib_bh))
775 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
776
Koji Sato17c76b02009-04-06 19:01:24 -0700777 path[level + 1].bp_index++;
778 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900779 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700780 path[level + 1].bp_index--;
781
782 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900783 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700784 path[level].bp_bh = path[level].bp_sib_bh;
785 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900786 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700787 path[level + 1].bp_index++;
788 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900789 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700790 path[level].bp_sib_bh = NULL;
791 }
792
793 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
794}
795
796static void nilfs_btree_split(struct nilfs_btree *btree,
797 struct nilfs_btree_path *path,
798 int level, __u64 *keyp, __u64 *ptrp)
799{
800 struct nilfs_btree_node *node, *right;
801 __u64 newkey;
802 __u64 newptr;
803 int nchildren, n, move;
804
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900805 node = nilfs_btree_get_nonroot_node(path, level);
806 right = nilfs_btree_get_sib_node(path, level);
807 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700808 move = 0;
809
810 n = (nchildren + 1) / 2;
811 if (n > nchildren - path[level].bp_index) {
812 n--;
813 move = 1;
814 }
815
816 nilfs_btree_node_move_right(btree, node, right, n);
817
818 if (!buffer_dirty(path[level].bp_bh))
819 nilfs_btnode_mark_dirty(path[level].bp_bh);
820 if (!buffer_dirty(path[level].bp_sib_bh))
821 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
822
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900823 newkey = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700824 newptr = path[level].bp_newreq.bpr_ptr;
825
826 if (move) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900827 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700828 nilfs_btree_node_insert(btree, right, *keyp, *ptrp,
829 path[level].bp_index);
830
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900831 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700832 *ptrp = path[level].bp_newreq.bpr_ptr;
833
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900834 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700835 path[level].bp_bh = path[level].bp_sib_bh;
836 path[level].bp_sib_bh = NULL;
837 } else {
838 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
839
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900840 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700841 *ptrp = path[level].bp_newreq.bpr_ptr;
842
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900843 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700844 path[level].bp_sib_bh = NULL;
845 }
846
847 path[level + 1].bp_index++;
848}
849
850static void nilfs_btree_grow(struct nilfs_btree *btree,
851 struct nilfs_btree_path *path,
852 int level, __u64 *keyp, __u64 *ptrp)
853{
854 struct nilfs_btree_node *root, *child;
855 int n;
856
Koji Sato17c76b02009-04-06 19:01:24 -0700857 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900858 child = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700859
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900860 n = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -0700861
862 nilfs_btree_node_move_right(btree, root, child, n);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900863 nilfs_btree_node_set_level(root, level + 1);
Koji Sato17c76b02009-04-06 19:01:24 -0700864
865 if (!buffer_dirty(path[level].bp_sib_bh))
866 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
867
Koji Sato17c76b02009-04-06 19:01:24 -0700868 path[level].bp_bh = path[level].bp_sib_bh;
869 path[level].bp_sib_bh = NULL;
870
871 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
872
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900873 *keyp = nilfs_btree_node_get_key(child, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700874 *ptrp = path[level].bp_newreq.bpr_ptr;
875}
876
877static __u64 nilfs_btree_find_near(const struct nilfs_btree *btree,
878 const struct nilfs_btree_path *path)
879{
880 struct nilfs_btree_node *node;
881 int level;
882
883 if (path == NULL)
884 return NILFS_BMAP_INVALID_PTR;
885
886 /* left sibling */
887 level = NILFS_BTREE_LEVEL_NODE_MIN;
888 if (path[level].bp_index > 0) {
889 node = nilfs_btree_get_node(btree, path, level);
890 return nilfs_btree_node_get_ptr(btree, node,
891 path[level].bp_index - 1);
892 }
893
894 /* parent */
895 level = NILFS_BTREE_LEVEL_NODE_MIN + 1;
896 if (level <= nilfs_btree_height(btree) - 1) {
897 node = nilfs_btree_get_node(btree, path, level);
898 return nilfs_btree_node_get_ptr(btree, node,
899 path[level].bp_index);
900 }
901
902 return NILFS_BMAP_INVALID_PTR;
903}
904
905static __u64 nilfs_btree_find_target_v(const struct nilfs_btree *btree,
906 const struct nilfs_btree_path *path,
907 __u64 key)
908{
909 __u64 ptr;
910
911 ptr = nilfs_bmap_find_target_seq(&btree->bt_bmap, key);
912 if (ptr != NILFS_BMAP_INVALID_PTR)
913 /* sequential access */
914 return ptr;
915 else {
916 ptr = nilfs_btree_find_near(btree, path);
917 if (ptr != NILFS_BMAP_INVALID_PTR)
918 /* near */
919 return ptr;
920 }
921 /* block group */
922 return nilfs_bmap_find_target_in_group(&btree->bt_bmap);
923}
924
925static void nilfs_btree_set_target_v(struct nilfs_btree *btree, __u64 key,
926 __u64 ptr)
927{
928 btree->bt_bmap.b_last_allocated_key = key;
929 btree->bt_bmap.b_last_allocated_ptr = ptr;
930}
931
932static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
933 struct nilfs_btree_path *path,
934 int *levelp, __u64 key, __u64 ptr,
935 struct nilfs_bmap_stats *stats)
936{
937 struct buffer_head *bh;
938 struct nilfs_btree_node *node, *parent, *sib;
939 __u64 sibptr;
940 int pindex, level, ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900941 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -0700942
943 stats->bs_nblocks = 0;
944 level = NILFS_BTREE_LEVEL_DATA;
945
946 /* allocate a new ptr for data block */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900947 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700948 path[level].bp_newreq.bpr_ptr =
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +0900949 nilfs_btree_find_target_v(btree, path, key);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900950 dat = nilfs_bmap_get_dat(&btree->bt_bmap);
951 }
Koji Sato17c76b02009-04-06 19:01:24 -0700952
Ryusuke Konishid4b96152009-05-24 03:25:44 +0900953 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900954 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -0700955 if (ret < 0)
956 goto err_out_data;
957
958 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
959 level < nilfs_btree_height(btree) - 1;
960 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900961 node = nilfs_btree_get_nonroot_node(path, level);
962 if (nilfs_btree_node_get_nchildren(node) <
963 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700964 path[level].bp_op = nilfs_btree_do_insert;
965 stats->bs_nblocks++;
966 goto out;
967 }
968
969 parent = nilfs_btree_get_node(btree, path, level + 1);
970 pindex = path[level + 1].bp_index;
971
972 /* left sibling */
973 if (pindex > 0) {
974 sibptr = nilfs_btree_node_get_ptr(btree, parent,
975 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900976 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700977 if (ret < 0)
978 goto err_out_child_node;
979 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900980 if (nilfs_btree_node_get_nchildren(sib) <
981 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700982 path[level].bp_sib_bh = bh;
983 path[level].bp_op = nilfs_btree_carry_left;
984 stats->bs_nblocks++;
985 goto out;
986 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900987 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700988 }
989
990 /* right sibling */
991 if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900992 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -0700993 sibptr = nilfs_btree_node_get_ptr(btree, parent,
994 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900995 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700996 if (ret < 0)
997 goto err_out_child_node;
998 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900999 if (nilfs_btree_node_get_nchildren(sib) <
1000 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001001 path[level].bp_sib_bh = bh;
1002 path[level].bp_op = nilfs_btree_carry_right;
1003 stats->bs_nblocks++;
1004 goto out;
1005 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001006 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001007 }
1008
1009 /* split */
1010 path[level].bp_newreq.bpr_ptr =
1011 path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001012 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001013 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001014 if (ret < 0)
1015 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001016 ret = nilfs_btree_get_new_block(btree,
1017 path[level].bp_newreq.bpr_ptr,
1018 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001019 if (ret < 0)
1020 goto err_out_curr_node;
1021
1022 stats->bs_nblocks++;
1023
Koji Sato17c76b02009-04-06 19:01:24 -07001024 nilfs_btree_node_init(btree,
1025 (struct nilfs_btree_node *)bh->b_data,
1026 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001027 path[level].bp_sib_bh = bh;
1028 path[level].bp_op = nilfs_btree_split;
1029 }
1030
1031 /* root */
1032 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001033 if (nilfs_btree_node_get_nchildren(node) <
1034 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001035 path[level].bp_op = nilfs_btree_do_insert;
1036 stats->bs_nblocks++;
1037 goto out;
1038 }
1039
1040 /* grow */
1041 path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001042 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001043 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001044 if (ret < 0)
1045 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001046 ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
1047 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001048 if (ret < 0)
1049 goto err_out_curr_node;
1050
Koji Sato17c76b02009-04-06 19:01:24 -07001051 nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data,
1052 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001053 path[level].bp_sib_bh = bh;
1054 path[level].bp_op = nilfs_btree_grow;
1055
1056 level++;
1057 path[level].bp_op = nilfs_btree_do_insert;
1058
1059 /* a newly-created node block and a data block are added */
1060 stats->bs_nblocks += 2;
1061
1062 /* success */
1063 out:
1064 *levelp = level;
1065 return ret;
1066
1067 /* error */
1068 err_out_curr_node:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001069 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
1070 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001071 err_out_child_node:
1072 for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001073 nilfs_btnode_delete(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001074 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001075 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001076
1077 }
1078
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001079 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq,
1080 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001081 err_out_data:
1082 *levelp = level;
1083 stats->bs_nblocks = 0;
1084 return ret;
1085}
1086
1087static void nilfs_btree_commit_insert(struct nilfs_btree *btree,
1088 struct nilfs_btree_path *path,
1089 int maxlevel, __u64 key, __u64 ptr)
1090{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001091 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001092 int level;
1093
1094 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1095 ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001096 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001097 nilfs_btree_set_target_v(btree, key, ptr);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001098 dat = nilfs_bmap_get_dat(&btree->bt_bmap);
1099 }
Koji Sato17c76b02009-04-06 19:01:24 -07001100
1101 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001102 nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001103 &path[level - 1].bp_newreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001104 path[level].bp_op(btree, path, level, &key, &ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001105 }
1106
1107 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1108 nilfs_bmap_set_dirty(&btree->bt_bmap);
1109}
1110
1111static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
1112{
1113 struct nilfs_btree *btree;
1114 struct nilfs_btree_path *path;
1115 struct nilfs_bmap_stats stats;
1116 int level, ret;
1117
1118 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001119 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001120 if (path == NULL)
1121 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001122
1123 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1124 NILFS_BTREE_LEVEL_NODE_MIN);
1125 if (ret != -ENOENT) {
1126 if (ret == 0)
1127 ret = -EEXIST;
1128 goto out;
1129 }
1130
1131 ret = nilfs_btree_prepare_insert(btree, path, &level, key, ptr, &stats);
1132 if (ret < 0)
1133 goto out;
1134 nilfs_btree_commit_insert(btree, path, level, key, ptr);
1135 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1136
1137 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001138 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001139 return ret;
1140}
1141
1142static void nilfs_btree_do_delete(struct nilfs_btree *btree,
1143 struct nilfs_btree_path *path,
1144 int level, __u64 *keyp, __u64 *ptrp)
1145{
1146 struct nilfs_btree_node *node;
1147
1148 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001149 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001150 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1151 path[level].bp_index);
1152 if (!buffer_dirty(path[level].bp_bh))
1153 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001154 if (path[level].bp_index == 0)
1155 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001156 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001157 } else {
1158 node = nilfs_btree_get_root(btree);
1159 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1160 path[level].bp_index);
1161 }
1162}
1163
1164static void nilfs_btree_borrow_left(struct nilfs_btree *btree,
1165 struct nilfs_btree_path *path,
1166 int level, __u64 *keyp, __u64 *ptrp)
1167{
1168 struct nilfs_btree_node *node, *left;
1169 int nchildren, lnchildren, n;
1170
1171 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1172
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001173 node = nilfs_btree_get_nonroot_node(path, level);
1174 left = nilfs_btree_get_sib_node(path, level);
1175 nchildren = nilfs_btree_node_get_nchildren(node);
1176 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001177
1178 n = (nchildren + lnchildren) / 2 - nchildren;
1179
1180 nilfs_btree_node_move_right(btree, left, node, n);
1181
1182 if (!buffer_dirty(path[level].bp_bh))
1183 nilfs_btnode_mark_dirty(path[level].bp_bh);
1184 if (!buffer_dirty(path[level].bp_sib_bh))
1185 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1186
Koji Sato17c76b02009-04-06 19:01:24 -07001187 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001188 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001189
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001190 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001191 path[level].bp_sib_bh = NULL;
1192 path[level].bp_index += n;
1193}
1194
1195static void nilfs_btree_borrow_right(struct nilfs_btree *btree,
1196 struct nilfs_btree_path *path,
1197 int level, __u64 *keyp, __u64 *ptrp)
1198{
1199 struct nilfs_btree_node *node, *right;
1200 int nchildren, rnchildren, n;
1201
1202 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1203
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001204 node = nilfs_btree_get_nonroot_node(path, level);
1205 right = nilfs_btree_get_sib_node(path, level);
1206 nchildren = nilfs_btree_node_get_nchildren(node);
1207 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001208
1209 n = (nchildren + rnchildren) / 2 - nchildren;
1210
1211 nilfs_btree_node_move_left(btree, node, right, n);
1212
1213 if (!buffer_dirty(path[level].bp_bh))
1214 nilfs_btnode_mark_dirty(path[level].bp_bh);
1215 if (!buffer_dirty(path[level].bp_sib_bh))
1216 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1217
Koji Sato17c76b02009-04-06 19:01:24 -07001218 path[level + 1].bp_index++;
1219 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001220 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001221 path[level + 1].bp_index--;
1222
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001223 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001224 path[level].bp_sib_bh = NULL;
1225}
1226
1227static void nilfs_btree_concat_left(struct nilfs_btree *btree,
1228 struct nilfs_btree_path *path,
1229 int level, __u64 *keyp, __u64 *ptrp)
1230{
1231 struct nilfs_btree_node *node, *left;
1232 int n;
1233
1234 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1235
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001236 node = nilfs_btree_get_nonroot_node(path, level);
1237 left = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001238
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001239 n = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001240
1241 nilfs_btree_node_move_left(btree, left, node, n);
1242
1243 if (!buffer_dirty(path[level].bp_sib_bh))
1244 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1245
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001246 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001247 path[level].bp_bh = path[level].bp_sib_bh;
1248 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001249 path[level].bp_index += nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001250}
1251
1252static void nilfs_btree_concat_right(struct nilfs_btree *btree,
1253 struct nilfs_btree_path *path,
1254 int level, __u64 *keyp, __u64 *ptrp)
1255{
1256 struct nilfs_btree_node *node, *right;
1257 int n;
1258
1259 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1260
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001261 node = nilfs_btree_get_nonroot_node(path, level);
1262 right = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001263
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001264 n = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001265
1266 nilfs_btree_node_move_left(btree, node, right, n);
1267
1268 if (!buffer_dirty(path[level].bp_bh))
1269 nilfs_btnode_mark_dirty(path[level].bp_bh);
1270
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001271 nilfs_btnode_delete(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001272 path[level].bp_sib_bh = NULL;
1273 path[level + 1].bp_index++;
1274}
1275
1276static void nilfs_btree_shrink(struct nilfs_btree *btree,
1277 struct nilfs_btree_path *path,
1278 int level, __u64 *keyp, __u64 *ptrp)
1279{
1280 struct nilfs_btree_node *root, *child;
1281 int n;
1282
1283 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1284
Koji Sato17c76b02009-04-06 19:01:24 -07001285 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001286 child = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001287
1288 nilfs_btree_node_delete(btree, root, NULL, NULL, 0);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001289 nilfs_btree_node_set_level(root, level);
1290 n = nilfs_btree_node_get_nchildren(child);
Koji Sato17c76b02009-04-06 19:01:24 -07001291 nilfs_btree_node_move_left(btree, root, child, n);
Koji Sato17c76b02009-04-06 19:01:24 -07001292
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001293 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001294 path[level].bp_bh = NULL;
1295}
1296
1297
1298static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
1299 struct nilfs_btree_path *path,
1300 int *levelp,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001301 struct nilfs_bmap_stats *stats,
1302 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001303{
1304 struct buffer_head *bh;
1305 struct nilfs_btree_node *node, *parent, *sib;
1306 __u64 sibptr;
1307 int pindex, level, ret;
1308
1309 ret = 0;
1310 stats->bs_nblocks = 0;
1311 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1312 level < nilfs_btree_height(btree) - 1;
1313 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001314 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001315 path[level].bp_oldreq.bpr_ptr =
1316 nilfs_btree_node_get_ptr(btree, node,
1317 path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001318 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001319 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001320 if (ret < 0)
1321 goto err_out_child_node;
Koji Sato17c76b02009-04-06 19:01:24 -07001322
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001323 if (nilfs_btree_node_get_nchildren(node) >
1324 nilfs_btree_node_nchildren_min(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001325 path[level].bp_op = nilfs_btree_do_delete;
1326 stats->bs_nblocks++;
1327 goto out;
1328 }
1329
1330 parent = nilfs_btree_get_node(btree, path, level + 1);
1331 pindex = path[level + 1].bp_index;
1332
1333 if (pindex > 0) {
1334 /* left sibling */
1335 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1336 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001337 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001338 if (ret < 0)
1339 goto err_out_curr_node;
1340 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001341 if (nilfs_btree_node_get_nchildren(sib) >
1342 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001343 path[level].bp_sib_bh = bh;
1344 path[level].bp_op = nilfs_btree_borrow_left;
1345 stats->bs_nblocks++;
1346 goto out;
1347 } else {
1348 path[level].bp_sib_bh = bh;
1349 path[level].bp_op = nilfs_btree_concat_left;
1350 stats->bs_nblocks++;
1351 /* continue; */
1352 }
1353 } else if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001354 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -07001355 /* right sibling */
1356 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1357 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001358 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001359 if (ret < 0)
1360 goto err_out_curr_node;
1361 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001362 if (nilfs_btree_node_get_nchildren(sib) >
1363 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001364 path[level].bp_sib_bh = bh;
1365 path[level].bp_op = nilfs_btree_borrow_right;
1366 stats->bs_nblocks++;
1367 goto out;
1368 } else {
1369 path[level].bp_sib_bh = bh;
1370 path[level].bp_op = nilfs_btree_concat_right;
1371 stats->bs_nblocks++;
1372 /* continue; */
1373 }
1374 } else {
1375 /* no siblings */
1376 /* the only child of the root node */
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001377 WARN_ON(level != nilfs_btree_height(btree) - 2);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001378 if (nilfs_btree_node_get_nchildren(node) - 1 <=
Koji Sato17c76b02009-04-06 19:01:24 -07001379 NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1380 path[level].bp_op = nilfs_btree_shrink;
1381 stats->bs_nblocks += 2;
1382 } else {
1383 path[level].bp_op = nilfs_btree_do_delete;
1384 stats->bs_nblocks++;
1385 }
1386
1387 goto out;
1388
1389 }
1390 }
1391
1392 node = nilfs_btree_get_root(btree);
1393 path[level].bp_oldreq.bpr_ptr =
1394 nilfs_btree_node_get_ptr(btree, node, path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001395
1396 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001397 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001398 if (ret < 0)
1399 goto err_out_child_node;
1400
Koji Sato17c76b02009-04-06 19:01:24 -07001401 /* child of the root node is deleted */
1402 path[level].bp_op = nilfs_btree_do_delete;
1403 stats->bs_nblocks++;
1404
1405 /* success */
1406 out:
1407 *levelp = level;
1408 return ret;
1409
1410 /* error */
1411 err_out_curr_node:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001412 nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001413 err_out_child_node:
1414 for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001415 brelse(path[level].bp_sib_bh);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001416 nilfs_bmap_abort_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001417 &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001418 }
1419 *levelp = level;
1420 stats->bs_nblocks = 0;
1421 return ret;
1422}
1423
1424static void nilfs_btree_commit_delete(struct nilfs_btree *btree,
1425 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001426 int maxlevel, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001427{
1428 int level;
1429
1430 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001431 nilfs_bmap_commit_end_ptr(&btree->bt_bmap,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001432 &path[level].bp_oldreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001433 path[level].bp_op(btree, path, level, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001434 }
1435
1436 if (!nilfs_bmap_dirty(&btree->bt_bmap))
1437 nilfs_bmap_set_dirty(&btree->bt_bmap);
1438}
1439
1440static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key)
1441
1442{
1443 struct nilfs_btree *btree;
1444 struct nilfs_btree_path *path;
1445 struct nilfs_bmap_stats stats;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001446 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001447 int level, ret;
1448
1449 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001450 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001451 if (path == NULL)
1452 return -ENOMEM;
Li Hongf9054402010-04-02 17:36:34 +08001453
Koji Sato17c76b02009-04-06 19:01:24 -07001454 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1455 NILFS_BTREE_LEVEL_NODE_MIN);
1456 if (ret < 0)
1457 goto out;
1458
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001459
1460 dat = NILFS_BMAP_USE_VBN(&btree->bt_bmap) ?
1461 nilfs_bmap_get_dat(&btree->bt_bmap) : NULL;
1462
1463 ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001464 if (ret < 0)
1465 goto out;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001466 nilfs_btree_commit_delete(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001467 nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks);
1468
1469out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001470 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001471 return ret;
1472}
1473
1474static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp)
1475{
1476 struct nilfs_btree *btree;
1477 struct nilfs_btree_path *path;
1478 int ret;
1479
1480 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001481 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001482 if (path == NULL)
1483 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001484
1485 ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL);
1486
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001487 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001488
1489 return ret;
1490}
1491
1492static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key)
1493{
1494 struct buffer_head *bh;
1495 struct nilfs_btree *btree;
1496 struct nilfs_btree_node *root, *node;
1497 __u64 maxkey, nextmaxkey;
1498 __u64 ptr;
1499 int nchildren, ret;
1500
1501 btree = (struct nilfs_btree *)bmap;
1502 root = nilfs_btree_get_root(btree);
1503 switch (nilfs_btree_height(btree)) {
1504 case 2:
1505 bh = NULL;
1506 node = root;
1507 break;
1508 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001509 nchildren = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -07001510 if (nchildren > 1)
1511 return 0;
1512 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001513 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001514 if (ret < 0)
1515 return ret;
1516 node = (struct nilfs_btree_node *)bh->b_data;
1517 break;
1518 default:
1519 return 0;
1520 }
1521
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001522 nchildren = nilfs_btree_node_get_nchildren(node);
1523 maxkey = nilfs_btree_node_get_key(node, nchildren - 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001524 nextmaxkey = (nchildren > 1) ?
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001525 nilfs_btree_node_get_key(node, nchildren - 2) : 0;
Koji Sato17c76b02009-04-06 19:01:24 -07001526 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001527 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001528
Ryusuke Konishi30333422009-05-24 00:09:44 +09001529 return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
Koji Sato17c76b02009-04-06 19:01:24 -07001530}
1531
1532static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
1533 __u64 *keys, __u64 *ptrs, int nitems)
1534{
1535 struct buffer_head *bh;
1536 struct nilfs_btree *btree;
1537 struct nilfs_btree_node *node, *root;
1538 __le64 *dkeys;
1539 __le64 *dptrs;
1540 __u64 ptr;
1541 int nchildren, i, ret;
1542
1543 btree = (struct nilfs_btree *)bmap;
1544 root = nilfs_btree_get_root(btree);
1545 switch (nilfs_btree_height(btree)) {
1546 case 2:
1547 bh = NULL;
1548 node = root;
1549 break;
1550 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001551 nchildren = nilfs_btree_node_get_nchildren(root);
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001552 WARN_ON(nchildren > 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001553 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001554 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001555 if (ret < 0)
1556 return ret;
1557 node = (struct nilfs_btree_node *)bh->b_data;
1558 break;
1559 default:
1560 node = NULL;
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001561 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -07001562 }
1563
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001564 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001565 if (nchildren < nitems)
1566 nitems = nchildren;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001567 dkeys = nilfs_btree_node_dkeys(node);
1568 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001569 for (i = 0; i < nitems; i++) {
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +09001570 keys[i] = le64_to_cpu(dkeys[i]);
1571 ptrs[i] = le64_to_cpu(dptrs[i]);
Koji Sato17c76b02009-04-06 19:01:24 -07001572 }
1573
1574 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001575 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001576
1577 return nitems;
1578}
1579
1580static int
1581nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
1582 union nilfs_bmap_ptr_req *dreq,
1583 union nilfs_bmap_ptr_req *nreq,
1584 struct buffer_head **bhp,
1585 struct nilfs_bmap_stats *stats)
1586{
1587 struct buffer_head *bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001588 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
1589 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001590 int ret;
1591
Koji Sato17c76b02009-04-06 19:01:24 -07001592 stats->bs_nblocks = 0;
1593
1594 /* for data */
1595 /* cannot find near ptr */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001596 if (NILFS_BMAP_USE_VBN(bmap)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001597 dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001598 dat = nilfs_bmap_get_dat(bmap);
1599 }
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001600
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001601 ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001602 if (ret < 0)
1603 return ret;
1604
1605 *bhp = NULL;
1606 stats->bs_nblocks++;
1607 if (nreq != NULL) {
1608 nreq->bpr_ptr = dreq->bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001609 ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001610 if (ret < 0)
1611 goto err_out_dreq;
1612
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001613 ret = nilfs_btree_get_new_block(btree, nreq->bpr_ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001614 if (ret < 0)
1615 goto err_out_nreq;
1616
1617 *bhp = bh;
1618 stats->bs_nblocks++;
1619 }
1620
1621 /* success */
1622 return 0;
1623
1624 /* error */
1625 err_out_nreq:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001626 nilfs_bmap_abort_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001627 err_out_dreq:
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001628 nilfs_bmap_abort_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001629 stats->bs_nblocks = 0;
1630 return ret;
1631
1632}
1633
1634static void
1635nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
1636 __u64 key, __u64 ptr,
1637 const __u64 *keys, const __u64 *ptrs,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001638 int n,
Koji Sato17c76b02009-04-06 19:01:24 -07001639 union nilfs_bmap_ptr_req *dreq,
1640 union nilfs_bmap_ptr_req *nreq,
1641 struct buffer_head *bh)
1642{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001643 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
Koji Sato17c76b02009-04-06 19:01:24 -07001644 struct nilfs_btree_node *node;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001645 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001646 __u64 tmpptr;
1647
1648 /* free resources */
1649 if (bmap->b_ops->bop_clear != NULL)
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001650 bmap->b_ops->bop_clear(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001651
1652 /* ptr must be a pointer to a buffer head. */
1653 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1654
1655 /* convert and insert */
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001656 dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL;
Ryusuke Konishi30333422009-05-24 00:09:44 +09001657 nilfs_btree_init(bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001658 if (nreq != NULL) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001659 nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
1660 nilfs_bmap_commit_alloc_ptr(bmap, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001661
1662 /* create child node at level 1 */
Koji Sato17c76b02009-04-06 19:01:24 -07001663 node = (struct nilfs_btree_node *)bh->b_data;
1664 nilfs_btree_node_init(btree, node, 0, 1, n, keys, ptrs);
1665 nilfs_btree_node_insert(btree, node,
1666 key, dreq->bpr_ptr, n);
1667 if (!buffer_dirty(bh))
1668 nilfs_btnode_mark_dirty(bh);
1669 if (!nilfs_bmap_dirty(bmap))
1670 nilfs_bmap_set_dirty(bmap);
1671
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001672 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001673
1674 /* create root node at level 2 */
1675 node = nilfs_btree_get_root(btree);
1676 tmpptr = nreq->bpr_ptr;
1677 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1678 2, 1, &keys[0], &tmpptr);
1679 } else {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001680 nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001681
1682 /* create root node at level 1 */
1683 node = nilfs_btree_get_root(btree);
1684 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1685 1, n, keys, ptrs);
1686 nilfs_btree_node_insert(btree, node,
1687 key, dreq->bpr_ptr, n);
1688 if (!nilfs_bmap_dirty(bmap))
1689 nilfs_bmap_set_dirty(bmap);
1690 }
1691
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001692 if (NILFS_BMAP_USE_VBN(bmap))
1693 nilfs_btree_set_target_v(btree, key, dreq->bpr_ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001694}
1695
1696/**
1697 * nilfs_btree_convert_and_insert -
1698 * @bmap:
1699 * @key:
1700 * @ptr:
1701 * @keys:
1702 * @ptrs:
1703 * @n:
Koji Sato17c76b02009-04-06 19:01:24 -07001704 */
1705int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap,
1706 __u64 key, __u64 ptr,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001707 const __u64 *keys, const __u64 *ptrs, int n)
Koji Sato17c76b02009-04-06 19:01:24 -07001708{
1709 struct buffer_head *bh;
1710 union nilfs_bmap_ptr_req dreq, nreq, *di, *ni;
1711 struct nilfs_bmap_stats stats;
1712 int ret;
1713
1714 if (n + 1 <= NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1715 di = &dreq;
1716 ni = NULL;
1717 } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX(
1718 1 << bmap->b_inode->i_blkbits)) {
1719 di = &dreq;
1720 ni = &nreq;
1721 } else {
1722 di = NULL;
1723 ni = NULL;
1724 BUG();
1725 }
1726
1727 ret = nilfs_btree_prepare_convert_and_insert(bmap, key, di, ni, &bh,
1728 &stats);
1729 if (ret < 0)
1730 return ret;
1731 nilfs_btree_commit_convert_and_insert(bmap, key, ptr, keys, ptrs, n,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001732 di, ni, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001733 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1734 return 0;
1735}
1736
1737static int nilfs_btree_propagate_p(struct nilfs_btree *btree,
1738 struct nilfs_btree_path *path,
1739 int level,
1740 struct buffer_head *bh)
1741{
1742 while ((++level < nilfs_btree_height(btree) - 1) &&
1743 !buffer_dirty(path[level].bp_bh))
1744 nilfs_btnode_mark_dirty(path[level].bp_bh);
1745
1746 return 0;
1747}
1748
1749static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
1750 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001751 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001752{
1753 struct nilfs_btree_node *parent;
1754 int ret;
1755
1756 parent = nilfs_btree_get_node(btree, path, level + 1);
1757 path[level].bp_oldreq.bpr_ptr =
1758 nilfs_btree_node_get_ptr(btree, parent,
1759 path[level + 1].bp_index);
1760 path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001761 ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req,
1762 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001763 if (ret < 0)
1764 return ret;
1765
1766 if (buffer_nilfs_node(path[level].bp_bh)) {
1767 path[level].bp_ctxt.oldkey = path[level].bp_oldreq.bpr_ptr;
1768 path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr;
1769 path[level].bp_ctxt.bh = path[level].bp_bh;
1770 ret = nilfs_btnode_prepare_change_key(
1771 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1772 &path[level].bp_ctxt);
1773 if (ret < 0) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001774 nilfs_dat_abort_update(dat,
1775 &path[level].bp_oldreq.bpr_req,
1776 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001777 return ret;
1778 }
1779 }
1780
1781 return 0;
1782}
1783
1784static void nilfs_btree_commit_update_v(struct nilfs_btree *btree,
1785 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001786 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001787{
1788 struct nilfs_btree_node *parent;
1789
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001790 nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req,
1791 &path[level].bp_newreq.bpr_req,
1792 btree->bt_bmap.b_ptr_type == NILFS_BMAP_PTR_VS);
Koji Sato17c76b02009-04-06 19:01:24 -07001793
1794 if (buffer_nilfs_node(path[level].bp_bh)) {
1795 nilfs_btnode_commit_change_key(
1796 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1797 &path[level].bp_ctxt);
1798 path[level].bp_bh = path[level].bp_ctxt.bh;
1799 }
1800 set_buffer_nilfs_volatile(path[level].bp_bh);
1801
1802 parent = nilfs_btree_get_node(btree, path, level + 1);
1803 nilfs_btree_node_set_ptr(btree, parent, path[level + 1].bp_index,
1804 path[level].bp_newreq.bpr_ptr);
1805}
1806
1807static void nilfs_btree_abort_update_v(struct nilfs_btree *btree,
1808 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001809 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001810{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001811 nilfs_dat_abort_update(dat, &path[level].bp_oldreq.bpr_req,
1812 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001813 if (buffer_nilfs_node(path[level].bp_bh))
1814 nilfs_btnode_abort_change_key(
1815 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1816 &path[level].bp_ctxt);
1817}
1818
1819static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree,
1820 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001821 int minlevel, int *maxlevelp,
1822 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001823{
1824 int level, ret;
1825
1826 level = minlevel;
1827 if (!buffer_nilfs_volatile(path[level].bp_bh)) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001828 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001829 if (ret < 0)
1830 return ret;
1831 }
1832 while ((++level < nilfs_btree_height(btree) - 1) &&
1833 !buffer_dirty(path[level].bp_bh)) {
1834
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001835 WARN_ON(buffer_nilfs_volatile(path[level].bp_bh));
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001836 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001837 if (ret < 0)
1838 goto out;
1839 }
1840
1841 /* success */
Koji Sato17c76b02009-04-06 19:01:24 -07001842 *maxlevelp = level - 1;
1843 return 0;
1844
1845 /* error */
1846 out:
1847 while (--level > minlevel)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001848 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001849 if (!buffer_nilfs_volatile(path[level].bp_bh))
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 return ret;
1852}
1853
1854static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree,
1855 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001856 int minlevel, int maxlevel,
1857 struct buffer_head *bh,
1858 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001859{
1860 int level;
1861
1862 if (!buffer_nilfs_volatile(path[minlevel].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001863 nilfs_btree_commit_update_v(btree, path, minlevel, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001864
1865 for (level = minlevel + 1; level <= maxlevel; level++)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001866 nilfs_btree_commit_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001867}
1868
1869static int nilfs_btree_propagate_v(struct nilfs_btree *btree,
1870 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001871 int level, struct buffer_head *bh)
Koji Sato17c76b02009-04-06 19:01:24 -07001872{
Li Hong308f4412010-04-02 18:40:39 +08001873 int maxlevel = 0, ret;
Koji Sato17c76b02009-04-06 19:01:24 -07001874 struct nilfs_btree_node *parent;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001875 struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07001876 __u64 ptr;
1877
1878 get_bh(bh);
1879 path[level].bp_bh = bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001880 ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel,
1881 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001882 if (ret < 0)
1883 goto out;
1884
1885 if (buffer_nilfs_volatile(path[level].bp_bh)) {
1886 parent = nilfs_btree_get_node(btree, path, level + 1);
1887 ptr = nilfs_btree_node_get_ptr(btree, parent,
1888 path[level + 1].bp_index);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001889 ret = nilfs_dat_mark_dirty(dat, ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001890 if (ret < 0)
1891 goto out;
1892 }
1893
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001894 nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001895
1896 out:
1897 brelse(path[level].bp_bh);
1898 path[level].bp_bh = NULL;
1899 return ret;
1900}
1901
1902static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
1903 struct buffer_head *bh)
1904{
1905 struct nilfs_btree *btree;
1906 struct nilfs_btree_path *path;
1907 struct nilfs_btree_node *node;
1908 __u64 key;
1909 int level, ret;
1910
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001911 WARN_ON(!buffer_dirty(bh));
Koji Sato17c76b02009-04-06 19:01:24 -07001912
1913 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001914 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001915 if (path == NULL)
1916 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001917
1918 if (buffer_nilfs_node(bh)) {
1919 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001920 key = nilfs_btree_node_get_key(node, 0);
1921 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001922 } else {
1923 key = nilfs_bmap_data_get_key(bmap, bh);
1924 level = NILFS_BTREE_LEVEL_DATA;
1925 }
1926
1927 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
1928 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001929 if (unlikely(ret == -ENOENT))
Koji Sato17c76b02009-04-06 19:01:24 -07001930 printk(KERN_CRIT "%s: key = %llu, level == %d\n",
1931 __func__, (unsigned long long)key, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001932 goto out;
1933 }
1934
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001935 ret = NILFS_BMAP_USE_VBN(bmap) ?
1936 nilfs_btree_propagate_v(btree, path, level, bh) :
1937 nilfs_btree_propagate_p(btree, path, level, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001938
1939 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001940 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001941
1942 return ret;
1943}
1944
1945static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap,
1946 struct buffer_head *bh)
1947{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001948 return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), bh->b_blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07001949}
1950
1951static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree,
1952 struct list_head *lists,
1953 struct buffer_head *bh)
1954{
1955 struct list_head *head;
1956 struct buffer_head *cbh;
1957 struct nilfs_btree_node *node, *cnode;
1958 __u64 key, ckey;
1959 int level;
1960
1961 get_bh(bh);
1962 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001963 key = nilfs_btree_node_get_key(node, 0);
1964 level = nilfs_btree_node_get_level(node);
Ryusuke Konishicfa913a2010-07-07 17:19:54 +09001965 if (level < NILFS_BTREE_LEVEL_NODE_MIN ||
1966 level >= NILFS_BTREE_LEVEL_MAX) {
1967 dump_stack();
1968 printk(KERN_WARNING
1969 "%s: invalid btree level: %d (key=%llu, ino=%lu, "
1970 "blocknr=%llu)\n",
1971 __func__, level, (unsigned long long)key,
1972 NILFS_BMAP_I(&btree->bt_bmap)->vfs_inode.i_ino,
1973 (unsigned long long)bh->b_blocknr);
1974 return;
1975 }
1976
Koji Sato17c76b02009-04-06 19:01:24 -07001977 list_for_each(head, &lists[level]) {
1978 cbh = list_entry(head, struct buffer_head, b_assoc_buffers);
1979 cnode = (struct nilfs_btree_node *)cbh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001980 ckey = nilfs_btree_node_get_key(cnode, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07001981 if (key < ckey)
1982 break;
1983 }
1984 list_add_tail(&bh->b_assoc_buffers, head);
1985}
1986
1987static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *bmap,
1988 struct list_head *listp)
1989{
1990 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
1991 struct address_space *btcache = &NILFS_BMAP_I(bmap)->i_btnode_cache;
1992 struct list_head lists[NILFS_BTREE_LEVEL_MAX];
1993 struct pagevec pvec;
1994 struct buffer_head *bh, *head;
1995 pgoff_t index = 0;
1996 int level, i;
1997
1998 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1999 level < NILFS_BTREE_LEVEL_MAX;
2000 level++)
2001 INIT_LIST_HEAD(&lists[level]);
2002
2003 pagevec_init(&pvec, 0);
2004
2005 while (pagevec_lookup_tag(&pvec, btcache, &index, PAGECACHE_TAG_DIRTY,
2006 PAGEVEC_SIZE)) {
2007 for (i = 0; i < pagevec_count(&pvec); i++) {
2008 bh = head = page_buffers(pvec.pages[i]);
2009 do {
2010 if (buffer_dirty(bh))
2011 nilfs_btree_add_dirty_buffer(btree,
2012 lists, bh);
2013 } while ((bh = bh->b_this_page) != head);
2014 }
2015 pagevec_release(&pvec);
2016 cond_resched();
2017 }
2018
2019 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
2020 level < NILFS_BTREE_LEVEL_MAX;
2021 level++)
Ryusuke Konishi0935db72009-11-29 02:39:11 +09002022 list_splice_tail(&lists[level], listp);
Koji Sato17c76b02009-04-06 19:01:24 -07002023}
2024
2025static int nilfs_btree_assign_p(struct nilfs_btree *btree,
2026 struct nilfs_btree_path *path,
2027 int level,
2028 struct buffer_head **bh,
2029 sector_t blocknr,
2030 union nilfs_binfo *binfo)
2031{
2032 struct nilfs_btree_node *parent;
2033 __u64 key;
2034 __u64 ptr;
2035 int ret;
2036
2037 parent = nilfs_btree_get_node(btree, path, level + 1);
2038 ptr = nilfs_btree_node_get_ptr(btree, parent,
2039 path[level + 1].bp_index);
2040 if (buffer_nilfs_node(*bh)) {
2041 path[level].bp_ctxt.oldkey = ptr;
2042 path[level].bp_ctxt.newkey = blocknr;
2043 path[level].bp_ctxt.bh = *bh;
2044 ret = nilfs_btnode_prepare_change_key(
2045 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2046 &path[level].bp_ctxt);
2047 if (ret < 0)
2048 return ret;
2049 nilfs_btnode_commit_change_key(
2050 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
2051 &path[level].bp_ctxt);
2052 *bh = path[level].bp_ctxt.bh;
2053 }
2054
2055 nilfs_btree_node_set_ptr(btree, parent,
2056 path[level + 1].bp_index, blocknr);
2057
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002058 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002059 /* on-disk format */
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +09002060 binfo->bi_dat.bi_blkoff = cpu_to_le64(key);
Koji Sato17c76b02009-04-06 19:01:24 -07002061 binfo->bi_dat.bi_level = level;
2062
2063 return 0;
2064}
2065
2066static int nilfs_btree_assign_v(struct nilfs_btree *btree,
2067 struct nilfs_btree_path *path,
2068 int level,
2069 struct buffer_head **bh,
2070 sector_t blocknr,
2071 union nilfs_binfo *binfo)
2072{
2073 struct nilfs_btree_node *parent;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002074 struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap);
Koji Sato17c76b02009-04-06 19:01:24 -07002075 __u64 key;
2076 __u64 ptr;
2077 union nilfs_bmap_ptr_req req;
2078 int ret;
2079
2080 parent = nilfs_btree_get_node(btree, path, level + 1);
2081 ptr = nilfs_btree_node_get_ptr(btree, parent,
2082 path[level + 1].bp_index);
2083 req.bpr_ptr = ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002084 ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
2085 if (ret < 0)
Koji Sato17c76b02009-04-06 19:01:24 -07002086 return ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002087 nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002088
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002089 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002090 /* on-disk format */
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +09002091 binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr);
2092 binfo->bi_v.bi_blkoff = cpu_to_le64(key);
Koji Sato17c76b02009-04-06 19:01:24 -07002093
2094 return 0;
2095}
2096
2097static int nilfs_btree_assign(struct nilfs_bmap *bmap,
2098 struct buffer_head **bh,
2099 sector_t blocknr,
2100 union nilfs_binfo *binfo)
2101{
2102 struct nilfs_btree *btree;
2103 struct nilfs_btree_path *path;
2104 struct nilfs_btree_node *node;
2105 __u64 key;
2106 int level, ret;
2107
2108 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002109 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002110 if (path == NULL)
2111 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07002112
2113 if (buffer_nilfs_node(*bh)) {
2114 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002115 key = nilfs_btree_node_get_key(node, 0);
2116 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07002117 } else {
2118 key = nilfs_bmap_data_get_key(bmap, *bh);
2119 level = NILFS_BTREE_LEVEL_DATA;
2120 }
2121
2122 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
2123 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002124 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002125 goto out;
2126 }
2127
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09002128 ret = NILFS_BMAP_USE_VBN(bmap) ?
2129 nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) :
2130 nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
Koji Sato17c76b02009-04-06 19:01:24 -07002131
2132 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002133 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002134
2135 return ret;
2136}
2137
2138static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap,
2139 struct buffer_head **bh,
2140 sector_t blocknr,
2141 union nilfs_binfo *binfo)
2142{
Koji Sato17c76b02009-04-06 19:01:24 -07002143 struct nilfs_btree_node *node;
2144 __u64 key;
2145 int ret;
2146
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002147 ret = nilfs_dat_move(nilfs_bmap_get_dat(bmap), (*bh)->b_blocknr,
2148 blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002149 if (ret < 0)
2150 return ret;
2151
2152 if (buffer_nilfs_node(*bh)) {
2153 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002154 key = nilfs_btree_node_get_key(node, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07002155 } else
2156 key = nilfs_bmap_data_get_key(bmap, *bh);
2157
2158 /* on-disk format */
2159 binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr);
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +09002160 binfo->bi_v.bi_blkoff = cpu_to_le64(key);
Koji Sato17c76b02009-04-06 19:01:24 -07002161
2162 return 0;
2163}
2164
2165static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
2166{
2167 struct buffer_head *bh;
2168 struct nilfs_btree *btree;
2169 struct nilfs_btree_path *path;
2170 __u64 ptr;
2171 int ret;
2172
2173 btree = (struct nilfs_btree *)bmap;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002174 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002175 if (path == NULL)
2176 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07002177
2178 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1);
2179 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002180 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002181 goto out;
2182 }
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09002183 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002184 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002185 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002186 goto out;
2187 }
2188
2189 if (!buffer_dirty(bh))
2190 nilfs_btnode_mark_dirty(bh);
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09002191 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002192 if (!nilfs_bmap_dirty(&btree->bt_bmap))
2193 nilfs_bmap_set_dirty(&btree->bt_bmap);
2194
2195 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002196 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002197 return ret;
2198}
2199
2200static const struct nilfs_bmap_operations nilfs_btree_ops = {
2201 .bop_lookup = nilfs_btree_lookup,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002202 .bop_lookup_contig = nilfs_btree_lookup_contig,
Koji Sato17c76b02009-04-06 19:01:24 -07002203 .bop_insert = nilfs_btree_insert,
2204 .bop_delete = nilfs_btree_delete,
2205 .bop_clear = NULL,
2206
2207 .bop_propagate = nilfs_btree_propagate,
2208
2209 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2210
2211 .bop_assign = nilfs_btree_assign,
2212 .bop_mark = nilfs_btree_mark,
2213
2214 .bop_last_key = nilfs_btree_last_key,
2215 .bop_check_insert = NULL,
2216 .bop_check_delete = nilfs_btree_check_delete,
2217 .bop_gather_data = nilfs_btree_gather_data,
2218};
2219
2220static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
2221 .bop_lookup = NULL,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002222 .bop_lookup_contig = NULL,
Koji Sato17c76b02009-04-06 19:01:24 -07002223 .bop_insert = NULL,
2224 .bop_delete = NULL,
2225 .bop_clear = NULL,
2226
2227 .bop_propagate = nilfs_btree_propagate_gc,
2228
2229 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2230
2231 .bop_assign = nilfs_btree_assign_gc,
2232 .bop_mark = NULL,
2233
2234 .bop_last_key = NULL,
2235 .bop_check_insert = NULL,
2236 .bop_check_delete = NULL,
2237 .bop_gather_data = NULL,
2238};
2239
Ryusuke Konishi30333422009-05-24 00:09:44 +09002240int nilfs_btree_init(struct nilfs_bmap *bmap)
Koji Sato17c76b02009-04-06 19:01:24 -07002241{
Koji Sato17c76b02009-04-06 19:01:24 -07002242 bmap->b_ops = &nilfs_btree_ops;
Koji Sato17c76b02009-04-06 19:01:24 -07002243 return 0;
2244}
2245
2246void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
2247{
Koji Sato17c76b02009-04-06 19:01:24 -07002248 bmap->b_ops = &nilfs_btree_ops_gc;
2249}