blob: 81e871645b5fa3393a306b21876c1380dd3a9c9c [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 Konishie7c274f2010-07-10 19:09:49 +090069static int nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr,
Ryusuke Konishif198dbb2009-05-22 01:07:13 +090070 struct buffer_head **bhp)
71{
Ryusuke Konishie7c274f2010-07-10 19:09:49 +090072 struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache;
Ryusuke Konishi1d5385b2010-07-16 23:52:40 +090073 struct buffer_head *bh;
Ryusuke Konishi1376e932009-11-13 16:49:09 +090074 int err;
75
76 err = nilfs_btnode_submit_block(btnc, ptr, 0, bhp);
77 if (err)
78 return err == -EEXIST ? 0 : err;
79
Ryusuke Konishi1d5385b2010-07-16 23:52:40 +090080 bh = *bhp;
81 wait_on_buffer(bh);
82 if (!buffer_uptodate(bh)) {
83 brelse(bh);
Ryusuke Konishi1376e932009-11-13 16:49:09 +090084 return -EIO;
85 }
Ryusuke Konishi1d5385b2010-07-16 23:52:40 +090086 if (nilfs_btree_broken_node_block(bh)) {
87 clear_buffer_uptodate(bh);
88 brelse(bh);
89 return -EINVAL;
90 }
Ryusuke Konishi1376e932009-11-13 16:49:09 +090091 return 0;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +090092}
93
Ryusuke Konishie7c274f2010-07-10 19:09:49 +090094static int nilfs_btree_get_new_block(const struct nilfs_bmap *btree,
Ryusuke Konishif198dbb2009-05-22 01:07:13 +090095 __u64 ptr, struct buffer_head **bhp)
96{
Ryusuke Konishie7c274f2010-07-10 19:09:49 +090097 struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache;
Ryusuke Konishi45f49102009-11-13 16:25:19 +090098 struct buffer_head *bh;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +090099
Ryusuke Konishi45f49102009-11-13 16:25:19 +0900100 bh = nilfs_btnode_create_block(btnc, ptr);
101 if (!bh)
102 return -ENOMEM;
103
104 set_buffer_nilfs_volatile(bh);
105 *bhp = bh;
106 return 0;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900107}
Koji Sato17c76b02009-04-06 19:01:24 -0700108
109static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900110nilfs_btree_node_get_flags(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700111{
112 return node->bn_flags;
113}
114
115static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900116nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags)
Koji Sato17c76b02009-04-06 19:01:24 -0700117{
118 node->bn_flags = flags;
119}
120
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900121static inline int nilfs_btree_node_root(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700122{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900123 return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT;
Koji Sato17c76b02009-04-06 19:01:24 -0700124}
125
126static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900127nilfs_btree_node_get_level(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700128{
129 return node->bn_level;
130}
131
132static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900133nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700134{
135 node->bn_level = level;
136}
137
138static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900139nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700140{
141 return le16_to_cpu(node->bn_nchildren);
142}
143
144static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900145nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren)
Koji Sato17c76b02009-04-06 19:01:24 -0700146{
147 node->bn_nchildren = cpu_to_le16(nchildren);
148}
149
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900150static inline int nilfs_btree_node_size(const struct nilfs_bmap *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700151{
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900152 return 1 << btree->b_inode->i_blkbits;
Koji Sato17c76b02009-04-06 19:01:24 -0700153}
154
155static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900156nilfs_btree_node_nchildren_min(const struct nilfs_btree_node *node,
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900157 const struct nilfs_bmap *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700158{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900159 return nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700160 NILFS_BTREE_ROOT_NCHILDREN_MIN :
161 NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree));
162}
163
164static inline int
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900165nilfs_btree_node_nchildren_max(const struct nilfs_btree_node *node,
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900166 const struct nilfs_bmap *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700167{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900168 return nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700169 NILFS_BTREE_ROOT_NCHILDREN_MAX :
170 NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree));
171}
172
173static inline __le64 *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900174nilfs_btree_node_dkeys(const struct nilfs_btree_node *node)
Koji Sato17c76b02009-04-06 19:01:24 -0700175{
176 return (__le64 *)((char *)(node + 1) +
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900177 (nilfs_btree_node_root(node) ?
Koji Sato17c76b02009-04-06 19:01:24 -0700178 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE));
179}
180
181static inline __le64 *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900182nilfs_btree_node_dptrs(const struct nilfs_btree_node *node,
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900183 const struct nilfs_bmap *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700184{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900185 return (__le64 *)(nilfs_btree_node_dkeys(node) +
186 nilfs_btree_node_nchildren_max(node, btree));
Koji Sato17c76b02009-04-06 19:01:24 -0700187}
188
189static inline __u64
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900190nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index)
Koji Sato17c76b02009-04-06 19:01:24 -0700191{
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900192 return le64_to_cpu(*(nilfs_btree_node_dkeys(node) + index));
Koji Sato17c76b02009-04-06 19:01:24 -0700193}
194
195static inline void
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900196nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key)
Koji Sato17c76b02009-04-06 19:01:24 -0700197{
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900198 *(nilfs_btree_node_dkeys(node) + index) = cpu_to_le64(key);
Koji Sato17c76b02009-04-06 19:01:24 -0700199}
200
201static inline __u64
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900202nilfs_btree_node_get_ptr(const struct nilfs_bmap *btree,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900203 const struct nilfs_btree_node *node, int index)
Koji Sato17c76b02009-04-06 19:01:24 -0700204{
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900205 return le64_to_cpu(*(nilfs_btree_node_dptrs(node, btree) + index));
Koji Sato17c76b02009-04-06 19:01:24 -0700206}
207
208static inline void
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900209nilfs_btree_node_set_ptr(struct nilfs_bmap *btree,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900210 struct nilfs_btree_node *node, int index, __u64 ptr)
Koji Sato17c76b02009-04-06 19:01:24 -0700211{
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900212 *(nilfs_btree_node_dptrs(node, btree) + index) = cpu_to_le64(ptr);
Koji Sato17c76b02009-04-06 19:01:24 -0700213}
214
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900215static void nilfs_btree_node_init(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700216 struct nilfs_btree_node *node,
217 int flags, int level, int nchildren,
218 const __u64 *keys, const __u64 *ptrs)
219{
220 __le64 *dkeys;
221 __le64 *dptrs;
222 int i;
223
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900224 nilfs_btree_node_set_flags(node, flags);
225 nilfs_btree_node_set_level(node, level);
226 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700227
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900228 dkeys = nilfs_btree_node_dkeys(node);
229 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700230 for (i = 0; i < nchildren; i++) {
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900231 dkeys[i] = cpu_to_le64(keys[i]);
232 dptrs[i] = cpu_to_le64(ptrs[i]);
Koji Sato17c76b02009-04-06 19:01:24 -0700233 }
234}
235
236/* Assume the buffer heads corresponding to left and right are locked. */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900237static void nilfs_btree_node_move_left(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700238 struct nilfs_btree_node *left,
239 struct nilfs_btree_node *right,
240 int n)
241{
242 __le64 *ldkeys, *rdkeys;
243 __le64 *ldptrs, *rdptrs;
244 int lnchildren, rnchildren;
245
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900246 ldkeys = nilfs_btree_node_dkeys(left);
247 ldptrs = nilfs_btree_node_dptrs(left, btree);
248 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700249
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900250 rdkeys = nilfs_btree_node_dkeys(right);
251 rdptrs = nilfs_btree_node_dptrs(right, btree);
252 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700253
254 memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys));
255 memcpy(ldptrs + lnchildren, rdptrs, n * sizeof(*rdptrs));
256 memmove(rdkeys, rdkeys + n, (rnchildren - n) * sizeof(*rdkeys));
257 memmove(rdptrs, rdptrs + n, (rnchildren - n) * sizeof(*rdptrs));
258
259 lnchildren += n;
260 rnchildren -= n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900261 nilfs_btree_node_set_nchildren(left, lnchildren);
262 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700263}
264
265/* Assume that the buffer heads corresponding to left and right are locked. */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900266static void nilfs_btree_node_move_right(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700267 struct nilfs_btree_node *left,
268 struct nilfs_btree_node *right,
269 int n)
270{
271 __le64 *ldkeys, *rdkeys;
272 __le64 *ldptrs, *rdptrs;
273 int lnchildren, rnchildren;
274
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900275 ldkeys = nilfs_btree_node_dkeys(left);
276 ldptrs = nilfs_btree_node_dptrs(left, btree);
277 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700278
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900279 rdkeys = nilfs_btree_node_dkeys(right);
280 rdptrs = nilfs_btree_node_dptrs(right, btree);
281 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700282
283 memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys));
284 memmove(rdptrs + n, rdptrs, rnchildren * sizeof(*rdptrs));
285 memcpy(rdkeys, ldkeys + lnchildren - n, n * sizeof(*rdkeys));
286 memcpy(rdptrs, ldptrs + lnchildren - n, n * sizeof(*rdptrs));
287
288 lnchildren -= n;
289 rnchildren += n;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900290 nilfs_btree_node_set_nchildren(left, lnchildren);
291 nilfs_btree_node_set_nchildren(right, rnchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700292}
293
294/* Assume that the buffer head corresponding to node is locked. */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900295static void nilfs_btree_node_insert(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700296 struct nilfs_btree_node *node,
297 __u64 key, __u64 ptr, int index)
298{
299 __le64 *dkeys;
300 __le64 *dptrs;
301 int nchildren;
302
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900303 dkeys = nilfs_btree_node_dkeys(node);
304 dptrs = nilfs_btree_node_dptrs(node, btree);
305 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700306 if (index < nchildren) {
307 memmove(dkeys + index + 1, dkeys + index,
308 (nchildren - index) * sizeof(*dkeys));
309 memmove(dptrs + index + 1, dptrs + index,
310 (nchildren - index) * sizeof(*dptrs));
311 }
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900312 dkeys[index] = cpu_to_le64(key);
313 dptrs[index] = cpu_to_le64(ptr);
Koji Sato17c76b02009-04-06 19:01:24 -0700314 nchildren++;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900315 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700316}
317
318/* Assume that the buffer head corresponding to node is locked. */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900319static void nilfs_btree_node_delete(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700320 struct nilfs_btree_node *node,
321 __u64 *keyp, __u64 *ptrp, int index)
322{
323 __u64 key;
324 __u64 ptr;
325 __le64 *dkeys;
326 __le64 *dptrs;
327 int nchildren;
328
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900329 dkeys = nilfs_btree_node_dkeys(node);
330 dptrs = nilfs_btree_node_dptrs(node, btree);
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +0900331 key = le64_to_cpu(dkeys[index]);
332 ptr = le64_to_cpu(dptrs[index]);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900333 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700334 if (keyp != NULL)
335 *keyp = key;
336 if (ptrp != NULL)
337 *ptrp = ptr;
338
339 if (index < nchildren - 1) {
340 memmove(dkeys + index, dkeys + index + 1,
341 (nchildren - index - 1) * sizeof(*dkeys));
342 memmove(dptrs + index, dptrs + index + 1,
343 (nchildren - index - 1) * sizeof(*dptrs));
344 }
345 nchildren--;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900346 nilfs_btree_node_set_nchildren(node, nchildren);
Koji Sato17c76b02009-04-06 19:01:24 -0700347}
348
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900349static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node,
Koji Sato17c76b02009-04-06 19:01:24 -0700350 __u64 key, int *indexp)
351{
352 __u64 nkey;
353 int index, low, high, s;
354
355 /* binary search */
356 low = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900357 high = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700358 index = 0;
359 s = 0;
360 while (low <= high) {
361 index = (low + high) / 2;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900362 nkey = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700363 if (nkey == key) {
364 s = 0;
365 goto out;
366 } else if (nkey < key) {
367 low = index + 1;
368 s = -1;
369 } else {
370 high = index - 1;
371 s = 1;
372 }
373 }
374
375 /* adjust index */
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900376 if (nilfs_btree_node_get_level(node) > NILFS_BTREE_LEVEL_NODE_MIN) {
377 if (s > 0 && index > 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700378 index--;
379 } else if (s < 0)
380 index++;
381
382 out:
Koji Sato17c76b02009-04-06 19:01:24 -0700383 *indexp = index;
384
385 return s == 0;
386}
387
Ryusuke Konishi1d5385b2010-07-16 23:52:40 +0900388/**
389 * nilfs_btree_node_broken - verify consistency of btree node
390 * @node: btree node block to be examined
391 * @size: node size (in bytes)
392 * @blocknr: block number
393 *
394 * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned.
395 */
396static int nilfs_btree_node_broken(const struct nilfs_btree_node *node,
397 size_t size, sector_t blocknr)
398{
399 int level, flags, nchildren;
400 int ret = 0;
401
402 level = nilfs_btree_node_get_level(node);
403 flags = nilfs_btree_node_get_flags(node);
404 nchildren = nilfs_btree_node_get_nchildren(node);
405
406 if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
407 level >= NILFS_BTREE_LEVEL_MAX ||
408 (flags & NILFS_BTREE_NODE_ROOT) ||
409 nchildren < 0 ||
410 nchildren > NILFS_BTREE_NODE_NCHILDREN_MAX(size))) {
411 printk(KERN_CRIT "NILFS: bad btree node (blocknr=%llu): "
412 "level = %d, flags = 0x%x, nchildren = %d\n",
413 (unsigned long long)blocknr, level, flags, nchildren);
414 ret = 1;
415 }
416 return ret;
417}
418
419int nilfs_btree_broken_node_block(struct buffer_head *bh)
420{
421 return nilfs_btree_node_broken((struct nilfs_btree_node *)bh->b_data,
422 bh->b_size, bh->b_blocknr);
423}
424
Koji Sato17c76b02009-04-06 19:01:24 -0700425static inline struct nilfs_btree_node *
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900426nilfs_btree_get_root(const struct nilfs_bmap *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700427{
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900428 return (struct nilfs_btree_node *)btree->b_u.u_data;
Koji Sato17c76b02009-04-06 19:01:24 -0700429}
430
431static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900432nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700433{
434 return (struct nilfs_btree_node *)path[level].bp_bh->b_data;
435}
436
437static inline struct nilfs_btree_node *
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900438nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level)
Koji Sato17c76b02009-04-06 19:01:24 -0700439{
440 return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data;
441}
442
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900443static inline int nilfs_btree_height(const struct nilfs_bmap *btree)
Koji Sato17c76b02009-04-06 19:01:24 -0700444{
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900445 return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700446}
447
448static inline struct nilfs_btree_node *
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900449nilfs_btree_get_node(const struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700450 const struct nilfs_btree_path *path,
451 int level)
452{
453 return (level == nilfs_btree_height(btree) - 1) ?
454 nilfs_btree_get_root(btree) :
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900455 nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700456}
457
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900458static inline int
459nilfs_btree_bad_node(struct nilfs_btree_node *node, int level)
460{
461 if (unlikely(nilfs_btree_node_get_level(node) != level)) {
462 dump_stack();
463 printk(KERN_CRIT "NILFS: btree level mismatch: %d != %d\n",
464 nilfs_btree_node_get_level(node), level);
465 return 1;
466 }
467 return 0;
468}
469
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900470static int nilfs_btree_do_lookup(const struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700471 struct nilfs_btree_path *path,
472 __u64 key, __u64 *ptrp, int minlevel)
473{
474 struct nilfs_btree_node *node;
475 __u64 ptr;
476 int level, index, found, ret;
477
Koji Sato17c76b02009-04-06 19:01:24 -0700478 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900479 level = nilfs_btree_node_get_level(node);
480 if (level < minlevel || nilfs_btree_node_get_nchildren(node) <= 0)
Koji Sato17c76b02009-04-06 19:01:24 -0700481 return -ENOENT;
482
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900483 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700484 ptr = nilfs_btree_node_get_ptr(btree, node, index);
485 path[level].bp_bh = NULL;
486 path[level].bp_index = index;
487
488 for (level--; level >= minlevel; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900489 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700490 if (ret < 0)
491 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900492 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900493 if (nilfs_btree_bad_node(node, level))
494 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -0700495 if (!found)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900496 found = nilfs_btree_node_lookup(node, key, &index);
Koji Sato17c76b02009-04-06 19:01:24 -0700497 else
498 index = 0;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900499 if (index < nilfs_btree_node_nchildren_max(node, btree))
Koji Sato17c76b02009-04-06 19:01:24 -0700500 ptr = nilfs_btree_node_get_ptr(btree, node, index);
501 else {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700502 WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN);
Koji Sato17c76b02009-04-06 19:01:24 -0700503 /* insert */
504 ptr = NILFS_BMAP_INVALID_PTR;
505 }
506 path[level].bp_index = index;
507 }
508 if (!found)
509 return -ENOENT;
510
511 if (ptrp != NULL)
512 *ptrp = ptr;
513
514 return 0;
515}
516
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900517static int nilfs_btree_do_lookup_last(const struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700518 struct nilfs_btree_path *path,
519 __u64 *keyp, __u64 *ptrp)
520{
521 struct nilfs_btree_node *node;
522 __u64 ptr;
523 int index, level, ret;
524
525 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900526 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700527 if (index < 0)
528 return -ENOENT;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900529 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700530 ptr = nilfs_btree_node_get_ptr(btree, node, index);
531 path[level].bp_bh = NULL;
532 path[level].bp_index = index;
533
534 for (level--; level > 0; level--) {
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900535 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700536 if (ret < 0)
537 return ret;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900538 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishi9b945d52009-10-10 22:58:10 +0900539 if (nilfs_btree_bad_node(node, level))
540 return -EINVAL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900541 index = nilfs_btree_node_get_nchildren(node) - 1;
Koji Sato17c76b02009-04-06 19:01:24 -0700542 ptr = nilfs_btree_node_get_ptr(btree, node, index);
543 path[level].bp_index = index;
544 }
545
546 if (keyp != NULL)
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900547 *keyp = nilfs_btree_node_get_key(node, index);
Koji Sato17c76b02009-04-06 19:01:24 -0700548 if (ptrp != NULL)
549 *ptrp = ptr;
550
551 return 0;
552}
553
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900554static int nilfs_btree_lookup(const struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700555 __u64 key, int level, __u64 *ptrp)
556{
Koji Sato17c76b02009-04-06 19:01:24 -0700557 struct nilfs_btree_path *path;
558 __u64 ptr;
559 int ret;
560
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900561 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -0700562 if (path == NULL)
563 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -0700564
565 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
566
567 if (ptrp != NULL)
568 *ptrp = ptr;
569
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900570 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -0700571
572 return ret;
573}
574
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900575static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900576 __u64 key, __u64 *ptrp, unsigned maxblocks)
577{
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900578 struct nilfs_btree_path *path;
579 struct nilfs_btree_node *node;
580 struct inode *dat = NULL;
581 __u64 ptr, ptr2;
582 sector_t blocknr;
583 int level = NILFS_BTREE_LEVEL_NODE_MIN;
584 int ret, cnt, index, maxlevel;
585
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900586 path = nilfs_btree_alloc_path();
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900587 if (path == NULL)
588 return -ENOMEM;
Li Hongf9054402010-04-02 17:36:34 +0800589
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900590 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
591 if (ret < 0)
592 goto out;
593
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900594 if (NILFS_BMAP_USE_VBN(btree)) {
595 dat = nilfs_bmap_get_dat(btree);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900596 ret = nilfs_dat_translate(dat, ptr, &blocknr);
597 if (ret < 0)
598 goto out;
599 ptr = blocknr;
600 }
601 cnt = 1;
602 if (cnt == maxblocks)
603 goto end;
604
605 maxlevel = nilfs_btree_height(btree) - 1;
606 node = nilfs_btree_get_node(btree, path, level);
607 index = path[level].bp_index + 1;
608 for (;;) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900609 while (index < nilfs_btree_node_get_nchildren(node)) {
610 if (nilfs_btree_node_get_key(node, index) !=
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900611 key + cnt)
612 goto end;
613 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
614 if (dat) {
615 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
616 if (ret < 0)
617 goto out;
618 ptr2 = blocknr;
619 }
620 if (ptr2 != ptr + cnt || ++cnt == maxblocks)
621 goto end;
622 index++;
623 continue;
624 }
625 if (level == maxlevel)
626 break;
627
628 /* look-up right sibling node */
629 node = nilfs_btree_get_node(btree, path, level + 1);
630 index = path[level + 1].bp_index + 1;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900631 if (index >= nilfs_btree_node_get_nchildren(node) ||
632 nilfs_btree_node_get_key(node, index) != key + cnt)
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900633 break;
634 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
635 path[level + 1].bp_index = index;
636
637 brelse(path[level].bp_bh);
638 path[level].bp_bh = NULL;
639 ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh);
640 if (ret < 0)
641 goto out;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900642 node = nilfs_btree_get_nonroot_node(path, level);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900643 index = 0;
644 path[level].bp_index = index;
645 }
646 end:
647 *ptrp = ptr;
648 ret = cnt;
649 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900650 nilfs_btree_free_path(path);
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +0900651 return ret;
652}
653
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900654static void nilfs_btree_promote_key(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700655 struct nilfs_btree_path *path,
656 int level, __u64 key)
657{
658 if (level < nilfs_btree_height(btree) - 1) {
659 do {
Koji Sato17c76b02009-04-06 19:01:24 -0700660 nilfs_btree_node_set_key(
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900661 nilfs_btree_get_nonroot_node(path, level),
Koji Sato17c76b02009-04-06 19:01:24 -0700662 path[level].bp_index, key);
663 if (!buffer_dirty(path[level].bp_bh))
664 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700665 } while ((path[level].bp_index == 0) &&
666 (++level < nilfs_btree_height(btree) - 1));
667 }
668
669 /* root */
670 if (level == nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900671 nilfs_btree_node_set_key(nilfs_btree_get_root(btree),
Koji Sato17c76b02009-04-06 19:01:24 -0700672 path[level].bp_index, key);
673 }
674}
675
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900676static void nilfs_btree_do_insert(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700677 struct nilfs_btree_path *path,
678 int level, __u64 *keyp, __u64 *ptrp)
679{
680 struct nilfs_btree_node *node;
681
682 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900683 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700684 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
685 path[level].bp_index);
686 if (!buffer_dirty(path[level].bp_bh))
687 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700688
689 if (path[level].bp_index == 0)
690 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900691 nilfs_btree_node_get_key(node,
692 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700693 } else {
694 node = nilfs_btree_get_root(btree);
695 nilfs_btree_node_insert(btree, node, *keyp, *ptrp,
696 path[level].bp_index);
697 }
698}
699
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900700static void nilfs_btree_carry_left(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700701 struct nilfs_btree_path *path,
702 int level, __u64 *keyp, __u64 *ptrp)
703{
704 struct nilfs_btree_node *node, *left;
705 int nchildren, lnchildren, n, move;
706
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900707 node = nilfs_btree_get_nonroot_node(path, level);
708 left = nilfs_btree_get_sib_node(path, level);
709 nchildren = nilfs_btree_node_get_nchildren(node);
710 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -0700711 move = 0;
712
713 n = (nchildren + lnchildren + 1) / 2 - lnchildren;
714 if (n > path[level].bp_index) {
715 /* move insert point */
716 n--;
717 move = 1;
718 }
719
720 nilfs_btree_node_move_left(btree, left, node, n);
721
722 if (!buffer_dirty(path[level].bp_bh))
723 nilfs_btnode_mark_dirty(path[level].bp_bh);
724 if (!buffer_dirty(path[level].bp_sib_bh))
725 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
726
Koji Sato17c76b02009-04-06 19:01:24 -0700727 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900728 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700729
730 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900731 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700732 path[level].bp_bh = path[level].bp_sib_bh;
733 path[level].bp_sib_bh = NULL;
734 path[level].bp_index += lnchildren;
735 path[level + 1].bp_index--;
736 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900737 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700738 path[level].bp_sib_bh = NULL;
739 path[level].bp_index -= n;
740 }
741
742 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
743}
744
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900745static void nilfs_btree_carry_right(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700746 struct nilfs_btree_path *path,
747 int level, __u64 *keyp, __u64 *ptrp)
748{
749 struct nilfs_btree_node *node, *right;
750 int nchildren, rnchildren, n, move;
751
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900752 node = nilfs_btree_get_nonroot_node(path, level);
753 right = nilfs_btree_get_sib_node(path, level);
754 nchildren = nilfs_btree_node_get_nchildren(node);
755 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -0700756 move = 0;
757
758 n = (nchildren + rnchildren + 1) / 2 - rnchildren;
759 if (n > nchildren - path[level].bp_index) {
760 /* move insert point */
761 n--;
762 move = 1;
763 }
764
765 nilfs_btree_node_move_right(btree, node, right, n);
766
767 if (!buffer_dirty(path[level].bp_bh))
768 nilfs_btnode_mark_dirty(path[level].bp_bh);
769 if (!buffer_dirty(path[level].bp_sib_bh))
770 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
771
Koji Sato17c76b02009-04-06 19:01:24 -0700772 path[level + 1].bp_index++;
773 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900774 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -0700775 path[level + 1].bp_index--;
776
777 if (move) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900778 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700779 path[level].bp_bh = path[level].bp_sib_bh;
780 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900781 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700782 path[level + 1].bp_index++;
783 } else {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900784 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700785 path[level].bp_sib_bh = NULL;
786 }
787
788 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
789}
790
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900791static void nilfs_btree_split(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700792 struct nilfs_btree_path *path,
793 int level, __u64 *keyp, __u64 *ptrp)
794{
795 struct nilfs_btree_node *node, *right;
796 __u64 newkey;
797 __u64 newptr;
798 int nchildren, n, move;
799
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900800 node = nilfs_btree_get_nonroot_node(path, level);
801 right = nilfs_btree_get_sib_node(path, level);
802 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700803 move = 0;
804
805 n = (nchildren + 1) / 2;
806 if (n > nchildren - path[level].bp_index) {
807 n--;
808 move = 1;
809 }
810
811 nilfs_btree_node_move_right(btree, node, right, n);
812
813 if (!buffer_dirty(path[level].bp_bh))
814 nilfs_btnode_mark_dirty(path[level].bp_bh);
815 if (!buffer_dirty(path[level].bp_sib_bh))
816 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
817
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900818 newkey = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700819 newptr = path[level].bp_newreq.bpr_ptr;
820
821 if (move) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900822 path[level].bp_index -= nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -0700823 nilfs_btree_node_insert(btree, right, *keyp, *ptrp,
824 path[level].bp_index);
825
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900826 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700827 *ptrp = path[level].bp_newreq.bpr_ptr;
828
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900829 brelse(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700830 path[level].bp_bh = path[level].bp_sib_bh;
831 path[level].bp_sib_bh = NULL;
832 } else {
833 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
834
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900835 *keyp = nilfs_btree_node_get_key(right, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700836 *ptrp = path[level].bp_newreq.bpr_ptr;
837
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900838 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700839 path[level].bp_sib_bh = NULL;
840 }
841
842 path[level + 1].bp_index++;
843}
844
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900845static void nilfs_btree_grow(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700846 struct nilfs_btree_path *path,
847 int level, __u64 *keyp, __u64 *ptrp)
848{
849 struct nilfs_btree_node *root, *child;
850 int n;
851
Koji Sato17c76b02009-04-06 19:01:24 -0700852 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900853 child = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -0700854
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900855 n = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -0700856
857 nilfs_btree_node_move_right(btree, root, child, n);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900858 nilfs_btree_node_set_level(root, level + 1);
Koji Sato17c76b02009-04-06 19:01:24 -0700859
860 if (!buffer_dirty(path[level].bp_sib_bh))
861 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
862
Koji Sato17c76b02009-04-06 19:01:24 -0700863 path[level].bp_bh = path[level].bp_sib_bh;
864 path[level].bp_sib_bh = NULL;
865
866 nilfs_btree_do_insert(btree, path, level, keyp, ptrp);
867
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900868 *keyp = nilfs_btree_node_get_key(child, 0);
Koji Sato17c76b02009-04-06 19:01:24 -0700869 *ptrp = path[level].bp_newreq.bpr_ptr;
870}
871
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900872static __u64 nilfs_btree_find_near(const struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700873 const struct nilfs_btree_path *path)
874{
875 struct nilfs_btree_node *node;
876 int level;
877
878 if (path == NULL)
879 return NILFS_BMAP_INVALID_PTR;
880
881 /* left sibling */
882 level = NILFS_BTREE_LEVEL_NODE_MIN;
883 if (path[level].bp_index > 0) {
884 node = nilfs_btree_get_node(btree, path, level);
885 return nilfs_btree_node_get_ptr(btree, node,
886 path[level].bp_index - 1);
887 }
888
889 /* parent */
890 level = NILFS_BTREE_LEVEL_NODE_MIN + 1;
891 if (level <= nilfs_btree_height(btree) - 1) {
892 node = nilfs_btree_get_node(btree, path, level);
893 return nilfs_btree_node_get_ptr(btree, node,
894 path[level].bp_index);
895 }
896
897 return NILFS_BMAP_INVALID_PTR;
898}
899
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900900static __u64 nilfs_btree_find_target_v(const struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700901 const struct nilfs_btree_path *path,
902 __u64 key)
903{
904 __u64 ptr;
905
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900906 ptr = nilfs_bmap_find_target_seq(btree, key);
Koji Sato17c76b02009-04-06 19:01:24 -0700907 if (ptr != NILFS_BMAP_INVALID_PTR)
908 /* sequential access */
909 return ptr;
910 else {
911 ptr = nilfs_btree_find_near(btree, path);
912 if (ptr != NILFS_BMAP_INVALID_PTR)
913 /* near */
914 return ptr;
915 }
916 /* block group */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900917 return nilfs_bmap_find_target_in_group(btree);
Koji Sato17c76b02009-04-06 19:01:24 -0700918}
919
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900920static void nilfs_btree_set_target_v(struct nilfs_bmap *btree, __u64 key,
Koji Sato17c76b02009-04-06 19:01:24 -0700921 __u64 ptr)
922{
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900923 btree->b_last_allocated_key = key;
924 btree->b_last_allocated_ptr = ptr;
Koji Sato17c76b02009-04-06 19:01:24 -0700925}
926
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900927static int nilfs_btree_prepare_insert(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -0700928 struct nilfs_btree_path *path,
929 int *levelp, __u64 key, __u64 ptr,
930 struct nilfs_bmap_stats *stats)
931{
932 struct buffer_head *bh;
933 struct nilfs_btree_node *node, *parent, *sib;
934 __u64 sibptr;
935 int pindex, level, ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900936 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -0700937
938 stats->bs_nblocks = 0;
939 level = NILFS_BTREE_LEVEL_DATA;
940
941 /* allocate a new ptr for data block */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900942 if (NILFS_BMAP_USE_VBN(btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700943 path[level].bp_newreq.bpr_ptr =
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +0900944 nilfs_btree_find_target_v(btree, path, key);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900945 dat = nilfs_bmap_get_dat(btree);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +0900946 }
Koji Sato17c76b02009-04-06 19:01:24 -0700947
Ryusuke Konishie7c274f2010-07-10 19:09:49 +0900948 ret = nilfs_bmap_prepare_alloc_ptr(btree, &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -0700949 if (ret < 0)
950 goto err_out_data;
951
952 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
953 level < nilfs_btree_height(btree) - 1;
954 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900955 node = nilfs_btree_get_nonroot_node(path, level);
956 if (nilfs_btree_node_get_nchildren(node) <
957 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700958 path[level].bp_op = nilfs_btree_do_insert;
959 stats->bs_nblocks++;
960 goto out;
961 }
962
963 parent = nilfs_btree_get_node(btree, path, level + 1);
964 pindex = path[level + 1].bp_index;
965
966 /* left sibling */
967 if (pindex > 0) {
968 sibptr = nilfs_btree_node_get_ptr(btree, parent,
969 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900970 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700971 if (ret < 0)
972 goto err_out_child_node;
973 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900974 if (nilfs_btree_node_get_nchildren(sib) <
975 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700976 path[level].bp_sib_bh = bh;
977 path[level].bp_op = nilfs_btree_carry_left;
978 stats->bs_nblocks++;
979 goto out;
980 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +0900981 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700982 }
983
984 /* right sibling */
985 if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900986 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -0700987 sibptr = nilfs_btree_node_get_ptr(btree, parent,
988 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +0900989 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -0700990 if (ret < 0)
991 goto err_out_child_node;
992 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +0900993 if (nilfs_btree_node_get_nchildren(sib) <
994 nilfs_btree_node_nchildren_max(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -0700995 path[level].bp_sib_bh = bh;
996 path[level].bp_op = nilfs_btree_carry_right;
997 stats->bs_nblocks++;
998 goto out;
999 } else
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001000 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001001 }
1002
1003 /* split */
1004 path[level].bp_newreq.bpr_ptr =
1005 path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001006 ret = nilfs_bmap_prepare_alloc_ptr(btree,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001007 &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001008 if (ret < 0)
1009 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001010 ret = nilfs_btree_get_new_block(btree,
1011 path[level].bp_newreq.bpr_ptr,
1012 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001013 if (ret < 0)
1014 goto err_out_curr_node;
1015
1016 stats->bs_nblocks++;
1017
Koji Sato17c76b02009-04-06 19:01:24 -07001018 nilfs_btree_node_init(btree,
1019 (struct nilfs_btree_node *)bh->b_data,
1020 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001021 path[level].bp_sib_bh = bh;
1022 path[level].bp_op = nilfs_btree_split;
1023 }
1024
1025 /* root */
1026 node = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001027 if (nilfs_btree_node_get_nchildren(node) <
1028 nilfs_btree_node_nchildren_max(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001029 path[level].bp_op = nilfs_btree_do_insert;
1030 stats->bs_nblocks++;
1031 goto out;
1032 }
1033
1034 /* grow */
1035 path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001036 ret = nilfs_bmap_prepare_alloc_ptr(btree, &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001037 if (ret < 0)
1038 goto err_out_child_node;
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001039 ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
1040 &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001041 if (ret < 0)
1042 goto err_out_curr_node;
1043
Koji Sato17c76b02009-04-06 19:01:24 -07001044 nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data,
1045 0, level, 0, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001046 path[level].bp_sib_bh = bh;
1047 path[level].bp_op = nilfs_btree_grow;
1048
1049 level++;
1050 path[level].bp_op = nilfs_btree_do_insert;
1051
1052 /* a newly-created node block and a data block are added */
1053 stats->bs_nblocks += 2;
1054
1055 /* success */
1056 out:
1057 *levelp = level;
1058 return ret;
1059
1060 /* error */
1061 err_out_curr_node:
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001062 nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001063 err_out_child_node:
1064 for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001065 nilfs_btnode_delete(path[level].bp_sib_bh);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001066 nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001067
1068 }
1069
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001070 nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001071 err_out_data:
1072 *levelp = level;
1073 stats->bs_nblocks = 0;
1074 return ret;
1075}
1076
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001077static void nilfs_btree_commit_insert(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001078 struct nilfs_btree_path *path,
1079 int maxlevel, __u64 key, __u64 ptr)
1080{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001081 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001082 int level;
1083
1084 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1085 ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001086 if (NILFS_BMAP_USE_VBN(btree)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001087 nilfs_btree_set_target_v(btree, key, ptr);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001088 dat = nilfs_bmap_get_dat(btree);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001089 }
Koji Sato17c76b02009-04-06 19:01:24 -07001090
1091 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001092 nilfs_bmap_commit_alloc_ptr(btree,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001093 &path[level - 1].bp_newreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001094 path[level].bp_op(btree, path, level, &key, &ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001095 }
1096
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001097 if (!nilfs_bmap_dirty(btree))
1098 nilfs_bmap_set_dirty(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001099}
1100
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001101static int nilfs_btree_insert(struct nilfs_bmap *btree, __u64 key, __u64 ptr)
Koji Sato17c76b02009-04-06 19:01:24 -07001102{
Koji Sato17c76b02009-04-06 19:01:24 -07001103 struct nilfs_btree_path *path;
1104 struct nilfs_bmap_stats stats;
1105 int level, ret;
1106
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001107 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001108 if (path == NULL)
1109 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001110
1111 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1112 NILFS_BTREE_LEVEL_NODE_MIN);
1113 if (ret != -ENOENT) {
1114 if (ret == 0)
1115 ret = -EEXIST;
1116 goto out;
1117 }
1118
1119 ret = nilfs_btree_prepare_insert(btree, path, &level, key, ptr, &stats);
1120 if (ret < 0)
1121 goto out;
1122 nilfs_btree_commit_insert(btree, path, level, key, ptr);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001123 nilfs_bmap_add_blocks(btree, stats.bs_nblocks);
Koji Sato17c76b02009-04-06 19:01:24 -07001124
1125 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001126 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001127 return ret;
1128}
1129
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001130static void nilfs_btree_do_delete(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001131 struct nilfs_btree_path *path,
1132 int level, __u64 *keyp, __u64 *ptrp)
1133{
1134 struct nilfs_btree_node *node;
1135
1136 if (level < nilfs_btree_height(btree) - 1) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001137 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001138 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1139 path[level].bp_index);
1140 if (!buffer_dirty(path[level].bp_bh))
1141 nilfs_btnode_mark_dirty(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001142 if (path[level].bp_index == 0)
1143 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001144 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001145 } else {
1146 node = nilfs_btree_get_root(btree);
1147 nilfs_btree_node_delete(btree, node, keyp, ptrp,
1148 path[level].bp_index);
1149 }
1150}
1151
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001152static void nilfs_btree_borrow_left(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001153 struct nilfs_btree_path *path,
1154 int level, __u64 *keyp, __u64 *ptrp)
1155{
1156 struct nilfs_btree_node *node, *left;
1157 int nchildren, lnchildren, n;
1158
1159 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1160
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001161 node = nilfs_btree_get_nonroot_node(path, level);
1162 left = nilfs_btree_get_sib_node(path, level);
1163 nchildren = nilfs_btree_node_get_nchildren(node);
1164 lnchildren = nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001165
1166 n = (nchildren + lnchildren) / 2 - nchildren;
1167
1168 nilfs_btree_node_move_right(btree, left, node, n);
1169
1170 if (!buffer_dirty(path[level].bp_bh))
1171 nilfs_btnode_mark_dirty(path[level].bp_bh);
1172 if (!buffer_dirty(path[level].bp_sib_bh))
1173 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1174
Koji Sato17c76b02009-04-06 19:01:24 -07001175 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001176 nilfs_btree_node_get_key(node, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001177
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001178 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001179 path[level].bp_sib_bh = NULL;
1180 path[level].bp_index += n;
1181}
1182
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001183static void nilfs_btree_borrow_right(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001184 struct nilfs_btree_path *path,
1185 int level, __u64 *keyp, __u64 *ptrp)
1186{
1187 struct nilfs_btree_node *node, *right;
1188 int nchildren, rnchildren, n;
1189
1190 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1191
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001192 node = nilfs_btree_get_nonroot_node(path, level);
1193 right = nilfs_btree_get_sib_node(path, level);
1194 nchildren = nilfs_btree_node_get_nchildren(node);
1195 rnchildren = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001196
1197 n = (nchildren + rnchildren) / 2 - nchildren;
1198
1199 nilfs_btree_node_move_left(btree, node, right, n);
1200
1201 if (!buffer_dirty(path[level].bp_bh))
1202 nilfs_btnode_mark_dirty(path[level].bp_bh);
1203 if (!buffer_dirty(path[level].bp_sib_bh))
1204 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1205
Koji Sato17c76b02009-04-06 19:01:24 -07001206 path[level + 1].bp_index++;
1207 nilfs_btree_promote_key(btree, path, level + 1,
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001208 nilfs_btree_node_get_key(right, 0));
Koji Sato17c76b02009-04-06 19:01:24 -07001209 path[level + 1].bp_index--;
1210
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001211 brelse(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001212 path[level].bp_sib_bh = NULL;
1213}
1214
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001215static void nilfs_btree_concat_left(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001216 struct nilfs_btree_path *path,
1217 int level, __u64 *keyp, __u64 *ptrp)
1218{
1219 struct nilfs_btree_node *node, *left;
1220 int n;
1221
1222 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1223
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001224 node = nilfs_btree_get_nonroot_node(path, level);
1225 left = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001226
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001227 n = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001228
1229 nilfs_btree_node_move_left(btree, left, node, n);
1230
1231 if (!buffer_dirty(path[level].bp_sib_bh))
1232 nilfs_btnode_mark_dirty(path[level].bp_sib_bh);
1233
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001234 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001235 path[level].bp_bh = path[level].bp_sib_bh;
1236 path[level].bp_sib_bh = NULL;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001237 path[level].bp_index += nilfs_btree_node_get_nchildren(left);
Koji Sato17c76b02009-04-06 19:01:24 -07001238}
1239
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001240static void nilfs_btree_concat_right(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001241 struct nilfs_btree_path *path,
1242 int level, __u64 *keyp, __u64 *ptrp)
1243{
1244 struct nilfs_btree_node *node, *right;
1245 int n;
1246
1247 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1248
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001249 node = nilfs_btree_get_nonroot_node(path, level);
1250 right = nilfs_btree_get_sib_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001251
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001252 n = nilfs_btree_node_get_nchildren(right);
Koji Sato17c76b02009-04-06 19:01:24 -07001253
1254 nilfs_btree_node_move_left(btree, node, right, n);
1255
1256 if (!buffer_dirty(path[level].bp_bh))
1257 nilfs_btnode_mark_dirty(path[level].bp_bh);
1258
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001259 nilfs_btnode_delete(path[level].bp_sib_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001260 path[level].bp_sib_bh = NULL;
1261 path[level + 1].bp_index++;
1262}
1263
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001264static void nilfs_btree_shrink(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001265 struct nilfs_btree_path *path,
1266 int level, __u64 *keyp, __u64 *ptrp)
1267{
1268 struct nilfs_btree_node *root, *child;
1269 int n;
1270
1271 nilfs_btree_do_delete(btree, path, level, keyp, ptrp);
1272
Koji Sato17c76b02009-04-06 19:01:24 -07001273 root = nilfs_btree_get_root(btree);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001274 child = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001275
1276 nilfs_btree_node_delete(btree, root, NULL, NULL, 0);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001277 nilfs_btree_node_set_level(root, level);
1278 n = nilfs_btree_node_get_nchildren(child);
Koji Sato17c76b02009-04-06 19:01:24 -07001279 nilfs_btree_node_move_left(btree, root, child, n);
Koji Sato17c76b02009-04-06 19:01:24 -07001280
Ryusuke Konishi9f098902009-05-22 00:38:56 +09001281 nilfs_btnode_delete(path[level].bp_bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001282 path[level].bp_bh = NULL;
1283}
1284
1285
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001286static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001287 struct nilfs_btree_path *path,
1288 int *levelp,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001289 struct nilfs_bmap_stats *stats,
1290 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001291{
1292 struct buffer_head *bh;
1293 struct nilfs_btree_node *node, *parent, *sib;
1294 __u64 sibptr;
1295 int pindex, level, ret;
1296
1297 ret = 0;
1298 stats->bs_nblocks = 0;
1299 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1300 level < nilfs_btree_height(btree) - 1;
1301 level++) {
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001302 node = nilfs_btree_get_nonroot_node(path, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001303 path[level].bp_oldreq.bpr_ptr =
1304 nilfs_btree_node_get_ptr(btree, node,
1305 path[level].bp_index);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001306 ret = nilfs_bmap_prepare_end_ptr(btree,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001307 &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001308 if (ret < 0)
1309 goto err_out_child_node;
Koji Sato17c76b02009-04-06 19:01:24 -07001310
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001311 if (nilfs_btree_node_get_nchildren(node) >
1312 nilfs_btree_node_nchildren_min(node, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001313 path[level].bp_op = nilfs_btree_do_delete;
1314 stats->bs_nblocks++;
1315 goto out;
1316 }
1317
1318 parent = nilfs_btree_get_node(btree, path, level + 1);
1319 pindex = path[level + 1].bp_index;
1320
1321 if (pindex > 0) {
1322 /* left sibling */
1323 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1324 pindex - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001325 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001326 if (ret < 0)
1327 goto err_out_curr_node;
1328 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001329 if (nilfs_btree_node_get_nchildren(sib) >
1330 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001331 path[level].bp_sib_bh = bh;
1332 path[level].bp_op = nilfs_btree_borrow_left;
1333 stats->bs_nblocks++;
1334 goto out;
1335 } else {
1336 path[level].bp_sib_bh = bh;
1337 path[level].bp_op = nilfs_btree_concat_left;
1338 stats->bs_nblocks++;
1339 /* continue; */
1340 }
1341 } else if (pindex <
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001342 nilfs_btree_node_get_nchildren(parent) - 1) {
Koji Sato17c76b02009-04-06 19:01:24 -07001343 /* right sibling */
1344 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1345 pindex + 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001346 ret = nilfs_btree_get_block(btree, sibptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001347 if (ret < 0)
1348 goto err_out_curr_node;
1349 sib = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001350 if (nilfs_btree_node_get_nchildren(sib) >
1351 nilfs_btree_node_nchildren_min(sib, btree)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001352 path[level].bp_sib_bh = bh;
1353 path[level].bp_op = nilfs_btree_borrow_right;
1354 stats->bs_nblocks++;
1355 goto out;
1356 } else {
1357 path[level].bp_sib_bh = bh;
1358 path[level].bp_op = nilfs_btree_concat_right;
1359 stats->bs_nblocks++;
1360 /* continue; */
1361 }
1362 } else {
1363 /* no siblings */
1364 /* the only child of the root node */
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001365 WARN_ON(level != nilfs_btree_height(btree) - 2);
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001366 if (nilfs_btree_node_get_nchildren(node) - 1 <=
Koji Sato17c76b02009-04-06 19:01:24 -07001367 NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1368 path[level].bp_op = nilfs_btree_shrink;
1369 stats->bs_nblocks += 2;
1370 } else {
1371 path[level].bp_op = nilfs_btree_do_delete;
1372 stats->bs_nblocks++;
1373 }
1374
1375 goto out;
1376
1377 }
1378 }
1379
1380 node = nilfs_btree_get_root(btree);
1381 path[level].bp_oldreq.bpr_ptr =
1382 nilfs_btree_node_get_ptr(btree, node, path[level].bp_index);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001383
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001384 ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat);
Ryusuke Konishid4b96152009-05-24 03:25:44 +09001385 if (ret < 0)
1386 goto err_out_child_node;
1387
Koji Sato17c76b02009-04-06 19:01:24 -07001388 /* child of the root node is deleted */
1389 path[level].bp_op = nilfs_btree_do_delete;
1390 stats->bs_nblocks++;
1391
1392 /* success */
1393 out:
1394 *levelp = level;
1395 return ret;
1396
1397 /* error */
1398 err_out_curr_node:
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001399 nilfs_bmap_abort_end_ptr(btree, &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001400 err_out_child_node:
1401 for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001402 brelse(path[level].bp_sib_bh);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001403 nilfs_bmap_abort_end_ptr(btree, &path[level].bp_oldreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001404 }
1405 *levelp = level;
1406 stats->bs_nblocks = 0;
1407 return ret;
1408}
1409
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001410static void nilfs_btree_commit_delete(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001411 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001412 int maxlevel, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001413{
1414 int level;
1415
1416 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001417 nilfs_bmap_commit_end_ptr(btree, &path[level].bp_oldreq, dat);
Pekka Enberg8acfbf02009-04-06 19:01:49 -07001418 path[level].bp_op(btree, path, level, NULL, NULL);
Koji Sato17c76b02009-04-06 19:01:24 -07001419 }
1420
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001421 if (!nilfs_bmap_dirty(btree))
1422 nilfs_bmap_set_dirty(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001423}
1424
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001425static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key)
Koji Sato17c76b02009-04-06 19:01:24 -07001426
1427{
Koji Sato17c76b02009-04-06 19:01:24 -07001428 struct nilfs_btree_path *path;
1429 struct nilfs_bmap_stats stats;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001430 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001431 int level, ret;
1432
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001433 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001434 if (path == NULL)
1435 return -ENOMEM;
Li Hongf9054402010-04-02 17:36:34 +08001436
Koji Sato17c76b02009-04-06 19:01:24 -07001437 ret = nilfs_btree_do_lookup(btree, path, key, NULL,
1438 NILFS_BTREE_LEVEL_NODE_MIN);
1439 if (ret < 0)
1440 goto out;
1441
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001442
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001443 dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001444
1445 ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001446 if (ret < 0)
1447 goto out;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001448 nilfs_btree_commit_delete(btree, path, level, dat);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001449 nilfs_bmap_sub_blocks(btree, stats.bs_nblocks);
Koji Sato17c76b02009-04-06 19:01:24 -07001450
1451out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001452 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001453 return ret;
1454}
1455
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001456static int nilfs_btree_last_key(const struct nilfs_bmap *btree, __u64 *keyp)
Koji Sato17c76b02009-04-06 19:01:24 -07001457{
Koji Sato17c76b02009-04-06 19:01:24 -07001458 struct nilfs_btree_path *path;
1459 int ret;
1460
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001461 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001462 if (path == NULL)
1463 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001464
1465 ret = nilfs_btree_do_lookup_last(btree, path, keyp, NULL);
1466
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001467 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001468
1469 return ret;
1470}
1471
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001472static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key)
Koji Sato17c76b02009-04-06 19:01:24 -07001473{
1474 struct buffer_head *bh;
Koji Sato17c76b02009-04-06 19:01:24 -07001475 struct nilfs_btree_node *root, *node;
1476 __u64 maxkey, nextmaxkey;
1477 __u64 ptr;
1478 int nchildren, ret;
1479
Koji Sato17c76b02009-04-06 19:01:24 -07001480 root = nilfs_btree_get_root(btree);
1481 switch (nilfs_btree_height(btree)) {
1482 case 2:
1483 bh = NULL;
1484 node = root;
1485 break;
1486 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001487 nchildren = nilfs_btree_node_get_nchildren(root);
Koji Sato17c76b02009-04-06 19:01:24 -07001488 if (nchildren > 1)
1489 return 0;
1490 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001491 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001492 if (ret < 0)
1493 return ret;
1494 node = (struct nilfs_btree_node *)bh->b_data;
1495 break;
1496 default:
1497 return 0;
1498 }
1499
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001500 nchildren = nilfs_btree_node_get_nchildren(node);
1501 maxkey = nilfs_btree_node_get_key(node, nchildren - 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001502 nextmaxkey = (nchildren > 1) ?
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001503 nilfs_btree_node_get_key(node, nchildren - 2) : 0;
Koji Sato17c76b02009-04-06 19:01:24 -07001504 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001505 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001506
Ryusuke Konishi30333422009-05-24 00:09:44 +09001507 return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
Koji Sato17c76b02009-04-06 19:01:24 -07001508}
1509
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001510static int nilfs_btree_gather_data(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001511 __u64 *keys, __u64 *ptrs, int nitems)
1512{
1513 struct buffer_head *bh;
Koji Sato17c76b02009-04-06 19:01:24 -07001514 struct nilfs_btree_node *node, *root;
1515 __le64 *dkeys;
1516 __le64 *dptrs;
1517 __u64 ptr;
1518 int nchildren, i, ret;
1519
Koji Sato17c76b02009-04-06 19:01:24 -07001520 root = nilfs_btree_get_root(btree);
1521 switch (nilfs_btree_height(btree)) {
1522 case 2:
1523 bh = NULL;
1524 node = root;
1525 break;
1526 case 3:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001527 nchildren = nilfs_btree_node_get_nchildren(root);
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001528 WARN_ON(nchildren > 1);
Koji Sato17c76b02009-04-06 19:01:24 -07001529 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001530 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001531 if (ret < 0)
1532 return ret;
1533 node = (struct nilfs_btree_node *)bh->b_data;
1534 break;
1535 default:
1536 node = NULL;
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001537 return -EINVAL;
Koji Sato17c76b02009-04-06 19:01:24 -07001538 }
1539
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001540 nchildren = nilfs_btree_node_get_nchildren(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001541 if (nchildren < nitems)
1542 nitems = nchildren;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001543 dkeys = nilfs_btree_node_dkeys(node);
1544 dptrs = nilfs_btree_node_dptrs(node, btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001545 for (i = 0; i < nitems; i++) {
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +09001546 keys[i] = le64_to_cpu(dkeys[i]);
1547 ptrs[i] = le64_to_cpu(dptrs[i]);
Koji Sato17c76b02009-04-06 19:01:24 -07001548 }
1549
1550 if (bh != NULL)
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001551 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001552
1553 return nitems;
1554}
1555
1556static int
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001557nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *btree, __u64 key,
Koji Sato17c76b02009-04-06 19:01:24 -07001558 union nilfs_bmap_ptr_req *dreq,
1559 union nilfs_bmap_ptr_req *nreq,
1560 struct buffer_head **bhp,
1561 struct nilfs_bmap_stats *stats)
1562{
1563 struct buffer_head *bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001564 struct inode *dat = NULL;
Koji Sato17c76b02009-04-06 19:01:24 -07001565 int ret;
1566
Koji Sato17c76b02009-04-06 19:01:24 -07001567 stats->bs_nblocks = 0;
1568
1569 /* for data */
1570 /* cannot find near ptr */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001571 if (NILFS_BMAP_USE_VBN(btree)) {
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001572 dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001573 dat = nilfs_bmap_get_dat(btree);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001574 }
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001575
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001576 ret = nilfs_bmap_prepare_alloc_ptr(btree, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001577 if (ret < 0)
1578 return ret;
1579
1580 *bhp = NULL;
1581 stats->bs_nblocks++;
1582 if (nreq != NULL) {
1583 nreq->bpr_ptr = dreq->bpr_ptr + 1;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001584 ret = nilfs_bmap_prepare_alloc_ptr(btree, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001585 if (ret < 0)
1586 goto err_out_dreq;
1587
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09001588 ret = nilfs_btree_get_new_block(btree, nreq->bpr_ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001589 if (ret < 0)
1590 goto err_out_nreq;
1591
1592 *bhp = bh;
1593 stats->bs_nblocks++;
1594 }
1595
1596 /* success */
1597 return 0;
1598
1599 /* error */
1600 err_out_nreq:
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001601 nilfs_bmap_abort_alloc_ptr(btree, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001602 err_out_dreq:
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001603 nilfs_bmap_abort_alloc_ptr(btree, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001604 stats->bs_nblocks = 0;
1605 return ret;
1606
1607}
1608
1609static void
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001610nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001611 __u64 key, __u64 ptr,
1612 const __u64 *keys, const __u64 *ptrs,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001613 int n,
Koji Sato17c76b02009-04-06 19:01:24 -07001614 union nilfs_bmap_ptr_req *dreq,
1615 union nilfs_bmap_ptr_req *nreq,
1616 struct buffer_head *bh)
1617{
Koji Sato17c76b02009-04-06 19:01:24 -07001618 struct nilfs_btree_node *node;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001619 struct inode *dat;
Koji Sato17c76b02009-04-06 19:01:24 -07001620 __u64 tmpptr;
1621
1622 /* free resources */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001623 if (btree->b_ops->bop_clear != NULL)
1624 btree->b_ops->bop_clear(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001625
1626 /* ptr must be a pointer to a buffer head. */
1627 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1628
1629 /* convert and insert */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001630 dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL;
1631 nilfs_btree_init(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001632 if (nreq != NULL) {
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001633 nilfs_bmap_commit_alloc_ptr(btree, dreq, dat);
1634 nilfs_bmap_commit_alloc_ptr(btree, nreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001635
1636 /* create child node at level 1 */
Koji Sato17c76b02009-04-06 19:01:24 -07001637 node = (struct nilfs_btree_node *)bh->b_data;
1638 nilfs_btree_node_init(btree, node, 0, 1, n, keys, ptrs);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001639 nilfs_btree_node_insert(btree, node, key, dreq->bpr_ptr, n);
Koji Sato17c76b02009-04-06 19:01:24 -07001640 if (!buffer_dirty(bh))
1641 nilfs_btnode_mark_dirty(bh);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001642 if (!nilfs_bmap_dirty(btree))
1643 nilfs_bmap_set_dirty(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001644
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09001645 brelse(bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001646
1647 /* create root node at level 2 */
1648 node = nilfs_btree_get_root(btree);
1649 tmpptr = nreq->bpr_ptr;
1650 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1651 2, 1, &keys[0], &tmpptr);
1652 } else {
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001653 nilfs_bmap_commit_alloc_ptr(btree, dreq, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001654
1655 /* create root node at level 1 */
1656 node = nilfs_btree_get_root(btree);
1657 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1658 1, n, keys, ptrs);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001659 nilfs_btree_node_insert(btree, node, key, dreq->bpr_ptr, n);
1660 if (!nilfs_bmap_dirty(btree))
1661 nilfs_bmap_set_dirty(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001662 }
1663
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001664 if (NILFS_BMAP_USE_VBN(btree))
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001665 nilfs_btree_set_target_v(btree, key, dreq->bpr_ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001666}
1667
1668/**
1669 * nilfs_btree_convert_and_insert -
1670 * @bmap:
1671 * @key:
1672 * @ptr:
1673 * @keys:
1674 * @ptrs:
1675 * @n:
Koji Sato17c76b02009-04-06 19:01:24 -07001676 */
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001677int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001678 __u64 key, __u64 ptr,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001679 const __u64 *keys, const __u64 *ptrs, int n)
Koji Sato17c76b02009-04-06 19:01:24 -07001680{
1681 struct buffer_head *bh;
1682 union nilfs_bmap_ptr_req dreq, nreq, *di, *ni;
1683 struct nilfs_bmap_stats stats;
1684 int ret;
1685
1686 if (n + 1 <= NILFS_BTREE_ROOT_NCHILDREN_MAX) {
1687 di = &dreq;
1688 ni = NULL;
1689 } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX(
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001690 1 << btree->b_inode->i_blkbits)) {
Koji Sato17c76b02009-04-06 19:01:24 -07001691 di = &dreq;
1692 ni = &nreq;
1693 } else {
1694 di = NULL;
1695 ni = NULL;
1696 BUG();
1697 }
1698
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001699 ret = nilfs_btree_prepare_convert_and_insert(btree, key, di, ni, &bh,
Koji Sato17c76b02009-04-06 19:01:24 -07001700 &stats);
1701 if (ret < 0)
1702 return ret;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001703 nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n,
Ryusuke Konishi30333422009-05-24 00:09:44 +09001704 di, ni, bh);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001705 nilfs_bmap_add_blocks(btree, stats.bs_nblocks);
Koji Sato17c76b02009-04-06 19:01:24 -07001706 return 0;
1707}
1708
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001709static int nilfs_btree_propagate_p(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001710 struct nilfs_btree_path *path,
1711 int level,
1712 struct buffer_head *bh)
1713{
1714 while ((++level < nilfs_btree_height(btree) - 1) &&
1715 !buffer_dirty(path[level].bp_bh))
1716 nilfs_btnode_mark_dirty(path[level].bp_bh);
1717
1718 return 0;
1719}
1720
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001721static int nilfs_btree_prepare_update_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001722 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001723 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001724{
1725 struct nilfs_btree_node *parent;
1726 int ret;
1727
1728 parent = nilfs_btree_get_node(btree, path, level + 1);
1729 path[level].bp_oldreq.bpr_ptr =
1730 nilfs_btree_node_get_ptr(btree, parent,
1731 path[level + 1].bp_index);
1732 path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001733 ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req,
1734 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001735 if (ret < 0)
1736 return ret;
1737
1738 if (buffer_nilfs_node(path[level].bp_bh)) {
1739 path[level].bp_ctxt.oldkey = path[level].bp_oldreq.bpr_ptr;
1740 path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr;
1741 path[level].bp_ctxt.bh = path[level].bp_bh;
1742 ret = nilfs_btnode_prepare_change_key(
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001743 &NILFS_BMAP_I(btree)->i_btnode_cache,
Koji Sato17c76b02009-04-06 19:01:24 -07001744 &path[level].bp_ctxt);
1745 if (ret < 0) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001746 nilfs_dat_abort_update(dat,
1747 &path[level].bp_oldreq.bpr_req,
1748 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001749 return ret;
1750 }
1751 }
1752
1753 return 0;
1754}
1755
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001756static void nilfs_btree_commit_update_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001757 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001758 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001759{
1760 struct nilfs_btree_node *parent;
1761
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001762 nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req,
1763 &path[level].bp_newreq.bpr_req,
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001764 btree->b_ptr_type == NILFS_BMAP_PTR_VS);
Koji Sato17c76b02009-04-06 19:01:24 -07001765
1766 if (buffer_nilfs_node(path[level].bp_bh)) {
1767 nilfs_btnode_commit_change_key(
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001768 &NILFS_BMAP_I(btree)->i_btnode_cache,
Koji Sato17c76b02009-04-06 19:01:24 -07001769 &path[level].bp_ctxt);
1770 path[level].bp_bh = path[level].bp_ctxt.bh;
1771 }
1772 set_buffer_nilfs_volatile(path[level].bp_bh);
1773
1774 parent = nilfs_btree_get_node(btree, path, level + 1);
1775 nilfs_btree_node_set_ptr(btree, parent, path[level + 1].bp_index,
1776 path[level].bp_newreq.bpr_ptr);
1777}
1778
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001779static void nilfs_btree_abort_update_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001780 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001781 int level, struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001782{
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001783 nilfs_dat_abort_update(dat, &path[level].bp_oldreq.bpr_req,
1784 &path[level].bp_newreq.bpr_req);
Koji Sato17c76b02009-04-06 19:01:24 -07001785 if (buffer_nilfs_node(path[level].bp_bh))
1786 nilfs_btnode_abort_change_key(
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001787 &NILFS_BMAP_I(btree)->i_btnode_cache,
Koji Sato17c76b02009-04-06 19:01:24 -07001788 &path[level].bp_ctxt);
1789}
1790
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001791static int nilfs_btree_prepare_propagate_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001792 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001793 int minlevel, int *maxlevelp,
1794 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001795{
1796 int level, ret;
1797
1798 level = minlevel;
1799 if (!buffer_nilfs_volatile(path[level].bp_bh)) {
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001800 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001801 if (ret < 0)
1802 return ret;
1803 }
1804 while ((++level < nilfs_btree_height(btree) - 1) &&
1805 !buffer_dirty(path[level].bp_bh)) {
1806
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001807 WARN_ON(buffer_nilfs_volatile(path[level].bp_bh));
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001808 ret = nilfs_btree_prepare_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001809 if (ret < 0)
1810 goto out;
1811 }
1812
1813 /* success */
Koji Sato17c76b02009-04-06 19:01:24 -07001814 *maxlevelp = level - 1;
1815 return 0;
1816
1817 /* error */
1818 out:
1819 while (--level > minlevel)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001820 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001821 if (!buffer_nilfs_volatile(path[level].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001822 nilfs_btree_abort_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001823 return ret;
1824}
1825
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001826static void nilfs_btree_commit_propagate_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001827 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001828 int minlevel, int maxlevel,
1829 struct buffer_head *bh,
1830 struct inode *dat)
Koji Sato17c76b02009-04-06 19:01:24 -07001831{
1832 int level;
1833
1834 if (!buffer_nilfs_volatile(path[minlevel].bp_bh))
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001835 nilfs_btree_commit_update_v(btree, path, minlevel, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001836
1837 for (level = minlevel + 1; level <= maxlevel; level++)
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001838 nilfs_btree_commit_update_v(btree, path, level, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001839}
1840
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001841static int nilfs_btree_propagate_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001842 struct nilfs_btree_path *path,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001843 int level, struct buffer_head *bh)
Koji Sato17c76b02009-04-06 19:01:24 -07001844{
Li Hong308f4412010-04-02 18:40:39 +08001845 int maxlevel = 0, ret;
Koji Sato17c76b02009-04-06 19:01:24 -07001846 struct nilfs_btree_node *parent;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001847 struct inode *dat = nilfs_bmap_get_dat(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07001848 __u64 ptr;
1849
1850 get_bh(bh);
1851 path[level].bp_bh = bh;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001852 ret = nilfs_btree_prepare_propagate_v(btree, path, level, &maxlevel,
1853 dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001854 if (ret < 0)
1855 goto out;
1856
1857 if (buffer_nilfs_volatile(path[level].bp_bh)) {
1858 parent = nilfs_btree_get_node(btree, path, level + 1);
1859 ptr = nilfs_btree_node_get_ptr(btree, parent,
1860 path[level + 1].bp_index);
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001861 ret = nilfs_dat_mark_dirty(dat, ptr);
Koji Sato17c76b02009-04-06 19:01:24 -07001862 if (ret < 0)
1863 goto out;
1864 }
1865
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09001866 nilfs_btree_commit_propagate_v(btree, path, level, maxlevel, bh, dat);
Koji Sato17c76b02009-04-06 19:01:24 -07001867
1868 out:
1869 brelse(path[level].bp_bh);
1870 path[level].bp_bh = NULL;
1871 return ret;
1872}
1873
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001874static int nilfs_btree_propagate(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001875 struct buffer_head *bh)
1876{
Koji Sato17c76b02009-04-06 19:01:24 -07001877 struct nilfs_btree_path *path;
1878 struct nilfs_btree_node *node;
1879 __u64 key;
1880 int level, ret;
1881
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001882 WARN_ON(!buffer_dirty(bh));
Koji Sato17c76b02009-04-06 19:01:24 -07001883
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001884 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07001885 if (path == NULL)
1886 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07001887
1888 if (buffer_nilfs_node(bh)) {
1889 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001890 key = nilfs_btree_node_get_key(node, 0);
1891 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07001892 } else {
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001893 key = nilfs_bmap_data_get_key(btree, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001894 level = NILFS_BTREE_LEVEL_DATA;
1895 }
1896
1897 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
1898 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07001899 if (unlikely(ret == -ENOENT))
Koji Sato17c76b02009-04-06 19:01:24 -07001900 printk(KERN_CRIT "%s: key = %llu, level == %d\n",
1901 __func__, (unsigned long long)key, level);
Koji Sato17c76b02009-04-06 19:01:24 -07001902 goto out;
1903 }
1904
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001905 ret = NILFS_BMAP_USE_VBN(btree) ?
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09001906 nilfs_btree_propagate_v(btree, path, level, bh) :
1907 nilfs_btree_propagate_p(btree, path, level, bh);
Koji Sato17c76b02009-04-06 19:01:24 -07001908
1909 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001910 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07001911
1912 return ret;
1913}
1914
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001915static int nilfs_btree_propagate_gc(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001916 struct buffer_head *bh)
1917{
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001918 return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(btree), bh->b_blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07001919}
1920
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001921static void nilfs_btree_add_dirty_buffer(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001922 struct list_head *lists,
1923 struct buffer_head *bh)
1924{
1925 struct list_head *head;
1926 struct buffer_head *cbh;
1927 struct nilfs_btree_node *node, *cnode;
1928 __u64 key, ckey;
1929 int level;
1930
1931 get_bh(bh);
1932 node = (struct nilfs_btree_node *)bh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001933 key = nilfs_btree_node_get_key(node, 0);
1934 level = nilfs_btree_node_get_level(node);
Ryusuke Konishicfa913a2010-07-07 17:19:54 +09001935 if (level < NILFS_BTREE_LEVEL_NODE_MIN ||
1936 level >= NILFS_BTREE_LEVEL_MAX) {
1937 dump_stack();
1938 printk(KERN_WARNING
1939 "%s: invalid btree level: %d (key=%llu, ino=%lu, "
1940 "blocknr=%llu)\n",
1941 __func__, level, (unsigned long long)key,
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001942 NILFS_BMAP_I(btree)->vfs_inode.i_ino,
Ryusuke Konishicfa913a2010-07-07 17:19:54 +09001943 (unsigned long long)bh->b_blocknr);
1944 return;
1945 }
1946
Koji Sato17c76b02009-04-06 19:01:24 -07001947 list_for_each(head, &lists[level]) {
1948 cbh = list_entry(head, struct buffer_head, b_assoc_buffers);
1949 cnode = (struct nilfs_btree_node *)cbh->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09001950 ckey = nilfs_btree_node_get_key(cnode, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07001951 if (key < ckey)
1952 break;
1953 }
1954 list_add_tail(&bh->b_assoc_buffers, head);
1955}
1956
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001957static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001958 struct list_head *listp)
1959{
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001960 struct address_space *btcache = &NILFS_BMAP_I(btree)->i_btnode_cache;
Koji Sato17c76b02009-04-06 19:01:24 -07001961 struct list_head lists[NILFS_BTREE_LEVEL_MAX];
1962 struct pagevec pvec;
1963 struct buffer_head *bh, *head;
1964 pgoff_t index = 0;
1965 int level, i;
1966
1967 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1968 level < NILFS_BTREE_LEVEL_MAX;
1969 level++)
1970 INIT_LIST_HEAD(&lists[level]);
1971
1972 pagevec_init(&pvec, 0);
1973
1974 while (pagevec_lookup_tag(&pvec, btcache, &index, PAGECACHE_TAG_DIRTY,
1975 PAGEVEC_SIZE)) {
1976 for (i = 0; i < pagevec_count(&pvec); i++) {
1977 bh = head = page_buffers(pvec.pages[i]);
1978 do {
1979 if (buffer_dirty(bh))
1980 nilfs_btree_add_dirty_buffer(btree,
1981 lists, bh);
1982 } while ((bh = bh->b_this_page) != head);
1983 }
1984 pagevec_release(&pvec);
1985 cond_resched();
1986 }
1987
1988 for (level = NILFS_BTREE_LEVEL_NODE_MIN;
1989 level < NILFS_BTREE_LEVEL_MAX;
1990 level++)
Ryusuke Konishi0935db72009-11-29 02:39:11 +09001991 list_splice_tail(&lists[level], listp);
Koji Sato17c76b02009-04-06 19:01:24 -07001992}
1993
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09001994static int nilfs_btree_assign_p(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07001995 struct nilfs_btree_path *path,
1996 int level,
1997 struct buffer_head **bh,
1998 sector_t blocknr,
1999 union nilfs_binfo *binfo)
2000{
2001 struct nilfs_btree_node *parent;
2002 __u64 key;
2003 __u64 ptr;
2004 int ret;
2005
2006 parent = nilfs_btree_get_node(btree, path, level + 1);
2007 ptr = nilfs_btree_node_get_ptr(btree, parent,
2008 path[level + 1].bp_index);
2009 if (buffer_nilfs_node(*bh)) {
2010 path[level].bp_ctxt.oldkey = ptr;
2011 path[level].bp_ctxt.newkey = blocknr;
2012 path[level].bp_ctxt.bh = *bh;
2013 ret = nilfs_btnode_prepare_change_key(
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002014 &NILFS_BMAP_I(btree)->i_btnode_cache,
Koji Sato17c76b02009-04-06 19:01:24 -07002015 &path[level].bp_ctxt);
2016 if (ret < 0)
2017 return ret;
2018 nilfs_btnode_commit_change_key(
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002019 &NILFS_BMAP_I(btree)->i_btnode_cache,
Koji Sato17c76b02009-04-06 19:01:24 -07002020 &path[level].bp_ctxt);
2021 *bh = path[level].bp_ctxt.bh;
2022 }
2023
2024 nilfs_btree_node_set_ptr(btree, parent,
2025 path[level + 1].bp_index, blocknr);
2026
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002027 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002028 /* on-disk format */
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +09002029 binfo->bi_dat.bi_blkoff = cpu_to_le64(key);
Koji Sato17c76b02009-04-06 19:01:24 -07002030 binfo->bi_dat.bi_level = level;
2031
2032 return 0;
2033}
2034
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002035static int nilfs_btree_assign_v(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07002036 struct nilfs_btree_path *path,
2037 int level,
2038 struct buffer_head **bh,
2039 sector_t blocknr,
2040 union nilfs_binfo *binfo)
2041{
2042 struct nilfs_btree_node *parent;
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002043 struct inode *dat = nilfs_bmap_get_dat(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07002044 __u64 key;
2045 __u64 ptr;
2046 union nilfs_bmap_ptr_req req;
2047 int ret;
2048
2049 parent = nilfs_btree_get_node(btree, path, level + 1);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002050 ptr = nilfs_btree_node_get_ptr(btree, parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002051 req.bpr_ptr = ptr;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002052 ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
2053 if (ret < 0)
Koji Sato17c76b02009-04-06 19:01:24 -07002054 return ret;
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002055 nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002056
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002057 key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index);
Koji Sato17c76b02009-04-06 19:01:24 -07002058 /* on-disk format */
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +09002059 binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr);
2060 binfo->bi_v.bi_blkoff = cpu_to_le64(key);
Koji Sato17c76b02009-04-06 19:01:24 -07002061
2062 return 0;
2063}
2064
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002065static int nilfs_btree_assign(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07002066 struct buffer_head **bh,
2067 sector_t blocknr,
2068 union nilfs_binfo *binfo)
2069{
Koji Sato17c76b02009-04-06 19:01:24 -07002070 struct nilfs_btree_path *path;
2071 struct nilfs_btree_node *node;
2072 __u64 key;
2073 int level, ret;
2074
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002075 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002076 if (path == NULL)
2077 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07002078
2079 if (buffer_nilfs_node(*bh)) {
2080 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002081 key = nilfs_btree_node_get_key(node, 0);
2082 level = nilfs_btree_node_get_level(node);
Koji Sato17c76b02009-04-06 19:01:24 -07002083 } else {
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002084 key = nilfs_bmap_data_get_key(btree, *bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002085 level = NILFS_BTREE_LEVEL_DATA;
2086 }
2087
2088 ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1);
2089 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002090 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002091 goto out;
2092 }
2093
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002094 ret = NILFS_BMAP_USE_VBN(btree) ?
Ryusuke Konishi7cde31d2009-05-24 18:07:59 +09002095 nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) :
2096 nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
Koji Sato17c76b02009-04-06 19:01:24 -07002097
2098 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002099 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002100
2101 return ret;
2102}
2103
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002104static int nilfs_btree_assign_gc(struct nilfs_bmap *btree,
Koji Sato17c76b02009-04-06 19:01:24 -07002105 struct buffer_head **bh,
2106 sector_t blocknr,
2107 union nilfs_binfo *binfo)
2108{
Koji Sato17c76b02009-04-06 19:01:24 -07002109 struct nilfs_btree_node *node;
2110 __u64 key;
2111 int ret;
2112
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002113 ret = nilfs_dat_move(nilfs_bmap_get_dat(btree), (*bh)->b_blocknr,
Ryusuke Konishi2e0c2c72009-08-15 15:34:33 +09002114 blocknr);
Koji Sato17c76b02009-04-06 19:01:24 -07002115 if (ret < 0)
2116 return ret;
2117
2118 if (buffer_nilfs_node(*bh)) {
2119 node = (struct nilfs_btree_node *)(*bh)->b_data;
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002120 key = nilfs_btree_node_get_key(node, 0);
Koji Sato17c76b02009-04-06 19:01:24 -07002121 } else
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002122 key = nilfs_bmap_data_get_key(btree, *bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002123
2124 /* on-disk format */
2125 binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr);
Ryusuke Konishi25b8d7d2010-07-10 16:50:41 +09002126 binfo->bi_v.bi_blkoff = cpu_to_le64(key);
Koji Sato17c76b02009-04-06 19:01:24 -07002127
2128 return 0;
2129}
2130
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002131static int nilfs_btree_mark(struct nilfs_bmap *btree, __u64 key, int level)
Koji Sato17c76b02009-04-06 19:01:24 -07002132{
2133 struct buffer_head *bh;
Koji Sato17c76b02009-04-06 19:01:24 -07002134 struct nilfs_btree_path *path;
2135 __u64 ptr;
2136 int ret;
2137
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002138 path = nilfs_btree_alloc_path();
Koji Sato17c76b02009-04-06 19:01:24 -07002139 if (path == NULL)
2140 return -ENOMEM;
Koji Sato17c76b02009-04-06 19:01:24 -07002141
2142 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1);
2143 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002144 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002145 goto out;
2146 }
Ryusuke Konishif198dbb2009-05-22 01:07:13 +09002147 ret = nilfs_btree_get_block(btree, ptr, &bh);
Koji Sato17c76b02009-04-06 19:01:24 -07002148 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -07002149 WARN_ON(ret == -ENOENT);
Koji Sato17c76b02009-04-06 19:01:24 -07002150 goto out;
2151 }
2152
2153 if (!buffer_dirty(bh))
2154 nilfs_btnode_mark_dirty(bh);
Ryusuke Konishi087d01b2009-05-22 00:33:13 +09002155 brelse(bh);
Ryusuke Konishie7c274f2010-07-10 19:09:49 +09002156 if (!nilfs_bmap_dirty(btree))
2157 nilfs_bmap_set_dirty(btree);
Koji Sato17c76b02009-04-06 19:01:24 -07002158
2159 out:
Ryusuke Konishi6d28f7e2009-08-15 01:14:10 +09002160 nilfs_btree_free_path(path);
Koji Sato17c76b02009-04-06 19:01:24 -07002161 return ret;
2162}
2163
2164static const struct nilfs_bmap_operations nilfs_btree_ops = {
2165 .bop_lookup = nilfs_btree_lookup,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002166 .bop_lookup_contig = nilfs_btree_lookup_contig,
Koji Sato17c76b02009-04-06 19:01:24 -07002167 .bop_insert = nilfs_btree_insert,
2168 .bop_delete = nilfs_btree_delete,
2169 .bop_clear = NULL,
2170
2171 .bop_propagate = nilfs_btree_propagate,
2172
2173 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2174
2175 .bop_assign = nilfs_btree_assign,
2176 .bop_mark = nilfs_btree_mark,
2177
2178 .bop_last_key = nilfs_btree_last_key,
2179 .bop_check_insert = NULL,
2180 .bop_check_delete = nilfs_btree_check_delete,
2181 .bop_gather_data = nilfs_btree_gather_data,
2182};
2183
2184static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
2185 .bop_lookup = NULL,
Ryusuke Konishic3a7abf2009-05-25 02:47:14 +09002186 .bop_lookup_contig = NULL,
Koji Sato17c76b02009-04-06 19:01:24 -07002187 .bop_insert = NULL,
2188 .bop_delete = NULL,
2189 .bop_clear = NULL,
2190
2191 .bop_propagate = nilfs_btree_propagate_gc,
2192
2193 .bop_lookup_dirty_buffers = nilfs_btree_lookup_dirty_buffers,
2194
2195 .bop_assign = nilfs_btree_assign_gc,
2196 .bop_mark = NULL,
2197
2198 .bop_last_key = NULL,
2199 .bop_check_insert = NULL,
2200 .bop_check_delete = NULL,
2201 .bop_gather_data = NULL,
2202};
2203
Ryusuke Konishi30333422009-05-24 00:09:44 +09002204int nilfs_btree_init(struct nilfs_bmap *bmap)
Koji Sato17c76b02009-04-06 19:01:24 -07002205{
Koji Sato17c76b02009-04-06 19:01:24 -07002206 bmap->b_ops = &nilfs_btree_ops;
Koji Sato17c76b02009-04-06 19:01:24 -07002207 return 0;
2208}
2209
2210void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
2211{
Koji Sato17c76b02009-04-06 19:01:24 -07002212 bmap->b_ops = &nilfs_btree_ops_gc;
2213}