Skip to content
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
66 changes: 27 additions & 39 deletions libnvme/src/nvme/cmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -4383,7 +4383,7 @@ nvme_init_copy(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 sdlba,
data_len = nr * sizeof(struct nvme_copy_range_f3);
break;
default:
data_len = nr * sizeof(struct nvme_copy_range);
data_len = nr * sizeof(struct nvme_copy_range_f0);
break;
}

Expand Down Expand Up @@ -5236,44 +5236,28 @@ nvme_init_dsm_range(struct nvme_dsm_range *dsm, __u32 *ctx_attrs,
}

/**
* nvme_init_copy_range_elbt() - Constructs a copy range elbt structure
* @elbt:
* @eilbrts: Expected initial logical block reference tag
*/
static inline void
nvme_init_copy_range_elbt(__u8 *elbt, __u64 eilbrt)
{
int i;

for (i = 0; i < 8; i++)
elbt[9 - i] = (eilbrt >> (8 * i)) & 0xff;
elbt[1] = 0;
elbt[0] = 0;
}

/**
* nvme_init_copy_range() - Constructs a copy range structure
* nvme_init_copy_range_f0() - Constructs a copy range structure
* @copy: Copy range array
* @nlbs: Number of logical blocks
* @slbas: Starting LBA
* @eilbrts: Expected initial logical block reference tag
* @elbts: 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
*/
static inline void
nvme_init_copy_range(struct nvme_copy_range *copy, __u16 *nlbs,
__u64 *slbas, __u32 *eilbrts, __u32 *elbatms,
__u32 *elbats, __u16 nr)
nvme_init_copy_range_f0(struct nvme_copy_range_f0 *copy, __u16 *nlbs,
__u64 *slbas, __u32 *elbts, __u16 *elbatms,
__u16 *elbats, __u16 nr)
{
int i;

for (i = 0; i < nr; i++) {
copy[i].nlb = htole16(nlbs[i]);
copy[i].slba = htole64(slbas[i]);
copy[i].eilbrt = htole32(eilbrts[i]);
copy[i].elbatm = htole16(elbatms[i]);
copy[i].elbat = htole16(elbats[i]);
copy[i].elbt = htobe32(elbts[i]);
copy[i].elbatm = htobe16(elbatms[i]);
copy[i].elbat = htobe16(elbats[i]);
}
}

Expand All @@ -5289,17 +5273,19 @@ nvme_init_copy_range(struct nvme_copy_range *copy, __u16 *nlbs,
*/
static inline void
nvme_init_copy_range_f1(struct nvme_copy_range_f1 *copy, __u16 *nlbs,
__u64 *slbas, __u64 *eilbrts, __u32 *elbatms,
__u32 *elbats, __u16 nr)
__u64 *slbas, __u64 *eilbrts, __u16 *elbatms,
__u16 *elbats, __u16 nr)
{
int i;

memset(copy, 0, sizeof(*copy) * nr);

for (i = 0; i < nr; i++) {
copy[i].nlb = htole16(nlbs[i]);
copy[i].slba = htole64(slbas[i]);
copy[i].elbatm = htole16(elbatms[i]);
copy[i].elbat = htole16(elbats[i]);
nvme_init_copy_range_elbt(copy[i].elbt, eilbrts[i]);
*(__be64 *)&copy[i].elbt[2] = htobe64(eilbrts[i]);
copy[i].elbatm = htobe16(elbatms[i]);
copy[i].elbat = htobe16(elbats[i]);
}
}

Expand All @@ -5310,15 +5296,15 @@ nvme_init_copy_range_f1(struct nvme_copy_range_f1 *copy, __u16 *nlbs,
* @nlbs: Number of logical blocks
* @slbas: Starting LBA
* @sopts: Source options
* @eilbrts: Expected initial logical block reference tag
* @elbts: 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
*/
static inline 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,
__u32 *elbts, __u16 *elbatms, __u16 *elbats,
__u16 nr)
{
int i;
Expand All @@ -5328,9 +5314,9 @@ nvme_init_copy_range_f2(struct nvme_copy_range_f2 *copy,
copy[i].nlb = htole16(nlbs[i]);
copy[i].slba = htole64(slbas[i]);
copy[i].sopt = htole16(sopts[i]);
copy[i].eilbrt = htole32(eilbrts[i]);
copy[i].elbatm = htole16(elbatms[i]);
copy[i].elbat = htole16(elbats[i]);
copy[i].elbt = htobe32(elbts[i]);
copy[i].elbatm = htobe16(elbatms[i]);
copy[i].elbat = htobe16(elbats[i]);
}
}

