aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAshish Samant <ashish.samant@oracle.com>2017-11-02 18:59:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-03 10:39:19 -0400
commit105ddc93f06ebe3e553f58563d11ed63dbcd59f0 (patch)
tree40516332f788df92c2d7c1304f81c8f674aa76b0
parentb83d7e432399d44454411dec5c25afb5c4469e96 (diff)
ocfs2: fstrim: Fix start offset of first cluster group during fstrim
The first cluster group descriptor is not stored at the start of the group but at an offset from the start. We need to take this into account while doing fstrim on the first cluster group. Otherwise we will wrongly start fstrim a few blocks after the desired start block and the range can cross over into the next cluster group and zero out the group descriptor there. This can cause filesytem corruption that cannot be fixed by fsck. Link: http://lkml.kernel.org/r/1507835579-7308-1-git-send-email-ashish.samant@oracle.com Signed-off-by: Ashish Samant <ashish.samant@oracle.com> Reviewed-by: Junxiao Bi <junxiao.bi@oracle.com> Reviewed-by: Joseph Qi <jiangqi903@gmail.com> Cc: Mark Fasheh <mfasheh@versity.com> Cc: Joel Becker <jlbec@evilplan.org> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/ocfs2/alloc.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index a177eae3aa1a..addd7c5f2d3e 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -7304,13 +7304,24 @@ out:
7304 7304
7305static int ocfs2_trim_extent(struct super_block *sb, 7305static int ocfs2_trim_extent(struct super_block *sb,
7306 struct ocfs2_group_desc *gd, 7306 struct ocfs2_group_desc *gd,
7307 u32 start, u32 count) 7307 u64 group, u32 start, u32 count)
7308{ 7308{
7309 u64 discard, bcount; 7309 u64 discard, bcount;
7310 struct ocfs2_super *osb = OCFS2_SB(sb);
7310 7311
7311 bcount = ocfs2_clusters_to_blocks(sb, count); 7312 bcount = ocfs2_clusters_to_blocks(sb, count);
7312 discard = le64_to_cpu(gd->bg_blkno) + 7313 discard = ocfs2_clusters_to_blocks(sb, start);
7313 ocfs2_clusters_to_blocks(sb, start); 7314
7315 /*
7316 * For the first cluster group, the gd->bg_blkno is not at the start
7317 * of the group, but at an offset from the start. If we add it while
7318 * calculating discard for first group, we will wrongly start fstrim a
7319 * few blocks after the desried start block and the range can cross
7320 * over into the next cluster group. So, add it only if this is not
7321 * the first cluster group.
7322 */
7323 if (group != osb->first_cluster_group_blkno)
7324 discard += le64_to_cpu(gd->bg_blkno);
7314 7325
7315 trace_ocfs2_trim_extent(sb, (unsigned long long)discard, bcount); 7326 trace_ocfs2_trim_extent(sb, (unsigned long long)discard, bcount);
7316 7327
@@ -7318,7 +7329,7 @@ static int ocfs2_trim_extent(struct super_block *sb,
7318} 7329}
7319 7330
7320static int ocfs2_trim_group(struct super_block *sb, 7331static int ocfs2_trim_group(struct super_block *sb,
7321 struct ocfs2_group_desc *gd, 7332 struct ocfs2_group_desc *gd, u64 group,
7322 u32 start, u32 max, u32 minbits) 7333 u32 start, u32 max, u32 minbits)
7323{ 7334{
7324 int ret = 0, count = 0, next; 7335 int ret = 0, count = 0, next;
@@ -7337,7 +7348,7 @@ static int ocfs2_trim_group(struct super_block *sb,
7337 next = ocfs2_find_next_bit(bitmap, max, start); 7348 next = ocfs2_find_next_bit(bitmap, max, start);
7338 7349
7339 if ((next - start) >= minbits) { 7350 if ((next - start) >= minbits) {
7340 ret = ocfs2_trim_extent(sb, gd, 7351 ret = ocfs2_trim_extent(sb, gd, group,
7341 start, next - start); 7352 start, next - start);
7342 if (ret < 0) { 7353 if (ret < 0) {
7343 mlog_errno(ret); 7354 mlog_errno(ret);
@@ -7435,7 +7446,8 @@ int ocfs2_trim_fs(struct super_block *sb, struct fstrim_range *range)
7435 } 7446 }
7436 7447
7437 gd = (struct ocfs2_group_desc *)gd_bh->b_data; 7448 gd = (struct ocfs2_group_desc *)gd_bh->b_data;
7438 cnt = ocfs2_trim_group(sb, gd, first_bit, last_bit, minlen); 7449 cnt = ocfs2_trim_group(sb, gd, group,
7450 first_bit, last_bit, minlen);
7439 brelse(gd_bh); 7451 brelse(gd_bh);
7440 gd_bh = NULL; 7452 gd_bh = NULL;
7441 if (cnt < 0) { 7453 if (cnt < 0) {