diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2015-07-22 07:57:12 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-07-23 18:21:34 -0400 |
commit | f3f5da624e0a891c34d8cd513c57f1d9b0c7dadc (patch) | |
tree | d2a92a8d8d03287c8b51df5dfae24d267e151e6b | |
parent | 5aa2a96b34073fb775917fbc7d5578a04164b9f7 (diff) |
block: Do a full clone when splitting discard bios
This fixes a data corruption bug when using discard on top of MD linear,
raid0 and raid10 personalities.
Commit 20d0189b1012 "block: Introduce new bio_split()" permits sharing
the bio_vec between the two resulting bios. That is fine for read/write
requests where the bio_vec is immutable. For discards, however, we need
to be able to attach a payload and update the bio_vec so the page can
get mapped to a scatterlist entry. Therefore the bio_vec can not be
shared when splitting discards and we must do a full clone.
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Reported-by: Seunguk Shin <seunguk.shin@samsung.com>
Tested-by: Seunguk Shin <seunguk.shin@samsung.com>
Cc: Seunguk Shin <seunguk.shin@samsung.com>
Cc: Jens Axboe <axboe@fb.com>
Cc: Kent Overstreet <kent.overstreet@gmail.com>
Cc: <stable@vger.kernel.org> # v3.14+
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | block/bio.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/block/bio.c b/block/bio.c index b671a0ff731c..d6e5ba3399f0 100644 --- a/block/bio.c +++ b/block/bio.c | |||
@@ -1831,8 +1831,9 @@ EXPORT_SYMBOL(bio_endio); | |||
1831 | * Allocates and returns a new bio which represents @sectors from the start of | 1831 | * Allocates and returns a new bio which represents @sectors from the start of |
1832 | * @bio, and updates @bio to represent the remaining sectors. | 1832 | * @bio, and updates @bio to represent the remaining sectors. |
1833 | * | 1833 | * |
1834 | * The newly allocated bio will point to @bio's bi_io_vec; it is the caller's | 1834 | * Unless this is a discard request the newly allocated bio will point |
1835 | * responsibility to ensure that @bio is not freed before the split. | 1835 | * to @bio's bi_io_vec; it is the caller's responsibility to ensure that |
1836 | * @bio is not freed before the split. | ||
1836 | */ | 1837 | */ |
1837 | struct bio *bio_split(struct bio *bio, int sectors, | 1838 | struct bio *bio_split(struct bio *bio, int sectors, |
1838 | gfp_t gfp, struct bio_set *bs) | 1839 | gfp_t gfp, struct bio_set *bs) |
@@ -1842,7 +1843,15 @@ struct bio *bio_split(struct bio *bio, int sectors, | |||
1842 | BUG_ON(sectors <= 0); | 1843 | BUG_ON(sectors <= 0); |
1843 | BUG_ON(sectors >= bio_sectors(bio)); | 1844 | BUG_ON(sectors >= bio_sectors(bio)); |
1844 | 1845 | ||
1845 | split = bio_clone_fast(bio, gfp, bs); | 1846 | /* |
1847 | * Discards need a mutable bio_vec to accommodate the payload | ||
1848 | * required by the DSM TRIM and UNMAP commands. | ||
1849 | */ | ||
1850 | if (bio->bi_rw & REQ_DISCARD) | ||
1851 | split = bio_clone_bioset(bio, gfp, bs); | ||
1852 | else | ||
1853 | split = bio_clone_fast(bio, gfp, bs); | ||
1854 | |||
1846 | if (!split) | 1855 | if (!split) |
1847 | return NULL; | 1856 | return NULL; |
1848 | 1857 | ||