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}