Skip to content

Commit

Permalink
ioctl: Live Migration
Browse files Browse the repository at this point in the history
Continues efforts from the newly minted TP4159 PCIe Infrastructure for
Live Migration specification by adding additional types and ioctl
methods.

Signed-off-by: Nate Thornton <[email protected]>
  • Loading branch information
NateThornton committed Nov 13, 2024
1 parent 1144da5 commit aaa49bc
Show file tree
Hide file tree
Showing 5 changed files with 672 additions and 4 deletions.
6 changes: 6 additions & 0 deletions src/libnvme.map
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ LIBNVME_1_0 {
nvme_default_host;
nvme_dev_self_test;
nvme_dim_send;
nvme_lm_cdq;
nvme_lm_track_send;
nvme_lm_migration_send;
nvme_lm_migration_recv;
nvme_lm_set_features_ctrl_data_queue;
nvme_lm_get_features_ctrl_data_queue;
nvme_directive_recv;
nvme_directive_send;
nvme_directive_send_id_endir;
Expand Down
100 changes: 100 additions & 0 deletions src/nvme/api-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -962,4 +962,104 @@ struct nvme_dim_args {
__u8 tas;
};

/**
* struct nvme_lm_cdq_args - Arguments for Controller Data Queue (CDQ) command
* @result: Set on completion to the command's CQE DWORD 0 controller response
* @data: Pointer to data
* @args_size: Length of structure
* @fd: File descriptor of nvme device
* @timeout: Timeout in ms
* @sel: Select (SEL): This field specifies the type of management operation to perform.
* @sz: Size of CDQ in dwords
* @cntlid: Controller ID: This field specifies the ID of the controller to be used by the
* specified Select (SEL) field.
* @cdqid: Controller Data Queue ID (CDQID): This field specifies the ID of the CDQ to be used
* for the specified Select (SEL) field.
*/
struct nvme_lm_cdq_args {
__u32 *result;
void *data;
int args_size;
int fd;
__u32 timeout;
__u8 sel;
__u8 sz;
__u8 qt;
__u16 cntlid;
__u16 cdqid;
};

/**
* struct nvme_lm_track_send_args - Arguments for the Track Send command
* @result: Set on completion to the command's CQE DWORD 0 controller response
* @args_size: Length of structure
* @fd: File descriptor of nvme device
* @timeout: Timeout in ms
* @sel: Select (SEL): This field specifies the type of management operation to perform
* @lact: Logging Action (LACT): This field specifies the type of logging action to perform
* @cdqid: Controller Data Queue ID (CDQID): This field specifies the ID of the CDQ to be used
* for the logging action
*/
struct nvme_lm_track_send_args {
__u32 *result;
int args_size;
int fd;
__u32 timeout;
__u8 sel;
__u8 lact;
__u16 cdqid;
};

/**
* struct nvme_lm_migration_send_args - Arguments for the Migration Send command
* @result: Set on completion to the command's CQE DWORD 0 controller response
* @data: Pointer to data
* @args_size: Length of structure
* @fd: File descriptor of nvme device
* @timeout: Timeout in ms
* @sel: Select (SEL): This field specifies the type of management operation to perform
*/
struct nvme_lm_migration_send_args {
__u32 *result;
void *data;
int args_size;
int fd;
__u32 timeout;
__u8 sel;
__u8 uidx;
bool dudmq;
__u8 stype;
__u16 cntlid;
__u8 seqind;
__u8 csvi;
__u16 csuuidi;
__u64 offset;
__u32 numd;
};

/**
* struct nvme_lm_migration_recv_args - Arguments for the Migration Receive command
* @result: Set on completion to the command's CQE DWORD 0 controller response
* @data: Pointer to data
* @args_size: Length of structure
* @fd: File descriptor of nvme device
* @timeout: Timeout in ms
* @sel: Select (SEL): This field specifies the type of management operation to perform
*/
struct nvme_lm_migration_recv_args {
__u32 *result;
void *data;
int args_size;
int fd;
__u32 timeout;
__u16 cntlid;
__u8 sel;
__u8 csvi;
__u8 csuidxp;
__u16 csuuidi;
__u64 offset;
__u8 uidx;
__u32 numd;
};

#endif /* _LIBNVME_API_TYPES_H */
168 changes: 164 additions & 4 deletions src/nvme/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2149,10 +2149,100 @@ int nvme_dim_send(struct nvme_dim_args *args)
__u32 cdw10 = NVME_SET(args->tas, DIM_TAS);

struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_discovery_info_mgmt,
.cdw10 = cdw10,
.addr = (__u64)(uintptr_t)args->data,
.data_len = args->data_len,
.opcode = nvme_admin_discovery_info_mgmt,
.cdw10 = cdw10,
.addr = (__u64)(uintptr_t)args->data,
.data_len = args->data_len,
.timeout_ms = args->timeout,
};

