nvmf: restore the loaded reservation information to NS
Load reservation information based on ptpl configuration file, and restore the information to NS data structure. Change-Id: I5f46d49a6d1e6e49aab93ca7cd654469a3a08659 Signed-off-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455912 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
parent
ced3e20709
commit
1edc5f0040
@ -43,6 +43,7 @@
|
||||
#include "spdk/nvmf_spec.h"
|
||||
#include "spdk/uuid.h"
|
||||
#include "spdk/json.h"
|
||||
#include "spdk/file.h"
|
||||
|
||||
#include "spdk/bdev_module.h"
|
||||
#include "spdk_internal/log.h"
|
||||
@ -1005,6 +1006,11 @@ static struct spdk_bdev_module ns_bdev_module = {
|
||||
.name = "NVMe-oF Target",
|
||||
};
|
||||
|
||||
static int
|
||||
spdk_nvmf_ns_load_reservation(const char *file, struct spdk_nvmf_reservation_info *info);
|
||||
static int
|
||||
nvmf_ns_reservation_restore(struct spdk_nvmf_ns *ns, struct spdk_nvmf_reservation_info *info);
|
||||
|
||||
uint32_t
|
||||
spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bdev *bdev,
|
||||
const struct spdk_nvmf_ns_opts *user_opts, size_t opts_size,
|
||||
@ -1012,6 +1018,7 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
|
||||
{
|
||||
struct spdk_nvmf_ns_opts opts;
|
||||
struct spdk_nvmf_ns *ns;
|
||||
struct spdk_nvmf_reservation_info info = {0};
|
||||
int rc;
|
||||
|
||||
if (!(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE ||
|
||||
@ -1111,6 +1118,17 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
|
||||
TAILQ_INIT(&ns->registrants);
|
||||
|
||||
if (ptpl_file) {
|
||||
rc = spdk_nvmf_ns_load_reservation(ptpl_file, &info);
|
||||
if (!rc) {
|
||||
rc = nvmf_ns_reservation_restore(ns, &info);
|
||||
if (rc) {
|
||||
SPDK_ERRLOG("Subsystem restore reservation failed\n");
|
||||
subsystem->ns[opts.nsid - 1] = NULL;
|
||||
spdk_bdev_close(ns->desc);
|
||||
free(ns);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ns->ptpl_file = strdup(ptpl_file);
|
||||
}
|
||||
|
||||
@ -1336,6 +1354,195 @@ spdk_nvmf_subsystem_get_max_namespaces(const struct spdk_nvmf_subsystem *subsyst
|
||||
return subsystem->max_allowed_nsid;
|
||||
}
|
||||
|
||||
struct _nvmf_ns_registrant {
|
||||
uint64_t rkey;
|
||||
char *host_uuid;
|
||||
};
|
||||
|
||||
struct _nvmf_ns_registrants {
|
||||
size_t num_regs;
|
||||
struct _nvmf_ns_registrant reg[SPDK_NVMF_MAX_NUM_REGISTRANTS];
|
||||
};
|
||||
|
||||
struct _nvmf_ns_reservation {
|
||||
bool ptpl_activated;
|
||||
enum spdk_nvme_reservation_type rtype;
|
||||
uint64_t crkey;
|
||||
char *bdev_uuid;
|
||||
char *holder_uuid;
|
||||
struct _nvmf_ns_registrants regs;
|
||||
};
|
||||
|
||||
static const struct spdk_json_object_decoder nvmf_ns_pr_reg_decoders[] = {
|
||||
{"rkey", offsetof(struct _nvmf_ns_registrant, rkey), spdk_json_decode_uint64},
|
||||
{"host_uuid", offsetof(struct _nvmf_ns_registrant, host_uuid), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static int
|
||||
nvmf_decode_ns_pr_reg(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct _nvmf_ns_registrant *reg = out;
|
||||
|
||||
return spdk_json_decode_object(val, nvmf_ns_pr_reg_decoders,
|
||||
SPDK_COUNTOF(nvmf_ns_pr_reg_decoders), reg);
|
||||
}
|
||||
|
||||
static int
|
||||
nvmf_decode_ns_pr_regs(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
struct _nvmf_ns_registrants *regs = out;
|
||||
|
||||
return spdk_json_decode_array(val, nvmf_decode_ns_pr_reg, regs->reg,
|
||||
SPDK_NVMF_MAX_NUM_REGISTRANTS, ®s->num_regs,
|
||||
sizeof(struct _nvmf_ns_registrant));
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder nvmf_ns_pr_decoders[] = {
|
||||
{"ptpl", offsetof(struct _nvmf_ns_reservation, ptpl_activated), spdk_json_decode_bool, true},
|
||||
{"rtype", offsetof(struct _nvmf_ns_reservation, rtype), spdk_json_decode_uint32, true},
|
||||
{"crkey", offsetof(struct _nvmf_ns_reservation, crkey), spdk_json_decode_uint64, true},
|
||||
{"bdev_uuid", offsetof(struct _nvmf_ns_reservation, bdev_uuid), spdk_json_decode_string},
|
||||
{"holder_uuid", offsetof(struct _nvmf_ns_reservation, holder_uuid), spdk_json_decode_string, true},
|
||||
{"registrants", offsetof(struct _nvmf_ns_reservation, regs), nvmf_decode_ns_pr_regs},
|
||||
};
|
||||
|
||||
static int
|
||||
spdk_nvmf_ns_load_reservation(const char *file, struct spdk_nvmf_reservation_info *info)
|
||||
{
|
||||
FILE *fd;
|
||||
size_t json_size;
|
||||
ssize_t values_cnt, rc;
|
||||
void *json = NULL, *end;
|
||||
struct spdk_json_val *values = NULL;
|
||||
struct _nvmf_ns_reservation res = {};
|
||||
uint32_t i;
|
||||
|
||||
fd = fopen(file, "r");
|
||||
/* It's not an error if the file does not exist */
|
||||
if (!fd) {
|
||||
SPDK_NOTICELOG("File %s does not exist\n", file);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Load all persist file contents into a local buffer */
|
||||
json = spdk_posix_file_load(fd, &json_size);
|
||||
fclose(fd);
|
||||
if (!json) {
|
||||
SPDK_ERRLOG("Load persit file %s failed\n", file);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc = spdk_json_parse(json, json_size, NULL, 0, &end, 0);
|
||||
if (rc < 0) {
|
||||
SPDK_NOTICELOG("Parsing JSON configuration failed (%zd)\n", rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
values_cnt = rc;
|
||||
values = calloc(values_cnt, sizeof(struct spdk_json_val));
|
||||
if (values == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = spdk_json_parse(json, json_size, values, values_cnt, &end, 0);
|
||||
if (rc != values_cnt) {
|
||||
SPDK_ERRLOG("Parsing JSON configuration failed (%zd)\n", rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Decode json */
|
||||
if (spdk_json_decode_object(values, nvmf_ns_pr_decoders,
|
||||
SPDK_COUNTOF(nvmf_ns_pr_decoders),
|
||||
&res)) {
|
||||
SPDK_ERRLOG("Invalid objects in the persist file %s\n", file);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
info->ptpl_activated = res.ptpl_activated;
|
||||
info->rtype = res.rtype;
|
||||
info->crkey = res.crkey;
|
||||
snprintf(info->bdev_uuid, sizeof(info->bdev_uuid), "%s", res.bdev_uuid);
|
||||
snprintf(info->holder_uuid, sizeof(info->holder_uuid), "%s", res.holder_uuid);
|
||||
info->num_regs = res.regs.num_regs;
|
||||
for (i = 0; i < res.regs.num_regs; i++) {
|
||||
info->registrants[i].rkey = res.regs.reg[i].rkey;
|
||||
snprintf(info->registrants[i].host_uuid, sizeof(info->registrants[i].host_uuid), "%s",
|
||||
res.regs.reg[i].host_uuid);
|
||||
}
|
||||
|
||||
exit:
|
||||
free(json);
|
||||
free(values);
|
||||
free(res.bdev_uuid);
|
||||
free(res.holder_uuid);
|
||||
for (i = 0; i < res.regs.num_regs; i++) {
|
||||
free(res.regs.reg[i].host_uuid);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool
|
||||
nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns);
|
||||
|
||||
static int
|
||||
nvmf_ns_reservation_restore(struct spdk_nvmf_ns *ns, struct spdk_nvmf_reservation_info *info)
|
||||
{
|
||||
uint32_t i;
|
||||
struct spdk_nvmf_registrant *reg, *holder = NULL;
|
||||
struct spdk_uuid bdev_uuid, holder_uuid;
|
||||
|
||||
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "NSID %u, PTPL %u, Number of registrants %u\n",
|
||||
ns->nsid, info->ptpl_activated, info->num_regs);
|
||||
|
||||
/* it's not an error */
|
||||
if (!info->ptpl_activated || !info->num_regs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
spdk_uuid_parse(&bdev_uuid, info->bdev_uuid);
|
||||
if (spdk_uuid_compare(&bdev_uuid, spdk_bdev_get_uuid(ns->bdev))) {
|
||||
SPDK_ERRLOG("Existing bdev UUID is not same with configuration file\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ns->crkey = info->crkey;
|
||||
ns->rtype = info->rtype;
|
||||
ns->ptpl_activated = info->ptpl_activated;
|
||||
spdk_uuid_parse(&holder_uuid, info->holder_uuid);
|
||||
|
||||
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Bdev UUID %s\n", info->bdev_uuid);
|
||||
if (info->rtype) {
|
||||
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Holder UUID %s, RTYPE %u, RKEY 0x%"PRIx64"\n",
|
||||
info->holder_uuid, info->rtype, info->crkey);
|
||||
}
|
||||
|
||||
for (i = 0; i < info->num_regs; i++) {
|
||||
reg = calloc(1, sizeof(*reg));
|
||||
if (!reg) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
spdk_uuid_parse(®->hostid, info->registrants[i].host_uuid);
|
||||
reg->rkey = info->registrants[i].rkey;
|
||||
TAILQ_INSERT_TAIL(&ns->registrants, reg, link);
|
||||
if (!spdk_uuid_compare(&holder_uuid, ®->hostid)) {
|
||||
holder = reg;
|
||||
}
|
||||
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Registrant RKEY 0x%"PRIx64", Host UUID %s\n",
|
||||
info->registrants[i].rkey, info->registrants[i].host_uuid);
|
||||
}
|
||||
|
||||
if (nvmf_ns_reservation_all_registrants_type(ns)) {
|
||||
ns->holder = TAILQ_FIRST(&ns->registrants);
|
||||
} else {
|
||||
ns->holder = holder;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_nvmf_ns_json_write_cb(void *cb_ctx, const void *data, size_t size)
|
||||
{
|
||||
@ -1392,9 +1599,6 @@ exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool
|
||||
nvmf_ns_reservation_all_registrants_type(struct spdk_nvmf_ns *ns);
|
||||
|
||||
static int
|
||||
nvmf_ns_update_reservation_info(struct spdk_nvmf_ns *ns)
|
||||
{
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..)
|
||||
|
||||
SPDK_LIB_LIST = json
|
||||
TEST_FILE = ctrlr_discovery_ut.c
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk
|
||||
|
Loading…
Reference in New Issue
Block a user