Skip to content

Commit

Permalink
nvme-copy: add cross-namespace copy formats, status codes, ONCS bits
Browse files Browse the repository at this point in the history
Add support for NVMe TP4130 ("Cross-Namespace Copy"):
- Add Copy Descriptor Formats 2h and 3h
- Add new status codes for Copy: Incompatible Namespace or Format, Fast
  Copy Not Possible, Overlapping I/O Range, and Insufficient Resources
- Add two new ONCS bits NVMCSA and NVMAFC
  • Loading branch information
jgu-pure committed Oct 25, 2023
1 parent da8c28e commit ebd7de7
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 5 deletions.
2 changes: 2 additions & 0 deletions src/libnvme.map
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ LIBNVME_1_6 {
nvme_set_root;
nvme_subsystem_get_iopolicy;
nvme_subsystem_release_fds;
nvme_init_copy_range_f2;
nvme_init_copy_range_f3;
};

LIBNVME_1_5 {
Expand Down
4 changes: 4 additions & 0 deletions src/nvme/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1976,6 +1976,10 @@ int nvme_copy(struct nvme_copy_args *args)

if (args->format == 1)
data_len = args->nr * sizeof(struct nvme_copy_range_f1);
else if (args->format == 2)
data_len = args->nr * sizeof(struct nvme_copy_range_f2);
else if (args->format == 3)
data_len = args->nr * sizeof(struct nvme_copy_range_f3);
else
data_len = args->nr * sizeof(struct nvme_copy_range);

Expand Down
89 changes: 89 additions & 0 deletions src/nvme/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1506,6 +1506,14 @@ enum nvme_id_ctrl_cqes {
* the Verify command.
* @NVME_CTRL_ONCS_COPY: If set, then the controller supports
* the copy command.
* @NVME_CTRL_ONCS_COPY_SINGLE_ATOMICITY: If set, then the write portion of a
* Copy command is performed as a single
* write command to which the same
* atomicity requirements that apply to
* a write command apply.
* @NVME_CTRL_ONCS_ALL_FAST_COPY: If set, then all copy operations for
* the Copy command are fast copy
* operations.
*/
enum nvme_id_ctrl_oncs {
NVME_CTRL_ONCS_COMPARE = 1 << 0,
Expand All @@ -1517,6 +1525,8 @@ enum nvme_id_ctrl_oncs {
NVME_CTRL_ONCS_TIMESTAMP = 1 << 6,
NVME_CTRL_ONCS_VERIFY = 1 << 7,
NVME_CTRL_ONCS_COPY = 1 << 8,
NVME_CTRL_ONCS_COPY_SINGLE_ATOMICITY = 1 << 9,
NVME_CTRL_ONCS_ALL_FAST_COPY = 1 << 10,
};

/**
Expand Down Expand Up @@ -4802,6 +4812,66 @@ struct nvme_copy_range_f1 {
__le16 elbatm;
};

/**
* enum nvme_copy_range_sopt - NVMe Copy Range Source Options
* @NVME_COPY_SOPT_FCO: NVMe Copy Source Option Fast Copy Only
*/
enum nvme_copy_range_sopt {
NVME_COPY_SOPT_FCO = 1 << 15,
};

/**
* struct nvme_copy_range_f2 - Copy - Source Range Entries Descriptor Format 2h
* @snsid: Source Namespace Identifier
* @rsvd4: Reserved
* @slba: Starting LBA
* @nlb: Number of Logical Blocks
* @rsvd18: Reserved
* @sopt: Source Options
* @eilbrt: Expected Initial Logical Block Reference Tag /
* Expected Logical Block Storage Tag
* @elbatm: Expected Logical Block Application Tag Mask
* @elbat: Expected Logical Block Application Tag
*/
struct nvme_copy_range_f2 {
__le32 snsid;
__u8 rsvd4[4];
__le64 slba;
__le16 nlb;
__u8 rsvd18[4];
__le16 sopt;
__le32 eilbrt;
__le16 elbat;
__le16 elbatm;
};

/**
* struct nvme_copy_range_f3 - Copy - Source Range Entries Descriptor Format 3h
* @snsid: Source Namespace Identifier
* @rsvd4: Reserved
* @slba: Starting LBA
* @nlb: Number of Logical Blocks
* @rsvd18: Reserved
* @sopt: Source Options
* @rsvd24: Reserved
* @elbt: Expected Initial Logical Block Reference Tag /
* Expected Logical Block Storage Tag
* @elbatm: Expected Logical Block Application Tag Mask
* @elbat: Expected Logical Block Application Tag
*/
struct nvme_copy_range_f3 {
__le32 snsid;
__u8 rsvd4[4];
__le64 slba;
__le16 nlb;
__u8 rsvd18[4];
__le16 sopt;
__u8 rsvd24[2];
__u8 elbt[10];
__le16 elbat;
__le16 elbatm;
};

/**
* struct nvme_registered_ctrl - Registered Controller Data Structure
* @cntlid: Controller ID
Expand Down Expand Up @@ -6254,6 +6324,21 @@ struct nvme_mi_vpd_hdr {
* @NVME_SC_INVALID_PI: Invalid Protection Information
* @NVME_SC_READ_ONLY: Attempted Write to Read Only Range
* @NVME_SC_CMD_SIZE_LIMIT_EXCEEDED: Command Size Limit Exceeded
* @NVME_SC_INCOMPATIBLE_NS: Incompatible Namespace or Format: At
* least one source namespace and the
* destination namespace have incompatible
* formats.
* @NVME_SC_FAST_COPY_NOT_POSSIBLE: Fast Copy Not Possible: The Fast Copy
* Only (FCO) bit was set to ‘1’ in a Source
* Range entry and the controller was not
* able to use fast copy operations to copy
* the specified data.
* @NVME_SC_OVERLAPPING_IO_RANGE: Overlapping I/O Range: A source logical
* block range overlaps the destination
* logical block range.
* @NVME_SC_INSUFFICIENT_RESOURCES: Insufficient Resources: A resource
* shortage prevented the controller from
* performing the requested copy.
* @NVME_SC_CONNECT_FORMAT: Incompatible Format: The NVM subsystem
* does not support the record format
* specified by the host.
Expand Down Expand Up @@ -6499,6 +6584,10 @@ enum nvme_status_field {
NVME_SC_INVALID_PI = 0x81,
NVME_SC_READ_ONLY = 0x82,
NVME_SC_CMD_SIZE_LIMIT_EXCEEDED = 0x83,
NVME_SC_INCOMPATIBLE_NS = 0x85,
NVME_SC_FAST_COPY_NOT_POSSIBLE = 0x86,
NVME_SC_OVERLAPPING_IO_RANGE = 0x87,
NVME_SC_INSUFFICIENT_RESOURCES = 0x89,

/*
* I/O Command Set Specific - Fabrics commands:
Expand Down
56 changes: 51 additions & 5 deletions src/nvme/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ static const char * const nvm_status[] = {
[NVME_SC_INVALID_PI] = "Invalid Protection Information: The command's Protection Information Field settings are invalid for the namespace's Protection Information format",
[NVME_SC_READ_ONLY] = "Attempted Write to Read Only Range: The LBA range specified contains read-only blocks",
[NVME_SC_CMD_SIZE_LIMIT_EXCEEDED] = "Command Size Limit Exceeded",
[NVME_SC_INCOMPATIBLE_NS] = "Incompatible Namespace or Format",
[NVME_SC_FAST_COPY_NOT_POSSIBLE] = "Fast Copy Not Possible",
[NVME_SC_OVERLAPPING_IO_RANGE] = "Overlapping I/O Range",
[NVME_SC_INSUFFICIENT_RESOURCES] = "Insufficient Resources",
[NVME_SC_ZNS_INVALID_OP_REQUEST] = "Invalid Zone Operation Request: The operation requested is invalid",
[NVME_SC_ZNS_ZRWA_RESOURCES_UNAVAILABLE] = "ZRWA Resources Unavailable: No ZRWAs are available",
[NVME_SC_ZNS_BOUNDARY_ERROR] = "Zoned Boundary Error: Invalid Zone Boundary crossing",
Expand Down Expand Up @@ -386,6 +390,15 @@ const char *nvme_status_to_string(int status, bool fabrics)
return s;
}

static inline void nvme_init_copy_range_elbt(__u8 *elbt, __u64 eilbrt)
{
int j;
for (j = 0; j < 8; j++)
elbt[9 - j] = (eilbrt >> (8 * j)) & 0xff;
elbt[1] = 0;
elbt[0] = 0;
}

void nvme_init_copy_range(struct nvme_copy_range *copy, __u16 *nlbs,
__u64 *slbas, __u32 *eilbrts, __u32 *elbatms,
__u32 *elbats, __u16 nr)
Expand All @@ -405,20 +418,53 @@ void nvme_init_copy_range_f1(struct nvme_copy_range_f1 *copy, __u16 *nlbs,
__u64 *slbas, __u64 *eilbrts, __u32 *elbatms,
__u32 *elbats, __u16 nr)
{
int i, j;
int i;

for (i = 0; i < nr; i++) {
copy[i].nlb = cpu_to_le16(nlbs[i]);
copy[i].slba = cpu_to_le64(slbas[i]);
copy[i].elbatm = cpu_to_le16(elbatms[i]);
copy[i].elbat = cpu_to_le16(elbats[i]);
for (j = 0; j < 8; j++)
copy[i].elbt[9 - j] = (eilbrts[i] >> (8 * j)) & 0xff;
copy[i].elbt[1] = 0;
copy[i].elbt[0] = 0;
nvme_init_copy_range_elbt(copy[i].elbt, eilbrts[i]);
}
}

void nvme_init_copy_range_f2(struct nvme_copy_range_f2 *copy, __u32 *snsids,
__u16 *nlbs, __u64 *slbas, __u16 *sopts,
__u32 *eilbrts, __u32 *elbatms, __u32 *elbats,
__u16 nr)
{
int i;

for (i = 0; i < nr; i++) {
copy[i].snsid = cpu_to_le32(snsids[i]);
copy[i].nlb = cpu_to_le16(nlbs[i]);
copy[i].slba = cpu_to_le64(slbas[i]);
copy[i].sopt = cpu_to_le16(sopts[i]);
copy[i].eilbrt = cpu_to_le32(eilbrts[i]);
copy[i].elbatm = cpu_to_le16(elbatms[i]);
copy[i].elbat = cpu_to_le16(elbats[i]);
}
}

void nvme_init_copy_range_f3(struct nvme_copy_range_f3 *copy, __u32 *snsids,
__u16 *nlbs, __u64 *slbas, __u16 *sopts,
__u64 *eilbrts, __u32 *elbatms, __u32 *elbats,
__u16 nr)
{
int i;

for (i = 0; i < nr; i++) {
copy[i].snsid = cpu_to_le32(snsids[i]);
copy[i].nlb = cpu_to_le16(nlbs[i]);
copy[i].slba = cpu_to_le64(slbas[i]);
copy[i].sopt = cpu_to_le16(sopts[i]);
copy[i].elbatm = cpu_to_le16(elbatms[i]);
copy[i].elbat = cpu_to_le16(elbats[i]);
nvme_init_copy_range_elbt(copy[i].elbt, eilbrts[i]);
}
}

void nvme_init_dsm_range(struct nvme_dsm_range *dsm, __u32 *ctx_attrs,
__u32 *llbas, __u64 *slbas, __u16 nr_ranges)
{
Expand Down
34 changes: 34 additions & 0 deletions src/nvme/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,40 @@ void nvme_init_copy_range_f1(struct nvme_copy_range_f1 *copy, __u16 *nlbs,
__u64 *slbas, __u64 *eilbrts, __u32 *elbatms,
__u32 *elbats, __u16 nr);

/**
* nvme_init_copy_range_f2() - Constructs a copy range f2 structure
* @copy: Copy range array
* @snsids: Source namespace identifier
* @nlbs: Number of logical blocks
* @slbas: Starting LBA
* @sopts: Source options
* @eilbrts: Expected initial logical block reference tag
* @elbatms: Expected logical block application tag mask
* @elbats: Expected logical block application tag
* @nr: Number of descriptors to construct
*/
void nvme_init_copy_range_f2(struct nvme_copy_range_f2 *copy, __u32 *snsids,
__u16 *nlbs, __u64 *slbas, __u16 *sopts,
__u32 *eilbrts, __u32 *elbatms, __u32 *elbats,
__u16 nr);

/**
* nvme_init_copy_range_f3() - Constructs a copy range f3 structure
* @copy: Copy range array
* @snsids: Source namespace identifier
* @nlbs: Number of logical blocks
* @slbas: Starting LBA
* @sopts: Source options
* @eilbrts: Expected initial logical block reference tag
* @elbatms: Expected logical block application tag mask
* @elbats: Expected logical block application tag
* @nr: Number of descriptors to construct
*/
void nvme_init_copy_range_f3(struct nvme_copy_range_f3 *copy, __u32 *snsids,
__u16 *nlbs, __u64 *slbas, __u16 *sopts,
__u64 *eilbrts, __u32 *elbatms, __u32 *elbats,
__u16 nr);

/**
* nvme_get_feature_length() - Retreive the command payload length for a
* specific feature identifier
Expand Down

0 comments on commit ebd7de7

Please sign in to comment.