if (args->args_size < sizeof(*args)) {
errno = EINVAL;
return -1;
}

return nvme_submit_admin_passthru(args->fd, &cmd, args->result);
}

int nvme_lm_cdq(struct nvme_lm_cdq_args *args)
{
__u32 cdw10 = NVME_SET(args->sel, LM_SELECT);
__u32 cdw11 = 0, data_len = 0;
int err;

if (args->sel == NVME_LM_CREATE_CONTROLLER_DATA_QUEUE) {
cdw10 |= NVME_SET(args->qt, LM_QUEUE_TYPE);
cdw11 |= NVME_SET(args->cntlid, LM_CREATE_CDQ_CNTLID) | NVME_LM_CREATE_CDQ_PC;
data_len = args->sz << 2;
} else if (args->sel == NVME_LM_DELETE_CONTROLLER_DATA_QUEUE) {
cdw11 |= NVME_SET(args->cdqid, LM_DELETE_CDQ_CDQID);
}

struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_ctrl_data_queue,
.cdw10 = cdw10,
.cdw11 = cdw11,
.cdw12 = args->sz,
.addr = (__u64)(uintptr_t)args->data,
.data_len = data_len,
.timeout_ms = args->timeout,
};

if (args->args_size < sizeof(*args)) {
errno = EINVAL;
return -1;
}

err = nvme_submit_admin_passthru(args->fd, &cmd, args->result);

if (!err)
args->cdqid = NVME_GET(cmd.result, LM_CREATE_CDQ_CDQID);

return err;
}

int nvme_lm_track_send(struct nvme_lm_track_send_args *args)
{
__u32 cdw10 = NVME_SET(args->sel, LM_SELECT) | NVME_SET(args->lact, LM_LACT);

struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_track_send,
.cdw10 = cdw10,
.cdw11 = args->cdqid,
.timeout_ms = args->timeout,
};

if (args->args_size < sizeof(*args)) {
errno = EINVAL;
return -1;
}

return nvme_submit_admin_passthru(args->fd, &cmd, args->result);
}

int nvme_lm_migration_send(struct nvme_lm_migration_send_args *args)
{
__u32 cdw10 = NVME_SET(args->sel, LM_SELECT);
__u32 cdw11 = NVME_SET(args->cntlid, LM_MIGRATION_CNTLID);

if (args->sel == NVME_LM_SUSPEND) {
cdw11 |= NVME_SET(args->dudmq, LM_DUDMQ) | NVME_SET(args->stype, LM_STYPE);
} else if (args->sel == NVME_LM_SET_CONTROLLER_STATE) {
cdw10 |= NVME_SET(args->seqind, LM_SEQIND);
cdw11 |= NVME_SET(args->csuuidi, LM_MIGRATION_SEND_CSUUIDI) |
NVME_SET(args->csvi, LM_MIGRATION_SEND_CSVI);
}

struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_migration_send,
.cdw10 = cdw10,
.cdw11 = cdw11,
.cdw12 = (__u32)args->offset,
.cdw13 = (__u32)(args->offset >> 32),
.cdw14 = NVME_SET(args->uidx, LM_MIGRATION_UIDX),
.cdw15 = args->numd,
.addr = (__u64)(uintptr_t)args->data,
.data_len = args->numd << 2,
.timeout_ms = args->timeout,
};

Expand All @@ -2163,3 +2253,73 @@ int nvme_dim_send(struct nvme_dim_args *args)

return nvme_submit_admin_passthru(args->fd, &cmd, args->result);
}

int nvme_lm_migration_recv(struct nvme_lm_migration_recv_args *args)
{
__u32 cdw10 = NVME_SET(args->sel, LM_SELECT);
__u32 cdw11 = NVME_SET(args->cntlid, LM_MIGRATION_CNTLID);

if (args->sel == NVME_LM_GET_CONTROLLER_STATE) {
cdw10 |= NVME_SET(args->csvi, LM_MIGRATION_RECV_CSVI);
cdw11 |= NVME_SET(args->csuuidi, LM_MIGRATION_RECV_CSUUIDI) |
NVME_SET(args->csuidxp, LM_MIGRATION_RECV_CSUIDXP);
}

struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_migration_receive,
.cdw10 = cdw10,
.cdw11 = cdw11,
.cdw12 = (__u32)args->offset,
.cdw13 = (__u32)(args->offset >> 32),
.cdw14 = NVME_SET(args->uidx, LM_MIGRATION_UIDX),
.cdw15 = args->numd,
.addr = (__u64)(uintptr_t)args->data,
.data_len = (args->numd + 1) << 2,
.timeout_ms = args->timeout,
};

