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