Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2019 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "nvme_internal.h"
7 : : #include "nvme_io_msg.h"
8 : :
9 : : #define SPDK_NVME_MSG_IO_PROCESS_SIZE 8
10 : :
11 : : /**
12 : : * Send message to IO queue.
13 : : */
14 : : int
15 : 92 : nvme_io_msg_send(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, spdk_nvme_io_msg_fn fn,
16 : : void *arg)
17 : : {
18 : : int rc;
19 : 45 : struct spdk_nvme_io_msg *io;
20 : :
21 : : /* Protect requests ring against preemptive producers */
22 [ - + ]: 92 : pthread_mutex_lock(&ctrlr->external_io_msgs_lock);
23 : :
24 : 92 : io = (struct spdk_nvme_io_msg *)calloc(1, sizeof(struct spdk_nvme_io_msg));
25 [ - + ]: 92 : if (!io) {
26 : 0 : SPDK_ERRLOG("IO msg allocation failed.");
27 [ # # ]: 0 : pthread_mutex_unlock(&ctrlr->external_io_msgs_lock);
28 : 0 : return -ENOMEM;
29 : : }
30 : :
31 : 92 : io->ctrlr = ctrlr;
32 : 92 : io->nsid = nsid;
33 : 92 : io->fn = fn;
34 : 92 : io->arg = arg;
35 : :
36 : 92 : rc = spdk_ring_enqueue(ctrlr->external_io_msgs, (void **)&io, 1, NULL);
37 [ - + ]: 92 : if (rc != 1) {
38 : 0 : assert(false);
39 : : free(io);
40 : : pthread_mutex_unlock(&ctrlr->external_io_msgs_lock);
41 : : return -ENOMEM;
42 : : }
43 : :
44 [ - + ]: 92 : pthread_mutex_unlock(&ctrlr->external_io_msgs_lock);
45 : :
46 : 92 : return 0;
47 : : }
48 : :
49 : : int
50 : 35193033 : nvme_io_msg_process(struct spdk_nvme_ctrlr *ctrlr)
51 : : {
52 : : int i;
53 : : int count;
54 : : struct spdk_nvme_io_msg *io;
55 : 17532297 : void *requests[SPDK_NVME_MSG_IO_PROCESS_SIZE];
56 : :
57 [ + + ]: 35193033 : if (!spdk_process_is_primary()) {
58 : 28537967 : return 0;
59 : : }
60 : :
61 [ + + + - : 6655066 : if (!ctrlr->external_io_msgs || !ctrlr->external_io_msgs_qpair || ctrlr->prepare_for_reset) {
- + + + ]
62 : : /* Not ready or pending reset */
63 : 6652273 : return 0;
64 : : }
65 : :
66 [ - + + + ]: 2793 : if (ctrlr->needs_io_msg_update) {
67 : 5 : ctrlr->needs_io_msg_update = false;
68 : 5 : nvme_io_msg_ctrlr_update(ctrlr);
69 : : }
70 : :
71 : 2793 : spdk_nvme_qpair_process_completions(ctrlr->external_io_msgs_qpair, 0);
72 : :
73 : 2793 : count = spdk_ring_dequeue(ctrlr->external_io_msgs, requests,
74 : : SPDK_NVME_MSG_IO_PROCESS_SIZE);
75 [ + + ]: 2793 : if (count == 0) {
76 : 2741 : return 0;
77 : : }
78 : :
79 [ + + ]: 139 : for (i = 0; i < count; i++) {
80 : 87 : io = requests[i];
81 : :
82 [ - + ]: 87 : assert(io != NULL);
83 : :
84 : 87 : io->fn(io->ctrlr, io->nsid, io->arg);
85 : 87 : free(io);
86 : : }
87 : :
88 : 52 : return count;
89 : : }
90 : :
91 : : static bool
92 : 73 : nvme_io_msg_is_producer_registered(struct spdk_nvme_ctrlr *ctrlr,
93 : : struct nvme_io_msg_producer *io_msg_producer)
94 : : {
95 : : struct nvme_io_msg_producer *tmp;
96 : :
97 [ + + ]: 78 : STAILQ_FOREACH(tmp, &ctrlr->io_producers, link) {
98 [ + + ]: 42 : if (tmp == io_msg_producer) {
99 : 37 : return true;
100 : : }
101 : : }
102 : 36 : return false;
103 : : }
104 : :
105 : : int
106 : 42 : nvme_io_msg_ctrlr_register(struct spdk_nvme_ctrlr *ctrlr,
107 : : struct nvme_io_msg_producer *io_msg_producer)
108 : : {
109 [ - + ]: 42 : if (io_msg_producer == NULL) {
110 : 0 : SPDK_ERRLOG("io_msg_producer cannot be NULL\n");
111 : 0 : return -EINVAL;
112 : : }
113 : :
114 : 42 : nvme_ctrlr_lock(ctrlr);
115 [ + + ]: 42 : if (nvme_io_msg_is_producer_registered(ctrlr, io_msg_producer)) {
116 : 6 : nvme_ctrlr_unlock(ctrlr);
117 : 6 : return -EEXIST;
118 : : }
119 : :
120 [ + + - + : 36 : if (!STAILQ_EMPTY(&ctrlr->io_producers) || ctrlr->is_resetting) {
- + ]
121 : : /* There are registered producers - IO messaging already started */
122 : 5 : STAILQ_INSERT_TAIL(&ctrlr->io_producers, io_msg_producer, link);
123 : 5 : nvme_ctrlr_unlock(ctrlr);
124 : 5 : return 0;
125 : : }
126 : :
127 [ - + ]: 31 : pthread_mutex_init(&ctrlr->external_io_msgs_lock, NULL);
128 : :
129 : : /**
130 : : * Initialize ring and qpair for controller
131 : : */
132 : 31 : ctrlr->external_io_msgs = spdk_ring_create(SPDK_RING_TYPE_MP_SC, 65536, SPDK_ENV_SOCKET_ID_ANY);
133 [ - + ]: 31 : if (!ctrlr->external_io_msgs) {
134 : 0 : SPDK_ERRLOG("Unable to allocate memory for message ring\n");
135 : 0 : nvme_ctrlr_unlock(ctrlr);
136 : 0 : return -ENOMEM;
137 : : }
138 : :
139 : 31 : ctrlr->external_io_msgs_qpair = spdk_nvme_ctrlr_alloc_io_qpair(ctrlr, NULL, 0);
140 [ - + ]: 31 : if (ctrlr->external_io_msgs_qpair == NULL) {
141 : 0 : SPDK_ERRLOG("spdk_nvme_ctrlr_alloc_io_qpair() failed\n");
142 : 0 : spdk_ring_free(ctrlr->external_io_msgs);
143 : 0 : ctrlr->external_io_msgs = NULL;
144 : 0 : nvme_ctrlr_unlock(ctrlr);
145 : 0 : return -ENOMEM;
146 : : }
147 : :
148 : 31 : STAILQ_INSERT_TAIL(&ctrlr->io_producers, io_msg_producer, link);
149 : 31 : nvme_ctrlr_unlock(ctrlr);
150 : :
151 : 31 : return 0;
152 : : }
153 : :
154 : : void
155 : 119 : nvme_io_msg_ctrlr_update(struct spdk_nvme_ctrlr *ctrlr)
156 : : {
157 : : struct nvme_io_msg_producer *io_msg_producer;
158 : :
159 [ + + ]: 119 : if (!spdk_process_is_primary()) {
160 : 5 : ctrlr->needs_io_msg_update = true;
161 : 5 : return;
162 : : }
163 : :
164 : : /* Update all producers */
165 : 114 : nvme_ctrlr_lock(ctrlr);
166 [ + + ]: 122 : STAILQ_FOREACH(io_msg_producer, &ctrlr->io_producers, link) {
167 : 8 : io_msg_producer->update(ctrlr);
168 : : }
169 : 114 : nvme_ctrlr_unlock(ctrlr);
170 : : }
171 : :
172 : : void
173 : 2223 : nvme_io_msg_ctrlr_detach(struct spdk_nvme_ctrlr *ctrlr)
174 : : {
175 : : struct nvme_io_msg_producer *io_msg_producer, *tmp;
176 : :
177 [ - + ]: 2223 : if (!spdk_process_is_primary()) {
178 : 0 : return;
179 : : }
180 : :
181 : : /* Stop all producers */
182 [ + + ]: 2228 : STAILQ_FOREACH_SAFE(io_msg_producer, &ctrlr->io_producers, link, tmp) {
183 : 5 : io_msg_producer->stop(ctrlr);
184 [ + - + - : 5 : STAILQ_REMOVE(&ctrlr->io_producers, io_msg_producer, nvme_io_msg_producer, link);
- - - - ]
185 : : }
186 : :
187 [ + + ]: 2223 : if (ctrlr->external_io_msgs) {
188 : 31 : spdk_ring_free(ctrlr->external_io_msgs);
189 : 31 : ctrlr->external_io_msgs = NULL;
190 : : }
191 : :
192 [ + + ]: 2223 : if (ctrlr->external_io_msgs_qpair) {
193 : 31 : spdk_nvme_ctrlr_free_io_qpair(ctrlr->external_io_msgs_qpair);
194 : 31 : ctrlr->external_io_msgs_qpair = NULL;
195 : : }
196 : :
197 [ - + ]: 2223 : pthread_mutex_destroy(&ctrlr->external_io_msgs_lock);
198 : : }
199 : :
200 : : void
201 : 31 : nvme_io_msg_ctrlr_unregister(struct spdk_nvme_ctrlr *ctrlr,
202 : : struct nvme_io_msg_producer *io_msg_producer)
203 : : {
204 [ - + ]: 31 : assert(io_msg_producer != NULL);
205 : :
206 : 31 : nvme_ctrlr_lock(ctrlr);
207 [ - + ]: 31 : if (!nvme_io_msg_is_producer_registered(ctrlr, io_msg_producer)) {
208 : 0 : nvme_ctrlr_unlock(ctrlr);
209 : 0 : return;
210 : : }
211 : :
212 [ + - + + : 31 : STAILQ_REMOVE(&ctrlr->io_producers, io_msg_producer, nvme_io_msg_producer, link);
- - - - ]
213 [ + + ]: 31 : if (STAILQ_EMPTY(&ctrlr->io_producers)) {
214 : 26 : nvme_io_msg_ctrlr_detach(ctrlr);
215 : : }
216 : 31 : nvme_ctrlr_unlock(ctrlr);
217 : : }
|