Expand All @@ -5349,19 +5335,21 @@ nvme_init_copy_range_f2(struct nvme_copy_range_f2 *copy,
static inline 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,
__u64 *eilbrts, __u16 *elbatms, __u16 *elbats,
__u16 nr)
{
int i;

memset(copy, 0, sizeof(*copy) * nr);

for (i = 0; i < nr; i++) {
copy[i].snsid = htole32(snsids[i]);
copy[i].nlb = htole16(nlbs[i]);
copy[i].slba = htole64(slbas[i]);
copy[i].sopt = htole16(sopts[i]);
copy[i].elbatm = htole16(elbatms[i]);
copy[i].elbat = htole16(elbats[i]);
nvme_init_copy_range_elbt(copy[i].elbt, eilbrts[i]);
*(__be64 *)&copy[i].elbt[2] = htobe64(eilbrts[i]);
copy[i].elbatm = htobe16(elbatms[i]);
copy[i].elbat = htobe16(elbats[i]);
}
}

Expand Down
64 changes: 42 additions & 22 deletions libnvme/src/nvme/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -6436,32 +6436,41 @@ struct nvme_dsm_range {
};

/**
* struct nvme_copy_range - Copy - Source Range Entries Descriptor Format
* struct nvme_copy_range_f0 - Copy - Source Range Entries Descriptor Format 0h
* @rsvd0: Reserved
* @slba: Starting LBA
* @nlb: Number of Logical Blocks
* @rsvd18: Reserved
* @eilbrt: Expected Initial Logical Block Reference Tag /
* @cetype: Bits 3-0: Command Extension Type
* @rsvd19: Reserved
* @cev: Command Extension Value
* @rsvd22: 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 {
struct nvme_copy_range_f0 {
__u8 rsvd0[8];
__le64 slba;
__le16 nlb;
__u8 rsvd18[6];
__le32 eilbrt;
__le16 elbat;
__le16 elbatm;
__u8 cetype;
__u8 rsvd19;
__le16 cev;
__u8 rsvd22[2];
__be32 elbt;
__be16 elbat;
__be16 elbatm;
};

/**
* struct nvme_copy_range_f1 - Copy - Source Range Entries Descriptor Format 1h
* @rsvd0: Reserved
* @slba: Starting LBA
* @nlb: Number of Logical Blocks
* @rsvd18: Reserved
* @cetype: Bits 3-0: Command Extension Type
* @rsvd19: Reserved
* @cev: Command Extension Value
* @rsvd22: Reserved
* @elbt: Expected Initial Logical Block Reference Tag /
* Expected Logical Block Storage Tag
* @elbatm: Expected Logical Block Application Tag Mask
Expand All @@ -6471,10 +6480,13 @@ struct nvme_copy_range_f1 {
__u8 rsvd0[8];
__le64 slba;
__le16 nlb;
__u8 rsvd18[8];
__u8 cetype;
__u8 rsvd19;
__le16 cev;
__u8 rsvd22[4];
__u8 elbt[10];
__le16 elbat;
__le16 elbatm;
__be16 elbat;
__be16 elbatm;
};

/**
Expand All @@ -6491,9 +6503,11 @@ enum nvme_copy_range_sopt {
* @rsvd4: Reserved
* @slba: Starting LBA
* @nlb: Number of Logical Blocks
* @rsvd18: Reserved
* @cetype: Bits 3-0: Command Extension Type
* @rsvd19: Reserved
* @cev: Command Extension Value
* @sopt: Source Options
* @eilbrt: Expected Initial Logical Block Reference Tag /
* @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
Expand All @@ -6503,11 +6517,13 @@ struct nvme_copy_range_f2 {
__u8 rsvd4[4];
__le64 slba;
__le16 nlb;
__u8 rsvd18[4];
__u8 cetype;
__u8 rsvd19;
__le16 cev;
__le16 sopt;
__le32 eilbrt;
__le16 elbat;
__le16 elbatm;
__be32 elbt;
__be16 elbat;
__be16 elbatm;
};

/**
Expand All @@ -6516,8 +6532,10 @@ struct nvme_copy_range_f2 {
* @rsvd4: Reserved
* @slba: Starting LBA
* @nlb: Number of Logical Blocks
* @rsvd18: Reserved
* @cetype: Bits 3-0: Command Extension Type
* @rsvd19: Reserved
* @sopt: Source Options
* @cev: Command Extension Value
* @rsvd24: Reserved
* @elbt: Expected Initial Logical Block Reference Tag /
* Expected Logical Block Storage Tag
Expand All @@ -6529,12 +6547,14 @@ struct nvme_copy_range_f3 {
__u8 rsvd4[4];
__le64 slba;
__le16 nlb;
__u8 rsvd18[4];
__u8 cetype;
__u8 rsvd19;
__le16 cev;
__le16 sopt;
__u8 rsvd24[2];
__u8 elbt[10];
__le16 elbat;
__le16 elbatm;
__be16 elbat;
__be16 elbatm;
};

/**
Expand Down
79 changes: 69 additions & 10 deletions libnvme/test/ioctl/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -983,26 +983,26 @@ static void test_dsm(void)
static void test_copy(void)
{
__u16 nr = TEST_COPY_NR, cev = 0, dspec = 0;
int copy_size = sizeof(struct nvme_copy_range) * nr, err;
int copy_size = sizeof(struct nvme_copy_range_f0) * nr, err;
bool prinfor = false, prinfow = false, stcw = false,
stcr = false, fua = false, lr = false;
__u8 cetype = 0, dtype = 0, desfmt = 0xf;
__u64 sdlba = 0xfffff;
__u16 nlbs[TEST_COPY_NR] = { 0xa, 0xb, 0xc };
__u64 slbas[TEST_COPY_NR] = { 0x1000, 0x20000000, 0x300040000000 };
__u32 short_pi[TEST_COPY_NR] = { 0x1000, 0x20000000, 0x40000000 };
__u32 elbatms[TEST_COPY_NR] = { 0x1ff, 0x3ff, 0x3ff };
__u32 elbats[TEST_COPY_NR] = { 0x111, 0x222, 0x333 };
__u8 expected_data[sizeof(struct nvme_copy_range) * TEST_COPY_NR] = {
__u16 elbatms[TEST_COPY_NR] = { 0x1ff, 0x3ff, 0x3ff };
__u16 elbats[TEST_COPY_NR] = { 0x111, 0x222, 0x333 };
__u8 expected_data[sizeof(struct nvme_copy_range_f0) * TEST_COPY_NR] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0, 0, 0, 0,
0xa, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0x11, 1, 0xff, 1,
0xa, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 1, 0x11, 1, 0xff,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x20, 0, 0, 0, 0,
0xb, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x20, 0x22, 2, 0xff, 3,
0xb, 0, 0, 0, 0, 0, 0, 0, 0x20, 0, 0, 0, 2, 0x22, 3, 0xff,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0, 0x30, 0, 0,
0xc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0x33, 3, 0xff, 3
0xc, 0, 0, 0, 0, 0, 0, 0, 0x40, 0, 0, 0, 3, 0x33, 3, 0xff
};

_cleanup_free_ struct nvme_copy_range *copy = NULL;
_cleanup_free_ struct nvme_copy_range_f0 *copy = NULL;

copy = calloc(1, copy_size);
check(copy, "copy: ENOMEM");
Expand All @@ -1017,13 +1017,14 @@ static void test_copy(void)
((dtype & 0xf) << 20) |
((prinfow & 0xf) << 26) |
((fua & 0x1) << 30) | ((lr & 0x1) << 31),
.data_len = nr * sizeof(struct nvme_copy_range),
.data_len = nr * sizeof(struct nvme_copy_range_f0),
.in_data = expected_data,
};
struct nvme_passthru_cmd cmd;

set_mock_io_cmds(&mock_io_cmd, 1);
nvme_init_copy_range(copy, nlbs, slbas, short_pi, elbatms, elbats, nr);
nvme_init_copy_range_f0(copy, nlbs, slbas, short_pi, elbatms, elbats,
nr);
nvme_init_copy(&cmd, TEST_NSID, sdlba, nr, desfmt,
prinfor, prinfow, cetype, dtype, stcw, stcr,
fua, lr, cev, dspec, (void *)copy);
Expand All @@ -1033,6 +1034,63 @@ static void test_copy(void)
check(cmd.result == 0, "returned result %" PRIu64, (uint64_t)cmd.result);
}

static void test_copy_range_f1(void)
{
__u16 nr = TEST_COPY_NR, cev = 0, dspec = 0;
int copy_size = sizeof(struct nvme_copy_range_f1) * nr, err;
bool prinfor = false, prinfow = false, stcw = false,
stcr = false, fua = false, lr = false;
__u8 cetype = 0, dtype = 0, desfmt = 0x1;
__u64 sdlba = 0xfffff;
__u16 nlbs[TEST_COPY_NR] = { 0xa, 0xb, 0xc };
__u64 slbas[TEST_COPY_NR] = { 0x1000, 0x20000000, 0x300040000000 };
__u64 long_pi[TEST_COPY_NR] = { 0x1000, 0x20000000, 0x40000000 };
__u16 elbatms[TEST_COPY_NR] = { 0x1ff, 0x3ff, 0x3ff };
__u16 elbats[TEST_COPY_NR] = { 0x111, 0x222, 0x333 };
__u8 expected_data[sizeof(struct nvme_copy_range_f1) * TEST_COPY_NR] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0, 0, 0, 0,
0xa, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0x10, 0, 1, 0x11, 1, 0xff, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0x20, 0, 0, 0, 0, 0xb, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0x20, 0, 0, 0, 2, 0x22, 3, 0xff,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40, 0, 0x30, 0, 0,
0xc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0x40, 0, 0, 0, 3, 0x33, 3, 0xff
};

_cleanup_free_ struct nvme_copy_range_f1 *copy = NULL;

copy = calloc(1, copy_size);
check(copy, "copy: ENOMEM");

struct mock_cmd mock_io_cmd = {
.opcode = nvme_cmd_copy,
.nsid = TEST_NSID,
.cdw10 = sdlba & 0xffffffff,
.cdw11 = sdlba >> 32,
.cdw12 = ((nr - 1) & 0xff) | ((desfmt & 0xf) << 8) |
((prinfor & 0xf) << 12) |
((dtype & 0xf) << 20) |
((prinfow & 0xf) << 26) |
((fua & 0x1) << 30) | ((lr & 0x1) << 31),
.data_len = nr * sizeof(struct nvme_copy_range_f1),
.in_data = expected_data,
};
struct nvme_passthru_cmd cmd;

set_mock_io_cmds(&mock_io_cmd, 1);
nvme_init_copy_range_f1(copy, nlbs, slbas, long_pi, elbatms, elbats,
nr);
nvme_init_copy(&cmd, TEST_NSID, sdlba, nr, desfmt,
prinfor, prinfow, cetype, dtype, stcw, stcr,
fua, lr, cev, dspec, (void *)copy);
err = nvme_submit_io_passthru(test_hdl, &cmd);
end_mock_cmds();
check(err == 0, "returned error %d", err);
check(cmd.result == 0, "returned result %" PRIu64,
(uint64_t)cmd.result);
}

static void test_resv_acquire(void)
{
enum nvme_resv_rtype rtype = NVME_RESERVATION_RTYPE_EAAR;
Expand Down Expand Up @@ -1447,6 +1505,7 @@ int main(void)
RUN_TEST(verify);
RUN_TEST(dsm);
RUN_TEST(copy);
RUN_TEST(copy_range_f1);
RUN_TEST(resv_acquire);
RUN_TEST(resv_register);
RUN_TEST(resv_release);
Expand Down
Loading
Loading