diff options
Diffstat (limited to 'fs/ocfs2/refcounttree.c')
-rw-r--r-- | fs/ocfs2/refcounttree.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 0a92436557e3..37aa0c8696d6 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
@@ -2482,6 +2482,7 @@ static inline unsigned int ocfs2_cow_align_length(struct super_block *sb, | |||
2482 | * | 2482 | * |
2483 | * cpos is vitual start cluster position we want to do CoW in a | 2483 | * cpos is vitual start cluster position we want to do CoW in a |
2484 | * file and write_len is the cluster length. | 2484 | * file and write_len is the cluster length. |
2485 | * max_cpos is the place where we want to stop CoW intentionally. | ||
2485 | * | 2486 | * |
2486 | * Normal we will start CoW from the beginning of extent record cotaining cpos. | 2487 | * Normal we will start CoW from the beginning of extent record cotaining cpos. |
2487 | * We try to break up extents on boundaries of MAX_CONTIG_BYTES so that we | 2488 | * We try to break up extents on boundaries of MAX_CONTIG_BYTES so that we |
@@ -2491,6 +2492,7 @@ static int ocfs2_refcount_cal_cow_clusters(struct inode *inode, | |||
2491 | struct buffer_head *di_bh, | 2492 | struct buffer_head *di_bh, |
2492 | u32 cpos, | 2493 | u32 cpos, |
2493 | u32 write_len, | 2494 | u32 write_len, |
2495 | u32 max_cpos, | ||
2494 | u32 *cow_start, | 2496 | u32 *cow_start, |
2495 | u32 *cow_len) | 2497 | u32 *cow_len) |
2496 | { | 2498 | { |
@@ -2505,6 +2507,8 @@ static int ocfs2_refcount_cal_cow_clusters(struct inode *inode, | |||
2505 | int contig_clusters = ocfs2_cow_contig_clusters(inode->i_sb); | 2507 | int contig_clusters = ocfs2_cow_contig_clusters(inode->i_sb); |
2506 | int leaf_clusters; | 2508 | int leaf_clusters; |
2507 | 2509 | ||
2510 | BUG_ON(cpos + write_len > max_cpos); | ||
2511 | |||
2508 | if (tree_height > 0) { | 2512 | if (tree_height > 0) { |
2509 | ret = ocfs2_find_leaf(INODE_CACHE(inode), el, cpos, &eb_bh); | 2513 | ret = ocfs2_find_leaf(INODE_CACHE(inode), el, cpos, &eb_bh); |
2510 | if (ret) { | 2514 | if (ret) { |
@@ -2549,15 +2553,20 @@ static int ocfs2_refcount_cal_cow_clusters(struct inode *inode, | |||
2549 | } | 2553 | } |
2550 | 2554 | ||
2551 | /* | 2555 | /* |
2552 | * If we encounter a hole or a non-refcounted record, | 2556 | * If we encounter a hole, a non-refcounted record or |
2553 | * stop the search. | 2557 | * pass the max_cpos, stop the search. |
2554 | */ | 2558 | */ |
2555 | if ((!(rec->e_flags & OCFS2_EXT_REFCOUNTED)) || | 2559 | if ((!(rec->e_flags & OCFS2_EXT_REFCOUNTED)) || |
2556 | (*cow_len && rec_end != le32_to_cpu(rec->e_cpos))) | 2560 | (*cow_len && rec_end != le32_to_cpu(rec->e_cpos)) || |
2561 | (max_cpos <= le32_to_cpu(rec->e_cpos))) | ||
2557 | break; | 2562 | break; |
2558 | 2563 | ||
2559 | leaf_clusters = le16_to_cpu(rec->e_leaf_clusters); | 2564 | leaf_clusters = le16_to_cpu(rec->e_leaf_clusters); |
2560 | rec_end = le32_to_cpu(rec->e_cpos) + leaf_clusters; | 2565 | rec_end = le32_to_cpu(rec->e_cpos) + leaf_clusters; |
2566 | if (rec_end > max_cpos) { | ||
2567 | rec_end = max_cpos; | ||
2568 | leaf_clusters = rec_end - le32_to_cpu(rec->e_cpos); | ||
2569 | } | ||
2561 | 2570 | ||
2562 | /* | 2571 | /* |
2563 | * How many clusters do we actually need from | 2572 | * How many clusters do we actually need from |
@@ -3184,12 +3193,13 @@ static int ocfs2_replace_cow(struct inode *inode, | |||
3184 | } | 3193 | } |
3185 | 3194 | ||
3186 | /* | 3195 | /* |
3187 | * Starting at cpos, try to CoW write_len clusters. | 3196 | * Starting at cpos, try to CoW write_len clusters. Don't CoW |
3188 | * This will stop when it runs into a hole or an unrefcounted extent. | 3197 | * past max_cpos. This will stop when it runs into a hole or an |
3198 | * unrefcounted extent. | ||
3189 | */ | 3199 | */ |
3190 | static int ocfs2_refcount_cow_hunk(struct inode *inode, | 3200 | static int ocfs2_refcount_cow_hunk(struct inode *inode, |
3191 | struct buffer_head *di_bh, | 3201 | struct buffer_head *di_bh, |
3192 | u32 cpos, u32 write_len) | 3202 | u32 cpos, u32 write_len, u32 max_cpos) |
3193 | { | 3203 | { |
3194 | int ret; | 3204 | int ret; |
3195 | u32 cow_start = 0, cow_len = 0; | 3205 | u32 cow_start = 0, cow_len = 0; |
@@ -3201,12 +3211,14 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, | |||
3201 | 3211 | ||
3202 | BUG_ON(!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL)); | 3212 | BUG_ON(!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL)); |
3203 | 3213 | ||
3204 | ret = ocfs2_refcount_cal_cow_clusters(inode, di_bh, cpos, write_len, | 3214 | ret = ocfs2_refcount_cal_cow_clusters(inode, di_bh, |
3215 | cpos, write_len, max_cpos, | ||
3205 | &cow_start, &cow_len); | 3216 | &cow_start, &cow_len); |
3206 | if (ret) { | 3217 | if (ret) { |
3207 | mlog_errno(ret); | 3218 | mlog_errno(ret); |
3208 | goto out; | 3219 | goto out; |
3209 | } | 3220 | } |
3221 | |||
3210 | mlog(0, "CoW inode %lu, cpos %u, write_len %u, cow_start %u, " | 3222 | mlog(0, "CoW inode %lu, cpos %u, write_len %u, cow_start %u, " |
3211 | "cow_len %u\n", inode->i_ino, | 3223 | "cow_len %u\n", inode->i_ino, |
3212 | cpos, write_len, cow_start, cow_len); | 3224 | cpos, write_len, cow_start, cow_len); |
@@ -3233,12 +3245,12 @@ out: | |||
3233 | 3245 | ||
3234 | /* | 3246 | /* |
3235 | * CoW any and all clusters between cpos and cpos+write_len. | 3247 | * CoW any and all clusters between cpos and cpos+write_len. |
3236 | * If this returns successfully, all clusters between cpos and | 3248 | * Don't CoW past max_cpos. If this returns successfully, all |
3237 | * cpos+write_len are safe to modify. | 3249 | * clusters between cpos and cpos+write_len are safe to modify. |
3238 | */ | 3250 | */ |
3239 | int ocfs2_refcount_cow(struct inode *inode, | 3251 | int ocfs2_refcount_cow(struct inode *inode, |
3240 | struct buffer_head *di_bh, | 3252 | struct buffer_head *di_bh, |
3241 | u32 cpos, u32 write_len) | 3253 | u32 cpos, u32 write_len, u32 max_cpos) |
3242 | { | 3254 | { |
3243 | int ret = 0; | 3255 | int ret = 0; |
3244 | u32 p_cluster, num_clusters; | 3256 | u32 p_cluster, num_clusters; |
@@ -3257,7 +3269,7 @@ int ocfs2_refcount_cow(struct inode *inode, | |||
3257 | 3269 | ||
3258 | if (ext_flags & OCFS2_EXT_REFCOUNTED) { | 3270 | if (ext_flags & OCFS2_EXT_REFCOUNTED) { |
3259 | ret = ocfs2_refcount_cow_hunk(inode, di_bh, cpos, | 3271 | ret = ocfs2_refcount_cow_hunk(inode, di_bh, cpos, |
3260 | num_clusters); | 3272 | num_clusters, max_cpos); |
3261 | if (ret) { | 3273 | if (ret) { |
3262 | mlog_errno(ret); | 3274 | mlog_errno(ret); |
3263 | break; | 3275 | break; |