diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ocfs2/refcounttree.c | 127 |
1 files changed, 71 insertions, 56 deletions
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 62d21c6ce1d9..40de7bb9e9a6 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
@@ -45,12 +45,20 @@ struct ocfs2_cow_context { | |||
45 | struct inode *inode; | 45 | struct inode *inode; |
46 | u32 cow_start; | 46 | u32 cow_start; |
47 | u32 cow_len; | 47 | u32 cow_len; |
48 | struct ocfs2_extent_tree di_et; | 48 | struct ocfs2_extent_tree data_et; |
49 | struct ocfs2_caching_info *ref_ci; | 49 | struct ocfs2_refcount_tree *ref_tree; |
50 | struct buffer_head *ref_root_bh; | 50 | struct buffer_head *ref_root_bh; |
51 | struct ocfs2_alloc_context *meta_ac; | 51 | struct ocfs2_alloc_context *meta_ac; |
52 | struct ocfs2_alloc_context *data_ac; | 52 | struct ocfs2_alloc_context *data_ac; |
53 | struct ocfs2_cached_dealloc_ctxt dealloc; | 53 | struct ocfs2_cached_dealloc_ctxt dealloc; |
54 | int (*get_clusters)(struct ocfs2_cow_context *context, | ||
55 | u32 v_cluster, u32 *p_cluster, | ||
56 | u32 *num_clusters, | ||
57 | unsigned int *extent_flags); | ||
58 | int (*cow_duplicate_clusters)(handle_t *handle, | ||
59 | struct ocfs2_cow_context *context, | ||
60 | u32 cpos, u32 old_cluster, | ||
61 | u32 new_cluster, u32 new_len); | ||
54 | }; | 62 | }; |
55 | 63 | ||
56 | static inline struct ocfs2_refcount_tree * | 64 | static inline struct ocfs2_refcount_tree * |
@@ -2489,7 +2497,7 @@ static inline unsigned int ocfs2_cow_align_length(struct super_block *sb, | |||
2489 | * get good I/O from the resulting extent tree. | 2497 | * get good I/O from the resulting extent tree. |
2490 | */ | 2498 | */ |
2491 | static int ocfs2_refcount_cal_cow_clusters(struct inode *inode, | 2499 | static int ocfs2_refcount_cal_cow_clusters(struct inode *inode, |
2492 | struct buffer_head *di_bh, | 2500 | struct ocfs2_extent_list *el, |
2493 | u32 cpos, | 2501 | u32 cpos, |
2494 | u32 write_len, | 2502 | u32 write_len, |
2495 | u32 max_cpos, | 2503 | u32 max_cpos, |
@@ -2497,8 +2505,6 @@ static int ocfs2_refcount_cal_cow_clusters(struct inode *inode, | |||
2497 | u32 *cow_len) | 2505 | u32 *cow_len) |
2498 | { | 2506 | { |
2499 | int ret = 0; | 2507 | int ret = 0; |
2500 | struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data; | ||
2501 | struct ocfs2_extent_list *el = &di->id2.i_list; | ||
2502 | int tree_height = le16_to_cpu(el->l_tree_depth), i; | 2508 | int tree_height = le16_to_cpu(el->l_tree_depth), i; |
2503 | struct buffer_head *eb_bh = NULL; | 2509 | struct buffer_head *eb_bh = NULL; |
2504 | struct ocfs2_extent_block *eb = NULL; | 2510 | struct ocfs2_extent_block *eb = NULL; |
@@ -2769,13 +2775,13 @@ static int ocfs2_clear_cow_buffer(handle_t *handle, struct buffer_head *bh) | |||
2769 | return 0; | 2775 | return 0; |
2770 | } | 2776 | } |
2771 | 2777 | ||
2772 | static int ocfs2_duplicate_clusters(handle_t *handle, | 2778 | static int ocfs2_duplicate_clusters_by_page(handle_t *handle, |
2773 | struct ocfs2_cow_context *context, | 2779 | struct ocfs2_cow_context *context, |
2774 | u32 cpos, u32 old_cluster, | 2780 | u32 cpos, u32 old_cluster, |
2775 | u32 new_cluster, u32 new_len) | 2781 | u32 new_cluster, u32 new_len) |
2776 | { | 2782 | { |
2777 | int ret = 0, partial; | 2783 | int ret = 0, partial; |
2778 | struct ocfs2_caching_info *ci = context->di_et.et_ci; | 2784 | struct ocfs2_caching_info *ci = context->data_et.et_ci; |
2779 | struct super_block *sb = ocfs2_metadata_cache_get_super(ci); | 2785 | struct super_block *sb = ocfs2_metadata_cache_get_super(ci); |
2780 | u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster); | 2786 | u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster); |
2781 | struct page *page; | 2787 | struct page *page; |
@@ -2909,7 +2915,7 @@ static int ocfs2_replace_clusters(handle_t *handle, | |||
2909 | unsigned int ext_flags) | 2915 | unsigned int ext_flags) |
2910 | { | 2916 | { |
2911 | int ret; | 2917 | int ret; |
2912 | struct ocfs2_caching_info *ci = context->di_et.et_ci; | 2918 | struct ocfs2_caching_info *ci = context->data_et.et_ci; |
2913 | u64 ino = ocfs2_metadata_cache_owner(ci); | 2919 | u64 ino = ocfs2_metadata_cache_owner(ci); |
2914 | 2920 | ||
2915 | mlog(0, "inode %llu, cpos %u, old %u, new %u, len %u, ext_flags %u\n", | 2921 | mlog(0, "inode %llu, cpos %u, old %u, new %u, len %u, ext_flags %u\n", |
@@ -2917,15 +2923,15 @@ static int ocfs2_replace_clusters(handle_t *handle, | |||
2917 | 2923 | ||
2918 | /*If the old clusters is unwritten, no need to duplicate. */ | 2924 | /*If the old clusters is unwritten, no need to duplicate. */ |
2919 | if (!(ext_flags & OCFS2_EXT_UNWRITTEN)) { | 2925 | if (!(ext_flags & OCFS2_EXT_UNWRITTEN)) { |
2920 | ret = ocfs2_duplicate_clusters(handle, context, cpos, | 2926 | ret = context->cow_duplicate_clusters(handle, context, cpos, |
2921 | old, new, len); | 2927 | old, new, len); |
2922 | if (ret) { | 2928 | if (ret) { |
2923 | mlog_errno(ret); | 2929 | mlog_errno(ret); |
2924 | goto out; | 2930 | goto out; |
2925 | } | 2931 | } |
2926 | } | 2932 | } |
2927 | 2933 | ||
2928 | ret = ocfs2_clear_ext_refcount(handle, &context->di_et, | 2934 | ret = ocfs2_clear_ext_refcount(handle, &context->data_et, |
2929 | cpos, new, len, ext_flags, | 2935 | cpos, new, len, ext_flags, |
2930 | context->meta_ac, &context->dealloc); | 2936 | context->meta_ac, &context->dealloc); |
2931 | if (ret) | 2937 | if (ret) |
@@ -2983,6 +2989,15 @@ static int ocfs2_cow_sync_writeback(struct super_block *sb, | |||
2983 | return ret; | 2989 | return ret; |
2984 | } | 2990 | } |
2985 | 2991 | ||
2992 | static int ocfs2_di_get_clusters(struct ocfs2_cow_context *context, | ||
2993 | u32 v_cluster, u32 *p_cluster, | ||
2994 | u32 *num_clusters, | ||
2995 | unsigned int *extent_flags) | ||
2996 | { | ||
2997 | return ocfs2_get_clusters(context->inode, v_cluster, p_cluster, | ||
2998 | num_clusters, extent_flags); | ||
2999 | } | ||
3000 | |||
2986 | static int ocfs2_make_clusters_writable(struct super_block *sb, | 3001 | static int ocfs2_make_clusters_writable(struct super_block *sb, |
2987 | struct ocfs2_cow_context *context, | 3002 | struct ocfs2_cow_context *context, |
2988 | u32 cpos, u32 p_cluster, | 3003 | u32 cpos, u32 p_cluster, |
@@ -2994,14 +3009,15 @@ static int ocfs2_make_clusters_writable(struct super_block *sb, | |||
2994 | struct ocfs2_super *osb = OCFS2_SB(sb); | 3009 | struct ocfs2_super *osb = OCFS2_SB(sb); |
2995 | handle_t *handle; | 3010 | handle_t *handle; |
2996 | struct buffer_head *ref_leaf_bh = NULL; | 3011 | struct buffer_head *ref_leaf_bh = NULL; |
3012 | struct ocfs2_caching_info *ref_ci = &context->ref_tree->rf_ci; | ||
2997 | struct ocfs2_refcount_rec rec; | 3013 | struct ocfs2_refcount_rec rec; |
2998 | 3014 | ||
2999 | mlog(0, "cpos %u, p_cluster %u, num_clusters %u, e_flags %u\n", | 3015 | mlog(0, "cpos %u, p_cluster %u, num_clusters %u, e_flags %u\n", |
3000 | cpos, p_cluster, num_clusters, e_flags); | 3016 | cpos, p_cluster, num_clusters, e_flags); |
3001 | 3017 | ||
3002 | ret = ocfs2_lock_refcount_allocators(sb, p_cluster, num_clusters, | 3018 | ret = ocfs2_lock_refcount_allocators(sb, p_cluster, num_clusters, |
3003 | &context->di_et, | 3019 | &context->data_et, |
3004 | context->ref_ci, | 3020 | ref_ci, |
3005 | context->ref_root_bh, | 3021 | context->ref_root_bh, |
3006 | &context->meta_ac, | 3022 | &context->meta_ac, |
3007 | &context->data_ac, &credits); | 3023 | &context->data_ac, &credits); |
@@ -3018,8 +3034,7 @@ static int ocfs2_make_clusters_writable(struct super_block *sb, | |||
3018 | } | 3034 | } |
3019 | 3035 | ||
3020 | while (num_clusters) { | 3036 | while (num_clusters) { |
3021 | ret = ocfs2_get_refcount_rec(context->ref_ci, | 3037 | ret = ocfs2_get_refcount_rec(ref_ci, context->ref_root_bh, |
3022 | context->ref_root_bh, | ||
3023 | p_cluster, num_clusters, | 3038 | p_cluster, num_clusters, |
3024 | &rec, &index, &ref_leaf_bh); | 3039 | &rec, &index, &ref_leaf_bh); |
3025 | if (ret) { | 3040 | if (ret) { |
@@ -3041,7 +3056,8 @@ static int ocfs2_make_clusters_writable(struct super_block *sb, | |||
3041 | */ | 3056 | */ |
3042 | if (le32_to_cpu(rec.r_refcount) == 1) { | 3057 | if (le32_to_cpu(rec.r_refcount) == 1) { |
3043 | delete = 0; | 3058 | delete = 0; |
3044 | ret = ocfs2_clear_ext_refcount(handle, &context->di_et, | 3059 | ret = ocfs2_clear_ext_refcount(handle, |
3060 | &context->data_et, | ||
3045 | cpos, p_cluster, | 3061 | cpos, p_cluster, |
3046 | set_len, e_flags, | 3062 | set_len, e_flags, |
3047 | context->meta_ac, | 3063 | context->meta_ac, |
@@ -3072,7 +3088,7 @@ static int ocfs2_make_clusters_writable(struct super_block *sb, | |||
3072 | set_len = new_len; | 3088 | set_len = new_len; |
3073 | } | 3089 | } |
3074 | 3090 | ||
3075 | ret = __ocfs2_decrease_refcount(handle, context->ref_ci, | 3091 | ret = __ocfs2_decrease_refcount(handle, ref_ci, |
3076 | context->ref_root_bh, | 3092 | context->ref_root_bh, |
3077 | p_cluster, set_len, | 3093 | p_cluster, set_len, |
3078 | context->meta_ac, | 3094 | context->meta_ac, |
@@ -3114,17 +3130,14 @@ out: | |||
3114 | return ret; | 3130 | return ret; |
3115 | } | 3131 | } |
3116 | 3132 | ||
3117 | static int ocfs2_replace_cow(struct inode *inode, | 3133 | static int ocfs2_replace_cow(struct ocfs2_cow_context *context) |
3118 | struct buffer_head *di_bh, | ||
3119 | struct buffer_head *ref_root_bh, | ||
3120 | struct ocfs2_caching_info *ref_ci, | ||
3121 | u32 cow_start, u32 cow_len) | ||
3122 | { | 3134 | { |
3123 | int ret = 0; | 3135 | int ret = 0; |
3124 | u32 p_cluster, num_clusters, start = cow_start; | 3136 | struct inode *inode = context->inode; |
3137 | u32 cow_start = context->cow_start, cow_len = context->cow_len; | ||
3138 | u32 p_cluster, num_clusters; | ||
3125 | unsigned int ext_flags; | 3139 | unsigned int ext_flags; |
3126 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 3140 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
3127 | struct ocfs2_cow_context *context; | ||
3128 | 3141 | ||
3129 | if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) { | 3142 | if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) { |
3130 | ocfs2_error(inode->i_sb, "Inode %lu want to use refcount " | 3143 | ocfs2_error(inode->i_sb, "Inode %lu want to use refcount " |
@@ -3133,26 +3146,11 @@ static int ocfs2_replace_cow(struct inode *inode, | |||
3133 | return -EROFS; | 3146 | return -EROFS; |
3134 | } | 3147 | } |
3135 | 3148 | ||
3136 | context = kzalloc(sizeof(struct ocfs2_cow_context), GFP_NOFS); | ||
3137 | if (!context) { | ||
3138 | ret = -ENOMEM; | ||
3139 | mlog_errno(ret); | ||
3140 | return ret; | ||
3141 | } | ||
3142 | |||
3143 | context->inode = inode; | ||
3144 | context->cow_start = cow_start; | ||
3145 | context->cow_len = cow_len; | ||
3146 | context->ref_ci = ref_ci; | ||
3147 | context->ref_root_bh = ref_root_bh; | ||
3148 | |||
3149 | ocfs2_init_dealloc_ctxt(&context->dealloc); | 3149 | ocfs2_init_dealloc_ctxt(&context->dealloc); |
3150 | ocfs2_init_dinode_extent_tree(&context->di_et, | ||
3151 | INODE_CACHE(inode), di_bh); | ||
3152 | 3150 | ||
3153 | while (cow_len) { | 3151 | while (cow_len) { |
3154 | ret = ocfs2_get_clusters(inode, cow_start, &p_cluster, | 3152 | ret = context->get_clusters(context, cow_start, &p_cluster, |
3155 | &num_clusters, &ext_flags); | 3153 | &num_clusters, &ext_flags); |
3156 | if (ret) { | 3154 | if (ret) { |
3157 | mlog_errno(ret); | 3155 | mlog_errno(ret); |
3158 | break; | 3156 | break; |
@@ -3175,20 +3173,11 @@ static int ocfs2_replace_cow(struct inode *inode, | |||
3175 | cow_start += num_clusters; | 3173 | cow_start += num_clusters; |
3176 | } | 3174 | } |
3177 | 3175 | ||
3178 | |||
3179 | /* | ||
3180 | * truncate the extent map here since no matter whether we meet with | ||
3181 | * any error during the action, we shouldn't trust cached extent map | ||
3182 | * any more. | ||
3183 | */ | ||
3184 | ocfs2_extent_map_trunc(inode, start); | ||
3185 | |||
3186 | if (ocfs2_dealloc_has_cluster(&context->dealloc)) { | 3176 | if (ocfs2_dealloc_has_cluster(&context->dealloc)) { |
3187 | ocfs2_schedule_truncate_log_flush(osb, 1); | 3177 | ocfs2_schedule_truncate_log_flush(osb, 1); |
3188 | ocfs2_run_deallocs(osb, &context->dealloc); | 3178 | ocfs2_run_deallocs(osb, &context->dealloc); |
3189 | } | 3179 | } |
3190 | 3180 | ||
3191 | kfree(context); | ||
3192 | return ret; | 3181 | return ret; |
3193 | } | 3182 | } |
3194 | 3183 | ||
@@ -3208,10 +3197,11 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, | |||
3208 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | 3197 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; |
3209 | struct buffer_head *ref_root_bh = NULL; | 3198 | struct buffer_head *ref_root_bh = NULL; |
3210 | struct ocfs2_refcount_tree *ref_tree; | 3199 | struct ocfs2_refcount_tree *ref_tree; |
3200 | struct ocfs2_cow_context *context = NULL; | ||
3211 | 3201 | ||
3212 | BUG_ON(!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL)); | 3202 | BUG_ON(!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL)); |
3213 | 3203 | ||
3214 | ret = ocfs2_refcount_cal_cow_clusters(inode, di_bh, | 3204 | ret = ocfs2_refcount_cal_cow_clusters(inode, &di->id2.i_list, |
3215 | cpos, write_len, max_cpos, | 3205 | cpos, write_len, max_cpos, |
3216 | &cow_start, &cow_len); | 3206 | &cow_start, &cow_len); |
3217 | if (ret) { | 3207 | if (ret) { |
@@ -3225,6 +3215,13 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, | |||
3225 | 3215 | ||
3226 | BUG_ON(cow_len == 0); | 3216 | BUG_ON(cow_len == 0); |
3227 | 3217 | ||
3218 | context = kzalloc(sizeof(struct ocfs2_cow_context), GFP_NOFS); | ||
3219 | if (!context) { | ||
3220 | ret = -ENOMEM; | ||
3221 | mlog_errno(ret); | ||
3222 | goto out; | ||
3223 | } | ||
3224 | |||
3228 | ret = ocfs2_lock_refcount_tree(osb, le64_to_cpu(di->i_refcount_loc), | 3225 | ret = ocfs2_lock_refcount_tree(osb, le64_to_cpu(di->i_refcount_loc), |
3229 | 1, &ref_tree, &ref_root_bh); | 3226 | 1, &ref_tree, &ref_root_bh); |
3230 | if (ret) { | 3227 | if (ret) { |
@@ -3232,14 +3229,32 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, | |||
3232 | goto out; | 3229 | goto out; |
3233 | } | 3230 | } |
3234 | 3231 | ||
3235 | ret = ocfs2_replace_cow(inode, di_bh, ref_root_bh, &ref_tree->rf_ci, | 3232 | context->inode = inode; |
3236 | cow_start, cow_len); | 3233 | context->cow_start = cow_start; |
3234 | context->cow_len = cow_len; | ||
3235 | context->ref_tree = ref_tree; | ||
3236 | context->ref_root_bh = ref_root_bh; | ||
3237 | context->cow_duplicate_clusters = ocfs2_duplicate_clusters_by_page; | ||
3238 | context->get_clusters = ocfs2_di_get_clusters; | ||
3239 | |||
3240 | ocfs2_init_dinode_extent_tree(&context->data_et, | ||
3241 | INODE_CACHE(inode), di_bh); | ||
3242 | |||
3243 | ret = ocfs2_replace_cow(context); | ||
3237 | if (ret) | 3244 | if (ret) |
3238 | mlog_errno(ret); | 3245 | mlog_errno(ret); |
3239 | 3246 | ||
3247 | /* | ||
3248 | * truncate the extent map here since no matter whether we meet with | ||
3249 | * any error during the action, we shouldn't trust cached extent map | ||
3250 | * any more. | ||
3251 | */ | ||
3252 | ocfs2_extent_map_trunc(inode, cow_start); | ||
3253 | |||
3240 | ocfs2_unlock_refcount_tree(osb, ref_tree, 1); | 3254 | ocfs2_unlock_refcount_tree(osb, ref_tree, 1); |
3241 | brelse(ref_root_bh); | 3255 | brelse(ref_root_bh); |
3242 | out: | 3256 | out: |
3257 | kfree(context); | ||
3243 | return ret; | 3258 | return ret; |
3244 | } | 3259 | } |
3245 | 3260 | ||