Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests: ublk: kublk: move per-thread data out of ublk_queue

Towards the goal of decoupling ublk_queues from ublk server threads,
move resources/data that should be per-thread rather than per-queue out
of ublk_queue and into a new struct ublk_thread.

Signed-off-by: Uday Shankar <ushankar@purestorage.com>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20250529-ublk_task_per_io-v8-5-e9d3b119336a@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Uday Shankar and committed by
Jens Axboe
b9848ca7 8f75ba28

+144 -117
+119 -105
tools/testing/selftests/ublk/kublk.c
··· 348 348 349 349 for (i = 0; i < info->nr_hw_queues; i++) { 350 350 ublk_print_cpu_set(&affinity[i], buf, sizeof(buf)); 351 - printf("\tqueue %u: tid %d affinity(%s)\n", 352 - i, dev->q[i].tid, buf); 351 + printf("\tqueue %u: affinity(%s)\n", 352 + i, buf); 353 353 } 354 354 free(affinity); 355 355 } ··· 419 419 free(q->ios[i].buf_addr); 420 420 } 421 421 422 - static void ublk_thread_deinit(struct ublk_queue *q) 422 + static void ublk_thread_deinit(struct ublk_thread *t) 423 423 { 424 - q->tid = 0; 424 + io_uring_unregister_buffers(&t->ring); 425 425 426 - io_uring_unregister_buffers(&q->ring); 426 + io_uring_unregister_ring_fd(&t->ring); 427 427 428 - io_uring_unregister_ring_fd(&q->ring); 429 - 430 - if (q->ring.ring_fd > 0) { 431 - io_uring_unregister_files(&q->ring); 432 - close(q->ring.ring_fd); 433 - q->ring.ring_fd = -1; 428 + if (t->ring.ring_fd > 0) { 429 + io_uring_unregister_files(&t->ring); 430 + close(t->ring.ring_fd); 431 + t->ring.ring_fd = -1; 434 432 } 435 433 } 436 434 ··· 443 445 q->tgt_ops = dev->tgt.ops; 444 446 q->state = 0; 445 447 q->q_depth = depth; 446 - q->cmd_inflight = 0; 447 448 448 449 if (dev->dev_info.flags & (UBLK_F_SUPPORT_ZERO_COPY | UBLK_F_AUTO_BUF_REG)) { 449 450 q->state |= UBLKSRV_NO_BUF; ··· 467 470 for (i = 0; i < q->q_depth; i++) { 468 471 q->ios[i].buf_addr = NULL; 469 472 q->ios[i].flags = UBLKSRV_NEED_FETCH_RQ | UBLKSRV_IO_FREE; 473 + q->ios[i].tag = i; 470 474 471 475 if (q->state & UBLKSRV_NO_BUF) 472 476 continue; ··· 488 490 return -ENOMEM; 489 491 } 490 492 491 - static int ublk_thread_init(struct ublk_queue *q) 493 + static int ublk_thread_init(struct ublk_thread *t) 492 494 { 493 - struct ublk_dev *dev = q->dev; 495 + struct ublk_dev *dev = t->dev; 494 496 int ring_depth = dev->tgt.sq_depth, cq_depth = dev->tgt.cq_depth; 495 497 int ret; 496 498 497 - q->tid = gettid(); 498 - 499 - ret = ublk_setup_ring(&q->ring, ring_depth, cq_depth, 499 + ret = ublk_setup_ring(&t->ring, ring_depth, cq_depth, 500 500 IORING_SETUP_COOP_TASKRUN | 501 501 IORING_SETUP_SINGLE_ISSUER | 502 502 IORING_SETUP_DEFER_TASKRUN); 503 503 if (ret < 0) { 504 - ublk_err("ublk dev %d queue %d setup io_uring failed %d\n", 505 - q->dev->dev_info.dev_id, q->q_id, ret); 504 + ublk_err("ublk dev %d thread %d setup io_uring failed %d\n", 505 + dev->dev_info.dev_id, t->idx, ret); 506 506 goto fail; 507 507 } 508 508 509 509 if (dev->dev_info.flags & (UBLK_F_SUPPORT_ZERO_COPY | UBLK_F_AUTO_BUF_REG)) { 510 - ret = io_uring_register_buffers_sparse(&q->ring, q->q_depth); 510 + ret = io_uring_register_buffers_sparse( 511 + &t->ring, dev->dev_info.queue_depth); 511 512 if (ret) { 512 - ublk_err("ublk dev %d queue %d register spare buffers failed %d", 513 - dev->dev_info.dev_id, q->q_id, ret); 513 + ublk_err("ublk dev %d thread %d register spare buffers failed %d", 514 + dev->dev_info.dev_id, t->idx, ret); 514 515 goto fail; 515 516 } 516 517 } 517 518 518 - io_uring_register_ring_fd(&q->ring); 519 + io_uring_register_ring_fd(&t->ring); 519 520 520 - ret = io_uring_register_files(&q->ring, dev->fds, dev->nr_fds); 521 + ret = io_uring_register_files(&t->ring, dev->fds, dev->nr_fds); 521 522 if (ret) { 522 - ublk_err("ublk dev %d queue %d register files failed %d\n", 523 - q->dev->dev_info.dev_id, q->q_id, ret); 523 + ublk_err("ublk dev %d thread %d register files failed %d\n", 524 + t->dev->dev_info.dev_id, t->idx, ret); 524 525 goto fail; 525 526 } 526 527 527 528 return 0; 528 529 fail: 529 - ublk_thread_deinit(q); 530 - ublk_err("ublk dev %d queue %d thread init failed\n", 531 - dev->dev_info.dev_id, q->q_id); 530 + ublk_thread_deinit(t); 531 + ublk_err("ublk dev %d thread %d init failed\n", 532 + dev->dev_info.dev_id, t->idx); 532 533 return -ENOMEM; 533 534 } 534 535 ··· 586 589 sqe->addr = ublk_auto_buf_reg_to_sqe_addr(&buf); 587 590 } 588 591 589 - int ublk_queue_io_cmd(struct ublk_queue *q, struct ublk_io *io, unsigned tag) 592 + int ublk_queue_io_cmd(struct ublk_io *io) 590 593 { 594 + struct ublk_thread *t = io->t; 595 + struct ublk_queue *q = ublk_io_to_queue(io); 591 596 struct ublksrv_io_cmd *cmd; 592 597 struct io_uring_sqe *sqe[1]; 593 598 unsigned int cmd_op = 0; ··· 614 615 else if (io->flags & UBLKSRV_NEED_FETCH_RQ) 615 616 cmd_op = UBLK_U_IO_FETCH_REQ; 616 617 617 - if (io_uring_sq_space_left(&q->ring) < 1) 618 - io_uring_submit(&q->ring); 618 + if (io_uring_sq_space_left(&t->ring) < 1) 619 + io_uring_submit(&t->ring); 619 620 620 - ublk_io_alloc_sqes(ublk_get_io(q, tag), sqe, 1); 621 + ublk_io_alloc_sqes(io, sqe, 1); 621 622 if (!sqe[0]) { 622 - ublk_err("%s: run out of sqe %d, tag %d\n", 623 - __func__, q->q_id, tag); 623 + ublk_err("%s: run out of sqe. thread %u, tag %d\n", 624 + __func__, t->idx, io->tag); 624 625 return -1; 625 626 } 626 627 ··· 635 636 sqe[0]->opcode = IORING_OP_URING_CMD; 636 637 sqe[0]->flags = IOSQE_FIXED_FILE; 637 638 sqe[0]->rw_flags = 0; 638 - cmd->tag = tag; 639 + cmd->tag = io->tag; 639 640 cmd->q_id = q->q_id; 640 641 if (!(q->state & UBLKSRV_NO_BUF)) 641 642 cmd->addr = (__u64) (uintptr_t) io->buf_addr; ··· 643 644 cmd->addr = 0; 644 645 645 646 if (q->state & UBLKSRV_AUTO_BUF_REG) 646 - ublk_set_auto_buf_reg(q, sqe[0], tag); 647 + ublk_set_auto_buf_reg(q, sqe[0], io->tag); 647 648 648 - user_data = build_user_data(tag, _IOC_NR(cmd_op), 0, q->q_id, 0); 649 + user_data = build_user_data(io->tag, _IOC_NR(cmd_op), 0, q->q_id, 0); 649 650 io_uring_sqe_set_data64(sqe[0], user_data); 650 651 651 652 io->flags = 0; 652 653 653 - q->cmd_inflight += 1; 654 + t->cmd_inflight += 1; 654 655 655 - ublk_dbg(UBLK_DBG_IO_CMD, "%s: (qid %d tag %u cmd_op %u) iof %x stopping %d\n", 656 - __func__, q->q_id, tag, cmd_op, 657 - io->flags, !!(q->state & UBLKSRV_QUEUE_STOPPING)); 656 + ublk_dbg(UBLK_DBG_IO_CMD, "%s: (thread %u qid %d tag %u cmd_op %u) iof %x stopping %d\n", 657 + __func__, t->idx, q->q_id, io->tag, cmd_op, 658 + io->flags, !!(t->state & UBLKSRV_THREAD_STOPPING)); 658 659 return 1; 659 660 } 660 661 661 - static void ublk_submit_fetch_commands(struct ublk_queue *q) 662 + static void ublk_submit_fetch_commands(struct ublk_thread *t) 662 663 { 664 + /* 665 + * Service exclusively the queue whose q_id matches our thread 666 + * index. This may change in the future. 667 + */ 668 + struct ublk_queue *q = &t->dev->q[t->idx]; 669 + struct ublk_io *io; 663 670 int i = 0; 664 671 665 - for (i = 0; i < q->q_depth; i++) 666 - ublk_queue_io_cmd(q, &q->ios[i], i); 672 + for (i = 0; i < q->q_depth; i++) { 673 + io = &q->ios[i]; 674 + io->t = t; 675 + ublk_queue_io_cmd(io); 676 + } 667 677 } 668 678 669 - static int ublk_queue_is_idle(struct ublk_queue *q) 679 + static int ublk_thread_is_idle(struct ublk_thread *t) 670 680 { 671 - return !io_uring_sq_ready(&q->ring) && !q->io_inflight; 681 + return !io_uring_sq_ready(&t->ring) && !t->io_inflight; 672 682 } 673 683 674 - static int ublk_queue_is_done(struct ublk_queue *q) 684 + static int ublk_thread_is_done(struct ublk_thread *t) 675 685 { 676 - return (q->state & UBLKSRV_QUEUE_STOPPING) && ublk_queue_is_idle(q); 686 + return (t->state & UBLKSRV_THREAD_STOPPING) && ublk_thread_is_idle(t); 677 687 } 678 688 679 689 static inline void ublksrv_handle_tgt_cqe(struct ublk_queue *q, ··· 700 692 q->tgt_ops->tgt_io_done(q, tag, cqe); 701 693 } 702 694 703 - static void ublk_handle_cqe(struct ublk_dev *dev, 695 + static void ublk_handle_cqe(struct ublk_thread *t, 704 696 struct io_uring_cqe *cqe, void *data) 705 697 { 698 + struct ublk_dev *dev = t->dev; 706 699 unsigned q_id = user_data_to_q_id(cqe->user_data); 707 700 struct ublk_queue *q = &dev->q[q_id]; 708 701 unsigned tag = user_data_to_tag(cqe->user_data); 709 702 unsigned cmd_op = user_data_to_op(cqe->user_data); 710 703 int fetch = (cqe->res != UBLK_IO_RES_ABORT) && 711 - !(q->state & UBLKSRV_QUEUE_STOPPING); 704 + !(t->state & UBLKSRV_THREAD_STOPPING); 712 705 struct ublk_io *io; 713 706 714 707 if (cqe->res < 0 && cqe->res != -ENODEV) ··· 720 711 __func__, cqe->res, q->q_id, tag, cmd_op, 721 712 is_target_io(cqe->user_data), 722 713 user_data_to_tgt_data(cqe->user_data), 723 - (q->state & UBLKSRV_QUEUE_STOPPING)); 714 + (t->state & UBLKSRV_THREAD_STOPPING)); 724 715 725 716 /* Don't retrieve io in case of target io */ 726 717 if (is_target_io(cqe->user_data)) { ··· 729 720 } 730 721 731 722 io = &q->ios[tag]; 732 - q->cmd_inflight--; 723 + t->cmd_inflight--; 733 724 734 725 if (!fetch) { 735 - q->state |= UBLKSRV_QUEUE_STOPPING; 726 + t->state |= UBLKSRV_THREAD_STOPPING; 736 727 io->flags &= ~UBLKSRV_NEED_FETCH_RQ; 737 728 } 738 729 ··· 742 733 q->tgt_ops->queue_io(q, tag); 743 734 } else if (cqe->res == UBLK_IO_RES_NEED_GET_DATA) { 744 735 io->flags |= UBLKSRV_NEED_GET_DATA | UBLKSRV_IO_FREE; 745 - ublk_queue_io_cmd(q, io, tag); 736 + ublk_queue_io_cmd(io); 746 737 } else { 747 738 /* 748 739 * COMMIT_REQ will be completed immediately since no fetching ··· 756 747 } 757 748 } 758 749 759 - static int ublk_reap_events_uring(struct ublk_queue *q) 750 + static int ublk_reap_events_uring(struct ublk_thread *t) 760 751 { 761 752 struct io_uring_cqe *cqe; 762 753 unsigned head; 763 754 int count = 0; 764 755 765 - io_uring_for_each_cqe(&q->ring, head, cqe) { 766 - ublk_handle_cqe(q->dev, cqe, NULL); 756 + io_uring_for_each_cqe(&t->ring, head, cqe) { 757 + ublk_handle_cqe(t, cqe, NULL); 767 758 count += 1; 768 759 } 769 - io_uring_cq_advance(&q->ring, count); 760 + io_uring_cq_advance(&t->ring, count); 770 761 771 762 return count; 772 763 } 773 764 774 - static int ublk_process_io(struct ublk_queue *q) 765 + static int ublk_process_io(struct ublk_thread *t) 775 766 { 776 767 int ret, reapped; 777 768 778 - ublk_dbg(UBLK_DBG_QUEUE, "dev%d-q%d: to_submit %d inflight cmd %u stopping %d\n", 779 - q->dev->dev_info.dev_id, 780 - q->q_id, io_uring_sq_ready(&q->ring), 781 - q->cmd_inflight, 782 - (q->state & UBLKSRV_QUEUE_STOPPING)); 769 + ublk_dbg(UBLK_DBG_THREAD, "dev%d-t%u: to_submit %d inflight cmd %u stopping %d\n", 770 + t->dev->dev_info.dev_id, 771 + t->idx, io_uring_sq_ready(&t->ring), 772 + t->cmd_inflight, 773 + (t->state & UBLKSRV_THREAD_STOPPING)); 783 774 784 - if (ublk_queue_is_done(q)) 775 + if (ublk_thread_is_done(t)) 785 776 return -ENODEV; 786 777 787 - ret = io_uring_submit_and_wait(&q->ring, 1); 788 - reapped = ublk_reap_events_uring(q); 778 + ret = io_uring_submit_and_wait(&t->ring, 1); 779 + reapped = ublk_reap_events_uring(t); 789 780 790 - ublk_dbg(UBLK_DBG_QUEUE, "submit result %d, reapped %d stop %d idle %d\n", 791 - ret, reapped, (q->state & UBLKSRV_QUEUE_STOPPING), 792 - (q->state & UBLKSRV_QUEUE_IDLE)); 781 + ublk_dbg(UBLK_DBG_THREAD, "submit result %d, reapped %d stop %d idle %d\n", 782 + ret, reapped, (t->state & UBLKSRV_THREAD_STOPPING), 783 + (t->state & UBLKSRV_THREAD_IDLE)); 793 784 794 785 return reapped; 795 786 } 796 787 797 - static void ublk_queue_set_sched_affinity(const struct ublk_queue *q, 788 + static void ublk_thread_set_sched_affinity(const struct ublk_thread *t, 798 789 cpu_set_t *cpuset) 799 790 { 800 791 if (sched_setaffinity(0, sizeof(*cpuset), cpuset) < 0) 801 - ublk_err("ublk dev %u queue %u set affinity failed", 802 - q->dev->dev_info.dev_id, q->q_id); 792 + ublk_err("ublk dev %u thread %u set affinity failed", 793 + t->dev->dev_info.dev_id, t->idx); 803 794 } 804 795 805 - struct ublk_queue_info { 806 - struct ublk_queue *q; 807 - sem_t *queue_sem; 796 + struct ublk_thread_info { 797 + struct ublk_dev *dev; 798 + unsigned idx; 799 + sem_t *ready; 808 800 cpu_set_t *affinity; 809 801 }; 810 802 811 803 static void *ublk_io_handler_fn(void *data) 812 804 { 813 - struct ublk_queue_info *info = data; 814 - struct ublk_queue *q = info->q; 815 - int dev_id = q->dev->dev_info.dev_id; 805 + struct ublk_thread_info *info = data; 806 + struct ublk_thread *t = &info->dev->threads[info->idx]; 807 + int dev_id = info->dev->dev_info.dev_id; 816 808 int ret; 817 809 818 - ret = ublk_thread_init(q); 810 + t->dev = info->dev; 811 + t->idx = info->idx; 812 + 813 + ret = ublk_thread_init(t); 819 814 if (ret) { 820 - ublk_err("ublk dev %d queue %d thread init failed\n", 821 - dev_id, q->q_id); 815 + ublk_err("ublk dev %d thread %u init failed\n", 816 + dev_id, t->idx); 822 817 return NULL; 823 818 } 824 819 /* IO perf is sensitive with queue pthread affinity on NUMA machine*/ 825 - ublk_queue_set_sched_affinity(q, info->affinity); 826 - sem_post(info->queue_sem); 820 + ublk_thread_set_sched_affinity(t, info->affinity); 821 + sem_post(info->ready); 827 822 828 - ublk_dbg(UBLK_DBG_QUEUE, "tid %d: ublk dev %d queue %d started\n", 829 - q->tid, dev_id, q->q_id); 823 + ublk_dbg(UBLK_DBG_THREAD, "tid %d: ublk dev %d thread %u started\n", 824 + gettid(), dev_id, t->idx); 830 825 831 826 /* submit all io commands to ublk driver */ 832 - ublk_submit_fetch_commands(q); 827 + ublk_submit_fetch_commands(t); 833 828 do { 834 - if (ublk_process_io(q) < 0) 829 + if (ublk_process_io(t) < 0) 835 830 break; 836 831 } while (1); 837 832 838 - ublk_dbg(UBLK_DBG_QUEUE, "ublk dev %d queue %d exited\n", dev_id, q->q_id); 839 - ublk_thread_deinit(q); 833 + ublk_dbg(UBLK_DBG_THREAD, "tid %d: ublk dev %d thread %d exiting\n", 834 + gettid(), dev_id, t->idx); 835 + ublk_thread_deinit(t); 840 836 return NULL; 841 837 } 842 838 ··· 884 870 static int ublk_start_daemon(const struct dev_ctx *ctx, struct ublk_dev *dev) 885 871 { 886 872 const struct ublksrv_ctrl_dev_info *dinfo = &dev->dev_info; 887 - struct ublk_queue_info *qinfo; 873 + struct ublk_thread_info *tinfo; 888 874 unsigned extra_flags = 0; 889 875 cpu_set_t *affinity_buf; 890 876 void *thread_ret; 891 - sem_t queue_sem; 877 + sem_t ready; 892 878 int ret, i; 893 879 894 880 ublk_dbg(UBLK_DBG_DEV, "%s enter\n", __func__); 895 881 896 - qinfo = (struct ublk_queue_info *)calloc(sizeof(struct ublk_queue_info), 897 - dinfo->nr_hw_queues); 898 - if (!qinfo) 882 + tinfo = calloc(sizeof(struct ublk_thread_info), dinfo->nr_hw_queues); 883 + if (!tinfo) 899 884 return -ENOMEM; 900 885 901 - sem_init(&queue_sem, 0, 0); 886 + sem_init(&ready, 0, 0); 902 887 ret = ublk_dev_prep(ctx, dev); 903 888 if (ret) 904 889 return ret; ··· 920 907 goto fail; 921 908 } 922 909 923 - qinfo[i].q = &dev->q[i]; 924 - qinfo[i].queue_sem = &queue_sem; 925 - qinfo[i].affinity = &affinity_buf[i]; 926 - pthread_create(&dev->q[i].thread, NULL, 910 + tinfo[i].dev = dev; 911 + tinfo[i].idx = i; 912 + tinfo[i].ready = &ready; 913 + tinfo[i].affinity = &affinity_buf[i]; 914 + pthread_create(&dev->threads[i].thread, NULL, 927 915 ublk_io_handler_fn, 928 - &qinfo[i]); 916 + &tinfo[i]); 929 917 } 930 918 931 919 for (i = 0; i < dinfo->nr_hw_queues; i++) 932 - sem_wait(&queue_sem); 933 - free(qinfo); 920 + sem_wait(&ready); 921 + free(tinfo); 934 922 free(affinity_buf); 935 923 936 924 /* everything is fine now, start us */ ··· 954 940 955 941 /* wait until we are terminated */ 956 942 for (i = 0; i < dinfo->nr_hw_queues; i++) 957 - pthread_join(dev->q[i].thread, &thread_ret); 943 + pthread_join(dev->threads[i].thread, &thread_ret); 958 944 fail: 959 945 for (i = 0; i < dinfo->nr_hw_queues; i++) 960 946 ublk_queue_deinit(&dev->q[i]);
+25 -12
tools/testing/selftests/ublk/kublk.h
··· 51 51 #define UBLK_IO_MAX_BYTES (1 << 20) 52 52 #define UBLK_MAX_QUEUES_SHIFT 5 53 53 #define UBLK_MAX_QUEUES (1 << UBLK_MAX_QUEUES_SHIFT) 54 + #define UBLK_MAX_THREADS_SHIFT 5 55 + #define UBLK_MAX_THREADS (1 << UBLK_MAX_THREADS_SHIFT) 54 56 #define UBLK_QUEUE_DEPTH 1024 55 57 56 58 #define UBLK_DBG_DEV (1U << 0) 57 - #define UBLK_DBG_QUEUE (1U << 1) 59 + #define UBLK_DBG_THREAD (1U << 1) 58 60 #define UBLK_DBG_IO_CMD (1U << 2) 59 61 #define UBLK_DBG_IO (1U << 3) 60 62 #define UBLK_DBG_CTRL_CMD (1U << 4) ··· 64 62 65 63 struct ublk_dev; 66 64 struct ublk_queue; 65 + struct ublk_thread; 67 66 68 67 struct stripe_ctx { 69 68 /* stripe */ ··· 133 130 134 131 unsigned short tgt_ios; 135 132 void *private_data; 133 + struct ublk_thread *t; 136 134 }; 137 135 138 136 struct ublk_tgt_ops { ··· 172 168 struct ublk_queue { 173 169 int q_id; 174 170 int q_depth; 175 - unsigned int cmd_inflight; 176 - unsigned int io_inflight; 177 171 struct ublk_dev *dev; 178 172 const struct ublk_tgt_ops *tgt_ops; 179 173 struct ublksrv_io_desc *io_cmd_buf; 180 - struct io_uring ring; 174 + 181 175 struct ublk_io ios[UBLK_QUEUE_DEPTH]; 182 - #define UBLKSRV_QUEUE_STOPPING (1U << 0) 183 - #define UBLKSRV_QUEUE_IDLE (1U << 1) 184 176 #define UBLKSRV_NO_BUF (1U << 2) 185 177 #define UBLKSRV_ZC (1U << 3) 186 178 #define UBLKSRV_AUTO_BUF_REG (1U << 4) 187 179 #define UBLKSRV_AUTO_BUF_REG_FALLBACK (1U << 5) 188 180 unsigned state; 189 - pid_t tid; 181 + }; 182 + 183 + struct ublk_thread { 184 + struct ublk_dev *dev; 185 + struct io_uring ring; 186 + unsigned int cmd_inflight; 187 + unsigned int io_inflight; 188 + 190 189 pthread_t thread; 190 + unsigned idx; 191 + 192 + #define UBLKSRV_THREAD_STOPPING (1U << 0) 193 + #define UBLKSRV_THREAD_IDLE (1U << 1) 194 + unsigned state; 191 195 }; 192 196 193 197 struct ublk_dev { 194 198 struct ublk_tgt tgt; 195 199 struct ublksrv_ctrl_dev_info dev_info; 196 200 struct ublk_queue q[UBLK_MAX_QUEUES]; 201 + struct ublk_thread threads[UBLK_MAX_THREADS]; 197 202 198 203 int fds[MAX_BACK_FILES + 1]; /* fds[0] points to /dev/ublkcN */ 199 204 int nr_fds; ··· 227 214 228 215 229 216 extern unsigned int ublk_dbg_mask; 230 - extern int ublk_queue_io_cmd(struct ublk_queue *q, struct ublk_io *io, unsigned tag); 217 + extern int ublk_queue_io_cmd(struct ublk_io *io); 231 218 232 219 233 220 static inline int ublk_io_auto_zc_fallback(const struct ublksrv_io_desc *iod) ··· 312 299 static inline int ublk_io_alloc_sqes(struct ublk_io *io, 313 300 struct io_uring_sqe *sqes[], int nr_sqes) 314 301 { 315 - struct io_uring *ring = &ublk_io_to_queue(io)->ring; 302 + struct io_uring *ring = &io->t->ring; 316 303 unsigned left = io_uring_sq_space_left(ring); 317 304 int i; 318 305 ··· 403 390 404 391 ublk_mark_io_done(io, res); 405 392 406 - return ublk_queue_io_cmd(q, io, tag); 393 + return ublk_queue_io_cmd(io); 407 394 } 408 395 409 396 static inline void ublk_queued_tgt_io(struct ublk_queue *q, unsigned tag, int queued) ··· 413 400 else { 414 401 struct ublk_io *io = ublk_get_io(q, tag); 415 402 416 - q->io_inflight += queued; 403 + io->t->io_inflight += queued; 417 404 io->tgt_ios = queued; 418 405 io->result = 0; 419 406 } ··· 423 410 { 424 411 struct ublk_io *io = ublk_get_io(q, tag); 425 412 426 - q->io_inflight--; 413 + io->t->io_inflight--; 427 414 428 415 return --io->tgt_ios == 0; 429 416 }