diff options
Diffstat (limited to 'fs/xfs/xfs_dir2_node.c')
-rw-r--r-- | fs/xfs/xfs_dir2_node.c | 475 |
1 files changed, 277 insertions, 198 deletions
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index abf617d5060b..baaf9d96e354 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -41,14 +41,6 @@ | |||
41 | */ | 41 | */ |
42 | static int xfs_dir2_leafn_add(struct xfs_buf *bp, xfs_da_args_t *args, | 42 | static int xfs_dir2_leafn_add(struct xfs_buf *bp, xfs_da_args_t *args, |
43 | int index); | 43 | int index); |
44 | #ifdef DEBUG | ||
45 | static void xfs_dir2_leafn_check(struct xfs_inode *dp, struct xfs_buf *bp); | ||
46 | #else | ||
47 | #define xfs_dir2_leafn_check(dp, bp) | ||
48 | #endif | ||
49 | static void xfs_dir2_leafn_moveents(xfs_da_args_t *args, struct xfs_buf *bp_s, | ||
50 | int start_s, struct xfs_buf *bp_d, | ||
51 | int start_d, int count); | ||
52 | static void xfs_dir2_leafn_rebalance(xfs_da_state_t *state, | 44 | static void xfs_dir2_leafn_rebalance(xfs_da_state_t *state, |
53 | xfs_da_state_blk_t *blk1, | 45 | xfs_da_state_blk_t *blk1, |
54 | xfs_da_state_blk_t *blk2); | 46 | xfs_da_state_blk_t *blk2); |
@@ -58,6 +50,39 @@ static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp, | |||
58 | static int xfs_dir2_node_addname_int(xfs_da_args_t *args, | 50 | static int xfs_dir2_node_addname_int(xfs_da_args_t *args, |
59 | xfs_da_state_blk_t *fblk); | 51 | xfs_da_state_blk_t *fblk); |
60 | 52 | ||
53 | /* | ||
54 | * Check internal consistency of a leafn block. | ||
55 | */ | ||
56 | #ifdef DEBUG | ||
57 | #define xfs_dir3_leaf_check(mp, bp) \ | ||
58 | do { \ | ||
59 | if (!xfs_dir3_leafn_check((mp), (bp))) \ | ||
60 | ASSERT(0); \ | ||
61 | } while (0); | ||
62 | |||
63 | static bool | ||
64 | xfs_dir3_leafn_check( | ||
65 | struct xfs_mount *mp, | ||
66 | struct xfs_buf *bp) | ||
67 | { | ||
68 | struct xfs_dir2_leaf *leaf = bp->b_addr; | ||
69 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
70 | |||
71 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
72 | |||
73 | if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC) { | ||
74 | struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; | ||
75 | if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) | ||
76 | return false; | ||
77 | } else if (leafhdr.magic != XFS_DIR2_LEAFN_MAGIC) | ||
78 | return false; | ||
79 | |||
80 | return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf); | ||
81 | } | ||
82 | #else | ||
83 | #define xfs_dir3_leaf_check(mp, bp) | ||
84 | #endif | ||
85 | |||
61 | static bool | 86 | static bool |
62 | xfs_dir3_free_verify( | 87 | xfs_dir3_free_verify( |
63 | struct xfs_buf *bp) | 88 | struct xfs_buf *bp) |
@@ -360,11 +385,19 @@ xfs_dir2_leaf_to_node( | |||
360 | xfs_dir2_free_log_bests(tp, fbp, 0, freehdr.nvalid - 1); | 385 | xfs_dir2_free_log_bests(tp, fbp, 0, freehdr.nvalid - 1); |
361 | xfs_dir2_free_log_header(tp, fbp); | 386 | xfs_dir2_free_log_header(tp, fbp); |
362 | 387 | ||
363 | /* convert the leaf to a leafnode */ | 388 | /* |
364 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC); | 389 | * Converting the leaf to a leafnode is just a matter of changing the |
365 | lbp->b_ops = &xfs_dir2_leafn_buf_ops; | 390 | * magic number and the ops. Do the change directly to the buffer as |
366 | xfs_dir2_leaf_log_header(tp, lbp); | 391 | * it's less work (and less code) than decoding the header to host |
367 | xfs_dir2_leafn_check(dp, lbp); | 392 | * format and back again. |
393 | */ | ||
394 | if (leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)) | ||
395 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC); | ||
396 | else | ||
397 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); | ||
398 | lbp->b_ops = &xfs_dir3_leafn_buf_ops; | ||
399 | xfs_dir3_leaf_log_header(tp, lbp); | ||
400 | xfs_dir3_leaf_check(mp, lbp); | ||
368 | return 0; | 401 | return 0; |
369 | } | 402 | } |
370 | 403 | ||
@@ -388,6 +421,8 @@ xfs_dir2_leafn_add( | |||
388 | int lowstale; /* previous stale entry */ | 421 | int lowstale; /* previous stale entry */ |
389 | xfs_mount_t *mp; /* filesystem mount point */ | 422 | xfs_mount_t *mp; /* filesystem mount point */ |
390 | xfs_trans_t *tp; /* transaction pointer */ | 423 | xfs_trans_t *tp; /* transaction pointer */ |
424 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
425 | struct xfs_dir2_leaf_entry *ents; | ||
391 | 426 | ||
392 | trace_xfs_dir2_leafn_add(args, index); | 427 | trace_xfs_dir2_leafn_add(args, index); |
393 | 428 | ||
@@ -395,6 +430,8 @@ xfs_dir2_leafn_add( | |||
395 | mp = dp->i_mount; | 430 | mp = dp->i_mount; |
396 | tp = args->trans; | 431 | tp = args->trans; |
397 | leaf = bp->b_addr; | 432 | leaf = bp->b_addr; |
433 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
434 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
398 | 435 | ||
399 | /* | 436 | /* |
400 | * Quick check just to make sure we are not going to index | 437 | * Quick check just to make sure we are not going to index |
@@ -410,15 +447,15 @@ xfs_dir2_leafn_add( | |||
410 | * a compact. | 447 | * a compact. |
411 | */ | 448 | */ |
412 | 449 | ||
413 | if (be16_to_cpu(leaf->hdr.count) == xfs_dir2_max_leaf_ents(mp)) { | 450 | if (leafhdr.count == xfs_dir3_max_leaf_ents(mp, leaf)) { |
414 | if (!leaf->hdr.stale) | 451 | if (!leafhdr.stale) |
415 | return XFS_ERROR(ENOSPC); | 452 | return XFS_ERROR(ENOSPC); |
416 | compact = be16_to_cpu(leaf->hdr.stale) > 1; | 453 | compact = leafhdr.stale > 1; |
417 | } else | 454 | } else |
418 | compact = 0; | 455 | compact = 0; |
419 | ASSERT(index == 0 || be32_to_cpu(leaf->ents[index - 1].hashval) <= args->hashval); | 456 | ASSERT(index == 0 || be32_to_cpu(ents[index - 1].hashval) <= args->hashval); |
420 | ASSERT(index == be16_to_cpu(leaf->hdr.count) || | 457 | ASSERT(index == leafhdr.count || |
421 | be32_to_cpu(leaf->ents[index].hashval) >= args->hashval); | 458 | be32_to_cpu(ents[index].hashval) >= args->hashval); |
422 | 459 | ||
423 | if (args->op_flags & XFS_DA_OP_JUSTCHECK) | 460 | if (args->op_flags & XFS_DA_OP_JUSTCHECK) |
424 | return 0; | 461 | return 0; |
@@ -427,62 +464,35 @@ xfs_dir2_leafn_add( | |||
427 | * Compact out all but one stale leaf entry. Leaves behind | 464 | * Compact out all but one stale leaf entry. Leaves behind |
428 | * the entry closest to index. | 465 | * the entry closest to index. |
429 | */ | 466 | */ |
430 | if (compact) { | 467 | if (compact) |
431 | xfs_dir2_leaf_compact_x1(bp, &index, &lowstale, &highstale, | 468 | xfs_dir3_leaf_compact_x1(&leafhdr, ents, &index, &lowstale, |
432 | &lfloglow, &lfloghigh); | 469 | &highstale, &lfloglow, &lfloghigh); |
433 | } | 470 | else if (leafhdr.stale) { |
434 | /* | 471 | /* |
435 | * Set impossible logging indices for this case. | 472 | * Set impossible logging indices for this case. |
436 | */ | 473 | */ |
437 | else if (leaf->hdr.stale) { | 474 | lfloglow = leafhdr.count; |
438 | lfloglow = be16_to_cpu(leaf->hdr.count); | ||
439 | lfloghigh = -1; | 475 | lfloghigh = -1; |
440 | } | 476 | } |
441 | 477 | ||
442 | /* | 478 | /* |
443 | * Insert the new entry, log everything. | 479 | * Insert the new entry, log everything. |
444 | */ | 480 | */ |
445 | lep = xfs_dir2_leaf_find_entry(leaf, index, compact, lowstale, | 481 | lep = xfs_dir3_leaf_find_entry(&leafhdr, ents, index, compact, lowstale, |
446 | highstale, &lfloglow, &lfloghigh); | 482 | highstale, &lfloglow, &lfloghigh); |
447 | 483 | ||
448 | lep->hashval = cpu_to_be32(args->hashval); | 484 | lep->hashval = cpu_to_be32(args->hashval); |
449 | lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp, | 485 | lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp, |
450 | args->blkno, args->index)); | 486 | args->blkno, args->index)); |
451 | xfs_dir2_leaf_log_header(tp, bp); | 487 | |
452 | xfs_dir2_leaf_log_ents(tp, bp, lfloglow, lfloghigh); | 488 | xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); |
453 | xfs_dir2_leafn_check(dp, bp); | 489 | xfs_dir3_leaf_log_header(tp, bp); |
490 | xfs_dir3_leaf_log_ents(tp, bp, lfloglow, lfloghigh); | ||
491 | xfs_dir3_leaf_check(mp, bp); | ||
454 | return 0; | 492 | return 0; |
455 | } | 493 | } |
456 | 494 | ||
457 | #ifdef DEBUG | 495 | #ifdef DEBUG |
458 | /* | ||
459 | * Check internal consistency of a leafn block. | ||
460 | */ | ||
461 | void | ||
462 | xfs_dir2_leafn_check( | ||
463 | struct xfs_inode *dp, | ||
464 | struct xfs_buf *bp) | ||
465 | { | ||
466 | int i; /* leaf index */ | ||
467 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | ||
468 | xfs_mount_t *mp; /* filesystem mount point */ | ||
469 | int stale; /* count of stale leaves */ | ||
470 | |||
471 | leaf = bp->b_addr; | ||
472 | mp = dp->i_mount; | ||
473 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | ||
474 | ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp)); | ||
475 | for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) { | ||
476 | if (i + 1 < be16_to_cpu(leaf->hdr.count)) { | ||
477 | ASSERT(be32_to_cpu(leaf->ents[i].hashval) <= | ||
478 | be32_to_cpu(leaf->ents[i + 1].hashval)); | ||
479 | } | ||
480 | if (leaf->ents[i].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | ||
481 | stale++; | ||
482 | } | ||
483 | ASSERT(be16_to_cpu(leaf->hdr.stale) == stale); | ||
484 | } | ||
485 | |||
486 | static void | 496 | static void |
487 | xfs_dir2_free_hdr_check( | 497 | xfs_dir2_free_hdr_check( |
488 | struct xfs_mount *mp, | 498 | struct xfs_mount *mp, |
@@ -510,15 +520,22 @@ xfs_dir2_leafn_lasthash( | |||
510 | struct xfs_buf *bp, /* leaf buffer */ | 520 | struct xfs_buf *bp, /* leaf buffer */ |
511 | int *count) /* count of entries in leaf */ | 521 | int *count) /* count of entries in leaf */ |
512 | { | 522 | { |
513 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 523 | struct xfs_dir2_leaf *leaf = bp->b_addr; |
524 | struct xfs_dir2_leaf_entry *ents; | ||
525 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
526 | |||
527 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
528 | |||
529 | ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || | ||
530 | leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); | ||
514 | 531 | ||
515 | leaf = bp->b_addr; | ||
516 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | ||
517 | if (count) | 532 | if (count) |
518 | *count = be16_to_cpu(leaf->hdr.count); | 533 | *count = leafhdr.count; |
519 | if (!leaf->hdr.count) | 534 | if (!leafhdr.count) |
520 | return 0; | 535 | return 0; |
521 | return be32_to_cpu(leaf->ents[be16_to_cpu(leaf->hdr.count) - 1].hashval); | 536 | |
537 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
538 | return be32_to_cpu(ents[leafhdr.count - 1].hashval); | ||
522 | } | 539 | } |
523 | 540 | ||
524 | /* | 541 | /* |
@@ -547,16 +564,19 @@ xfs_dir2_leafn_lookup_for_addname( | |||
547 | xfs_dir2_db_t newdb; /* new data block number */ | 564 | xfs_dir2_db_t newdb; /* new data block number */ |
548 | xfs_dir2_db_t newfdb; /* new free block number */ | 565 | xfs_dir2_db_t newfdb; /* new free block number */ |
549 | xfs_trans_t *tp; /* transaction pointer */ | 566 | xfs_trans_t *tp; /* transaction pointer */ |
567 | struct xfs_dir2_leaf_entry *ents; | ||
568 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
550 | 569 | ||
551 | dp = args->dp; | 570 | dp = args->dp; |
552 | tp = args->trans; | 571 | tp = args->trans; |
553 | mp = dp->i_mount; | 572 | mp = dp->i_mount; |
554 | leaf = bp->b_addr; | 573 | leaf = bp->b_addr; |
555 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 574 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
556 | #ifdef __KERNEL__ | 575 | ents = xfs_dir3_leaf_ents_p(leaf); |
557 | ASSERT(be16_to_cpu(leaf->hdr.count) > 0); | 576 | |
558 | #endif | 577 | xfs_dir3_leaf_check(mp, bp); |
559 | xfs_dir2_leafn_check(dp, bp); | 578 | ASSERT(leafhdr.count > 0); |
579 | |||
560 | /* | 580 | /* |
561 | * Look up the hash value in the leaf entries. | 581 | * Look up the hash value in the leaf entries. |
562 | */ | 582 | */ |
@@ -576,9 +596,9 @@ xfs_dir2_leafn_lookup_for_addname( | |||
576 | /* | 596 | /* |
577 | * Loop over leaf entries with the right hash value. | 597 | * Loop over leaf entries with the right hash value. |
578 | */ | 598 | */ |
579 | for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) && | 599 | for (lep = &ents[index]; |
580 | be32_to_cpu(lep->hashval) == args->hashval; | 600 | index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; |
581 | lep++, index++) { | 601 | lep++, index++) { |
582 | /* | 602 | /* |
583 | * Skip stale leaf entries. | 603 | * Skip stale leaf entries. |
584 | */ | 604 | */ |
@@ -694,16 +714,19 @@ xfs_dir2_leafn_lookup_for_entry( | |||
694 | xfs_dir2_db_t newdb; /* new data block number */ | 714 | xfs_dir2_db_t newdb; /* new data block number */ |
695 | xfs_trans_t *tp; /* transaction pointer */ | 715 | xfs_trans_t *tp; /* transaction pointer */ |
696 | enum xfs_dacmp cmp; /* comparison result */ | 716 | enum xfs_dacmp cmp; /* comparison result */ |
717 | struct xfs_dir2_leaf_entry *ents; | ||
718 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
697 | 719 | ||
698 | dp = args->dp; | 720 | dp = args->dp; |
699 | tp = args->trans; | 721 | tp = args->trans; |
700 | mp = dp->i_mount; | 722 | mp = dp->i_mount; |
701 | leaf = bp->b_addr; | 723 | leaf = bp->b_addr; |
702 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 724 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
703 | #ifdef __KERNEL__ | 725 | ents = xfs_dir3_leaf_ents_p(leaf); |
704 | ASSERT(be16_to_cpu(leaf->hdr.count) > 0); | 726 | |
705 | #endif | 727 | xfs_dir3_leaf_check(mp, bp); |
706 | xfs_dir2_leafn_check(dp, bp); | 728 | ASSERT(leafhdr.count > 0); |
729 | |||
707 | /* | 730 | /* |
708 | * Look up the hash value in the leaf entries. | 731 | * Look up the hash value in the leaf entries. |
709 | */ | 732 | */ |
@@ -718,9 +741,9 @@ xfs_dir2_leafn_lookup_for_entry( | |||
718 | /* | 741 | /* |
719 | * Loop over leaf entries with the right hash value. | 742 | * Loop over leaf entries with the right hash value. |
720 | */ | 743 | */ |
721 | for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) && | 744 | for (lep = &ents[index]; |
722 | be32_to_cpu(lep->hashval) == args->hashval; | 745 | index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; |
723 | lep++, index++) { | 746 | lep++, index++) { |
724 | /* | 747 | /* |
725 | * Skip stale leaf entries. | 748 | * Skip stale leaf entries. |
726 | */ | 749 | */ |
@@ -792,8 +815,7 @@ xfs_dir2_leafn_lookup_for_entry( | |||
792 | return XFS_ERROR(EEXIST); | 815 | return XFS_ERROR(EEXIST); |
793 | } | 816 | } |
794 | } | 817 | } |
795 | ASSERT(index == be16_to_cpu(leaf->hdr.count) || | 818 | ASSERT(index == leafhdr.count || (args->op_flags & XFS_DA_OP_OKNOENT)); |
796 | (args->op_flags & XFS_DA_OP_OKNOENT)); | ||
797 | if (curbp) { | 819 | if (curbp) { |
798 | if (args->cmpresult == XFS_CMP_DIFFERENT) { | 820 | if (args->cmpresult == XFS_CMP_DIFFERENT) { |
799 | /* Giving back last used data block. */ | 821 | /* Giving back last used data block. */ |
@@ -838,52 +860,50 @@ xfs_dir2_leafn_lookup_int( | |||
838 | * Log entries and headers. Stale entries are preserved. | 860 | * Log entries and headers. Stale entries are preserved. |
839 | */ | 861 | */ |
840 | static void | 862 | static void |
841 | xfs_dir2_leafn_moveents( | 863 | xfs_dir3_leafn_moveents( |
842 | xfs_da_args_t *args, /* operation arguments */ | 864 | xfs_da_args_t *args, /* operation arguments */ |
843 | struct xfs_buf *bp_s, /* source leaf buffer */ | 865 | struct xfs_buf *bp_s, /* source */ |
844 | int start_s, /* source leaf index */ | 866 | struct xfs_dir3_icleaf_hdr *shdr, |
845 | struct xfs_buf *bp_d, /* destination leaf buffer */ | 867 | struct xfs_dir2_leaf_entry *sents, |
846 | int start_d, /* destination leaf index */ | 868 | int start_s,/* source leaf index */ |
847 | int count) /* count of leaves to copy */ | 869 | struct xfs_buf *bp_d, /* destination */ |
870 | struct xfs_dir3_icleaf_hdr *dhdr, | ||
871 | struct xfs_dir2_leaf_entry *dents, | ||
872 | int start_d,/* destination leaf index */ | ||
873 | int count) /* count of leaves to copy */ | ||
848 | { | 874 | { |
849 | xfs_dir2_leaf_t *leaf_d; /* destination leaf structure */ | 875 | struct xfs_trans *tp = args->trans; |
850 | xfs_dir2_leaf_t *leaf_s; /* source leaf structure */ | 876 | int stale; /* count stale leaves copied */ |
851 | int stale; /* count stale leaves copied */ | ||
852 | xfs_trans_t *tp; /* transaction pointer */ | ||
853 | 877 | ||
854 | trace_xfs_dir2_leafn_moveents(args, start_s, start_d, count); | 878 | trace_xfs_dir2_leafn_moveents(args, start_s, start_d, count); |
855 | 879 | ||
856 | /* | 880 | /* |
857 | * Silently return if nothing to do. | 881 | * Silently return if nothing to do. |
858 | */ | 882 | */ |
859 | if (count == 0) { | 883 | if (count == 0) |
860 | return; | 884 | return; |
861 | } | 885 | |
862 | tp = args->trans; | ||
863 | leaf_s = bp_s->b_addr; | ||
864 | leaf_d = bp_d->b_addr; | ||
865 | /* | 886 | /* |
866 | * If the destination index is not the end of the current | 887 | * If the destination index is not the end of the current |
867 | * destination leaf entries, open up a hole in the destination | 888 | * destination leaf entries, open up a hole in the destination |
868 | * to hold the new entries. | 889 | * to hold the new entries. |
869 | */ | 890 | */ |
870 | if (start_d < be16_to_cpu(leaf_d->hdr.count)) { | 891 | if (start_d < dhdr->count) { |
871 | memmove(&leaf_d->ents[start_d + count], &leaf_d->ents[start_d], | 892 | memmove(&dents[start_d + count], &dents[start_d], |
872 | (be16_to_cpu(leaf_d->hdr.count) - start_d) * | 893 | (dhdr->count - start_d) * sizeof(xfs_dir2_leaf_entry_t)); |
873 | sizeof(xfs_dir2_leaf_entry_t)); | 894 | xfs_dir3_leaf_log_ents(tp, bp_d, start_d + count, |
874 | xfs_dir2_leaf_log_ents(tp, bp_d, start_d + count, | 895 | count + dhdr->count - 1); |
875 | count + be16_to_cpu(leaf_d->hdr.count) - 1); | ||
876 | } | 896 | } |
877 | /* | 897 | /* |
878 | * If the source has stale leaves, count the ones in the copy range | 898 | * If the source has stale leaves, count the ones in the copy range |
879 | * so we can update the header correctly. | 899 | * so we can update the header correctly. |
880 | */ | 900 | */ |
881 | if (leaf_s->hdr.stale) { | 901 | if (shdr->stale) { |
882 | int i; /* temp leaf index */ | 902 | int i; /* temp leaf index */ |
883 | 903 | ||
884 | for (i = start_s, stale = 0; i < start_s + count; i++) { | 904 | for (i = start_s, stale = 0; i < start_s + count; i++) { |
885 | if (leaf_s->ents[i].address == | 905 | if (sents[i].address == |
886 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | 906 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) |
887 | stale++; | 907 | stale++; |
888 | } | 908 | } |
889 | } else | 909 | } else |
@@ -891,29 +911,27 @@ xfs_dir2_leafn_moveents( | |||
891 | /* | 911 | /* |
892 | * Copy the leaf entries from source to destination. | 912 | * Copy the leaf entries from source to destination. |
893 | */ | 913 | */ |
894 | memcpy(&leaf_d->ents[start_d], &leaf_s->ents[start_s], | 914 | memcpy(&dents[start_d], &sents[start_s], |
895 | count * sizeof(xfs_dir2_leaf_entry_t)); | 915 | count * sizeof(xfs_dir2_leaf_entry_t)); |
896 | xfs_dir2_leaf_log_ents(tp, bp_d, start_d, start_d + count - 1); | 916 | xfs_dir3_leaf_log_ents(tp, bp_d, start_d, start_d + count - 1); |
917 | |||
897 | /* | 918 | /* |
898 | * If there are source entries after the ones we copied, | 919 | * If there are source entries after the ones we copied, |
899 | * delete the ones we copied by sliding the next ones down. | 920 | * delete the ones we copied by sliding the next ones down. |
900 | */ | 921 | */ |
901 | if (start_s + count < be16_to_cpu(leaf_s->hdr.count)) { | 922 | if (start_s + count < shdr->count) { |
902 | memmove(&leaf_s->ents[start_s], &leaf_s->ents[start_s + count], | 923 | memmove(&sents[start_s], &sents[start_s + count], |
903 | count * sizeof(xfs_dir2_leaf_entry_t)); | 924 | count * sizeof(xfs_dir2_leaf_entry_t)); |
904 | xfs_dir2_leaf_log_ents(tp, bp_s, start_s, start_s + count - 1); | 925 | xfs_dir3_leaf_log_ents(tp, bp_s, start_s, start_s + count - 1); |
905 | } | 926 | } |
927 | |||
906 | /* | 928 | /* |
907 | * Update the headers and log them. | 929 | * Update the headers and log them. |
908 | */ | 930 | */ |
909 | be16_add_cpu(&leaf_s->hdr.count, -(count)); | 931 | shdr->count -= count; |
910 | be16_add_cpu(&leaf_s->hdr.stale, -(stale)); | 932 | shdr->stale -= stale; |
911 | be16_add_cpu(&leaf_d->hdr.count, count); | 933 | dhdr->count += count; |
912 | be16_add_cpu(&leaf_d->hdr.stale, stale); | 934 | dhdr->stale += stale; |
913 | xfs_dir2_leaf_log_header(tp, bp_s); | ||
914 | xfs_dir2_leaf_log_header(tp, bp_d); | ||
915 | xfs_dir2_leafn_check(args->dp, bp_s); | ||
916 | xfs_dir2_leafn_check(args->dp, bp_d); | ||
917 | } | 935 | } |
918 | 936 | ||
919 | /* | 937 | /* |
@@ -922,21 +940,25 @@ xfs_dir2_leafn_moveents( | |||
922 | */ | 940 | */ |
923 | int /* sort order */ | 941 | int /* sort order */ |
924 | xfs_dir2_leafn_order( | 942 | xfs_dir2_leafn_order( |
925 | struct xfs_buf *leaf1_bp, /* leaf1 buffer */ | 943 | struct xfs_buf *leaf1_bp, /* leaf1 buffer */ |
926 | struct xfs_buf *leaf2_bp) /* leaf2 buffer */ | 944 | struct xfs_buf *leaf2_bp) /* leaf2 buffer */ |
927 | { | 945 | { |
928 | xfs_dir2_leaf_t *leaf1; /* leaf1 structure */ | 946 | struct xfs_dir2_leaf *leaf1 = leaf1_bp->b_addr; |
929 | xfs_dir2_leaf_t *leaf2; /* leaf2 structure */ | 947 | struct xfs_dir2_leaf *leaf2 = leaf2_bp->b_addr; |
930 | 948 | struct xfs_dir2_leaf_entry *ents1; | |
931 | leaf1 = leaf1_bp->b_addr; | 949 | struct xfs_dir2_leaf_entry *ents2; |
932 | leaf2 = leaf2_bp->b_addr; | 950 | struct xfs_dir3_icleaf_hdr hdr1; |
933 | ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 951 | struct xfs_dir3_icleaf_hdr hdr2; |
934 | ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 952 | |
935 | if (be16_to_cpu(leaf1->hdr.count) > 0 && | 953 | xfs_dir3_leaf_hdr_from_disk(&hdr1, leaf1); |
936 | be16_to_cpu(leaf2->hdr.count) > 0 && | 954 | xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf2); |
937 | (be32_to_cpu(leaf2->ents[0].hashval) < be32_to_cpu(leaf1->ents[0].hashval) || | 955 | ents1 = xfs_dir3_leaf_ents_p(leaf1); |
938 | be32_to_cpu(leaf2->ents[be16_to_cpu(leaf2->hdr.count) - 1].hashval) < | 956 | ents2 = xfs_dir3_leaf_ents_p(leaf2); |
939 | be32_to_cpu(leaf1->ents[be16_to_cpu(leaf1->hdr.count) - 1].hashval))) | 957 | |
958 | if (hdr1.count > 0 && hdr2.count > 0 && | ||
959 | (be32_to_cpu(ents2[0].hashval) < be32_to_cpu(ents1[0].hashval) || | ||
960 | be32_to_cpu(ents2[hdr2.count - 1].hashval) < | ||
961 | be32_to_cpu(ents1[hdr1.count - 1].hashval))) | ||
940 | return 1; | 962 | return 1; |
941 | return 0; | 963 | return 0; |
942 | } | 964 | } |
@@ -965,6 +987,10 @@ xfs_dir2_leafn_rebalance( | |||
965 | #endif | 987 | #endif |
966 | int oldsum; /* old total leaf count */ | 988 | int oldsum; /* old total leaf count */ |
967 | int swap; /* swapped leaf blocks */ | 989 | int swap; /* swapped leaf blocks */ |
990 | struct xfs_dir2_leaf_entry *ents1; | ||
991 | struct xfs_dir2_leaf_entry *ents2; | ||
992 | struct xfs_dir3_icleaf_hdr hdr1; | ||
993 | struct xfs_dir3_icleaf_hdr hdr2; | ||
968 | 994 | ||
969 | args = state->args; | 995 | args = state->args; |
970 | /* | 996 | /* |
@@ -979,11 +1005,17 @@ xfs_dir2_leafn_rebalance( | |||
979 | } | 1005 | } |
980 | leaf1 = blk1->bp->b_addr; | 1006 | leaf1 = blk1->bp->b_addr; |
981 | leaf2 = blk2->bp->b_addr; | 1007 | leaf2 = blk2->bp->b_addr; |
982 | oldsum = be16_to_cpu(leaf1->hdr.count) + be16_to_cpu(leaf2->hdr.count); | 1008 | xfs_dir3_leaf_hdr_from_disk(&hdr1, leaf1); |
1009 | xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf2); | ||
1010 | ents1 = xfs_dir3_leaf_ents_p(leaf1); | ||
1011 | ents2 = xfs_dir3_leaf_ents_p(leaf2); | ||
1012 | |||
1013 | oldsum = hdr1.count + hdr2.count; | ||
983 | #ifdef DEBUG | 1014 | #ifdef DEBUG |
984 | oldstale = be16_to_cpu(leaf1->hdr.stale) + be16_to_cpu(leaf2->hdr.stale); | 1015 | oldstale = hdr1.stale + hdr2.stale; |
985 | #endif | 1016 | #endif |
986 | mid = oldsum >> 1; | 1017 | mid = oldsum >> 1; |
1018 | |||
987 | /* | 1019 | /* |
988 | * If the old leaf count was odd then the new one will be even, | 1020 | * If the old leaf count was odd then the new one will be even, |
989 | * so we need to divide the new count evenly. | 1021 | * so we need to divide the new count evenly. |
@@ -991,10 +1023,10 @@ xfs_dir2_leafn_rebalance( | |||
991 | if (oldsum & 1) { | 1023 | if (oldsum & 1) { |
992 | xfs_dahash_t midhash; /* middle entry hash value */ | 1024 | xfs_dahash_t midhash; /* middle entry hash value */ |
993 | 1025 | ||
994 | if (mid >= be16_to_cpu(leaf1->hdr.count)) | 1026 | if (mid >= hdr1.count) |
995 | midhash = be32_to_cpu(leaf2->ents[mid - be16_to_cpu(leaf1->hdr.count)].hashval); | 1027 | midhash = be32_to_cpu(ents2[mid - hdr1.count].hashval); |
996 | else | 1028 | else |
997 | midhash = be32_to_cpu(leaf1->ents[mid].hashval); | 1029 | midhash = be32_to_cpu(ents1[mid].hashval); |
998 | isleft = args->hashval <= midhash; | 1030 | isleft = args->hashval <= midhash; |
999 | } | 1031 | } |
1000 | /* | 1032 | /* |
@@ -1008,30 +1040,42 @@ xfs_dir2_leafn_rebalance( | |||
1008 | * Calculate moved entry count. Positive means left-to-right, | 1040 | * Calculate moved entry count. Positive means left-to-right, |
1009 | * negative means right-to-left. Then move the entries. | 1041 | * negative means right-to-left. Then move the entries. |
1010 | */ | 1042 | */ |
1011 | count = be16_to_cpu(leaf1->hdr.count) - mid + (isleft == 0); | 1043 | count = hdr1.count - mid + (isleft == 0); |
1012 | if (count > 0) | 1044 | if (count > 0) |
1013 | xfs_dir2_leafn_moveents(args, blk1->bp, | 1045 | xfs_dir3_leafn_moveents(args, blk1->bp, &hdr1, ents1, |
1014 | be16_to_cpu(leaf1->hdr.count) - count, blk2->bp, 0, count); | 1046 | hdr1.count - count, blk2->bp, |
1047 | &hdr2, ents2, 0, count); | ||
1015 | else if (count < 0) | 1048 | else if (count < 0) |
1016 | xfs_dir2_leafn_moveents(args, blk2->bp, 0, blk1->bp, | 1049 | xfs_dir3_leafn_moveents(args, blk2->bp, &hdr2, ents2, 0, |
1017 | be16_to_cpu(leaf1->hdr.count), count); | 1050 | blk1->bp, &hdr1, ents1, |
1018 | ASSERT(be16_to_cpu(leaf1->hdr.count) + be16_to_cpu(leaf2->hdr.count) == oldsum); | 1051 | hdr1.count, count); |
1019 | ASSERT(be16_to_cpu(leaf1->hdr.stale) + be16_to_cpu(leaf2->hdr.stale) == oldstale); | 1052 | |
1053 | ASSERT(hdr1.count + hdr2.count == oldsum); | ||
1054 | ASSERT(hdr1.stale + hdr2.stale == oldstale); | ||
1055 | |||
1056 | /* log the changes made when moving the entries */ | ||
1057 | xfs_dir3_leaf_hdr_to_disk(leaf1, &hdr1); | ||
1058 | xfs_dir3_leaf_hdr_to_disk(leaf2, &hdr2); | ||
1059 | xfs_dir3_leaf_log_header(args->trans, blk1->bp); | ||
1060 | xfs_dir3_leaf_log_header(args->trans, blk2->bp); | ||
1061 | |||
1062 | xfs_dir3_leaf_check(args->dp->i_mount, blk1->bp); | ||
1063 | xfs_dir3_leaf_check(args->dp->i_mount, blk2->bp); | ||
1064 | |||
1020 | /* | 1065 | /* |
1021 | * Mark whether we're inserting into the old or new leaf. | 1066 | * Mark whether we're inserting into the old or new leaf. |
1022 | */ | 1067 | */ |
1023 | if (be16_to_cpu(leaf1->hdr.count) < be16_to_cpu(leaf2->hdr.count)) | 1068 | if (hdr1.count < hdr2.count) |
1024 | state->inleaf = swap; | 1069 | state->inleaf = swap; |
1025 | else if (be16_to_cpu(leaf1->hdr.count) > be16_to_cpu(leaf2->hdr.count)) | 1070 | else if (hdr1.count > hdr2.count) |
1026 | state->inleaf = !swap; | 1071 | state->inleaf = !swap; |
1027 | else | 1072 | else |
1028 | state->inleaf = | 1073 | state->inleaf = swap ^ (blk1->index <= hdr1.count); |
1029 | swap ^ (blk1->index <= be16_to_cpu(leaf1->hdr.count)); | ||
1030 | /* | 1074 | /* |
1031 | * Adjust the expected index for insertion. | 1075 | * Adjust the expected index for insertion. |
1032 | */ | 1076 | */ |
1033 | if (!state->inleaf) | 1077 | if (!state->inleaf) |
1034 | blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); | 1078 | blk2->index = blk1->index - hdr1.count; |
1035 | 1079 | ||
1036 | /* | 1080 | /* |
1037 | * Finally sanity check just to make sure we are not returning a | 1081 | * Finally sanity check just to make sure we are not returning a |
@@ -1153,6 +1197,8 @@ xfs_dir2_leafn_remove( | |||
1153 | int needscan; /* need to rescan data frees */ | 1197 | int needscan; /* need to rescan data frees */ |
1154 | xfs_trans_t *tp; /* transaction pointer */ | 1198 | xfs_trans_t *tp; /* transaction pointer */ |
1155 | struct xfs_dir2_data_free *bf; /* bestfree table */ | 1199 | struct xfs_dir2_data_free *bf; /* bestfree table */ |
1200 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1201 | struct xfs_dir2_leaf_entry *ents; | ||
1156 | 1202 | ||
1157 | trace_xfs_dir2_leafn_remove(args, index); | 1203 | trace_xfs_dir2_leafn_remove(args, index); |
1158 | 1204 | ||
@@ -1160,11 +1206,14 @@ xfs_dir2_leafn_remove( | |||
1160 | tp = args->trans; | 1206 | tp = args->trans; |
1161 | mp = dp->i_mount; | 1207 | mp = dp->i_mount; |
1162 | leaf = bp->b_addr; | 1208 | leaf = bp->b_addr; |
1163 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1209 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
1210 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1211 | |||
1164 | /* | 1212 | /* |
1165 | * Point to the entry we're removing. | 1213 | * Point to the entry we're removing. |
1166 | */ | 1214 | */ |
1167 | lep = &leaf->ents[index]; | 1215 | lep = &ents[index]; |
1216 | |||
1168 | /* | 1217 | /* |
1169 | * Extract the data block and offset from the entry. | 1218 | * Extract the data block and offset from the entry. |
1170 | */ | 1219 | */ |
@@ -1172,14 +1221,18 @@ xfs_dir2_leafn_remove( | |||
1172 | ASSERT(dblk->blkno == db); | 1221 | ASSERT(dblk->blkno == db); |
1173 | off = xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)); | 1222 | off = xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)); |
1174 | ASSERT(dblk->index == off); | 1223 | ASSERT(dblk->index == off); |
1224 | |||
1175 | /* | 1225 | /* |
1176 | * Kill the leaf entry by marking it stale. | 1226 | * Kill the leaf entry by marking it stale. |
1177 | * Log the leaf block changes. | 1227 | * Log the leaf block changes. |
1178 | */ | 1228 | */ |
1179 | be16_add_cpu(&leaf->hdr.stale, 1); | 1229 | leafhdr.stale++; |
1180 | xfs_dir2_leaf_log_header(tp, bp); | 1230 | xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); |
1231 | xfs_dir3_leaf_log_header(tp, bp); | ||
1232 | |||
1181 | lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); | 1233 | lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); |
1182 | xfs_dir2_leaf_log_ents(tp, bp, index, index); | 1234 | xfs_dir3_leaf_log_ents(tp, bp, index, index); |
1235 | |||
1183 | /* | 1236 | /* |
1184 | * Make the data entry free. Keep track of the longest freespace | 1237 | * Make the data entry free. Keep track of the longest freespace |
1185 | * in the data block in case it changes. | 1238 | * in the data block in case it changes. |
@@ -1267,15 +1320,13 @@ xfs_dir2_leafn_remove( | |||
1267 | return error; | 1320 | return error; |
1268 | } | 1321 | } |
1269 | 1322 | ||
1270 | xfs_dir2_leafn_check(dp, bp); | 1323 | xfs_dir3_leaf_check(mp, bp); |
1271 | /* | 1324 | /* |
1272 | * Return indication of whether this leaf block is empty enough | 1325 | * Return indication of whether this leaf block is empty enough |
1273 | * to justify trying to join it with a neighbor. | 1326 | * to justify trying to join it with a neighbor. |
1274 | */ | 1327 | */ |
1275 | *rval = | 1328 | *rval = (xfs_dir3_leaf_hdr_size(leaf) + |
1276 | ((uint)sizeof(leaf->hdr) + | 1329 | (uint)sizeof(ents[0]) * (leafhdr.count - leafhdr.stale)) < |
1277 | (uint)sizeof(leaf->ents[0]) * | ||
1278 | (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale))) < | ||
1279 | mp->m_dir_magicpct; | 1330 | mp->m_dir_magicpct; |
1280 | return 0; | 1331 | return 0; |
1281 | } | 1332 | } |
@@ -1308,11 +1359,11 @@ xfs_dir2_leafn_split( | |||
1308 | /* | 1359 | /* |
1309 | * Initialize the new leaf block. | 1360 | * Initialize the new leaf block. |
1310 | */ | 1361 | */ |
1311 | error = xfs_dir2_leaf_init(args, xfs_dir2_da_to_db(mp, blkno), | 1362 | error = xfs_dir3_leaf_get_buf(args, xfs_dir2_da_to_db(mp, blkno), |
1312 | &newblk->bp, XFS_DIR2_LEAFN_MAGIC); | 1363 | &newblk->bp, XFS_DIR2_LEAFN_MAGIC); |
1313 | if (error) { | 1364 | if (error) |
1314 | return error; | 1365 | return error; |
1315 | } | 1366 | |
1316 | newblk->blkno = blkno; | 1367 | newblk->blkno = blkno; |
1317 | newblk->magic = XFS_DIR2_LEAFN_MAGIC; | 1368 | newblk->magic = XFS_DIR2_LEAFN_MAGIC; |
1318 | /* | 1369 | /* |
@@ -1336,8 +1387,8 @@ xfs_dir2_leafn_split( | |||
1336 | */ | 1387 | */ |
1337 | oldblk->hashval = xfs_dir2_leafn_lasthash(oldblk->bp, NULL); | 1388 | oldblk->hashval = xfs_dir2_leafn_lasthash(oldblk->bp, NULL); |
1338 | newblk->hashval = xfs_dir2_leafn_lasthash(newblk->bp, NULL); | 1389 | newblk->hashval = xfs_dir2_leafn_lasthash(newblk->bp, NULL); |
1339 | xfs_dir2_leafn_check(args->dp, oldblk->bp); | 1390 | xfs_dir3_leaf_check(mp, oldblk->bp); |
1340 | xfs_dir2_leafn_check(args->dp, newblk->bp); | 1391 | xfs_dir3_leaf_check(mp, newblk->bp); |
1341 | return error; | 1392 | return error; |
1342 | } | 1393 | } |
1343 | 1394 | ||
@@ -1363,9 +1414,10 @@ xfs_dir2_leafn_toosmall( | |||
1363 | int error; /* error return value */ | 1414 | int error; /* error return value */ |
1364 | int forward; /* sibling block direction */ | 1415 | int forward; /* sibling block direction */ |
1365 | int i; /* sibling counter */ | 1416 | int i; /* sibling counter */ |
1366 | xfs_da_blkinfo_t *info; /* leaf block header */ | ||
1367 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1417 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
1368 | int rval; /* result from path_shift */ | 1418 | int rval; /* result from path_shift */ |
1419 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1420 | struct xfs_dir2_leaf_entry *ents; | ||
1369 | 1421 | ||
1370 | /* | 1422 | /* |
1371 | * Check for the degenerate case of the block being over 50% full. | 1423 | * Check for the degenerate case of the block being over 50% full. |
@@ -1373,11 +1425,13 @@ xfs_dir2_leafn_toosmall( | |||
1373 | * to coalesce with a sibling. | 1425 | * to coalesce with a sibling. |
1374 | */ | 1426 | */ |
1375 | blk = &state->path.blk[state->path.active - 1]; | 1427 | blk = &state->path.blk[state->path.active - 1]; |
1376 | info = blk->bp->b_addr; | 1428 | leaf = blk->bp->b_addr; |
1377 | ASSERT(info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1429 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
1378 | leaf = (xfs_dir2_leaf_t *)info; | 1430 | ents = xfs_dir3_leaf_ents_p(leaf); |
1379 | count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale); | 1431 | xfs_dir3_leaf_check(state->args->dp->i_mount, blk->bp); |
1380 | bytes = (uint)sizeof(leaf->hdr) + count * (uint)sizeof(leaf->ents[0]); | 1432 | |
1433 | count = leafhdr.count - leafhdr.stale; | ||
1434 | bytes = xfs_dir3_leaf_hdr_size(leaf) + count * sizeof(ents[0]); | ||
1381 | if (bytes > (state->blocksize >> 1)) { | 1435 | if (bytes > (state->blocksize >> 1)) { |
1382 | /* | 1436 | /* |
1383 | * Blk over 50%, don't try to join. | 1437 | * Blk over 50%, don't try to join. |
@@ -1396,7 +1450,7 @@ xfs_dir2_leafn_toosmall( | |||
1396 | * Make altpath point to the block we want to keep and | 1450 | * Make altpath point to the block we want to keep and |
1397 | * path point to the block we want to drop (this one). | 1451 | * path point to the block we want to drop (this one). |
1398 | */ | 1452 | */ |
1399 | forward = (info->forw != 0); | 1453 | forward = (leafhdr.forw != 0); |
1400 | memcpy(&state->altpath, &state->path, sizeof(state->path)); | 1454 | memcpy(&state->altpath, &state->path, sizeof(state->path)); |
1401 | error = xfs_da_path_shift(state, &state->altpath, forward, 0, | 1455 | error = xfs_da_path_shift(state, &state->altpath, forward, 0, |
1402 | &rval); | 1456 | &rval); |
@@ -1412,15 +1466,17 @@ xfs_dir2_leafn_toosmall( | |||
1412 | * We prefer coalescing with the lower numbered sibling so as | 1466 | * We prefer coalescing with the lower numbered sibling so as |
1413 | * to shrink a directory over time. | 1467 | * to shrink a directory over time. |
1414 | */ | 1468 | */ |
1415 | forward = be32_to_cpu(info->forw) < be32_to_cpu(info->back); | 1469 | forward = leafhdr.forw < leafhdr.back; |
1416 | for (i = 0, bp = NULL; i < 2; forward = !forward, i++) { | 1470 | for (i = 0, bp = NULL; i < 2; forward = !forward, i++) { |
1417 | blkno = forward ? be32_to_cpu(info->forw) : be32_to_cpu(info->back); | 1471 | struct xfs_dir3_icleaf_hdr hdr2; |
1472 | |||
1473 | blkno = forward ? leafhdr.forw : leafhdr.back; | ||
1418 | if (blkno == 0) | 1474 | if (blkno == 0) |
1419 | continue; | 1475 | continue; |
1420 | /* | 1476 | /* |
1421 | * Read the sibling leaf block. | 1477 | * Read the sibling leaf block. |
1422 | */ | 1478 | */ |
1423 | error = xfs_dir2_leafn_read(state->args->trans, state->args->dp, | 1479 | error = xfs_dir3_leafn_read(state->args->trans, state->args->dp, |
1424 | blkno, -1, &bp); | 1480 | blkno, -1, &bp); |
1425 | if (error) | 1481 | if (error) |
1426 | return error; | 1482 | return error; |
@@ -1428,13 +1484,15 @@ xfs_dir2_leafn_toosmall( | |||
1428 | /* | 1484 | /* |
1429 | * Count bytes in the two blocks combined. | 1485 | * Count bytes in the two blocks combined. |
1430 | */ | 1486 | */ |
1431 | leaf = (xfs_dir2_leaf_t *)info; | 1487 | count = leafhdr.count - leafhdr.stale; |
1432 | count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale); | ||
1433 | bytes = state->blocksize - (state->blocksize >> 2); | 1488 | bytes = state->blocksize - (state->blocksize >> 2); |
1489 | |||
1434 | leaf = bp->b_addr; | 1490 | leaf = bp->b_addr; |
1435 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1491 | xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf); |
1436 | count += be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale); | 1492 | ents = xfs_dir3_leaf_ents_p(leaf); |
1437 | bytes -= count * (uint)sizeof(leaf->ents[0]); | 1493 | count += hdr2.count - hdr2.stale; |
1494 | bytes -= count * sizeof(ents[0]); | ||
1495 | |||
1438 | /* | 1496 | /* |
1439 | * Fits with at least 25% to spare. | 1497 | * Fits with at least 25% to spare. |
1440 | */ | 1498 | */ |
@@ -1481,34 +1539,53 @@ xfs_dir2_leafn_unbalance( | |||
1481 | xfs_da_args_t *args; /* operation arguments */ | 1539 | xfs_da_args_t *args; /* operation arguments */ |
1482 | xfs_dir2_leaf_t *drop_leaf; /* dead leaf structure */ | 1540 | xfs_dir2_leaf_t *drop_leaf; /* dead leaf structure */ |
1483 | xfs_dir2_leaf_t *save_leaf; /* surviving leaf structure */ | 1541 | xfs_dir2_leaf_t *save_leaf; /* surviving leaf structure */ |
1542 | struct xfs_dir3_icleaf_hdr savehdr; | ||
1543 | struct xfs_dir3_icleaf_hdr drophdr; | ||
1544 | struct xfs_dir2_leaf_entry *sents; | ||
1545 | struct xfs_dir2_leaf_entry *dents; | ||
1484 | 1546 | ||
1485 | args = state->args; | 1547 | args = state->args; |
1486 | ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC); | 1548 | ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC); |
1487 | ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC); | 1549 | ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC); |
1488 | drop_leaf = drop_blk->bp->b_addr; | 1550 | drop_leaf = drop_blk->bp->b_addr; |
1489 | save_leaf = save_blk->bp->b_addr; | 1551 | save_leaf = save_blk->bp->b_addr; |
1490 | ASSERT(drop_leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1552 | |
1491 | ASSERT(save_leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1553 | xfs_dir3_leaf_hdr_from_disk(&savehdr, save_leaf); |
1554 | xfs_dir3_leaf_hdr_from_disk(&drophdr, drop_leaf); | ||
1555 | sents = xfs_dir3_leaf_ents_p(save_leaf); | ||
1556 | dents = xfs_dir3_leaf_ents_p(drop_leaf); | ||
1557 | |||
1492 | /* | 1558 | /* |
1493 | * If there are any stale leaf entries, take this opportunity | 1559 | * If there are any stale leaf entries, take this opportunity |
1494 | * to purge them. | 1560 | * to purge them. |
1495 | */ | 1561 | */ |
1496 | if (drop_leaf->hdr.stale) | 1562 | if (drophdr.stale) |
1497 | xfs_dir2_leaf_compact(args, drop_blk->bp); | 1563 | xfs_dir3_leaf_compact(args, &drophdr, drop_blk->bp); |
1498 | if (save_leaf->hdr.stale) | 1564 | if (savehdr.stale) |
1499 | xfs_dir2_leaf_compact(args, save_blk->bp); | 1565 | xfs_dir3_leaf_compact(args, &savehdr, save_blk->bp); |
1566 | |||
1500 | /* | 1567 | /* |
1501 | * Move the entries from drop to the appropriate end of save. | 1568 | * Move the entries from drop to the appropriate end of save. |
1502 | */ | 1569 | */ |
1503 | drop_blk->hashval = be32_to_cpu(drop_leaf->ents[be16_to_cpu(drop_leaf->hdr.count) - 1].hashval); | 1570 | drop_blk->hashval = be32_to_cpu(dents[drophdr.count - 1].hashval); |
1504 | if (xfs_dir2_leafn_order(save_blk->bp, drop_blk->bp)) | 1571 | if (xfs_dir2_leafn_order(save_blk->bp, drop_blk->bp)) |
1505 | xfs_dir2_leafn_moveents(args, drop_blk->bp, 0, save_blk->bp, 0, | 1572 | xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0, |
1506 | be16_to_cpu(drop_leaf->hdr.count)); | 1573 | save_blk->bp, &savehdr, sents, 0, |
1574 | drophdr.count); | ||
1507 | else | 1575 | else |
1508 | xfs_dir2_leafn_moveents(args, drop_blk->bp, 0, save_blk->bp, | 1576 | xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0, |
1509 | be16_to_cpu(save_leaf->hdr.count), be16_to_cpu(drop_leaf->hdr.count)); | 1577 | save_blk->bp, &savehdr, sents, |
1510 | save_blk->hashval = be32_to_cpu(save_leaf->ents[be16_to_cpu(save_leaf->hdr.count) - 1].hashval); | 1578 | savehdr.count, drophdr.count); |
1511 | xfs_dir2_leafn_check(args->dp, save_blk->bp); | 1579 | save_blk->hashval = be32_to_cpu(sents[savehdr.count - 1].hashval); |
1580 | |||
1581 | /* log the changes made when moving the entries */ | ||
1582 | xfs_dir3_leaf_hdr_to_disk(save_leaf, &savehdr); | ||
1583 | xfs_dir3_leaf_hdr_to_disk(drop_leaf, &drophdr); | ||
1584 | xfs_dir3_leaf_log_header(args->trans, save_blk->bp); | ||
1585 | xfs_dir3_leaf_log_header(args->trans, drop_blk->bp); | ||
1586 | |||
1587 | xfs_dir3_leaf_check(args->dp->i_mount, save_blk->bp); | ||
1588 | xfs_dir3_leaf_check(args->dp->i_mount, drop_blk->bp); | ||
1512 | } | 1589 | } |
1513 | 1590 | ||
1514 | /* | 1591 | /* |
@@ -2113,13 +2190,15 @@ xfs_dir2_node_replace( | |||
2113 | * and locked it. But paranoia is good. | 2190 | * and locked it. But paranoia is good. |
2114 | */ | 2191 | */ |
2115 | if (rval == EEXIST) { | 2192 | if (rval == EEXIST) { |
2193 | struct xfs_dir2_leaf_entry *ents; | ||
2116 | /* | 2194 | /* |
2117 | * Find the leaf entry. | 2195 | * Find the leaf entry. |
2118 | */ | 2196 | */ |
2119 | blk = &state->path.blk[state->path.active - 1]; | 2197 | blk = &state->path.blk[state->path.active - 1]; |
2120 | ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC); | 2198 | ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC); |
2121 | leaf = blk->bp->b_addr; | 2199 | leaf = blk->bp->b_addr; |
2122 | lep = &leaf->ents[blk->index]; | 2200 | ents = xfs_dir3_leaf_ents_p(leaf); |
2201 | lep = &ents[blk->index]; | ||
2123 | ASSERT(state->extravalid); | 2202 | ASSERT(state->extravalid); |
2124 | /* | 2203 | /* |
2125 | * Point to the data entry. | 2204 | * Point to the data entry. |