xref: /spdk/lib/nvmf/ctrlr_bdev.c (revision d92f0f75caf311608f5f0e19d4b3db349609b4e8)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "subsystem.h"
37 #include "ctrlr.h"
38 #include "request.h"
39 
40 #include "spdk/bdev.h"
41 #include "spdk/endian.h"
42 #include "spdk/io_channel.h"
43 #include "spdk/nvme.h"
44 #include "spdk/nvmf_spec.h"
45 #include "spdk/trace.h"
46 #include "spdk/scsi_spec.h"
47 #include "spdk/string.h"
48 #include "spdk/util.h"
49 
50 #include "spdk_internal/log.h"
51 
52 /* read command dword 12 */
53 struct __attribute__((packed)) nvme_read_cdw12 {
54 	uint16_t	nlb;		/* number of logical blocks */
55 	uint16_t	rsvd	: 10;
56 	uint8_t		prinfo	: 4;	/* protection information field */
57 	uint8_t		fua	: 1;	/* force unit access */
58 	uint8_t		lr	: 1;	/* limited retry */
59 };
60 
61 bool
62 spdk_nvmf_ctrlr_dsm_supported(struct spdk_nvmf_ctrlr *ctrlr)
63 {
64 	struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys;
65 	struct spdk_nvmf_ns *ns;
66 
67 	for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
68 	     ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
69 		if (ns->bdev == NULL) {
70 			continue;
71 		}
72 
73 		if (!spdk_bdev_io_type_supported(ns->bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
74 			SPDK_DEBUGLOG(SPDK_TRACE_NVMF,
75 				      "Subsystem %s namespace %u (%s) does not support unmap - not enabling DSM\n",
76 				      spdk_nvmf_subsystem_get_nqn(subsystem),
77 				      ns->id, spdk_bdev_get_name(ns->bdev));
78 			return false;
79 		}
80 	}
81 
82 	SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "All devices in Subsystem %s support unmap - enabling DSM\n",
83 		      spdk_nvmf_subsystem_get_nqn(subsystem));
84 	return true;
85 }
86 
87 static void
88 nvmf_bdev_ctrlr_complete_cmd(struct spdk_bdev_io *bdev_io, bool success,
89 			     void *cb_arg)
90 {
91 	struct spdk_nvmf_request 	*req = cb_arg;
92 	struct spdk_nvme_cpl 		*response = &req->rsp->nvme_cpl;
93 	int				sc, sct;
94 
95 	spdk_bdev_io_get_nvme_status(bdev_io, &sc, &sct);
96 	response->status.sc = sc;
97 	response->status.sct = sct;
98 
99 	spdk_nvmf_request_complete(req);
100 	spdk_bdev_free_io(bdev_io);
101 }
102 
103 int
104 spdk_nvmf_bdev_ctrlr_identify_ns(struct spdk_bdev *bdev, struct spdk_nvme_ns_data *nsdata)
105 {
106 	uint64_t num_blocks;
107 
108 	num_blocks = spdk_bdev_get_num_blocks(bdev);
109 
110 	nsdata->nsze = num_blocks;
111 	nsdata->ncap = num_blocks;
112 	nsdata->nuse = num_blocks;
113 	nsdata->nlbaf = 0;
114 	nsdata->flbas.format = 0;
115 	nsdata->lbaf[0].lbads = spdk_u32log2(spdk_bdev_get_block_size(bdev));
116 	nsdata->noiob = spdk_bdev_get_optimal_io_boundary(bdev);
117 
118 	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
119 }
120 
121 static int
122 nvmf_bdev_ctrlr_rw_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
123 		       struct spdk_io_channel *ch, struct spdk_nvmf_request *req)
124 {
125 	uint64_t lba_address;
126 	uint64_t blockcnt;
127 	uint64_t io_bytes;
128 	uint64_t offset;
129 	uint64_t llen;
130 	uint32_t block_size = spdk_bdev_get_block_size(bdev);
131 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
132 	struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
133 	struct nvme_read_cdw12 *cdw12 = (struct nvme_read_cdw12 *)&cmd->cdw12;
134 
135 	blockcnt = spdk_bdev_get_num_blocks(bdev);
136 	lba_address = cmd->cdw11;
137 	lba_address = (lba_address << 32) + cmd->cdw10;
138 	offset = lba_address * block_size;
139 	llen = cdw12->nlb + 1;
140 
141 	if (lba_address >= blockcnt || llen > blockcnt || lba_address > (blockcnt - llen)) {
142 		SPDK_ERRLOG("end of media\n");
143 		response->status.sc = SPDK_NVME_SC_LBA_OUT_OF_RANGE;
144 		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
145 	}
146 
147 	io_bytes = llen * block_size;
148 	if (io_bytes > req->length) {
149 		SPDK_ERRLOG("Read/Write NLB > SGL length\n");
150 		response->status.sc = SPDK_NVME_SC_DATA_SGL_LENGTH_INVALID;
151 		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
152 	}
153 
154 	if (cmd->opc == SPDK_NVME_OPC_READ) {
155 		spdk_trace_record(TRACE_NVMF_LIB_READ_START, 0, 0, (uint64_t)req, 0);
156 		if (spdk_bdev_read(desc, ch, req->data, offset, req->length, nvmf_bdev_ctrlr_complete_cmd,
157 				   req)) {
158 			response->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
159 			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
160 		}
161 	} else {
162 		spdk_trace_record(TRACE_NVMF_LIB_WRITE_START, 0, 0, (uint64_t)req, 0);
163 		if (spdk_bdev_write(desc, ch, req->data, offset, req->length, nvmf_bdev_ctrlr_complete_cmd,
164 				    req)) {
165 			response->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
166 			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
167 		}
168 	}
169 	return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS;
170 
171 }
172 
173 static int
174 nvmf_bdev_ctrlr_flush_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
175 			  struct spdk_io_channel *ch, struct spdk_nvmf_request *req)
176 {
177 	uint64_t nbytes;
178 	struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
179 
180 	nbytes = spdk_bdev_get_num_blocks(bdev) * spdk_bdev_get_block_size(bdev);
181 	if (spdk_bdev_flush(desc, ch, 0, nbytes, nvmf_bdev_ctrlr_complete_cmd, req)) {
182 		response->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
183 		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
184 	}
185 	return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS;
186 }
187 
188 struct nvmf_virtual_ctrlr_unmap {
189 	struct spdk_nvmf_request	*req;
190 	uint32_t			count;
191 };
192 
193 static void
194 nvmf_virtual_ctrlr_dsm_cpl(struct spdk_bdev_io *bdev_io, bool success,
195 			   void *cb_arg)
196 {
197 	struct nvmf_virtual_ctrlr_unmap *unmap_ctx = cb_arg;
198 	struct spdk_nvmf_request 	*req = unmap_ctx->req;
199 	struct spdk_nvme_cpl 		*response = &req->rsp->nvme_cpl;
200 	int				sc, sct;
201 
202 	unmap_ctx->count--;
203 
204 	if (response->status.sct == SPDK_NVME_SCT_GENERIC &&
205 	    response->status.sc == SPDK_NVME_SC_SUCCESS) {
206 		spdk_bdev_io_get_nvme_status(bdev_io, &sc, &sct);
207 		response->status.sc = sc;
208 		response->status.sct = sct;
209 	}
210 
211 	if (unmap_ctx->count == 0) {
212 		spdk_nvmf_request_complete(req);
213 		spdk_bdev_free_io(bdev_io);
214 		free(unmap_ctx);
215 	}
216 }
217 
218 static int
219 nvmf_bdev_ctrlr_dsm_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
220 			struct spdk_io_channel *ch, struct spdk_nvmf_request *req)
221 {
222 	uint32_t attribute;
223 	uint16_t nr, i;
224 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
225 	struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
226 
227 	nr = ((cmd->cdw10 & 0x000000ff) + 1);
228 	if (nr * sizeof(struct spdk_nvme_dsm_range) > req->length) {
229 		SPDK_ERRLOG("Dataset Management number of ranges > SGL length\n");
230 		response->status.sc = SPDK_NVME_SC_DATA_SGL_LENGTH_INVALID;
231 		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
232 	}
233 
234 	attribute = cmd->cdw11 & 0x00000007;
235 	if (attribute & SPDK_NVME_DSM_ATTR_DEALLOCATE) {
236 		struct nvmf_virtual_ctrlr_unmap *unmap_ctx;
237 		struct spdk_nvme_dsm_range *dsm_range;
238 		uint64_t lba;
239 		uint32_t lba_count;
240 		uint32_t block_size = spdk_bdev_get_block_size(bdev);
241 
242 		unmap_ctx = calloc(1, sizeof(*unmap_ctx));
243 		if (!unmap_ctx) {
244 			response->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
245 			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
246 		}
247 
248 		unmap_ctx->req = req;
249 
250 		response->status.sct = SPDK_NVME_SCT_GENERIC;
251 		response->status.sc = SPDK_NVME_SC_SUCCESS;
252 
253 		dsm_range = (struct spdk_nvme_dsm_range *)req->data;
254 		for (i = 0; i < nr; i++) {
255 			lba = dsm_range[i].starting_lba;
256 			lba_count = dsm_range[i].length;
257 
258 			unmap_ctx->count++;
259 
260 			if (spdk_bdev_unmap(desc, ch, lba * block_size, lba_count * block_size,
261 					    nvmf_virtual_ctrlr_dsm_cpl, unmap_ctx)) {
262 				response->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
263 				unmap_ctx->count--;
264 				/* We can't return here - we may have to wait for any other
265 				 * unmaps already sent to complete */
266 				break;
267 			}
268 		}
269 
270 		if (unmap_ctx->count == 0) {
271 			free(unmap_ctx);
272 			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
273 		}
274 
275 		return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS;
276 	}
277 
278 	response->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
279 	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
280 }
281 
282 static int
283 nvmf_bdev_ctrlr_nvme_passthru_io(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
284 				 struct spdk_io_channel *ch, struct spdk_nvmf_request *req)
285 {
286 	if (spdk_bdev_nvme_io_passthru(desc, ch, &req->cmd->nvme_cmd, req->data, req->length,
287 				       nvmf_bdev_ctrlr_complete_cmd, req)) {
288 		req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
289 		req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_INVALID_OPCODE;
290 		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
291 	}
292 
293 	return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS;
294 }
295 
296 int
297 spdk_nvmf_ctrlr_process_io_cmd(struct spdk_nvmf_request *req)
298 {
299 	uint32_t nsid;
300 	struct spdk_nvmf_ns *ns;
301 	struct spdk_bdev *bdev;
302 	struct spdk_bdev_desc *desc;
303 	struct spdk_io_channel *ch;
304 	struct spdk_nvmf_subsystem *subsystem = req->qpair->ctrlr->subsys;
305 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
306 	struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
307 
308 	/* pre-set response details for this command */
309 	response->status.sc = SPDK_NVME_SC_SUCCESS;
310 	nsid = cmd->nsid;
311 
312 	ns = _spdk_nvmf_subsystem_get_ns(subsystem, nsid);
313 	if (ns == NULL || ns->bdev == NULL) {
314 		SPDK_ERRLOG("Unsuccessful query for nsid %u\n", cmd->nsid);
315 		response->status.sc = SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT;
316 		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
317 	}
318 
319 	bdev = ns->bdev;
320 	desc = ns->desc;
321 	ch = ns->ch;
322 	switch (cmd->opc) {
323 	case SPDK_NVME_OPC_READ:
324 	case SPDK_NVME_OPC_WRITE:
325 		return nvmf_bdev_ctrlr_rw_cmd(bdev, desc, ch, req);
326 	case SPDK_NVME_OPC_FLUSH:
327 		return nvmf_bdev_ctrlr_flush_cmd(bdev, desc, ch, req);
328 	case SPDK_NVME_OPC_DATASET_MANAGEMENT:
329 		return nvmf_bdev_ctrlr_dsm_cmd(bdev, desc, ch, req);
330 	default:
331 		return nvmf_bdev_ctrlr_nvme_passthru_io(bdev, desc, ch, req);
332 	}
333 }
334 
335 static int
336 spdk_nvmf_ns_bdev_attach(struct spdk_nvmf_ns *ns)
337 {
338 	if (ns->bdev == NULL) {
339 		return 0;
340 	}
341 
342 	ns->ch = spdk_bdev_get_io_channel(ns->desc);
343 	if (ns->ch == NULL) {
344 		SPDK_ERRLOG("io_channel allocation failed\n");
345 		return -1;
346 	}
347 
348 	return 0;
349 }
350 
351 static void
352 spdk_nvmf_ns_bdev_detach(struct spdk_nvmf_ns *ns)
353 {
354 	if (ns->bdev == NULL) {
355 		return;
356 	}
357 
358 	if (ns->ch) {
359 		spdk_put_io_channel(ns->ch);
360 		ns->ch = NULL;
361 	}
362 	if (ns->desc) {
363 		spdk_bdev_close(ns->desc);
364 		ns->desc = NULL;
365 	}
366 	ns->bdev = NULL;
367 }
368 
369 int
370 spdk_nvmf_subsystem_bdev_attach(struct spdk_nvmf_subsystem *subsystem)
371 {
372 	struct spdk_nvmf_ns *ns;
373 
374 	for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
375 	     ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
376 		if (spdk_nvmf_ns_bdev_attach(ns)) {
377 			return -1;
378 		}
379 	}
380 
381 	return 0;
382 }
383 
384 void
385 spdk_nvmf_subsystem_bdev_detach(struct spdk_nvmf_subsystem *subsystem)
386 {
387 	struct spdk_nvmf_ns *ns;
388 
389 	for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
390 	     ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
391 		spdk_nvmf_ns_bdev_detach(ns);
392 	}
393 	subsystem->max_nsid = 0;
394 }
395