diff options
| author | Tao Ma <tao.ma@oracle.com> | 2008-01-30 01:21:05 -0500 |
|---|---|---|
| committer | Mark Fasheh <mfasheh@suse.com> | 2008-04-18 11:56:10 -0400 |
| commit | 677b975282e48d1818df4181336307377d56b04e (patch) | |
| tree | eb4014d515d3dd23bf70d9cace666f2c85864141 | |
| parent | 52f7c21b613f80cb425d115c9e5b4ed958a133c0 (diff) | |
ocfs2: Add support for cross extent block
In ocfs2_merge_rec_left, when we find the merge extent is "CONTIG_RIGHT"
with the first extent record of the next extent block, we will merge it to
the next extent block and change all the related extent blocks accordingly.
In ocfs2_merge_rec_right, when we find the merge extent is "CONTIG_LEFT"
with the last extent record of the previous extent block, we will merge
it to the prevoius extent block and change all the related extent blocks
accordingly.
As for CONTIG_LEFTRIGHT, we will handle CONTIG_RIGHT first so that when
the index is zero, the merge process will be more efficient and easier.
Signed-off-by: Tao Ma <tao.ma@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
| -rw-r--r-- | fs/ocfs2/alloc.c | 366 |
1 files changed, 325 insertions, 41 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 447206eb5c2e..f63cb32e224d 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
| @@ -1450,6 +1450,8 @@ static void ocfs2_adjust_root_records(struct ocfs2_extent_list *root_el, | |||
| 1450 | * - When our insert into the right path leaf is at the leftmost edge | 1450 | * - When our insert into the right path leaf is at the leftmost edge |
| 1451 | * and requires an update of the path immediately to it's left. This | 1451 | * and requires an update of the path immediately to it's left. This |
| 1452 | * can occur at the end of some types of rotation and appending inserts. | 1452 | * can occur at the end of some types of rotation and appending inserts. |
| 1453 | * - When we've adjusted the last extent record in the left path leaf and the | ||
| 1454 | * 1st extent record in the right path leaf during cross extent block merge. | ||
| 1453 | */ | 1455 | */ |
| 1454 | static void ocfs2_complete_edge_insert(struct inode *inode, handle_t *handle, | 1456 | static void ocfs2_complete_edge_insert(struct inode *inode, handle_t *handle, |
| 1455 | struct ocfs2_path *left_path, | 1457 | struct ocfs2_path *left_path, |
| @@ -2712,24 +2714,147 @@ static void ocfs2_cleanup_merge(struct ocfs2_extent_list *el, | |||
| 2712 | } | 2714 | } |
| 2713 | } | 2715 | } |
| 2714 | 2716 | ||
| 2717 | static int ocfs2_get_right_path(struct inode *inode, | ||
| 2718 | struct ocfs2_path *left_path, | ||
| 2719 | struct ocfs2_path **ret_right_path) | ||
| 2720 | { | ||
| 2721 | int ret; | ||
| 2722 | u32 right_cpos; | ||
| 2723 | struct ocfs2_path *right_path = NULL; | ||
| 2724 | struct ocfs2_extent_list *left_el; | ||
| 2725 | |||
| 2726 | *ret_right_path = NULL; | ||
| 2727 | |||
| 2728 | /* This function shouldn't be called for non-trees. */ | ||
| 2729 | BUG_ON(left_path->p_tree_depth == 0); | ||
| 2730 | |||
| 2731 | left_el = path_leaf_el(left_path); | ||
| 2732 | BUG_ON(left_el->l_next_free_rec != left_el->l_count); | ||
| 2733 | |||
| 2734 | ret = ocfs2_find_cpos_for_right_leaf(inode->i_sb, left_path, | ||
| 2735 | &right_cpos); | ||
| 2736 | if (ret) { | ||
| 2737 | mlog_errno(ret); | ||
| 2738 | goto out; | ||
| 2739 | } | ||
| 2740 | |||
| 2741 | /* This function shouldn't be called for the rightmost leaf. */ | ||
| 2742 | BUG_ON(right_cpos == 0); | ||
| 2743 | |||
| 2744 | right_path = ocfs2_new_path(path_root_bh(left_path), | ||
| 2745 | path_root_el(left_path)); | ||
| 2746 | if (!right_path) { | ||
| 2747 | ret = -ENOMEM; | ||
| 2748 | mlog_errno(ret); | ||
| 2749 | goto out; | ||
| 2750 | } | ||
| 2751 | |||
| 2752 | ret = ocfs2_find_path(inode, right_path, right_cpos); | ||
| 2753 | if (ret) { | ||
| 2754 | mlog_errno(ret); | ||
| 2755 | goto out; | ||
| 2756 | } | ||
| 2757 | |||
| 2758 | *ret_right_path = right_path; | ||
| 2759 | out: | ||
| 2760 | if (ret) | ||
| 2761 | ocfs2_free_path(right_path); | ||
| 2762 | return ret; | ||
| 2763 | } | ||
| 2764 | |||
| 2715 | /* | 2765 | /* |
| 2716 | * Remove split_rec clusters from the record at index and merge them | 2766 | * Remove split_rec clusters from the record at index and merge them |
| 2717 | * onto the beginning of the record at index + 1. | 2767 | * onto the beginning of the record "next" to it. |
| 2768 | * For index < l_count - 1, the next means the extent rec at index + 1. | ||
| 2769 | * For index == l_count - 1, the "next" means the 1st extent rec of the | ||
| 2770 | * next extent block. | ||
| 2718 | */ | 2771 | */ |
| 2719 | static int ocfs2_merge_rec_right(struct inode *inode, struct buffer_head *bh, | 2772 | static int ocfs2_merge_rec_right(struct inode *inode, |
| 2720 | handle_t *handle, | 2773 | struct ocfs2_path *left_path, |
| 2721 | struct ocfs2_extent_rec *split_rec, | 2774 | handle_t *handle, |
| 2722 | struct ocfs2_extent_list *el, int index) | 2775 | struct ocfs2_extent_rec *split_rec, |
| 2776 | int index) | ||
| 2723 | { | 2777 | { |
| 2724 | int ret; | 2778 | int ret, next_free, i; |
| 2725 | unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters); | 2779 | unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters); |
| 2726 | struct ocfs2_extent_rec *left_rec; | 2780 | struct ocfs2_extent_rec *left_rec; |
| 2727 | struct ocfs2_extent_rec *right_rec; | 2781 | struct ocfs2_extent_rec *right_rec; |
| 2782 | struct ocfs2_extent_list *right_el; | ||
| 2783 | struct ocfs2_path *right_path = NULL; | ||
| 2784 | int subtree_index = 0; | ||
| 2785 | struct ocfs2_extent_list *el = path_leaf_el(left_path); | ||
| 2786 | struct buffer_head *bh = path_leaf_bh(left_path); | ||
| 2787 | struct buffer_head *root_bh = NULL; | ||
| 2728 | 2788 | ||
| 2729 | BUG_ON(index >= le16_to_cpu(el->l_next_free_rec)); | 2789 | BUG_ON(index >= le16_to_cpu(el->l_next_free_rec)); |
| 2730 | |||
| 2731 | left_rec = &el->l_recs[index]; | 2790 | left_rec = &el->l_recs[index]; |
| 2732 | right_rec = &el->l_recs[index + 1]; | 2791 | |
| 2792 | if (index == le16_to_cpu(el->l_next_free_rec - 1) && | ||
| 2793 | le16_to_cpu(el->l_next_free_rec) == le16_to_cpu(el->l_count)) { | ||
| 2794 | /* we meet with a cross extent block merge. */ | ||
| 2795 | ret = ocfs2_get_right_path(inode, left_path, &right_path); | ||
| 2796 | if (ret) { | ||
| 2797 | mlog_errno(ret); | ||
| 2798 | goto out; | ||
| 2799 | } | ||
| 2800 | |||
| 2801 | right_el = path_leaf_el(right_path); | ||
| 2802 | next_free = le16_to_cpu(right_el->l_next_free_rec); | ||
| 2803 | BUG_ON(next_free <= 0); | ||
| 2804 | right_rec = &right_el->l_recs[0]; | ||
| 2805 | if (ocfs2_is_empty_extent(right_rec)) { | ||
| 2806 | BUG_ON(le16_to_cpu(next_free) <= 1); | ||
| 2807 | right_rec = &right_el->l_recs[1]; | ||
| 2808 | } | ||
| 2809 | |||
| 2810 | BUG_ON(le32_to_cpu(left_rec->e_cpos) + | ||
| 2811 | le16_to_cpu(left_rec->e_leaf_clusters) != | ||
| 2812 | le32_to_cpu(right_rec->e_cpos)); | ||
| 2813 | |||
| 2814 | subtree_index = ocfs2_find_subtree_root(inode, | ||
| 2815 | left_path, right_path); | ||
| 2816 | |||
| 2817 | ret = ocfs2_extend_rotate_transaction(handle, subtree_index, | ||
| 2818 | handle->h_buffer_credits, | ||
| 2819 | right_path); | ||
| 2820 | if (ret) { | ||
| 2821 | mlog_errno(ret); | ||
| 2822 | goto out; | ||
| 2823 | } | ||
| 2824 | |||
| 2825 | root_bh = left_path->p_node[subtree_index].bh; | ||
| 2826 | BUG_ON(root_bh != right_path->p_node[subtree_index].bh); | ||
| 2827 | |||
| 2828 | ret = ocfs2_journal_access(handle, inode, root_bh, | ||
| 2829 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 2830 | if (ret) { | ||
| 2831 | mlog_errno(ret); | ||
| 2832 | goto out; | ||
| 2833 | } | ||
| 2834 | |||
| 2835 | for (i = subtree_index + 1; | ||
| 2836 | i < path_num_items(right_path); i++) { | ||
| 2837 | ret = ocfs2_journal_access(handle, inode, | ||
| 2838 | right_path->p_node[i].bh, | ||
| 2839 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 2840 | if (ret) { | ||
| 2841 | mlog_errno(ret); | ||
| 2842 | goto out; | ||
| 2843 | } | ||
| 2844 | |||
| 2845 | ret = ocfs2_journal_access(handle, inode, | ||
| 2846 | left_path->p_node[i].bh, | ||
| 2847 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 2848 | if (ret) { | ||
| 2849 | mlog_errno(ret); | ||
| 2850 | goto out; | ||
| 2851 | } | ||
| 2852 | } | ||
| 2853 | |||
| 2854 | } else { | ||
| 2855 | BUG_ON(index == le16_to_cpu(el->l_next_free_rec) - 1); | ||
| 2856 | right_rec = &el->l_recs[index + 1]; | ||
| 2857 | } | ||
| 2733 | 2858 | ||
| 2734 | ret = ocfs2_journal_access(handle, inode, bh, | 2859 | ret = ocfs2_journal_access(handle, inode, bh, |
| 2735 | OCFS2_JOURNAL_ACCESS_WRITE); | 2860 | OCFS2_JOURNAL_ACCESS_WRITE); |
| @@ -2751,30 +2876,156 @@ static int ocfs2_merge_rec_right(struct inode *inode, struct buffer_head *bh, | |||
| 2751 | if (ret) | 2876 | if (ret) |
| 2752 | mlog_errno(ret); | 2877 | mlog_errno(ret); |
| 2753 | 2878 | ||
| 2879 | if (right_path) { | ||
| 2880 | ret = ocfs2_journal_dirty(handle, path_leaf_bh(right_path)); | ||
| 2881 | if (ret) | ||
| 2882 | mlog_errno(ret); | ||
| 2883 | |||
| 2884 | ocfs2_complete_edge_insert(inode, handle, left_path, | ||
| 2885 | right_path, subtree_index); | ||
| 2886 | } | ||
| 2887 | out: | ||
| 2888 | if (right_path) | ||
| 2889 | ocfs2_free_path(right_path); | ||
| 2890 | return ret; | ||
| 2891 | } | ||
| 2892 | |||
| 2893 | static int ocfs2_get_left_path(struct inode *inode, | ||
| 2894 | struct ocfs2_path *right_path, | ||
| 2895 | struct ocfs2_path **ret_left_path) | ||
| 2896 | { | ||
| 2897 | int ret; | ||
| 2898 | u32 left_cpos; | ||
| 2899 | struct ocfs2_path *left_path = NULL; | ||
| 2900 | |||
| 2901 | *ret_left_path = NULL; | ||
| 2902 | |||
| 2903 | /* This function shouldn't be called for non-trees. */ | ||
| 2904 | BUG_ON(right_path->p_tree_depth == 0); | ||
| 2905 | |||
| 2906 | ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb, | ||
| 2907 | right_path, &left_cpos); | ||
| 2908 | if (ret) { | ||
| 2909 | mlog_errno(ret); | ||
| 2910 | goto out; | ||
| 2911 | } | ||
| 2912 | |||
| 2913 | /* This function shouldn't be called for the leftmost leaf. */ | ||
| 2914 | BUG_ON(left_cpos == 0); | ||
| 2915 | |||
| 2916 | left_path = ocfs2_new_path(path_root_bh(right_path), | ||
| 2917 | path_root_el(right_path)); | ||
| 2918 | if (!left_path) { | ||
| 2919 | ret = -ENOMEM; | ||
| 2920 | mlog_errno(ret); | ||
| 2921 | goto out; | ||
| 2922 | } | ||
| 2923 | |||
| 2924 | ret = ocfs2_find_path(inode, left_path, left_cpos); | ||
| 2925 | if (ret) { | ||
| 2926 | mlog_errno(ret); | ||
| 2927 | goto out; | ||
| 2928 | } | ||
| 2929 | |||
| 2930 | *ret_left_path = left_path; | ||
| 2754 | out: | 2931 | out: |
| 2932 | if (ret) | ||
| 2933 | ocfs2_free_path(left_path); | ||
| 2755 | return ret; | 2934 | return ret; |
| 2756 | } | 2935 | } |
| 2757 | 2936 | ||
| 2758 | /* | 2937 | /* |
| 2759 | * Remove split_rec clusters from the record at index and merge them | 2938 | * Remove split_rec clusters from the record at index and merge them |
| 2760 | * onto the tail of the record at index - 1. | 2939 | * onto the tail of the record "before" it. |
| 2940 | * For index > 0, the "before" means the extent rec at index - 1. | ||
| 2941 | * | ||
| 2942 | * For index == 0, the "before" means the last record of the previous | ||
| 2943 | * extent block. And there is also a situation that we may need to | ||
| 2944 | * remove the rightmost leaf extent block in the right_path and change | ||
| 2945 | * the right path to indicate the new rightmost path. | ||
| 2761 | */ | 2946 | */ |
| 2762 | static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh, | 2947 | static int ocfs2_merge_rec_left(struct inode *inode, |
| 2948 | struct ocfs2_path *right_path, | ||
| 2763 | handle_t *handle, | 2949 | handle_t *handle, |
| 2764 | struct ocfs2_extent_rec *split_rec, | 2950 | struct ocfs2_extent_rec *split_rec, |
| 2765 | struct ocfs2_extent_list *el, int index) | 2951 | struct ocfs2_cached_dealloc_ctxt *dealloc, |
| 2952 | int index) | ||
| 2766 | { | 2953 | { |
| 2767 | int ret, has_empty_extent = 0; | 2954 | int ret, i, subtree_index = 0, has_empty_extent = 0; |
| 2768 | unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters); | 2955 | unsigned int split_clusters = le16_to_cpu(split_rec->e_leaf_clusters); |
| 2769 | struct ocfs2_extent_rec *left_rec; | 2956 | struct ocfs2_extent_rec *left_rec; |
| 2770 | struct ocfs2_extent_rec *right_rec; | 2957 | struct ocfs2_extent_rec *right_rec; |
| 2958 | struct ocfs2_extent_list *el = path_leaf_el(right_path); | ||
| 2959 | struct buffer_head *bh = path_leaf_bh(right_path); | ||
| 2960 | struct buffer_head *root_bh = NULL; | ||
| 2961 | struct ocfs2_path *left_path = NULL; | ||
| 2962 | struct ocfs2_extent_list *left_el; | ||
| 2771 | 2963 | ||
| 2772 | BUG_ON(index <= 0); | 2964 | BUG_ON(index < 0); |
| 2773 | 2965 | ||
| 2774 | left_rec = &el->l_recs[index - 1]; | ||
| 2775 | right_rec = &el->l_recs[index]; | 2966 | right_rec = &el->l_recs[index]; |
| 2776 | if (ocfs2_is_empty_extent(&el->l_recs[0])) | 2967 | if (index == 0) { |
| 2777 | has_empty_extent = 1; | 2968 | /* we meet with a cross extent block merge. */ |
| 2969 | ret = ocfs2_get_left_path(inode, right_path, &left_path); | ||
| 2970 | if (ret) { | ||
| 2971 | mlog_errno(ret); | ||
| 2972 | goto out; | ||
| 2973 | } | ||
| 2974 | |||
| 2975 | left_el = path_leaf_el(left_path); | ||
| 2976 | BUG_ON(le16_to_cpu(left_el->l_next_free_rec) != | ||
| 2977 | le16_to_cpu(left_el->l_count)); | ||
| 2978 | |||
| 2979 | left_rec = &left_el->l_recs[ | ||
| 2980 | le16_to_cpu(left_el->l_next_free_rec) - 1]; | ||
| 2981 | BUG_ON(le32_to_cpu(left_rec->e_cpos) + | ||
| 2982 | le16_to_cpu(left_rec->e_leaf_clusters) != | ||
| 2983 | le32_to_cpu(split_rec->e_cpos)); | ||
| 2984 | |||
| 2985 | subtree_index = ocfs2_find_subtree_root(inode, | ||
| 2986 | left_path, right_path); | ||
| 2987 | |||
| 2988 | ret = ocfs2_extend_rotate_transaction(handle, subtree_index, | ||
| 2989 | handle->h_buffer_credits, | ||
| 2990 | left_path); | ||
| 2991 | if (ret) { | ||
| 2992 | mlog_errno(ret); | ||
| 2993 | goto out; | ||
| 2994 | } | ||
| 2995 | |||
| 2996 | root_bh = left_path->p_node[subtree_index].bh; | ||
| 2997 | BUG_ON(root_bh != right_path->p_node[subtree_index].bh); | ||
| 2998 | |||
| 2999 | ret = ocfs2_journal_access(handle, inode, root_bh, | ||
| 3000 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 3001 | if (ret) { | ||
| 3002 | mlog_errno(ret); | ||
| 3003 | goto out; | ||
| 3004 | } | ||
| 3005 | |||
| 3006 | for (i = subtree_index + 1; | ||
| 3007 | i < path_num_items(right_path); i++) { | ||
| 3008 | ret = ocfs2_journal_access(handle, inode, | ||
| 3009 | right_path->p_node[i].bh, | ||
| 3010 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 3011 | if (ret) { | ||
| 3012 | mlog_errno(ret); | ||
| 3013 | goto out; | ||
| 3014 | } | ||
| 3015 | |||
| 3016 | ret = ocfs2_journal_access(handle, inode, | ||
| 3017 | left_path->p_node[i].bh, | ||
| 3018 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 3019 | if (ret) { | ||
| 3020 | mlog_errno(ret); | ||
| 3021 | goto out; | ||
| 3022 | } | ||
| 3023 | } | ||
| 3024 | } else { | ||
| 3025 | left_rec = &el->l_recs[index - 1]; | ||
| 3026 | if (ocfs2_is_empty_extent(&el->l_recs[0])) | ||
| 3027 | has_empty_extent = 1; | ||
| 3028 | } | ||
| 2778 | 3029 | ||
| 2779 | ret = ocfs2_journal_access(handle, inode, bh, | 3030 | ret = ocfs2_journal_access(handle, inode, bh, |
| 2780 | OCFS2_JOURNAL_ACCESS_WRITE); | 3031 | OCFS2_JOURNAL_ACCESS_WRITE); |
| @@ -2790,9 +3041,8 @@ static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh, | |||
| 2790 | *left_rec = *split_rec; | 3041 | *left_rec = *split_rec; |
| 2791 | 3042 | ||
| 2792 | has_empty_extent = 0; | 3043 | has_empty_extent = 0; |
| 2793 | } else { | 3044 | } else |
| 2794 | le16_add_cpu(&left_rec->e_leaf_clusters, split_clusters); | 3045 | le16_add_cpu(&left_rec->e_leaf_clusters, split_clusters); |
| 2795 | } | ||
| 2796 | 3046 | ||
| 2797 | le32_add_cpu(&right_rec->e_cpos, split_clusters); | 3047 | le32_add_cpu(&right_rec->e_cpos, split_clusters); |
| 2798 | le64_add_cpu(&right_rec->e_blkno, | 3048 | le64_add_cpu(&right_rec->e_blkno, |
| @@ -2805,13 +3055,44 @@ static int ocfs2_merge_rec_left(struct inode *inode, struct buffer_head *bh, | |||
| 2805 | if (ret) | 3055 | if (ret) |
| 2806 | mlog_errno(ret); | 3056 | mlog_errno(ret); |
| 2807 | 3057 | ||
| 3058 | if (left_path) { | ||
| 3059 | ret = ocfs2_journal_dirty(handle, path_leaf_bh(left_path)); | ||
| 3060 | if (ret) | ||
| 3061 | mlog_errno(ret); | ||
| 3062 | |||
| 3063 | /* | ||
| 3064 | * In the situation that the right_rec is empty and the extent | ||
| 3065 | * block is empty also, ocfs2_complete_edge_insert can't handle | ||
| 3066 | * it and we need to delete the right extent block. | ||
| 3067 | */ | ||
| 3068 | if (le16_to_cpu(right_rec->e_leaf_clusters) == 0 && | ||
| 3069 | le16_to_cpu(el->l_next_free_rec) == 1) { | ||
| 3070 | |||
| 3071 | ret = ocfs2_remove_rightmost_path(inode, handle, | ||
| 3072 | right_path, dealloc); | ||
| 3073 | if (ret) { | ||
| 3074 | mlog_errno(ret); | ||
| 3075 | goto out; | ||
| 3076 | } | ||
| 3077 | |||
| 3078 | /* Now the rightmost extent block has been deleted. | ||
| 3079 | * So we use the new rightmost path. | ||
| 3080 | */ | ||
| 3081 | ocfs2_mv_path(right_path, left_path); | ||
| 3082 | left_path = NULL; | ||
| 3083 | } else | ||
| 3084 | ocfs2_complete_edge_insert(inode, handle, left_path, | ||
| 3085 | right_path, subtree_index); | ||
| 3086 | } | ||
| 2808 | out: | 3087 | out: |
| 3088 | if (left_path) | ||
| 3089 | ocfs2_free_path(left_path); | ||
| 2809 | return ret; | 3090 | return ret; |
| 2810 | } | 3091 | } |
| 2811 | 3092 | ||
| 2812 | static int ocfs2_try_to_merge_extent(struct inode *inode, | 3093 | static int ocfs2_try_to_merge_extent(struct inode *inode, |
| 2813 | handle_t *handle, | 3094 | handle_t *handle, |
| 2814 | struct ocfs2_path *left_path, | 3095 | struct ocfs2_path *path, |
| 2815 | int split_index, | 3096 | int split_index, |
| 2816 | struct ocfs2_extent_rec *split_rec, | 3097 | struct ocfs2_extent_rec *split_rec, |
| 2817 | struct ocfs2_cached_dealloc_ctxt *dealloc, | 3098 | struct ocfs2_cached_dealloc_ctxt *dealloc, |
| @@ -2819,7 +3100,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode, | |||
| 2819 | 3100 | ||
| 2820 | { | 3101 | { |
| 2821 | int ret = 0; | 3102 | int ret = 0; |
| 2822 | struct ocfs2_extent_list *el = path_leaf_el(left_path); | 3103 | struct ocfs2_extent_list *el = path_leaf_el(path); |
| 2823 | struct ocfs2_extent_rec *rec = &el->l_recs[split_index]; | 3104 | struct ocfs2_extent_rec *rec = &el->l_recs[split_index]; |
| 2824 | 3105 | ||
| 2825 | BUG_ON(ctxt->c_contig_type == CONTIG_NONE); | 3106 | BUG_ON(ctxt->c_contig_type == CONTIG_NONE); |
| @@ -2832,7 +3113,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode, | |||
| 2832 | * extents - having more than one in a leaf is | 3113 | * extents - having more than one in a leaf is |
| 2833 | * illegal. | 3114 | * illegal. |
| 2834 | */ | 3115 | */ |
| 2835 | ret = ocfs2_rotate_tree_left(inode, handle, left_path, | 3116 | ret = ocfs2_rotate_tree_left(inode, handle, path, |
| 2836 | dealloc); | 3117 | dealloc); |
| 2837 | if (ret) { | 3118 | if (ret) { |
| 2838 | mlog_errno(ret); | 3119 | mlog_errno(ret); |
| @@ -2847,7 +3128,6 @@ static int ocfs2_try_to_merge_extent(struct inode *inode, | |||
| 2847 | * Left-right contig implies this. | 3128 | * Left-right contig implies this. |
| 2848 | */ | 3129 | */ |
| 2849 | BUG_ON(!ctxt->c_split_covers_rec); | 3130 | BUG_ON(!ctxt->c_split_covers_rec); |
| 2850 | BUG_ON(split_index == 0); | ||
| 2851 | 3131 | ||
| 2852 | /* | 3132 | /* |
| 2853 | * Since the leftright insert always covers the entire | 3133 | * Since the leftright insert always covers the entire |
| @@ -2858,9 +3138,14 @@ static int ocfs2_try_to_merge_extent(struct inode *inode, | |||
| 2858 | * Since the adding of an empty extent shifts | 3138 | * Since the adding of an empty extent shifts |
| 2859 | * everything back to the right, there's no need to | 3139 | * everything back to the right, there's no need to |
| 2860 | * update split_index here. | 3140 | * update split_index here. |
| 3141 | * | ||
| 3142 | * When the split_index is zero, we need to merge it to the | ||
| 3143 | * prevoius extent block. It is more efficient and easier | ||
| 3144 | * if we do merge_right first and merge_left later. | ||
| 2861 | */ | 3145 | */ |
| 2862 | ret = ocfs2_merge_rec_left(inode, path_leaf_bh(left_path), | 3146 | ret = ocfs2_merge_rec_right(inode, path, |
| 2863 | handle, split_rec, el, split_index); | 3147 | handle, split_rec, |
| 3148 | split_index); | ||
| 2864 | if (ret) { | 3149 | if (ret) { |
| 2865 | mlog_errno(ret); | 3150 | mlog_errno(ret); |
| 2866 | goto out; | 3151 | goto out; |
| @@ -2871,32 +3156,30 @@ static int ocfs2_try_to_merge_extent(struct inode *inode, | |||
| 2871 | */ | 3156 | */ |
| 2872 | BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0])); | 3157 | BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0])); |
| 2873 | 3158 | ||
| 2874 | /* | 3159 | /* The merge left us with an empty extent, remove it. */ |
| 2875 | * The left merge left us with an empty extent, remove | 3160 | ret = ocfs2_rotate_tree_left(inode, handle, path, dealloc); |
| 2876 | * it. | ||
| 2877 | */ | ||
| 2878 | ret = ocfs2_rotate_tree_left(inode, handle, left_path, dealloc); | ||
| 2879 | if (ret) { | 3161 | if (ret) { |
| 2880 | mlog_errno(ret); | 3162 | mlog_errno(ret); |
| 2881 | goto out; | 3163 | goto out; |
| 2882 | } | 3164 | } |
| 2883 | split_index--; | 3165 | |
| 2884 | rec = &el->l_recs[split_index]; | 3166 | rec = &el->l_recs[split_index]; |
| 2885 | 3167 | ||
| 2886 | /* | 3168 | /* |
| 2887 | * Note that we don't pass split_rec here on purpose - | 3169 | * Note that we don't pass split_rec here on purpose - |
| 2888 | * we've merged it into the left side. | 3170 | * we've merged it into the rec already. |
| 2889 | */ | 3171 | */ |
| 2890 | ret = ocfs2_merge_rec_right(inode, path_leaf_bh(left_path), | 3172 | ret = ocfs2_merge_rec_left(inode, path, |
| 2891 | handle, rec, el, split_index); | 3173 | handle, rec, |
| 3174 | dealloc, | ||
| 3175 | split_index); | ||
| 3176 | |||
| 2892 | if (ret) { | 3177 | if (ret) { |
| 2893 | mlog_errno(ret); | 3178 | mlog_errno(ret); |
| 2894 | goto out; | 3179 | goto out; |
| 2895 | } | 3180 | } |
| 2896 | 3181 | ||
| 2897 | BUG_ON(!ocfs2_is_empty_extent(&el->l_recs[0])); | 3182 | ret = ocfs2_rotate_tree_left(inode, handle, path, |
| 2898 | |||
| 2899 | ret = ocfs2_rotate_tree_left(inode, handle, left_path, | ||
| 2900 | dealloc); | 3183 | dealloc); |
| 2901 | /* | 3184 | /* |
| 2902 | * Error from this last rotate is not critical, so | 3185 | * Error from this last rotate is not critical, so |
| @@ -2915,8 +3198,9 @@ static int ocfs2_try_to_merge_extent(struct inode *inode, | |||
| 2915 | */ | 3198 | */ |
| 2916 | if (ctxt->c_contig_type == CONTIG_RIGHT) { | 3199 | if (ctxt->c_contig_type == CONTIG_RIGHT) { |
| 2917 | ret = ocfs2_merge_rec_left(inode, | 3200 | ret = ocfs2_merge_rec_left(inode, |
| 2918 | path_leaf_bh(left_path), | 3201 | path, |
| 2919 | handle, split_rec, el, | 3202 | handle, split_rec, |
| 3203 | dealloc, | ||
| 2920 | split_index); | 3204 | split_index); |
| 2921 | if (ret) { | 3205 | if (ret) { |
| 2922 | mlog_errno(ret); | 3206 | mlog_errno(ret); |
| @@ -2924,8 +3208,8 @@ static int ocfs2_try_to_merge_extent(struct inode *inode, | |||
| 2924 | } | 3208 | } |
| 2925 | } else { | 3209 | } else { |
| 2926 | ret = ocfs2_merge_rec_right(inode, | 3210 | ret = ocfs2_merge_rec_right(inode, |
| 2927 | path_leaf_bh(left_path), | 3211 | path, |
| 2928 | handle, split_rec, el, | 3212 | handle, split_rec, |
| 2929 | split_index); | 3213 | split_index); |
| 2930 | if (ret) { | 3214 | if (ret) { |
| 2931 | mlog_errno(ret); | 3215 | mlog_errno(ret); |
| @@ -2938,7 +3222,7 @@ static int ocfs2_try_to_merge_extent(struct inode *inode, | |||
| 2938 | * The merge may have left an empty extent in | 3222 | * The merge may have left an empty extent in |
| 2939 | * our leaf. Try to rotate it away. | 3223 | * our leaf. Try to rotate it away. |
| 2940 | */ | 3224 | */ |
| 2941 | ret = ocfs2_rotate_tree_left(inode, handle, left_path, | 3225 | ret = ocfs2_rotate_tree_left(inode, handle, path, |
| 2942 | dealloc); | 3226 | dealloc); |
| 2943 | if (ret) | 3227 | if (ret) |
| 2944 | mlog_errno(ret); | 3228 | mlog_errno(ret); |
