Cap maximum aggregate IO size

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
This commit is contained in:
Brian Behlendorf 2017-06-27 10:09:16 -07:00 committed by GitHub
parent 47770d30f2
commit 2d678f779a
1 changed files with 5 additions and 2 deletions

View File

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