Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ioctl: Live Migration #911

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Start a new section LIBNVME_1_12 and move them there.

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;
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid any holes in the struct by rearranging the members in order to try to avoid ABI breakage. The only reliable alignment is to sort the members according their natural size: 64bit, pointers, 32bit, 16bit, 8bit. This is necessary that the version trick is working. Not nice, but it is what it is. We will address this in v2 :)


/**
* 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,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid unrelated whitespace changes.

};

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);
}
Copy link
Collaborator

@igaw igaw Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rest looks okay. Just move the ioctl.c and ioctl.h changes into a separate patch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Types moved to #913

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,
struct nvme_lm_ctrl_data_queue_fid_data *data,
__u32 *result);
#endif /* _LIBNVME_IOCTL_H */
Loading