summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2015-06-15 09:41:15 -0400
committerChris Mason <clm@fb.com>2015-07-29 08:15:24 -0700
commit4d89d377bbb0e34cd1571b57a984c2326cab69b5 (patch)
tree25f9ec35458694e08e6f852bd6f05c22faf00891
parentd04c6b88320debb403bff8d8b634a1efa48b8d3d (diff)
downloadop-kernel-dev-4d89d377bbb0e34cd1571b57a984c2326cab69b5.zip
op-kernel-dev-4d89d377bbb0e34cd1571b57a984c2326cab69b5.tar.gz
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 <jeffm@suse.com> Reviewed-by: Filipe Manana <fdmanana@suse.com> Tested-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r--fs/btrfs/extent-tree.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 16655bb..7aa6ad1 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1887,12 +1887,21 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
u64 *discarded_bytes)
{
int ret = 0;
+ u64 aligned_start = ALIGN(start, 1 << 9);
- *discarded_bytes = 0;
- ret = blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_NOFS, 0);
- if (!ret)
- *discarded_bytes = len;
+ if (WARN_ON(start != aligned_start)) {
+ len -= aligned_start - start;
+ len = round_down(len, 1 << 9);
+ start = aligned_start;
+ }
+ *discarded_bytes = 0;
+ if (len) {
+ ret = blkdev_issue_discard(bdev, start >> 9, len >> 9,
+ GFP_NOFS, 0);
+ if (!ret)
+ *discarded_bytes = len;
+ }
return ret;
}
OpenPOWER on IntegriCloud