|
@@ -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) {
|