.examine_disk = vbdev_gpt_examine,
};
-SPDK_BDEV_MODULE_REGISTER(&gpt_if)
+SPDK_BDEV_MODULE_REGISTER(gpt, &gpt_if)
/* Base block device gpt context */
struct gpt_base {
struct spdk_gpt gpt;
struct spdk_bdev_part_base *part_base;
+ SPDK_BDEV_PART_TAILQ parts;
/* This channel is only used for reading the partition table. */
struct spdk_io_channel *ch;
struct spdk_bdev_io_wait_entry bdev_io_wait;
};
-static SPDK_BDEV_PART_TAILQ g_gpt_disks = TAILQ_HEAD_INITIALIZER(g_gpt_disks);
-
static bool g_gpt_disabled;
static void
{
struct gpt_base *gpt_base = ctx;
- spdk_dma_free(gpt_base->gpt.buf);
+ spdk_free(gpt_base->gpt.buf);
free(gpt_base);
}
static void
-spdk_gpt_base_bdev_hotremove_cb(void *_base_bdev)
+spdk_gpt_base_bdev_hotremove_cb(void *_part_base)
{
- spdk_bdev_part_base_hotremove(_base_bdev, &g_gpt_disks);
+ struct spdk_bdev_part_base *part_base = _part_base;
+ struct gpt_base *gpt_base = spdk_bdev_part_base_get_ctx(part_base);
+
+ spdk_bdev_part_base_hotremove(part_base, &gpt_base->parts);
}
static int vbdev_gpt_destruct(void *ctx);
return NULL;
}
+ TAILQ_INIT(&gpt_base->parts);
gpt_base->part_base = spdk_bdev_part_base_construct(bdev,
spdk_gpt_base_bdev_hotremove_cb,
&gpt_if, &vbdev_gpt_fn_table,
- &g_gpt_disks, spdk_gpt_base_free, gpt_base,
+ &gpt_base->parts, spdk_gpt_base_free, gpt_base,
sizeof(struct gpt_channel), NULL, NULL);
if (!gpt_base->part_base) {
free(gpt_base);
}
gpt = &gpt_base->gpt;
+ gpt->parse_phase = SPDK_GPT_PARSE_PHASE_PRIMARY;
gpt->buf_size = spdk_max(SPDK_GPT_BUFFER_SIZE, bdev->blocklen);
- gpt->buf = spdk_dma_zmalloc(gpt->buf_size, spdk_bdev_get_buf_align(bdev), NULL);
+ gpt->buf = spdk_zmalloc(gpt->buf_size, spdk_bdev_get_buf_align(bdev), NULL,
+ SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
if (!gpt->buf) {
SPDK_ERRLOG("Cannot alloc buf\n");
spdk_bdev_part_base_free(gpt_base->part_base);
struct spdk_gpt_partition_entry *gpt_entry = &gpt->partitions[gpt_disk->partition_index];
uint64_t offset_blocks = spdk_bdev_part_get_offset_blocks(&gpt_disk->part);
- spdk_json_write_name(w, "gpt");
- spdk_json_write_object_begin(w);
+ spdk_json_write_named_object_begin(w, "gpt");
- spdk_json_write_name(w, "base_bdev");
- spdk_json_write_string(w, spdk_bdev_get_name(part_base_bdev));
+ spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(part_base_bdev));
- spdk_json_write_name(w, "offset_blocks");
- spdk_json_write_uint64(w, offset_blocks);
+ spdk_json_write_named_uint64(w, "offset_blocks", offset_blocks);
spdk_json_write_name(w, "partition_type_guid");
write_guid(w, &gpt_entry->part_type_guid);
}
static void
-spdk_gpt_bdev_complete(struct spdk_bdev_io *bdev_io, bool status, void *arg)
+spdk_gpt_read_secondary_table_complete(struct spdk_bdev_io *bdev_io, bool status, void *arg)
{
struct gpt_base *gpt_base = (struct gpt_base *)arg;
struct spdk_bdev *bdev = spdk_bdev_part_base_get_bdev(gpt_base->part_base);
goto end;
}
- rc = spdk_gpt_parse(&gpt_base->gpt);
+ rc = spdk_gpt_parse_partition_table(&gpt_base->gpt);
+ if (rc) {
+ SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT, "Failed to parse secondary partition table\n");
+ goto end;
+ }
+
+ SPDK_WARNLOG("Gpt: bdev=%s primary partition table broken, use the secondary\n",
+ spdk_bdev_get_name(bdev));
+
+ num_partitions = vbdev_gpt_create_bdevs(gpt_base);
+ if (num_partitions < 0) {
+ SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT, "Failed to split dev=%s by gpt table\n",
+ spdk_bdev_get_name(bdev));
+ }
+
+end:
+ spdk_bdev_module_examine_done(&gpt_if);
+ if (num_partitions <= 0) {
+ /* If no gpt_disk instances were created, free the base context */
+ spdk_bdev_part_base_free(gpt_base->part_base);
+ }
+}
+
+static int
+vbdev_gpt_read_secondary_table(struct gpt_base *gpt_base)
+{
+ struct spdk_gpt *gpt;
+ struct spdk_bdev_desc *part_base_desc;
+ uint64_t secondary_offset;
+
+ gpt = &gpt_base->gpt;
+ gpt->parse_phase = SPDK_GPT_PARSE_PHASE_SECONDARY;
+ gpt->header = NULL;
+ gpt->partitions = NULL;
+
+ part_base_desc = spdk_bdev_part_base_get_desc(gpt_base->part_base);
+
+ secondary_offset = gpt->total_sectors * gpt->sector_size - gpt->buf_size;
+ return spdk_bdev_read(part_base_desc, gpt_base->ch, gpt_base->gpt.buf, secondary_offset,
+ gpt_base->gpt.buf_size, spdk_gpt_read_secondary_table_complete,
+ gpt_base);
+}
+
+static void
+spdk_gpt_bdev_complete(struct spdk_bdev_io *bdev_io, bool status, void *arg)
+{
+ struct gpt_base *gpt_base = (struct gpt_base *)arg;
+ struct spdk_bdev *bdev = spdk_bdev_part_base_get_bdev(gpt_base->part_base);
+ int rc, num_partitions = 0;
+
+ spdk_bdev_free_io(bdev_io);
+
+ if (status != SPDK_BDEV_IO_STATUS_SUCCESS) {
+ SPDK_ERRLOG("Gpt: bdev=%s io error status=%d\n",
+ spdk_bdev_get_name(bdev), status);
+ goto end;
+ }
+
+ rc = spdk_gpt_parse_mbr(&gpt_base->gpt);
if (rc) {
- SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT, "Failed to parse gpt\n");
+ SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT, "Failed to parse mbr\n");
goto end;
}
+ rc = spdk_gpt_parse_partition_table(&gpt_base->gpt);
+ if (rc) {
+ SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT, "Failed to parse primary partition table\n");
+ rc = vbdev_gpt_read_secondary_table(gpt_base);
+ if (rc) {
+ SPDK_ERRLOG("Failed to read secondary table\n");
+ goto end;
+ }
+ return;
+ }
+
num_partitions = vbdev_gpt_create_bdevs(gpt_base);
if (num_partitions < 0) {
SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT, "Failed to split dev=%s by gpt table\n",
}
end:
+ spdk_put_io_channel(gpt_base->ch);
+ gpt_base->ch = NULL;
/*
* Notify the generic bdev layer that the actions related to the original examine
* callback are now completed.