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 #926

Merged
merged 1 commit into from
Dec 10, 2024
Merged
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
10 changes: 10 additions & 0 deletions src/libnvme.map
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
LIBNVME_1.12 {
global:
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;
};

LIBNVME_1.11 {
global:
nvme_ctrl_get_keyring;
Expand Down
33 changes: 17 additions & 16 deletions src/nvme/api-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -969,25 +969,25 @@ struct nvme_dim_args {
* @args_size: Length of structure
* @fd: File descriptor of nvme device
* @timeout: Timeout in ms
* @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.
* @mos: Management Operation Specific (MOS): This field is specific to the SEL type
* @cntlid: Controller ID: For Create CDQ, specifies the target migratable controller
* @cdqid: Controller Data Queue ID (CDQID): For Create CDQ, this field is the CDQID created
* by the controller if no error is present. For Delete CDQ, this field is the CDQID
* to delete.
* @sel: Select (SEL): This field specifies the type of management operation to perform.
* @sz: Size of CDQ in dwords
* @qt: Queue Type (QT): This field specifies the type of queue to create
* @sz: For Create CDQ, specifies the size of CDQ, in dwords
*/
struct nvme_lm_cdq_args {
__u32 *result;
void *data;
int args_size;
int fd;
__u32 timeout;
__u16 mos;
__u16 cntlid;
__u16 cdqid;
__u8 sel;
__u8 sz;
__u8 qt;
};

/**
Expand All @@ -996,19 +996,18 @@ struct nvme_lm_cdq_args {
* @args_size: Length of structure
* @fd: File descriptor of nvme device
* @timeout: Timeout in ms
* @cdqid: Controller Data Queue ID (CDQID): This field specifies the ID of the CDQ to be used
* for the logging action
* @mos: Management Operation Specific (MOS): This field is specific to the SEL type
* @cdqid: Controller Data Queue ID (CDQID)
* @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
*/
struct nvme_lm_track_send_args {
__u32 *result;
int args_size;
int fd;
__u32 timeout;
__u16 mos;
__u16 cdqid;
__u8 sel;
__u8 lact;
};

/**
Expand All @@ -1022,6 +1021,7 @@ struct nvme_lm_track_send_args {
* @fd: File descriptor of nvme device
* @timeout: Timeout in ms
* @numd: Number of Dwords (NUMD): This field specifies the number of dwords being transferred
* @mos: Management Operation Specific (MOS): This field is specific to the SEL type
* @cntlid: Controller ID: This field specifies the identifier of the controller to which the
* operation is performed.
* @csuuidi: Controller State UUID Index (CSUUIDI): A non-zero value in this field specifies the
Expand All @@ -1048,6 +1048,7 @@ struct nvme_lm_migration_send_args {
int fd;
__u32 timeout;
__u32 numd;
__u16 mos;
__u16 cntlid;
__u16 csuuidi;
__u8 sel;
Expand All @@ -1068,7 +1069,9 @@ struct nvme_lm_migration_send_args {
* @args_size: Length of structure
* @fd: File descriptor of nvme device
* @timeout: Timeout in ms
* @numdl: Number of Dwords Lower (NMUDL): This field specifies the number of dwords to return.
* @numd: Number of Dwords (NUMD): This field specifies the number of dwords to return. This
* is a 0's based value.
* @mos: Management Operation Specific (MOS): This field is specific to the SEL type
* @cntlid: Controller ID: This field specifies the identifier of the controller to which the
* operation is performed.
* @csuuidi: Controller State UUID Index (CSUUIDI): A non-zero value in this field specifies the
Expand All @@ -1078,9 +1081,7 @@ struct nvme_lm_migration_send_args {
* @uidx: UUID Index (UIDX): If this field is set to a non-zero value, then the value of this
* field is the index of a UUID in the UUID List (refer to Figure 320) that is used by
* the command.
* @csvi: Controller State Version Index (CSVI): A non-zero value in this field specifies the
* index to a specific entry in the NVMe Controller State Version list of the Supported
* Controller State Formats data structure.
* @csuidxp: Controller State UUID Index Parameter (CSUIDXP): This field is vendor specific.
*/
struct nvme_lm_migration_recv_args {
__u64 offset;
Expand All @@ -1090,11 +1091,11 @@ struct nvme_lm_migration_recv_args {
int fd;
__u32 timeout;
__u32 numd;
__u16 mos;
__u16 cntlid;
__u16 csuuidi;
__u8 sel;
__u8 uidx;
__u8 csvi;
__u8 csuidxp;
};

Expand Down
171 changes: 171 additions & 0 deletions src/nvme/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2163,3 +2163,174 @@ int nvme_dim_send(struct nvme_dim_args *args)

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_CDQ_SEL) |
NVME_SET(args->mos, LM_CDQ_MOS);
__u32 cdw11 = 0, data_len = 0;
int err;

if (args->sel == NVME_LM_SEL_CREATE_CDQ) {
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_SEL_DELETE_CDQ) {
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_TRACK_SEND_SEL) |
NVME_SET(args->mos, LM_TRACK_SEND_MOS);

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_MIGRATION_SEND_SEL) |
NVME_SET(args->mos, LM_MIGRATION_SEND_MOS);
__u32 cdw11 = 0;

if (args->sel == NVME_LM_SEL_SUSPEND) {
cdw11 = NVME_SET(args->stype, LM_STYPE) |
NVME_SET(args->cntlid, LM_SUSPEND_CNTLID);
if (args->dudmq)
cdw11 |= NVME_LM_DUDMQ;
} else if (args->sel == NVME_LM_SEL_RESUME) {
cdw11 = NVME_SET(args->cntlid, LM_RESUME_CNTLID);
} else if (args->sel == NVME_LM_SEL_SET_CONTROLLER_STATE) {
cdw11 = NVME_SET(args->csuuidi, LM_SET_CONTROLLER_STATE_CSUUIDI) |
NVME_SET(args->csvi, LM_SET_CONTROLLER_STATE_CSVI) |
NVME_SET(args->cntlid, LM_SET_CONTROLLER_STATE_CNTLID);
}

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_SEND_UIDX),
.cdw15 = args->numd,
.addr = (__u64)(uintptr_t)args->data,
.data_len = args->numd << 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_migration_recv(struct nvme_lm_migration_recv_args *args)
{
__u32 cdw10 = NVME_SET(args->sel, LM_MIGRATION_RECV_SEL) |
NVME_SET(args->mos, LM_MIGRATION_RECV_MOS);
__u32 cdw11 = 0, data_len = 0;

if (args->sel == NVME_LM_SEL_GET_CONTROLLER_STATE) {
cdw11 = NVME_SET(args->csuidxp, LM_GET_CONTROLLER_STATE_CSUIDXP) |
NVME_SET(args->csuuidi, LM_GET_CONTROLLER_STATE_CSUUIDI) |
NVME_SET(args->cntlid, LM_GET_CONTROLLER_STATE_CNTLID);
data_len = (args->numd + 1 /*0's based*/) << 2;
}

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_RECV_UIDX),
.cdw15 = args->numd,
.addr = (__u64)(uintptr_t)args->data,
.data_len = 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_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 @@ -4258,4 +4258,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