opal: add support for getting locking range info

Change-Id: I8e3e39673c260f823a9703e86006b5334dedc987
Signed-off-by: Chunyang Hui <chunyang.hui@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457576
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Chunyang Hui 2019-06-11 22:57:09 +08:00 committed by Changpeng Liu
parent 505dbf59ff
commit fbd2f3fd2e
5 changed files with 388 additions and 20 deletions

View File

@ -50,8 +50,7 @@ Nvme Opal library spdk_opal_cmd deprecated. Adding seperate command APIs.
NVMe Opal library add support for activating locking SP which will make the transaction NVMe Opal library add support for activating locking SP which will make the transaction
from "Manufactured-Inactive" state to "Manufactured" state. Upon successfully invoking from "Manufactured-Inactive" state to "Manufactured" state. Upon successfully invoking
of this method, lock and unlock features will be enabled. of this method, lock and unlock features will be enabled.
NVMe Opal library add support for locking/unlocking range. NVMe Opal library add support for locking/unlocking range and list locking range info.
Added spdk_nvme_ctrlr_io_cmd_raw_no_payload_build() allowing a caller to pass Added spdk_nvme_ctrlr_io_cmd_raw_no_payload_build() allowing a caller to pass
a completely formed command to an NVMe submission queue (buffer addresses and all). a completely formed command to an NVMe submission queue (buffer addresses and all).

View File

