| 861 | } |
| 862 | |
| 863 | static zio_t * |
| 864 | vdev_queue_io_to_issue(vdev_queue_t *vq) |
| 865 | { |
| 866 | zio_t *zio, *aio; |
| 867 | zio_priority_t p; |
| 868 | avl_index_t idx; |
| 869 | avl_tree_t *tree; |
| 870 | |
| 871 | again: |
| 872 | ASSERT(MUTEX_HELD(&vq->vq_lock)); |
| 873 | |
| 874 | p = vdev_queue_class_to_issue(vq); |
| 875 | |
| 876 | if (p == ZIO_PRIORITY_NUM_QUEUEABLE) { |
| 877 | /* No eligible queued i/os */ |
| 878 | return (NULL); |
| 879 | } |
| 880 | |
| 881 | /* |
| 882 | * For LBA-ordered queues (async / scrub / initializing), issue the |
| 883 | * i/o which follows the most recently issued i/o in LBA (offset) order. |
| 884 | * |
| 885 | * For FIFO queues (sync/trim), issue the i/o with the lowest timestamp. |
| 886 | */ |
| 887 | tree = vdev_queue_class_tree(vq, p); |
| 888 | vq->vq_io_search.io_timestamp = 0; |
| 889 | vq->vq_io_search.io_offset = vq->vq_last_offset - 1; |
| 890 | VERIFY3P(avl_find(tree, &vq->vq_io_search, &idx), ==, NULL); |
| 891 | zio = avl_nearest(tree, idx, AVL_AFTER); |
| 892 | if (zio == NULL) |
| 893 | zio = avl_first(tree); |
| 894 | ASSERT3U(zio->io_priority, ==, p); |
| 895 | |
| 896 | aio = vdev_queue_aggregate(vq, zio); |
| 897 | if (aio != NULL) |
| 898 | zio = aio; |
| 899 | else |
| 900 | vdev_queue_io_remove(vq, zio); |
| 901 | |
| 902 | /* |
| 903 | * If the I/O is or was optional and therefore has no data, we need to |
| 904 | * simply discard it. We need to drop the vdev queue's lock to avoid a |
| 905 | * deadlock that we could encounter since this I/O will complete |
| 906 | * immediately. |
| 907 | */ |
| 908 | if (zio->io_flags & ZIO_FLAG_NODATA) { |
| 909 | mutex_exit(&vq->vq_lock); |
| 910 | zio_vdev_io_bypass(zio); |
| 911 | zio_execute(zio); |
| 912 | mutex_enter(&vq->vq_lock); |
| 913 | goto again; |
| 914 | } |
| 915 | |
| 916 | vdev_queue_pending_add(vq, zio); |
| 917 | vq->vq_last_offset = zio->io_offset + zio->io_size; |
| 918 | |
| 919 | return (zio); |
| 920 | } |
no test coverage detected