diff options
Diffstat (limited to 'fs/ocfs2/alloc.c')
| -rw-r--r-- | fs/ocfs2/alloc.c | 24 | 
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:  static int ocfs2_trim_extent(struct super_block *sb,  			     struct ocfs2_group_desc *gd, -			     u32 start, u32 count) +			     u64 group, u32 start, u32 count)  {  	u64 discard, bcount; +	struct ocfs2_super *osb = OCFS2_SB(sb);  	bcount = ocfs2_clusters_to_blocks(sb, count); -	discard = le64_to_cpu(gd->bg_blkno) + -			ocfs2_clusters_to_blocks(sb, start); +	discard = ocfs2_clusters_to_blocks(sb, start); + +	/* +	 * For the first cluster group, the gd->bg_blkno is not at the start +	 * of the group, but at an offset from the start. If we add it while +	 * calculating discard for first group, we will wrongly start fstrim a +	 * few blocks after the desried start block and the range can cross +	 * over into the next cluster group. So, add it only if this is not +	 * the first cluster group. +	 */ +	if (group != osb->first_cluster_group_blkno) +		discard += le64_to_cpu(gd->bg_blkno);  	trace_ocfs2_trim_extent(sb, (unsigned long long)discard, bcount); @@ -7318,7 +7329,7 @@ static int ocfs2_trim_extent(struct super_block *sb,  }  static int ocfs2_trim_group(struct super_block *sb, -			    struct ocfs2_group_desc *gd, +			    struct ocfs2_group_desc *gd, u64 group,  			    u32 start, u32 max, u32 minbits)  {  	int ret = 0, count = 0, next; @@ -7337,7 +7348,7 @@ static int ocfs2_trim_group(struct super_block *sb,  		next = ocfs2_find_next_bit(bitmap, max, start);  		if ((next - start) >= minbits) { -			ret = ocfs2_trim_extent(sb, gd, +			ret = ocfs2_trim_extent(sb, gd, group,  						start, next - start);  			if (ret < 0) {  				mlog_errno(ret); @@ -7435,7 +7446,8 @@ int ocfs2_trim_fs(struct super_block *sb, struct fstrim_range *range)  		}  		gd = (struct ocfs2_group_desc *)gd_bh->b_data; -		cnt = ocfs2_trim_group(sb, gd, first_bit, last_bit, minlen); +		cnt = ocfs2_trim_group(sb, gd, group, +				       first_bit, last_bit, minlen);  		brelse(gd_bh);  		gd_bh = NULL;  		if (cnt < 0) { |