Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2015 Intel Corporation.
3 : : * All rights reserved.
4 : : * Copyright (c) 2021 Mellanox Technologies LTD. All rights reserved.
5 : : * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
6 : : * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
7 : : */
8 : :
9 : : #include "nvme_internal.h"
10 : :
11 : : static inline struct nvme_request *_nvme_ns_cmd_rw(struct spdk_nvme_ns *ns,
12 : : struct spdk_nvme_qpair *qpair,
13 : : const struct nvme_payload *payload, uint32_t payload_offset, uint32_t md_offset,
14 : : uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn,
15 : : void *cb_arg, uint32_t opc, uint32_t io_flags,
16 : : uint16_t apptag_mask, uint16_t apptag, uint32_t cdw13, bool check_sgl,
17 : : void *accel_sequence, int *rc);
18 : :
19 : : static bool
20 : 274094 : nvme_ns_check_request_length(uint32_t lba_count, uint32_t sectors_per_max_io,
21 : : uint32_t sectors_per_stripe, uint32_t qdepth)
22 : : {
23 : 274094 : uint32_t child_per_io = UINT32_MAX;
24 : :
25 : : /* After a namespace is destroyed(e.g. hotplug), all the fields associated with the
26 : : * namespace will be cleared to zero, the function will return TRUE for this case,
27 : : * and -EINVAL will be returned to caller.
28 : : */
29 [ - + ]: 274094 : if (sectors_per_stripe > 0) {
30 [ # # ]: 0 : child_per_io = (lba_count + sectors_per_stripe - 1) / sectors_per_stripe;
31 [ + + ]: 274094 : } else if (sectors_per_max_io > 0) {
32 [ - + ]: 164853 : child_per_io = (lba_count + sectors_per_max_io - 1) / sectors_per_max_io;
33 : 0 : }
34 : :
35 [ - + - + : 274094 : SPDK_DEBUGLOG(nvme, "checking maximum i/o length %d\n", child_per_io);
# # ]
36 : :
37 : 274094 : return child_per_io >= qdepth;
38 : : }
39 : :
40 : : static inline int
41 : 274100 : nvme_ns_map_failure_rc(uint32_t lba_count, uint32_t sectors_per_max_io,
42 : : uint32_t sectors_per_stripe, uint32_t qdepth, int rc)
43 : : {
44 [ - + # # ]: 274100 : assert(rc);
45 [ + + + + ]: 548194 : if (rc == -ENOMEM &&
46 : 274094 : nvme_ns_check_request_length(lba_count, sectors_per_max_io, sectors_per_stripe, qdepth)) {
47 : 109244 : return -EINVAL;
48 : : }
49 : 164856 : return rc;
50 : 0 : }
51 : :
52 : : static inline bool
53 : 249480499 : _nvme_md_excluded_from_xfer(struct spdk_nvme_ns *ns, uint32_t io_flags)
54 : : {
55 [ + - - + ]: 249480604 : return (io_flags & SPDK_NVME_IO_FLAGS_PRACT) &&
56 [ + + # # : 105 : (ns->flags & SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED) &&
# # ]
57 [ + + + - : 249190960 : (ns->flags & SPDK_NVME_NS_DPS_PI_SUPPORTED) &&
# # ]
58 [ + - # # ]: 18 : (ns->md_size == 8);
59 : : }
60 : :
61 : : static inline uint32_t
62 : 125612180 : _nvme_get_host_buffer_sector_size(struct spdk_nvme_ns *ns, uint32_t io_flags)
63 : : {
64 [ - + ]: 125757011 : return _nvme_md_excluded_from_xfer(ns, io_flags) ?
65 [ + + # # : 125612180 : ns->sector_size : ns->extended_lba_size;
+ - + - ]
66 : : }
67 : :
68 : : static inline uint32_t
69 : 123868319 : _nvme_get_sectors_per_max_io(struct spdk_nvme_ns *ns, uint32_t io_flags)
70 : : {
71 [ - + ]: 124013150 : return _nvme_md_excluded_from_xfer(ns, io_flags) ?
72 [ + + # # : 123868319 : ns->sectors_per_max_io_no_md : ns->sectors_per_max_io;
+ - + - ]
73 : : }
74 : :
75 : : static struct nvme_request *
76 : 58607399 : _nvme_add_child_request(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
77 : : const struct nvme_payload *payload,
78 : : uint32_t payload_offset, uint32_t md_offset,
79 : : uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc,
80 : : uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag, uint32_t cdw13,
81 : : struct nvme_request *parent, bool check_sgl, int *rc)
82 : : {
83 : : struct nvme_request *child;
84 : :
85 : 58607399 : child = _nvme_ns_cmd_rw(ns, qpair, payload, payload_offset, md_offset, lba, lba_count, cb_fn,
86 [ # # ]: 0 : cb_arg, opc, io_flags, apptag_mask, apptag, cdw13, check_sgl, NULL, rc);
87 [ + + ]: 58607399 : if (child == NULL) {
88 : 109440 : nvme_request_free_children(parent);
89 : 109440 : nvme_free_request(parent);
90 : 109440 : return NULL;
91 : : }
92 : :
93 : 58497959 : nvme_request_add_child(parent, child);
94 : 58497959 : return child;
95 : 0 : }
96 : :
97 : : static struct nvme_request *
98 : 1490985 : _nvme_ns_cmd_split_request(struct spdk_nvme_ns *ns,
99 : : struct spdk_nvme_qpair *qpair,
100 : : const struct nvme_payload *payload,
101 : : uint32_t payload_offset, uint32_t md_offset,
102 : : uint64_t lba, uint32_t lba_count,
103 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc,
104 : : uint32_t io_flags, struct nvme_request *req,
105 : : uint32_t sectors_per_max_io, uint32_t sector_mask,
106 : : uint16_t apptag_mask, uint16_t apptag, uint32_t cdw13,
107 : : void *accel_sequence, int *rc)
108 : : {
109 : 1490985 : uint32_t sector_size = _nvme_get_host_buffer_sector_size(ns, io_flags);
110 : 1490985 : uint32_t remaining_lba_count = lba_count;
111 : : struct nvme_request *child;
112 : :
113 [ - + ]: 1490985 : if (spdk_unlikely(accel_sequence != NULL)) {
114 : 0 : SPDK_ERRLOG("Splitting requests with accel sequence is unsupported\n");
115 [ # # ]: 0 : *rc = -EINVAL;
116 : 0 : return NULL;
117 : : }
118 : :
119 [ + + ]: 59986932 : while (remaining_lba_count > 0) {
120 : 58605387 : lba_count = sectors_per_max_io - (lba & sector_mask);
121 [ # # ]: 58605387 : lba_count = spdk_min(remaining_lba_count, lba_count);
122 : :
123 : 58605387 : child = _nvme_add_child_request(ns, qpair, payload, payload_offset, md_offset,
124 : 0 : lba, lba_count, cb_fn, cb_arg, opc,
125 : 0 : io_flags, apptag_mask, apptag, cdw13, req, true, rc);
126 [ + + ]: 58605387 : if (child == NULL) {
127 : 109440 : return NULL;
128 : : }
129 : :
130 : 58495947 : remaining_lba_count -= lba_count;
131 : 58495947 : lba += lba_count;
132 : 58495947 : payload_offset += lba_count * sector_size;
133 [ # # # # ]: 58495947 : md_offset += lba_count * ns->md_size;
134 : : }
135 : :
136 : 1381545 : return req;
137 : 0 : }
138 : :
139 : : static inline bool
140 : 188096883 : _is_io_flags_valid(uint32_t io_flags)
141 : : {
142 [ + + ]: 188096883 : if (spdk_unlikely(io_flags & ~SPDK_NVME_IO_FLAGS_VALID_MASK)) {
143 : : /* Invalid io_flags */
144 : 9 : SPDK_ERRLOG("Invalid io_flags 0x%x\n", io_flags);
145 : 9 : return false;
146 : : }
147 : :
148 : 188096874 : return true;
149 : 289662 : }
150 : :
151 : : static inline bool
152 : 569396 : _is_accel_sequence_valid(struct spdk_nvme_qpair *qpair, void *seq)
153 : : {
154 : : /* An accel sequence can only be executed if the controller supports accel and a qpair is
155 : : * part of a of a poll group */
156 [ + + + - : 569396 : if (spdk_likely(seq == NULL || ((qpair->ctrlr->flags & SPDK_NVME_CTRLR_ACCEL_SEQUENCE_SUPPORTED) &&
+ - + - #
# # # # #
# # # # ]
157 : : qpair->poll_group != NULL))) {
158 : 569396 : return true;
159 : : }
160 : :
161 : 0 : return false;
162 : 0 : }
163 : :
164 : : static void
165 : 122102308 : _nvme_ns_cmd_setup_request(struct spdk_nvme_ns *ns, struct nvme_request *req,
166 : : uint32_t opc, uint64_t lba, uint32_t lba_count,
167 : : uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag,
168 : : uint32_t cdw13)
169 : : {
170 : : struct spdk_nvme_cmd *cmd;
171 : :
172 [ + + # # ]: 122102308 : assert(_is_io_flags_valid(io_flags));
173 : :
174 [ + - ]: 122102308 : cmd = &req->cmd;
175 [ + - ]: 122102308 : cmd->opc = opc;
176 [ + - + - : 122102308 : cmd->nsid = ns->id;
+ - + - ]
177 : :
178 [ + - + - : 122102308 : *(uint64_t *)&cmd->cdw10 = lba;
+ - ]
179 : :
180 [ + + + - : 122102308 : if (ns->flags & SPDK_NVME_NS_DPS_PI_SUPPORTED) {
+ - ]
181 [ + + # # : 39 : switch (ns->pi_type) {
# # ]
182 : 3 : case SPDK_NVME_FMT_NVM_PROTECTION_TYPE1:
183 : : case SPDK_NVME_FMT_NVM_PROTECTION_TYPE2:
184 [ # # # # ]: 3 : cmd->cdw14 = (uint32_t)lba;
185 : 3 : break;
186 : : }
187 : 0 : }
188 : :
189 [ - + + - : 122102308 : cmd->fuse = (io_flags & SPDK_NVME_IO_FLAGS_FUSE_MASK);
+ - ]
190 : :
191 [ + - + - : 122102308 : cmd->cdw12 = lba_count - 1;
+ - ]
192 [ + - + - : 122102308 : cmd->cdw12 |= (io_flags & SPDK_NVME_IO_FLAGS_CDW12_MASK);
+ - ]
193 : :
194 [ + - + - : 122102308 : cmd->cdw13 = cdw13;
+ - ]
195 : :
196 [ + - + - ]: 122102308 : cmd->cdw15 = apptag_mask;
197 [ + - + - : 122102308 : cmd->cdw15 = (cmd->cdw15 << 16 | apptag);
+ - + - +
- ]
198 : 122102308 : }
199 : :
200 : : static struct nvme_request *
201 : 3975476 : _nvme_ns_cmd_split_request_prp(struct spdk_nvme_ns *ns,
202 : : struct spdk_nvme_qpair *qpair,
203 : : const struct nvme_payload *payload,
204 : : uint32_t payload_offset, uint32_t md_offset,
205 : : uint64_t lba, uint32_t lba_count,
206 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc,
207 : : uint32_t io_flags, struct nvme_request *req,
208 : : uint16_t apptag_mask, uint16_t apptag, uint32_t cdw13,
209 : : void *accel_sequence, int *rc)
210 : : {
211 [ # # # # : 3975476 : spdk_nvme_req_reset_sgl_cb reset_sgl_fn = req->payload.reset_sgl_fn;
# # ]
212 [ # # # # : 3975476 : spdk_nvme_req_next_sge_cb next_sge_fn = req->payload.next_sge_fn;
# # ]
213 [ # # # # : 3975476 : void *sgl_cb_arg = req->payload.contig_or_cb_arg;
# # ]
214 : : bool start_valid, end_valid, last_sge, child_equals_parent;
215 : 3975476 : uint64_t child_lba = lba;
216 : 3975476 : uint32_t req_current_length = 0;
217 : 3975476 : uint32_t child_length = 0;
218 : 3518306 : uint32_t sge_length;
219 [ # # # # : 3975476 : uint32_t page_size = qpair->ctrlr->page_size;
# # # # ]
220 : 3518306 : uintptr_t address;
221 : :
222 [ # # # # ]: 3975476 : reset_sgl_fn(sgl_cb_arg, payload_offset);
223 [ # # # # ]: 3975476 : next_sge_fn(sgl_cb_arg, (void **)&address, &sge_length);
224 [ + + # # : 17057903 : while (req_current_length < req->payload_size) {
# # ]
225 : :
226 [ - + ]: 13082430 : if (sge_length == 0) {
227 : 0 : continue;
228 [ + + # # : 13082430 : } else if (req_current_length + sge_length > req->payload_size) {
# # ]
229 [ # # # # ]: 56251 : sge_length = req->payload_size - req_current_length;
230 : 0 : }
231 : :
232 : : /*
233 : : * The start of the SGE is invalid if the start address is not page aligned,
234 : : * unless it is the first SGE in the child request.
235 : : */
236 [ + + + - ]: 13082430 : start_valid = child_length == 0 || _is_page_aligned(address, page_size);
237 : :
238 : : /* Boolean for whether this is the last SGE in the parent request. */
239 [ # # # # ]: 13082430 : last_sge = (req_current_length + sge_length == req->payload_size);
240 : :
241 : : /*
242 : : * The end of the SGE is invalid if the end address is not page aligned,
243 : : * unless it is the last SGE in the parent request.
244 : : */
245 [ + + + + ]: 13082430 : end_valid = last_sge || _is_page_aligned(address + sge_length, page_size);
246 : :
247 : : /*
248 : : * This child request equals the parent request, meaning that no splitting
249 : : * was required for the parent request (the one passed into this function).
250 : : * In this case, we do not create a child request at all - we just send
251 : : * the original request as a single request at the end of this function.
252 : : */
253 [ # # # # ]: 13082430 : child_equals_parent = (child_length + sge_length == req->payload_size);
254 : :
255 [ + - # # ]: 13082430 : if (start_valid) {
256 : : /*
257 : : * The start of the SGE is valid, so advance the length parameters,
258 : : * to include this SGE with previous SGEs for this child request
259 : : * (if any). If it is not valid, we do not advance the length
260 : : * parameters nor get the next SGE, because we must send what has
261 : : * been collected before this SGE as a child request.
262 : : */
263 : 13082430 : child_length += sge_length;
264 : 13082430 : req_current_length += sge_length;
265 [ + + # # : 13082430 : if (req_current_length < req->payload_size) {
# # ]
266 [ # # # # ]: 9106957 : next_sge_fn(sgl_cb_arg, (void **)&address, &sge_length);
267 : : /*
268 : : * If the next SGE is not page aligned, we will need to create a
269 : : * child request for what we have so far, and then start a new
270 : : * child request for the next SGE.
271 : : */
272 : 9106957 : start_valid = _is_page_aligned(address, page_size);
273 : 0 : }
274 : 0 : }
275 : :
276 [ + + + + : 13082430 : if (start_valid && end_valid && !last_sge) {
+ + # # #
# # # ]
277 : 9105874 : continue;
278 : : }
279 : :
280 : : /*
281 : : * We need to create a split here. Send what we have accumulated so far as a child
282 : : * request. Checking if child_equals_parent allows us to *not* create a child request
283 : : * when no splitting is required - in that case we will fall-through and just create
284 : : * a single request with no children for the entire I/O.
285 : : */
286 [ + + # # ]: 3976556 : if (!child_equals_parent) {
287 : : struct nvme_request *child;
288 : : uint32_t child_lba_count;
289 : :
290 [ + + + + : 2009 : if ((child_length % ns->extended_lba_size) != 0) {
# # # # ]
291 [ # # # # ]: 3 : SPDK_ERRLOG("child_length %u not even multiple of lba_size %u\n",
292 : : child_length, ns->extended_lba_size);
293 [ # # ]: 3 : *rc = -EINVAL;
294 : 3 : return NULL;
295 : : }
296 [ - + ]: 2006 : if (spdk_unlikely(accel_sequence != NULL)) {
297 : 0 : SPDK_ERRLOG("Splitting requests with accel sequence is unsupported\n");
298 [ # # ]: 0 : *rc = -EINVAL;
299 : 0 : return NULL;
300 : : }
301 : :
302 [ - + # # : 2006 : child_lba_count = child_length / ns->extended_lba_size;
# # ]
303 : : /*
304 : : * Note the last parameter is set to "false" - this tells the recursive
305 : : * call to _nvme_ns_cmd_rw() to not bother with checking for SGL splitting
306 : : * since we have already verified it here.
307 : : */
308 : 2006 : child = _nvme_add_child_request(ns, qpair, payload, payload_offset, md_offset,
309 : 0 : child_lba, child_lba_count,
310 : 0 : cb_fn, cb_arg, opc, io_flags,
311 : 0 : apptag_mask, apptag, cdw13, req, false, rc);
312 [ - + ]: 2006 : if (child == NULL) {
313 : 0 : return NULL;
314 : : }
315 : 2006 : payload_offset += child_length;
316 [ # # # # ]: 2006 : md_offset += child_lba_count * ns->md_size;
317 : 2006 : child_lba += child_lba_count;
318 : 2006 : child_length = 0;
319 : 0 : }
320 : : }
321 : :
322 [ + + # # : 3975473 : if (child_length == req->payload_size) {
# # ]
323 : : /* No splitting was required, so setup the whole payload as one request. */
324 : 3974547 : _nvme_ns_cmd_setup_request(ns, req, opc, lba, lba_count, io_flags, apptag_mask, apptag, cdw13);
325 : 0 : }
326 : :
327 : 3975473 : return req;
328 : 0 : }
329 : :
330 : : static struct nvme_request *
331 : 674405 : _nvme_ns_cmd_split_request_sgl(struct spdk_nvme_ns *ns,
332 : : struct spdk_nvme_qpair *qpair,
333 : : const struct nvme_payload *payload,
334 : : uint32_t payload_offset, uint32_t md_offset,
335 : : uint64_t lba, uint32_t lba_count,
336 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc,
337 : : uint32_t io_flags, struct nvme_request *req,
338 : : uint16_t apptag_mask, uint16_t apptag, uint32_t cdw13,
339 : : void *accel_sequence, int *rc)
340 : : {
341 [ # # # # : 674405 : spdk_nvme_req_reset_sgl_cb reset_sgl_fn = req->payload.reset_sgl_fn;
# # ]
342 [ # # # # : 674405 : spdk_nvme_req_next_sge_cb next_sge_fn = req->payload.next_sge_fn;
# # ]
343 [ # # # # : 674405 : void *sgl_cb_arg = req->payload.contig_or_cb_arg;
# # ]
344 : 674405 : uint64_t child_lba = lba;
345 : 674405 : uint32_t req_current_length = 0;
346 : 674405 : uint32_t accumulated_length = 0;
347 : 312469 : uint32_t sge_length;
348 : : uint16_t max_sges, num_sges;
349 : 312469 : uintptr_t address;
350 : :
351 [ # # # # : 674405 : max_sges = ns->ctrlr->max_sges;
# # # # ]
352 : :
353 [ # # # # ]: 674405 : reset_sgl_fn(sgl_cb_arg, payload_offset);
354 : 674405 : num_sges = 0;
355 : :
356 [ + + # # : 5293653 : while (req_current_length < req->payload_size) {
# # ]
357 [ # # # # ]: 4619251 : next_sge_fn(sgl_cb_arg, (void **)&address, &sge_length);
358 : :
359 [ + + # # : 4619251 : if (req_current_length + sge_length > req->payload_size) {
# # ]
360 [ # # # # ]: 888 : sge_length = req->payload_size - req_current_length;
361 : 0 : }
362 : :
363 : 4619251 : accumulated_length += sge_length;
364 : 4619251 : req_current_length += sge_length;
365 : 4619251 : num_sges++;
366 : :
367 [ + + + + : 4619251 : if (num_sges < max_sges && req_current_length < req->payload_size) {
# # # # ]
368 : 3944843 : continue;
369 : : }
370 : :
371 : : /*
372 : : * We need to create a split here. Send what we have accumulated so far as a child
373 : : * request. Checking if the child equals the full payload allows us to *not*
374 : : * create a child request when no splitting is required - in that case we will
375 : : * fall-through and just create a single request with no children for the entire I/O.
376 : : */
377 [ + + # # : 674408 : if (accumulated_length != req->payload_size) {
# # ]
378 : : struct nvme_request *child;
379 : : uint32_t child_lba_count;
380 : : uint32_t child_length;
381 : : uint32_t extra_length;
382 : :
383 : 9 : child_length = accumulated_length;
384 : : /* Child length may not be a multiple of the block size! */
385 [ - + # # : 9 : child_lba_count = child_length / ns->extended_lba_size;
# # ]
386 [ # # # # ]: 9 : extra_length = child_length - (child_lba_count * ns->extended_lba_size);
387 [ + + ]: 9 : if (extra_length != 0) {
388 : : /* The last SGE does not end on a block boundary. We need to cut it off. */
389 [ + + ]: 6 : if (extra_length >= child_length) {
390 : 3 : SPDK_ERRLOG("Unable to send I/O. Would require more than the supported number of "
391 : : "SGL Elements.");
392 [ # # ]: 3 : *rc = -EINVAL;
393 : 3 : return NULL;
394 : : }
395 : 3 : child_length -= extra_length;
396 : 0 : }
397 : :
398 [ - + ]: 6 : if (spdk_unlikely(accel_sequence != NULL)) {
399 : 0 : SPDK_ERRLOG("Splitting requests with accel sequence is unsupported\n");
400 [ # # ]: 0 : *rc = -EINVAL;
401 : 0 : return NULL;
402 : : }
403 : :
404 : : /*
405 : : * Note the last parameter is set to "false" - this tells the recursive
406 : : * call to _nvme_ns_cmd_rw() to not bother with checking for SGL splitting
407 : : * since we have already verified it here.
408 : : */
409 : 6 : child = _nvme_add_child_request(ns, qpair, payload, payload_offset, md_offset,
410 : 0 : child_lba, child_lba_count,
411 : 0 : cb_fn, cb_arg, opc, io_flags,
412 : 0 : apptag_mask, apptag, cdw13, req, false, rc);
413 [ - + ]: 6 : if (child == NULL) {
414 : 0 : return NULL;
415 : : }
416 : 6 : payload_offset += child_length;
417 [ # # # # ]: 6 : md_offset += child_lba_count * ns->md_size;
418 : 6 : child_lba += child_lba_count;
419 : 6 : accumulated_length -= child_length;
420 : 6 : num_sges = accumulated_length > 0;
421 : 0 : }
422 : : }
423 : :
424 [ + + # # : 674402 : if (accumulated_length == req->payload_size) {
# # ]
425 : : /* No splitting was required, so setup the whole payload as one request. */
426 : 674399 : _nvme_ns_cmd_setup_request(ns, req, opc, lba, lba_count, io_flags, apptag_mask, apptag, cdw13);
427 : 0 : }
428 : :
429 : 674402 : return req;
430 : 0 : }
431 : :
432 : : static inline struct nvme_request *
433 : 123868319 : _nvme_ns_cmd_rw(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
434 : : const struct nvme_payload *payload, uint32_t payload_offset, uint32_t md_offset,
435 : : uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc,
436 : : uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag, uint32_t cdw13, bool check_sgl,
437 : : void *accel_sequence, int *rc)
438 : : {
439 : : struct nvme_request *req;
440 : 123868319 : uint32_t sector_size = _nvme_get_host_buffer_sector_size(ns, io_flags);
441 : 123868319 : uint32_t sectors_per_max_io = _nvme_get_sectors_per_max_io(ns, io_flags);
442 [ + - + - ]: 123868319 : uint32_t sectors_per_stripe = ns->sectors_per_stripe;
443 : :
444 [ + + # # ]: 123868319 : assert(rc != NULL);
445 [ + + + - : 123868319 : assert(*rc == 0);
# # ]
446 : :
447 [ + - + - ]: 123868319 : req = nvme_allocate_request(qpair, payload, lba_count * sector_size, lba_count * ns->md_size,
448 : 144831 : cb_fn, cb_arg);
449 [ + + ]: 123868319 : if (req == NULL) {
450 [ # # ]: 274094 : *rc = -ENOMEM;
451 : 274094 : return NULL;
452 : : }
453 : :
454 [ + - + - ]: 123594225 : req->payload_offset = payload_offset;
455 [ + - + - ]: 123594225 : req->md_offset = md_offset;
456 [ + - + - ]: 123594225 : req->accel_sequence = accel_sequence;
457 : :
458 : : /* Zone append commands cannot be split. */
459 [ + + ]: 123594225 : if (opc == SPDK_NVME_OPC_ZONE_APPEND) {
460 [ - + # # : 252867 : assert(ns->csi == SPDK_NVME_CSI_ZNS);
# # # # ]
461 : : /*
462 : : * As long as we disable driver-assisted striping for Zone append commands,
463 : : * _nvme_ns_cmd_rw() should never cause a proper request to be split.
464 : : * If a request is split, after all, error handling is done in caller functions.
465 : : */
466 : 252867 : sectors_per_stripe = 0;
467 : 0 : }
468 : :
469 : : /*
470 : : * Intel DC P3*00 NVMe controllers benefit from driver-assisted striping.
471 : : * If this controller defines a stripe boundary and this I/O spans a stripe
472 : : * boundary, split the request into multiple requests and submit each
473 : : * separately to hardware.
474 : : */
475 [ + + + - ]: 123594225 : if (sectors_per_stripe > 0 &&
476 [ + + ]: 22392605 : (((lba & (sectors_per_stripe - 1)) + lba_count) > sectors_per_stripe)) {
477 : 1304728 : return _nvme_ns_cmd_split_request(ns, qpair, payload, payload_offset, md_offset, lba, lba_count,
478 : 0 : cb_fn,
479 : 0 : cb_arg, opc,
480 : 0 : io_flags, req, sectors_per_stripe, sectors_per_stripe - 1,
481 : 0 : apptag_mask, apptag, cdw13, accel_sequence, rc);
482 [ + + ]: 122289497 : } else if (lba_count > sectors_per_max_io) {
483 : 186257 : return _nvme_ns_cmd_split_request(ns, qpair, payload, payload_offset, md_offset, lba, lba_count,
484 : 0 : cb_fn,
485 : 0 : cb_arg, opc,
486 : 0 : io_flags, req, sectors_per_max_io, 0, apptag_mask,
487 : 0 : apptag, cdw13, accel_sequence, rc);
488 [ + + + + : 122103240 : } else if (nvme_payload_type(&req->payload) == NVME_PAYLOAD_TYPE_SGL && check_sgl) {
# # # # ]
489 [ + + # # : 4649881 : if (ns->ctrlr->flags & SPDK_NVME_CTRLR_SGL_SUPPORTED) {
# # # # #
# ]
490 : 674405 : return _nvme_ns_cmd_split_request_sgl(ns, qpair, payload, payload_offset, md_offset,
491 : 0 : lba, lba_count, cb_fn, cb_arg, opc, io_flags,
492 : 0 : req, apptag_mask, apptag, cdw13,
493 : 0 : accel_sequence, rc);
494 : : } else {
495 : 3975476 : return _nvme_ns_cmd_split_request_prp(ns, qpair, payload, payload_offset, md_offset,
496 : 0 : lba, lba_count, cb_fn, cb_arg, opc, io_flags,
497 : 0 : req, apptag_mask, apptag, cdw13,
498 : 0 : accel_sequence, rc);
499 : : }
500 : : }
501 : :
502 : 117453359 : _nvme_ns_cmd_setup_request(ns, req, opc, lba, lba_count, io_flags, apptag_mask, apptag, cdw13);
503 : 117453359 : return req;
504 : 144831 : }
505 : :
506 : : int
507 : 3075 : spdk_nvme_ns_cmd_compare(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer,
508 : : uint64_t lba,
509 : : uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
510 : : uint32_t io_flags)
511 : : {
512 : : struct nvme_request *req;
513 : 3 : struct nvme_payload payload;
514 : 3075 : int rc = 0;
515 : :
516 [ - + ]: 3075 : if (!_is_io_flags_valid(io_flags)) {
517 : 0 : return -EINVAL;
518 : : }
519 : :
520 : 3075 : payload = NVME_PAYLOAD_CONTIG(buffer, NULL);
521 : :
522 : 3075 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg,
523 : : SPDK_NVME_OPC_COMPARE,
524 : 0 : io_flags, 0,
525 : : 0, 0, false, NULL, &rc);
526 [ + - ]: 3075 : if (req != NULL) {
527 : 3075 : return nvme_qpair_submit_request(qpair, req);
528 : : } else {
529 : 0 : return nvme_ns_map_failure_rc(lba_count,
530 [ # # # # ]: 0 : ns->sectors_per_max_io,
531 [ # # # # ]: 0 : ns->sectors_per_stripe,
532 [ # # # # : 0 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
533 : 0 : rc);
534 : : }
535 : 0 : }
536 : :
537 : : int
538 : 18 : spdk_nvme_ns_cmd_compare_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
539 : : void *buffer,
540 : : void *metadata,
541 : : uint64_t lba,
542 : : uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
543 : : uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag)
544 : : {
545 : : struct nvme_request *req;
546 : 18 : struct nvme_payload payload;
547 : 18 : int rc = 0;
548 : :
549 [ - + ]: 18 : if (!_is_io_flags_valid(io_flags)) {
550 : 0 : return -EINVAL;
551 : : }
552 : :
553 : 18 : payload = NVME_PAYLOAD_CONTIG(buffer, metadata);
554 : :
555 : 18 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg,
556 : : SPDK_NVME_OPC_COMPARE,
557 : 0 : io_flags,
558 : 0 : apptag_mask, apptag, 0, false, NULL, &rc);
559 [ + - ]: 18 : if (req != NULL) {
560 : 18 : return nvme_qpair_submit_request(qpair, req);
561 : : } else {
562 : 0 : return nvme_ns_map_failure_rc(lba_count,
563 [ # # # # ]: 0 : ns->sectors_per_max_io,
564 [ # # # # ]: 0 : ns->sectors_per_stripe,
565 [ # # # # : 0 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
566 : 0 : rc);
567 : : }
568 : 0 : }
569 : :
570 : : int
571 : 6 : spdk_nvme_ns_cmd_comparev(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
572 : : uint64_t lba, uint32_t lba_count,
573 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
574 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
575 : : spdk_nvme_req_next_sge_cb next_sge_fn)
576 : : {
577 : : struct nvme_request *req;
578 : 6 : struct nvme_payload payload;
579 : 6 : int rc = 0;
580 : :
581 [ - + ]: 6 : if (!_is_io_flags_valid(io_flags)) {
582 : 0 : return -EINVAL;
583 : : }
584 : :
585 [ + - + + ]: 6 : if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
586 : 3 : return -EINVAL;
587 : : }
588 : :
589 : 3 : payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, NULL);
590 : :
591 : 3 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg,
592 : : SPDK_NVME_OPC_COMPARE,
593 : 0 : io_flags, 0, 0, 0, true, NULL, &rc);
594 [ + - ]: 3 : if (req != NULL) {
595 : 3 : return nvme_qpair_submit_request(qpair, req);
596 : : } else {
597 : 0 : return nvme_ns_map_failure_rc(lba_count,
598 [ # # # # ]: 0 : ns->sectors_per_max_io,
599 [ # # # # ]: 0 : ns->sectors_per_stripe,
600 [ # # # # : 0 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
601 : 0 : rc);
602 : : }
603 : 0 : }
604 : :
605 : : int
606 : 113 : spdk_nvme_ns_cmd_comparev_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
607 : : uint64_t lba, uint32_t lba_count,
608 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
609 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
610 : : spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata,
611 : : uint16_t apptag_mask, uint16_t apptag)
612 : : {
613 : : struct nvme_request *req;
614 : 52 : struct nvme_payload payload;
615 : 113 : int rc = 0;
616 : :
617 [ - + ]: 113 : if (!_is_io_flags_valid(io_flags)) {
618 : 0 : return -EINVAL;
619 : : }
620 : :
621 [ + - - + ]: 113 : if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
622 : 0 : return -EINVAL;
623 : : }
624 : :
625 : 113 : payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, metadata);
626 : :
627 : 113 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg,
628 : 0 : SPDK_NVME_OPC_COMPARE, io_flags, apptag_mask, apptag, 0, true,
629 : : NULL, &rc);
630 [ + - ]: 113 : if (req != NULL) {
631 : 113 : return nvme_qpair_submit_request(qpair, req);
632 : : } else {
633 : 0 : return nvme_ns_map_failure_rc(lba_count,
634 [ # # # # ]: 0 : ns->sectors_per_max_io,
635 [ # # # # ]: 0 : ns->sectors_per_stripe,
636 [ # # # # : 0 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
637 : 0 : rc);
638 : : }
639 : 0 : }
640 : :
641 : : int
642 : 2540518 : spdk_nvme_ns_cmd_read(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer,
643 : : uint64_t lba,
644 : : uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
645 : : uint32_t io_flags)
646 : : {
647 : : struct nvme_request *req;
648 : 497357 : struct nvme_payload payload;
649 : 2540518 : int rc = 0;
650 : :
651 [ - + ]: 2540518 : if (!_is_io_flags_valid(io_flags)) {
652 : 0 : return -EINVAL;
653 : : }
654 : :
655 : 2540518 : payload = NVME_PAYLOAD_CONTIG(buffer, NULL);
656 : :
657 : 2612932 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_READ,
658 : 72414 : io_flags, 0,
659 : : 0, 0, false, NULL, &rc);
660 [ + + ]: 2540518 : if (req != NULL) {
661 : 2540515 : return nvme_qpair_submit_request(qpair, req);
662 : : } else {
663 : 3 : return nvme_ns_map_failure_rc(lba_count,
664 [ # # # # ]: 0 : ns->sectors_per_max_io,
665 [ # # # # ]: 0 : ns->sectors_per_stripe,
666 [ # # # # : 3 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
667 : 0 : rc);
668 : : }
669 : 72414 : }
670 : :
671 : : int
672 : 31977415 : spdk_nvme_ns_cmd_read_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer,
673 : : void *metadata,
674 : : uint64_t lba,
675 : : uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
676 : : uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag)
677 : : {
678 : : struct nvme_request *req;
679 : 10412142 : struct nvme_payload payload;
680 : 31977415 : int rc = 0;
681 : :
682 [ - + ]: 31977415 : if (!_is_io_flags_valid(io_flags)) {
683 : 0 : return -EINVAL;
684 : : }
685 : :
686 : 31977415 : payload = NVME_PAYLOAD_CONTIG(buffer, metadata);
687 : :
688 : 31977418 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_READ,
689 : 3 : io_flags,
690 : 3 : apptag_mask, apptag, 0, false, NULL, &rc);
691 [ + + ]: 31977415 : if (req != NULL) {
692 : 31787589 : return nvme_qpair_submit_request(qpair, req);
693 : : } else {
694 : 189826 : return nvme_ns_map_failure_rc(lba_count,
695 [ # # # # ]: 0 : ns->sectors_per_max_io,
696 [ # # # # ]: 0 : ns->sectors_per_stripe,
697 [ # # # # : 189826 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
698 : 0 : rc);
699 : : }
700 : 3 : }
701 : :
702 : : static int
703 : 569389 : nvme_ns_cmd_rw_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer,
704 : : uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
705 : : struct spdk_nvme_ns_cmd_ext_io_opts *opts, enum spdk_nvme_nvm_opcode opc)
706 : : {
707 : : struct nvme_request *req;
708 : 0 : struct nvme_payload payload;
709 : : void *seq;
710 : 569389 : int rc = 0;
711 : :
712 [ + + - + : 569389 : assert(opc == SPDK_NVME_OPC_READ || opc == SPDK_NVME_OPC_WRITE);
# # ]
713 [ - + # # ]: 569389 : assert(opts);
714 : :
715 [ # # # # ]: 569389 : payload = NVME_PAYLOAD_CONTIG(buffer, opts->metadata);
716 : :
717 [ - + # # : 569389 : if (spdk_unlikely(!_is_io_flags_valid(opts->io_flags))) {
# # ]
718 : 0 : return -EINVAL;
719 : : }
720 : :
721 [ + - + - : 569389 : seq = nvme_ns_cmd_get_ext_io_opt(opts, accel_sequence, NULL);
# # # # #
# # # ]
722 [ - + ]: 569389 : if (spdk_unlikely(!_is_accel_sequence_valid(qpair, seq))) {
723 : 0 : return -EINVAL;
724 : : }
725 : :
726 [ # # ]: 569389 : payload.opts = opts;
727 : :
728 [ # # # # ]: 569389 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, opc, opts->io_flags,
729 [ # # # # : 569389 : opts->apptag_mask, opts->apptag, 0, false, seq, &rc);
# # # # ]
730 [ - + ]: 569389 : if (spdk_unlikely(req == NULL)) {
731 : 0 : return nvme_ns_map_failure_rc(lba_count,
732 [ # # # # ]: 0 : ns->sectors_per_max_io,
733 [ # # # # ]: 0 : ns->sectors_per_stripe,
734 [ # # # # : 0 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
735 : 0 : rc);
736 : : }
737 : :
738 : 569389 : return nvme_qpair_submit_request(qpair, req);
739 : 0 : }
740 : :
741 : : int
742 : 367003 : spdk_nvme_ns_cmd_read_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer,
743 : : uint64_t lba,
744 : : uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
745 : : struct spdk_nvme_ns_cmd_ext_io_opts *opts)
746 : : {
747 : 367003 : return nvme_ns_cmd_rw_ext(ns, qpair, buffer, lba, lba_count, cb_fn, cb_arg, opts,
748 : : SPDK_NVME_OPC_READ);
749 : : }
750 : :
751 : : int
752 : 72 : spdk_nvme_ns_cmd_readv(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
753 : : uint64_t lba, uint32_t lba_count,
754 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
755 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
756 : : spdk_nvme_req_next_sge_cb next_sge_fn)
757 : : {
758 : : struct nvme_request *req;
759 : 42 : struct nvme_payload payload;
760 : 72 : int rc = 0;
761 : :
762 [ - + ]: 72 : if (!_is_io_flags_valid(io_flags)) {
763 : 0 : return -EINVAL;
764 : : }
765 : :
766 [ + - + + ]: 72 : if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
767 : 6 : return -EINVAL;
768 : : }
769 : :
770 : 66 : payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, NULL);
771 : :
772 : 66 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_READ,
773 : 0 : io_flags, 0, 0, 0, true, NULL, &rc);
774 [ + + ]: 66 : if (req != NULL) {
775 : 63 : return nvme_qpair_submit_request(qpair, req);
776 : : } else {
777 : 3 : return nvme_ns_map_failure_rc(lba_count,
778 [ # # # # ]: 0 : ns->sectors_per_max_io,
779 [ # # # # ]: 0 : ns->sectors_per_stripe,
780 [ # # # # : 3 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
781 : 0 : rc);
782 : : }
783 : 0 : }
784 : :
785 : : int
786 : 1000606 : spdk_nvme_ns_cmd_readv_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
787 : : uint64_t lba, uint32_t lba_count,
788 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
789 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
790 : : spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata,
791 : : uint16_t apptag_mask, uint16_t apptag)
792 : : {
793 : : struct nvme_request *req;
794 : 802890 : struct nvme_payload payload;
795 : 1000606 : int rc = 0;
796 : :
797 [ - + ]: 1000606 : if (!_is_io_flags_valid(io_flags)) {
798 : 0 : return -EINVAL;
799 : : }
800 : :
801 [ + - + + ]: 1000606 : if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
802 : 3 : return -EINVAL;
803 : : }
804 : :
805 : 1000603 : payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, metadata);
806 : :
807 : 1000603 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_READ,
808 : 0 : io_flags, apptag_mask, apptag, 0, true, NULL, &rc);
809 [ + + ]: 1000603 : if (req != NULL) {
810 : 1000470 : return nvme_qpair_submit_request(qpair, req);
811 : : } else {
812 : 133 : return nvme_ns_map_failure_rc(lba_count,
813 [ # # # # ]: 0 : ns->sectors_per_max_io,
814 [ # # # # ]: 0 : ns->sectors_per_stripe,
815 [ # # # # : 133 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
816 : 0 : rc);
817 : : }
818 : 0 : }
819 : :
820 : : static int
821 : 25 : nvme_ns_cmd_rwv_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t lba,
822 : : uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
823 : : spdk_nvme_req_next_sge_cb next_sge_fn, struct spdk_nvme_ns_cmd_ext_io_opts *opts,
824 : : enum spdk_nvme_nvm_opcode opc)
825 : : {
826 : : struct nvme_request *req;
827 : 25 : struct nvme_payload payload;
828 : : void *seq;
829 : 25 : int rc = 0;
830 : :
831 [ + + - + : 25 : assert(opc == SPDK_NVME_OPC_READ || opc == SPDK_NVME_OPC_WRITE);
# # ]
832 : :
833 [ + + + + ]: 25 : if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
834 : 12 : return -EINVAL;
835 : : }
836 : :
837 : 13 : payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, NULL);
838 : :
839 [ + - ]: 13 : if (opts) {
840 [ + + # # : 13 : if (spdk_unlikely(!_is_io_flags_valid(opts->io_flags))) {
# # ]
841 : 6 : return -EINVAL;
842 : : }
843 : :
844 [ + - - + : 7 : seq = nvme_ns_cmd_get_ext_io_opt(opts, accel_sequence, NULL);
# # # # #
# # # ]
845 [ - + ]: 7 : if (spdk_unlikely(!_is_accel_sequence_valid(qpair, seq))) {
846 : 0 : return -EINVAL;
847 : : }
848 : :
849 [ # # ]: 7 : payload.opts = opts;
850 [ # # # # : 7 : payload.md = opts->metadata;
# # ]
851 [ # # # # ]: 12 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, opc, opts->io_flags,
852 [ # # # # : 7 : opts->apptag_mask, opts->apptag, opts->cdw13, true, seq, &rc);
# # # # #
# # # ]
853 : :
854 : 0 : } else {
855 : 0 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, opc, 0, 0, 0, 0,
856 : : true, NULL, &rc);
857 : : }
858 : :
859 [ - + ]: 7 : if (req == NULL) {
860 : 0 : return nvme_ns_map_failure_rc(lba_count,
861 [ # # # # ]: 0 : ns->sectors_per_max_io,
862 [ # # # # ]: 0 : ns->sectors_per_stripe,
863 [ # # # # : 0 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
864 : 0 : rc);
865 : : }
866 : :
867 : 7 : return nvme_qpair_submit_request(qpair, req);
868 : 0 : }
869 : :
870 : : int
871 : 12 : spdk_nvme_ns_cmd_readv_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
872 : : uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn,
873 : : void *cb_arg, spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
874 : : spdk_nvme_req_next_sge_cb next_sge_fn,
875 : : struct spdk_nvme_ns_cmd_ext_io_opts *opts)
876 : : {
877 : 12 : return nvme_ns_cmd_rwv_ext(ns, qpair, lba, lba_count, cb_fn, cb_arg, reset_sgl_fn, next_sge_fn,
878 : 0 : opts, SPDK_NVME_OPC_READ);
879 : : }
880 : :
881 : : int
882 : 3416959 : spdk_nvme_ns_cmd_write(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
883 : : void *buffer, uint64_t lba,
884 : : uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
885 : : uint32_t io_flags)
886 : : {
887 : : struct nvme_request *req;
888 : 135904 : struct nvme_payload payload;
889 : 3416959 : int rc = 0;
890 : :
891 [ + + ]: 3416959 : if (!_is_io_flags_valid(io_flags)) {
892 : 3 : return -EINVAL;
893 : : }
894 : :
895 : 3416956 : payload = NVME_PAYLOAD_CONTIG(buffer, NULL);
896 : :
897 : 3489370 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_WRITE,
898 : 72414 : io_flags, 0, 0, 0, false, NULL, &rc);
899 [ + - ]: 3416956 : if (req != NULL) {
900 : 3416956 : return nvme_qpair_submit_request(qpair, req);
901 : : } else {
902 : 0 : return nvme_ns_map_failure_rc(lba_count,
903 [ # # # # ]: 0 : ns->sectors_per_max_io,
904 [ # # # # ]: 0 : ns->sectors_per_stripe,
905 [ # # # # : 0 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
906 : 0 : rc);
907 : : }
908 : 72414 : }
909 : :
910 : : static int
911 : 252876 : nvme_ns_cmd_check_zone_append(struct spdk_nvme_ns *ns, uint32_t lba_count, uint32_t io_flags)
912 : : {
913 : : uint32_t sector_size;
914 : :
915 : : /* Not all NVMe Zoned Namespaces support the zone append command. */
916 [ - + # # : 252876 : if (!(ns->ctrlr->flags & SPDK_NVME_CTRLR_ZONE_APPEND_SUPPORTED)) {
# # # # #
# ]
917 : 0 : return -EINVAL;
918 : : }
919 : :
920 : 252876 : sector_size = _nvme_get_host_buffer_sector_size(ns, io_flags);
921 : :
922 : : /* Fail a too large zone append command early. */
923 [ + + # # : 252876 : if (lba_count * sector_size > ns->ctrlr->max_zone_append_size) {
# # # # #
# ]
924 : 9 : return -EINVAL;
925 : : }
926 : :
927 : 252867 : return 0;
928 : 0 : }
929 : :
930 : : int
931 : 252870 : nvme_ns_cmd_zone_append_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
932 : : void *buffer, void *metadata, uint64_t zslba,
933 : : uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
934 : : uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag)
935 : : {
936 : : struct nvme_request *req;
937 : 12 : struct nvme_payload payload;
938 : 252870 : int rc = 0;
939 : :
940 [ - + ]: 252870 : if (!_is_io_flags_valid(io_flags)) {
941 : 0 : return -EINVAL;
942 : : }
943 : :
944 : 252870 : rc = nvme_ns_cmd_check_zone_append(ns, lba_count, io_flags);
945 [ + + ]: 252870 : if (rc) {
946 : 6 : return rc;
947 : : }
948 : :
949 : 252864 : payload = NVME_PAYLOAD_CONTIG(buffer, metadata);
950 : :
951 : 252864 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, zslba, lba_count, cb_fn, cb_arg,
952 : : SPDK_NVME_OPC_ZONE_APPEND,
953 : 0 : io_flags, apptag_mask, apptag, 0, false, NULL, &rc);
954 [ + - ]: 252864 : if (req != NULL) {
955 : : /*
956 : : * Zone append commands cannot be split (num_children has to be 0).
957 : : * For NVME_PAYLOAD_TYPE_CONTIG, _nvme_ns_cmd_rw() should never cause a split
958 : : * to happen, since a too large request would have already been failed by
959 : : * nvme_ns_cmd_check_zone_append(), since zasl <= mdts.
960 : : */
961 [ - + # # : 252864 : assert(req->num_children == 0);
# # # # ]
962 [ - + # # : 252864 : if (req->num_children) {
# # ]
963 : 0 : nvme_request_free_children(req);
964 : 0 : nvme_free_request(req);
965 : 0 : return -EINVAL;
966 : : }
967 : 252864 : return nvme_qpair_submit_request(qpair, req);
968 : : } else {
969 : 0 : return nvme_ns_map_failure_rc(lba_count,
970 [ # # # # ]: 0 : ns->sectors_per_max_io,
971 [ # # # # ]: 0 : ns->sectors_per_stripe,
972 [ # # # # : 0 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
973 : 0 : rc);
974 : : }
975 : 0 : }
976 : :
977 : : int
978 : 6 : nvme_ns_cmd_zone_appendv_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
979 : : uint64_t zslba, uint32_t lba_count,
980 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
981 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
982 : : spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata,
983 : : uint16_t apptag_mask, uint16_t apptag)
984 : : {
985 : : struct nvme_request *req;
986 : 6 : struct nvme_payload payload;
987 : 6 : int rc = 0;
988 : :
989 [ - + ]: 6 : if (!_is_io_flags_valid(io_flags)) {
990 : 0 : return -EINVAL;
991 : : }
992 : :
993 [ + - - + ]: 6 : if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
994 : 0 : return -EINVAL;
995 : : }
996 : :
997 : 6 : rc = nvme_ns_cmd_check_zone_append(ns, lba_count, io_flags);
998 [ + + ]: 6 : if (rc) {
999 : 3 : return rc;
1000 : : }
1001 : :
1002 : 3 : payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, metadata);
1003 : :
1004 : 3 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, zslba, lba_count, cb_fn, cb_arg,
1005 : : SPDK_NVME_OPC_ZONE_APPEND,
1006 : 0 : io_flags, apptag_mask, apptag, 0, true, NULL, &rc);
1007 [ + - ]: 3 : if (req != NULL) {
1008 : : /*
1009 : : * Zone append commands cannot be split (num_children has to be 0).
1010 : : * For NVME_PAYLOAD_TYPE_SGL, _nvme_ns_cmd_rw() can cause a split.
1011 : : * However, _nvme_ns_cmd_split_request_sgl() and _nvme_ns_cmd_split_request_prp()
1012 : : * do not always cause a request to be split. These functions verify payload size,
1013 : : * verify num sge < max_sge, and verify SGE alignment rules (in case of PRPs).
1014 : : * If any of the verifications fail, they will split the request.
1015 : : * In our case, a split is very unlikely, since we already verified the size using
1016 : : * nvme_ns_cmd_check_zone_append(), however, we still need to call these functions
1017 : : * in order to perform the verification part. If they do cause a split, we return
1018 : : * an error here. For proper requests, these functions will never cause a split.
1019 : : */
1020 [ - + # # : 3 : if (req->num_children) {
# # ]
1021 : 0 : nvme_request_free_children(req);
1022 : 0 : nvme_free_request(req);
1023 : 0 : return -EINVAL;
1024 : : }
1025 : 3 : return nvme_qpair_submit_request(qpair, req);
1026 : : } else {
1027 : 0 : return nvme_ns_map_failure_rc(lba_count,
1028 [ # # # # ]: 0 : ns->sectors_per_max_io,
1029 [ # # # # ]: 0 : ns->sectors_per_stripe,
1030 [ # # # # : 0 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
1031 : 0 : rc);
1032 : : }
1033 : 0 : }
1034 : :
1035 : : int
1036 : 23613856 : spdk_nvme_ns_cmd_write_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1037 : : void *buffer, void *metadata, uint64_t lba,
1038 : : uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
1039 : : uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag)
1040 : : {
1041 : : struct nvme_request *req;
1042 : 5498782 : struct nvme_payload payload;
1043 : 23613856 : int rc = 0;
1044 : :
1045 [ - + ]: 23613856 : if (!_is_io_flags_valid(io_flags)) {
1046 : 0 : return -EINVAL;
1047 : : }
1048 : :
1049 : 23613856 : payload = NVME_PAYLOAD_CONTIG(buffer, metadata);
1050 : :
1051 : 23613856 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_WRITE,
1052 : 0 : io_flags, apptag_mask, apptag, 0, false, NULL, &rc);
1053 [ + + ]: 23613856 : if (req != NULL) {
1054 : 23529761 : return nvme_qpair_submit_request(qpair, req);
1055 : : } else {
1056 : 84095 : return nvme_ns_map_failure_rc(lba_count,
1057 [ # # # # ]: 0 : ns->sectors_per_max_io,
1058 [ # # # # ]: 0 : ns->sectors_per_stripe,
1059 [ # # # # : 84095 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
1060 : 0 : rc);
1061 : : }
1062 : 0 : }
1063 : :
1064 : : int
1065 : 202386 : spdk_nvme_ns_cmd_write_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1066 : : void *buffer, uint64_t lba,
1067 : : uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
1068 : : struct spdk_nvme_ns_cmd_ext_io_opts *opts)
1069 : : {
1070 : 202386 : return nvme_ns_cmd_rw_ext(ns, qpair, buffer, lba, lba_count, cb_fn, cb_arg, opts,
1071 : : SPDK_NVME_OPC_WRITE);
1072 : : }
1073 : :
1074 : : int
1075 : 66 : spdk_nvme_ns_cmd_writev(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1076 : : uint64_t lba, uint32_t lba_count,
1077 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
1078 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
1079 : : spdk_nvme_req_next_sge_cb next_sge_fn)
1080 : : {
1081 : : struct nvme_request *req;
1082 : 36 : struct nvme_payload payload;
1083 : 66 : int rc = 0;
1084 : :
1085 [ - + ]: 66 : if (!_is_io_flags_valid(io_flags)) {
1086 : 0 : return -EINVAL;
1087 : : }
1088 : :
1089 [ + + - + ]: 66 : if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
1090 : 3 : return -EINVAL;
1091 : : }
1092 : :
1093 : 63 : payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, NULL);
1094 : :
1095 : 63 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_WRITE,
1096 : 0 : io_flags, 0, 0, 0, true, NULL, &rc);
1097 [ + + ]: 63 : if (req != NULL) {
1098 : 60 : return nvme_qpair_submit_request(qpair, req);
1099 : : } else {
1100 : 3 : return nvme_ns_map_failure_rc(lba_count,
1101 [ # # # # ]: 0 : ns->sectors_per_max_io,
1102 [ # # # # ]: 0 : ns->sectors_per_stripe,
1103 [ # # # # : 3 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
1104 : 0 : rc);
1105 : : }
1106 : 0 : }
1107 : :
1108 : : int
1109 : 1885971 : spdk_nvme_ns_cmd_writev_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1110 : : uint64_t lba, uint32_t lba_count,
1111 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags,
1112 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
1113 : : spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata,
1114 : : uint16_t apptag_mask, uint16_t apptag)
1115 : : {
1116 : : struct nvme_request *req;
1117 : 1518574 : struct nvme_payload payload;
1118 : 1885971 : int rc = 0;
1119 : :
1120 [ - + ]: 1885971 : if (!_is_io_flags_valid(io_flags)) {
1121 : 0 : return -EINVAL;
1122 : : }
1123 : :
1124 [ + - - + ]: 1885971 : if (reset_sgl_fn == NULL || next_sge_fn == NULL) {
1125 : 0 : return -EINVAL;
1126 : : }
1127 : :
1128 : 1885971 : payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, metadata);
1129 : :
1130 : 1885971 : req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_WRITE,
1131 : 0 : io_flags, apptag_mask, apptag, 0, true, NULL, &rc);
1132 [ + + ]: 1885971 : if (req != NULL) {
1133 : 1885934 : return nvme_qpair_submit_request(qpair, req);
1134 : : } else {
1135 : 37 : return nvme_ns_map_failure_rc(lba_count,
1136 [ # # # # ]: 0 : ns->sectors_per_max_io,
1137 [ # # # # ]: 0 : ns->sectors_per_stripe,
1138 [ # # # # : 37 : qpair->ctrlr->opts.io_queue_requests,
# # # # #
# ]
1139 : 0 : rc);
1140 : : }
1141 : 0 : }
1142 : :
1143 : : int
1144 : 13 : spdk_nvme_ns_cmd_writev_ext(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, uint64_t lba,
1145 : : uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg,
1146 : : spdk_nvme_req_reset_sgl_cb reset_sgl_fn,
1147 : : spdk_nvme_req_next_sge_cb next_sge_fn,
1148 : : struct spdk_nvme_ns_cmd_ext_io_opts *opts)
1149 : : {
1150 : 13 : return nvme_ns_cmd_rwv_ext(ns, qpair, lba, lba_count, cb_fn, cb_arg, reset_sgl_fn, next_sge_fn,
1151 : 0 : opts, SPDK_NVME_OPC_WRITE);
1152 : : }
1153 : :
1154 : : int
1155 : 733619 : spdk_nvme_ns_cmd_write_zeroes(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1156 : : uint64_t lba, uint32_t lba_count,
1157 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg,
1158 : : uint32_t io_flags)
1159 : : {
1160 : : struct nvme_request *req;
1161 : : struct spdk_nvme_cmd *cmd;
1162 : : uint64_t *tmp_lba;
1163 : :
1164 [ - + ]: 733619 : if (!_is_io_flags_valid(io_flags)) {
1165 : 0 : return -EINVAL;
1166 : : }
1167 : :
1168 [ + - - + ]: 733619 : if (lba_count == 0 || lba_count > UINT16_MAX + 1) {
1169 : 0 : return -EINVAL;
1170 : : }
1171 : :
1172 : 733619 : req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
1173 [ + + ]: 733619 : if (req == NULL) {
1174 : 96 : return -ENOMEM;
1175 : : }
1176 : :
1177 [ # # ]: 733523 : cmd = &req->cmd;
1178 [ # # ]: 733523 : cmd->opc = SPDK_NVME_OPC_WRITE_ZEROES;
1179 [ # # # # : 733523 : cmd->nsid = ns->id;
# # # # ]
1180 : :
1181 [ # # # # ]: 733523 : tmp_lba = (uint64_t *)&cmd->cdw10;
1182 [ # # ]: 733523 : *tmp_lba = lba;
1183 [ # # # # : 733523 : cmd->cdw12 = lba_count - 1;
# # ]
1184 [ # # # # : 733523 : cmd->fuse = (io_flags & SPDK_NVME_IO_FLAGS_FUSE_MASK);
# # ]
1185 [ # # # # : 733523 : cmd->cdw12 |= (io_flags & SPDK_NVME_IO_FLAGS_CDW12_MASK);
# # ]
1186 : :
1187 : 733523 : return nvme_qpair_submit_request(qpair, req);
1188 : 0 : }
1189 : :
1190 : : int
1191 : 3 : spdk_nvme_ns_cmd_verify(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1192 : : uint64_t lba, uint32_t lba_count,
1193 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg,
1194 : : uint32_t io_flags)
1195 : : {
1196 : : struct nvme_request *req;
1197 : : struct spdk_nvme_cmd *cmd;
1198 : :
1199 [ - + ]: 3 : if (!_is_io_flags_valid(io_flags)) {
1200 : 0 : return -EINVAL;
1201 : : }
1202 : :
1203 [ + - - + ]: 3 : if (lba_count == 0 || lba_count > UINT16_MAX + 1) {
1204 : 0 : return -EINVAL;
1205 : : }
1206 : :
1207 : 3 : req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
1208 [ - + ]: 3 : if (req == NULL) {
1209 : 0 : return -ENOMEM;
1210 : : }
1211 : :
1212 [ # # ]: 3 : cmd = &req->cmd;
1213 [ # # ]: 3 : cmd->opc = SPDK_NVME_OPC_VERIFY;
1214 [ # # # # : 3 : cmd->nsid = ns->id;
# # # # ]
1215 : :
1216 [ # # # # : 3 : *(uint64_t *)&cmd->cdw10 = lba;
# # ]
1217 [ # # # # : 3 : cmd->cdw12 = lba_count - 1;
# # ]
1218 [ # # # # : 3 : cmd->fuse = (io_flags & SPDK_NVME_IO_FLAGS_FUSE_MASK);
# # ]
1219 [ # # # # : 3 : cmd->cdw12 |= (io_flags & SPDK_NVME_IO_FLAGS_CDW12_MASK);
# # ]
1220 : :
1221 : 3 : return nvme_qpair_submit_request(qpair, req);
1222 : 0 : }
1223 : :
1224 : : int
1225 : 3 : spdk_nvme_ns_cmd_write_uncorrectable(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1226 : : uint64_t lba, uint32_t lba_count,
1227 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
1228 : : {
1229 : : struct nvme_request *req;
1230 : : struct spdk_nvme_cmd *cmd;
1231 : : uint64_t *tmp_lba;
1232 : :
1233 [ + - - + ]: 3 : if (lba_count == 0 || lba_count > UINT16_MAX + 1) {
1234 : 0 : return -EINVAL;
1235 : : }
1236 : :
1237 : 3 : req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
1238 [ - + ]: 3 : if (req == NULL) {
1239 : 0 : return -ENOMEM;
1240 : : }
1241 : :
1242 [ # # ]: 3 : cmd = &req->cmd;
1243 [ # # ]: 3 : cmd->opc = SPDK_NVME_OPC_WRITE_UNCORRECTABLE;
1244 [ # # # # : 3 : cmd->nsid = ns->id;
# # # # ]
1245 : :
1246 [ # # # # ]: 3 : tmp_lba = (uint64_t *)&cmd->cdw10;
1247 [ # # ]: 3 : *tmp_lba = lba;
1248 [ # # # # : 3 : cmd->cdw12 = lba_count - 1;
# # ]
1249 : :
1250 : 3 : return nvme_qpair_submit_request(qpair, req);
1251 : 0 : }
1252 : :
1253 : : int
1254 : 258379 : spdk_nvme_ns_cmd_dataset_management(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1255 : : uint32_t type,
1256 : : const struct spdk_nvme_dsm_range *ranges, uint16_t num_ranges,
1257 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
1258 : : {
1259 : : struct nvme_request *req;
1260 : : struct spdk_nvme_cmd *cmd;
1261 : :
1262 [ + + - + ]: 258379 : if (num_ranges == 0 || num_ranges > SPDK_NVME_DATASET_MANAGEMENT_MAX_RANGES) {
1263 : 3 : return -EINVAL;
1264 : : }
1265 : :
1266 [ - + ]: 258376 : if (ranges == NULL) {
1267 : 0 : return -EINVAL;
1268 : : }
1269 : :
1270 : 258376 : req = nvme_allocate_request_user_copy(qpair, (void *)ranges,
1271 : 0 : num_ranges * sizeof(struct spdk_nvme_dsm_range),
1272 : 0 : cb_fn, cb_arg, true);
1273 [ + + ]: 258376 : if (req == NULL) {
1274 : 2721 : return -ENOMEM;
1275 : : }
1276 : :
1277 [ # # ]: 255655 : cmd = &req->cmd;
1278 [ # # ]: 255655 : cmd->opc = SPDK_NVME_OPC_DATASET_MANAGEMENT;
1279 [ # # # # : 255655 : cmd->nsid = ns->id;
# # # # ]
1280 : :
1281 [ # # # # : 255655 : cmd->cdw10_bits.dsm.nr = num_ranges - 1;
# # # # #
# ]
1282 [ # # # # : 255655 : cmd->cdw11 = type;
# # ]
1283 : :
1284 : 255655 : return nvme_qpair_submit_request(qpair, req);
1285 : 0 : }
1286 : :
1287 : : int
1288 : 50 : spdk_nvme_ns_cmd_copy(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1289 : : const struct spdk_nvme_scc_source_range *ranges,
1290 : : uint16_t num_ranges, uint64_t dest_lba,
1291 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
1292 : : {
1293 : : struct nvme_request *req;
1294 : : struct spdk_nvme_cmd *cmd;
1295 : :
1296 [ + + ]: 50 : if (num_ranges == 0) {
1297 : 3 : return -EINVAL;
1298 : : }
1299 : :
1300 [ - + ]: 47 : if (ranges == NULL) {
1301 : 0 : return -EINVAL;
1302 : : }
1303 : :
1304 : 47 : req = nvme_allocate_request_user_copy(qpair, (void *)ranges,
1305 : 0 : num_ranges * sizeof(struct spdk_nvme_scc_source_range),
1306 : 0 : cb_fn, cb_arg, true);
1307 [ - + ]: 47 : if (req == NULL) {
1308 : 0 : return -ENOMEM;
1309 : : }
1310 : :
1311 [ # # ]: 47 : cmd = &req->cmd;
1312 [ # # ]: 47 : cmd->opc = SPDK_NVME_OPC_COPY;
1313 [ # # # # : 47 : cmd->nsid = ns->id;
# # # # ]
1314 : :
1315 [ # # # # : 47 : *(uint64_t *)&cmd->cdw10 = dest_lba;
# # ]
1316 [ # # # # : 47 : cmd->cdw12 = num_ranges - 1;
# # # # ]
1317 : :
1318 : 47 : return nvme_qpair_submit_request(qpair, req);
1319 : 0 : }
1320 : :
1321 : : int
1322 : 3 : spdk_nvme_ns_cmd_flush(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1323 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
1324 : : {
1325 : : struct nvme_request *req;
1326 : : struct spdk_nvme_cmd *cmd;
1327 : :
1328 : 3 : req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
1329 [ - + ]: 3 : if (req == NULL) {
1330 : 0 : return -ENOMEM;
1331 : : }
1332 : :
1333 [ # # ]: 3 : cmd = &req->cmd;
1334 [ # # ]: 3 : cmd->opc = SPDK_NVME_OPC_FLUSH;
1335 [ # # # # : 3 : cmd->nsid = ns->id;
# # # # ]
1336 : :
1337 : 3 : return nvme_qpair_submit_request(qpair, req);
1338 : 0 : }
1339 : :
1340 : : int
1341 : 3 : spdk_nvme_ns_cmd_reservation_register(struct spdk_nvme_ns *ns,
1342 : : struct spdk_nvme_qpair *qpair,
1343 : : struct spdk_nvme_reservation_register_data *payload,
1344 : : bool ignore_key,
1345 : : enum spdk_nvme_reservation_register_action action,
1346 : : enum spdk_nvme_reservation_register_cptpl cptpl,
1347 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
1348 : : {
1349 : : struct nvme_request *req;
1350 : : struct spdk_nvme_cmd *cmd;
1351 : :
1352 : 3 : req = nvme_allocate_request_user_copy(qpair,
1353 : 0 : payload, sizeof(struct spdk_nvme_reservation_register_data),
1354 : 0 : cb_fn, cb_arg, true);
1355 [ - + ]: 3 : if (req == NULL) {
1356 : 0 : return -ENOMEM;
1357 : : }
1358 : :
1359 [ # # ]: 3 : cmd = &req->cmd;
1360 [ # # ]: 3 : cmd->opc = SPDK_NVME_OPC_RESERVATION_REGISTER;
1361 [ # # # # : 3 : cmd->nsid = ns->id;
# # # # ]
1362 : :
1363 [ # # # # : 3 : cmd->cdw10_bits.resv_register.rrega = action;
# # # # ]
1364 [ # # # # : 3 : cmd->cdw10_bits.resv_register.iekey = ignore_key;
# # # # #
# ]
1365 [ # # # # : 3 : cmd->cdw10_bits.resv_register.cptpl = cptpl;
# # # # ]
1366 : :
1367 : 3 : return nvme_qpair_submit_request(qpair, req);
1368 : 0 : }
1369 : :
1370 : : int
1371 : 3 : spdk_nvme_ns_cmd_reservation_release(struct spdk_nvme_ns *ns,
1372 : : struct spdk_nvme_qpair *qpair,
1373 : : struct spdk_nvme_reservation_key_data *payload,
1374 : : bool ignore_key,
1375 : : enum spdk_nvme_reservation_release_action action,
1376 : : enum spdk_nvme_reservation_type type,
1377 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
1378 : : {
1379 : : struct nvme_request *req;
1380 : : struct spdk_nvme_cmd *cmd;
1381 : :
1382 : 3 : req = nvme_allocate_request_user_copy(qpair,
1383 : 0 : payload, sizeof(struct spdk_nvme_reservation_key_data), cb_fn,
1384 : 0 : cb_arg, true);
1385 [ - + ]: 3 : if (req == NULL) {
1386 : 0 : return -ENOMEM;
1387 : : }
1388 : :
1389 [ # # ]: 3 : cmd = &req->cmd;
1390 [ # # ]: 3 : cmd->opc = SPDK_NVME_OPC_RESERVATION_RELEASE;
1391 [ # # # # : 3 : cmd->nsid = ns->id;
# # # # ]
1392 : :
1393 [ # # # # : 3 : cmd->cdw10_bits.resv_release.rrela = action;
# # # # ]
1394 [ # # # # : 3 : cmd->cdw10_bits.resv_release.iekey = ignore_key;
# # # # #
# ]
1395 [ # # # # : 3 : cmd->cdw10_bits.resv_release.rtype = type;
# # # # ]
1396 : :
1397 : 3 : return nvme_qpair_submit_request(qpair, req);
1398 : 0 : }
1399 : :
1400 : : int
1401 : 3 : spdk_nvme_ns_cmd_reservation_acquire(struct spdk_nvme_ns *ns,
1402 : : struct spdk_nvme_qpair *qpair,
1403 : : struct spdk_nvme_reservation_acquire_data *payload,
1404 : : bool ignore_key,
1405 : : enum spdk_nvme_reservation_acquire_action action,
1406 : : enum spdk_nvme_reservation_type type,
1407 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
1408 : : {
1409 : : struct nvme_request *req;
1410 : : struct spdk_nvme_cmd *cmd;
1411 : :
1412 : 3 : req = nvme_allocate_request_user_copy(qpair,
1413 : 0 : payload, sizeof(struct spdk_nvme_reservation_acquire_data),
1414 : 0 : cb_fn, cb_arg, true);
1415 [ - + ]: 3 : if (req == NULL) {
1416 : 0 : return -ENOMEM;
1417 : : }
1418 : :
1419 [ # # ]: 3 : cmd = &req->cmd;
1420 [ # # ]: 3 : cmd->opc = SPDK_NVME_OPC_RESERVATION_ACQUIRE;
1421 [ # # # # : 3 : cmd->nsid = ns->id;
# # # # ]
1422 : :
1423 [ # # # # : 3 : cmd->cdw10_bits.resv_acquire.racqa = action;
# # # # ]
1424 [ # # # # : 3 : cmd->cdw10_bits.resv_acquire.iekey = ignore_key;
# # # # #
# ]
1425 [ # # # # : 3 : cmd->cdw10_bits.resv_acquire.rtype = type;
# # # # ]
1426 : :
1427 : 3 : return nvme_qpair_submit_request(qpair, req);
1428 : 0 : }
1429 : :
1430 : : int
1431 : 3 : spdk_nvme_ns_cmd_reservation_report(struct spdk_nvme_ns *ns,
1432 : : struct spdk_nvme_qpair *qpair,
1433 : : void *payload, uint32_t len,
1434 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
1435 : : {
1436 : : uint32_t num_dwords;
1437 : : struct nvme_request *req;
1438 : : struct spdk_nvme_cmd *cmd;
1439 : :
1440 [ - + ]: 3 : if (len & 0x3) {
1441 : 0 : return -EINVAL;
1442 : : }
1443 : :
1444 : 3 : req = nvme_allocate_request_user_copy(qpair, payload, len, cb_fn, cb_arg, false);
1445 [ - + ]: 3 : if (req == NULL) {
1446 : 0 : return -ENOMEM;
1447 : : }
1448 : :
1449 [ # # ]: 3 : cmd = &req->cmd;
1450 [ # # ]: 3 : cmd->opc = SPDK_NVME_OPC_RESERVATION_REPORT;
1451 [ # # # # : 3 : cmd->nsid = ns->id;
# # # # ]
1452 : :
1453 [ # # ]: 3 : num_dwords = (len >> 2);
1454 [ # # # # : 3 : cmd->cdw10 = num_dwords - 1; /* 0-based */
# # ]
1455 : :
1456 : 3 : return nvme_qpair_submit_request(qpair, req);
1457 : 0 : }
1458 : :
1459 : : int
1460 : 8 : spdk_nvme_ns_cmd_io_mgmt_recv(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1461 : : void *payload, uint32_t len, uint8_t mo, uint16_t mos,
1462 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
1463 : : {
1464 : : uint32_t num_dwords;
1465 : : struct nvme_request *req;
1466 : : struct spdk_nvme_cmd *cmd;
1467 : :
1468 [ + + ]: 8 : if (len & 0x3) {
1469 : 3 : return -EINVAL;
1470 : : }
1471 : :
1472 : 5 : req = nvme_allocate_request_user_copy(qpair, payload, len, cb_fn, cb_arg, false);
1473 [ - + ]: 5 : if (req == NULL) {
1474 : 0 : return -ENOMEM;
1475 : : }
1476 : :
1477 [ # # ]: 5 : cmd = &req->cmd;
1478 [ # # ]: 5 : cmd->opc = SPDK_NVME_OPC_IO_MANAGEMENT_RECEIVE;
1479 [ # # # # : 5 : cmd->nsid = ns->id;
# # # # ]
1480 : :
1481 [ # # # # : 5 : cmd->cdw10_bits.mgmt_send_recv.mo = mo;
# # # # ]
1482 [ # # # # : 5 : cmd->cdw10_bits.mgmt_send_recv.mos = mos;
# # # # ]
1483 : :
1484 [ # # ]: 5 : num_dwords = (len >> 2);
1485 [ # # # # : 5 : cmd->cdw11 = num_dwords - 1; /* 0-based */
# # ]
1486 : :
1487 : 5 : return nvme_qpair_submit_request(qpair, req);
1488 : 0 : }
1489 : :
1490 : : int
1491 : 4 : spdk_nvme_ns_cmd_io_mgmt_send(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
1492 : : void *payload, uint32_t len, uint8_t mo, uint16_t mos,
1493 : : spdk_nvme_cmd_cb cb_fn, void *cb_arg)
1494 : : {
1495 : : struct nvme_request *req;
1496 : : struct spdk_nvme_cmd *cmd;
1497 : :
1498 : 4 : req = nvme_allocate_request_user_copy(qpair, payload, len, cb_fn, cb_arg, false);
1499 [ - + ]: 4 : if (req == NULL) {
1500 : 0 : return -ENOMEM;
1501 : : }
1502 : :
1503 [ # # ]: 4 : cmd = &req->cmd;
1504 [ # # ]: 4 : cmd->opc = SPDK_NVME_OPC_IO_MANAGEMENT_SEND;
1505 [ # # # # : 4 : cmd->nsid = ns->id;
# # # # ]
1506 : :
1507 [ # # # # : 4 : cmd->cdw10_bits.mgmt_send_recv.mo = mo;
# # # # ]
1508 [ # # # # : 4 : cmd->cdw10_bits.mgmt_send_recv.mos = mos;
# # # # ]
1509 : :
1510 : 4 : return nvme_qpair_submit_request(qpair, req);
1511 : 0 : }
|