if (args->args_size < sizeof(*args)) {
errno = EINVAL;
return -1;
}

return nvme_submit_admin_passthru(args->fd, &cmd, args->result);
}

int nvme_lm_set_features_ctrl_data_queue(int fd, __u16 cdqid, __u32 hp, __u32 tpt, bool etpt,
__u32 *result)
{
struct nvme_set_features_args args = {
.args_size = sizeof(args),
.fd = fd,
.fid = NVME_FEAT_FID_CTRL_DATA_QUEUE,
.nsid = NVME_NSID_NONE,
.cdw11 = cdqid | NVME_SET(tpt, LM_CTRL_DATA_QUEUE_ETPT),
.cdw12 = hp,
.cdw13 = tpt,
.save = false,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = result,
};

return nvme_set_features(&args);
}

int nvme_lm_get_features_ctrl_data_queue(int fd, __u16 cdqid,
struct nvme_lm_ctrl_data_queue_fid_data *data,
__u32 *result)
{
struct nvme_get_features_args args = {
.args_size = sizeof(args),
.fd = fd,
.fid = NVME_FEAT_FID_CTRL_DATA_QUEUE,
.nsid = NVME_NSID_NONE,
.cdw11 = cdqid,
.data = data,
.data_len = sizeof(*data),
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = result,
};

return nvme_get_features(&args);
}
64 changes: 64 additions & 0 deletions src/nvme/ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4242,4 +4242,68 @@ int nvme_zns_append(struct nvme_zns_append_args *args);
*/
int nvme_dim_send(struct nvme_dim_args *args);

/**
* nvme_lm_cdq() - Controller Data Queue - Controller Data Queue command
* @args: &struct nvme_lm_cdq_args argument structure
*
* Return: The nvme command status if a response was received (see
* &enum nvme_status_field) or -1 with errno set otherwise.)
*/
int nvme_lm_cdq(struct nvme_lm_cdq_args *args);

/**
* nvme_lm_track_send() - Track Send command
* @args: &struct nvme_lm_track_send_args argument structure
*
* Return: The nvme command status if a response was received (see
* &enum nvme_status_field) or -1 with errno set otherwise.
*/
int nvme_lm_track_send(struct nvme_lm_track_send_args *args);

/**
* nvme_lm_migration_send() - Migration Send command
* @args: &struct nvme_lm_migration_send_args argument structure
*
* Return: The nvme command status if a response was received (see
* &enum nvme_status_field) or -1 with errno set otherwise.
*/
int nvme_lm_migration_send(struct nvme_lm_migration_send_args *args);

/**
* nvme_lm_migration_recv - Migration Receive command
* @args: &struct nvme_lm_migration_rev_args argument structure
*
* Return: The nvme command status if a response was received (see
* &enum nvme_status_field) or -1 with errno set otherwise.
*/
int nvme_lm_migration_recv(struct nvme_lm_migration_recv_args *args);

/**
* nvme_lm_set_features_ctrl_data_queue - Set Controller Datea Queue feature
* @fd: File descriptor of nvme device
* @cdqid: Controller Data Queue ID (CDQID)
* @hp: Head Pointer
* @tpt: Tail Pointer Trigger
* @etpt: Enable Tail Pointer Trigger
* @result: The command completions result from CQE dword0
*
* Return: The nvme command status if a response was received (see
* &enum nvme_status_field) or -1 with errno set otherwise.
*/
int nvme_lm_set_features_ctrl_data_queue(int fd, __u16 cdqid, __u32 hp, __u32 tpt, bool etpt,
__u32 *result);

/**
* nvme_lm_get_features_ctrl_data_queue - Get Controller Data Queue feature
* @fd: File descriptor of nvme device
* @cdqid: Controller Data Queue ID (CDQID)
* @data: Get Controller Data Queue feature data
* @result: The command completions result from CQE dword0
*
* Return: The nvme command status if a response was received (see
* &enum nvme_status_field) or -1 with errno set otherwise.
*/
int nvme_lm_get_features_ctrl_data_queue(int fd, __u16 cdqid,

Check failure on line 4306 in src/nvme/ioctl.h

View workflow job for this annotation

GitHub Actions / checkpatch review

ERROR: trailing whitespace
struct nvme_lm_ctrl_data_queue_fid_data *data,
__u32 *result);
#endif /* _LIBNVME_IOCTL_H */
Loading

0 comments on commit aaa49bc

Please sign in to comment.