blob: 959b7b578f9d973a766432b38431bfa245a7068b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
3 */
4
Jeff Mahoney098297b2014-04-23 10:00:36 -04005/*
6 * Now we have all buffers that must be used in balancing of the tree
7 * Further calculations can not cause schedule(), and thus the buffer
8 * tree will be stable until the balancing will be finished
9 * balance the tree according to the analysis made before,
10 * and using buffers obtained after all above.
11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <asm/uaccess.h>
14#include <linux/time.h>
Al Virof466c6f2012-03-17 01:16:43 -040015#include "reiserfs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <linux/buffer_head.h>
Ahmed S. Darwish79a81ae2007-02-12 00:52:09 -080017#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
Jeff Mahoneyfba4ebb2009-03-30 14:02:42 -040019static inline void buffer_info_init_left(struct tree_balance *tb,
20 struct buffer_info *bi)
21{
22 bi->tb = tb;
23 bi->bi_bh = tb->L[0];
24 bi->bi_parent = tb->FL[0];
25 bi->bi_position = get_left_neighbor_position(tb, 0);
26}
27
28static inline void buffer_info_init_right(struct tree_balance *tb,
29 struct buffer_info *bi)
30{
31 bi->tb = tb;
32 bi->bi_bh = tb->R[0];
33 bi->bi_parent = tb->FR[0];
34 bi->bi_position = get_right_neighbor_position(tb, 0);
35}
36
37static inline void buffer_info_init_tbS0(struct tree_balance *tb,
38 struct buffer_info *bi)
39{
40 bi->tb = tb;
41 bi->bi_bh = PATH_PLAST_BUFFER(tb->tb_path);
42 bi->bi_parent = PATH_H_PPARENT(tb->tb_path, 0);
43 bi->bi_position = PATH_H_POSITION(tb->tb_path, 1);
44}
45
46static inline void buffer_info_init_bh(struct tree_balance *tb,
47 struct buffer_info *bi,
48 struct buffer_head *bh)
49{
50 bi->tb = tb;
51 bi->bi_bh = bh;
52 bi->bi_parent = NULL;
53 bi->bi_position = 0;
54}
55
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070056inline void do_balance_mark_leaf_dirty(struct tree_balance *tb,
57 struct buffer_head *bh, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -070058{
Jeff Mahoney09f1b802014-04-23 10:00:39 -040059 journal_mark_dirty(tb->transaction_handle, bh);
Linus Torvalds1da177e2005-04-16 15:20:36 -070060}
61
62#define do_balance_mark_internal_dirty do_balance_mark_leaf_dirty
63#define do_balance_mark_sb_dirty do_balance_mark_leaf_dirty
64
Jeff Mahoney098297b2014-04-23 10:00:36 -040065/*
66 * summary:
67 * if deleting something ( tb->insert_size[0] < 0 )
68 * return(balance_leaf_when_delete()); (flag d handled here)
69 * else
70 * if lnum is larger than 0 we put items into the left node
71 * if rnum is larger than 0 we put items into the right node
72 * if snum1 is larger than 0 we put items into the new node s1
73 * if snum2 is larger than 0 we put items into the new node s2
74 * Note that all *num* count new items being created.
Jeff Mahoney098297b2014-04-23 10:00:36 -040075 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
Jeff Mahoney098297b2014-04-23 10:00:36 -040077/*
78 * Balance leaf node in case of delete or cut: insert_size[0] < 0
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 *
80 * lnum, rnum can have values >= -1
81 * -1 means that the neighbor must be joined with S
82 * 0 means that nothing should be done with the neighbor
Jeff Mahoney098297b2014-04-23 10:00:36 -040083 * >0 means to shift entirely or partly the specified number of items
84 * to the neighbor
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070086static int balance_leaf_when_delete(struct tree_balance *tb, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -070087{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070088 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
89 int item_pos = PATH_LAST_POSITION(tb->tb_path);
90 int pos_in_item = tb->tb_path->pos_in_item;
91 struct buffer_info bi;
92 int n;
93 struct item_head *ih;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
Linus Torvaldsbd4c6252005-07-12 20:21:28 -070095 RFALSE(tb->FR[0] && B_LEVEL(tb->FR[0]) != DISK_LEAF_NODE_LEVEL + 1,
96 "vs- 12000: level: wrong FR %z", tb->FR[0]);
97 RFALSE(tb->blknum[0] > 1,
98 "PAP-12005: tb->blknum == %d, can not be > 1", tb->blknum[0]);
99 RFALSE(!tb->blknum[0] && !PATH_H_PPARENT(tb->tb_path, 0),
100 "PAP-12010: tree can not be empty");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
Jeff Mahoney4cf5f7a2014-04-23 10:00:35 -0400102 ih = item_head(tbS0, item_pos);
Jeff Mahoneyfba4ebb2009-03-30 14:02:42 -0400103 buffer_info_init_tbS0(tb, &bi);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700105 /* Delete or truncate the item */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700107 switch (flag) {
108 case M_DELETE: /* delete item in S[0] */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700110 RFALSE(ih_item_len(ih) + IH_SIZE != -tb->insert_size[0],
111 "vs-12013: mode Delete, insert size %d, ih to be deleted %h",
112 -tb->insert_size[0], ih);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700114 leaf_delete_items(&bi, 0, item_pos, 1, -1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700116 if (!item_pos && tb->CFL[0]) {
117 if (B_NR_ITEMS(tbS0)) {
118 replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0,
119 0);
120 } else {
121 if (!PATH_H_POSITION(tb->tb_path, 1))
122 replace_key(tb, tb->CFL[0], tb->lkey[0],
123 PATH_H_PPARENT(tb->tb_path,
124 0), 0);
125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700128 RFALSE(!item_pos && !tb->CFL[0],
129 "PAP-12020: tb->CFL[0]==%p, tb->L[0]==%p", tb->CFL[0],
130 tb->L[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700132 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700134 case M_CUT:{ /* cut item in S[0] */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700135 if (is_direntry_le_ih(ih)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
Jeff Mahoney098297b2014-04-23 10:00:36 -0400137 /*
138 * UFS unlink semantics are such that you
139 * can only delete one directory entry at
140 * a time.
141 */
142
143 /*
144 * when we cut a directory tb->insert_size[0]
145 * means number of entries to be cut (always 1)
146 */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700147 tb->insert_size[0] = -1;
148 leaf_cut_from_buffer(&bi, item_pos, pos_in_item,
149 -tb->insert_size[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700151 RFALSE(!item_pos && !pos_in_item && !tb->CFL[0],
152 "PAP-12030: can not change delimiting key. CFL[0]=%p",
153 tb->CFL[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700155 if (!item_pos && !pos_in_item && tb->CFL[0]) {
156 replace_key(tb, tb->CFL[0], tb->lkey[0],
157 tbS0, 0);
158 }
159 } else {
160 leaf_cut_from_buffer(&bi, item_pos, pos_in_item,
161 -tb->insert_size[0]);
162
163 RFALSE(!ih_item_len(ih),
164 "PAP-12035: cut must leave non-zero dynamic length of item");
165 }
166 break;
167 }
168
169 default:
170 print_cur_tb("12040");
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -0400171 reiserfs_panic(tb->tb_sb, "PAP-12040",
172 "unexpected mode: %s(%d)",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700173 (flag ==
174 M_PASTE) ? "PASTE" : ((flag ==
175 M_INSERT) ? "INSERT" :
176 "UNKNOWN"), flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178
Jeff Mahoney098297b2014-04-23 10:00:36 -0400179 /*
180 * the rule is that no shifting occurs unless by shifting
181 * a node can be freed
182 */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700183 n = B_NR_ITEMS(tbS0);
Jeff Mahoney098297b2014-04-23 10:00:36 -0400184 /* L[0] takes part in balancing */
185 if (tb->lnum[0]) {
186 /* L[0] must be joined with S[0] */
187 if (tb->lnum[0] == -1) {
188 /* R[0] must be also joined with S[0] */
189 if (tb->rnum[0] == -1) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700190 if (tb->FR[0] == PATH_H_PPARENT(tb->tb_path, 0)) {
Jeff Mahoney098297b2014-04-23 10:00:36 -0400191 /*
192 * all contents of all the 3 buffers
193 * will be in L[0]
194 */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700195 if (PATH_H_POSITION(tb->tb_path, 1) == 0
196 && 1 < B_NR_ITEMS(tb->FR[0]))
197 replace_key(tb, tb->CFL[0],
198 tb->lkey[0],
199 tb->FR[0], 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700201 leaf_move_items(LEAF_FROM_S_TO_L, tb, n,
202 -1, NULL);
203 leaf_move_items(LEAF_FROM_R_TO_L, tb,
204 B_NR_ITEMS(tb->R[0]),
205 -1, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700207 reiserfs_invalidate_buffer(tb, tbS0);
208 reiserfs_invalidate_buffer(tb,
209 tb->R[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700211 return 0;
212 }
Jeff Mahoney098297b2014-04-23 10:00:36 -0400213 /*
214 * all contents of all the 3 buffers will
215 * be in R[0]
216 */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700217 leaf_move_items(LEAF_FROM_S_TO_R, tb, n, -1,
218 NULL);
219 leaf_move_items(LEAF_FROM_L_TO_R, tb,
220 B_NR_ITEMS(tb->L[0]), -1, NULL);
221
222 /* right_delimiting_key is correct in R[0] */
223 replace_key(tb, tb->CFR[0], tb->rkey[0],
224 tb->R[0], 0);
225
226 reiserfs_invalidate_buffer(tb, tbS0);
227 reiserfs_invalidate_buffer(tb, tb->L[0]);
228
229 return -1;
230 }
231
232 RFALSE(tb->rnum[0] != 0,
233 "PAP-12045: rnum must be 0 (%d)", tb->rnum[0]);
234 /* all contents of L[0] and S[0] will be in L[0] */
235 leaf_shift_left(tb, n, -1);
236
237 reiserfs_invalidate_buffer(tb, tbS0);
238
239 return 0;
240 }
Jeff Mahoney098297b2014-04-23 10:00:36 -0400241
242 /*
243 * a part of contents of S[0] will be in L[0] and the
244 * rest part of S[0] will be in R[0]
245 */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700246
247 RFALSE((tb->lnum[0] + tb->rnum[0] < n) ||
248 (tb->lnum[0] + tb->rnum[0] > n + 1),
249 "PAP-12050: rnum(%d) and lnum(%d) and item number(%d) in S[0] are not consistent",
250 tb->rnum[0], tb->lnum[0], n);
251 RFALSE((tb->lnum[0] + tb->rnum[0] == n) &&
252 (tb->lbytes != -1 || tb->rbytes != -1),
253 "PAP-12055: bad rbytes (%d)/lbytes (%d) parameters when items are not split",
254 tb->rbytes, tb->lbytes);
255 RFALSE((tb->lnum[0] + tb->rnum[0] == n + 1) &&
256 (tb->lbytes < 1 || tb->rbytes != -1),
257 "PAP-12060: bad rbytes (%d)/lbytes (%d) parameters when items are split",
258 tb->rbytes, tb->lbytes);
259
260 leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
261 leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
262
263 reiserfs_invalidate_buffer(tb, tbS0);
264
265 return 0;
266 }
267
268 if (tb->rnum[0] == -1) {
269 /* all contents of R[0] and S[0] will be in R[0] */
270 leaf_shift_right(tb, n, -1);
271 reiserfs_invalidate_buffer(tb, tbS0);
272 return 0;
273 }
274
275 RFALSE(tb->rnum[0],
276 "PAP-12065: bad rnum parameter must be 0 (%d)", tb->rnum[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278}
279
Jeff Mahoneyf1f007c2014-04-23 10:00:47 -0400280static void balance_leaf_insert_left(struct tree_balance *tb,
281 struct item_head *ih, const char *body)
282{
Jeff Mahoney4bf4de62014-04-23 10:00:56 -0400283 int ret;
Jeff Mahoneyf1f007c2014-04-23 10:00:47 -0400284 struct buffer_info bi;
285 int n = B_NR_ITEMS(tb->L[0]);
286
Jeff Mahoney4bf4de62014-04-23 10:00:56 -0400287 if (tb->item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) {
288 /* part of new item falls into L[0] */
289 int new_item_len, shift;
290 int version;
Jeff Mahoneyf1f007c2014-04-23 10:00:47 -0400291
Jeff Mahoney4bf4de62014-04-23 10:00:56 -0400292 ret = leaf_shift_left(tb, tb->lnum[0] - 1, -1);
Jeff Mahoneyf1f007c2014-04-23 10:00:47 -0400293
Jeff Mahoney4bf4de62014-04-23 10:00:56 -0400294 /* Calculate item length to insert to S[0] */
295 new_item_len = ih_item_len(ih) - tb->lbytes;
Jeff Mahoneyf1f007c2014-04-23 10:00:47 -0400296
Jeff Mahoney4bf4de62014-04-23 10:00:56 -0400297 /* Calculate and check item length to insert to L[0] */
298 put_ih_item_len(ih, ih_item_len(ih) - new_item_len);
Jeff Mahoneyf1f007c2014-04-23 10:00:47 -0400299
Jeff Mahoney4bf4de62014-04-23 10:00:56 -0400300 RFALSE(ih_item_len(ih) <= 0,
301 "PAP-12080: there is nothing to insert into L[0]: "
302 "ih_item_len=%d", ih_item_len(ih));
Jeff Mahoneyf1f007c2014-04-23 10:00:47 -0400303
Jeff Mahoney4bf4de62014-04-23 10:00:56 -0400304 /* Insert new item into L[0] */
305 buffer_info_init_left(tb, &bi);
306 leaf_insert_into_buf(&bi, n + tb->item_pos - ret, ih, body,
307 min_t(int, tb->zeroes_num, ih_item_len(ih)));
Jeff Mahoneyf1f007c2014-04-23 10:00:47 -0400308
Jeff Mahoney4bf4de62014-04-23 10:00:56 -0400309 version = ih_version(ih);
Jeff Mahoneyf1f007c2014-04-23 10:00:47 -0400310
Jeff Mahoney4bf4de62014-04-23 10:00:56 -0400311 /*
312 * Calculate key component, item length and body to
313 * insert into S[0]
314 */
315 shift = 0;
316 if (is_indirect_le_ih(ih))
317 shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT;
Jeff Mahoneyf1f007c2014-04-23 10:00:47 -0400318
Jeff Mahoney4bf4de62014-04-23 10:00:56 -0400319 add_le_ih_k_offset(ih, tb->lbytes << shift);
Jeff Mahoneyf1f007c2014-04-23 10:00:47 -0400320
Jeff Mahoney4bf4de62014-04-23 10:00:56 -0400321 put_ih_item_len(ih, new_item_len);
322 if (tb->lbytes > tb->zeroes_num) {
323 body += (tb->lbytes - tb->zeroes_num);
324 tb->zeroes_num = 0;
325 } else
326 tb->zeroes_num -= tb->lbytes;
327
328 RFALSE(ih_item_len(ih) <= 0,
329 "PAP-12085: there is nothing to insert into S[0]: "
330 "ih_item_len=%d", ih_item_len(ih));
331 } else {
332 /* new item in whole falls into L[0] */
333 /* Shift lnum[0]-1 items to L[0] */
334 ret = leaf_shift_left(tb, tb->lnum[0] - 1, tb->lbytes);
335
336 /* Insert new item into L[0] */
337 buffer_info_init_left(tb, &bi);
338 leaf_insert_into_buf(&bi, n + tb->item_pos - ret, ih, body,
339 tb->zeroes_num);
340 tb->insert_size[0] = 0;
341 tb->zeroes_num = 0;
342 }
Jeff Mahoneyf1f007c2014-04-23 10:00:47 -0400343}
344
Jeff Mahoney3fade932014-04-23 10:00:57 -0400345static void balance_leaf_paste_left_shift_dirent(struct tree_balance *tb,
346 struct item_head *ih,
347 const char *body)
348{
349 int n = B_NR_ITEMS(tb->L[0]);
350 struct buffer_info bi;
351
352 RFALSE(tb->zeroes_num,
353 "PAP-12090: invalid parameter in case of a directory");
354
355 /* directory item */
356 if (tb->lbytes > tb->pos_in_item) {
357 /* new directory entry falls into L[0] */
358 struct item_head *pasted;
359 int ret, l_pos_in_item = tb->pos_in_item;
360
361 /*
362 * Shift lnum[0] - 1 items in whole.
363 * Shift lbytes - 1 entries from given directory item
364 */
365 ret = leaf_shift_left(tb, tb->lnum[0], tb->lbytes - 1);
366 if (ret && !tb->item_pos) {
367 pasted = item_head(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1);
368 l_pos_in_item += ih_entry_count(pasted) -
369 (tb->lbytes - 1);
370 }
371
372 /* Append given directory entry to directory item */
373 buffer_info_init_left(tb, &bi);
374 leaf_paste_in_buffer(&bi, n + tb->item_pos - ret,
375 l_pos_in_item, tb->insert_size[0],
376 body, tb->zeroes_num);
377
378 /*
379 * previous string prepared space for pasting new entry,
380 * following string pastes this entry
381 */
382
383 /*
384 * when we have merge directory item, pos_in_item
385 * has been changed too
386 */
387
388 /* paste new directory entry. 1 is entry number */
389 leaf_paste_entries(&bi, n + tb->item_pos - ret,
390 l_pos_in_item, 1,
391 (struct reiserfs_de_head *) body,
392 body + DEH_SIZE, tb->insert_size[0]);
393 tb->insert_size[0] = 0;
394 } else {
395 /* new directory item doesn't fall into L[0] */
396 /*
397 * Shift lnum[0]-1 items in whole. Shift lbytes
398 * directory entries from directory item number lnum[0]
399 */
400 leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
401 }
402
403 /* Calculate new position to append in item body */
404 tb->pos_in_item -= tb->lbytes;
405}
406
407static void balance_leaf_paste_left_shift(struct tree_balance *tb,
408 struct item_head *ih,
409 const char *body)
410{
411 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
412 int n = B_NR_ITEMS(tb->L[0]);
413 struct buffer_info bi;
414
415 if (is_direntry_le_ih(item_head(tbS0, tb->item_pos))) {
416 balance_leaf_paste_left_shift_dirent(tb, ih, body);
417 return;
418 }
419
420 RFALSE(tb->lbytes <= 0,
421 "PAP-12095: there is nothing to shift to L[0]. "
422 "lbytes=%d", tb->lbytes);
423 RFALSE(tb->pos_in_item != ih_item_len(item_head(tbS0, tb->item_pos)),
424 "PAP-12100: incorrect position to paste: "
425 "item_len=%d, pos_in_item=%d",
426 ih_item_len(item_head(tbS0, tb->item_pos)), tb->pos_in_item);
427
428 /* appended item will be in L[0] in whole */
429 if (tb->lbytes >= tb->pos_in_item) {
430 struct item_head *tbS0_pos_ih, *tbL0_ih;
431 struct item_head *tbS0_0_ih;
432 struct reiserfs_key *left_delim_key;
433 int ret, l_n, version, temp_l;
434
435 tbS0_pos_ih = item_head(tbS0, tb->item_pos);
436 tbS0_0_ih = item_head(tbS0, 0);
437
438 /*
439 * this bytes number must be appended
440 * to the last item of L[h]
441 */
442 l_n = tb->lbytes - tb->pos_in_item;
443
444 /* Calculate new insert_size[0] */
445 tb->insert_size[0] -= l_n;
446
447 RFALSE(tb->insert_size[0] <= 0,
448 "PAP-12105: there is nothing to paste into "
449 "L[0]. insert_size=%d", tb->insert_size[0]);
450
451 ret = leaf_shift_left(tb, tb->lnum[0],
452 ih_item_len(tbS0_pos_ih));
453
454 tbL0_ih = item_head(tb->L[0], n + tb->item_pos - ret);
455
456 /* Append to body of item in L[0] */
457 buffer_info_init_left(tb, &bi);
458 leaf_paste_in_buffer(&bi, n + tb->item_pos - ret,
459 ih_item_len(tbL0_ih), l_n, body,
460 min_t(int, l_n, tb->zeroes_num));
461
462 /*
463 * 0-th item in S0 can be only of DIRECT type
464 * when l_n != 0
465 */
466 temp_l = l_n;
467
468 RFALSE(ih_item_len(tbS0_0_ih),
469 "PAP-12106: item length must be 0");
470 RFALSE(comp_short_le_keys(&tbS0_0_ih->ih_key,
471 leaf_key(tb->L[0], n + tb->item_pos - ret)),
472 "PAP-12107: items must be of the same file");
473
474 if (is_indirect_le_ih(tbL0_ih)) {
475 int shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT;
476 temp_l = l_n << shift;
477 }
478 /* update key of first item in S0 */
479 version = ih_version(tbS0_0_ih);
480 add_le_key_k_offset(version, &tbS0_0_ih->ih_key, temp_l);
481
482 /* update left delimiting key */
483 left_delim_key = internal_key(tb->CFL[0], tb->lkey[0]);
484 add_le_key_k_offset(version, left_delim_key, temp_l);
485
486 /*
487 * Calculate new body, position in item and
488 * insert_size[0]
489 */
490 if (l_n > tb->zeroes_num) {
491 body += (l_n - tb->zeroes_num);
492 tb->zeroes_num = 0;
493 } else
494 tb->zeroes_num -= l_n;
495 tb->pos_in_item = 0;
496
497 RFALSE(comp_short_le_keys(&tbS0_0_ih->ih_key,
498 leaf_key(tb->L[0],
499 B_NR_ITEMS(tb->L[0]) - 1)) ||
500 !op_is_left_mergeable(leaf_key(tbS0, 0), tbS0->b_size) ||
501 !op_is_left_mergeable(left_delim_key, tbS0->b_size),
502 "PAP-12120: item must be merge-able with left "
503 "neighboring item");
504 } else {
505 /* only part of the appended item will be in L[0] */
506
507 /* Calculate position in item for append in S[0] */
508 tb->pos_in_item -= tb->lbytes;
509
510 RFALSE(tb->pos_in_item <= 0,
511 "PAP-12125: no place for paste. pos_in_item=%d",
512 tb->pos_in_item);
513
514 /*
515 * Shift lnum[0] - 1 items in whole.
516 * Shift lbytes - 1 byte from item number lnum[0]
517 */
518 leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
519 }
520}
521
522
523/* appended item will be in L[0] in whole */
524static void balance_leaf_paste_left_whole(struct tree_balance *tb,
525 struct item_head *ih,
526 const char *body)
527{
528 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
529 int n = B_NR_ITEMS(tb->L[0]);
530 struct buffer_info bi;
531 struct item_head *pasted;
532 int ret;
533
534 /* if we paste into first item of S[0] and it is left mergable */
535 if (!tb->item_pos &&
536 op_is_left_mergeable(leaf_key(tbS0, 0), tbS0->b_size)) {
537 /*
538 * then increment pos_in_item by the size of the
539 * last item in L[0]
540 */
541 pasted = item_head(tb->L[0], n - 1);
542 if (is_direntry_le_ih(pasted))
543 tb->pos_in_item += ih_entry_count(pasted);
544 else
545 tb->pos_in_item += ih_item_len(pasted);
546 }
547
548 /*
549 * Shift lnum[0] - 1 items in whole.
550 * Shift lbytes - 1 byte from item number lnum[0]
551 */
552 ret = leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
553
554 /* Append to body of item in L[0] */
555 buffer_info_init_left(tb, &bi);
556 leaf_paste_in_buffer(&bi, n + tb->item_pos - ret, tb->pos_in_item,
557 tb->insert_size[0], body, tb->zeroes_num);
558
559 /* if appended item is directory, paste entry */
560 pasted = item_head(tb->L[0], n + tb->item_pos - ret);
561 if (is_direntry_le_ih(pasted))
562 leaf_paste_entries(&bi, n + tb->item_pos - ret,
563 tb->pos_in_item, 1,
564 (struct reiserfs_de_head *)body,
565 body + DEH_SIZE, tb->insert_size[0]);
566
567 /*
568 * if appended item is indirect item, put unformatted node
569 * into un list
570 */
571 if (is_indirect_le_ih(pasted))
572 set_ih_free_space(pasted, 0);
573
574 tb->insert_size[0] = 0;
575 tb->zeroes_num = 0;
576}
577
Jeff Mahoneycf22df12014-04-23 10:00:48 -0400578static void balance_leaf_paste_left(struct tree_balance *tb,
579 struct item_head *ih, const char *body)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580{
Jeff Mahoney3fade932014-04-23 10:00:57 -0400581 /* we must shift the part of the appended item */
582 if (tb->item_pos == tb->lnum[0] - 1 && tb->lbytes != -1)
583 balance_leaf_paste_left_shift(tb, ih, body);
584 else
585 balance_leaf_paste_left_whole(tb, ih, body);
Jeff Mahoneycf22df12014-04-23 10:00:48 -0400586}
587
Jeff Mahoney0080e9f2014-04-23 10:00:55 -0400588/* Shift lnum[0] items from S[0] to the left neighbor L[0] */
589static void balance_leaf_left(struct tree_balance *tb, struct item_head *ih,
590 const char *body, int flag)
591{
592 if (tb->lnum[0] <= 0)
593 return;
594
595 /* new item or it part falls to L[0], shift it too */
596 if (tb->item_pos < tb->lnum[0]) {
597 BUG_ON(flag != M_INSERT && flag != M_PASTE);
598
599 if (flag == M_INSERT)
600 balance_leaf_insert_left(tb, ih, body);
601 else /* M_PASTE */
602 balance_leaf_paste_left(tb, ih, body);
603 } else
604 /* new item doesn't fall into L[0] */
605 leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
606}
607
608
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400609static void balance_leaf_insert_right(struct tree_balance *tb,
610 struct item_head *ih, const char *body)
611{
612
613 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
614 int n = B_NR_ITEMS(tbS0);
615 struct buffer_info bi;
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400616 int ret;
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400617
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400618 /* new item or part of it doesn't fall into R[0] */
619 if (n - tb->rnum[0] >= tb->item_pos) {
620 leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
621 return;
622 }
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400623
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400624 /* new item or its part falls to R[0] */
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400625
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400626 /* part of new item falls into R[0] */
627 if (tb->item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1) {
628 loff_t old_key_comp, old_len, r_zeroes_number;
629 const char *r_body;
630 int version, shift;
631 loff_t offset;
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400632
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400633 leaf_shift_right(tb, tb->rnum[0] - 1, -1);
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400634
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400635 version = ih_version(ih);
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400636
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400637 /* Remember key component and item length */
638 old_key_comp = le_ih_k_offset(ih);
639 old_len = ih_item_len(ih);
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400640
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400641 /*
642 * Calculate key component and item length to insert
643 * into R[0]
644 */
645 shift = 0;
646 if (is_indirect_le_ih(ih))
647 shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT;
648 offset = le_ih_k_offset(ih) + ((old_len - tb->rbytes) << shift);
649 set_le_ih_k_offset(ih, offset);
650 put_ih_item_len(ih, tb->rbytes);
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400651
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400652 /* Insert part of the item into R[0] */
653 buffer_info_init_right(tb, &bi);
654 if ((old_len - tb->rbytes) > tb->zeroes_num) {
655 r_zeroes_number = 0;
656 r_body = body + (old_len - tb->rbytes) - tb->zeroes_num;
657 } else {
658 r_body = body;
659 r_zeroes_number = tb->zeroes_num -
660 (old_len - tb->rbytes);
661 tb->zeroes_num -= r_zeroes_number;
662 }
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400663
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400664 leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeroes_number);
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400665
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400666 /* Replace right delimiting key by first key in R[0] */
667 replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400668
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400669 /*
670 * Calculate key component and item length to
671 * insert into S[0]
672 */
673 set_le_ih_k_offset(ih, old_key_comp);
674 put_ih_item_len(ih, old_len - tb->rbytes);
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400675
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400676 tb->insert_size[0] -= tb->rbytes;
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400677
Jeff Mahoney8dbf0d82014-04-23 10:00:58 -0400678 } else {
679 /* whole new item falls into R[0] */
680
681 /* Shift rnum[0]-1 items to R[0] */
682 ret = leaf_shift_right(tb, tb->rnum[0] - 1, tb->rbytes);
683
684 /* Insert new item into R[0] */
685 buffer_info_init_right(tb, &bi);
686 leaf_insert_into_buf(&bi, tb->item_pos - n + tb->rnum[0] - 1,
687 ih, body, tb->zeroes_num);
688
689 if (tb->item_pos - n + tb->rnum[0] - 1 == 0)
690 replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
691
692 tb->zeroes_num = tb->insert_size[0] = 0;
693 }
Jeff Mahoneye80ef3d2014-04-23 10:00:49 -0400694}
695
Jeff Mahoney2369ecd2014-04-23 10:00:59 -0400696
697static void balance_leaf_paste_right_shift_dirent(struct tree_balance *tb,
698 struct item_head *ih, const char *body)
699{
700 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
701 struct buffer_info bi;
702 int entry_count;
703
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400704 RFALSE(tb->zeroes_num,
Jeff Mahoney2369ecd2014-04-23 10:00:59 -0400705 "PAP-12145: invalid parameter in case of a directory");
706 entry_count = ih_entry_count(item_head(tbS0, tb->item_pos));
707
708 /* new directory entry falls into R[0] */
709 if (entry_count - tb->rbytes < tb->pos_in_item) {
710 int paste_entry_position;
711
712 RFALSE(tb->rbytes - 1 >= entry_count || !tb->insert_size[0],
713 "PAP-12150: no enough of entries to shift to R[0]: "
714 "rbytes=%d, entry_count=%d", tb->rbytes, entry_count);
715
716 /*
717 * Shift rnum[0]-1 items in whole.
718 * Shift rbytes-1 directory entries from directory
719 * item number rnum[0]
720 */
721 leaf_shift_right(tb, tb->rnum[0], tb->rbytes - 1);
722
723 /* Paste given directory entry to directory item */
724 paste_entry_position = tb->pos_in_item - entry_count +
725 tb->rbytes - 1;
726 buffer_info_init_right(tb, &bi);
727 leaf_paste_in_buffer(&bi, 0, paste_entry_position,
728 tb->insert_size[0], body, tb->zeroes_num);
729
730 /* paste entry */
731 leaf_paste_entries(&bi, 0, paste_entry_position, 1,
732 (struct reiserfs_de_head *) body,
733 body + DEH_SIZE, tb->insert_size[0]);
734
735 /* change delimiting keys */
736 if (paste_entry_position == 0)
737 replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
738
739 tb->insert_size[0] = 0;
740 tb->pos_in_item++;
741 } else {
742 /* new directory entry doesn't fall into R[0] */
743 leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
744 }
745}
746
747static void balance_leaf_paste_right_shift(struct tree_balance *tb,
748 struct item_head *ih, const char *body)
749{
750 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
751 int n_shift, n_rem, r_zeroes_number, version;
752 unsigned long temp_rem;
753 const char *r_body;
754 struct buffer_info bi;
755
756 /* we append to directory item */
757 if (is_direntry_le_ih(item_head(tbS0, tb->item_pos))) {
758 balance_leaf_paste_right_shift_dirent(tb, ih, body);
759 return;
760 }
761
762 /* regular object */
763
764 /*
765 * Calculate number of bytes which must be shifted
766 * from appended item
767 */
768 n_shift = tb->rbytes - tb->insert_size[0];
769 if (n_shift < 0)
770 n_shift = 0;
771
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400772 RFALSE(tb->pos_in_item != ih_item_len(item_head(tbS0, tb->item_pos)),
Jeff Mahoney2369ecd2014-04-23 10:00:59 -0400773 "PAP-12155: invalid position to paste. ih_item_len=%d, "
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400774 "pos_in_item=%d", tb->pos_in_item,
775 ih_item_len(item_head(tbS0, tb->item_pos)));
Jeff Mahoney2369ecd2014-04-23 10:00:59 -0400776
777 leaf_shift_right(tb, tb->rnum[0], n_shift);
778
779 /*
780 * Calculate number of bytes which must remain in body
781 * after appending to R[0]
782 */
783 n_rem = tb->insert_size[0] - tb->rbytes;
784 if (n_rem < 0)
785 n_rem = 0;
786
787 temp_rem = n_rem;
788
789 version = ih_version(item_head(tb->R[0], 0));
790
791 if (is_indirect_le_key(version, leaf_key(tb->R[0], 0))) {
792 int shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT;
793 temp_rem = n_rem << shift;
794 }
795
796 add_le_key_k_offset(version, leaf_key(tb->R[0], 0), temp_rem);
797 add_le_key_k_offset(version, internal_key(tb->CFR[0], tb->rkey[0]),
798 temp_rem);
799
800 do_balance_mark_internal_dirty(tb, tb->CFR[0], 0);
801
802 /* Append part of body into R[0] */
803 buffer_info_init_right(tb, &bi);
804 if (n_rem > tb->zeroes_num) {
805 r_zeroes_number = 0;
806 r_body = body + n_rem - tb->zeroes_num;
807 } else {
808 r_body = body;
809 r_zeroes_number = tb->zeroes_num - n_rem;
810 tb->zeroes_num -= r_zeroes_number;
811 }
812
813 leaf_paste_in_buffer(&bi, 0, n_shift, tb->insert_size[0] - n_rem,
814 r_body, r_zeroes_number);
815
816 if (is_indirect_le_ih(item_head(tb->R[0], 0)))
817 set_ih_free_space(item_head(tb->R[0], 0), 0);
818
819 tb->insert_size[0] = n_rem;
820 if (!n_rem)
821 tb->pos_in_item++;
822}
823
824static void balance_leaf_paste_right_whole(struct tree_balance *tb,
825 struct item_head *ih, const char *body)
826{
827 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
828 int n = B_NR_ITEMS(tbS0);
829 struct item_head *pasted;
830 struct buffer_info bi;
831
832 buffer_info_init_right(tb, &bi);
833 leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
834
835 /* append item in R[0] */
836 if (tb->pos_in_item >= 0) {
837 buffer_info_init_right(tb, &bi);
838 leaf_paste_in_buffer(&bi, tb->item_pos - n + tb->rnum[0],
839 tb->pos_in_item, tb->insert_size[0], body,
840 tb->zeroes_num);
841 }
842
843 /* paste new entry, if item is directory item */
844 pasted = item_head(tb->R[0], tb->item_pos - n + tb->rnum[0]);
845 if (is_direntry_le_ih(pasted) && tb->pos_in_item >= 0) {
846 leaf_paste_entries(&bi, tb->item_pos - n + tb->rnum[0],
847 tb->pos_in_item, 1,
848 (struct reiserfs_de_head *)body,
849 body + DEH_SIZE, tb->insert_size[0]);
850
851 if (!tb->pos_in_item) {
852
853 RFALSE(tb->item_pos - n + tb->rnum[0],
854 "PAP-12165: directory item must be first "
855 "item of node when pasting is in 0th position");
856
857 /* update delimiting keys */
858 replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
859 }
860 }
861
862 if (is_indirect_le_ih(pasted))
863 set_ih_free_space(pasted, 0);
864 tb->zeroes_num = tb->insert_size[0] = 0;
865}
866
Jeff Mahoney3f0eb272014-04-23 10:00:50 -0400867static void balance_leaf_paste_right(struct tree_balance *tb,
868 struct item_head *ih, const char *body)
Jeff Mahoneycf22df12014-04-23 10:00:48 -0400869{
870 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
Jeff Mahoney3f0eb272014-04-23 10:00:50 -0400871 int n = B_NR_ITEMS(tbS0);
Jeff Mahoneycf22df12014-04-23 10:00:48 -0400872
Jeff Mahoney2369ecd2014-04-23 10:00:59 -0400873 /* new item doesn't fall into R[0] */
874 if (n - tb->rnum[0] > tb->item_pos) {
875 leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
876 return;
877 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878
Jeff Mahoney2369ecd2014-04-23 10:00:59 -0400879 /* pasted item or part of it falls to R[0] */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -0700880
Jeff Mahoney2369ecd2014-04-23 10:00:59 -0400881 if (tb->item_pos == n - tb->rnum[0] && tb->rbytes != -1)
882 /* we must shift the part of the appended item */
883 balance_leaf_paste_right_shift(tb, ih, body);
884 else
885 /* pasted item in whole falls into R[0] */
886 balance_leaf_paste_right_whole(tb, ih, body);
Jeff Mahoney3f0eb272014-04-23 10:00:50 -0400887}
888
Jeff Mahoney0080e9f2014-04-23 10:00:55 -0400889/* shift rnum[0] items from S[0] to the right neighbor R[0] */
890static void balance_leaf_right(struct tree_balance *tb, struct item_head *ih,
891 const char *body, int flag)
892{
893 if (tb->rnum[0] <= 0)
894 return;
895
896 BUG_ON(flag != M_INSERT && flag != M_PASTE);
897
898 if (flag == M_INSERT)
899 balance_leaf_insert_right(tb, ih, body);
900 else /* M_PASTE */
901 balance_leaf_paste_right(tb, ih, body);
Jeff Mahoney0080e9f2014-04-23 10:00:55 -0400902}
903
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400904static void balance_leaf_new_nodes_insert(struct tree_balance *tb,
905 struct item_head *ih,
906 const char *body,
907 struct item_head *insert_key,
908 struct buffer_head **insert_ptr,
909 int i)
910{
911 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
912 int n = B_NR_ITEMS(tbS0);
913 struct buffer_info bi;
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400914 int shift;
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400915
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400916 /* new item or it part don't falls into S_new[i] */
917 if (n - tb->snum[i] >= tb->item_pos) {
918 leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
919 tb->snum[i], tb->sbytes[i], tb->S_new[i]);
920 return;
921 }
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400922
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400923 /* new item or it's part falls to first new node S_new[i] */
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400924
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400925 /* part of new item falls into S_new[i] */
926 if (tb->item_pos == n - tb->snum[i] + 1 && tb->sbytes[i] != -1) {
927 int old_key_comp, old_len, r_zeroes_number;
928 const char *r_body;
929 int version;
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400930
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400931 /* Move snum[i]-1 items from S[0] to S_new[i] */
932 leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i] - 1, -1,
933 tb->S_new[i]);
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400934
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400935 /* Remember key component and item length */
936 version = ih_version(ih);
937 old_key_comp = le_ih_k_offset(ih);
938 old_len = ih_item_len(ih);
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400939
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400940 /*
941 * Calculate key component and item length to insert
942 * into S_new[i]
943 */
944 shift = 0;
945 if (is_indirect_le_ih(ih))
946 shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT;
947 set_le_ih_k_offset(ih,
948 le_ih_k_offset(ih) +
949 ((old_len - tb->sbytes[i]) << shift));
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400950
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400951 put_ih_item_len(ih, tb->sbytes[i]);
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400952
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400953 /* Insert part of the item into S_new[i] before 0-th item */
954 buffer_info_init_bh(tb, &bi, tb->S_new[i]);
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400955
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400956 if ((old_len - tb->sbytes[i]) > tb->zeroes_num) {
957 r_zeroes_number = 0;
958 r_body = body + (old_len - tb->sbytes[i]) -
959 tb->zeroes_num;
960 } else {
961 r_body = body;
962 r_zeroes_number = tb->zeroes_num - (old_len -
963 tb->sbytes[i]);
964 tb->zeroes_num -= r_zeroes_number;
965 }
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400966
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400967 leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeroes_number);
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400968
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400969 /*
970 * Calculate key component and item length to
971 * insert into S[i]
972 */
973 set_le_ih_k_offset(ih, old_key_comp);
974 put_ih_item_len(ih, old_len - tb->sbytes[i]);
975 tb->insert_size[0] -= tb->sbytes[i];
976 } else {
977 /* whole new item falls into S_new[i] */
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400978
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400979 /*
980 * Shift snum[0] - 1 items to S_new[i]
981 * (sbytes[i] of split item)
982 */
983 leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
984 tb->snum[i] - 1, tb->sbytes[i], tb->S_new[i]);
985
986 /* Insert new item into S_new[i] */
987 buffer_info_init_bh(tb, &bi, tb->S_new[i]);
988 leaf_insert_into_buf(&bi, tb->item_pos - n + tb->snum[i] - 1,
989 ih, body, tb->zeroes_num);
990
991 tb->zeroes_num = tb->insert_size[0] = 0;
992 }
Jeff Mahoney65ab18c2014-04-23 10:00:51 -0400993}
994
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -0400995/* we append to directory item */
996static void balance_leaf_new_nodes_paste_dirent(struct tree_balance *tb,
997 struct item_head *ih,
998 const char *body,
999 struct item_head *insert_key,
1000 struct buffer_head **insert_ptr,
1001 int i)
1002{
1003 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
1004 struct item_head *aux_ih = item_head(tbS0, tb->item_pos);
1005 int entry_count = ih_entry_count(aux_ih);
1006 struct buffer_info bi;
1007
1008 if (entry_count - tb->sbytes[i] < tb->pos_in_item &&
1009 tb->pos_in_item <= entry_count) {
1010 /* new directory entry falls into S_new[i] */
1011
1012 RFALSE(!tb->insert_size[0],
1013 "PAP-12215: insert_size is already 0");
1014 RFALSE(tb->sbytes[i] - 1 >= entry_count,
1015 "PAP-12220: there are no so much entries (%d), only %d",
1016 tb->sbytes[i] - 1, entry_count);
1017
1018 /*
1019 * Shift snum[i]-1 items in whole.
1020 * Shift sbytes[i] directory entries
1021 * from directory item number snum[i]
1022 */
1023 leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i],
1024 tb->sbytes[i] - 1, tb->S_new[i]);
1025
1026 /*
1027 * Paste given directory entry to
1028 * directory item
1029 */
1030 buffer_info_init_bh(tb, &bi, tb->S_new[i]);
1031 leaf_paste_in_buffer(&bi, 0, tb->pos_in_item - entry_count +
1032 tb->sbytes[i] - 1, tb->insert_size[0],
1033 body, tb->zeroes_num);
1034
1035 /* paste new directory entry */
1036 leaf_paste_entries(&bi, 0, tb->pos_in_item - entry_count +
1037 tb->sbytes[i] - 1, 1,
1038 (struct reiserfs_de_head *) body,
1039 body + DEH_SIZE, tb->insert_size[0]);
1040
1041 tb->insert_size[0] = 0;
1042 tb->pos_in_item++;
1043 } else {
1044 /* new directory entry doesn't fall into S_new[i] */
1045 leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i],
1046 tb->sbytes[i], tb->S_new[i]);
1047 }
1048
1049}
1050
1051static void balance_leaf_new_nodes_paste_shift(struct tree_balance *tb,
1052 struct item_head *ih,
1053 const char *body,
1054 struct item_head *insert_key,
1055 struct buffer_head **insert_ptr,
1056 int i)
1057{
1058 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
1059 struct item_head *aux_ih = item_head(tbS0, tb->item_pos);
1060 int n_shift, n_rem, r_zeroes_number, shift;
1061 const char *r_body;
1062 struct item_head *tmp;
1063 struct buffer_info bi;
1064
1065 RFALSE(ih, "PAP-12210: ih must be 0");
1066
1067 if (is_direntry_le_ih(aux_ih)) {
1068 balance_leaf_new_nodes_paste_dirent(tb, ih, body, insert_key,
1069 insert_ptr, i);
1070 return;
1071 }
1072
1073 /* regular object */
1074
1075
1076 RFALSE(tb->pos_in_item != ih_item_len(item_head(tbS0, tb->item_pos)) ||
1077 tb->insert_size[0] <= 0,
1078 "PAP-12225: item too short or insert_size <= 0");
1079
1080 /*
1081 * Calculate number of bytes which must be shifted from appended item
1082 */
1083 n_shift = tb->sbytes[i] - tb->insert_size[0];
1084 if (n_shift < 0)
1085 n_shift = 0;
1086 leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i], n_shift,
1087 tb->S_new[i]);
1088
1089 /*
1090 * Calculate number of bytes which must remain in body after
1091 * append to S_new[i]
1092 */
1093 n_rem = tb->insert_size[0] - tb->sbytes[i];
1094 if (n_rem < 0)
1095 n_rem = 0;
1096
1097 /* Append part of body into S_new[0] */
1098 buffer_info_init_bh(tb, &bi, tb->S_new[i]);
1099 if (n_rem > tb->zeroes_num) {
1100 r_zeroes_number = 0;
1101 r_body = body + n_rem - tb->zeroes_num;
1102 } else {
1103 r_body = body;
1104 r_zeroes_number = tb->zeroes_num - n_rem;
1105 tb->zeroes_num -= r_zeroes_number;
1106 }
1107
1108 leaf_paste_in_buffer(&bi, 0, n_shift, tb->insert_size[0] - n_rem,
1109 r_body, r_zeroes_number);
1110
1111 tmp = item_head(tb->S_new[i], 0);
1112 shift = 0;
1113 if (is_indirect_le_ih(tmp)) {
1114 set_ih_free_space(tmp, 0);
1115 shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT;
1116 }
1117 add_le_ih_k_offset(tmp, n_rem << shift);
1118
1119 tb->insert_size[0] = n_rem;
1120 if (!n_rem)
1121 tb->pos_in_item++;
1122}
1123
1124static void balance_leaf_new_nodes_paste_whole(struct tree_balance *tb,
1125 struct item_head *ih,
1126 const char *body,
1127 struct item_head *insert_key,
1128 struct buffer_head **insert_ptr,
1129 int i)
1130
1131{
1132 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
1133 int n = B_NR_ITEMS(tbS0);
1134 int leaf_mi;
1135 struct item_head *pasted;
1136 struct buffer_info bi;
1137
1138#ifdef CONFIG_REISERFS_CHECK
1139 struct item_head *ih_check = item_head(tbS0, tb->item_pos);
1140
1141 if (!is_direntry_le_ih(ih_check) &&
1142 (tb->pos_in_item != ih_item_len(ih_check) ||
1143 tb->insert_size[0] <= 0))
1144 reiserfs_panic(tb->tb_sb,
1145 "PAP-12235",
1146 "pos_in_item must be equal to ih_item_len");
1147#endif
1148
1149 leaf_mi = leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i],
1150 tb->sbytes[i], tb->S_new[i]);
1151
1152 RFALSE(leaf_mi,
1153 "PAP-12240: unexpected value returned by leaf_move_items (%d)",
1154 leaf_mi);
1155
1156 /* paste into item */
1157 buffer_info_init_bh(tb, &bi, tb->S_new[i]);
1158 leaf_paste_in_buffer(&bi, tb->item_pos - n + tb->snum[i],
1159 tb->pos_in_item, tb->insert_size[0],
1160 body, tb->zeroes_num);
1161
1162 pasted = item_head(tb->S_new[i], tb->item_pos - n +
1163 tb->snum[i]);
1164 if (is_direntry_le_ih(pasted))
1165 leaf_paste_entries(&bi, tb->item_pos - n + tb->snum[i],
1166 tb->pos_in_item, 1,
1167 (struct reiserfs_de_head *)body,
1168 body + DEH_SIZE, tb->insert_size[0]);
1169
1170 /* if we paste to indirect item update ih_free_space */
1171 if (is_indirect_le_ih(pasted))
1172 set_ih_free_space(pasted, 0);
1173
1174 tb->zeroes_num = tb->insert_size[0] = 0;
1175
1176}
Jeff Mahoney9d496552014-04-23 10:00:52 -04001177static void balance_leaf_new_nodes_paste(struct tree_balance *tb,
1178 struct item_head *ih,
1179 const char *body,
1180 struct item_head *insert_key,
1181 struct buffer_head **insert_ptr,
1182 int i)
1183{
1184 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
1185 int n = B_NR_ITEMS(tbS0);
Jeff Mahoney9d496552014-04-23 10:00:52 -04001186
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -04001187 /* pasted item doesn't fall into S_new[i] */
1188 if (n - tb->snum[i] > tb->item_pos) {
1189 leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
1190 tb->snum[i], tb->sbytes[i], tb->S_new[i]);
1191 return;
1192 }
Jeff Mahoney9d496552014-04-23 10:00:52 -04001193
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -04001194 /* pasted item or part if it falls to S_new[i] */
Jeff Mahoney9d496552014-04-23 10:00:52 -04001195
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -04001196 if (tb->item_pos == n - tb->snum[i] && tb->sbytes[i] != -1)
1197 /* we must shift part of the appended item */
1198 balance_leaf_new_nodes_paste_shift(tb, ih, body, insert_key,
1199 insert_ptr, i);
1200 else
1201 /* item falls wholly into S_new[i] */
1202 balance_leaf_new_nodes_paste_whole(tb, ih, body, insert_key,
1203 insert_ptr, i);
Jeff Mahoney9d496552014-04-23 10:00:52 -04001204}
1205
Jeff Mahoney0080e9f2014-04-23 10:00:55 -04001206/* Fill new nodes that appear in place of S[0] */
1207static void balance_leaf_new_nodes(struct tree_balance *tb,
1208 struct item_head *ih,
1209 const char *body,
1210 struct item_head *insert_key,
1211 struct buffer_head **insert_ptr,
1212 int flag)
1213{
1214 int i;
1215 for (i = tb->blknum[0] - 2; i >= 0; i--) {
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -04001216 BUG_ON(flag != M_INSERT && flag != M_PASTE);
Jeff Mahoney0080e9f2014-04-23 10:00:55 -04001217
1218 RFALSE(!tb->snum[i],
1219 "PAP-12200: snum[%d] == %d. Must be > 0", i,
1220 tb->snum[i]);
1221
1222 /* here we shift from S to S_new nodes */
1223
1224 tb->S_new[i] = get_FEB(tb);
1225
1226 /* initialized block type and tree level */
1227 set_blkh_level(B_BLK_HEAD(tb->S_new[i]), DISK_LEAF_NODE_LEVEL);
1228
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -04001229 if (flag == M_INSERT)
Jeff Mahoney0080e9f2014-04-23 10:00:55 -04001230 balance_leaf_new_nodes_insert(tb, ih, body, insert_key,
1231 insert_ptr, i);
Jeff Mahoneyb54b8c92014-04-23 10:01:00 -04001232 else /* M_PASTE */
Jeff Mahoney0080e9f2014-04-23 10:00:55 -04001233 balance_leaf_new_nodes_paste(tb, ih, body, insert_key,
1234 insert_ptr, i);
Jeff Mahoney0080e9f2014-04-23 10:00:55 -04001235
1236 memcpy(insert_key + i, leaf_key(tb->S_new[i], 0), KEY_SIZE);
1237 insert_ptr[i] = tb->S_new[i];
1238
1239 RFALSE(!buffer_journaled(tb->S_new[i])
1240 || buffer_journal_dirty(tb->S_new[i])
1241 || buffer_dirty(tb->S_new[i]),
1242 "PAP-12247: S_new[%d] : (%b)",
1243 i, format_bh(tb->S_new[i]));
1244 }
1245}
1246
Jeff Mahoney8c480ea2014-04-23 10:00:53 -04001247static void balance_leaf_finish_node_insert(struct tree_balance *tb,
1248 struct item_head *ih,
1249 const char *body)
1250{
1251 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
1252 struct buffer_info bi;
Jeff Mahoney441378c2014-04-23 10:01:01 -04001253 buffer_info_init_tbS0(tb, &bi);
1254 leaf_insert_into_buf(&bi, tb->item_pos, ih, body, tb->zeroes_num);
Jeff Mahoney8c480ea2014-04-23 10:00:53 -04001255
Jeff Mahoney441378c2014-04-23 10:01:01 -04001256 /* If we insert the first key change the delimiting key */
1257 if (tb->item_pos == 0) {
1258 if (tb->CFL[0]) /* can be 0 in reiserfsck */
1259 replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0);
1260
1261 }
1262}
1263
1264static void balance_leaf_finish_node_paste_dirent(struct tree_balance *tb,
1265 struct item_head *ih,
1266 const char *body)
1267{
1268 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
1269 struct item_head *pasted = item_head(tbS0, tb->item_pos);
1270 struct buffer_info bi;
1271
1272 if (tb->pos_in_item >= 0 && tb->pos_in_item <= ih_entry_count(pasted)) {
1273 RFALSE(!tb->insert_size[0],
1274 "PAP-12260: insert_size is 0 already");
1275
1276 /* prepare space */
1277 buffer_info_init_tbS0(tb, &bi);
1278 leaf_paste_in_buffer(&bi, tb->item_pos, tb->pos_in_item,
1279 tb->insert_size[0], body, tb->zeroes_num);
1280
1281 /* paste entry */
1282 leaf_paste_entries(&bi, tb->item_pos, tb->pos_in_item, 1,
1283 (struct reiserfs_de_head *)body,
1284 body + DEH_SIZE, tb->insert_size[0]);
1285
1286 if (!tb->item_pos && !tb->pos_in_item) {
1287 RFALSE(!tb->CFL[0] || !tb->L[0],
1288 "PAP-12270: CFL[0]/L[0] must be specified");
1289 if (tb->CFL[0])
1290 replace_key(tb, tb->CFL[0], tb->lkey[0],
1291 tbS0, 0);
1292 }
1293
1294 tb->insert_size[0] = 0;
1295 }
Jeff Mahoney8c480ea2014-04-23 10:00:53 -04001296}
1297
Jeff Mahoney7f447ba2014-04-23 10:00:54 -04001298static void balance_leaf_finish_node_paste(struct tree_balance *tb,
1299 struct item_head *ih,
1300 const char *body)
1301{
1302 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
1303 struct buffer_info bi;
Jeff Mahoney441378c2014-04-23 10:01:01 -04001304 struct item_head *pasted = item_head(tbS0, tb->item_pos);
Jeff Mahoney7f447ba2014-04-23 10:00:54 -04001305
Jeff Mahoney441378c2014-04-23 10:01:01 -04001306 /* when directory, may be new entry already pasted */
1307 if (is_direntry_le_ih(pasted)) {
1308 balance_leaf_finish_node_paste_dirent(tb, ih, body);
1309 return;
1310 }
Jeff Mahoney7f447ba2014-04-23 10:00:54 -04001311
Jeff Mahoney441378c2014-04-23 10:01:01 -04001312 /* regular object */
Jeff Mahoney7f447ba2014-04-23 10:00:54 -04001313
Jeff Mahoney441378c2014-04-23 10:01:01 -04001314 if (tb->pos_in_item == ih_item_len(pasted)) {
1315 RFALSE(tb->insert_size[0] <= 0,
1316 "PAP-12275: insert size must not be %d",
1317 tb->insert_size[0]);
1318 buffer_info_init_tbS0(tb, &bi);
1319 leaf_paste_in_buffer(&bi, tb->item_pos,
1320 tb->pos_in_item, tb->insert_size[0], body,
1321 tb->zeroes_num);
Jeff Mahoney7f447ba2014-04-23 10:00:54 -04001322
Jeff Mahoney441378c2014-04-23 10:01:01 -04001323 if (is_indirect_le_ih(pasted))
1324 set_ih_free_space(pasted, 0);
Jeff Mahoney7f447ba2014-04-23 10:00:54 -04001325
Jeff Mahoney441378c2014-04-23 10:01:01 -04001326 tb->insert_size[0] = 0;
1327 }
Jeff Mahoney7f447ba2014-04-23 10:00:54 -04001328#ifdef CONFIG_REISERFS_CHECK
Jeff Mahoney441378c2014-04-23 10:01:01 -04001329 else if (tb->insert_size[0]) {
1330 print_cur_tb("12285");
1331 reiserfs_panic(tb->tb_sb, "PAP-12285",
1332 "insert_size must be 0 (%d)", tb->insert_size[0]);
1333 }
1334#endif
Jeff Mahoney7f447ba2014-04-23 10:00:54 -04001335}
1336
Jeff Mahoney0080e9f2014-04-23 10:00:55 -04001337/*
1338 * if the affected item was not wholly shifted then we
1339 * perform all necessary operations on that part or whole
1340 * of the affected item which remains in S
1341 */
1342static void balance_leaf_finish_node(struct tree_balance *tb,
1343 struct item_head *ih,
1344 const char *body, int flag)
1345{
1346 /* if we must insert or append into buffer S[0] */
1347 if (0 <= tb->item_pos && tb->item_pos < tb->s0num) {
1348 if (flag == M_INSERT)
1349 balance_leaf_finish_node_insert(tb, ih, body);
1350 else /* M_PASTE */
1351 balance_leaf_finish_node_paste(tb, ih, body);
1352 }
1353}
1354
Jeff Mahoney3f0eb272014-04-23 10:00:50 -04001355/**
1356 * balance_leaf - reiserfs tree balancing algorithm
1357 * @tb: tree balance state
1358 * @ih: item header of inserted item (little endian)
1359 * @body: body of inserted item or bytes to paste
1360 * @flag: i - insert, d - delete, c - cut, p - paste (see do_balance)
1361 * passed back:
1362 * @insert_key: key to insert new nodes
1363 * @insert_ptr: array of nodes to insert at the next level
1364 *
1365 * In our processing of one level we sometimes determine what must be
1366 * inserted into the next higher level. This insertion consists of a
1367 * key or two keys and their corresponding pointers.
1368 */
1369static int balance_leaf(struct tree_balance *tb, struct item_head *ih,
1370 const char *body, int flag,
1371 struct item_head *insert_key,
1372 struct buffer_head **insert_ptr)
1373{
1374 struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
Jeff Mahoney3f0eb272014-04-23 10:00:50 -04001375
1376 PROC_INFO_INC(tb->tb_sb, balance_at[0]);
1377
1378 /* Make balance in case insert_size[0] < 0 */
1379 if (tb->insert_size[0] < 0)
1380 return balance_leaf_when_delete(tb, flag);
1381
1382 tb->item_pos = PATH_LAST_POSITION(tb->tb_path),
1383 tb->pos_in_item = tb->tb_path->pos_in_item,
1384 tb->zeroes_num = 0;
1385 if (flag == M_INSERT && !body)
1386 tb->zeroes_num = ih_item_len(ih);
1387
1388 /*
1389 * for indirect item pos_in_item is measured in unformatted node
1390 * pointers. Recalculate to bytes
1391 */
1392 if (flag != M_INSERT
1393 && is_indirect_le_ih(item_head(tbS0, tb->item_pos)))
1394 tb->pos_in_item *= UNFM_P_SIZE;
1395
Jeff Mahoney0080e9f2014-04-23 10:00:55 -04001396 balance_leaf_left(tb, ih, body, flag);
Jeff Mahoney3f0eb272014-04-23 10:00:50 -04001397
1398 /* tb->lnum[0] > 0 */
1399 /* Calculate new item position */
1400 tb->item_pos -= (tb->lnum[0] - ((tb->lbytes != -1) ? 1 : 0));
1401
Jeff Mahoney0080e9f2014-04-23 10:00:55 -04001402 balance_leaf_right(tb, ih, body, flag);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001403
1404 /* tb->rnum[0] > 0 */
1405 RFALSE(tb->blknum[0] > 3,
Dave Jones416e2ab2014-02-17 16:21:24 -05001406 "PAP-12180: blknum can not be %d. It must be <= 3", tb->blknum[0]);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001407 RFALSE(tb->blknum[0] < 0,
Dave Jones416e2ab2014-02-17 16:21:24 -05001408 "PAP-12185: blknum can not be %d. It must be >= 0", tb->blknum[0]);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001409
Jeff Mahoney97fd4b92014-04-23 10:00:45 -04001410 /*
1411 * if while adding to a node we discover that it is possible to split
1412 * it in two, and merge the left part into the left neighbor and the
1413 * right part into the right neighbor, eliminating the node
1414 */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001415 if (tb->blknum[0] == 0) { /* node S[0] is empty now */
1416
1417 RFALSE(!tb->lnum[0] || !tb->rnum[0],
1418 "PAP-12190: lnum and rnum must not be zero");
Jeff Mahoney97fd4b92014-04-23 10:00:45 -04001419 /*
1420 * if insertion was done before 0-th position in R[0], right
1421 * delimiting key of the tb->L[0]'s and left delimiting key are
1422 * not set correctly
1423 */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001424 if (tb->CFL[0]) {
1425 if (!tb->CFR[0])
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001426 reiserfs_panic(tb->tb_sb, "vs-12195",
1427 "CFR not initialized");
Jeff Mahoney4cf5f7a2014-04-23 10:00:35 -04001428 copy_key(internal_key(tb->CFL[0], tb->lkey[0]),
1429 internal_key(tb->CFR[0], tb->rkey[0]));
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001430 do_balance_mark_internal_dirty(tb, tb->CFL[0], 0);
1431 }
1432
1433 reiserfs_invalidate_buffer(tb, tbS0);
1434 return 0;
1435 }
1436
Jeff Mahoney0080e9f2014-04-23 10:00:55 -04001437 balance_leaf_new_nodes(tb, ih, body, insert_key, insert_ptr, flag);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001438
Jeff Mahoney0080e9f2014-04-23 10:00:55 -04001439 balance_leaf_finish_node(tb, ih, body, flag);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001440
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001441#ifdef CONFIG_REISERFS_CHECK
1442 if (flag == M_PASTE && tb->insert_size[0]) {
1443 print_cur_tb("12290");
1444 reiserfs_panic(tb->tb_sb,
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001445 "PAP-12290", "insert_size is still not 0 (%d)",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001446 tb->insert_size[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 }
Jeff Mahoney97fd4b92014-04-23 10:00:45 -04001448#endif
1449
1450 /* Leaf level of the tree is balanced (end of balance_leaf) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 return 0;
Jeff Mahoney97fd4b92014-04-23 10:00:45 -04001452}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
1454/* Make empty node */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001455void make_empty_node(struct buffer_info *bi)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001457 struct block_head *blkh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001459 RFALSE(bi->bi_bh == NULL, "PAP-12295: pointer to the buffer is NULL");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001461 blkh = B_BLK_HEAD(bi->bi_bh);
1462 set_blkh_nr_item(blkh, 0);
1463 set_blkh_free_space(blkh, MAX_CHILD_SIZE(bi->bi_bh));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001465 if (bi->bi_parent)
1466 B_N_CHILD(bi->bi_parent, bi->bi_position)->dc_size = 0; /* Endian safe if 0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467}
1468
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469/* Get first empty buffer */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001470struct buffer_head *get_FEB(struct tree_balance *tb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001472 int i;
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001473 struct buffer_info bi;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001475 for (i = 0; i < MAX_FEB_SIZE; i++)
Al Viro9dce07f2008-03-29 03:07:28 +00001476 if (tb->FEB[i] != NULL)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001477 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001479 if (i == MAX_FEB_SIZE)
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001480 reiserfs_panic(tb->tb_sb, "vs-12300", "FEB list is empty");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481
Jeff Mahoneyfba4ebb2009-03-30 14:02:42 -04001482 buffer_info_init_bh(tb, &bi, tb->FEB[i]);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001483 make_empty_node(&bi);
Jeff Mahoneyfba4ebb2009-03-30 14:02:42 -04001484 set_buffer_uptodate(tb->FEB[i]);
1485 tb->used[i] = tb->FEB[i];
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001486 tb->FEB[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
Jeff Mahoneyfba4ebb2009-03-30 14:02:42 -04001488 return tb->used[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489}
1490
Jeff Mahoney098297b2014-04-23 10:00:36 -04001491/* This is now used because reiserfs_free_block has to be able to schedule. */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001492static void store_thrown(struct tree_balance *tb, struct buffer_head *bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001494 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001496 if (buffer_dirty(bh))
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001497 reiserfs_warning(tb->tb_sb, "reiserfs-12320",
1498 "called with dirty buffer");
Ahmed S. Darwish79a81ae2007-02-12 00:52:09 -08001499 for (i = 0; i < ARRAY_SIZE(tb->thrown); i++)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001500 if (!tb->thrown[i]) {
1501 tb->thrown[i] = bh;
1502 get_bh(bh); /* free_thrown puts this */
1503 return;
1504 }
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001505 reiserfs_warning(tb->tb_sb, "reiserfs-12321",
1506 "too many thrown buffers");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507}
1508
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001509static void free_thrown(struct tree_balance *tb)
1510{
1511 int i;
1512 b_blocknr_t blocknr;
Ahmed S. Darwish79a81ae2007-02-12 00:52:09 -08001513 for (i = 0; i < ARRAY_SIZE(tb->thrown); i++) {
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001514 if (tb->thrown[i]) {
1515 blocknr = tb->thrown[i]->b_blocknr;
1516 if (buffer_dirty(tb->thrown[i]))
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001517 reiserfs_warning(tb->tb_sb, "reiserfs-12322",
1518 "called with dirty buffer %d",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001519 blocknr);
1520 brelse(tb->thrown[i]); /* incremented in store_thrown */
1521 reiserfs_free_block(tb->transaction_handle, NULL,
1522 blocknr, 0);
1523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525}
1526
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001527void reiserfs_invalidate_buffer(struct tree_balance *tb, struct buffer_head *bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001529 struct block_head *blkh;
1530 blkh = B_BLK_HEAD(bh);
1531 set_blkh_level(blkh, FREE_LEVEL);
1532 set_blkh_nr_item(blkh, 0);
1533
1534 clear_buffer_dirty(bh);
1535 store_thrown(tb, bh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536}
1537
1538/* Replace n_dest'th key in buffer dest by n_src'th key of buffer src.*/
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001539void replace_key(struct tree_balance *tb, struct buffer_head *dest, int n_dest,
1540 struct buffer_head *src, int n_src)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541{
1542
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001543 RFALSE(dest == NULL || src == NULL,
1544 "vs-12305: source or destination buffer is 0 (src=%p, dest=%p)",
1545 src, dest);
1546 RFALSE(!B_IS_KEYS_LEVEL(dest),
1547 "vs-12310: invalid level (%z) for destination buffer. dest must be leaf",
1548 dest);
1549 RFALSE(n_dest < 0 || n_src < 0,
1550 "vs-12315: src(%d) or dest(%d) key number < 0", n_src, n_dest);
1551 RFALSE(n_dest >= B_NR_ITEMS(dest) || n_src >= B_NR_ITEMS(src),
1552 "vs-12320: src(%d(%d)) or dest(%d(%d)) key number is too big",
1553 n_src, B_NR_ITEMS(src), n_dest, B_NR_ITEMS(dest));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001555 if (B_IS_ITEMS_LEVEL(src))
1556 /* source buffer contains leaf node */
Jeff Mahoney4cf5f7a2014-04-23 10:00:35 -04001557 memcpy(internal_key(dest, n_dest), item_head(src, n_src),
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001558 KEY_SIZE);
1559 else
Jeff Mahoney4cf5f7a2014-04-23 10:00:35 -04001560 memcpy(internal_key(dest, n_dest), internal_key(src, n_src),
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001561 KEY_SIZE);
1562
1563 do_balance_mark_internal_dirty(tb, dest, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564}
1565
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001566int get_left_neighbor_position(struct tree_balance *tb, int h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001568 int Sh_position = PATH_H_POSITION(tb->tb_path, h + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
Al Viro9dce07f2008-03-29 03:07:28 +00001570 RFALSE(PATH_H_PPARENT(tb->tb_path, h) == NULL || tb->FL[h] == NULL,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001571 "vs-12325: FL[%d](%p) or F[%d](%p) does not exist",
1572 h, tb->FL[h], h, PATH_H_PPARENT(tb->tb_path, h));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001574 if (Sh_position == 0)
1575 return B_NR_ITEMS(tb->FL[h]);
1576 else
1577 return Sh_position - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578}
1579
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001580int get_right_neighbor_position(struct tree_balance *tb, int h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001582 int Sh_position = PATH_H_POSITION(tb->tb_path, h + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
Al Viro9dce07f2008-03-29 03:07:28 +00001584 RFALSE(PATH_H_PPARENT(tb->tb_path, h) == NULL || tb->FR[h] == NULL,
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001585 "vs-12330: F[%d](%p) or FR[%d](%p) does not exist",
1586 h, PATH_H_PPARENT(tb->tb_path, h), h, tb->FR[h]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001588 if (Sh_position == B_NR_ITEMS(PATH_H_PPARENT(tb->tb_path, h)))
1589 return 0;
1590 else
1591 return Sh_position + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592}
1593
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594#ifdef CONFIG_REISERFS_CHECK
1595
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001596int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value);
1597static void check_internal_node(struct super_block *s, struct buffer_head *bh,
1598 char *mes)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001600 struct disk_child *dc;
1601 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001603 RFALSE(!bh, "PAP-12336: bh == 0");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001605 if (!bh || !B_IS_IN_TREE(bh))
1606 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001608 RFALSE(!buffer_dirty(bh) &&
1609 !(buffer_journaled(bh) || buffer_journal_dirty(bh)),
1610 "PAP-12337: buffer (%b) must be dirty", bh);
1611 dc = B_N_CHILD(bh, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001613 for (i = 0; i <= B_NR_ITEMS(bh); i++, dc++) {
1614 if (!is_reusable(s, dc_block_number(dc), 1)) {
1615 print_cur_tb(mes);
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001616 reiserfs_panic(s, "PAP-12338",
1617 "invalid child pointer %y in %b",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001618 dc, bh);
1619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 }
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001621}
1622
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001623static int locked_or_not_in_tree(struct tree_balance *tb,
1624 struct buffer_head *bh, char *which)
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001625{
1626 if ((!buffer_journal_prepared(bh) && buffer_locked(bh)) ||
1627 !B_IS_IN_TREE(bh)) {
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001628 reiserfs_warning(tb->tb_sb, "vs-12339", "%s (%b)", which, bh);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001629 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 }
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001631 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632}
1633
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001634static int check_before_balancing(struct tree_balance *tb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001636 int retval = 0;
1637
Frederic Weisbecker08f14fc2009-05-16 19:10:38 +02001638 if (REISERFS_SB(tb->tb_sb)->cur_tb) {
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001639 reiserfs_panic(tb->tb_sb, "vs-12335", "suspect that schedule "
1640 "occurred based on cur_tb not being null at "
1641 "this point in code. do_balance cannot properly "
Frederic Weisbecker08f14fc2009-05-16 19:10:38 +02001642 "handle concurrent tree accesses on a same "
1643 "mount point.");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001644 }
1645
Jeff Mahoney098297b2014-04-23 10:00:36 -04001646 /*
1647 * double check that buffers that we will modify are unlocked.
1648 * (fix_nodes should already have prepped all of these for us).
1649 */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001650 if (tb->lnum[0]) {
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001651 retval |= locked_or_not_in_tree(tb, tb->L[0], "L[0]");
1652 retval |= locked_or_not_in_tree(tb, tb->FL[0], "FL[0]");
1653 retval |= locked_or_not_in_tree(tb, tb->CFL[0], "CFL[0]");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001654 check_leaf(tb->L[0]);
1655 }
1656 if (tb->rnum[0]) {
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001657 retval |= locked_or_not_in_tree(tb, tb->R[0], "R[0]");
1658 retval |= locked_or_not_in_tree(tb, tb->FR[0], "FR[0]");
1659 retval |= locked_or_not_in_tree(tb, tb->CFR[0], "CFR[0]");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001660 check_leaf(tb->R[0]);
1661 }
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001662 retval |= locked_or_not_in_tree(tb, PATH_PLAST_BUFFER(tb->tb_path),
1663 "S[0]");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001664 check_leaf(PATH_PLAST_BUFFER(tb->tb_path));
1665
1666 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667}
1668
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001669static void check_after_balance_leaf(struct tree_balance *tb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001671 if (tb->lnum[0]) {
1672 if (B_FREE_SPACE(tb->L[0]) !=
1673 MAX_CHILD_SIZE(tb->L[0]) -
1674 dc_size(B_N_CHILD
1675 (tb->FL[0], get_left_neighbor_position(tb, 0)))) {
1676 print_cur_tb("12221");
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001677 reiserfs_panic(tb->tb_sb, "PAP-12355",
1678 "shift to left was incorrect");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001679 }
1680 }
1681 if (tb->rnum[0]) {
1682 if (B_FREE_SPACE(tb->R[0]) !=
1683 MAX_CHILD_SIZE(tb->R[0]) -
1684 dc_size(B_N_CHILD
1685 (tb->FR[0], get_right_neighbor_position(tb, 0)))) {
1686 print_cur_tb("12222");
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001687 reiserfs_panic(tb->tb_sb, "PAP-12360",
1688 "shift to right was incorrect");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001689 }
1690 }
1691 if (PATH_H_PBUFFER(tb->tb_path, 1) &&
1692 (B_FREE_SPACE(PATH_H_PBUFFER(tb->tb_path, 0)) !=
1693 (MAX_CHILD_SIZE(PATH_H_PBUFFER(tb->tb_path, 0)) -
1694 dc_size(B_N_CHILD(PATH_H_PBUFFER(tb->tb_path, 1),
1695 PATH_H_POSITION(tb->tb_path, 1)))))) {
1696 int left = B_FREE_SPACE(PATH_H_PBUFFER(tb->tb_path, 0));
1697 int right = (MAX_CHILD_SIZE(PATH_H_PBUFFER(tb->tb_path, 0)) -
1698 dc_size(B_N_CHILD(PATH_H_PBUFFER(tb->tb_path, 1),
1699 PATH_H_POSITION(tb->tb_path,
1700 1))));
1701 print_cur_tb("12223");
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001702 reiserfs_warning(tb->tb_sb, "reiserfs-12363",
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001703 "B_FREE_SPACE (PATH_H_PBUFFER(tb->tb_path,0)) = %d; "
1704 "MAX_CHILD_SIZE (%d) - dc_size( %y, %d ) [%d] = %d",
1705 left,
1706 MAX_CHILD_SIZE(PATH_H_PBUFFER(tb->tb_path, 0)),
1707 PATH_H_PBUFFER(tb->tb_path, 1),
1708 PATH_H_POSITION(tb->tb_path, 1),
1709 dc_size(B_N_CHILD
1710 (PATH_H_PBUFFER(tb->tb_path, 1),
1711 PATH_H_POSITION(tb->tb_path, 1))),
1712 right);
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001713 reiserfs_panic(tb->tb_sb, "PAP-12365", "S is incorrect");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001714 }
1715}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001717static void check_leaf_level(struct tree_balance *tb)
1718{
1719 check_leaf(tb->L[0]);
1720 check_leaf(tb->R[0]);
1721 check_leaf(PATH_PLAST_BUFFER(tb->tb_path));
1722}
1723
1724static void check_internal_levels(struct tree_balance *tb)
1725{
1726 int h;
1727
1728 /* check all internal nodes */
1729 for (h = 1; tb->insert_size[h]; h++) {
1730 check_internal_node(tb->tb_sb, PATH_H_PBUFFER(tb->tb_path, h),
1731 "BAD BUFFER ON PATH");
1732 if (tb->lnum[h])
1733 check_internal_node(tb->tb_sb, tb->L[h], "BAD L");
1734 if (tb->rnum[h])
1735 check_internal_node(tb->tb_sb, tb->R[h], "BAD R");
1736 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737
1738}
1739
1740#endif
1741
Jeff Mahoney098297b2014-04-23 10:00:36 -04001742/*
1743 * Now we have all of the buffers that must be used in balancing of
1744 * the tree. We rely on the assumption that schedule() will not occur
1745 * while do_balance works. ( Only interrupt handlers are acceptable.)
1746 * We balance the tree according to the analysis made before this,
1747 * using buffers already obtained. For SMP support it will someday be
1748 * necessary to add ordered locking of tb.
1749 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750
Jeff Mahoney098297b2014-04-23 10:00:36 -04001751/*
1752 * Some interesting rules of balancing:
1753 * we delete a maximum of two nodes per level per balancing: we never
1754 * delete R, when we delete two of three nodes L, S, R then we move
1755 * them into R.
1756 *
1757 * we only delete L if we are deleting two nodes, if we delete only
1758 * one node we delete S
1759 *
1760 * if we shift leaves then we shift as much as we can: this is a
1761 * deliberate policy of extremism in node packing which results in
1762 * higher average utilization after repeated random balance operations
1763 * at the cost of more memory copies and more balancing as a result of
1764 * small insertions to full nodes.
1765 *
1766 * if we shift internal nodes we try to evenly balance the node
1767 * utilization, with consequent less balancing at the cost of lower
1768 * utilization.
1769 *
1770 * one could argue that the policy for directories in leaves should be
1771 * that of internal nodes, but we will wait until another day to
1772 * evaluate this.... It would be nice to someday measure and prove
1773 * these assumptions as to what is optimal....
1774 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001776static inline void do_balance_starts(struct tree_balance *tb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777{
Jeff Mahoney098297b2014-04-23 10:00:36 -04001778 /* use print_cur_tb() to see initial state of struct tree_balance */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001780 /* store_print_tb (tb); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001782 /* do not delete, just comment it out */
Jeff Mahoney098297b2014-04-23 10:00:36 -04001783 /*
1784 print_tb(flag, PATH_LAST_POSITION(tb->tb_path),
1785 tb->tb_path->pos_in_item, tb, "check");
1786 */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001787 RFALSE(check_before_balancing(tb), "PAP-12340: locked buffers in TB");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788#ifdef CONFIG_REISERFS_CHECK
Frederic Weisbecker08f14fc2009-05-16 19:10:38 +02001789 REISERFS_SB(tb->tb_sb)->cur_tb = tb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790#endif
1791}
1792
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001793static inline void do_balance_completed(struct tree_balance *tb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794{
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001795
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796#ifdef CONFIG_REISERFS_CHECK
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001797 check_leaf_level(tb);
1798 check_internal_levels(tb);
Frederic Weisbecker08f14fc2009-05-16 19:10:38 +02001799 REISERFS_SB(tb->tb_sb)->cur_tb = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800#endif
1801
Jeff Mahoney098297b2014-04-23 10:00:36 -04001802 /*
1803 * reiserfs_free_block is no longer schedule safe. So, we need to
1804 * put the buffers we want freed on the thrown list during do_balance,
1805 * and then free them now
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001806 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001808 REISERFS_SB(tb->tb_sb)->s_do_balance++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001810 /* release all nodes hold to perform the balancing */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 unfix_nodes(tb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001813 free_thrown(tb);
1814}
1815
Jeff Mahoney098297b2014-04-23 10:00:36 -04001816/*
1817 * do_balance - balance the tree
1818 *
1819 * @tb: tree_balance structure
1820 * @ih: item header of inserted item
1821 * @body: body of inserted item or bytes to paste
1822 * @flag: 'i' - insert, 'd' - delete, 'c' - cut, 'p' paste
1823 *
1824 * Cut means delete part of an item (includes removing an entry from a
1825 * directory).
1826 *
1827 * Delete means delete whole item.
1828 *
1829 * Insert means add a new item into the tree.
1830 *
1831 * Paste means to append to the end of an existing file or to
1832 * insert a directory entry.
1833 */
1834void do_balance(struct tree_balance *tb, struct item_head *ih,
1835 const char *body, int flag)
1836{
1837 int child_pos; /* position of a child node in its parent */
1838 int h; /* level of the tree being processed */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001839
Jeff Mahoney098297b2014-04-23 10:00:36 -04001840 /*
1841 * in our processing of one level we sometimes determine what
1842 * must be inserted into the next higher level. This insertion
1843 * consists of a key or two keys and their corresponding
1844 * pointers
1845 */
1846 struct item_head insert_key[2];
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001847
Jeff Mahoney098297b2014-04-23 10:00:36 -04001848 /* inserted node-ptrs for the next level */
1849 struct buffer_head *insert_ptr[2];
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001850
1851 tb->tb_mode = flag;
1852 tb->need_balance_dirty = 0;
1853
1854 if (FILESYSTEM_CHANGED_TB(tb)) {
Jeff Mahoneyc3a9c212009-03-30 14:02:25 -04001855 reiserfs_panic(tb->tb_sb, "clm-6000", "fs generation has "
1856 "changed");
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001857 }
1858 /* if we have no real work to do */
1859 if (!tb->insert_size[0]) {
Jeff Mahoney45b03d52009-03-30 14:02:21 -04001860 reiserfs_warning(tb->tb_sb, "PAP-12350",
1861 "insert_size == 0, mode == %c", flag);
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001862 unfix_nodes(tb);
1863 return;
1864 }
1865
Jeff Mahoneya228bf82014-04-23 10:00:42 -04001866 atomic_inc(&fs_generation(tb->tb_sb));
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001867 do_balance_starts(tb);
1868
Jeff Mahoney098297b2014-04-23 10:00:36 -04001869 /*
1870 * balance_leaf returns 0 except if combining L R and S into
1871 * one node. see balance_internal() for explanation of this
1872 * line of code.
1873 */
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001874 child_pos = PATH_H_B_ITEM_ORDER(tb->tb_path, 0) +
1875 balance_leaf(tb, ih, body, flag, insert_key, insert_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876
1877#ifdef CONFIG_REISERFS_CHECK
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001878 check_after_balance_leaf(tb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879#endif
1880
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001881 /* Balance internal level of the tree. */
1882 for (h = 1; h < MAX_HEIGHT && tb->insert_size[h]; h++)
1883 child_pos =
1884 balance_internal(tb, h, child_pos, insert_key, insert_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885
Linus Torvaldsbd4c6252005-07-12 20:21:28 -07001886 do_balance_completed(tb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887
1888}