aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/refcounttree.c
diff options
context:
space:
mode:
authorTao Ma <tao.ma@oracle.com>2009-08-24 02:31:03 -0400
committerJoel Becker <joel.becker@oracle.com>2009-09-22 23:09:40 -0400
commit913580b4cd445c4fb25d7cf167911a8cf6bdb1eb (patch)
tree24ad6cb14d27f101863035029eb8cea0ee8ed361 /fs/ocfs2/refcounttree.c
parent1061f9c1c9f81ed88b5d268a95d8e3ace80da63a (diff)
ocfs2: Abstract duplicate clusters process in CoW.
We currently use pagecache to duplicate clusters in CoW, but it isn't suitable for xattr case. So abstract it out so that the caller can decide which method it use. Signed-off-by: Tao Ma <tao.ma@oracle.com>
Diffstat (limited to 'fs/ocfs2/refcounttree.c')
-rw-r--r--fs/ocfs2/refcounttree.c127
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
56static inline struct ocfs2_refcount_tree * 64static 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 */
2491static int ocfs2_refcount_cal_cow_clusters(struct inode *inode, 2499static 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
2772static int ocfs2_duplicate_clusters(handle_t *handle, 2778static 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
2992static 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
2986static int ocfs2_make_clusters_writable(struct super_block *sb, 3001static 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
3117static int ocfs2_replace_cow(struct inode *inode, 3133static 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);
3242out: 3256out:
3257 kfree(context);
3243 return ret; 3258 return ret;
3244} 3259}
3245 3260