diff options
| -rw-r--r-- | fs/reiserfs/do_balan.c | 361 |
1 files changed, 222 insertions, 139 deletions
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c index cca685daf26d..843c4023ad36 100644 --- a/fs/reiserfs/do_balan.c +++ b/fs/reiserfs/do_balan.c | |||
| @@ -355,164 +355,247 @@ static void balance_leaf_insert_left(struct tree_balance *tb, | |||
| 355 | } | 355 | } |
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | static void balance_leaf_paste_left(struct tree_balance *tb, | 358 | static void balance_leaf_paste_left_shift_dirent(struct tree_balance *tb, |
| 359 | struct item_head *ih, const char *body) | 359 | struct item_head *ih, |
| 360 | const char *body) | ||
| 360 | { | 361 | { |
| 361 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); | 362 | int n = B_NR_ITEMS(tb->L[0]); |
| 362 | int ret_val; | ||
| 363 | struct buffer_info bi; | 363 | struct buffer_info bi; |
| 364 | |||
| 365 | RFALSE(tb->zeroes_num, | ||
| 366 | "PAP-12090: invalid parameter in case of a directory"); | ||
| 367 | |||
| 368 | /* directory item */ | ||
| 369 | if (tb->lbytes > tb->pos_in_item) { | ||
| 370 | /* new directory entry falls into L[0] */ | ||
| 371 | struct item_head *pasted; | ||
| 372 | int ret, l_pos_in_item = tb->pos_in_item; | ||
| 373 | |||
| 374 | /* | ||
| 375 | * Shift lnum[0] - 1 items in whole. | ||
| 376 | * Shift lbytes - 1 entries from given directory item | ||
| 377 | */ | ||
| 378 | ret = leaf_shift_left(tb, tb->lnum[0], tb->lbytes - 1); | ||
| 379 | if (ret && !tb->item_pos) { | ||
| 380 | pasted = item_head(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1); | ||
| 381 | l_pos_in_item += ih_entry_count(pasted) - | ||
| 382 | (tb->lbytes - 1); | ||
| 383 | } | ||
| 384 | |||
| 385 | /* Append given directory entry to directory item */ | ||
| 386 | buffer_info_init_left(tb, &bi); | ||
| 387 | leaf_paste_in_buffer(&bi, n + tb->item_pos - ret, | ||
| 388 | l_pos_in_item, tb->insert_size[0], | ||
| 389 | body, tb->zeroes_num); | ||
| 390 | |||
| 391 | /* | ||
| 392 | * previous string prepared space for pasting new entry, | ||
| 393 | * following string pastes this entry | ||
| 394 | */ | ||
| 395 | |||
| 396 | /* | ||
| 397 | * when we have merge directory item, pos_in_item | ||
| 398 | * has been changed too | ||
| 399 | */ | ||
| 400 | |||
| 401 | /* paste new directory entry. 1 is entry number */ | ||
| 402 | leaf_paste_entries(&bi, n + tb->item_pos - ret, | ||
| 403 | l_pos_in_item, 1, | ||
| 404 | (struct reiserfs_de_head *) body, | ||
| 405 | body + DEH_SIZE, tb->insert_size[0]); | ||
| 406 | tb->insert_size[0] = 0; | ||
| 407 | } else { | ||
| 408 | /* new directory item doesn't fall into L[0] */ | ||
| 409 | /* | ||
| 410 | * Shift lnum[0]-1 items in whole. Shift lbytes | ||
| 411 | * directory entries from directory item number lnum[0] | ||
| 412 | */ | ||
| 413 | leaf_shift_left(tb, tb->lnum[0], tb->lbytes); | ||
| 414 | } | ||
| 415 | |||
| 416 | /* Calculate new position to append in item body */ | ||
| 417 | tb->pos_in_item -= tb->lbytes; | ||
| 418 | } | ||
| 419 | |||
| 420 | static void balance_leaf_paste_left_shift(struct tree_balance *tb, | ||
| 421 | struct item_head *ih, | ||
| 422 | const char *body) | ||
| 423 | { | ||
| 424 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); | ||
| 364 | int n = B_NR_ITEMS(tb->L[0]); | 425 | int n = B_NR_ITEMS(tb->L[0]); |
| 426 | struct buffer_info bi; | ||
| 365 | 427 | ||
| 366 | if (tb->item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) { | 428 | if (is_direntry_le_ih(item_head(tbS0, tb->item_pos))) { |
| 367 | /* we must shift the part of the appended item */ | 429 | balance_leaf_paste_left_shift_dirent(tb, ih, body); |
| 368 | if (is_direntry_le_ih(item_head(tbS0, tb->item_pos))) { | 430 | return; |
| 431 | } | ||
| 369 | 432 | ||
| 370 | RFALSE(tb->zeroes_num, | 433 | RFALSE(tb->lbytes <= 0, |
| 371 | "PAP-12090: invalid parameter in case of a directory"); | 434 | "PAP-12095: there is nothing to shift to L[0]. " |
| 372 | /* directory item */ | 435 | "lbytes=%d", tb->lbytes); |
| 373 | if (tb->lbytes > tb->pos_in_item) { | 436 | RFALSE(tb->pos_in_item != ih_item_len(item_head(tbS0, tb->item_pos)), |
| 374 | /* new directory entry falls into L[0] */ | 437 | "PAP-12100: incorrect position to paste: " |
| 375 | struct item_head *pasted; | 438 | "item_len=%d, pos_in_item=%d", |
| 376 | int l_pos_in_item = tb->pos_in_item; | 439 | ih_item_len(item_head(tbS0, tb->item_pos)), tb->pos_in_item); |
| 377 | |||
| 378 | /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 entries from given directory item */ | ||
| 379 | ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes-1); | ||
| 380 | if (ret_val && !tb->item_pos) { | ||
| 381 | pasted = item_head(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1); | ||
| 382 | l_pos_in_item += ih_entry_count(pasted) - (tb->lbytes -1); | ||
| 383 | } | ||
| 384 | 440 | ||
| 385 | /* Append given directory entry to directory item */ | 441 | /* appended item will be in L[0] in whole */ |
| 386 | buffer_info_init_left(tb, &bi); | 442 | if (tb->lbytes >= tb->pos_in_item) { |
| 387 | leaf_paste_in_buffer(&bi, n + tb->item_pos - ret_val, l_pos_in_item, tb->insert_size[0], body, tb->zeroes_num); | 443 | struct item_head *tbS0_pos_ih, *tbL0_ih; |
| 444 | struct item_head *tbS0_0_ih; | ||
| 445 | struct reiserfs_key *left_delim_key; | ||
| 446 | int ret, l_n, version, temp_l; | ||
| 388 | 447 | ||
| 389 | /* previous string prepared space for pasting new entry, following string pastes this entry */ | 448 | tbS0_pos_ih = item_head(tbS0, tb->item_pos); |
| 449 | tbS0_0_ih = item_head(tbS0, 0); | ||
| 390 | 450 | ||
| 391 | /* when we have merge directory item, pos_in_item has been changed too */ | 451 | /* |
| 452 | * this bytes number must be appended | ||
| 453 | * to the last item of L[h] | ||
| 454 | */ | ||
| 455 | l_n = tb->lbytes - tb->pos_in_item; | ||
| 392 | 456 | ||
| 393 | /* paste new directory entry. 1 is entry number */ | 457 | /* Calculate new insert_size[0] */ |
| 394 | leaf_paste_entries(&bi, n + tb->item_pos - ret_val, l_pos_in_item, | 458 | tb->insert_size[0] -= l_n; |
| 395 | 1, (struct reiserfs_de_head *) body, | ||
| 396 | body + DEH_SIZE, tb->insert_size[0]); | ||
| 397 | tb->insert_size[0] = 0; | ||
| 398 | } else { | ||
| 399 | /* new directory item doesn't fall into L[0] */ | ||
| 400 | /* Shift lnum[0]-1 items in whole. Shift lbytes directory entries from directory item number lnum[0] */ | ||
| 401 | leaf_shift_left(tb, tb->lnum[0], tb->lbytes); | ||
| 402 | } | ||
| 403 | /* Calculate new position to append in item body */ | ||
| 404 | tb->pos_in_item -= tb->lbytes; | ||
| 405 | } else { | ||
| 406 | /* regular object */ | ||
| 407 | RFALSE(tb->lbytes <= 0, "PAP-12095: there is nothing to shift to L[0]. lbytes=%d", tb->lbytes); | ||
| 408 | RFALSE(tb->pos_in_item != ih_item_len(item_head(tbS0, tb->item_pos)), | ||
| 409 | "PAP-12100: incorrect position to paste: item_len=%d, pos_in_item=%d", | ||
| 410 | ih_item_len(item_head(tbS0, tb->item_pos)), tb->pos_in_item); | ||
| 411 | |||
| 412 | if (tb->lbytes >= tb->pos_in_item) { | ||
| 413 | /* appended item will be in L[0] in whole */ | ||
| 414 | int l_n; | ||
| 415 | |||
| 416 | /* this bytes number must be appended to the last item of L[h] */ | ||
| 417 | l_n = tb->lbytes - tb->pos_in_item; | ||
| 418 | |||
| 419 | /* Calculate new insert_size[0] */ | ||
| 420 | tb->insert_size[0] -= l_n; | ||
| 421 | |||
| 422 | RFALSE(tb->insert_size[0] <= 0, | ||
| 423 | "PAP-12105: there is nothing to paste into L[0]. insert_size=%d", | ||
| 424 | tb->insert_size[0]); | ||
| 425 | ret_val = leaf_shift_left(tb, tb->lnum[0], ih_item_len | ||
| 426 | (item_head(tbS0, tb->item_pos))); | ||
| 427 | /* Append to body of item in L[0] */ | ||
| 428 | buffer_info_init_left(tb, &bi); | ||
| 429 | leaf_paste_in_buffer | ||
| 430 | (&bi, n + tb->item_pos - ret_val, ih_item_len | ||
| 431 | (item_head(tb->L[0], n + tb->item_pos - ret_val)), | ||
| 432 | l_n, body, | ||
| 433 | tb->zeroes_num > l_n ? l_n : tb->zeroes_num); | ||
| 434 | /* 0-th item in S0 can be only of DIRECT type when l_n != 0 */ | ||
| 435 | { | ||
| 436 | int version; | ||
| 437 | int temp_l = l_n; | ||
| 438 | |||
| 439 | RFALSE(ih_item_len(item_head(tbS0, 0)), | ||
| 440 | "PAP-12106: item length must be 0"); | ||
| 441 | RFALSE(comp_short_le_keys(leaf_key(tbS0, 0), leaf_key | ||
| 442 | (tb->L[0], n + tb->item_pos - ret_val)), | ||
| 443 | "PAP-12107: items must be of the same file"); | ||
| 444 | if (is_indirect_le_ih(item_head(tb->L[0], n + tb->item_pos - ret_val))) { | ||
| 445 | temp_l = l_n << (tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT); | ||
| 446 | } | ||
| 447 | |||
