xref: /spdk/module/bdev/gpt/vbdev_gpt.c (revision 9889ab2dc80e40dae92dcef361d53dcba722043d)
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 /*
35  * This driver reads a GPT partition table from a bdev and exposes a virtual block device for
36  * each partition.
37  */
38 
39 #include "gpt.h"
40 
41 #include "spdk/conf.h"
42 #include "spdk/endian.h"
43 #include "spdk/env.h"
44 #include "spdk/thread.h"
45 #include "spdk/rpc.h"
46 #include "spdk/string.h"
47 #include "spdk/util.h"
48 
49 #include "spdk/bdev_module.h"
50 #include "spdk_internal/log.h"
51 
52 static int vbdev_gpt_init(void);
53 static void vbdev_gpt_examine(struct spdk_bdev *bdev);
54 static int vbdev_gpt_get_ctx_size(void);
55 
56 static struct spdk_bdev_module gpt_if = {
57 	.name = "gpt",
58 	.module_init = vbdev_gpt_init,
59 	.get_ctx_size = vbdev_gpt_get_ctx_size,
60 	.examine_disk = vbdev_gpt_examine,
61 
62 };
63 SPDK_BDEV_MODULE_REGISTER(gpt, &gpt_if)
64 
65 /* Base block device gpt context */
66 struct gpt_base {
67 	struct spdk_gpt			gpt;
68 	struct spdk_bdev_part_base	*part_base;
69 	SPDK_BDEV_PART_TAILQ		parts;
70 
71 	/* This channel is only used for reading the partition table. */
72 	struct spdk_io_channel		*ch;
73 };
74 
75 /* Context for each gpt virtual bdev */
76 struct gpt_disk {
77 	struct spdk_bdev_part	part;
78 	uint32_t		partition_index;
79 };
80 
81 struct gpt_channel {
82 	struct spdk_bdev_part_channel	part_ch;
83 };
84 
85 struct gpt_io {
86 	struct spdk_io_channel *ch;
87 	struct spdk_bdev_io *bdev_io;
88 
89 	/* for bdev_io_wait */
90 	struct spdk_bdev_io_wait_entry bdev_io_wait;
91 };
92 
93 static bool g_gpt_disabled;
94 
95 static void
96 spdk_gpt_base_free(void *ctx)
97 {
98 	struct gpt_base *gpt_base = ctx;
99 
100 	spdk_free(gpt_base->gpt.buf);
101 	free(gpt_base);
102 }
103 
104 static void
105 spdk_gpt_base_bdev_hotremove_cb(void *_part_base)
106 {
107 	struct spdk_bdev_part_base *part_base = _part_base;
108 	struct gpt_base *gpt_base = spdk_bdev_part_base_get_ctx(part_base);
109 
110 	spdk_bdev_part_base_hotremove(part_base, &gpt_base->parts);
111 }
112 
113 static int vbdev_gpt_destruct(void *ctx);
114 static void vbdev_gpt_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io);
115 static int vbdev_gpt_dump_info_json(void *ctx, struct spdk_json_write_ctx *w);
116 
117 static struct spdk_bdev_fn_table vbdev_gpt_fn_table = {
118 	.destruct		= vbdev_gpt_destruct,
119 	.submit_request		= vbdev_gpt_submit_request,
120 	.dump_info_json		= vbdev_gpt_dump_info_json,
121 };
122 
123 static struct gpt_base *
124 spdk_gpt_base_bdev_init(struct spdk_bdev *bdev)
125 {
126 	struct gpt_base *gpt_base;
127 	struct spdk_gpt *gpt;
128 
129 	gpt_base = calloc(1, sizeof(*gpt_base));
130 	if (!gpt_base) {
131 		SPDK_ERRLOG("Cannot alloc memory for gpt_base pointer\n");
132 		return NULL;
133 	}
134 
135 	TAILQ_INIT(&gpt_base->parts);
136 	gpt_base->part_base = spdk_bdev_part_base_construct(bdev,
137 			      spdk_gpt_base_bdev_hotremove_cb,
138 			      &gpt_if, &vbdev_gpt_fn_table,
139 			      &gpt_base->parts, spdk_gpt_base_free, gpt_base,
140 			      sizeof(struct gpt_channel), NULL, NULL);
141 	if (!gpt_base->part_base) {
142 		free(gpt_base);
143 		SPDK_ERRLOG("cannot construct gpt_base");
144 		return NULL;
145 	}
146 
147 	gpt = &gpt_base->gpt;
148 	gpt->parse_phase = SPDK_GPT_PARSE_PHASE_PRIMARY;
149 	gpt->buf_size = spdk_max(SPDK_GPT_BUFFER_SIZE, bdev->blocklen);
150 	gpt->buf = spdk_zmalloc(gpt->buf_size, spdk_bdev_get_buf_align(bdev), NULL,
151 				SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
152 	if (!gpt->buf) {
153 		SPDK_ERRLOG("Cannot alloc buf\n");
154 		spdk_bdev_part_base_free(gpt_base->part_base);
155 		return NULL;
156 	}
157 
158 	gpt->sector_size = bdev->blocklen;
159 	gpt->total_sectors = bdev->blockcnt;
160 	gpt->lba_start = 0;
161 	gpt->lba_end = gpt->total_sectors - 1;
162 
163 	return gpt_base;
164 }
165 
166 static int
167 vbdev_gpt_destruct(void *ctx)
168 {
169 	struct gpt_disk *gpt_disk = ctx;
170 
171 	return spdk_bdev_part_free(&gpt_disk->part);
172 }
173 
174 static void
175 _vbdev_gpt_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io);
176 
177 static void
178 vbdev_gpt_resubmit_request(void *arg)
179 {
180 	struct gpt_io *io = (struct gpt_io *)arg;
181 
182 	_vbdev_gpt_submit_request(io->ch, io->bdev_io);
183 }
184 
185 static void
186 vbdev_gpt_queue_io(struct gpt_io *io)
187 {
188 	int rc;
189 
190 	io->bdev_io_wait.bdev = io->bdev_io->bdev;
191 	io->bdev_io_wait.cb_fn = vbdev_gpt_resubmit_request;
192 	io->bdev_io_wait.cb_arg = io;
193 
194 	rc = spdk_bdev_queue_io_wait(io->bdev_io->bdev,
195 				     io->ch, &io->bdev_io_wait);
196 	if (rc != 0) {
197 		SPDK_ERRLOG("Queue io failed in vbdev_gpt_queue_io, rc=%d.\n", rc);
198 		spdk_bdev_io_complete(io->bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
199 	}
200 }
201 
202 static void
203 vbdev_gpt_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io, bool success)
204 {
205 	if (!success) {
206 		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
207 		return;
208 	}
209 
210 	_vbdev_gpt_submit_request(ch, bdev_io);
211 }
212 
213 static void
214 _vbdev_gpt_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
215 {
216 	struct gpt_channel *ch = spdk_io_channel_get_ctx(_ch);
217 	struct gpt_io *io = (struct gpt_io *)bdev_io->driver_ctx;
218 	int rc;
219 
220 	rc = spdk_bdev_part_submit_request(&ch->part_ch, bdev_io);
221 	if (rc) {
222 		if (rc == -ENOMEM) {
223 			SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT, "gpt: no memory, queue io\n");
224 			io->ch = _ch;
225 			io->bdev_io = bdev_io;
226 			vbdev_gpt_queue_io(io);
227 		} else {
228 			SPDK_ERRLOG("gpt: error on bdev_io submission, rc=%d.\n", rc);
229 			spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
230 		}
231 	}
232 }
233 
234 static void
235 vbdev_gpt_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
236 {
237 	switch (bdev_io->type) {
238 	case SPDK_BDEV_IO_TYPE_READ:
239 		spdk_bdev_io_get_buf(bdev_io, vbdev_gpt_get_buf_cb,
240 				     bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
241 		break;
242 	default:
243 		_vbdev_gpt_submit_request(_ch, bdev_io);
244 		break;
245 	}
246 }
247 
248 static void
249 write_guid(struct spdk_json_write_ctx *w, const struct spdk_gpt_guid *guid)
250 {
251 	spdk_json_write_string_fmt(w, "%08x-%04x-%04x-%04x-%04x%08x",
252 				   from_le32(&guid->raw[0]),
253 				   from_le16(&guid->raw[4]),
254 				   from_le16(&guid->raw[6]),
255 				   from_be16(&guid->raw[8]),
256 				   from_be16(&guid->raw[10]),
257 				   from_be32(&guid->raw[12]));
258 }
259 
260 static void
261 write_string_utf16le(struct spdk_json_write_ctx *w, const uint16_t *str, size_t max_len)
262 {
263 	size_t len;
264 	const uint16_t *p;
265 
266 	for (len = 0, p = str; len < max_len && *p; p++) {
267 		len++;
268 	}
269 
270 	spdk_json_write_string_utf16le_raw(w, str, len);
271 }
272 
273 static int
274 vbdev_gpt_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
275 {
276 	struct gpt_disk *gpt_disk = SPDK_CONTAINEROF(ctx, struct gpt_disk, part);
277 	struct spdk_bdev_part_base *base_bdev = spdk_bdev_part_get_base(&gpt_disk->part);
278 	struct gpt_base *gpt_base = spdk_bdev_part_base_get_ctx(base_bdev);
279 	struct spdk_bdev *part_base_bdev = spdk_bdev_part_base_get_bdev(base_bdev);
280 	struct spdk_gpt *gpt = &gpt_base->gpt;
281 	struct spdk_gpt_partition_entry *gpt_entry = &gpt->partitions[gpt_disk->partition_index];
282 	uint64_t offset_blocks = spdk_bdev_part_get_offset_blocks(&gpt_disk->part);
283 
284 	spdk_json_write_named_object_begin(w, "gpt");
285 
286 	spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(part_base_bdev));
287 
288 	spdk_json_write_named_uint64(w, "offset_blocks", offset_blocks);
289 
290 	spdk_json_write_name(w, "partition_type_guid");
291 	write_guid(w, &gpt_entry->part_type_guid);
292 
293 	spdk_json_write_name(w, "unique_partition_guid");
294 	write_guid(w, &gpt_entry->unique_partition_guid);
295 
296 	spdk_json_write_name(w, "partition_name");
297 	write_string_utf16le(w, gpt_entry->partition_name, SPDK_COUNTOF(gpt_entry->partition_name));
298 
299 	spdk_json_write_object_end(w);
300 
301 	return 0;
302 }
303 
304 static int
305 vbdev_gpt_create_bdevs(struct gpt_base *gpt_base)
306 {
307 	uint32_t num_partition_entries;
308 	uint64_t i, head_lba_start, head_lba_end;
309 	uint32_t num_partitions;
310 	struct spdk_gpt_partition_entry *p;
311 	struct gpt_disk *d;
312 	struct spdk_gpt *gpt;
313 	char *name;
314 	struct spdk_bdev *base_bdev;
315 	int rc;
316 
317 	gpt = &gpt_base->gpt;
318 	num_partition_entries = from_le32(&gpt->header->num_partition_entries);
319 	head_lba_start = from_le64(&gpt->header->first_usable_lba);
320 	head_lba_end = from_le64(&gpt->header->last_usable_lba);
321 	num_partitions = 0;
322 
323 	for (i = 0; i < num_partition_entries; i++) {
324 		p = &gpt->partitions[i];
325 		uint64_t lba_start = from_le64(&p->starting_lba);
326 		uint64_t lba_end = from_le64(&p->ending_lba);
327 
328 		if (!SPDK_GPT_GUID_EQUAL(&gpt->partitions[i].part_type_guid,
329 					 &SPDK_GPT_PART_TYPE_GUID) ||
330 		    lba_start == 0) {
331 			continue;
332 		}
333 		if (lba_start < head_lba_start || lba_end > head_lba_end) {
334 			continue;
335 		}
336 
337 		d = calloc(1, sizeof(*d));
338 		if (!d) {
339 			SPDK_ERRLOG("Memory allocation failure\n");
340 			return -1;
341 		}
342 
343 		/* index start at 1 instead of 0 to match the existing style */
344 		base_bdev = spdk_bdev_part_base_get_bdev(gpt_base->part_base);
345 		name = spdk_sprintf_alloc("%sp%" PRIu64, spdk_bdev_get_name(base_bdev), i + 1);
346 		if (!name) {
347 			SPDK_ERRLOG("name allocation failure\n");
348 			free(d);
349 			return -1;
350 		}
351 
352 		rc = spdk_bdev_part_construct(&d->part, gpt_base->part_base, name,
353 					      lba_start, lba_end - lba_start, "GPT Disk");
354 		free(name);
355 		if (rc) {
356 			SPDK_ERRLOG("could not construct bdev part\n");
357 			/* spdk_bdev_part_construct will free name on failure */
358 			free(d);
359 			return -1;
360 		}
361 		num_partitions++;
362 		d->partition_index = i;
363 	}
364 
365 	return num_partitions;
366 }
367 
368 static void
369 spdk_gpt_read_secondary_table_complete(struct spdk_bdev_io *bdev_io, bool status, void *arg)
370 {
371 	struct gpt_base *gpt_base = (struct gpt_base *)arg;
372 	struct spdk_bdev *bdev = spdk_bdev_part_base_get_bdev(gpt_base->part_base);
373 	int rc, num_partitions = 0;
374 
375 	spdk_bdev_free_io(bdev_io);
376 	spdk_put_io_channel(gpt_base->ch);
377 	gpt_base->ch = NULL;
378 
379 	if (status != SPDK_BDEV_IO_STATUS_SUCCESS) {
380 		SPDK_ERRLOG("Gpt: bdev=%s io error status=%d\n",
381 			    spdk_bdev_get_name(bdev), status);
382 		goto end;
383 	}
384 
385 	rc = spdk_gpt_parse_partition_table(&gpt_base->gpt);
386 	if (rc) {
387 		SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT, "Failed to parse secondary partition table\n");
388 		goto end;
389 	}
390 
391 	SPDK_WARNLOG("Gpt: bdev=%s primary partition table broken, use the secondary\n",
392 		     spdk_bdev_get_name(bdev));
393 
394 	num_partitions = vbdev_gpt_create_bdevs(gpt_base);
395 	if (num_partitions < 0) {
396 		SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT, "Failed to split dev=%s by gpt table\n",
397 			      spdk_bdev_get_name(bdev));
398 	}
399 
400 end:
401 	spdk_bdev_module_examine_done(&gpt_if);
402 	if (num_partitions <= 0) {
403 		/* If no gpt_disk instances were created, free the base context */
404 		spdk_bdev_part_base_free(gpt_base->part_base);
405 	}
406 }
407 
408 static int
409 vbdev_gpt_read_secondary_table(struct gpt_base *gpt_base)
410 {
411 	struct spdk_gpt *gpt;
412 	struct spdk_bdev_desc *part_base_desc;
413 	uint64_t secondary_offset;
414 
415 	gpt = &gpt_base->gpt;
416 	gpt->parse_phase = SPDK_GPT_PARSE_PHASE_SECONDARY;
417 	gpt->header = NULL;
418 	gpt->partitions = NULL;
419 
420 	part_base_desc = spdk_bdev_part_base_get_desc(gpt_base->part_base);
421 
422 	secondary_offset = gpt->total_sectors * gpt->sector_size - gpt->buf_size;
423 	return spdk_bdev_read(part_base_desc, gpt_base->ch, gpt_base->gpt.buf, secondary_offset,
424 			      gpt_base->gpt.buf_size, spdk_gpt_read_secondary_table_complete,
425 			      gpt_base);
426 }
427 
428 static void
429 spdk_gpt_bdev_complete(struct spdk_bdev_io *bdev_io, bool status, void *arg)
430 {
431 	struct gpt_base *gpt_base = (struct gpt_base *)arg;
432 	struct spdk_bdev *bdev = spdk_bdev_part_base_get_bdev(gpt_base->part_base);
433 	int rc, num_partitions = 0;
434 
435 	spdk_bdev_free_io(bdev_io);
436 
437 	if (status != SPDK_BDEV_IO_STATUS_SUCCESS) {
438 		SPDK_ERRLOG("Gpt: bdev=%s io error status=%d\n",
439 			    spdk_bdev_get_name(bdev), status);
440 		goto end;
441 	}
442 
443 	rc = spdk_gpt_parse_mbr(&gpt_base->gpt);
444 	if (rc) {
445 		SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT, "Failed to parse mbr\n");
446 		goto end;
447 	}
448 
449 	rc = spdk_gpt_parse_partition_table(&gpt_base->gpt);
450 	if (rc) {
451 		SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT, "Failed to parse primary partition table\n");
452 		rc = vbdev_gpt_read_secondary_table(gpt_base);
453 		if (rc) {
454 			SPDK_ERRLOG("Failed to read secondary table\n");
455 			goto end;
456 		}
457 		return;
458 	}
459 
460 	num_partitions = vbdev_gpt_create_bdevs(gpt_base);
461 	if (num_partitions < 0) {
462 		SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT, "Failed to split dev=%s by gpt table\n",
463 			      spdk_bdev_get_name(bdev));
464 	}
465 
466 end:
467 	spdk_put_io_channel(gpt_base->ch);
468 	gpt_base->ch = NULL;
469 	/*
470 	 * Notify the generic bdev layer that the actions related to the original examine
471 	 *  callback are now completed.
472 	 */
473 	spdk_bdev_module_examine_done(&gpt_if);
474 
475 	/*
476 	 * vbdev_gpt_create_bdevs returns the number of bdevs created upon success.
477 	 * We can branch on this value.
478 	 */
479 	if (num_partitions <= 0) {
480 		/* If no gpt_disk instances were created, free the base context */
481 		spdk_bdev_part_base_free(gpt_base->part_base);
482 	}
483 }
484 
485 static int
486 vbdev_gpt_read_gpt(struct spdk_bdev *bdev)
487 {
488 	struct gpt_base *gpt_base;
489 	struct spdk_bdev_desc *part_base_desc;
490 	int rc;
491 
492 	gpt_base = spdk_gpt_base_bdev_init(bdev);
493 	if (!gpt_base) {
494 		SPDK_ERRLOG("Cannot allocated gpt_base\n");
495 		return -1;
496 	}
497 
498 	part_base_desc = spdk_bdev_part_base_get_desc(gpt_base->part_base);
499 	gpt_base->ch = spdk_bdev_get_io_channel(part_base_desc);
500 	if (gpt_base->ch == NULL) {
501 		SPDK_ERRLOG("Failed to get an io_channel.\n");
502 		spdk_bdev_part_base_free(gpt_base->part_base);
503 		return -1;
504 	}
505 
506 	rc = spdk_bdev_read(part_base_desc, gpt_base->ch, gpt_base->gpt.buf, 0,
507 			    gpt_base->gpt.buf_size, spdk_gpt_bdev_complete, gpt_base);
508 	if (rc < 0) {
509 		spdk_put_io_channel(gpt_base->ch);
510 		spdk_bdev_part_base_free(gpt_base->part_base);
511 		SPDK_ERRLOG("Failed to send bdev_io command\n");
512 		return -1;
513 	}
514 
515 	return 0;
516 }
517 
518 static int
519 vbdev_gpt_init(void)
520 {
521 	struct spdk_conf_section *sp = spdk_conf_find_section(NULL, "Gpt");
522 
523 	if (sp && spdk_conf_section_get_boolval(sp, "Disable", false)) {
524 		/* Disable Gpt probe */
525 		g_gpt_disabled = true;
526 	}
527 
528 	return 0;
529 }
530 
531 static int
532 vbdev_gpt_get_ctx_size(void)
533 {
534 	return sizeof(struct gpt_io);
535 }
536 
537 static void
538 vbdev_gpt_examine(struct spdk_bdev *bdev)
539 {
540 	int rc;
541 
542 	/* A bdev with fewer than 2 blocks cannot have a GPT. Block 0 has
543 	 * the MBR and block 1 has the GPT header.
544 	 */
545 	if (g_gpt_disabled || spdk_bdev_get_num_blocks(bdev) < 2) {
546 		spdk_bdev_module_examine_done(&gpt_if);
547 		return;
548 	}
549 
550 	if (spdk_bdev_get_block_size(bdev) % 512 != 0) {
551 		SPDK_ERRLOG("GPT module does not support block size %" PRIu32 " for bdev %s\n",
552 			    spdk_bdev_get_block_size(bdev), spdk_bdev_get_name(bdev));
553 		spdk_bdev_module_examine_done(&gpt_if);
554 		return;
555 	}
556 
557 	rc = vbdev_gpt_read_gpt(bdev);
558 	if (rc) {
559 		spdk_bdev_module_examine_done(&gpt_if);
560 		SPDK_ERRLOG("Failed to read info from bdev %s\n", spdk_bdev_get_name(bdev));
561 	}
562 }
563 
564 SPDK_LOG_REGISTER_COMPONENT("vbdev_gpt", SPDK_LOG_VBDEV_GPT)
565