int setup_io_work_queue(struct tcmu_device *dev) { struct tcmur_handler *r_handler = tcmu_get_runner_handler(dev); struct tcmur_device *rdev = tcmu_dev_get_private(dev); struct tcmu_io_queue *io_wq = &rdev->work_queue; int ret, i, nr_threads = r_handler->nr_threads; if (!nr_threads) return 0; list_head_init(&io_wq->io_queue); ret = pthread_mutex_init(&io_wq->io_lock, NULL); if (ret != 0) { goto out; } ret = pthread_cond_init(&io_wq->io_cond, NULL); if (ret != 0) { goto cleanup_lock; } /* TODO: Allow user to override device defaults */ io_wq->io_wq_threads = calloc(nr_threads, sizeof(pthread_t)); if (!io_wq->io_wq_threads) { ret = ENOMEM; goto cleanup_cond; } for (i = 0; i < nr_threads; i++) { ret = pthread_create(&io_wq->io_wq_threads[i], NULL, io_work_queue, dev); if (ret != 0) { goto cleanup_threads; } } return 0; cleanup_threads: cleanup_io_work_queue_threads(dev); free(io_wq->io_wq_threads); cleanup_cond: pthread_cond_destroy(&io_wq->io_cond); cleanup_lock: pthread_mutex_destroy(&io_wq->io_lock); out: return -ret; }
int async_handle_cmd(struct tcmu_device *dev, struct tcmulib_cmd *cmd, tcmu_work_fn_t work_fn) { struct tcmur_handler *rhandler = tcmu_get_runner_handler(dev); int ret; if (!rhandler->nr_threads) { ret = work_fn(dev, cmd); if (!ret) ret = TCMU_ASYNC_HANDLED; } else { ret = aio_schedule(dev, cmd, work_fn); } return ret; }
void cleanup_io_work_queue_threads(struct tcmu_device *dev) { struct tcmur_handler *r_handler = tcmu_get_runner_handler(dev); struct tcmur_device *rdev = tcmu_get_daemon_dev_private(dev); struct tcmu_io_queue *io_wq = &rdev->work_queue; int i, nr_threads = r_handler->nr_threads; if (!io_wq->io_wq_threads) { return; } for (i = 0; i < nr_threads; i++) { if (io_wq->io_wq_threads[i]) { cancel_thread(io_wq->io_wq_threads[i]); } } }