nvmf_host.c (408572a24e55a4c9ff9f81d1403ec0e055841264) | nvmf_host.c (365b89e8ea4af34a05f68aa28e77573e89fa00b2) |
---|---|
1/*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2024 Chelsio Communications, Inc. 5 * Written by: John Baldwin <jhb@FreeBSD.org> 6 */ 7 8#include <sys/sysctl.h> --- 753 unchanged lines hidden (view full) --- 762 if (qp->nq_sqhd != qp->nq_sqtail) 763 return (false); 764 if (!TAILQ_EMPTY(&qp->nq_rx_capsules)) 765 return (false); 766 return (true); 767} 768 769static int | 1/*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2024 Chelsio Communications, Inc. 5 * Written by: John Baldwin <jhb@FreeBSD.org> 6 */ 7 8#include <sys/sysctl.h> --- 753 unchanged lines hidden (view full) --- 762 if (qp->nq_sqhd != qp->nq_sqtail) 763 return (false); 764 if (!TAILQ_EMPTY(&qp->nq_rx_capsules)) 765 return (false); 766 return (true); 767} 768 769static int |
770prepare_queues_for_handoff(struct nvmf_handoff_host *hh, 771 struct nvmf_qpair *admin_qp, u_int num_queues, 772 struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata) | 770prepare_queues_for_handoff(struct nvmf_ioc_nv *nv, struct nvmf_qpair *admin_qp, 771 u_int num_queues, struct nvmf_qpair **io_queues, 772 const struct nvme_controller_data *cdata) |
773{ | 773{ |
774 struct nvmf_handoff_qpair_params *io; | 774 nvlist_t *nvl, *nvl_qp; |
775 u_int i; 776 int error; 777 | 775 u_int i; 776 int error; 777 |
778 memset(hh, 0, sizeof(*hh)); | 778 if (num_queues == 0) 779 return (EINVAL); |
779 780 /* All queue pairs must be idle. */ 781 if (!is_queue_pair_idle(admin_qp)) 782 return (EBUSY); 783 for (i = 0; i < num_queues; i++) { 784 if (!is_queue_pair_idle(io_queues[i])) 785 return (EBUSY); 786 } 787 | 780 781 /* All queue pairs must be idle. */ 782 if (!is_queue_pair_idle(admin_qp)) 783 return (EBUSY); 784 for (i = 0; i < num_queues; i++) { 785 if (!is_queue_pair_idle(io_queues[i])) 786 return (EBUSY); 787 } 788 |
789 nvl = nvlist_create(0); 790 nvlist_add_number(nvl, "trtype", admin_qp->nq_association->na_trtype); 791 nvlist_add_number(nvl, "kato", admin_qp->nq_kato); 792 |
|
788 /* First, the admin queue. */ | 793 /* First, the admin queue. */ |
789 hh->trtype = admin_qp->nq_association->na_trtype; 790 hh->kato = admin_qp->nq_kato; 791 error = nvmf_kernel_handoff_params(admin_qp, &hh->admin); 792 if (error) | 794 error = nvmf_kernel_handoff_params(admin_qp, &nvl_qp); 795 if (error) { 796 nvlist_destroy(nvl); |
793 return (error); | 797 return (error); |
798 } 799 nvlist_move_nvlist(nvl, "admin", nvl_qp); |
|
794 795 /* Next, the I/O queues. */ | 800 801 /* Next, the I/O queues. */ |
796 hh->num_io_queues = num_queues; 797 io = calloc(num_queues, sizeof(*io)); | |
798 for (i = 0; i < num_queues; i++) { | 802 for (i = 0; i < num_queues; i++) { |
799 error = nvmf_kernel_handoff_params(io_queues[i], &io[i]); | 803 error = nvmf_kernel_handoff_params(io_queues[i], &nvl_qp); |
800 if (error) { | 804 if (error) { |
801 free(io); | 805 nvlist_destroy(nvl); |
802 return (error); 803 } | 806 return (error); 807 } |
808 nvlist_append_nvlist_array(nvl, "io", nvl_qp); |
|
804 } 805 | 809 } 810 |
806 hh->io = io; 807 hh->cdata = cdata; 808 return (0); | 811 nvlist_add_binary(nvl, "cdata", cdata, sizeof(*cdata)); 812 813 error = nvmf_pack_ioc_nvlist(nv, nvl); 814 nvlist_destroy(nvl); 815 return (error); |
809} 810 811int 812nvmf_handoff_host(struct nvmf_qpair *admin_qp, u_int num_queues, 813 struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata) 814{ | 816} 817 818int 819nvmf_handoff_host(struct nvmf_qpair *admin_qp, u_int num_queues, 820 struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata) 821{ |
815 struct nvmf_handoff_host hh; | 822 struct nvmf_ioc_nv nv; |
816 u_int i; 817 int error, fd; 818 819 fd = open("/dev/nvmf", O_RDWR); 820 if (fd == -1) { 821 error = errno; 822 goto out; 823 } 824 | 823 u_int i; 824 int error, fd; 825 826 fd = open("/dev/nvmf", O_RDWR); 827 if (fd == -1) { 828 error = errno; 829 goto out; 830 } 831 |
825 error = prepare_queues_for_handoff(&hh, admin_qp, num_queues, io_queues, | 832 error = prepare_queues_for_handoff(&nv, admin_qp, num_queues, io_queues, |
826 cdata); 827 if (error != 0) 828 goto out; 829 | 833 cdata); 834 if (error != 0) 835 goto out; 836 |
830 if (ioctl(fd, NVMF_HANDOFF_HOST, &hh) == -1) | 837 if (ioctl(fd, NVMF_HANDOFF_HOST, &nv) == -1) |
831 error = errno; | 838 error = errno; |
832 free(hh.io); | 839 free(nv.data); |
833 834out: 835 if (fd >= 0) 836 close(fd); 837 for (i = 0; i < num_queues; i++) 838 (void)nvmf_free_qpair(io_queues[i]); 839 (void)nvmf_free_qpair(admin_qp); 840 return (error); --- 36 unchanged lines hidden (view full) --- 877 error = errno; 878 879out: 880 if (fd >= 0) 881 close(fd); 882 return (error); 883} 884 | 840 841out: 842 if (fd >= 0) 843 close(fd); 844 for (i = 0; i < num_queues; i++) 845 (void)nvmf_free_qpair(io_queues[i]); 846 (void)nvmf_free_qpair(admin_qp); 847 return (error); --- 36 unchanged lines hidden (view full) --- 884 error = errno; 885 886out: 887 if (fd >= 0) 888 close(fd); 889 return (error); 890} 891 |
885int 886nvmf_reconnect_params(int fd, struct nvmf_reconnect_params *rparams) | 892static int 893nvmf_read_ioc_nv(int fd, u_long com, nvlist_t **nvlp) |
887{ | 894{ |
888 if (ioctl(fd, NVMF_RECONNECT_PARAMS, rparams) == -1) | 895 struct nvmf_ioc_nv nv; 896 nvlist_t *nvl; 897 int error; 898 899 memset(&nv, 0, sizeof(nv)); 900 if (ioctl(fd, com, &nv) == -1) |
889 return (errno); | 901 return (errno); |
902 903 nv.data = malloc(nv.len); 904 nv.size = nv.len; 905 if (ioctl(fd, com, &nv) == -1) { 906 error = errno; 907 free(nv.data); 908 return (error); 909 } 910 911 nvl = nvlist_unpack(nv.data, nv.len, 0); 912 free(nv.data); 913 if (nvl == NULL) 914 return (EINVAL); 915 916 *nvlp = nvl; |
|
890 return (0); 891} 892 893int | 917 return (0); 918} 919 920int |
921nvmf_reconnect_params(int fd, nvlist_t **nvlp) 922{ 923 return (nvmf_read_ioc_nv(fd, NVMF_RECONNECT_PARAMS, nvlp)); 924} 925 926int |
|
894nvmf_reconnect_host(int fd, struct nvmf_qpair *admin_qp, u_int num_queues, 895 struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata) 896{ | 927nvmf_reconnect_host(int fd, struct nvmf_qpair *admin_qp, u_int num_queues, 928 struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata) 929{ |
897 struct nvmf_handoff_host hh; | 930 struct nvmf_ioc_nv nv; |
898 u_int i; 899 int error; 900 | 931 u_int i; 932 int error; 933 |
901 error = prepare_queues_for_handoff(&hh, admin_qp, num_queues, io_queues, | 934 error = prepare_queues_for_handoff(&nv, admin_qp, num_queues, io_queues, |
902 cdata); 903 if (error != 0) 904 goto out; 905 | 935 cdata); 936 if (error != 0) 937 goto out; 938 |
906 if (ioctl(fd, NVMF_RECONNECT_HOST, &hh) == -1) | 939 if (ioctl(fd, NVMF_RECONNECT_HOST, &nv) == -1) |
907 error = errno; | 940 error = errno; |
908 free(hh.io); | 941 free(nv.data); |
909 910out: 911 for (i = 0; i < num_queues; i++) 912 (void)nvmf_free_qpair(io_queues[i]); 913 (void)nvmf_free_qpair(admin_qp); 914 return (error); 915} | 942 943out: 944 for (i = 0; i < num_queues; i++) 945 (void)nvmf_free_qpair(io_queues[i]); 946 (void)nvmf_free_qpair(admin_qp); 947 return (error); 948} |