summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomohiro Kusumi <[email protected]>2019-07-04 05:03:22 +0900
committerBrian Behlendorf <[email protected]>2019-07-03 13:03:22 -0700
commitaa7aab6c457f106d2b794b9adf3fe5aa451ad8e9 (patch)
treec5ce66e37169c22d02da8b546a9a48cedcc50ddd
parent46db9d6161d0781f00ee3cb5bc02e11685d2ffaf (diff)
Fail early on bio corruption confirmed on 5.2-rc1
Unable to import zpool with "Large kmem_alloc" warning due to corrupted bio's with invalid # of page vectors. See #8867 for details. Fail early with ENOMEM. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Tony Hutter <[email protected]> Signed-off-by: Tomohiro Kusumi <[email protected]> Closes #8867 Closes #8961
-rw-r--r--module/zfs/vdev_disk.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/module/zfs/vdev_disk.c b/module/zfs/vdev_disk.c
index 1686ddfce..8f06c4117 100644
--- a/module/zfs/vdev_disk.c
+++ b/module/zfs/vdev_disk.c
@@ -621,6 +621,7 @@ retry:
bio_offset = io_offset;
bio_size = io_size;
for (i = 0; i <= dr->dr_bio_count; i++) {
+ unsigned int nr_iovecs;
/* Finished constructing bio's for given buffer */
if (bio_size <= 0)
@@ -638,10 +639,11 @@ retry:
}
/* bio_alloc() with __GFP_WAIT never returns NULL */
- dr->dr_bio[i] = bio_alloc(GFP_NOIO,
- MIN(abd_nr_pages_off(zio->io_abd, bio_size, abd_offset),
- BIO_MAX_PAGES));
- if (unlikely(dr->dr_bio[i] == NULL)) {
+ nr_iovecs = MIN(abd_nr_pages_off(zio->io_abd, bio_size,
+ abd_offset), BIO_MAX_PAGES);
+ dr->dr_bio[i] = bio_alloc(GFP_NOIO, nr_iovecs);
+ if (unlikely(dr->dr_bio[i] == NULL ||
+ (unsigned int)dr->dr_bio[i]->bi_max_vecs != nr_iovecs)) {
vdev_disk_dio_free(dr);
return (SET_ERROR(ENOMEM));
}