]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Cap maximum aggregate IO size
authorBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 27 Jun 2017 17:09:16 +0000 (10:09 -0700)
committerGitHub <noreply@github.com>
Tue, 27 Jun 2017 17:09:16 +0000 (10:09 -0700)
Commit 8542ef8 allowed optional IOs to be aggregated beyond
the specified aggregation limit.  Since the aggregation limit
was also used to enforce the maximum block size, setting
`zfs_vdev_aggregation_limit=16777216` could result in an
attempt to allocate an ABD larger than 16M.

Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed-by: George Melikov <mail@gmelikov.ru>
Reviewed-by: Giuseppe Di Natale <dinatale2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #6259
Closes #6270

module/zfs/vdev_queue.c

index 2439f2951c23f3cbb5596421ca2df58bba5cb167..6b3e8729159009749b49c702726a3bc4a0c7d10c 100644 (file)
@@ -521,13 +521,14 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
        uint64_t maxgap = 0;
        uint64_t size;
        uint64_t limit;
+       int maxblocksize;
        boolean_t stretch = B_FALSE;
        avl_tree_t *t = vdev_queue_type_tree(vq, zio->io_type);
        enum zio_flag flags = zio->io_flags & ZIO_FLAG_AGG_INHERIT;
        abd_t *abd;
 
-       limit = MAX(MIN(zfs_vdev_aggregation_limit,
-           spa_maxblocksize(vq->vq_vdev->vdev_spa)), 0);
+       maxblocksize = spa_maxblocksize(vq->vq_vdev->vdev_spa);
+       limit = MAX(MIN(zfs_vdev_aggregation_limit, maxblocksize), 0);
 
        if (zio->io_flags & ZIO_FLAG_DONT_AGGREGATE || limit == 0)
                return (NULL);
@@ -584,6 +585,7 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
            (dio->io_flags & ZIO_FLAG_AGG_INHERIT) == flags &&
            (IO_SPAN(first, dio) <= limit ||
            (dio->io_flags & ZIO_FLAG_OPTIONAL)) &&
+           IO_SPAN(first, dio) <= maxblocksize &&
            IO_GAP(last, dio) <= maxgap) {
                last = dio;
                if (!(last->io_flags & ZIO_FLAG_OPTIONAL))
@@ -635,6 +637,7 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio)
                return (NULL);
 
        size = IO_SPAN(first, last);
+       ASSERT3U(size, <=, maxblocksize);
 
        abd = abd_alloc_for_io(size, B_TRUE);
        if (abd == NULL)