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