@ -939,7 +939,8 @@ opal_usage(void)
printf("\n"); printf("\n");
printf("\t[1: scan device]\n"); printf("\t[1: scan device]\n");
printf("\t[2: init - take ownership and activate locking]\n"); printf("\t[2: init - take ownership and activate locking]\n");
printf("\t[3: lock/unlock the range]\n"); printf("\t[3: setup locking range and enable locking]\n");
printf("\t[4: list locking ranges]\n");
printf("\t[9: revert tper]\n"); printf("\t[9: revert tper]\n");
printf("\t[0: quit]\n"); printf("\t[0: quit]\n");
} }
@ -1021,12 +1022,16 @@ opal_locking_usage(void)
} }
static void static void
opal_lock_range(struct dev *iter) opal_setup_lockingrange(struct dev *iter)
{ {
char passwd[MAX_PASSWORD_SIZE] = {0}; char passwd[MAX_PASSWORD_SIZE] = {0};
char *passwd_p; char *passwd_p;
int ret; int ret;
int ch; int ch;
uint64_t range_start;
uint64_t range_length;
int locking_range_flag;
struct spdk_opal_locking_range_info *info;
int state; int state;
enum spdk_opal_lock_state state_flag; enum spdk_opal_lock_state state_flag;
@ -1036,7 +1041,7 @@ opal_lock_range(struct dev *iter)
return; return;
} }
if (spdk_opal_supported(iter->opal_dev)) { if (spdk_opal_supported(iter->opal_dev)) {
printf("Please input the password for locking the range:\n"); printf("Please input the password for setting up locking range:\n");
while ((ch = getchar()) != '\n' && ch != EOF); while ((ch = getchar()) != '\n' && ch != EOF);
passwd_p = getpass(passwd); passwd_p = getpass(passwd);
if (passwd_p) { if (passwd_p) {
@ -1047,20 +1052,25 @@ opal_lock_range(struct dev *iter)
return; return;
} }
ret = spdk_opal_cmd_setup_locking_range(iter->opal_dev, printf("Specify locking range id:\n");
OPAL_ADMIN1, OPAL_LOCKING_RANGE_GLOBAL, 0, 0, passwd_p); /* just put here for testing */ if (!scanf("%d", &locking_range_flag)) {
if (ret) { printf("Invalid locking range id\n");
printf("Setup locking range failure: %d\n", ret); }
return;
printf("range length:\n");
if (!scanf("%ld", &range_length)) {
printf("Invalid range length\n");
}
printf("range start:\n");
if (!scanf("%ld", &range_start)) {
printf("Invalid range start address\n");
} }
opal_locking_usage(); opal_locking_usage();
ret = scanf("%d", &state); if (!scanf("%d", &state)) {
if (ret != 1) { printf("Invalid option\n");
printf("Invalid input\n");
return;
} }
switch (state) { switch (state) {
case 1: case 1:
state_flag = OPAL_RWLOCK; state_flag = OPAL_RWLOCK;
@ -1076,13 +1086,36 @@ opal_lock_range(struct dev *iter)
return; return;
} }
ret = spdk_opal_cmd_lock_unlock(iter->opal_dev, OPAL_ADMIN1, state_flag, ret = spdk_opal_cmd_setup_locking_range(iter->opal_dev,
OPAL_LOCKING_RANGE_GLOBAL, passwd_p); OPAL_ADMIN1, locking_range_flag, range_start, range_length, passwd_p);
if (ret) { if (ret) {
printf("lock range failure: %d\n", ret); printf("Setup locking range failure: %d\n", ret);
return; return;
} }
ret = spdk_opal_cmd_lock_unlock(iter->opal_dev, OPAL_ADMIN1, state_flag,
locking_range_flag, passwd_p);
if (ret) {
printf("Unlock range failure: %d\n", ret);
return;
}
ret = spdk_opal_cmd_get_locking_range_info(iter->opal_dev,
passwd_p, locking_range_flag);
if (ret) {
printf("Get locking range info failure: %d\n", ret);
return;
}
info = spdk_opal_get_locking_range_info(iter->opal_dev, locking_range_flag);
printf("locking range ID: %d\n", info->locking_range_id);
printf("range start: %ld\n", info->range_start);
printf("range length: %ld\n", info->range_length);
printf("read lock enabled: %d\n", info->read_lock_enabled);
printf("write lock enabled: %d\n", info->write_lock_enabled);
printf("read locked: %d\n", info->read_locked);
printf("write locked: %d\n", info->write_locked);
printf("...\n...\nOpal setup locking range success\n"); printf("...\n...\nOpal setup locking range success\n");
} else { } else {
printf("Input password invalid. Opal setup locking range failure\n"); printf("Input password invalid. Opal setup locking range failure\n");
@ -1095,6 +1128,69 @@ opal_lock_range(struct dev *iter)
} }
} }
static void
opal_list_locking_ranges(struct dev *iter)
{
char passwd[MAX_PASSWORD_SIZE] = {0};
char *passwd_p;
int ret;
int ch;
int max_ranges;
int i;
struct spdk_opal_locking_range_info *info;
if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
iter->opal_dev = spdk_opal_init_dev(iter->ctrlr);
if (iter->opal_dev == NULL) {
return;
}
if (spdk_opal_supported(iter->opal_dev)) {
printf("Please input password:\n");
while ((ch = getchar()) != '\n' && ch != EOF);
passwd_p = getpass(passwd);
if (passwd_p) {
ret = spdk_opal_cmd_get_max_ranges(iter->opal_dev, passwd_p);
if (ret) {
printf("get max ranges failure: %d\n", ret);
return;
}
max_ranges = spdk_opal_get_max_locking_ranges(iter->opal_dev);
for (i = 0; i < max_ranges; i++) {
ret = spdk_opal_cmd_get_locking_range_info(iter->opal_dev,
passwd_p, i);
if (ret) {
printf("Get locking range info failure: %d\n", ret);
return;
}
info = spdk_opal_get_locking_range_info(iter->opal_dev, i);
if (info == NULL) {
continue;
}
printf("===============================================\n");
printf("locking range ID: %d\t", info->locking_range_id);
if (i == 0) { printf("(Global Range)"); }
printf("\n===============================================\n");
printf("range start: %ld\t", info->range_start);
printf("range length: %ld\n", info->range_length);
printf("read lock enabled: %d\t", info->read_lock_enabled);
printf("write lock enabled: %d\t", info->write_lock_enabled);
printf("read locked: %d\t", info->read_locked);
printf("write locked: %d\n", info->write_locked);
printf("\n");
}
} else {
printf("Input password invalid. List locking ranges failure\n");
}
}
spdk_opal_close(iter->opal_dev);
} else {
printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n",
iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
}
}
static void static void
opal_revert_tper(struct dev *iter) opal_revert_tper(struct dev *iter)
{ {
@ -1165,7 +1261,10 @@ test_opal(void)
opal_init(ctrlr); /* Take ownership, Activate Locking SP */ opal_init(ctrlr); /* Take ownership, Activate Locking SP */
break; break;
case 3: case 3:
opal_lock_range(ctrlr); opal_setup_lockingrange(ctrlr);
break;
case 4:
opal_list_locking_ranges(ctrlr);
break; break;
case 9: case 9:
opal_revert_tper(ctrlr); opal_revert_tper(ctrlr);

View File

@ -151,6 +151,17 @@ enum spdk_opal_locking_range {
OPAL_LOCKING_RANGE_10, OPAL_LOCKING_RANGE_10,
}; };
struct spdk_opal_locking_range_info {
uint8_t locking_range_id;
uint8_t _padding[7];
uint64_t range_start;
uint64_t range_length;
bool read_lock_enabled;
bool write_lock_enabled;
bool read_locked;
bool write_locked;
};
struct spdk_opal_dev; struct spdk_opal_dev;
struct spdk_opal_dev *spdk_opal_init_dev(void *dev_handler); struct spdk_opal_dev *spdk_opal_init_dev(void *dev_handler);
@ -171,4 +182,11 @@ int spdk_opal_cmd_setup_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_
enum spdk_opal_locking_range locking_range_id, uint64_t range_start, enum spdk_opal_locking_range locking_range_id, uint64_t range_start,
uint64_t range_length, const char *passwd); uint64_t range_length, const char *passwd);
int spdk_opal_cmd_get_max_ranges(struct spdk_opal_dev *dev, const char *passwd);
int spdk_opal_cmd_get_locking_range_info(struct spdk_opal_dev *dev, const char *passwd,
enum spdk_opal_locking_range locking_range_id);
struct spdk_opal_locking_range_info *spdk_opal_get_locking_range_info(struct spdk_opal_dev *dev,
enum spdk_opal_locking_range id);
uint8_t spdk_opal_get_max_locking_ranges(struct spdk_opal_dev *dev);
#endif #endif

