From a58df6f53687ac6d1dee21f60de41b2552a43201 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Thu, 17 Dec 2015 09:26:05 -0800 Subject: [PATCH] Fix zfs_vdev_aggregation_limit bounds checking Update the bounds checking for zfs_vdev_aggregation_limit so that it has a floor of zero and a maximum value of the supported block size for the pool. Additionally add an early return when zfs_vdev_aggregation_limit equals zero to disable aggregation. For very fast solid state or memory devices it may be more expensive to perform the aggregation than to issue the IO immediately. Signed-off-by: Brian Behlendorf --- module/zfs/vdev_queue.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/module/zfs/vdev_queue.c b/module/zfs/vdev_queue.c index 0c62a6fa3..e828ce917 100644 --- a/module/zfs/vdev_queue.c +++ b/module/zfs/vdev_queue.c @@ -499,20 +499,17 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio) zio_t *first, *last, *aio, *dio, *mandatory, *nio; uint64_t maxgap = 0; uint64_t size; + uint64_t limit; 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; void *buf; - if (zio->io_flags & ZIO_FLAG_DONT_AGGREGATE) - return (NULL); + limit = MAX(MIN(zfs_vdev_aggregation_limit, + spa_maxblocksize(vq->vq_vdev->vdev_spa)), 0); - /* - * Prevent users from setting the zfs_vdev_aggregation_limit - * tuning larger than SPA_MAXBLOCKSIZE. - */ - zfs_vdev_aggregation_limit = - MIN(zfs_vdev_aggregation_limit, SPA_MAXBLOCKSIZE); + if (zio->io_flags & ZIO_FLAG_DONT_AGGREGATE || limit == 0) + return (NULL); first = last = zio; @@ -540,7 +537,7 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio) */ while ((dio = AVL_PREV(t, first)) != NULL && (dio->io_flags & ZIO_FLAG_AGG_INHERIT) == flags && - IO_SPAN(dio, last) <= zfs_vdev_aggregation_limit && + IO_SPAN(dio, last) <= limit && IO_GAP(dio, first) <= maxgap) { first = dio; if (mandatory == NULL && !(first->io_flags & ZIO_FLAG_OPTIONAL)) @@ -561,7 +558,7 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio) */ while ((dio = AVL_NEXT(t, last)) != NULL && (dio->io_flags & ZIO_FLAG_AGG_INHERIT) == flags && - IO_SPAN(first, dio) <= zfs_vdev_aggregation_limit && + IO_SPAN(first, dio) <= limit && IO_GAP(last, dio) <= maxgap) { last = dio; if (!(last->io_flags & ZIO_FLAG_OPTIONAL)) @@ -607,7 +604,7 @@ vdev_queue_aggregate(vdev_queue_t *vq, zio_t *zio) return (NULL); size = IO_SPAN(first, last); - ASSERT3U(size, <=, zfs_vdev_aggregation_limit); + ASSERT3U(size, <=, limit); buf = zio_buf_alloc_flags(size, KM_NOSLEEP); if (buf == NULL)