Opal: add take ownership cmd options

Also make some modification for invoking process in
nvme_manage tool.

Change-Id: Ib54db43d7336d3e839e7d9317c292b9a57b38f80
Signed-off-by: Chunyang Hui <chunyang.hui@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/445059
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Chunyang Hui 2019-02-13 17:51:11 +08:00 committed by Jim Harris
parent 1dd07870e3
commit 7250ec64db
5 changed files with 541 additions and 26 deletions

View File

@ -100,7 +100,8 @@ is specified, use that specified nbd device. If it's not specified, pick availab
### Opal ### Opal
Add Opal scan support for NVMe to check whether it supports SED Opal and dump Add Opal scan support for NVMe to check whether it supports SED Opal and dump
device info. nvme_manage tool can be used to invoke this. device info. Add Opal take ownership command support. nvme_manage tool can be used to invoke this.
This module should be considered experimental pending additional features and tests.
### iSCSI target ### iSCSI target

View File

@ -142,7 +142,7 @@ static void usage(void)
printf("\t[5: detach namespace from controller]\n"); printf("\t[5: detach namespace from controller]\n");
printf("\t[6: format namespace or controller]\n"); printf("\t[6: format namespace or controller]\n");
printf("\t[7: firmware update]\n"); printf("\t[7: firmware update]\n");
printf("\t[8: opal scan]\n"); printf("\t[8: opal]\n");
printf("\t[9: quit]\n"); printf("\t[9: quit]\n");
} }
@ -853,7 +853,8 @@ update_firmware_image(void)
spdk_dma_free(fw_image); spdk_dma_free(fw_image);
} }
static void spdk_dump_opal_info(struct spdk_opal_info *opal) static void
opal_dump_info(struct spdk_opal_info *opal)
{ {
if (!opal->opal_ssc_dev) { if (!opal->opal_ssc_dev) {
SPDK_ERRLOG("This device is not Opal enabled. Not Supported!\n"); SPDK_ERRLOG("This device is not Opal enabled. Not Supported!\n");
@ -928,30 +929,119 @@ static void spdk_dump_opal_info(struct spdk_opal_info *opal)
} }
} }
static void
opal_usage(void)
{
printf("Opal General Usage:\n");
printf("\n");
printf("\t[1: scan device]\n");
printf("\t[2: take ownership]\n");
printf("\t[0: quit]\n");
}
static void
opal_scan(struct dev *iter)
{
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("\n\nOpal Supported:\n");
display_controller(iter, CONTROLLER_DISPLAY_SIMPLISTIC);
spdk_opal_scan(iter->opal_dev);
opal_dump_info(spdk_opal_get_info(iter->opal_dev));
}
spdk_opal_close(iter->opal_dev);
} else {
printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\n",
iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
printf("%04x:%02x:%02x.%02x: Opal Not Supported\n\n\n",
iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
}
}
static void
opal_take_ownership(struct dev *iter)
{
char new_passwd[MAX_PASSWORD_SIZE];
char *passwd_p;
int ret;
int ch;
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)) {
memset(new_passwd, 0, sizeof(new_passwd));
printf("Please input the new password for ownership:\n");
while ((ch = getchar()) != '\n' && ch != EOF);
passwd_p = get_line(new_passwd, MAX_PASSWORD_SIZE, stdin);
if (passwd_p) {
ret = spdk_opal_cmd(iter->opal_dev, OPAL_CMD_TAKE_OWNERSHIP, passwd_p);
if (ret) {
printf("Take ownership failure: %d\n", ret);
return;
}
printf("...\n...\nTake Ownership Success\n");
} else {
printf("Input password invalid. Take ownership failure\n");
}
}
spdk_opal_close(iter->opal_dev);
} else {
printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\n",
iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
printf("%04x:%02x:%02x.%02x: Opal 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
test_opal(void) test_opal(void)
{ {
struct dev *iter; int exit_flag = false;
struct dev *ctrlr;
foreach_dev(iter) { ctrlr = get_controller();
if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) { if (ctrlr == NULL) {
iter->opal_dev = spdk_opal_init_dev(iter->ctrlr); printf("Invalid controller PCI Address.\n");
if (iter->opal_dev == NULL) { return;
return; }
}
if (spdk_opal_supported(iter->opal_dev)) { opal_usage();
printf("\n\nOpal Supported:\n"); while (!exit_flag) {
display_controller(iter, CONTROLLER_DISPLAY_SIMPLISTIC); int cmd;
spdk_opal_scan(iter->opal_dev); if (!scanf("%d", &cmd)) {
spdk_dump_opal_info(spdk_opal_get_info(iter->opal_dev)); printf("Invalid Command: command must be number 0-2\n");
} while (getchar() != '\n');
spdk_opal_close(iter->opal_dev); opal_usage();
} else { continue;
printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\n",
iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
printf("%04x:%02x:%02x.%02x: Opal Not Supported\n\n\n",
iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func);
} }
switch (cmd) {
case 0:
exit_flag = true;
continue;
case 1:
opal_scan(ctrlr);
break;
case 2:
opal_take_ownership(ctrlr);
break;
default:
printf("Invalid option\n");
}
while (getchar() != '\n');
printf("press Enter to display Opal cmd menu ...\n");
while (getchar() != '\n');
opal_usage();
} }
} }

View File

@ -42,6 +42,8 @@
#define SPDK_OPAL_NOT_SUPPORTED 0xFF #define SPDK_OPAL_NOT_SUPPORTED 0xFF
#define MAX_PASSWORD_SIZE 32 /* in byte */
/* /*
* TCG Storage Architecture Core Spec v2.01 r1.00 * TCG Storage Architecture Core Spec v2.01 r1.00
* 5.1.5 Method Status Codes * 5.1.5 Method Status Codes
@ -84,6 +86,7 @@ enum spdk_opal_cmd {
OPAL_CMD_ERASE_LOCKING_RANGE, OPAL_CMD_ERASE_LOCKING_RANGE,
OPAL_CMD_SECURE_ERASE_LOCKING_RANGE, OPAL_CMD_SECURE_ERASE_LOCKING_RANGE,
OPAL_CMD_INITIAL_SETUP, OPAL_CMD_INITIAL_SETUP,
OPAL_CMD_SCAN,
}; };
struct spdk_opal_info { struct spdk_opal_info {
@ -136,10 +139,12 @@ 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);
void spdk_opal_scan(struct spdk_opal_dev *dev); int spdk_opal_scan(struct spdk_opal_dev *dev);
void spdk_opal_close(struct spdk_opal_dev *dev); void spdk_opal_close(struct spdk_opal_dev *dev);
struct spdk_opal_info *spdk_opal_get_info(struct spdk_opal_dev *dev); struct spdk_opal_info *spdk_opal_get_info(struct spdk_opal_dev *dev);
bool spdk_opal_supported(struct spdk_opal_dev *dev); bool spdk_opal_supported(struct spdk_opal_dev *dev);
int spdk_opal_cmd(struct spdk_opal_dev *dev, unsigned int cmd, void *arg);
#endif #endif

View File

@ -129,6 +129,97 @@ opal_add_token_u8(int *err, struct spdk_opal_dev *dev, uint8_t token)
dev->cmd[dev->cmd_pos++] = token; dev->cmd[dev->cmd_pos++] = token;
} }
static void
opal_add_short_atom_header(struct spdk_opal_dev *dev, bool bytestring,
bool has_sign, size_t len)
{
uint8_t atom;
int err = 0;
atom = SPDK_SHORT_ATOM_ID;
atom |= bytestring ? SPDK_SHORT_ATOM_BYTESTRING_FLAG : 0;
atom |= has_sign ? SPDK_SHORT_ATOM_SIGN_FLAG : 0;
atom |= len & SPDK_SHORT_ATOM_LEN_MASK;
opal_add_token_u8(&err, dev, atom);
}
static void
opal_add_medium_atom_header(struct spdk_opal_dev *dev, bool bytestring,
bool has_sign, size_t len)
{
uint8_t header;
header = SPDK_MEDIUM_ATOM_ID;
header |= bytestring ? SPDK_MEDIUM_ATOM_BYTESTRING_FLAG : 0;
header |= has_sign ? SPDK_MEDIUM_ATOM_SIGN_FLAG : 0;
header |= (len >> 8) & SPDK_MEDIUM_ATOM_LEN_MASK;
dev->cmd[dev->cmd_pos++] = header;
dev->cmd[dev->cmd_pos++] = len;
}
static void
opal_add_token_bytestring(int *err, struct spdk_opal_dev *dev,
const uint8_t *bytestring, size_t len)
{
size_t header_len = 1;
bool is_short_atom = true;
if (*err) {
return;
}
if (len & ~SPDK_SHORT_ATOM_LEN_MASK) {
header_len = 2;
is_short_atom = false;
}
if (len >= IO_BUFFER_LENGTH - dev->cmd_pos - header_len) {
SPDK_ERRLOG("Error adding bytestring: end of buffer.\n");
*err = -ERANGE;
return;
}
if (is_short_atom) {
opal_add_short_atom_header(dev, true, false, len);
} else {
opal_add_medium_atom_header(dev, true, false, len);
}
memcpy(&dev->cmd[dev->cmd_pos], bytestring, len);
dev->cmd_pos += len;
}
static void
opal_add_token_u64(int *err, struct spdk_opal_dev *dev, uint64_t number)
{
int startat = 0;
/* add header first */
if (number <= SPDK_TINY_ATOM_DATA_MASK) {
dev->cmd[dev->cmd_pos++] = (uint8_t) number & SPDK_TINY_ATOM_DATA_MASK;
} else {
if (number < 0x100) {
dev->cmd[dev->cmd_pos++] = 0x81; /* short atom, 1 byte length */
startat = 0;
} else if (number < 0x10000) {
dev->cmd[dev->cmd_pos++] = 0x82; /* short atom, 2 byte length */
startat = 1;
} else if (number < 0x100000000) {
dev->cmd[dev->cmd_pos++] = 0x84; /* short atom, 4 byte length */
startat = 3;
} else {
dev->cmd[dev->cmd_pos++] = 0x88; /* short atom, 8 byte length */
startat = 7;
}
/* add number value */
for (int i = startat; i > -1; i--) {
dev->cmd[dev->cmd_pos++] = (uint8_t)((number >> (i * 8)) & 0xff);
}
}
}
static int static int
opal_cmd_finalize(struct spdk_opal_dev *dev, uint32_t hsn, uint32_t tsn, bool eod) opal_cmd_finalize(struct spdk_opal_dev *dev, uint32_t hsn, uint32_t tsn, bool eod)
{ {
@ -367,7 +458,6 @@ opal_response_token_matches(const struct spdk_opal_resp_token *token,
if (!token || if (!token ||
token->type != OPAL_DTA_TOKENID_TOKEN || token->type != OPAL_DTA_TOKENID_TOKEN ||
token->pos[0] != match) { token->pos[0] != match) {
SPDK_ERRLOG("Token not matching\n");
return false; return false;
} }
return true; return true;
@ -417,6 +507,31 @@ 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 size_t
opal_response_get_string(const struct spdk_opal_resp_parsed *resp, int n,
const char **store)
{
*store = NULL;
if (!resp) {
SPDK_ERRLOG("Response is NULL\n");
return 0;
}
if (n > resp->num) {
SPDK_ERRLOG("Response has %d tokens. Can't access %d\n",
resp->num, n);
return 0;
}
if (resp->resp_tokens[n].type != OPAL_DTA_TOKENID_BYTESTRING) {
SPDK_ERRLOG("Token is not a byte string!\n");
return 0;
}
*store = resp->resp_tokens[n].pos + 1;
return resp->resp_tokens[n].len - 1;
}
static int static int
opal_response_status(const struct spdk_opal_resp_parsed *resp) opal_response_status(const struct spdk_opal_resp_parsed *resp)
{ {
@ -789,10 +904,276 @@ opal_check_support(struct spdk_opal_dev *dev)
void void
spdk_opal_close(struct spdk_opal_dev *dev) spdk_opal_close(struct spdk_opal_dev *dev)
{ {
pthread_mutex_destroy(&dev->mutex_lock);
free(dev->opal_info); free(dev->opal_info);
free(dev); free(dev);
} }
static int
opal_start_session_cb(struct spdk_opal_dev *dev)
{
uint32_t hsn, tsn;
int error = 0;
error = opal_parse_and_check_status(dev);
if (error) {
return error;
}
hsn = opal_response_get_u64(&dev->parsed_resp, 4);
tsn = opal_response_get_u64(&dev->parsed_resp, 5);
if (hsn == 0 && tsn == 0) {
SPDK_ERRLOG("Couldn't authenticate session\n");
return -EPERM;
}
dev->hsn = hsn;
dev->tsn = tsn;
return 0;
}
static int
opal_start_generic_session(struct spdk_opal_dev *dev,
enum opal_uid_enum auth,
enum opal_uid_enum sp_type,
const char *key,
uint8_t key_len)
{
uint32_t hsn;
int err = 0;
if (key == NULL && auth != UID_ANYBODY) {
return OPAL_INVAL_PARAM;
}
opal_clear_cmd(dev);
opal_set_comid(dev, dev->comid);
hsn = GENERIC_HOST_SESSION_NUM;
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[sp_type], OPAL_UID_LENGTH);
opal_add_token_u8(&err, dev, SPDK_OPAL_TRUE); /* Write */
switch (auth) {
case UID_ANYBODY:
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
break;
case UID_ADMIN1:
case UID_SID:
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTNAME);
opal_add_token_u8(&err, dev, 0); /* HostChallenge */
opal_add_token_bytestring(&err, dev, key, key_len);
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDNAME);
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTNAME);
opal_add_token_u8(&err, dev, 3); /* HostSignAuth */
opal_add_token_bytestring(&err, dev, spdk_opal_uid[auth],
OPAL_UID_LENGTH);
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDNAME);
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
break;
default:
SPDK_ERRLOG("Cannot start Admin SP session with auth %d\n", auth);
return -EINVAL;
}
if (err) {
SPDK_ERRLOG("Error building start adminsp session command.\n");
return err;
}
return opal_finalize_and_send(dev, 1, opal_start_session_cb);
}
static int
opal_start_anybody_adminsp_session(struct spdk_opal_dev *dev, void *data)
{
return opal_start_generic_session(dev, UID_ANYBODY,
UID_ADMINSP, NULL, 0);
}
static int
opal_get_msid_cpin_pin_cb(struct spdk_opal_dev *dev)
{
const char *msid_pin;
size_t strlen;
int error = 0;
error = opal_parse_and_check_status(dev);
if (error) {
return error;
}
strlen = opal_response_get_string(&dev->parsed_resp, 4, &msid_pin);
if (!msid_pin) {
SPDK_ERRLOG("Couldn't extract PIN from response\n");
return -EINVAL;
}
dev->prev_d_len = strlen;
dev->prev_data = calloc(1, strlen);
if (!dev->prev_data) {
SPDK_ERRLOG("memory allocation error\n");
return -ENOMEM;
}
memcpy(dev->prev_data, msid_pin, strlen);
SPDK_DEBUGLOG(SPDK_LOG_OPAL, "MSID = %p\n", dev->prev_data);
return 0;
}
static int
opal_get_msid_cpin_pin(struct spdk_opal_dev *dev, void *data)
{
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_C_PIN_MSID],
OPAL_UID_LENGTH);
opal_add_token_bytestring(&err, dev, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTNAME);
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTCOLUMN);
opal_add_token_u8(&err, dev, SPDK_OPAL_PIN);
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDNAME);
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTNAME);
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDCOLUMN);
opal_add_token_u8(&err, dev, SPDK_OPAL_PIN);
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDNAME);
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
if (err) {
SPDK_ERRLOG("Error building Get MSID CPIN PIN command.\n");
return err;
}
return opal_finalize_and_send(dev, 1, opal_get_msid_cpin_pin_cb);
}
static int
opal_start_adminsp_session(struct spdk_opal_dev *dev, void *data)
{
int ret;
uint8_t *key = dev->prev_data;
if (!key) {
const struct spdk_opal_key *okey = data;
if (okey == NULL) {
SPDK_ERRLOG("No key found for auth session\n");
return -EINVAL;
}
ret = opal_start_generic_session(dev, UID_SID,
UID_ADMINSP,
okey->key,
okey->key_len);
} else {
ret = opal_start_generic_session(dev, UID_SID,
UID_ADMINSP,
key, dev->prev_d_len);
free(key);
dev->prev_data = NULL;
}
return ret;
}
static int
opal_generic_pw_cmd(uint8_t *key, size_t key_len, uint8_t *cpin_uid,
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, cpin_uid, OPAL_UID_LENGTH);
opal_add_token_bytestring(&err, dev, spdk_opal_method[SET_METHOD],
OPAL_UID_LENGTH);
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTNAME);
opal_add_token_u8(&err, dev, SPDK_OPAL_VALUES);
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTLIST);
opal_add_token_u8(&err, dev, SPDK_OPAL_STARTNAME);
opal_add_token_u8(&err, dev, SPDK_OPAL_PIN);
opal_add_token_bytestring(&err, dev, key, key_len);
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDNAME);
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDNAME);
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
return err;
}
static int
opal_set_sid_cpin_pin(struct spdk_opal_dev *dev, void *data)
{
uint8_t cpin_uid[OPAL_UID_LENGTH];
const char *new_passwd = data;
struct spdk_opal_key *opal_key;
opal_key = calloc(1, sizeof(struct spdk_opal_key));
if (!opal_key) {
SPDK_ERRLOG("Memory allocation failed for spdk_opal_key\n");
return -ENOMEM;
}
opal_key->key_len = strlen(new_passwd);
memcpy(opal_key->key, new_passwd, opal_key->key_len);
dev->dev_key = opal_key;
memcpy(cpin_uid, spdk_opal_uid[UID_C_PIN_SID], OPAL_UID_LENGTH);
if (opal_generic_pw_cmd(opal_key->key, opal_key->key_len, cpin_uid, dev)) {
SPDK_ERRLOG("Error building Set SID cpin\n");
return -ERANGE;
}
return opal_finalize_and_send(dev, 1, opal_parse_and_check_status);
}
static int
spdk_opal_take_ownership(struct spdk_opal_dev *dev, char *new_passwd)
{
const struct spdk_opal_step owner_steps[] = {
{ opal_discovery0, },
{ opal_start_anybody_adminsp_session, },
{ opal_get_msid_cpin_pin, },
{ opal_end_session, },
{ opal_start_adminsp_session, },
{ opal_set_sid_cpin_pin, new_passwd },
{ opal_end_session, },
{ NULL, }
};
int ret;
if (!dev) {
return -ENODEV;
}
pthread_mutex_lock(&dev->mutex_lock);
opal_setup_dev(dev, owner_steps);
ret = opal_next(dev);
pthread_mutex_unlock(&dev->mutex_lock);
return ret;
}
struct spdk_opal_dev * struct spdk_opal_dev *
spdk_opal_init_dev(void *dev_handler) spdk_opal_init_dev(void *dev_handler)
{ {
@ -819,10 +1200,18 @@ spdk_opal_init_dev(void *dev_handler)
SPDK_INFOLOG(SPDK_LOG_OPAL, "Opal is not supported on this device\n"); SPDK_INFOLOG(SPDK_LOG_OPAL, "Opal is not supported on this device\n");
dev->supported = false; dev->supported = false;
} }
if (pthread_mutex_init(&dev->mutex_lock, NULL)) {
SPDK_ERRLOG("Mutex init failed\n");
free(dev->opal_info);
free(dev);
return NULL;
}
return dev; return dev;
} }
void int
spdk_opal_scan(struct spdk_opal_dev *dev) spdk_opal_scan(struct spdk_opal_dev *dev)
{ {
int ret; int ret;
@ -831,8 +1220,8 @@ spdk_opal_scan(struct spdk_opal_dev *dev)
if (ret) { if (ret) {
SPDK_ERRLOG("check opal support failed: %d\n", ret); SPDK_ERRLOG("check opal support failed: %d\n", ret);
spdk_opal_close(dev); spdk_opal_close(dev);
return;
} }
return ret;
} }
struct spdk_opal_info * struct spdk_opal_info *
@ -847,5 +1236,33 @@ spdk_opal_supported(struct spdk_opal_dev *dev)
return dev->supported; return dev->supported;
} }
int
spdk_opal_cmd(struct spdk_opal_dev *dev, unsigned int cmd, void *arg)
{
if (!dev) {
SPDK_ERRLOG("Device null\n");
return -ENODEV;
}
if (!dev->supported) {
SPDK_ERRLOG("Device not supported\n");
return -EINVAL;
}
switch (cmd) {
case OPAL_CMD_SCAN:
return spdk_opal_scan(dev);
case OPAL_CMD_TAKE_OWNERSHIP:
return spdk_opal_take_ownership(dev, arg);
case OPAL_CMD_LOCK_UNLOCK:
case OPAL_CMD_ACTIVATE_LSP:
case OPAL_CMD_REVERT_TPER:
case OPAL_CMD_SETUP_LOCKING_RANGE:
default:
SPDK_ERRLOG("NOT SUPPORTED\n");
return -EINVAL;
}
}
/* 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

@ -325,6 +325,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 */
pthread_mutex_t mutex_lock; /* some structs are accessed by current thread only */
}; };
enum opal_lock_state { enum opal_lock_state {