bdev/gpt: read secondary partition table if the primary is broken

After passing the check of protective mbr, there is a high probability that
this bdev is in gpt format. If parsing primary table fails, read the secondary
table and try to get partition info from it. When parsing secondary table
successfully, add a warning log to notify users that primary table is broken.

Change-Id: I4f16edcdd57b9cde8d8cc74ec88ba95b97bd6b63
Signed-off-by: lorneli <lorneli@163.com>
Reviewed-on: https://review.gerrithub.io/c/441201
Reviewed-by: GangCao <gang.cao@intel.com>
Reviewed-by: wuzhouhui <wuzhouhui@kingsoft.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
lorneli 2019-01-19 15:05:54 +08:00 committed by Darek Stojaczyk
parent 0744f10860
commit fdb675cad5

View File

@ -340,7 +340,7 @@ vbdev_gpt_create_bdevs(struct gpt_base *gpt_base)
}
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);
@ -356,6 +356,64 @@ spdk_gpt_bdev_complete(struct spdk_bdev_io *bdev_io, bool status, void *arg)
goto end;
}
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 mbr\n");
@ -365,7 +423,12 @@ spdk_gpt_bdev_complete(struct spdk_bdev_io *bdev_io, bool status, void *arg)
rc = spdk_gpt_parse_partition_table(&gpt_base->gpt);
if (rc) {
SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT, "Failed to parse primary partition table\n");
goto end;
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);
@ -375,6 +438,8 @@ spdk_gpt_bdev_complete(struct spdk_bdev_io *bdev_io, bool status, void *arg)
}
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.