Skip to content
Open
79 changes: 49 additions & 30 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 @@ -5237,43 +5237,49 @@ 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
* @elbt: Expected logical block tags
* @eilbrt: Expected initial logical block reference tag
* @size: eilbrts size
*/
static inline void
nvme_init_copy_range_elbt(__u8 *elbt, __u64 eilbrt)
nvme_init_copy_range_elbt(__u8 *elbt, __u8 *eilbrt, int size)
{
int i;

for (i = 0; i < 8; i++)
elbt[9 - i] = (eilbrt >> (8 * i)) & 0xff;
elbt[1] = 0;
elbt[0] = 0;
for (i = 0; i < size; i++)
#if __BYTE_ORDER == __LITTLE_ENDIAN
elbt[size - 1 - i] = eilbrt[i];
#else /* __BYTE_ORDER == __LITTLE_ENDIAN */
elbt[i] = eilbrt[i];
#endif /* __BYTE_ORDER == __LITTLE_ENDIAN */
}

/**
* 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]);
nvme_init_copy_range_elbt(copy[i].elbt, (__u8 *)&elbts[i],
sizeof(elbts[i]));
nvme_init_copy_range_elbt(copy[i].elbatm, (__u8 *)&elbatms[i],
sizeof(copy[i].elbatm));
nvme_init_copy_range_elbt(copy[i].elbat, (__u8 *)&elbats[i],
sizeof(copy[i].elbat));
}
}

Expand All @@ -5289,17 +5295,22 @@ 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]);
nvme_init_copy_range_elbt(&copy[i].elbt[2], (__u8 *)&eilbrts[i],
sizeof(eilbrts[i]));
nvme_init_copy_range_elbt(copy[i].elbatm, (__u8 *)&elbatms[i],
sizeof(copy[i].elbatm));
nvme_init_copy_range_elbt(copy[i].elbat, (__u8 *)&elbats[i],
sizeof(copy[i].elbat));
}
}

Expand All @@ -5310,15 +5321,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 +5339,12 @@ 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]);
nvme_init_copy_range_elbt(copy[i].elbt, (__u8 *)&elbts[i],
sizeof(elbts[i]));
nvme_init_copy_range_elbt(copy[i].elbatm, (__u8 *)&elbatms[i],
sizeof(copy[i].elbatm));
nvme_init_copy_range_elbt(copy[i].elbat, (__u8 *)&elbats[i],
sizeof(copy[i].elbat));
}
}

Expand All @@ -5349,19 +5363,24 @@ 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]);
nvme_init_copy_range_elbt(&copy[i].elbt[2], (__u8 *)&eilbrts[i],
sizeof(eilbrts[i]));
nvme_init_copy_range_elbt(copy[i].elbatm, (__u8 *)&elbatms[i],
sizeof(copy[i].elbatm));
nvme_init_copy_range_elbt(copy[i].elbat, (__u8 *)&elbats[i],
sizeof(copy[i].elbat));
}
}

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];
__u8 elbt[4];
__u8 elbat[2];
__u8 elbatm[2];
};

/**
* 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;
__u8 elbat[2];
__u8 elbatm[2];
};

/**
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;
__u8 elbt[4];
__u8 elbat[2];
__u8 elbatm[2];
};

/**
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;
__u8 elbat[2];
__u8 elbatm[2];
};

/**
Expand Down
21 changes: 11 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 Down
14 changes: 7 additions & 7 deletions nvme.c
Original file line number Diff line number Diff line change
Expand Up @@ -7766,11 +7766,11 @@ static int copy_cmd(int argc, char **argv, struct command *acmd, struct plugin *
__u64 long_pi[256];
} eilbrts;

__u32 elbatms[256] = { 0 };
__u32 elbats[256] = { 0 };
__u16 elbatms[256] = { 0 };
__u16 elbats[256] = { 0 };

_cleanup_free_ union {
struct nvme_copy_range f0[256];
struct nvme_copy_range_f0 f0[256];
struct nvme_copy_range_f1 f1[256];
struct nvme_copy_range_f2 f2[256];
struct nvme_copy_range_f3 f3[256];
Expand Down Expand Up @@ -7876,9 +7876,9 @@ static int copy_cmd(int argc, char **argv, struct command *acmd, struct plugin *
return -EINVAL;
}

natms = argconfig_parse_comma_sep_array_u32(cfg.elbatms, elbatms,
natms = argconfig_parse_comma_sep_array_u16(cfg.elbatms, elbatms,
ARRAY_SIZE(elbatms));
nats = argconfig_parse_comma_sep_array_u32(cfg.elbats, elbats,
nats = argconfig_parse_comma_sep_array_u16(cfg.elbats, elbats,
ARRAY_SIZE(elbats));

nr = max(nb, max(ns, max(nrts, max(natms, nats))));
Expand Down Expand Up @@ -7922,8 +7922,8 @@ static int copy_cmd(int argc, char **argv, struct command *acmd, struct plugin *
eilbrts.long_pi, elbatms, elbats, nr);
break;
default:
nvme_init_copy_range(copy->f0, nlbs, slbas, eilbrts.short_pi,
elbatms, elbats, nr);
nvme_init_copy_range_f0(copy->f0, nlbs, slbas, eilbrts.short_pi,
elbatms, elbats, nr);
break;
}

Expand Down
Loading