Opal: Add async function for revert TPer
Some nvme drives might take 6-7mins for this operation. Thus, introduce async function to avoid waiting. Change-Id: Id48478aec653d3fb75a3c5ce75d4997284ed016c Signed-off-by: Chunyang Hui <chunyang.hui@intel.com> Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/468916 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Paul Luse <paul.e.luse@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
parent
0a18f228c3
commit
ac4949807b
@ -164,6 +164,8 @@ struct spdk_opal_locking_range_info {
|
|||||||
|
|
||||||
struct spdk_opal_dev;
|
struct spdk_opal_dev;
|
||||||
|
|
||||||
|
typedef void (*spdk_opal_revert_cb)(struct spdk_opal_dev *dev, void *ctx, int rc);
|
||||||
|
|
||||||
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_close(struct spdk_opal_dev *dev);
|
void spdk_opal_close(struct spdk_opal_dev *dev);
|
||||||
@ -173,7 +175,32 @@ bool spdk_opal_supported(struct spdk_opal_dev *dev);
|
|||||||
|
|
||||||
int spdk_opal_cmd_scan(struct spdk_opal_dev *dev);
|
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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Users should periodically call spdk_opal_revert_poll to check if the response is received.
|
||||||
|
* Once a final result is received, no matter success or failure, dev->revert_cb_fn will be called.
|
||||||
|
* Error code is put to dev->revert_cb_fn.
|
||||||
|
*
|
||||||
|
* Return: -EAGAIN for no result yet. 0 for final result received.
|
||||||
|
*/
|
||||||
|
int spdk_opal_revert_poll(struct spdk_opal_dev *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* asynchronous function: Just send cmd and return.
|
||||||
|
*
|
||||||
|
* Users should periodically call spdk_opal_revert_poll to check if the response is received.
|
||||||
|
* Because usually revert TPer operation will take a while.
|
||||||
|
*/
|
||||||
|
int spdk_opal_cmd_revert_tper_async(struct spdk_opal_dev *dev, const char *passwd,
|
||||||
|
spdk_opal_revert_cb cb_fn, void *cb_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* synchronous function: send and then receive.
|
||||||
|
*
|
||||||
|
* Wait until response is received.
|
||||||
|
*/
|
||||||
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,
|
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,
|
enum spdk_opal_lock_state flag, enum spdk_opal_locking_range locking_range,
|
||||||
@ -198,6 +225,8 @@ int spdk_opal_cmd_erase_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_
|
|||||||
|
|
||||||
struct spdk_opal_locking_range_info *spdk_opal_get_locking_range_info(struct spdk_opal_dev *dev,
|
struct spdk_opal_locking_range_info *spdk_opal_get_locking_range_info(struct spdk_opal_dev *dev,
|
||||||
enum spdk_opal_locking_range id);
|
enum spdk_opal_locking_range id);
|
||||||
|
void spdk_opal_free_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);
|
uint8_t spdk_opal_get_max_locking_ranges(struct spdk_opal_dev *dev);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,6 +37,10 @@
|
|||||||
|
|
||||||
#include "nvme_opal_internal.h"
|
#include "nvme_opal_internal.h"
|
||||||
|
|
||||||
|
typedef int (*spdk_opal_cb)(struct spdk_opal_dev *dev, void *ctx);
|
||||||
|
|
||||||
|
static int opal_parse_and_check_status(struct spdk_opal_dev *dev, void *data);
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
opal_error_to_human(int error)
|
opal_error_to_human(int error)
|
||||||
{
|
{
|
||||||
@ -96,7 +100,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, void *data)
|
opal_send_recv(struct spdk_opal_dev *dev, spdk_opal_cb cb, void *data)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -276,6 +280,11 @@ opal_cmd_finalize(struct spdk_opal_dev *dev, uint32_t hsn, uint32_t tsn, bool eo
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* synchronous function: send and then receive.
|
||||||
|
*
|
||||||
|
* Wait until response is received. And then call the callback functions.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
opal_finalize_and_send(struct spdk_opal_dev *dev, bool eod, spdk_opal_cb cb, void *data)
|
opal_finalize_and_send(struct spdk_opal_dev *dev, bool eod, spdk_opal_cb cb, void *data)
|
||||||
{
|
{
|
||||||
@ -972,7 +981,7 @@ spdk_opal_close(struct spdk_opal_dev *dev)
|
|||||||
pthread_mutex_destroy(&dev->mutex_lock);
|
pthread_mutex_destroy(&dev->mutex_lock);
|
||||||
if (dev->max_ranges > 0) {
|
if (dev->max_ranges > 0) {
|
||||||
for (int i = 0; i < dev->max_ranges; i++) {
|
for (int i = 0; i < dev->max_ranges; i++) {
|
||||||
free(dev->locking_range_info[i]);
|
spdk_opal_free_locking_range_info(dev, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(dev->opal_info);
|
free(dev->opal_info);
|
||||||
@ -1920,10 +1929,9 @@ opal_revert_tper(struct spdk_opal_dev *dev)
|
|||||||
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
|
opal_add_token_u8(&err, dev, SPDK_OPAL_ENDLIST);
|
||||||
if (err) {
|
if (err) {
|
||||||
SPDK_ERRLOG("Error building REVERT TPER command.\n");
|
SPDK_ERRLOG("Error building REVERT TPER command.\n");
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2044,7 +2052,8 @@ spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = opal_init_key(&opal_key, passwd, OPAL_LOCKING_RANGE_GLOBAL);
|
ret = opal_init_key(&opal_key, passwd, OPAL_LOCKING_RANGE_GLOBAL);
|
||||||
if (ret != 0) {
|
if (ret) {
|
||||||
|
SPDK_ERRLOG("Init key failed\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2067,6 +2076,104 @@ spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd)
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
|
||||||
|
if (ret) {
|
||||||
|
opal_end_session(dev);
|
||||||
|
SPDK_ERRLOG("Error on reverting TPer with error %d: %s\n", ret,
|
||||||
|
opal_error_to_human(ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Controller will terminate session. No "end session" here needed. */
|
||||||
|
|
||||||
|
end:
|
||||||
|
pthread_mutex_unlock(&dev->mutex_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spdk_opal_revert_poll(struct spdk_opal_dev *dev)
|
||||||
|
{
|
||||||
|
void *response = dev->resp;
|
||||||
|
struct spdk_opal_header *header = response;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
assert(dev->revert_cb_fn);
|
||||||
|
|
||||||
|
ret = spdk_nvme_ctrlr_security_receive(dev->dev_handler, SPDK_SCSI_SECP_TCG, dev->comid,
|
||||||
|
0, dev->resp, IO_BUFFER_LENGTH);
|
||||||
|
if (ret) {
|
||||||
|
SPDK_ERRLOG("Security Receive Error on dev = %p\n", dev);
|
||||||
|
dev->revert_cb_fn(dev, dev->ctx, ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header->com_packet.outstanding_data == 0 &&
|
||||||
|
header->com_packet.min_transfer == 0) {
|
||||||
|
ret = opal_parse_and_check_status(dev, NULL);
|
||||||
|
dev->revert_cb_fn(dev, dev->ctx, ret);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
memset(response, 0, IO_BUFFER_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spdk_opal_cmd_revert_tper_async(struct spdk_opal_dev *dev, const char *passwd,
|
||||||
|
spdk_opal_revert_cb cb_fn, void *cb_ctx)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct spdk_opal_key opal_key;
|
||||||
|
|
||||||
|
if (!dev || dev->supported == false) {
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cb_fn == NULL) {
|
||||||
|
SPDK_ERRLOG("No revert callback function specified.\n");
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->revert_cb_fn = cb_fn;
|
||||||
|
dev->ctx = cb_ctx;
|
||||||
|
|
||||||
|
ret = opal_init_key(&opal_key, passwd, OPAL_LOCKING_RANGE_GLOBAL);
|
||||||
|
if (ret) {
|
||||||
|
SPDK_ERRLOG("Init key failed\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&dev->mutex_lock);
|
||||||
|
opal_setup_dev(dev);
|
||||||
|
|
||||||
|
ret = opal_start_adminsp_session(dev, &opal_key);
|
||||||
|
if (ret) {
|
||||||
|
opal_end_session(dev);
|
||||||
|
SPDK_ERRLOG("Error on starting admin SP session with error %d: %s\n", ret,
|
||||||
|
opal_error_to_human(ret));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = opal_revert_tper(dev);
|
||||||
|
if (ret) {
|
||||||
|
opal_end_session(dev);
|
||||||
|
SPDK_ERRLOG("Error on reverting TPer with error %d: %s\n", ret,
|
||||||
|
opal_error_to_human(ret));
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = opal_cmd_finalize(dev, dev->hsn, dev->tsn, true); /* true: end of data */
|
||||||
|
if (ret) {
|
||||||
|
SPDK_ERRLOG("Error finalizing command buffer: %d\n", ret);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = opal_send_cmd(dev);
|
||||||
|
if (ret) {
|
||||||
|
SPDK_ERRLOG("Error sending opal command: %d\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
/* Controller will terminate session. No "end session" here needed. */
|
/* Controller will terminate session. No "end session" here needed. */
|
||||||
|
|
||||||
end:
|
end:
|
||||||
@ -2521,6 +2628,15 @@ spdk_opal_get_locking_range_info(struct spdk_opal_dev *dev, enum spdk_opal_locki
|
|||||||
return dev->locking_range_info[id];
|
return dev->locking_range_info[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spdk_opal_free_locking_range_info(struct spdk_opal_dev *dev, enum spdk_opal_locking_range id)
|
||||||
|
{
|
||||||
|
struct spdk_opal_locking_range_info *info = dev->locking_range_info[id];
|
||||||
|
|
||||||
|
free(info);
|
||||||
|
dev->locking_range_info[id] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
spdk_opal_get_max_locking_ranges(struct spdk_opal_dev *dev)
|
spdk_opal_get_max_locking_ranges(struct spdk_opal_dev *dev)
|
||||||
{
|
{
|
||||||
|
@ -52,8 +52,6 @@
|
|||||||
|
|
||||||
#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,
|
||||||
@ -303,6 +301,8 @@ struct spdk_opal_dev {
|
|||||||
struct spdk_opal_locking_range_info *locking_range_info[OPAL_MAX_LRS];
|
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 */
|
||||||
|
spdk_opal_revert_cb revert_cb_fn;
|
||||||
|
void *ctx; /* user context data */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user