Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright (C) 2020 Intel Corporation. All rights reserved.
3 : * Copyright (c) 2019, 2021 Mellanox Technologies LTD. All rights reserved.
4 : */
5 :
6 : /** \file
7 : * NVMe-oF Target transport plugin API
8 : */
9 :
10 : #ifndef SPDK_NVMF_TRANSPORT_H_
11 : #define SPDK_NVMF_TRANSPORT_H_
12 :
13 : #include "spdk/bdev.h"
14 : #include "spdk/thread.h"
15 : #include "spdk/nvme_spec.h"
16 : #include "spdk/nvmf.h"
17 : #include "spdk/nvmf_cmd.h"
18 : #include "spdk/nvmf_spec.h"
19 : #include "spdk/memory.h"
20 : #include "spdk/trace.h"
21 :
22 : #ifdef __cplusplus
23 : extern "C" {
24 : #endif
25 :
26 : #define SPDK_NVMF_MAX_SGL_ENTRIES 16
27 :
28 : /* The maximum number of buffers per request */
29 : #define NVMF_REQ_MAX_BUFFERS (SPDK_NVMF_MAX_SGL_ENTRIES * 2 + 1)
30 :
31 : /* Maximum pending AERs that can be migrated */
32 : #define SPDK_NVMF_MIGR_MAX_PENDING_AERS 256
33 :
34 : #define SPDK_NVMF_MAX_ASYNC_EVENTS 4
35 :
36 : /* Some backends require 4K aligned buffers. The iobuf library gives us that
37 : * naturally, but there are buffers allocated other ways that need to use this.
38 : */
39 : #define NVMF_DATA_BUFFER_ALIGNMENT VALUE_4KB
40 : #define NVMF_DATA_BUFFER_MASK (NVMF_DATA_BUFFER_ALIGNMENT - 1LL)
41 :
42 : #define SPDK_NVMF_DEFAULT_ACCEPT_POLL_RATE_US 10000
43 :
44 : union nvmf_h2c_msg {
45 : struct spdk_nvmf_capsule_cmd nvmf_cmd;
46 : struct spdk_nvme_cmd nvme_cmd;
47 : struct spdk_nvmf_fabric_prop_set_cmd prop_set_cmd;
48 : struct spdk_nvmf_fabric_prop_get_cmd prop_get_cmd;
49 : struct spdk_nvmf_fabric_connect_cmd connect_cmd;
50 : struct spdk_nvmf_fabric_auth_send_cmd auth_send_cmd;
51 : struct spdk_nvmf_fabric_auth_recv_cmd auth_recv_cmd;
52 : };
53 : SPDK_STATIC_ASSERT(sizeof(union nvmf_h2c_msg) == 64, "Incorrect size");
54 :
55 : union nvmf_c2h_msg {
56 : struct spdk_nvme_cpl nvme_cpl;
57 : struct spdk_nvmf_fabric_prop_get_rsp prop_get_rsp;
58 : struct spdk_nvmf_fabric_connect_rsp connect_rsp;
59 : };
60 : SPDK_STATIC_ASSERT(sizeof(union nvmf_c2h_msg) == 16, "Incorrect size");
61 :
62 : struct spdk_nvmf_dif_info {
63 : struct spdk_dif_ctx dif_ctx;
64 : uint32_t elba_length;
65 : uint32_t orig_length;
66 : };
67 :
68 : struct spdk_nvmf_stripped_data {
69 : uint32_t iovcnt;
70 : struct iovec iov[NVMF_REQ_MAX_BUFFERS];
71 : };
72 :
73 : enum spdk_nvmf_zcopy_phase {
74 : NVMF_ZCOPY_PHASE_NONE, /* Request is not using ZCOPY */
75 : NVMF_ZCOPY_PHASE_INIT, /* Requesting Buffers */
76 : NVMF_ZCOPY_PHASE_EXECUTE, /* Got buffers processing commands */
77 : NVMF_ZCOPY_PHASE_END_PENDING, /* Releasing buffers */
78 : NVMF_ZCOPY_PHASE_COMPLETE, /* Buffers Released */
79 : NVMF_ZCOPY_PHASE_INIT_FAILED /* Failed to get the buffers */
80 : };
81 :
82 : struct spdk_nvmf_request {
83 : struct spdk_nvmf_qpair *qpair;
84 : uint32_t length;
85 : uint8_t xfer; /* type enum spdk_nvme_data_transfer */
86 : union {
87 : uint8_t raw;
88 : struct {
89 : uint8_t data_from_pool : 1;
90 : uint8_t dif_enabled : 1;
91 : uint8_t first_fused : 1;
92 : uint8_t rsvd : 5;
93 : };
94 : };
95 : uint8_t zcopy_phase; /* type enum spdk_nvmf_zcopy_phase */
96 : uint8_t iovcnt;
97 : union nvmf_h2c_msg *cmd;
98 : union nvmf_c2h_msg *rsp;
99 : STAILQ_ENTRY(spdk_nvmf_request) buf_link;
100 : TAILQ_ENTRY(spdk_nvmf_request) link;
101 :
102 : /* Memory domain which describes payload in this request. If the bdev doesn't support memory
103 : * domains, bdev layer will do the necessary push or pull operation. */
104 : struct spdk_memory_domain *memory_domain;
105 : /* Context to be passed to memory domain operations. */
106 : void *memory_domain_ctx;
107 : struct spdk_accel_sequence *accel_sequence;
108 :
109 : struct iovec iov[NVMF_REQ_MAX_BUFFERS];
110 :
111 : struct spdk_nvmf_stripped_data *stripped_data;
112 :
113 : struct spdk_nvmf_dif_info dif;
114 :
115 : struct spdk_bdev_io_wait_entry bdev_io_wait;
116 : spdk_nvmf_nvme_passthru_cmd_cb cmd_cb_fn;
117 : struct spdk_nvmf_request *first_fused_req;
118 : struct spdk_nvmf_request *req_to_abort;
119 : struct spdk_poller *poller;
120 : struct spdk_bdev_io *zcopy_bdev_io; /* Contains the bdev_io when using ZCOPY */
121 :
122 : /* Timeout tracked for connect and abort flows. */
123 : uint64_t timeout_tsc;
124 : };
125 : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_request) == 776, "Incorrect size");
126 :
127 : enum spdk_nvmf_qpair_state {
128 : SPDK_NVMF_QPAIR_UNINITIALIZED = 0,
129 : SPDK_NVMF_QPAIR_CONNECTING,
130 : SPDK_NVMF_QPAIR_AUTHENTICATING,
131 : SPDK_NVMF_QPAIR_ENABLED,
132 : SPDK_NVMF_QPAIR_DEACTIVATING,
133 : SPDK_NVMF_QPAIR_ERROR,
134 : };
135 :
136 : typedef void (*spdk_nvmf_state_change_done)(void *cb_arg, int status);
137 :
138 : struct spdk_nvmf_qpair_auth;
139 :
140 : struct spdk_nvmf_qpair {
141 : uint8_t state; /* ref spdk_nvmf_qpair_state */
142 : uint8_t rsvd;
143 : uint16_t qid;
144 : uint16_t sq_head;
145 : uint16_t sq_head_max;
146 :
147 : struct spdk_nvmf_transport *transport;
148 : struct spdk_nvmf_ctrlr *ctrlr;
149 : struct spdk_nvmf_poll_group *group;
150 :
151 : union {
152 : struct spdk_nvmf_request *first_fused_req;
153 : struct spdk_nvmf_request *connect_req;
154 : };
155 :
156 : TAILQ_HEAD(, spdk_nvmf_request) outstanding;
157 : TAILQ_ENTRY(spdk_nvmf_qpair) link;
158 :
159 : spdk_nvmf_state_change_done state_cb;
160 : void *state_cb_arg;
161 :
162 : bool connect_received;
163 : bool disconnect_started;
164 :
165 : uint16_t trace_id;
166 :
167 : /* Number of IO outstanding at transport level */
168 : uint16_t queue_depth;
169 :
170 : struct spdk_nvmf_qpair_auth *auth;
171 : };
172 :
173 : struct spdk_nvmf_transport_poll_group {
174 : struct spdk_nvmf_transport *transport;
175 : /* Requests that are waiting to obtain a data buffer */
176 : STAILQ_HEAD(, spdk_nvmf_request) pending_buf_queue;
177 : struct spdk_iobuf_channel *buf_cache;
178 : struct spdk_nvmf_poll_group *group;
179 : TAILQ_ENTRY(spdk_nvmf_transport_poll_group) link;
180 : };
181 :
182 : struct spdk_nvmf_poll_group {
183 : struct spdk_thread *thread;
184 : struct spdk_poller *poller;
185 :
186 : TAILQ_HEAD(, spdk_nvmf_transport_poll_group) tgroups;
187 :
188 : /* Array of poll groups indexed by subsystem id (sid) */
189 : struct spdk_nvmf_subsystem_poll_group *sgroups;
190 : uint32_t num_sgroups;
191 :
192 : /* Protected by mutex. Counts qpairs that have connected at a
193 : * transport level, but are not associated with a subsystem
194 : * or controller yet (because the CONNECT capsule hasn't
195 : * been received). */
196 : uint32_t current_unassociated_qpairs;
197 :
198 : /* All of the queue pairs that belong to this poll group */
199 : TAILQ_HEAD(, spdk_nvmf_qpair) qpairs;
200 :
201 : /* Statistics */
202 : struct spdk_nvmf_poll_group_stat stat;
203 :
204 : spdk_nvmf_poll_group_destroy_done_fn destroy_cb_fn;
205 : void *destroy_cb_arg;
206 :
207 : struct spdk_nvmf_tgt *tgt;
208 :
209 : TAILQ_ENTRY(spdk_nvmf_poll_group) link;
210 :
211 : pthread_mutex_t mutex;
212 : };
213 :
214 : struct spdk_nvmf_listener {
215 : struct spdk_nvme_transport_id trid;
216 : uint32_t ref;
217 :
218 : TAILQ_ENTRY(spdk_nvmf_listener) link;
219 : };
220 :
221 : /**
222 : * A subset of struct spdk_nvme_ctrlr_data that are emulated by a fabrics device.
223 : */
224 : struct spdk_nvmf_ctrlr_data {
225 : uint8_t aerl;
226 : uint16_t kas;
227 : /** pci vendor id */
228 : uint16_t vid;
229 : /** pci subsystem vendor id */
230 : uint16_t ssvid;
231 : /** ieee oui identifier */
232 : uint8_t ieee[3];
233 : struct spdk_nvme_cdata_oacs oacs;
234 : struct spdk_nvme_cdata_oncs oncs;
235 : struct spdk_nvme_cdata_fuses fuses;
236 : struct spdk_nvme_cdata_sgls sgls;
237 : struct spdk_nvme_cdata_nvmf_specific nvmf_specific;
238 : };
239 :
240 : #define MAX_MEMPOOL_NAME_LENGTH 40
241 :
242 : struct spdk_nvmf_transport {
243 : struct spdk_nvmf_tgt *tgt;
244 : const struct spdk_nvmf_transport_ops *ops;
245 : struct spdk_nvmf_transport_opts opts;
246 :
247 : char iobuf_name[MAX_MEMPOOL_NAME_LENGTH];
248 :
249 : TAILQ_HEAD(, spdk_nvmf_listener) listeners;
250 : TAILQ_ENTRY(spdk_nvmf_transport) link;
251 :
252 : pthread_mutex_t mutex;
253 : };
254 :
255 : typedef void (*spdk_nvmf_transport_qpair_fini_cb)(void *cb_arg);
256 :
257 : struct spdk_nvmf_transport_ops {
258 : /**
259 : * Transport name
260 : */
261 : char name[SPDK_NVMF_TRSTRING_MAX_LEN];
262 :
263 : /**
264 : * Transport type
265 : */
266 : enum spdk_nvme_transport_type type;
267 :
268 : /**
269 : * Initialize transport options to default value
270 : */
271 : void (*opts_init)(struct spdk_nvmf_transport_opts *opts);
272 :
273 : /**
274 : * Create a transport for the given transport opts. Either synchronous
275 : * or asynchronous version shall be implemented.
276 : */
277 : struct spdk_nvmf_transport *(*create)(struct spdk_nvmf_transport_opts *opts);
278 : int (*create_async)(struct spdk_nvmf_transport_opts *opts, spdk_nvmf_transport_create_done_cb cb_fn,
279 : void *cb_arg);
280 :
281 : /**
282 : * Dump transport-specific opts into JSON
283 : */
284 : void (*dump_opts)(struct spdk_nvmf_transport *transport,
285 : struct spdk_json_write_ctx *w);
286 :
287 : /**
288 : * Destroy the transport
289 : */
290 : int (*destroy)(struct spdk_nvmf_transport *transport,
291 : spdk_nvmf_transport_destroy_done_cb cb_fn, void *cb_arg);
292 :
293 : /**
294 : * Instruct the transport to accept new connections at the address
295 : * provided. This may be called multiple times.
296 : */
297 : int (*listen)(struct spdk_nvmf_transport *transport, const struct spdk_nvme_transport_id *trid,
298 : struct spdk_nvmf_listen_opts *opts);
299 :
300 : /**
301 : * Dump transport-specific listen opts into JSON
302 : */
303 : void (*listen_dump_opts)(struct spdk_nvmf_transport *transport,
304 : const struct spdk_nvme_transport_id *trid, struct spdk_json_write_ctx *w);
305 :
306 : /**
307 : * Stop accepting new connections at the given address.
308 : */
309 : void (*stop_listen)(struct spdk_nvmf_transport *transport,
310 : const struct spdk_nvme_transport_id *trid);
311 :
312 : /**
313 : * It is a notification that a listener is being associated with the subsystem.
314 : * Most transports will not need to take any action here, as the enforcement
315 : * of the association is done in the generic code.
316 : *
317 : * Returns a negated errno code to block the association. 0 to allow.
318 : */
319 : int (*listen_associate)(struct spdk_nvmf_transport *transport,
320 : const struct spdk_nvmf_subsystem *subsystem,
321 : const struct spdk_nvme_transport_id *trid);
322 :
323 : /**
324 : * It is a notification that a namespace is being added to the subsystem.
325 : * Most transports will not need to take any action here.
326 : *
327 : * Returns a negated errno code to block the attachment. 0 to allow.
328 : */
329 : int (*subsystem_add_ns)(struct spdk_nvmf_transport *transport,
330 : const struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ns *ns);
331 :
332 : /**
333 : * It is a notification that a namespace has been removed from the subsystem.
334 : * Most transports will not need to take any action here.
335 : */
336 : void (*subsystem_remove_ns)(struct spdk_nvmf_transport *transport,
337 : const struct spdk_nvmf_subsystem *subsystem, uint32_t nsid);
338 :
339 : /**
340 : * Initialize subset of identify controller data.
341 : */
342 : void (*cdata_init)(struct spdk_nvmf_transport *transport, struct spdk_nvmf_subsystem *subsystem,
343 : struct spdk_nvmf_ctrlr_data *cdata);
344 :
345 : /**
346 : * Fill out a discovery log entry for a specific listen address.
347 : */
348 : void (*listener_discover)(struct spdk_nvmf_transport *transport,
349 : struct spdk_nvme_transport_id *trid,
350 : struct spdk_nvmf_discovery_log_page_entry *entry);
351 :
352 : /**
353 : * Create a new poll group
354 : */
355 : struct spdk_nvmf_transport_poll_group *(*poll_group_create)(struct spdk_nvmf_transport *transport,
356 : struct spdk_nvmf_poll_group *group);
357 :
358 : /**
359 : * Get the polling group of the queue pair optimal for the specific transport
360 : */
361 : struct spdk_nvmf_transport_poll_group *(*get_optimal_poll_group)(struct spdk_nvmf_qpair *qpair);
362 :
363 : /**
364 : * Destroy a poll group
365 : */
366 : void (*poll_group_destroy)(struct spdk_nvmf_transport_poll_group *group);
367 :
368 : /**
369 : * Add a qpair to a poll group
370 : */
371 : int (*poll_group_add)(struct spdk_nvmf_transport_poll_group *group,
372 : struct spdk_nvmf_qpair *qpair);
373 :
374 : /**
375 : * Remove a qpair from a poll group
376 : */
377 : int (*poll_group_remove)(struct spdk_nvmf_transport_poll_group *group,
378 : struct spdk_nvmf_qpair *qpair);
379 :
380 : /**
381 : * Poll the group to process I/O
382 : */
383 : int (*poll_group_poll)(struct spdk_nvmf_transport_poll_group *group);
384 :
385 : /*
386 : * Free the request without sending a response
387 : * to the originator. Release memory tied to this request.
388 : */
389 : int (*req_free)(struct spdk_nvmf_request *req);
390 :
391 : /*
392 : * Signal request completion, which sends a response
393 : * to the originator.
394 : */
395 : int (*req_complete)(struct spdk_nvmf_request *req);
396 :
397 : /*
398 : * Deinitialize a connection.
399 : */
400 : void (*qpair_fini)(struct spdk_nvmf_qpair *qpair,
401 : spdk_nvmf_transport_qpair_fini_cb cb_fn,
402 : void *cb_args);
403 :
404 : /*
405 : * Get the peer transport ID for the queue pair.
406 : */
407 : int (*qpair_get_peer_trid)(struct spdk_nvmf_qpair *qpair,
408 : struct spdk_nvme_transport_id *trid);
409 :
410 : /*
411 : * Get the local transport ID for the queue pair.
412 : */
413 : int (*qpair_get_local_trid)(struct spdk_nvmf_qpair *qpair,
414 : struct spdk_nvme_transport_id *trid);
415 :
416 : /*
417 : * Get the listener transport ID that accepted this qpair originally.
418 : */
419 : int (*qpair_get_listen_trid)(struct spdk_nvmf_qpair *qpair,
420 : struct spdk_nvme_transport_id *trid);
421 :
422 : /*
423 : * Abort the request which the abort request specifies.
424 : * This function can complete synchronously or asynchronously, but
425 : * is expected to call spdk_nvmf_request_complete() in the end
426 : * for both cases.
427 : */
428 : void (*qpair_abort_request)(struct spdk_nvmf_qpair *qpair,
429 : struct spdk_nvmf_request *req);
430 :
431 : /*
432 : * Dump transport poll group statistics into JSON.
433 : */
434 : void (*poll_group_dump_stat)(struct spdk_nvmf_transport_poll_group *group,
435 : struct spdk_json_write_ctx *w);
436 :
437 : /*
438 : * A notification that a subsystem has been configured to allow access
439 : * from the given host.
440 : * This callback is optional and not all transports need to implement it.
441 : */
442 : int (*subsystem_add_host)(struct spdk_nvmf_transport *transport,
443 : const struct spdk_nvmf_subsystem *subsystem,
444 : const char *hostnqn,
445 : const struct spdk_json_val *transport_specific);
446 :
447 : /*
448 : * A notification that a subsystem is no longer configured to allow access
449 : * from the given host.
450 : * This callback is optional and not all transports need to implement it.
451 : */
452 : void (*subsystem_remove_host)(struct spdk_nvmf_transport *transport,
453 : const struct spdk_nvmf_subsystem *subsystem,
454 : const char *hostnqn);
455 :
456 : /*
457 : * A callback used to dump subsystem's host data for a specific transport.
458 : * This callback is optional and not all transports need to implement it.
459 : */
460 : void (*subsystem_dump_host)(struct spdk_nvmf_transport *transport,
461 : const struct spdk_nvmf_subsystem *subsystem,
462 : const char *hostnqn, struct spdk_json_write_ctx *w);
463 : };
464 :
465 : /**
466 : * Register the operations for a given transport type.
467 : *
468 : * This function should be invoked by referencing the macro
469 : * SPDK_NVMF_TRANSPORT_REGISTER macro in the transport's .c file.
470 : *
471 : * \param ops The operations associated with an NVMe-oF transport.
472 : */
473 : void spdk_nvmf_transport_register(const struct spdk_nvmf_transport_ops *ops);
474 :
475 : int spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req);
476 :
477 : /**
478 : * Function to be called for each newly discovered qpair.
479 : *
480 : * \param tgt The nvmf target
481 : * \param qpair The newly discovered qpair.
482 : */
483 : void spdk_nvmf_tgt_new_qpair(struct spdk_nvmf_tgt *tgt, struct spdk_nvmf_qpair *qpair);
484 :
485 : static inline bool
486 53 : spdk_nvmf_qpair_is_active(struct spdk_nvmf_qpair *qpair)
487 : {
488 94 : return qpair->state == SPDK_NVMF_QPAIR_CONNECTING ||
489 94 : qpair->state == SPDK_NVMF_QPAIR_AUTHENTICATING ||
490 41 : qpair->state == SPDK_NVMF_QPAIR_ENABLED;
491 : }
492 :
493 : /**
494 : * A subset of struct spdk_nvme_registers that are emulated by a fabrics device.
495 : */
496 : struct spdk_nvmf_registers {
497 : union spdk_nvme_cap_register cap;
498 : union spdk_nvme_vs_register vs;
499 : union spdk_nvme_cc_register cc;
500 : union spdk_nvme_csts_register csts;
501 : union spdk_nvme_aqa_register aqa;
502 : uint64_t asq;
503 : uint64_t acq;
504 : };
505 : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_registers) == 40, "Incorrect size");
506 :
507 : const struct spdk_nvmf_registers *spdk_nvmf_ctrlr_get_regs(struct spdk_nvmf_ctrlr *ctrlr);
508 :
509 : void spdk_nvmf_request_free_buffers(struct spdk_nvmf_request *req,
510 : struct spdk_nvmf_transport_poll_group *group,
511 : struct spdk_nvmf_transport *transport);
512 : int spdk_nvmf_request_get_buffers(struct spdk_nvmf_request *req,
513 : struct spdk_nvmf_transport_poll_group *group,
514 : struct spdk_nvmf_transport *transport,
515 : uint32_t length);
516 :
517 : bool spdk_nvmf_request_get_dif_ctx(struct spdk_nvmf_request *req, struct spdk_dif_ctx *dif_ctx);
518 :
519 : void spdk_nvmf_request_exec(struct spdk_nvmf_request *req);
520 : void spdk_nvmf_request_exec_fabrics(struct spdk_nvmf_request *req);
521 : int spdk_nvmf_request_free(struct spdk_nvmf_request *req);
522 : int spdk_nvmf_request_complete(struct spdk_nvmf_request *req);
523 : void spdk_nvmf_request_zcopy_start(struct spdk_nvmf_request *req);
524 : void spdk_nvmf_request_zcopy_end(struct spdk_nvmf_request *req, bool commit);
525 :
526 : static inline bool
527 8 : spdk_nvmf_request_using_zcopy(const struct spdk_nvmf_request *req)
528 : {
529 8 : return req->zcopy_phase != NVMF_ZCOPY_PHASE_NONE;
530 : }
531 :
532 : /**
533 : * Remove the given qpair from the poll group.
534 : *
535 : * \param qpair The qpair to remove.
536 : */
537 : void spdk_nvmf_poll_group_remove(struct spdk_nvmf_qpair *qpair);
538 :
539 : /**
540 : * Get the NVMe-oF subsystem associated with this controller.
541 : *
542 : * \param ctrlr The NVMe-oF controller
543 : *
544 : * \return The NVMe-oF subsystem
545 : */
546 : struct spdk_nvmf_subsystem *
547 : spdk_nvmf_ctrlr_get_subsystem(struct spdk_nvmf_ctrlr *ctrlr);
548 :
549 : /**
550 : * Get the NVMe-oF controller ID.
551 : *
552 : * \param ctrlr The NVMe-oF controller
553 : *
554 : * \return The NVMe-oF controller ID
555 : */
556 : uint16_t spdk_nvmf_ctrlr_get_id(struct spdk_nvmf_ctrlr *ctrlr);
557 :
558 : struct spdk_nvmf_ctrlr_feat {
559 : union spdk_nvme_feat_arbitration arbitration;
560 : union spdk_nvme_feat_power_management power_management;
561 : union spdk_nvme_feat_error_recovery error_recovery;
562 : union spdk_nvme_feat_volatile_write_cache volatile_write_cache;
563 : union spdk_nvme_feat_number_of_queues number_of_queues;
564 : union spdk_nvme_feat_interrupt_coalescing interrupt_coalescing;
565 : union spdk_nvme_feat_interrupt_vector_configuration interrupt_vector_configuration;
566 : union spdk_nvme_feat_write_atomicity write_atomicity;
567 : union spdk_nvme_feat_async_event_configuration async_event_configuration;
568 : union spdk_nvme_feat_keep_alive_timer keep_alive_timer;
569 : };
570 : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_ctrlr_feat) == 40, "Incorrect size");
571 :
572 : /*
573 : * Migration data structure used to save & restore a NVMe-oF controller.
574 : *
575 : * The data structure is experimental.
576 : *
577 : */
578 : struct spdk_nvmf_ctrlr_migr_data {
579 : /* `data_size` is valid size of `spdk_nvmf_ctrlr_migr_data` without counting `unused`.
580 : * We use this field to migrate `spdk_nvmf_ctrlr_migr_data` from source VM and restore
581 : * it in destination VM.
582 : */
583 : uint32_t data_size;
584 : /* `regs_size` is valid size of `spdk_nvmf_registers`. */
585 : uint32_t regs_size;
586 : /* `feat_size` is valid size of `spdk_nvmf_ctrlr_feat`. */
587 : uint32_t feat_size;
588 : uint32_t reserved;
589 :
590 : struct spdk_nvmf_registers regs;
591 : uint8_t regs_reserved[216];
592 :
593 : struct spdk_nvmf_ctrlr_feat feat;
594 : uint8_t feat_reserved[216];
595 :
596 : uint16_t cntlid;
597 : uint8_t acre;
598 : uint8_t num_aer_cids;
599 : uint32_t num_async_events;
600 :
601 : union spdk_nvme_async_event_completion async_events[SPDK_NVMF_MIGR_MAX_PENDING_AERS];
602 : uint16_t aer_cids[SPDK_NVMF_MAX_ASYNC_EVENTS];
603 : uint64_t notice_aen_mask;
604 :
605 : uint8_t unused[2516];
606 : };
607 : SPDK_STATIC_ASSERT(offsetof(struct spdk_nvmf_ctrlr_migr_data,
608 : regs) - offsetof(struct spdk_nvmf_ctrlr_migr_data, data_size) == 16, "Incorrect header size");
609 : SPDK_STATIC_ASSERT(offsetof(struct spdk_nvmf_ctrlr_migr_data,
610 : feat) - offsetof(struct spdk_nvmf_ctrlr_migr_data, regs) == 256, "Incorrect regs size");
611 : SPDK_STATIC_ASSERT(offsetof(struct spdk_nvmf_ctrlr_migr_data,
612 : cntlid) - offsetof(struct spdk_nvmf_ctrlr_migr_data, feat) == 256, "Incorrect feat size");
613 : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_ctrlr_migr_data) == 4096, "Incorrect size");
614 :
615 : /**
616 : * Save the NVMe-oF controller state and configuration.
617 : *
618 : * The API is experimental.
619 : *
620 : * It is allowed to save the data only when the nvmf subystem is in paused
621 : * state i.e. there are no outstanding cmds in nvmf layer (other than aer),
622 : * pending async event completions are getting blocked.
623 : *
624 : * To preserve thread safety this function must be executed on the same thread
625 : * the NVMe-OF controller was created.
626 : *
627 : * \param ctrlr The NVMe-oF controller
628 : * \param data The NVMe-oF controller state and configuration to be saved
629 : *
630 : * \return 0 on success or a negated errno on failure.
631 : */
632 : int spdk_nvmf_ctrlr_save_migr_data(struct spdk_nvmf_ctrlr *ctrlr,
633 : struct spdk_nvmf_ctrlr_migr_data *data);
634 :
635 : /**
636 : * Restore the NVMe-oF controller state and configuration.
637 : *
638 : * The API is experimental.
639 : *
640 : * It is allowed to restore the data only when the nvmf subystem is in paused
641 : * state.
642 : *
643 : * To preserve thread safety this function must be executed on the same thread
644 : * the NVMe-OF controller was created.
645 : *
646 : * AERs shall be restored using spdk_nvmf_request_exec after this function is executed.
647 : *
648 : * \param ctrlr The NVMe-oF controller
649 : * \param data The NVMe-oF controller state and configuration to be restored
650 : *
651 : * \return 0 on success or a negated errno on failure.
652 : */
653 : int spdk_nvmf_ctrlr_restore_migr_data(struct spdk_nvmf_ctrlr *ctrlr,
654 : const struct spdk_nvmf_ctrlr_migr_data *data);
655 :
656 : static inline enum spdk_nvme_data_transfer
657 10 : spdk_nvmf_req_get_xfer(struct spdk_nvmf_request *req) {
658 : enum spdk_nvme_data_transfer xfer;
659 10 : struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
660 10 : struct spdk_nvme_sgl_descriptor *sgl = &cmd->dptr.sgl1;
661 :
662 : /* Figure out data transfer direction */
663 10 : if (cmd->opc == SPDK_NVME_OPC_FABRIC)
664 : {
665 2 : xfer = spdk_nvme_opc_get_data_transfer(req->cmd->nvmf_cmd.fctype);
666 : } else
667 : {
668 8 : xfer = spdk_nvme_opc_get_data_transfer(cmd->opc);
669 : }
670 :
671 10 : if (xfer == SPDK_NVME_DATA_NONE)
672 : {
673 0 : return xfer;
674 : }
675 :
676 : /* Even for commands that may transfer data, they could have specified 0 length.
677 : * We want those to show up with xfer SPDK_NVME_DATA_NONE.
678 : */
679 10 : switch (sgl->generic.type)
680 : {
681 4 : case SPDK_NVME_SGL_TYPE_DATA_BLOCK:
682 : case SPDK_NVME_SGL_TYPE_BIT_BUCKET:
683 : case SPDK_NVME_SGL_TYPE_SEGMENT:
684 : case SPDK_NVME_SGL_TYPE_LAST_SEGMENT:
685 : case SPDK_NVME_SGL_TYPE_TRANSPORT_DATA_BLOCK:
686 4 : if (sgl->unkeyed.length == 0) {
687 0 : xfer = SPDK_NVME_DATA_NONE;
688 : }
689 4 : break;
690 6 : case SPDK_NVME_SGL_TYPE_KEYED_DATA_BLOCK:
691 6 : if (sgl->keyed.length == 0) {
692 0 : xfer = SPDK_NVME_DATA_NONE;
693 : }
694 6 : break;
695 : }
696 :
697 10 : return xfer;
698 : }
699 :
700 : /**
701 : * Complete Asynchronous Event as Error.
702 : *
703 : * \param ctrlr Controller whose AER is going to be completed.
704 : * \param info Asynchronous Event Error Information to be reported.
705 : *
706 : * \return int. 0 if it completed successfully, or negative errno if it failed.
707 : */
708 : int spdk_nvmf_ctrlr_async_event_error_event(struct spdk_nvmf_ctrlr *ctrlr,
709 : enum spdk_nvme_async_event_info_error info);
710 :
711 : /**
712 : * Abort outstanding Asynchronous Event Requests (AERs).
713 : *
714 : * Completes AERs with ABORTED_BY_REQUEST status code.
715 : *
716 : * \param ctrlr Controller whose AERs are going to be aborted.
717 : */
718 : void spdk_nvmf_ctrlr_abort_aer(struct spdk_nvmf_ctrlr *ctrlr);
719 :
720 : /*
721 : * Macro used to register new transports.
722 : */
723 : #define SPDK_NVMF_TRANSPORT_REGISTER(name, transport_ops) \
724 : static void __attribute__((constructor)) _spdk_nvmf_transport_register_##name(void) \
725 : { \
726 : spdk_nvmf_transport_register(transport_ops); \
727 : }
728 :
729 : #ifdef __cplusplus
730 : }
731 : #endif
732 :
733 : #endif
|