Print this page
NEX-18069 Unable to get/set VDEV_PROP_RESILVER_MAXACTIVE/VDEV_PROP_RESILVER_MINACTIVE props
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-9552 zfs_scan_idle throttling harms performance and needs to be removed
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-13937 Improve kstat performance
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-3558 KRRP Integration
OS-103 handle CoS descriptor persistent references across vdev operations
OS-80 support for vdev and CoS properties for the new I/O scheduler
OS-95 lint warning introduced by OS-61
re #12643 rb4064 ZFS meta refactoring - vdev utilization tracking, auto-dedup
re #12585 rb4049 ZFS++ work port - refactoring to improve separation of open/closed code, bug fixes, performance improvements - open code
Bug 11205: add missing libzfs_closed_stubs.c to fix opensource-only build.
ZFS plus work: special vdevs, cos, cos/vdev properties

*** 19,37 **** --- 19,39 ---- * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ /* * Copyright (c) 2012, 2017 by Delphix. All rights reserved. * Copyright (c) 2014 Integros [integros.com] */ #include <sys/zfs_context.h> #include <sys/vdev_impl.h> + #include <sys/cos.h> #include <sys/spa_impl.h> #include <sys/zio.h> #include <sys/avl.h> #include <sys/dsl_pool.h> #include <sys/metaslab_impl.h>
*** 144,157 **** uint32_t zfs_vdev_sync_write_max_active = 10; uint32_t zfs_vdev_async_read_min_active = 1; uint32_t zfs_vdev_async_read_max_active = 3; uint32_t zfs_vdev_async_write_min_active = 1; uint32_t zfs_vdev_async_write_max_active = 10; uint32_t zfs_vdev_scrub_min_active = 1; uint32_t zfs_vdev_scrub_max_active = 2; - uint32_t zfs_vdev_removal_min_active = 1; - uint32_t zfs_vdev_removal_max_active = 2; /* * When the pool has less than zfs_vdev_async_write_active_min_dirty_percent * dirty data, use zfs_vdev_async_write_min_active. When it has more than * zfs_vdev_async_write_active_max_dirty_percent, use --- 146,159 ---- uint32_t zfs_vdev_sync_write_max_active = 10; uint32_t zfs_vdev_async_read_min_active = 1; uint32_t zfs_vdev_async_read_max_active = 3; uint32_t zfs_vdev_async_write_min_active = 1; uint32_t zfs_vdev_async_write_max_active = 10; + uint32_t zfs_vdev_resilver_min_active = 1; + uint32_t zfs_vdev_resilver_max_active = 3; uint32_t zfs_vdev_scrub_min_active = 1; uint32_t zfs_vdev_scrub_max_active = 2; /* * When the pool has less than zfs_vdev_async_write_active_min_dirty_percent * dirty data, use zfs_vdev_async_write_min_active. When it has more than * zfs_vdev_async_write_active_max_dirty_percent, use
*** 293,371 **** static void vdev_queue_io_add(vdev_queue_t *vq, zio_t *zio) { spa_t *spa = zio->io_spa; ASSERT3U(zio->io_priority, <, ZIO_PRIORITY_NUM_QUEUEABLE); avl_add(vdev_queue_class_tree(vq, zio->io_priority), zio); avl_add(vdev_queue_type_tree(vq, zio->io_type), zio); mutex_enter(&spa->spa_iokstat_lock); - spa->spa_queue_stats[zio->io_priority].spa_queued++; if (spa->spa_iokstat != NULL) ! kstat_waitq_enter(spa->spa_iokstat->ks_data); mutex_exit(&spa->spa_iokstat_lock); } static void vdev_queue_io_remove(vdev_queue_t *vq, zio_t *zio) { spa_t *spa = zio->io_spa; ASSERT3U(zio->io_priority, <, ZIO_PRIORITY_NUM_QUEUEABLE); avl_remove(vdev_queue_class_tree(vq, zio->io_priority), zio); avl_remove(vdev_queue_type_tree(vq, zio->io_type), zio); - mutex_enter(&spa->spa_iokstat_lock); ASSERT3U(spa->spa_queue_stats[zio->io_priority].spa_queued, >, 0); ! spa->spa_queue_stats[zio->io_priority].spa_queued--; if (spa->spa_iokstat != NULL) ! kstat_waitq_exit(spa->spa_iokstat->ks_data); mutex_exit(&spa->spa_iokstat_lock); } static void vdev_queue_pending_add(vdev_queue_t *vq, zio_t *zio) { spa_t *spa = zio->io_spa; ASSERT(MUTEX_HELD(&vq->vq_lock)); ASSERT3U(zio->io_priority, <, ZIO_PRIORITY_NUM_QUEUEABLE); vq->vq_class[zio->io_priority].vqc_active++; avl_add(&vq->vq_active_tree, zio); mutex_enter(&spa->spa_iokstat_lock); - spa->spa_queue_stats[zio->io_priority].spa_active++; if (spa->spa_iokstat != NULL) ! kstat_runq_enter(spa->spa_iokstat->ks_data); mutex_exit(&spa->spa_iokstat_lock); } static void vdev_queue_pending_remove(vdev_queue_t *vq, zio_t *zio) { spa_t *spa = zio->io_spa; ASSERT(MUTEX_HELD(&vq->vq_lock)); ASSERT3U(zio->io_priority, <, ZIO_PRIORITY_NUM_QUEUEABLE); vq->vq_class[zio->io_priority].vqc_active--; avl_remove(&vq->vq_active_tree, zio); - mutex_enter(&spa->spa_iokstat_lock); ASSERT3U(spa->spa_queue_stats[zio->io_priority].spa_active, >, 0); ! spa->spa_queue_stats[zio->io_priority].spa_active--; if (spa->spa_iokstat != NULL) { kstat_io_t *ksio = spa->spa_iokstat->ks_data; ! kstat_runq_exit(spa->spa_iokstat->ks_data); if (zio->io_type == ZIO_TYPE_READ) { ksio->reads++; ksio->nread += zio->io_size; } else if (zio->io_type == ZIO_TYPE_WRITE) { ksio->writes++; ksio->nwritten += zio->io_size; } } mutex_exit(&spa->spa_iokstat_lock); } static void vdev_queue_agg_io_done(zio_t *aio) --- 295,400 ---- static void vdev_queue_io_add(vdev_queue_t *vq, zio_t *zio) { spa_t *spa = zio->io_spa; + hrtime_t t = gethrtime_unscaled(); ASSERT3U(zio->io_priority, <, ZIO_PRIORITY_NUM_QUEUEABLE); avl_add(vdev_queue_class_tree(vq, zio->io_priority), zio); avl_add(vdev_queue_type_tree(vq, zio->io_type), zio); + atomic_inc_64(&spa->spa_queue_stats[zio->io_priority].spa_queued); mutex_enter(&spa->spa_iokstat_lock); if (spa->spa_iokstat != NULL) ! kstat_waitq_enter_time(spa->spa_iokstat->ks_data, t); ! if (vq->vq_vdev->vdev_iokstat != NULL) ! kstat_waitq_enter_time(vq->vq_vdev->vdev_iokstat->ks_data, t); mutex_exit(&spa->spa_iokstat_lock); } static void vdev_queue_io_remove(vdev_queue_t *vq, zio_t *zio) { spa_t *spa = zio->io_spa; + hrtime_t t = gethrtime_unscaled(); ASSERT3U(zio->io_priority, <, ZIO_PRIORITY_NUM_QUEUEABLE); avl_remove(vdev_queue_class_tree(vq, zio->io_priority), zio); avl_remove(vdev_queue_type_tree(vq, zio->io_type), zio); ASSERT3U(spa->spa_queue_stats[zio->io_priority].spa_queued, >, 0); ! atomic_dec_64(&spa->spa_queue_stats[zio->io_priority].spa_queued); ! ! mutex_enter(&spa->spa_iokstat_lock); if (spa->spa_iokstat != NULL) ! kstat_waitq_exit_time(spa->spa_iokstat->ks_data, t); ! if (vq->vq_vdev->vdev_iokstat != NULL) ! kstat_waitq_exit_time(vq->vq_vdev->vdev_iokstat->ks_data, t); mutex_exit(&spa->spa_iokstat_lock); } static void vdev_queue_pending_add(vdev_queue_t *vq, zio_t *zio) { spa_t *spa = zio->io_spa; + hrtime_t t = gethrtime_unscaled(); + ASSERT(MUTEX_HELD(&vq->vq_lock)); ASSERT3U(zio->io_priority, <, ZIO_PRIORITY_NUM_QUEUEABLE); vq->vq_class[zio->io_priority].vqc_active++; avl_add(&vq->vq_active_tree, zio); + atomic_inc_64(&spa->spa_queue_stats[zio->io_priority].spa_active); mutex_enter(&spa->spa_iokstat_lock); if (spa->spa_iokstat != NULL) ! kstat_runq_enter_time(spa->spa_iokstat->ks_data, t); ! if (vq->vq_vdev->vdev_iokstat != NULL) ! kstat_runq_enter_time(vq->vq_vdev->vdev_iokstat->ks_data, t); mutex_exit(&spa->spa_iokstat_lock); } static void vdev_queue_pending_remove(vdev_queue_t *vq, zio_t *zio) { spa_t *spa = zio->io_spa; + hrtime_t t = gethrtime_unscaled(); + ASSERT(MUTEX_HELD(&vq->vq_lock)); ASSERT3U(zio->io_priority, <, ZIO_PRIORITY_NUM_QUEUEABLE); vq->vq_class[zio->io_priority].vqc_active--; avl_remove(&vq->vq_active_tree, zio); ASSERT3U(spa->spa_queue_stats[zio->io_priority].spa_active, >, 0); ! atomic_dec_64(&spa->spa_queue_stats[zio->io_priority].spa_active); ! ! mutex_enter(&spa->spa_iokstat_lock); if (spa->spa_iokstat != NULL) { kstat_io_t *ksio = spa->spa_iokstat->ks_data; ! kstat_runq_exit_time(spa->spa_iokstat->ks_data, t); if (zio->io_type == ZIO_TYPE_READ) { ksio->reads++; ksio->nread += zio->io_size; } else if (zio->io_type == ZIO_TYPE_WRITE) { ksio->writes++; ksio->nwritten += zio->io_size; } } + + if (vq->vq_vdev->vdev_iokstat != NULL) { + kstat_io_t *ksio = vq->vq_vdev->vdev_iokstat->ks_data; + + kstat_runq_exit_time(ksio, t); + if (zio->io_type == ZIO_TYPE_READ) { + ksio->reads++; + ksio->nread += zio->io_size; + } else if (zio->io_type == ZIO_TYPE_WRITE) { + ksio->writes++; + ksio->nwritten += zio->io_size; + } + } mutex_exit(&spa->spa_iokstat_lock); } static void vdev_queue_agg_io_done(zio_t *aio)
*** 380,470 **** } abd_free(aio->io_abd); } static int ! vdev_queue_class_min_active(zio_priority_t p) { switch (p) { case ZIO_PRIORITY_SYNC_READ: ! return (zfs_vdev_sync_read_min_active); case ZIO_PRIORITY_SYNC_WRITE: ! return (zfs_vdev_sync_write_min_active); case ZIO_PRIORITY_ASYNC_READ: ! return (zfs_vdev_async_read_min_active); case ZIO_PRIORITY_ASYNC_WRITE: ! return (zfs_vdev_async_write_min_active); ! case ZIO_PRIORITY_SCRUB: ! return (zfs_vdev_scrub_min_active); ! case ZIO_PRIORITY_REMOVAL: ! return (zfs_vdev_removal_min_active); default: panic("invalid priority %u", p); return (0); } } static int ! vdev_queue_max_async_writes(spa_t *spa) { int writes; uint64_t dirty = spa->spa_dsl_pool->dp_dirty_total; uint64_t min_bytes = zfs_dirty_data_max * zfs_vdev_async_write_active_min_dirty_percent / 100; uint64_t max_bytes = zfs_dirty_data_max * zfs_vdev_async_write_active_max_dirty_percent / 100; /* * Sync tasks correspond to interactive user actions. To reduce the * execution time of those actions we push data out as fast as possible. */ if (spa_has_pending_synctask(spa)) { return (zfs_vdev_async_write_max_active); } if (dirty < min_bytes) ! return (zfs_vdev_async_write_min_active); if (dirty > max_bytes) ! return (zfs_vdev_async_write_max_active); /* * linear interpolation: * slope = (max_writes - min_writes) / (max_bytes - min_bytes) * move right by min_bytes * move up by min_writes */ ! writes = (dirty - min_bytes) * ! (zfs_vdev_async_write_max_active - ! zfs_vdev_async_write_min_active) / ! (max_bytes - min_bytes) + ! zfs_vdev_async_write_min_active; ! ASSERT3U(writes, >=, zfs_vdev_async_write_min_active); ! ASSERT3U(writes, <=, zfs_vdev_async_write_max_active); return (writes); } static int ! vdev_queue_class_max_active(spa_t *spa, zio_priority_t p) { switch (p) { case ZIO_PRIORITY_SYNC_READ: ! return (zfs_vdev_sync_read_max_active); case ZIO_PRIORITY_SYNC_WRITE: ! return (zfs_vdev_sync_write_max_active); case ZIO_PRIORITY_ASYNC_READ: ! return (zfs_vdev_async_read_max_active); case ZIO_PRIORITY_ASYNC_WRITE: ! return (vdev_queue_max_async_writes(spa)); ! case ZIO_PRIORITY_SCRUB: ! return (zfs_vdev_scrub_max_active); ! case ZIO_PRIORITY_REMOVAL: ! return (zfs_vdev_removal_max_active); default: panic("invalid priority %u", p); return (0); } } /* * Return the i/o class to issue from, or ZIO_PRIORITY_MAX_QUEUEABLE if * there is no eligible class. --- 409,592 ---- } abd_free(aio->io_abd); } + static uint64_t + scan_prio2active(uint64_t prio, boolean_t max_active) + { + uint64_t act, act_max; + + if (max_active) { + act_max = MAX(MAX(zfs_vdev_sync_read_max_active, + zfs_vdev_sync_write_max_active), + MAX(zfs_vdev_async_read_max_active, + zfs_vdev_async_write_max_active)); + act = ((prio * (zfs_vdev_sync_read_max_active + + zfs_vdev_sync_write_max_active + + zfs_vdev_async_read_max_active + + zfs_vdev_async_write_max_active)) / 100); + } else { + act_max = MAX(MAX(zfs_vdev_sync_read_min_active, + zfs_vdev_sync_write_min_active), + MAX(zfs_vdev_async_read_min_active, + zfs_vdev_async_write_min_active)); + act = ((prio * (zfs_vdev_sync_read_min_active + + zfs_vdev_sync_write_min_active + + zfs_vdev_async_read_min_active + + zfs_vdev_async_write_min_active)) / 100); + } + act = MAX(MIN(act, act_max), 1); + + return (act); + } + static int ! vdev_queue_class_min_active(zio_priority_t p, vdev_queue_t *vq) { + int zfs_min_active = 0; + int vqc_min_active; + vdev_prop_t prop = VDEV_ZIO_PRIO_TO_PROP_MIN(p); + + ASSERT(VDEV_PROP_MIN_VALID(prop)); + vqc_min_active = vdev_queue_get_prop_uint64(vq, prop); + switch (p) { case ZIO_PRIORITY_SYNC_READ: ! zfs_min_active = zfs_vdev_sync_read_min_active; ! break; case ZIO_PRIORITY_SYNC_WRITE: ! zfs_min_active = zfs_vdev_sync_write_min_active; ! break; case ZIO_PRIORITY_ASYNC_READ: ! zfs_min_active = zfs_vdev_async_read_min_active; ! break; case ZIO_PRIORITY_ASYNC_WRITE: ! zfs_min_active = zfs_vdev_async_write_min_active; ! break; ! case ZIO_PRIORITY_RESILVER: { ! uint64_t prio = vq->vq_vdev->vdev_spa->spa_resilver_prio; ! if (prio > 0) ! zfs_min_active = scan_prio2active(prio, B_FALSE); ! else ! zfs_min_active = zfs_vdev_resilver_min_active; ! break; ! } ! case ZIO_PRIORITY_SCRUB: { ! uint64_t prio = vq->vq_vdev->vdev_spa->spa_scrub_prio; ! if (prio > 0) ! zfs_min_active = scan_prio2active(prio, B_FALSE); ! else ! zfs_min_active = zfs_vdev_scrub_min_active; ! break; ! } default: panic("invalid priority %u", p); return (0); } + + /* zero vdev-specific setting means "use zfs global setting" */ + return ((vqc_min_active) ? vqc_min_active : zfs_min_active); } static int ! vdev_queue_max_async_writes(spa_t *spa, vdev_queue_t *vq) { int writes; uint64_t dirty = spa->spa_dsl_pool->dp_dirty_total; uint64_t min_bytes = zfs_dirty_data_max * zfs_vdev_async_write_active_min_dirty_percent / 100; uint64_t max_bytes = zfs_dirty_data_max * zfs_vdev_async_write_active_max_dirty_percent / 100; /* + * vdev-specific properties override global tunables + * zero vdev-specific settings indicate fallback on the globals + */ + int vqc_min_active = + vdev_queue_get_prop_uint64(vq, VDEV_PROP_AWRITE_MINACTIVE); + int min_active = + (vqc_min_active) ? vqc_min_active : zfs_vdev_async_write_min_active; + int vqc_max_active = + vdev_queue_get_prop_uint64(vq, VDEV_PROP_AWRITE_MAXACTIVE); + int max_active = + (vqc_max_active) ? vqc_max_active : zfs_vdev_async_write_max_active; + + /* * Sync tasks correspond to interactive user actions. To reduce the * execution time of those actions we push data out as fast as possible. */ if (spa_has_pending_synctask(spa)) { return (zfs_vdev_async_write_max_active); } if (dirty < min_bytes) ! return (min_active); if (dirty > max_bytes) ! return (max_active); /* * linear interpolation: * slope = (max_writes - min_writes) / (max_bytes - min_bytes) * move right by min_bytes * move up by min_writes */ ! writes = (dirty - min_bytes) * (max_active - min_active) / ! (max_bytes - min_bytes) + min_active; ! ASSERT3U(writes, >=, min_active); ! ASSERT3U(writes, <=, max_active); return (writes); } static int ! vdev_queue_class_max_active(spa_t *spa, zio_priority_t p, vdev_queue_t *vq) { + int zfs_max_active = 0; + int vqc_max_active; + vdev_prop_t prop = VDEV_ZIO_PRIO_TO_PROP_MAX(p); + + ASSERT(VDEV_PROP_MAX_VALID(prop)); + vqc_max_active = vdev_queue_get_prop_uint64(vq, prop); + switch (p) { case ZIO_PRIORITY_SYNC_READ: ! zfs_max_active = zfs_vdev_sync_read_max_active; ! break; case ZIO_PRIORITY_SYNC_WRITE: ! zfs_max_active = zfs_vdev_sync_write_max_active; ! break; case ZIO_PRIORITY_ASYNC_READ: ! zfs_max_active = zfs_vdev_async_read_max_active; ! break; case ZIO_PRIORITY_ASYNC_WRITE: ! /* takes into account vdev-specific props internally */ ! vqc_max_active = vdev_queue_max_async_writes(spa, vq); ! ASSERT(vqc_max_active); ! break; ! case ZIO_PRIORITY_RESILVER: { ! uint64_t prio = vq->vq_vdev->vdev_spa->spa_resilver_prio; ! if (prio > 0) ! zfs_max_active = scan_prio2active(prio, B_TRUE); ! else ! zfs_max_active = zfs_vdev_resilver_max_active; ! break; ! } ! case ZIO_PRIORITY_SCRUB: { ! uint64_t prio = vq->vq_vdev->vdev_spa->spa_scrub_prio; ! if (prio > 0) ! zfs_max_active = scan_prio2active(prio, B_TRUE); ! else ! zfs_max_active = zfs_vdev_scrub_max_active; ! break; ! } default: panic("invalid priority %u", p); return (0); } + + /* zero vdev-specific setting means "use zfs global setting" */ + return ((vqc_max_active) ? vqc_max_active : zfs_max_active); } /* * Return the i/o class to issue from, or ZIO_PRIORITY_MAX_QUEUEABLE if * there is no eligible class.
*** 480,490 **** /* find a queue that has not reached its minimum # outstanding i/os */ for (p = 0; p < ZIO_PRIORITY_NUM_QUEUEABLE; p++) { if (avl_numnodes(vdev_queue_class_tree(vq, p)) > 0 && vq->vq_class[p].vqc_active < ! vdev_queue_class_min_active(p)) return (p); } /* * If we haven't found a queue, look for one that hasn't reached its --- 602,612 ---- /* find a queue that has not reached its minimum # outstanding i/os */ for (p = 0; p < ZIO_PRIORITY_NUM_QUEUEABLE; p++) { if (avl_numnodes(vdev_queue_class_tree(vq, p)) > 0 && vq->vq_class[p].vqc_active < ! vdev_queue_class_min_active(p, vq)) return (p); } /* * If we haven't found a queue, look for one that hasn't reached its
*** 491,501 **** * maximum # outstanding i/os. */ for (p = 0; p < ZIO_PRIORITY_NUM_QUEUEABLE; p++) { if (avl_numnodes(vdev_queue_class_tree(vq, p)) > 0 && vq->vq_class[p].vqc_active < ! vdev_queue_class_max_active(spa, p)) return (p); } /* No eligible queued i/os */ return (ZIO_PRIORITY_NUM_QUEUEABLE); --- 613,623 ---- * maximum # outstanding i/os. */ for (p = 0; p < ZIO_PRIORITY_NUM_QUEUEABLE; p++) { if (avl_numnodes(vdev_queue_class_tree(vq, p)) > 0 && vq->vq_class[p].vqc_active < ! vdev_queue_class_max_active(spa, p, vq)) return (p); } /* No eligible queued i/os */ return (ZIO_PRIORITY_NUM_QUEUEABLE);
*** 548,559 **** * recording the last non-optional I/O. */ while ((dio = AVL_PREV(t, first)) != NULL && (dio->io_flags & ZIO_FLAG_AGG_INHERIT) == flags && IO_SPAN(dio, last) <= zfs_vdev_aggregation_limit && ! IO_GAP(dio, first) <= maxgap && ! dio->io_type == zio->io_type) { first = dio; if (mandatory == NULL && !(first->io_flags & ZIO_FLAG_OPTIONAL)) mandatory = first; } --- 670,680 ---- * recording the last non-optional I/O. */ while ((dio = AVL_PREV(t, first)) != NULL && (dio->io_flags & ZIO_FLAG_AGG_INHERIT) == flags && IO_SPAN(dio, last) <= zfs_vdev_aggregation_limit && ! IO_GAP(dio, first) <= maxgap) { first = dio; if (mandatory == NULL && !(first->io_flags & ZIO_FLAG_OPTIONAL)) mandatory = first; }
*** 573,584 **** */ while ((dio = AVL_NEXT(t, last)) != NULL && (dio->io_flags & ZIO_FLAG_AGG_INHERIT) == flags && (IO_SPAN(first, dio) <= zfs_vdev_aggregation_limit || (dio->io_flags & ZIO_FLAG_OPTIONAL)) && ! IO_GAP(last, dio) <= maxgap && ! dio->io_type == zio->io_type) { last = dio; if (!(last->io_flags & ZIO_FLAG_OPTIONAL)) mandatory = last; } --- 694,704 ---- */ while ((dio = AVL_NEXT(t, last)) != NULL && (dio->io_flags & ZIO_FLAG_AGG_INHERIT) == flags && (IO_SPAN(first, dio) <= zfs_vdev_aggregation_limit || (dio->io_flags & ZIO_FLAG_OPTIONAL)) && ! IO_GAP(last, dio) <= maxgap) { last = dio; if (!(last->io_flags & ZIO_FLAG_OPTIONAL)) mandatory = last; }
*** 733,750 **** * not match the child's i/o type. Fix it up here. */ if (zio->io_type == ZIO_TYPE_READ) { if (zio->io_priority != ZIO_PRIORITY_SYNC_READ && zio->io_priority != ZIO_PRIORITY_ASYNC_READ && ! zio->io_priority != ZIO_PRIORITY_SCRUB && ! zio->io_priority != ZIO_PRIORITY_REMOVAL) zio->io_priority = ZIO_PRIORITY_ASYNC_READ; } else { ASSERT(zio->io_type == ZIO_TYPE_WRITE); if (zio->io_priority != ZIO_PRIORITY_SYNC_WRITE && ! zio->io_priority != ZIO_PRIORITY_ASYNC_WRITE && ! zio->io_priority != ZIO_PRIORITY_REMOVAL) zio->io_priority = ZIO_PRIORITY_ASYNC_WRITE; } zio->io_flags |= ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_QUEUE; --- 853,868 ---- * not match the child's i/o type. Fix it up here. */ if (zio->io_type == ZIO_TYPE_READ) { if (zio->io_priority != ZIO_PRIORITY_SYNC_READ && zio->io_priority != ZIO_PRIORITY_ASYNC_READ && ! zio->io_priority != ZIO_PRIORITY_SCRUB) zio->io_priority = ZIO_PRIORITY_ASYNC_READ; } else { ASSERT(zio->io_type == ZIO_TYPE_WRITE); if (zio->io_priority != ZIO_PRIORITY_SYNC_WRITE && ! zio->io_priority != ZIO_PRIORITY_ASYNC_WRITE) zio->io_priority = ZIO_PRIORITY_ASYNC_WRITE; } zio->io_flags |= ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_QUEUE;
*** 787,792 **** --- 905,967 ---- } mutex_enter(&vq->vq_lock); } mutex_exit(&vq->vq_lock); + } + + uint64_t + vdev_queue_get_prop_uint64(vdev_queue_t *vq, vdev_prop_t p) + { + uint64_t val = 0; + int zprio = 0; + cos_t *cos = vq->vq_cos; + + switch (p) { + case VDEV_PROP_READ_MINACTIVE: + case VDEV_PROP_AREAD_MINACTIVE: + case VDEV_PROP_WRITE_MINACTIVE: + case VDEV_PROP_AWRITE_MINACTIVE: + case VDEV_PROP_SCRUB_MINACTIVE: + case VDEV_PROP_RESILVER_MINACTIVE: + zprio = VDEV_PROP_TO_ZIO_PRIO_MIN(p); + ASSERT(ZIO_PRIORITY_QUEUEABLE_VALID(zprio)); + if (vq->vq_cos != NULL) { + cos_prop_t p = COS_ZIO_PRIO_TO_PROP_MIN(zprio); + ASSERT(COS_PROP_MIN_VALID(p)); + val = cos_get_prop_uint64(vq->vq_cos, p); + } + if (val == 0) + val = vq->vq_class[zprio].vqc_min_active; + break; + case VDEV_PROP_READ_MAXACTIVE: + case VDEV_PROP_AREAD_MAXACTIVE: + case VDEV_PROP_WRITE_MAXACTIVE: + case VDEV_PROP_AWRITE_MAXACTIVE: + case VDEV_PROP_SCRUB_MAXACTIVE: + case VDEV_PROP_RESILVER_MAXACTIVE: + zprio = VDEV_PROP_TO_ZIO_PRIO_MAX(p); + ASSERT(ZIO_PRIORITY_QUEUEABLE_VALID(zprio)); + if (vq->vq_cos != NULL) { + cos_prop_t p = COS_ZIO_PRIO_TO_PROP_MAX(zprio); + ASSERT(COS_PROP_MAX_VALID(p)); + val = cos_get_prop_uint64(vq->vq_cos, p); + } + if (val == 0) + val = vq->vq_class[zprio].vqc_max_active; + break; + case VDEV_PROP_PREFERRED_READ: + if (vq->vq_cos != NULL) + val = cos_get_prop_uint64(vq->vq_cos, + COS_PROP_PREFERRED_READ); + if (val == 0) + val = vq->vq_preferred_read; + break; + default: + panic("Non-numeric property requested\n"); + return (0); + } + + VERIFY(cos == vq->vq_cos); + + return (val); }