Skip to content

Commit

Permalink
ext4: issue aligned discards
Browse files Browse the repository at this point in the history
Ext4 before this patch can issue discards without respecting block
device's discard alignment. Such a discard results in EIO and
kernel logs.

Verified that there were no regressions in xfstests smoke tests.

Signed-off-by: Harshad Shirwadkar <harshadshirwadkar@gmail.com>
  • Loading branch information
harshadjs authored and intel-lab-lkp committed Jun 5, 2020
1 parent 6b8ed62 commit 0f81717
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 11 deletions.
32 changes: 21 additions & 11 deletions fs/ext4/mballoc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2880,20 +2880,30 @@ static inline int ext4_issue_discard(struct super_block *sb,
ext4_group_t block_group, ext4_grpblk_t cluster, int count,
struct bio **biop)
{
ext4_fsblk_t discard_block;

discard_block = (EXT4_C2B(EXT4_SB(sb), cluster) +
ext4_group_first_block_no(sb, block_group));
count = EXT4_C2B(EXT4_SB(sb), count);
unsigned long long discard_start, discard_len, alignment, granularity,
aligned_discard_start;

granularity = max(bdev_discard_granularity(sb->s_bdev), 1 << 9);
alignment = max_t(int, bdev_logical_block_size(sb->s_bdev),
bdev_discard_alignment(sb->s_bdev));
discard_start = (EXT4_C2B(EXT4_SB(sb), cluster) +
ext4_group_first_block_no(sb, block_group)) <<
sb->s_blocksize_bits;
discard_len = EXT4_C2B(EXT4_SB(sb), count) << sb->s_blocksize_bits;
aligned_discard_start = round_up(discard_start, alignment);
discard_len -= min(discard_len, aligned_discard_start - discard_start);
discard_len = round_down(discard_len, granularity);
if (discard_len >> 9 == 0)
return 0;
trace_ext4_discard_blocks(sb,
(unsigned long long) discard_block, count);
if (biop) {
aligned_discard_start >> sb->s_blocksize_bits,
discard_len >> (sb->s_blocksize_bits));
if (biop)
return __blkdev_issue_discard(sb->s_bdev,
(sector_t)discard_block << (sb->s_blocksize_bits - 9),
(sector_t)count << (sb->s_blocksize_bits - 9),
aligned_discard_start >> 9, discard_len >> 9,
GFP_NOFS, 0, biop);
} else
return sb_issue_discard(sb, discard_block, count, GFP_NOFS, 0);
return sb_issue_discard(sb, aligned_discard_start, discard_len,
GFP_NOFS, 0);
}

static void ext4_free_data_in_buddy(struct super_block *sb,
Expand Down
7 changes: 7 additions & 0 deletions include/linux/blkdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,13 @@ static inline int queue_limit_discard_alignment(struct queue_limits *lim, sector
return offset << SECTOR_SHIFT;
}

static inline int bdev_discard_granularity(struct block_device *bdev)
{
struct request_queue *q = bdev_get_queue(bdev);

return q ? q->limits.discard_granularity : 0;
}

static inline int bdev_discard_alignment(struct block_device *bdev)
{
struct request_queue *q = bdev_get_queue(bdev);
Expand Down

0 comments on commit 0f81717

Please sign in to comment.