]> granicus.if.org Git - zfs/commitdiff
Fail early on bio corruption confirmed on 5.2-rc1
authorTomohiro Kusumi <kusumi.tomohiro@gmail.com>
Wed, 3 Jul 2019 20:03:22 +0000 (05:03 +0900)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 3 Jul 2019 20:03:22 +0000 (13:03 -0700)
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 <behlendorf1@llnl.gov>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Tomohiro Kusumi <kusumi.tomohiro@gmail.com>
Closes #8867
Closes #8961

module/zfs/vdev_disk.c

index 1686ddfce77df1646299fb0d2e22bba3e80bf1ad..8f06c411758fe094de044e435f9190ea13bcb4a5 100644 (file)
@@ -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));
                }