Skip to content

Commit 4d89d37

Browse files
jeffmahoneymasoncl
authored andcommitted
btrfs: btrfs_issue_discard ensure offset/length are aligned to sector boundaries
It's possible, though unexpected, to pass unaligned offsets and lengths to btrfs_issue_discard. We then shift the offset/length values to sector units. If an unaligned offset has been passed, it will result in the entire sector being discarded, possibly losing data. An unaligned length is safe but we'll end up returning an inaccurate number of discarded bytes. This patch aligns the offset to the 512B boundary, adjusts the length, and warns, since we shouldn't be discarding on an offset that isn't aligned with our sector size. Signed-off-by: Jeff Mahoney <[email protected]> Reviewed-by: Filipe Manana <[email protected]> Tested-by: Filipe Manana <[email protected]> Signed-off-by: Chris Mason <[email protected]>
1 parent d04c6b8 commit 4d89d37

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

fs/btrfs/extent-tree.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,12 +1887,21 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
18871887
u64 *discarded_bytes)
18881888
{
18891889
int ret = 0;
1890+
u64 aligned_start = ALIGN(start, 1 << 9);
18901891

1891-
*discarded_bytes = 0;
1892-
ret = blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_NOFS, 0);
1893-
if (!ret)
1894-
*discarded_bytes = len;
1892+
if (WARN_ON(start != aligned_start)) {
1893+
len -= aligned_start - start;
1894+
len = round_down(len, 1 << 9);
1895+
start = aligned_start;
1896+
}
18951897

1898+
*discarded_bytes = 0;
1899+
if (len) {
1900+
ret = blkdev_issue_discard(bdev, start >> 9, len >> 9,
1901+
GFP_NOFS, 0);
1902+
if (!ret)
1903+
*discarded_bytes = len;
1904+
}
18961905
return ret;
18971906
}
18981907

0 commit comments

Comments
 (0)