Opal: Add locking range support
Change-Id: I4974d4134aed3b63e204b79c9292ce940e32d40c Signed-off-by: Chunyang Hui <chunyang.hui@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455175 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
parent
755b4390f9
commit
505dbf59ff
@ -50,6 +50,8 @@ 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.
|
||||||
|
|
||||||
|
|
||||||
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).
|
||||||
|
@ -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: revert tper]\n");
|
printf("\t[3: lock/unlock the range]\n");
|
||||||
|
printf("\t[9: revert tper]\n");
|
||||||
printf("\t[0: quit]\n");
|
printf("\t[0: quit]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1009,6 +1010,91 @@ opal_init(struct dev *iter)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
opal_locking_usage(void)
|
||||||
|
{
|
||||||
|
printf("Choose Opal locking state:\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("\t[1: read write lock]\n");
|
||||||
|
printf("\t[2: read only]\n");
|
||||||
|
printf("\t[3: read write unlock]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
opal_lock_range(struct dev *iter)
|
||||||
|
{
|
||||||
|
char passwd[MAX_PASSWORD_SIZE] = {0};
|
||||||
|
char *passwd_p;
|
||||||
|
int ret;
|
||||||
|
int ch;
|
||||||
|
int state;
|
||||||
|
enum spdk_opal_lock_state state_flag;
|
||||||
|
|
||||||
|
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 the password for locking the range:\n");
|
||||||
|
while ((ch = getchar()) != '\n' && ch != EOF);
|
||||||
|
passwd_p = getpass(passwd);
|
||||||
|
if (passwd_p) {
|
||||||
|
ret = spdk_opal_cmd_lock_unlock(iter->opal_dev, OPAL_ADMIN1, OPAL_READWRITE,
|
||||||
|
OPAL_LOCKING_RANGE_GLOBAL, passwd_p);
|
||||||
|
if (ret) {
|
||||||
|
printf("Unlock range failure: %d\n", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = spdk_opal_cmd_setup_locking_range(iter->opal_dev,
|
||||||
|
OPAL_ADMIN1, OPAL_LOCKING_RANGE_GLOBAL, 0, 0, passwd_p); /* just put here for testing */
|
||||||
|
if (ret) {
|
||||||
|
printf("Setup locking range failure: %d\n", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
opal_locking_usage();
|
||||||
|
ret = scanf("%d", &state);
|
||||||
|
if (ret != 1) {
|
||||||
|
printf("Invalid input\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case 1:
|
||||||
|
state_flag = OPAL_RWLOCK;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
state_flag = OPAL_READONLY;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
state_flag = OPAL_READWRITE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Invalid options\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = spdk_opal_cmd_lock_unlock(iter->opal_dev, OPAL_ADMIN1, state_flag,
|
||||||
|
OPAL_LOCKING_RANGE_GLOBAL, passwd_p);
|
||||||
|
if (ret) {
|
||||||
|
printf("lock range failure: %d\n", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("...\n...\nOpal setup locking range success\n");
|
||||||
|
} else {
|
||||||
|
printf("Input password invalid. Opal setup locking range 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)
|
||||||
{
|
{
|
||||||
@ -1062,7 +1148,7 @@ test_opal(void)
|
|||||||
while (!exit_flag) {
|
while (!exit_flag) {
|
||||||
int cmd;
|
int cmd;
|
||||||
if (!scanf("%d", &cmd)) {
|
if (!scanf("%d", &cmd)) {
|
||||||
printf("Invalid Command: command must be number 0-2\n");
|
printf("Invalid Command: command must be number 0-9\n");
|
||||||
while (getchar() != '\n');
|
while (getchar() != '\n');
|
||||||
opal_usage();
|
opal_usage();
|
||||||
continue;
|
continue;
|
||||||
@ -1079,6 +1165,9 @@ 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);
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
opal_revert_tper(ctrlr);
|
opal_revert_tper(ctrlr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -119,10 +119,9 @@ struct spdk_opal_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum spdk_opal_lock_state {
|
enum spdk_opal_lock_state {
|
||||||
OPAL_LS_DISALBELOCKING = 0x00,
|
OPAL_READONLY = 0x01,
|
||||||
OPAL_LS_READLOCK_ENABLE = 0x01,
|
OPAL_RWLOCK = 0x02,
|
||||||
OPAL_LS_WRITELOCK_ENABLE = 0x02,
|
OPAL_READWRITE = 0x04,
|
||||||
OPAL_LS_RWLOCK_ENABLE = 0x04,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum spdk_opal_user {
|
enum spdk_opal_user {
|
||||||
@ -165,5 +164,11 @@ int spdk_opal_cmd_scan(struct spdk_opal_dev *dev);
|
|||||||
int spdk_opal_cmd_take_ownership(struct spdk_opal_dev *dev, char *new_passwd);
|
int spdk_opal_cmd_take_ownership(struct spdk_opal_dev *dev, char *new_passwd);
|
||||||
int spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd);
|
int spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd);
|
||||||
int spdk_opal_cmd_activate_locking_sp(struct spdk_opal_dev *dev, const char *passwd);
|
int spdk_opal_cmd_activate_locking_sp(struct spdk_opal_dev *dev, const char *passwd);
|
||||||
|
int spdk_opal_cmd_lock_unlock(struct spdk_opal_dev *dev, enum spdk_opal_user user,
|
||||||
|
enum spdk_opal_lock_state flag, enum spdk_opal_locking_range locking_range,
|
||||||
|
const char *passwd);
|
||||||
|
int spdk_opal_cmd_setup_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user,
|
||||||
|
enum spdk_opal_locking_range locking_range_id, uint64_t range_start,
|
||||||
|
uint64_t range_length, const char *passwd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,8 +37,6 @@
|
|||||||
|
|
||||||
#include "nvme_opal_internal.h"
|
#include "nvme_opal_internal.h"
|
||||||
|
|
||||||
typedef int (spdk_opal_cb)(struct spdk_opal_dev *dev);
|
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
opal_error_to_human(int error)
|
opal_error_to_human(int error)
|
||||||
{
|
{
|
||||||
@ -98,7 +96,7 @@ opal_recv_cmd(struct spdk_opal_dev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
opal_send_recv(struct spdk_opal_dev *dev, spdk_opal_cb *cb)
|
opal_send_recv(struct spdk_opal_dev *dev, spdk_opal_cb *cb, void *data)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -110,7 +108,7 @@ opal_send_recv(struct spdk_opal_dev *dev, spdk_opal_cb *cb)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return cb(dev);
|
return cb(dev, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -279,7 +277,7 @@ opal_cmd_finalize(struct spdk_opal_dev *dev, uint32_t hsn, uint32_t tsn, bool eo
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
opal_finalize_and_send(struct spdk_opal_dev *dev, bool eod, spdk_opal_cb cb)
|
opal_finalize_and_send(struct spdk_opal_dev *dev, bool eod, spdk_opal_cb cb, void *data)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -289,7 +287,7 @@ opal_finalize_and_send(struct spdk_opal_dev *dev, bool eod, spdk_opal_cb cb)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return opal_send_recv(dev, cb);
|
return opal_send_recv(dev, cb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
@ -582,7 +580,7 @@ opal_response_status(const struct spdk_opal_resp_parsed *resp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
opal_parse_and_check_status(struct spdk_opal_dev *dev)
|
opal_parse_and_check_status(struct spdk_opal_dev *dev, void *data)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
@ -638,6 +636,42 @@ opal_init_key(struct spdk_opal_key *opal_key, const char *passwd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_build_locking_user(uint8_t *buffer, size_t length, uint8_t user)
|
||||||
|
{
|
||||||
|
if (length < OPAL_UID_LENGTH) {
|
||||||
|
SPDK_ERRLOG("Can't build locking range user, buffer overflow\n");
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, spdk_opal_uid[UID_USER1], OPAL_UID_LENGTH);
|
||||||
|
|
||||||
|
buffer[7] = user;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_build_locking_range(uint8_t *buffer, size_t length, uint8_t locking_range)
|
||||||
|
{
|
||||||
|
if (length < OPAL_UID_LENGTH) {
|
||||||
|
SPDK_ERRLOG("Can't build locking range. Buffer overflow\n");
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, spdk_opal_uid[UID_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);
|
||||||
|
|
||||||
|
/* global */
|
||||||
|
if (locking_range == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* non-global */
|
||||||
|
buffer[5] = LOCKING_RANGE_NON_GLOBAL;
|
||||||
|
buffer[7] = locking_range;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
opal_check_tper(struct spdk_opal_dev *dev, const void *data)
|
opal_check_tper(struct spdk_opal_dev *dev, const void *data)
|
||||||
{
|
{
|
||||||
@ -856,11 +890,11 @@ opal_setup_dev(struct spdk_opal_dev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
opal_end_session_cb(struct spdk_opal_dev *dev)
|
opal_end_session_cb(struct spdk_opal_dev *dev, void *data)
|
||||||
{
|
{
|
||||||
dev->hsn = 0;
|
dev->hsn = 0;
|
||||||
dev->tsn = 0;
|
dev->tsn = 0;
|
||||||
return opal_parse_and_check_status(dev);
|
return opal_parse_and_check_status(dev, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -876,7 +910,7 @@ opal_end_session(struct spdk_opal_dev *dev)
|
|||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
return opal_finalize_and_send(dev, eod, opal_end_session_cb);
|
return opal_finalize_and_send(dev, eod, opal_end_session_cb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -901,12 +935,12 @@ spdk_opal_close(struct spdk_opal_dev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
opal_start_session_cb(struct spdk_opal_dev *dev)
|
opal_start_session_cb(struct spdk_opal_dev *dev, void *data)
|
||||||
{
|
{
|
||||||
uint32_t hsn, tsn;
|
uint32_t hsn, tsn;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
error = opal_parse_and_check_status(dev);
|
error = opal_parse_and_check_status(dev, NULL);
|
||||||
if (error) {
|
if (error) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -981,7 +1015,7 @@ opal_start_generic_session(struct spdk_opal_dev *dev,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return opal_finalize_and_send(dev, 1, opal_start_session_cb);
|
return opal_finalize_and_send(dev, 1, opal_start_session_cb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -993,13 +1027,13 @@ opal_start_anybody_adminsp_session(struct spdk_opal_dev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
opal_get_msid_cpin_pin_cb(struct spdk_opal_dev *dev)
|
opal_get_msid_cpin_pin_cb(struct spdk_opal_dev *dev, void *data)
|
||||||
{
|
{
|
||||||
const char *msid_pin;
|
const char *msid_pin;
|
||||||
size_t strlen;
|
size_t strlen;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
error = opal_parse_and_check_status(dev);
|
error = opal_parse_and_check_status(dev, NULL);
|
||||||
if (error) {
|
if (error) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -1053,7 +1087,7 @@ opal_get_msid_cpin_pin(struct spdk_opal_dev *dev)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return opal_finalize_and_send(dev, 1, opal_get_msid_cpin_pin_cb);
|
return opal_finalize_and_send(dev, 1, opal_get_msid_cpin_pin_cb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1114,12 +1148,12 @@ opal_generic_pw_cmd(uint8_t *key, size_t key_len, uint8_t *cpin_uid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
opal_get_locking_sp_lifecycle_cb(struct spdk_opal_dev *dev)
|
opal_get_locking_sp_lifecycle_cb(struct spdk_opal_dev *dev, void *data)
|
||||||
{
|
{
|
||||||
uint8_t lifecycle;
|
uint8_t lifecycle;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
error = opal_parse_and_check_status(dev);
|
error = opal_parse_and_check_status(dev, NULL);
|
||||||
if (error) {
|
if (error) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -1164,7 +1198,7 @@ opal_get_locking_sp_lifecycle(struct spdk_opal_dev *dev)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return opal_finalize_and_send(dev, 1, opal_get_locking_sp_lifecycle_cb);
|
return opal_finalize_and_send(dev, 1, opal_get_locking_sp_lifecycle_cb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1190,7 +1224,237 @@ opal_activate(struct spdk_opal_dev *dev)
|
|||||||
|
|
||||||
/* TODO: Single User Mode for activatation */
|
/* TODO: Single User Mode for activatation */
|
||||||
|
|
||||||
return opal_finalize_and_send(dev, 1, opal_parse_and_check_status);
|
return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_start_auth_session(struct spdk_opal_dev *dev, struct opal_common_session *session)
|
||||||
|
{
|
||||||
|
uint8_t uid_user[OPAL_UID_LENGTH];
|
||||||
|
size_t keylen = session->opal_key->key_len;
|
||||||
|
int err = 0;
|
||||||
|
uint8_t *key = session->opal_key->key;
|
||||||
|
uint32_t hsn = GENERIC_HOST_SESSION_NUM;
|
||||||
|
|
||||||
|
opal_clear_cmd(dev);
|
||||||
|
opal_set_comid(dev, dev->comid);
|
||||||
|
|
||||||
|
if (session->who != OPAL_ADMIN1) {
|
||||||
|
err = opal_build_locking_user(uid_user, sizeof(uid_user),
|
||||||
|
session->who);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memcpy(uid_user, spdk_opal_uid[UID_ADMIN1], OPAL_UID_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
|
||||||
|
opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_SMUID],
|
||||||
|
OPAL_UID_LENGTH);
|
||||||
|
opal_add_token_bytestring(&err, dev, spdk_opal_method[STARTSESSION_METHOD],
|
||||||
|
OPAL_UID_LENGTH);
|
||||||
|
|
||||||
|
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
|
||||||
|
opal_add_token_u64(&err, dev, hsn);
|
||||||
|
opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_LOCKINGSP],
|
||||||
|
OPAL_UID_LENGTH);
|
||||||
|
opal_add_tokens(&err, dev, 3, SPDK_OPAL_TRUE, SPDK_OPAL_STARTNAME,
|
||||||
|
0); /* True for a Read-Write session */
|
||||||
|
opal_add_token_bytestring(&err, dev, key, keylen);
|
||||||
|
opal_add_tokens(&err, dev, 3, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME, 3); /* HostSignAuth */
|
||||||
|
opal_add_token_bytestring(&err, dev, uid_user, OPAL_UID_LENGTH);
|
||||||
|
opal_add_tokens(&err, dev, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_ENDLIST);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
SPDK_ERRLOG("Error building STARTSESSION command.\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return opal_finalize_and_send(dev, 1, opal_start_session_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_lock_unlock_range(struct spdk_opal_dev *dev, struct spdk_opal_locking_session *locking_session)
|
||||||
|
{
|
||||||
|
uint8_t uid_locking_range[OPAL_UID_LENGTH];
|
||||||
|
uint8_t read_locked, write_locked;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
opal_clear_cmd(dev);
|
||||||
|
opal_set_comid(dev, dev->comid);
|
||||||
|
|
||||||
|
if (opal_build_locking_range(uid_locking_range, sizeof(uid_locking_range),
|
||||||
|
locking_session->session.opal_key->locking_range) < 0) {
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (locking_session->l_state) {
|
||||||
|
case OPAL_READONLY:
|
||||||
|
read_locked = 0;
|
||||||
|
write_locked = 1;
|
||||||
|
break;
|
||||||
|
case OPAL_READWRITE:
|
||||||
|
read_locked = 0;
|
||||||
|
write_locked = 0;
|
||||||
|
break;
|
||||||
|
case OPAL_RWLOCK:
|
||||||
|
read_locked = 1;
|
||||||
|
write_locked = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SPDK_ERRLOG("Tried to set an invalid locking state.\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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[SET_METHOD], OPAL_UID_LENGTH);
|
||||||
|
|
||||||
|
opal_add_tokens(&err, dev, 15, SPDK_OPAL_STARTLIST,
|
||||||
|
SPDK_OPAL_STARTNAME,
|
||||||
|
SPDK_OPAL_VALUES,
|
||||||
|
SPDK_OPAL_STARTLIST,
|
||||||
|
SPDK_OPAL_STARTNAME,
|
||||||
|
SPDK_OPAL_READLOCKED,
|
||||||
|
read_locked,
|
||||||
|
SPDK_OPAL_ENDNAME,
|
||||||
|
SPDK_OPAL_STARTNAME,
|
||||||
|
SPDK_OPAL_WRITELOCKED,
|
||||||
|
write_locked,
|
||||||
|
SPDK_OPAL_ENDNAME,
|
||||||
|
SPDK_OPAL_ENDLIST,
|
||||||
|
SPDK_OPAL_ENDNAME,
|
||||||
|
SPDK_OPAL_ENDLIST);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
SPDK_ERRLOG("Error building SET command.\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int opal_generic_locking_range_enable_disable(struct spdk_opal_dev *dev,
|
||||||
|
uint8_t *uid, bool read_lock_enabled, bool write_lock_enabled,
|
||||||
|
bool read_locked, bool write_locked)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
|
||||||
|
opal_add_token_bytestring(&err, dev, uid, OPAL_UID_LENGTH);
|
||||||
|
opal_add_token_bytestring(&err, dev, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
|
||||||
|
|
||||||
|
opal_add_tokens(&err, dev, 23, SPDK_OPAL_STARTLIST,
|
||||||
|
SPDK_OPAL_STARTNAME,
|
||||||
|
SPDK_OPAL_VALUES,
|
||||||
|
SPDK_OPAL_STARTLIST,
|
||||||
|
|
||||||
|
SPDK_OPAL_STARTNAME,
|
||||||
|
SPDK_OPAL_READLOCKENABLED,
|
||||||
|
read_lock_enabled,
|
||||||
|
SPDK_OPAL_ENDNAME,
|
||||||
|
|
||||||
|
SPDK_OPAL_STARTNAME,
|
||||||
|
SPDK_OPAL_WRITELOCKENABLED,
|
||||||
|
write_lock_enabled,
|
||||||
|
SPDK_OPAL_ENDNAME,
|
||||||
|
|
||||||
|
SPDK_OPAL_STARTNAME,
|
||||||
|
SPDK_OPAL_READLOCKED,
|
||||||
|
read_locked,
|
||||||
|
SPDK_OPAL_ENDNAME,
|
||||||
|
|
||||||
|
SPDK_OPAL_STARTNAME,
|
||||||
|
SPDK_OPAL_WRITELOCKED,
|
||||||
|
write_locked,
|
||||||
|
SPDK_OPAL_ENDNAME,
|
||||||
|
|
||||||
|
SPDK_OPAL_ENDLIST,
|
||||||
|
SPDK_OPAL_ENDNAME,
|
||||||
|
SPDK_OPAL_ENDLIST);
|
||||||
|
if (err) {
|
||||||
|
SPDK_ERRLOG("Error building locking range enable/disable command.\n");
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
spdk_enable_global_locking_range(struct spdk_opal_dev *dev, uint8_t *locking_range,
|
||||||
|
struct opal_locking_range_setup_session *setup_session)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = opal_generic_locking_range_enable_disable(dev, locking_range,
|
||||||
|
setup_session->read_lock_enabled,
|
||||||
|
setup_session->write_lock_enabled,
|
||||||
|
0, 0);
|
||||||
|
if (err) {
|
||||||
|
SPDK_ERRLOG("Failed to create enable global locking range command\n");
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
opal_setup_locking_range(struct spdk_opal_dev *dev,
|
||||||
|
struct opal_locking_range_setup_session *setup_session)
|
||||||
|
{
|
||||||
|
uint8_t uid_locking_range[OPAL_UID_LENGTH];
|
||||||
|
uint8_t locking_range_id;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
opal_clear_cmd(dev);
|
||||||
|
opal_set_comid(dev, dev->comid);
|
||||||
|
|
||||||
|
locking_range_id = setup_session->session.opal_key->locking_range;
|
||||||
|
err = opal_build_locking_range(uid_locking_range, OPAL_UID_LENGTH, locking_range_id);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locking_range_id == 0) {
|
||||||
|
err = spdk_enable_global_locking_range(dev, uid_locking_range, setup_session);
|
||||||
|
} else {
|
||||||
|
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[SET_METHOD],
|
||||||
|
OPAL_UID_LENGTH);
|
||||||
|
|
||||||
|
opal_add_tokens(&err, dev, 6,
|
||||||
|
SPDK_OPAL_STARTLIST,
|
||||||
|
SPDK_OPAL_STARTNAME,
|
||||||
|
SPDK_OPAL_VALUES,
|
||||||
|
SPDK_OPAL_STARTLIST,
|
||||||
|
SPDK_OPAL_STARTNAME,
|
||||||
|
SPDK_OPAL_RANGESTART);
|
||||||
|
opal_add_token_u64(&err, dev, setup_session->range_start);
|
||||||
|
opal_add_tokens(&err, dev, 3,
|
||||||
|
SPDK_OPAL_ENDNAME,
|
||||||
|
SPDK_OPAL_STARTNAME,
|
||||||
|
SPDK_OPAL_RANGELENGTH);
|
||||||
|
opal_add_token_u64(&err, dev, setup_session->range_length);
|
||||||
|
opal_add_tokens(&err, dev, 3,
|
||||||
|
SPDK_OPAL_ENDNAME,
|
||||||
|
SPDK_OPAL_STARTNAME,
|
||||||
|
SPDK_OPAL_READLOCKENABLED);
|
||||||
|
opal_add_token_u64(&err, dev, setup_session->read_lock_enabled);
|
||||||
|
opal_add_tokens(&err, dev, 3,
|
||||||
|
SPDK_OPAL_ENDNAME,
|
||||||
|
SPDK_OPAL_STARTNAME,
|
||||||
|
SPDK_OPAL_WRITELOCKENABLED);
|
||||||
|
opal_add_token_u64(&err, dev, setup_session->write_lock_enabled);
|
||||||
|
opal_add_tokens(&err, dev, 4,
|
||||||
|
SPDK_OPAL_ENDNAME,
|
||||||
|
SPDK_OPAL_ENDLIST,
|
||||||
|
SPDK_OPAL_ENDNAME,
|
||||||
|
SPDK_OPAL_ENDLIST);
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
|
SPDK_ERRLOG("Error building Setup Locking range command.\n");
|
||||||
|
return err;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1212,7 +1476,7 @@ opal_set_sid_cpin_pin(struct spdk_opal_dev *dev, void *data)
|
|||||||
SPDK_ERRLOG("Error building Set SID cpin\n");
|
SPDK_ERRLOG("Error building Set SID cpin\n");
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
}
|
}
|
||||||
return opal_finalize_and_send(dev, 1, opal_parse_and_check_status);
|
return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -1347,7 +1611,7 @@ opal_revert_tper(struct spdk_opal_dev *dev)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return opal_finalize_and_send(dev, 1, opal_parse_and_check_status);
|
return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -1436,6 +1700,105 @@ end:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spdk_opal_cmd_lock_unlock(struct spdk_opal_dev *dev, enum spdk_opal_user user,
|
||||||
|
enum spdk_opal_lock_state flag, enum spdk_opal_locking_range locking_range,
|
||||||
|
const char *passwd)
|
||||||
|
{
|
||||||
|
struct spdk_opal_locking_session locking_session;
|
||||||
|
struct spdk_opal_key opal_key;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!dev || dev->supported == false) {
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = opal_init_key(&opal_key, passwd, locking_range);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&locking_session, 0, sizeof(struct spdk_opal_locking_session));
|
||||||
|
locking_session.l_state = flag;
|
||||||
|
locking_session.session.who = user;
|
||||||
|
locking_session.session.opal_key = &opal_key;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&dev->mutex_lock);
|
||||||
|
|
||||||
|
ret = opal_start_auth_session(dev, &locking_session.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_lock_unlock_range(dev, &locking_session);
|
||||||
|
if (ret) {
|
||||||
|
SPDK_ERRLOG("lock unlock range 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_setup_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user,
|
||||||
|
enum spdk_opal_locking_range locking_range_id, uint64_t range_start,
|
||||||
|
uint64_t range_length, const char *passwd)
|
||||||
|
{
|
||||||
|
struct opal_locking_range_setup_session setup_session;
|
||||||
|
struct spdk_opal_key opal_key;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!dev || dev->supported == false) {
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = opal_init_key(&opal_key, passwd, locking_range_id);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&setup_session, 0, sizeof(struct opal_locking_range_setup_session));
|
||||||
|
setup_session.session.opal_key = &opal_key;
|
||||||
|
setup_session.session.who = user;
|
||||||
|
setup_session.id = locking_range_id;
|
||||||
|
setup_session.range_length = range_length;
|
||||||
|
setup_session.range_start = range_start;
|
||||||
|
setup_session.read_lock_enabled = true;
|
||||||
|
setup_session.write_lock_enabled = true;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&dev->mutex_lock);
|
||||||
|
ret = opal_start_auth_session(dev, &setup_session.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_setup_locking_range(dev, &setup_session);
|
||||||
|
if (ret) {
|
||||||
|
SPDK_ERRLOG("setup locking range 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)
|
||||||
{
|
{
|
||||||
|
@ -52,6 +52,8 @@
|
|||||||
|
|
||||||
#define SPDK_DTAERROR_NO_METHOD_STATUS 0x89
|
#define SPDK_DTAERROR_NO_METHOD_STATUS 0x89
|
||||||
|
|
||||||
|
typedef int (spdk_opal_cb)(struct spdk_opal_dev *dev, void *data);
|
||||||
|
|
||||||
enum opal_token_type {
|
enum opal_token_type {
|
||||||
OPAL_DTA_TOKENID_BYTESTRING = 0xE0,
|
OPAL_DTA_TOKENID_BYTESTRING = 0xE0,
|
||||||
OPAL_DTA_TOKENID_SINT = 0xE1,
|
OPAL_DTA_TOKENID_SINT = 0xE1,
|
||||||
@ -264,8 +266,8 @@ struct opal_locking_range_setup_session {
|
|||||||
uint8_t _padding[7];
|
uint8_t _padding[7];
|
||||||
uint64_t range_start;
|
uint64_t range_start;
|
||||||
uint64_t range_length;
|
uint64_t range_length;
|
||||||
bool RLE; /* Read Lock enabled */
|
bool read_lock_enabled;
|
||||||
bool WLE; /* Write Lock Enabled */
|
bool write_lock_enabled;
|
||||||
struct opal_common_session session;
|
struct opal_common_session session;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user