xref: /spdk/lib/scsi/dev.c (revision ba8f1a9e5d59b6dfa9fd07c1300891b4e03722d9)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
5  *   Copyright (c) Intel Corporation.
6  *   All rights reserved.
7  *
8  *   Redistribution and use in source and binary forms, with or without
9  *   modification, are permitted provided that the following conditions
10  *   are met:
11  *
12  *     * Redistributions of source code must retain the above copyright
13  *       notice, this list of conditions and the following disclaimer.
14  *     * Redistributions in binary form must reproduce the above copyright
15  *       notice, this list of conditions and the following disclaimer in
16  *       the documentation and/or other materials provided with the
17  *       distribution.
18  *     * Neither the name of Intel Corporation nor the names of its
19  *       contributors may be used to endorse or promote products derived
20  *       from this software without specific prior written permission.
21  *
22  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include "scsi_internal.h"
36 
37 static struct spdk_scsi_dev g_devs[SPDK_SCSI_MAX_DEVS];
38 
39 struct spdk_scsi_dev *
40 scsi_dev_get_list(void)
41 {
42 	return g_devs;
43 }
44 
45 static struct spdk_scsi_dev *
46 allocate_dev(void)
47 {
48 	struct spdk_scsi_dev *dev;
49 	int i;
50 
51 	for (i = 0; i < SPDK_SCSI_MAX_DEVS; i++) {
52 		dev = &g_devs[i];
53 		if (!dev->is_allocated) {
54 			memset(dev, 0, sizeof(*dev));
55 			dev->id = i;
56 			dev->is_allocated = 1;
57 			TAILQ_INIT(&dev->luns);
58 			return dev;
59 		}
60 	}
61 
62 	return NULL;
63 }
64 
65 static void
66 free_dev(struct spdk_scsi_dev *dev)
67 {
68 	assert(dev->is_allocated == 1);
69 	assert(dev->removed == true);
70 
71 	dev->is_allocated = 0;
72 
73 	if (dev->remove_cb) {
74 		dev->remove_cb(dev->remove_ctx, 0);
75 		dev->remove_cb = NULL;
76 	}
77 }
78 
79 void
80 spdk_scsi_dev_destruct(struct spdk_scsi_dev *dev,
81 		       spdk_scsi_dev_destruct_cb_t cb_fn, void *cb_arg)
82 {
83 	struct spdk_scsi_lun *lun, *tmp_lun;
84 
85 	if (dev == NULL) {
86 		if (cb_fn) {
87 			cb_fn(cb_arg, -EINVAL);
88 		}
89 		return;
90 	}
91 
92 	if (dev->removed) {
93 		if (cb_fn) {
94 			cb_fn(cb_arg, -EINVAL);
95 		}
96 		return;
97 	}
98 
99 	dev->removed = true;
100 	dev->remove_cb = cb_fn;
101 	dev->remove_ctx = cb_arg;
102 
103 	if (TAILQ_EMPTY(&dev->luns)) {
104 		free_dev(dev);
105 		return;
106 	}
107 
108 	TAILQ_FOREACH_SAFE(lun, &dev->luns, tailq, tmp_lun) {
109 		/*
110 		 * LUN will remove itself from this dev when all outstanding IO
111 		 * is done. When no more LUNs, dev will be deleted.
112 		 */
113 		scsi_lun_destruct(lun);
114 	}
115 }
116 
117 /*
118  * Search the lowest free LUN ID if the LUN ID is default, or check if the LUN ID is free otherwise,
119  * and also return the LUN which comes just before where we want to insert an new LUN.
120  */
121 static int
122 scsi_dev_find_free_lun(struct spdk_scsi_dev *dev, int lun_id,
123 		       struct spdk_scsi_lun **prev_lun)
124 {
125 	struct spdk_scsi_lun *lun, *_prev_lun = NULL;
126 
127 	if (prev_lun == NULL) {
128 		return -EINVAL;
129 	}
130 
131 	if (lun_id == -1) {
132 		lun_id = 0;
133 
134 		TAILQ_FOREACH(lun, &dev->luns, tailq) {
135 			if (lun->id > lun_id) {
136 				break;
137 			}
138 			lun_id = lun->id + 1;
139 			_prev_lun = lun;
140 		}
141 
142 		if (lun_id >= SPDK_SCSI_DEV_MAX_LUN) {
143 			return -ENOSPC;
144 		}
145 	} else {
146 		TAILQ_FOREACH(lun, &dev->luns, tailq) {
147 			if (lun->id == lun_id) {
148 				return -EEXIST;
149 			} else if (lun->id > lun_id) {
150 				break;
151 			}
152 			_prev_lun = lun;
153 		}
154 	}
155 
156 	*prev_lun = _prev_lun;
157 	return 0;
158 }
159 
160 int
161 spdk_scsi_dev_add_lun(struct spdk_scsi_dev *dev, const char *bdev_name, int lun_id,
162 		      void (*hotremove_cb)(const struct spdk_scsi_lun *, void *),
163 		      void *hotremove_ctx)
164 {
165 	return spdk_scsi_dev_add_lun_ext(dev, bdev_name, lun_id,
166 					 NULL, NULL,
167 					 hotremove_cb, hotremove_ctx);
168 }
169 
170 int
171 spdk_scsi_dev_add_lun_ext(struct spdk_scsi_dev *dev, const char *bdev_name, int lun_id,
172 			  void (*resize_cb)(const struct spdk_scsi_lun *, void *),
173 			  void *resize_ctx,
174 			  void (*hotremove_cb)(const struct spdk_scsi_lun *, void *),
175 			  void *hotremove_ctx)
176 {
177 	struct spdk_scsi_lun *lun, *prev_lun = NULL;
178 	int rc;
179 
180 	if (lun_id >= SPDK_SCSI_DEV_MAX_LUN) {
181 		SPDK_ERRLOG("LUN ID %d is more than the maximum.\n", lun_id);
182 		return -1;
183 	}
184 
185 	rc = scsi_dev_find_free_lun(dev, lun_id, &prev_lun);
186 	if (rc != 0) {
187 		SPDK_ERRLOG("%s\n", rc == -EEXIST ? "LUN ID is duplicated" : "Free LUN ID is not found");
188 		return rc;
189 	}
190 
191 	lun = scsi_lun_construct(bdev_name, resize_cb, resize_ctx, hotremove_cb, hotremove_ctx);
192 	if (lun == NULL) {
193 		return -1;
194 	}
195 
196 	lun->dev = dev;
197 
198 	if (lun_id != -1) {
199 		lun->id = lun_id;
200 	} else if (prev_lun == NULL) {
201 		lun->id = 0;
202 	} else {
203 		lun->id = prev_lun->id + 1;
204 	}
205 
206 	if (prev_lun == NULL) {
207 		TAILQ_INSERT_HEAD(&dev->luns, lun, tailq);
208 	} else {
209 		TAILQ_INSERT_AFTER(&dev->luns, prev_lun, lun, tailq);
210 	}
211 	return 0;
212 }
213 
214 void
215 spdk_scsi_dev_delete_lun(struct spdk_scsi_dev *dev,
216 			 struct spdk_scsi_lun *lun)
217 {
218 	TAILQ_REMOVE(&dev->luns, lun, tailq);
219 
220 	if (dev->removed && TAILQ_EMPTY(&dev->luns)) {
221 		free_dev(dev);
222 	}
223 }
224 
225 struct spdk_scsi_dev *spdk_scsi_dev_construct(const char *name, const char *bdev_name_list[],
226 		int *lun_id_list, int num_luns, uint8_t protocol_id,
227 		void (*hotremove_cb)(const struct spdk_scsi_lun *, void *),
228 		void *hotremove_ctx)
229 {
230 	return spdk_scsi_dev_construct_ext(name, bdev_name_list, lun_id_list,
231 					   num_luns, protocol_id,
232 					   NULL, NULL,
233 					   hotremove_cb, hotremove_ctx);
234 }
235 
236 struct spdk_scsi_dev *spdk_scsi_dev_construct_ext(const char *name, const char *bdev_name_list[],
237 		int *lun_id_list, int num_luns, uint8_t protocol_id,
238 		void (*resize_cb)(const struct spdk_scsi_lun *, void *),
239 		void *resize_ctx,
240 		void (*hotremove_cb)(const struct spdk_scsi_lun *, void *),
241 		void *hotremove_ctx)
242 {
243 	struct spdk_scsi_dev *dev;
244 	size_t name_len;
245 	bool found_lun_0;
246 	int i, rc;
247 
248 	name_len = strlen(name);
249 	if (name_len > sizeof(dev->name) - 1) {
250 		SPDK_ERRLOG("device %s: name longer than maximum allowed length %zu\n",
251 			    name, sizeof(dev->name) - 1);
252 		return NULL;
253 	}
254 
255 	if (num_luns == 0) {
256 		SPDK_ERRLOG("device %s: no LUNs specified\n", name);
257 		return NULL;
258 	}
259 
260 	found_lun_0 = false;
261 	for (i = 0; i < num_luns; i++) {
262 		if (lun_id_list[i] == 0) {
263 			found_lun_0 = true;
264 			break;
265 		}
266 	}
267 
268 	if (!found_lun_0) {
269 		SPDK_ERRLOG("device %s: no LUN 0 specified\n", name);
270 		return NULL;
271 	}
272 
273 	for (i = 0; i < num_luns; i++) {
274 		if (bdev_name_list[i] == NULL) {
275 			SPDK_ERRLOG("NULL spdk_scsi_lun for LUN %d\n",
276 				    lun_id_list[i]);
277 			return NULL;
278 		}
279 	}
280 
281 	dev = allocate_dev();
282 	if (dev == NULL) {
283 		return NULL;
284 	}
285 
286 	memcpy(dev->name, name, name_len + 1);
287 
288 	dev->num_ports = 0;
289 	dev->protocol_id = protocol_id;
290 
291 	for (i = 0; i < num_luns; i++) {
292 		rc = spdk_scsi_dev_add_lun_ext(dev, bdev_name_list[i], lun_id_list[i],
293 					       resize_cb, resize_ctx,
294 					       hotremove_cb, hotremove_ctx);
295 		if (rc < 0) {
296 			spdk_scsi_dev_destruct(dev, NULL, NULL);
297 			return NULL;
298 		}
299 	}
300 
301 	return dev;
302 }
303 
304 void
305 spdk_scsi_dev_queue_mgmt_task(struct spdk_scsi_dev *dev,
306 			      struct spdk_scsi_task *task)
307 {
308 	assert(task != NULL);
309 
310 	scsi_lun_execute_mgmt_task(task->lun, task);
311 }
312 
313 void
314 spdk_scsi_dev_queue_task(struct spdk_scsi_dev *dev,
315 			 struct spdk_scsi_task *task)
316 {
317 	assert(task != NULL);
318 
319 	scsi_lun_execute_task(task->lun, task);
320 }
321 
322 static struct spdk_scsi_port *
323 scsi_dev_find_free_port(struct spdk_scsi_dev *dev)
324 {
325 	int i;
326 
327 	for (i = 0; i < SPDK_SCSI_DEV_MAX_PORTS; i++) {
328 		if (!dev->port[i].is_used) {
329 			return &dev->port[i];
330 		}
331 	}
332 
333 	return NULL;
334 }
335 
336 int
337 spdk_scsi_dev_add_port(struct spdk_scsi_dev *dev, uint64_t id, const char *name)
338 {
339 	struct spdk_scsi_port *port;
340 	int rc;
341 
342 	if (dev->num_ports == SPDK_SCSI_DEV_MAX_PORTS) {
343 		SPDK_ERRLOG("device already has %d ports\n", SPDK_SCSI_DEV_MAX_PORTS);
344 		return -1;
345 	}
346 
347 	port = spdk_scsi_dev_find_port_by_id(dev, id);
348 	if (port != NULL) {
349 		SPDK_ERRLOG("device already has port(%" PRIu64 ")\n", id);
350 		return -1;
351 	}
352 
353 	port = scsi_dev_find_free_port(dev);
354 	if (port == NULL) {
355 		assert(false);
356 		return -1;
357 	}
358 
359 	rc = scsi_port_construct(port, id, dev->num_ports, name);
360 	if (rc != 0) {
361 		return rc;
362 	}
363 
364 	dev->num_ports++;
365 	return 0;
366 }
367 
368 int
369 spdk_scsi_dev_delete_port(struct spdk_scsi_dev *dev, uint64_t id)
370 {
371 	struct spdk_scsi_port *port;
372 
373 	port = spdk_scsi_dev_find_port_by_id(dev, id);
374 	if (port == NULL) {
375 		SPDK_ERRLOG("device does not have specified port(%" PRIu64 ")\n", id);
376 		return -1;
377 	}
378 
379 	scsi_port_destruct(port);
380 
381 	dev->num_ports--;
382 
383 	return 0;
384 }
385 
386 struct spdk_scsi_port *
387 spdk_scsi_dev_find_port_by_id(struct spdk_scsi_dev *dev, uint64_t id)
388 {
389 	int i;
390 
391 	for (i = 0; i < SPDK_SCSI_DEV_MAX_PORTS; i++) {
392 		if (!dev->port[i].is_used) {
393 			continue;
394 		}
395 		if (dev->port[i].id == id) {
396 			return &dev->port[i];
397 		}
398 	}
399 
400 	/* No matching port found. */
401 	return NULL;
402 }
403 
404 void
405 spdk_scsi_dev_free_io_channels(struct spdk_scsi_dev *dev)
406 {
407 	struct spdk_scsi_lun *lun, *tmp_lun;
408 
409 	TAILQ_FOREACH_SAFE(lun, &dev->luns, tailq, tmp_lun) {
410 		scsi_lun_free_io_channel(lun);
411 	}
412 }
413 
414 int
415 spdk_scsi_dev_allocate_io_channels(struct spdk_scsi_dev *dev)
416 {
417 	struct spdk_scsi_lun *lun, *tmp_lun;
418 	int rc;
419 
420 	TAILQ_FOREACH_SAFE(lun, &dev->luns, tailq, tmp_lun) {
421 		rc = scsi_lun_allocate_io_channel(lun);
422 		if (rc < 0) {
423 			spdk_scsi_dev_free_io_channels(dev);
424 			return -1;
425 		}
426 	}
427 
428 	return 0;
429 }
430 
431 const char *
432 spdk_scsi_dev_get_name(const struct spdk_scsi_dev *dev)
433 {
434 	return dev->name;
435 }
436 
437 int
438 spdk_scsi_dev_get_id(const struct spdk_scsi_dev *dev)
439 {
440 	return dev->id;
441 }
442 
443 struct spdk_scsi_lun *
444 spdk_scsi_dev_get_lun(struct spdk_scsi_dev *dev, int lun_id)
445 {
446 	struct spdk_scsi_lun *lun;
447 
448 	TAILQ_FOREACH(lun, &dev->luns, tailq) {
449 		if (lun->id == lun_id) {
450 			if (!spdk_scsi_lun_is_removing(lun)) {
451 				return lun;
452 			} else {
453 				return NULL;
454 			}
455 		}
456 	}
457 
458 	return NULL;
459 }
460 
461 struct spdk_scsi_lun *
462 spdk_scsi_dev_get_first_lun(struct spdk_scsi_dev *dev)
463 {
464 	struct spdk_scsi_lun *lun;
465 
466 	TAILQ_FOREACH(lun, &dev->luns, tailq) {
467 		if (!spdk_scsi_lun_is_removing(lun)) {
468 			return lun;
469 		}
470 	}
471 
472 	return NULL;
473 }
474 
475 struct spdk_scsi_lun *
476 spdk_scsi_dev_get_next_lun(struct spdk_scsi_lun *prev_lun)
477 {
478 	struct spdk_scsi_dev *dev;
479 	struct spdk_scsi_lun *lun;
480 
481 	if (prev_lun == NULL) {
482 		return NULL;
483 	}
484 
485 	dev = prev_lun->dev;
486 
487 	lun = TAILQ_NEXT(prev_lun, tailq);
488 	if (lun == NULL) {
489 		return NULL;
490 	}
491 
492 	TAILQ_FOREACH_FROM(lun, &dev->luns, tailq) {
493 		if (!spdk_scsi_lun_is_removing(lun)) {
494 			break;
495 		}
496 	}
497 
498 	return lun;
499 }
500 
501 bool
502 spdk_scsi_dev_has_pending_tasks(const struct spdk_scsi_dev *dev,
503 				const struct spdk_scsi_port *initiator_port)
504 {
505 	struct spdk_scsi_lun *lun;
506 
507 	TAILQ_FOREACH(lun, &dev->luns, tailq) {
508 		if (scsi_lun_has_pending_tasks(lun, initiator_port) ||
509 		    scsi_lun_has_pending_mgmt_tasks(lun, initiator_port)) {
510 			return true;
511 		}
512 	}
513 
514 	return false;
515 }
516