View File

@ -287,7 +287,7 @@ opal_finalize_and_send(struct spdk_opal_dev *dev, bool eod, spdk_opal_cb cb, voi
return ret; return ret;
} }
return opal_send_recv(dev, cb, NULL); return opal_send_recv(dev, cb, data);
} }
static size_t static size_t
@ -523,6 +523,28 @@ opal_response_get_u64(const struct spdk_opal_resp_parsed *resp, int index)
return resp->resp_tokens[index].stored.unsigned_num; return resp->resp_tokens[index].stored.unsigned_num;
} }
static uint16_t
opal_response_get_u16(const struct spdk_opal_resp_parsed *resp, int index)
{
uint64_t i = opal_response_get_u64(resp, index);
if (i > 0xffffull) {
SPDK_ERRLOG("parse reponse u16 failed. Overflow\n");
return 0;
}
return (uint16_t) i;
}
static uint8_t
opal_response_get_u8(const struct spdk_opal_resp_parsed *resp, int index)
{
uint64_t i = opal_response_get_u64(resp, index);
if (i > 0xffull) {
SPDK_ERRLOG("parse reponse u8 failed. Overflow\n");
return 0;
}
return (uint8_t) i;
}
static size_t static size_t
opal_response_get_string(const struct spdk_opal_resp_parsed *resp, int n, opal_response_get_string(const struct spdk_opal_resp_parsed *resp, int n,
const char **store) const char **store)
@ -1457,6 +1479,133 @@ opal_setup_locking_range(struct spdk_opal_dev *dev,
return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL); return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
} }
static int
opal_get_max_ranges_cb(struct spdk_opal_dev *dev, void *data)
{
uint8_t max_ranges;
int error = 0;
error = opal_parse_and_check_status(dev, NULL);
if (error) {
return error;
}
max_ranges = opal_response_get_u16(&dev->parsed_resp, 4); /* "MaxRanges" is token 4 of response */
dev->max_ranges = max_ranges;
return 0;
}
static int
opal_get_max_ranges(struct spdk_opal_dev *dev)
{
int err = 0;
opal_clear_cmd(dev);
opal_set_comid(dev, dev->comid);
opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_LOCKING_INFO_TABLE],
OPAL_UID_LENGTH);
opal_add_token_bytestring(&err, dev, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
opal_add_tokens(&err, dev, 12, SPDK_OPAL_STARTLIST,
SPDK_OPAL_STARTLIST,
SPDK_OPAL_STARTNAME,
SPDK_OPAL_STARTCOLUMN,
SPDK_OPAL_MAXRANGES,
SPDK_OPAL_ENDNAME,
SPDK_OPAL_STARTNAME,
SPDK_OPAL_ENDCOLUMN,
SPDK_OPAL_MAXRANGES,
SPDK_OPAL_ENDNAME,
SPDK_OPAL_ENDLIST,
SPDK_OPAL_ENDLIST);
if (err) {
SPDK_ERRLOG("Error Building GET Lifecycle Status command\n");
return err;
}
return opal_finalize_and_send(dev, 1, opal_get_max_ranges_cb, NULL);
}
static int
opal_get_locking_range_info_cb(struct spdk_opal_dev *dev, void *data)
{
int error = 0;
uint8_t id = *(uint8_t *)data;
error = opal_parse_and_check_status(dev, NULL);
if (error) {
return error;
}
if (id > dev->max_ranges) {
SPDK_ERRLOG("Locking range ID not valid\n");
return -EINVAL;
}
dev->locking_range_info[id]->range_start = opal_response_get_u64(&dev->parsed_resp, 4);
dev->locking_range_info[id]->range_length = opal_response_get_u64(&dev->parsed_resp, 8);
dev->locking_range_info[id]->read_lock_enabled = opal_response_get_u8(&dev->parsed_resp, 12);
dev->locking_range_info[id]->write_lock_enabled = opal_response_get_u8(&dev->parsed_resp, 16);
dev->locking_range_info[id]->read_locked = opal_response_get_u8(&dev->parsed_resp, 20);
dev->locking_range_info[id]->write_locked = opal_response_get_u8(&dev->parsed_resp, 24);
return 0;
}
static int
opal_get_locking_range_info(struct spdk_opal_dev *dev,
enum spdk_opal_locking_range locking_range_id)
{
int err = 0;
uint8_t uid_locking_range[OPAL_UID_LENGTH];
struct spdk_opal_locking_range_info *info;
err = opal_build_locking_range(uid_locking_range, OPAL_UID_LENGTH, locking_range_id);
if (err) {
return err;
}
info = calloc(1, sizeof(struct spdk_opal_locking_range_info));
if (info == NULL) {
SPDK_ERRLOG("Memory allocation failed for spdk_opal_locking_range_info\n");
return -ENOMEM;
}
info->locking_range_id = locking_range_id;
dev->locking_range_info[locking_range_id] = info;
opal_clear_cmd(dev);
opal_set_comid(dev, dev->comid);
opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
opal_add_token_bytestring(&err, dev, uid_locking_range, OPAL_UID_LENGTH);
opal_add_token_bytestring(&err, dev, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
opal_add_tokens(&err, dev, 12, SPDK_OPAL_STARTLIST,
SPDK_OPAL_STARTLIST,
SPDK_OPAL_STARTNAME,
SPDK_OPAL_STARTCOLUMN,
SPDK_OPAL_RANGESTART,
SPDK_OPAL_ENDNAME,
SPDK_OPAL_STARTNAME,
SPDK_OPAL_ENDCOLUMN,
SPDK_OPAL_WRITELOCKED,
SPDK_OPAL_ENDNAME,
SPDK_OPAL_ENDLIST,
SPDK_OPAL_ENDLIST);
if (err) {
SPDK_ERRLOG("Error Building get locking range info command\n");
return err;
}
return opal_finalize_and_send(dev, 1, opal_get_locking_range_info_cb, &locking_range_id);
}
static int static int
opal_set_sid_cpin_pin(struct spdk_opal_dev *dev, void *data) opal_set_sid_cpin_pin(struct spdk_opal_dev *dev, void *data)
{ {
@ -1799,6 +1948,95 @@ end:
return ret; return ret;
} }
int
spdk_opal_cmd_get_max_ranges(struct spdk_opal_dev *dev, const char *passwd)
{
struct spdk_opal_key opal_key;
struct opal_common_session session;
int ret;
if (!dev || dev->supported == false) {
return -ENODEV;
}
ret = opal_init_key(&opal_key, passwd, OPAL_LOCKING_RANGE_GLOBAL);
if (ret != 0) {
return ret;
}
memset(&session, 0, sizeof(struct opal_common_session));
session.opal_key = &opal_key;
session.who = OPAL_ADMIN1;
pthread_mutex_lock(&dev->mutex_lock);
ret = opal_start_auth_session(dev, &session);
if (ret) {
SPDK_ERRLOG("start authenticate session error %d: %s\n", ret, opal_error_to_human(ret));
pthread_mutex_unlock(&dev->mutex_lock);
return ret;
}
ret = opal_get_max_ranges(dev);
if (ret) {
SPDK_ERRLOG("get max ranges error %d: %s\n", ret, opal_error_to_human(ret));
goto end;
}
end:
ret += opal_end_session(dev);
if (ret) {
SPDK_ERRLOG("end session error %d: %s\n", ret, opal_error_to_human(ret));
}
pthread_mutex_unlock(&dev->mutex_lock);
return ret;
}
int
spdk_opal_cmd_get_locking_range_info(struct spdk_opal_dev *dev, const char *passwd,
enum spdk_opal_locking_range locking_range_id)
{
struct spdk_opal_key opal_key;
struct opal_common_session session;
int ret;
if (!dev || dev->supported == false) {
return -ENODEV;
}
ret = opal_init_key(&opal_key, passwd, OPAL_LOCKING_RANGE_GLOBAL);
if (ret != 0) {
return ret;
}
memset(&session, 0, sizeof(struct opal_common_session));
session.opal_key = &opal_key;
session.who = OPAL_ADMIN1;
pthread_mutex_lock(&dev->mutex_lock);
ret = opal_start_auth_session(dev, &session);
if (ret) {
SPDK_ERRLOG("start authenticate session error %d: %s\n", ret, opal_error_to_human(ret));
pthread_mutex_unlock(&dev->mutex_lock);
return ret;
}
ret = opal_get_locking_range_info(dev, locking_range_id);
if (ret) {
SPDK_ERRLOG("get locking range info error %d: %s\n", ret, opal_error_to_human(ret));
goto end;
}
end:
ret += opal_end_session(dev);
if (ret) {
SPDK_ERRLOG("end session error %d: %s\n", ret, opal_error_to_human(ret));
}
pthread_mutex_unlock(&dev->mutex_lock);
return ret;
}
struct spdk_opal_info * struct spdk_opal_info *
spdk_opal_get_info(struct spdk_opal_dev *dev) spdk_opal_get_info(struct spdk_opal_dev *dev)
{ {
@ -1811,5 +2049,17 @@ spdk_opal_supported(struct spdk_opal_dev *dev)
return dev->supported; return dev->supported;
} }
struct spdk_opal_locking_range_info *
spdk_opal_get_locking_range_info(struct spdk_opal_dev *dev, enum spdk_opal_locking_range id)
{
return dev->locking_range_info[id];
}
uint8_t
spdk_opal_get_max_locking_ranges(struct spdk_opal_dev *dev)
{
return dev->max_ranges;
}
/* Log component for opal submodule */ /* Log component for opal submodule */
SPDK_LOG_REGISTER_COMPONENT("opal", SPDK_LOG_OPAL) SPDK_LOG_REGISTER_COMPONENT("opal", SPDK_LOG_OPAL)

View File

@ -299,6 +299,8 @@ struct spdk_opal_dev {
struct spdk_opal_info *opal_info; struct spdk_opal_info *opal_info;
uint64_t timeout; /* seconds */ uint64_t timeout; /* seconds */
uint8_t max_ranges; /* max locking range number */
struct spdk_opal_locking_range_info *locking_range_info[OPAL_MAX_LRS];
pthread_mutex_t mutex_lock; /* some structs are accessed by current thread only */ pthread_mutex_t mutex_lock; /* some structs are accessed by current thread only */
}; };