diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ocfs2/alloc.c | 94 |
1 files changed, 86 insertions, 8 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index f63cb32e224d..7d81aa6f5672 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -3782,20 +3782,57 @@ out: | |||
3782 | } | 3782 | } |
3783 | 3783 | ||
3784 | static enum ocfs2_contig_type | 3784 | static enum ocfs2_contig_type |
3785 | ocfs2_figure_merge_contig_type(struct inode *inode, | 3785 | ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path, |
3786 | struct ocfs2_extent_list *el, int index, | 3786 | struct ocfs2_extent_list *el, int index, |
3787 | struct ocfs2_extent_rec *split_rec) | 3787 | struct ocfs2_extent_rec *split_rec) |
3788 | { | 3788 | { |
3789 | struct ocfs2_extent_rec *rec; | 3789 | int status; |
3790 | enum ocfs2_contig_type ret = CONTIG_NONE; | 3790 | enum ocfs2_contig_type ret = CONTIG_NONE; |
3791 | u32 left_cpos, right_cpos; | ||
3792 | struct ocfs2_extent_rec *rec = NULL; | ||
3793 | struct ocfs2_extent_list *new_el; | ||
3794 | struct ocfs2_path *left_path = NULL, *right_path = NULL; | ||
3795 | struct buffer_head *bh; | ||
3796 | struct ocfs2_extent_block *eb; | ||
3797 | |||
3798 | if (index > 0) { | ||
3799 | rec = &el->l_recs[index - 1]; | ||
3800 | } else if (path->p_tree_depth > 0) { | ||
3801 | status = ocfs2_find_cpos_for_left_leaf(inode->i_sb, | ||
3802 | path, &left_cpos); | ||
3803 | if (status) | ||
3804 | goto out; | ||
3805 | |||
3806 | if (left_cpos != 0) { | ||
3807 | left_path = ocfs2_new_path(path_root_bh(path), | ||
3808 | path_root_el(path)); | ||
3809 | if (!left_path) | ||
3810 | goto out; | ||
3811 | |||
3812 | status = ocfs2_find_path(inode, left_path, left_cpos); | ||
3813 | if (status) | ||
3814 | goto out; | ||
3815 | |||
3816 | new_el = path_leaf_el(left_path); | ||
3817 | |||
3818 | if (le16_to_cpu(new_el->l_next_free_rec) != | ||
3819 | le16_to_cpu(new_el->l_count)) { | ||
3820 | bh = path_leaf_bh(left_path); | ||
3821 | eb = (struct ocfs2_extent_block *)bh->b_data; | ||
3822 | OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, | ||
3823 | eb); | ||
3824 | goto out; | ||
3825 | } | ||
3826 | rec = &new_el->l_recs[ | ||
3827 | le16_to_cpu(new_el->l_next_free_rec) - 1]; | ||
3828 | } | ||
3829 | } | ||
3791 | 3830 | ||
3792 | /* | 3831 | /* |
3793 | * We're careful to check for an empty extent record here - | 3832 | * We're careful to check for an empty extent record here - |
3794 | * the merge code will know what to do if it sees one. | 3833 | * the merge code will know what to do if it sees one. |
3795 | */ | 3834 | */ |
3796 | 3835 | if (rec) { | |
3797 | if (index > 0) { | ||
3798 | rec = &el->l_recs[index - 1]; | ||
3799 | if (index == 1 && ocfs2_is_empty_extent(rec)) { | 3836 | if (index == 1 && ocfs2_is_empty_extent(rec)) { |
3800 | if (split_rec->e_cpos == el->l_recs[index].e_cpos) | 3837 | if (split_rec->e_cpos == el->l_recs[index].e_cpos) |
3801 | ret = CONTIG_RIGHT; | 3838 | ret = CONTIG_RIGHT; |
@@ -3804,10 +3841,45 @@ ocfs2_figure_merge_contig_type(struct inode *inode, | |||
3804 | } | 3841 | } |
3805 | } | 3842 | } |
3806 | 3843 | ||
3807 | if (index < (le16_to_cpu(el->l_next_free_rec) - 1)) { | 3844 | rec = NULL; |
3845 | if (index < (le16_to_cpu(el->l_next_free_rec) - 1)) | ||
3846 | rec = &el->l_recs[index + 1]; | ||
3847 | else if (le16_to_cpu(el->l_next_free_rec) == le16_to_cpu(el->l_count) && | ||
3848 | path->p_tree_depth > 0) { | ||
3849 | status = ocfs2_find_cpos_for_right_leaf(inode->i_sb, | ||
3850 | path, &right_cpos); | ||
3851 | if (status) | ||
3852 | goto out; | ||
3853 | |||
3854 | if (right_cpos == 0) | ||
3855 | goto out; | ||
3856 | |||
3857 | right_path = ocfs2_new_path(path_root_bh(path), | ||
3858 | path_root_el(path)); | ||
3859 | if (!right_path) | ||
3860 | goto out; | ||
3861 | |||
3862 | status = ocfs2_find_path(inode, right_path, right_cpos); | ||
3863 | if (status) | ||
3864 | goto out; | ||
3865 | |||
3866 | new_el = path_leaf_el(right_path); | ||
3867 | rec = &new_el->l_recs[0]; | ||
3868 | if (ocfs2_is_empty_extent(rec)) { | ||
3869 | if (le16_to_cpu(new_el->l_next_free_rec) <= 1) { | ||
3870 | bh = path_leaf_bh(right_path); | ||
3871 | eb = (struct ocfs2_extent_block *)bh->b_data; | ||
3872 | OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, | ||
3873 | eb); | ||
3874 | goto out; | ||
3875 | } | ||
3876 | rec = &new_el->l_recs[1]; | ||
3877 | } | ||
3878 | } | ||
3879 | |||
3880 | if (rec) { | ||
3808 | enum ocfs2_contig_type contig_type; | 3881 | enum ocfs2_contig_type contig_type; |
3809 | 3882 | ||
3810 | rec = &el->l_recs[index + 1]; | ||
3811 | contig_type = ocfs2_extent_contig(inode, rec, split_rec); | 3883 | contig_type = ocfs2_extent_contig(inode, rec, split_rec); |
3812 | 3884 | ||
3813 | if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT) | 3885 | if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT) |
@@ -3816,6 +3888,12 @@ ocfs2_figure_merge_contig_type(struct inode *inode, | |||
3816 | ret = contig_type; | 3888 | ret = contig_type; |
3817 | } | 3889 | } |
3818 | 3890 | ||
3891 | out: | ||
3892 | if (left_path) | ||
3893 | ocfs2_free_path(left_path); | ||
3894 | if (right_path) | ||
3895 | ocfs2_free_path(right_path); | ||
3896 | |||
3819 | return ret; | 3897 | return ret; |
3820 | } | 3898 | } |
3821 | 3899 | ||
@@ -4278,7 +4356,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode, | |||
4278 | goto out; | 4356 | goto out; |
4279 | } | 4357 | } |
4280 | 4358 | ||
4281 | ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, el, | 4359 | ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, path, el, |
4282 | split_index, | 4360 | split_index, |
4283 | split_rec); | 4361 | split_rec); |
4284 | 4362 | ||