From: Nitesh Shetty <nj.shetty@samsung.com>
To: Chaitanya Kulkarni <chaitanyak@nvidia.com>
Cc: "linux-nvme@lists.infradead.org" <linux-nvme@lists.infradead.org>,
"dm-devel@redhat.com" <dm-devel@redhat.com>,
Christoph Hellwig <hch@lst.de>, Alasdair Kergon <agk@redhat.com>,
Sagi Grimberg <sagi@grimberg.me>,
"gost.dev@samsung.com" <gost.dev@samsung.com>,
"nitheshshetty@gmail.com" <nitheshshetty@gmail.com>,
James Smart <james.smart@broadcom.com>,
Anuj Gupta <anuj20.g@samsung.com>,
Mike Snitzer <snitzer@kernel.org>,
"ming.lei@redhat.com" <ming.lei@redhat.com>,
"linux-block@vger.kernel.org" <linux-block@vger.kernel.org>,
"dlemoal@kernel.org" <dlemoal@kernel.org>,
Keith Busch <kbusch@kernel.org>,
"bvanassche@acm.org" <bvanassche@acm.org>,
Jens Axboe <axboe@kernel.dk>,
Christian Brauner <brauner@kernel.org>,
"joshi.k@samsung.com" <joshi.k@samsung.com>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"linux-fsdevel@vger.kernel.org" <linux-fsdevel@vger.kernel.org>,
Alexander Viro <viro@zeniv.linux.org.uk>
Subject: Re: [dm-devel] [PATCH v9 6/9] nvmet: add copy command support for bdev and file ns
Date: Tue, 25 Apr 2023 13:56:34 +0530 [thread overview]
Message-ID: <20230425082634.GA23150@green245> (raw)
In-Reply-To: <77ed029d-4058-b7f9-8dd1-6bc4b1c2b0dc@nvidia.com>
[-- Attachment #1: Type: text/plain, Size: 12391 bytes --]
On Tue, Apr 25, 2023 at 06:36:51AM +0000, Chaitanya Kulkarni wrote:
> On 4/11/23 01:10, Anuj Gupta wrote:
> > From: Nitesh Shetty <nj.shetty@samsung.com>
> >
> > Add support for handling target command on target.
>
> what is target command ?
>
> command that you have added is :nvme_cmd_copy
>
acked. It was supposed to be nvme_cmd_copy.
> > For bdev-ns we call into blkdev_issue_copy, which the block layer
> > completes by a offloaded copy request to backend bdev or by emulating the
> > request.
> >
> > For file-ns we call vfs_copy_file_range to service our request.
> >
> > Currently target always shows copy capability by setting
> > NVME_CTRL_ONCS_COPY in controller ONCS.
>
> there is nothing mentioned about target/loop.c in commit log ?
>
acked, will add the description for loop device.
> > Signed-off-by: Nitesh Shetty <nj.shetty@samsung.com>
> > Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
> > ---
> > drivers/nvme/target/admin-cmd.c | 9 +++--
> > drivers/nvme/target/io-cmd-bdev.c | 58 +++++++++++++++++++++++++++++++
> > drivers/nvme/target/io-cmd-file.c | 52 +++++++++++++++++++++++++++
> > drivers/nvme/target/loop.c | 6 ++++
> > drivers/nvme/target/nvmet.h | 1 +
> > 5 files changed, 124 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
> > index 80099df37314..978786ec6a9e 100644
> > --- a/drivers/nvme/target/admin-cmd.c
> > +++ b/drivers/nvme/target/admin-cmd.c
> > @@ -433,8 +433,7 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
> > id->nn = cpu_to_le32(NVMET_MAX_NAMESPACES);
> > id->mnan = cpu_to_le32(NVMET_MAX_NAMESPACES);
> > id->oncs = cpu_to_le16(NVME_CTRL_ONCS_DSM |
> > - NVME_CTRL_ONCS_WRITE_ZEROES);
> > -
> > + NVME_CTRL_ONCS_WRITE_ZEROES | NVME_CTRL_ONCS_COPY);
> > /* XXX: don't report vwc if the underlying device is write through */
> > id->vwc = NVME_CTRL_VWC_PRESENT;
> >
> > @@ -536,6 +535,12 @@ static void nvmet_execute_identify_ns(struct nvmet_req *req)
> >
> > if (req->ns->bdev)
> > nvmet_bdev_set_limits(req->ns->bdev, id);
> > + else {
> > + id->msrc = (u8)to0based(BIO_MAX_VECS - 1);
> > + id->mssrl = cpu_to_le16(BIO_MAX_VECS <<
> > + (PAGE_SHIFT - SECTOR_SHIFT));
> > + id->mcl = cpu_to_le32(le16_to_cpu(id->mssrl));
> > + }
> >
> > /*
> > * We just provide a single LBA format that matches what the
> > diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c
> > index c2d6cea0236b..0af273097aa4 100644
> > --- a/drivers/nvme/target/io-cmd-bdev.c
> > +++ b/drivers/nvme/target/io-cmd-bdev.c
> > @@ -46,6 +46,19 @@ void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id)
> > id->npda = id->npdg;
> > /* NOWS = Namespace Optimal Write Size */
> > id->nows = to0based(bdev_io_opt(bdev) / bdev_logical_block_size(bdev));
> > +
> > + /*Copy limits*/
>
> above comment doesn't make any sense ...
>
acked, will remove it next version.
> > + if (bdev_max_copy_sectors(bdev)) {
> > + id->msrc = id->msrc;
> > + id->mssrl = cpu_to_le16((bdev_max_copy_sectors(bdev) <<
> > + SECTOR_SHIFT) / bdev_logical_block_size(bdev));
> > + id->mcl = cpu_to_le32(id->mssrl);
> > + } else {
> > + id->msrc = (u8)to0based(BIO_MAX_VECS - 1);
> > + id->mssrl = cpu_to_le16((BIO_MAX_VECS << PAGE_SHIFT) /
> > + bdev_logical_block_size(bdev));
> > + id->mcl = cpu_to_le32(id->mssrl);
> > + }
> > }
> >
> > void nvmet_bdev_ns_disable(struct nvmet_ns *ns)
> > @@ -184,6 +197,19 @@ static void nvmet_bio_done(struct bio *bio)
> > nvmet_req_bio_put(req, bio);
> > }
> >
> > +static void nvmet_bdev_copy_end_io(void *private, int comp_len)
> > +{
> > + struct nvmet_req *req = (struct nvmet_req *)private;
> > +
> > + if (comp_len == req->copy_len) {
> > + req->cqe->result.u32 = cpu_to_le32(1);
> > + nvmet_req_complete(req, errno_to_nvme_status(req, 0));
> > + } else {
> > + req->cqe->result.u32 = cpu_to_le32(0);
> > + nvmet_req_complete(req, blk_to_nvme_status(req, BLK_STS_IOERR));
> > + }
> > +}
> > +
>
> please reduce calls for nvmet_req_complete().
>
> +static void nvmet_bdev_copy_end_io(void *private, int comp_len)
> +{
> + struct nvmet_req *req = (struct nvmet_req *)private;
> + u16 status;
> +
> + if (comp_len == req->copy_len) {
> + req->cqe->result.u32 = cpu_to_le32(1);
> + status = errno_to_nvme_status(req, 0));
> + } else {
> + req->cqe->result.u32 = cpu_to_le32(0);
> + status = blk_to_nvme_status(req, BLK_STS_IOERR));
> + }
> + nvmet_req_complete(req, status);
> +}
> +
>
makes sense, will modify this snippet.
> > #ifdef CONFIG_BLK_DEV_INTEGRITY
> > static int nvmet_bdev_alloc_bip(struct nvmet_req *req, struct bio *bio,
> > struct sg_mapping_iter *miter)
> > @@ -450,6 +476,34 @@ static void nvmet_bdev_execute_write_zeroes(struct nvmet_req *req)
> > }
> > }
> >
> > +/* At present we handle only one range entry */
>
> please add explanation why ...
>
Because we aligned copy offload similar to copy_file_range in out recent
revisions, discarding multi range support.
Sure we will update comments to reflect the same.
> > +static void nvmet_bdev_execute_copy(struct nvmet_req *req)
> > +{
> > + struct nvme_copy_range range;
> > + struct nvme_command *cmnd = req->cmd;
>
> don't use cmnd, cmd is used everywhere and matches req->cmd,
> applies to everywhere in this patch...
>
acked
> > + int ret;
>
> wrong return type is should be u16 since nvmet_copy_from_sgl()
> returns u16 if I remember correctly.
>
> > +
> > +
>
acked
> no extra white line between declaration and body of functions
>
acked
> > + ret = nvmet_copy_from_sgl(req, 0, &range, sizeof(range));
> > + if (ret)
> > + goto out;
> > +
> > + ret = blkdev_issue_copy(req->ns->bdev,
> > + le64_to_cpu(cmnd->copy.sdlba) << req->ns->blksize_shift,
> > + req->ns->bdev,
> > + le64_to_cpu(range.slba) << req->ns->blksize_shift,
> > + (le16_to_cpu(range.nlb) + 1) << req->ns->blksize_shift,
> > + nvmet_bdev_copy_end_io, (void *)req, GFP_KERNEL);
> > + if (ret) {
> > + req->cqe->result.u32 = cpu_to_le32(0);
> > + nvmet_req_complete(req, blk_to_nvme_status(req, BLK_STS_IOERR));
> > + }
> > +
> > + return;
> > +out:
> > + nvmet_req_complete(req, errno_to_nvme_status(req, ret));
> > +}
> > +
>
> again one call to nvmet_req_complete() can do the same job.
> consider following totally untested :-
> /* TODO: add detailed comment here why you support one range ? */
> static void nvmet_bdev_execute_copy(struct nvmet_req *req)
> {
> u32 blkshift = req->ns->blksize_shift;
> struct nvme_command *cmnd = req->cmd;
> struct nvme_copy_range range;
> u16 status;
>
> status = nvmet_copy_from_sgl(req, 0, &range, sizeof(range));
> if (status) {
> goto out;
> }
>
> ret = blkdev_issue_copy(req->ns->bdev,
> le64_to_cpu(cmnd->copy.sdlba) << blkshift,
> req->ns->bdev,
> le64_to_cpu(range.slba) << blksize_shift,
> (le16_to_cpu(range.nlb) + 1) <<
> blksize_shift,
> nvmet_bdev_copy_end_io, (void *)req,
> GFP_KERNEL);
> if (ret) {
> req->cqe->result.u32 = cpu_to_le32(0);
> status = blk_to_nvme_status(req, BLK_STS_IOERR);
> out:
> nvmet_req_complete(req, status);
> }
> }
>
acked, thanks for sharing the snippet
> > u16 nvmet_bdev_parse_io_cmd(struct nvmet_req *req)
> > {
> > switch (req->cmd->common.opcode) {
> > @@ -468,6 +522,10 @@ u16 nvmet_bdev_parse_io_cmd(struct nvmet_req *req)
> > case nvme_cmd_write_zeroes:
> > req->execute = nvmet_bdev_execute_write_zeroes;
> > return 0;
> > + case nvme_cmd_copy:
> > + req->execute = nvmet_bdev_execute_copy;
> > + return 0;
> > +
> > default:
> > return nvmet_report_invalid_opcode(req);
> > }
> > diff --git a/drivers/nvme/target/io-cmd-file.c b/drivers/nvme/target/io-cmd-file.c
> > index 2d068439b129..69f198ecec77 100644
> > --- a/drivers/nvme/target/io-cmd-file.c
> > +++ b/drivers/nvme/target/io-cmd-file.c
> > @@ -322,6 +322,49 @@ static void nvmet_file_dsm_work(struct work_struct *w)
> > }
> > }
> >
> > +static void nvmet_file_copy_work(struct work_struct *w)
> > +{
> > + struct nvmet_req *req = container_of(w, struct nvmet_req, f.work);
> > + int nr_range;
> > + loff_t pos;
> > + struct nvme_command *cmnd = req->cmd;
> > + int ret = 0, len = 0, src, id;
>
> reverse tree style for declaration ...
>
acked
> > +
> > + nr_range = cmnd->copy.nr_range + 1;
> > + pos = le64_to_cpu(req->cmd->copy.sdlba) << req->ns->blksize_shift;
>
> you have a cmd variable above and you are still using req->cmd ?
> why create a variable on stack then ? u don't need that variable
> anyways...
>
acked
> > + if (unlikely(pos + req->transfer_len > req->ns->size)) {
> > + nvmet_req_complete(req, errno_to_nvme_status(req, -ENOSPC));
> > + return;
> > + }
> > +
> > + for (id = 0 ; id < nr_range; id++) {
> > + struct nvme_copy_range range;
> > +
> > + ret = nvmet_copy_from_sgl(req, id * sizeof(range), &range,
> > + sizeof(range));
> > + if (ret)
> > + goto out;
> > +
> > + len = (le16_to_cpu(range.nlb) + 1) << (req->ns->blksize_shift);
> > + src = (le64_to_cpu(range.slba) << (req->ns->blksize_shift));
> > + ret = vfs_copy_file_range(req->ns->file, src, req->ns->file,
> > + pos, len, 0);
>
> 5th paramaeter to vfs_copy_file_range() is size_t you have used int
> for len ? also
> vfs_copy_file_range() returns ssize_t you are catching it in int ?
>
acked, will change it to ssize_t.
> > +out:
> > + if (ret != len) {
> > + pos += ret;
> > + req->cqe->result.u32 = cpu_to_le32(id);
> > + nvmet_req_complete(req, ret < 0 ?
> > + errno_to_nvme_status(req, ret) :
> > + errno_to_nvme_status(req, -EIO));
>
> again plz don't add multiple nvmet_req_complete() calls
>
acked
> > + return;
> > +
> > + } else
> > + pos += len;
> > + }
> > +
> > + nvmet_req_complete(req, 0);
> > +
> > +}
>
> wrt above comments consider following totally untested :-
>
> static void nvmet_file_copy_work(struct work_struct *w)
> {
> struct nvmet_req *req = container_of(w, struct nvmet_req, f.work);
> int nr_range = req->cmd->copy.nr_range + 1;
> u16 status = 0;
> int src, id;
> ssize_t ret;
> size_t len;
> loff_t pos;
>
> pos = le64_to_cpu(req->cmd->copy.sdlba) << req->ns->blksize_shift;
> if (unlikely(pos + req->transfer_len > req->ns->size)) {
> nvmet_req_complete(req, errno_to_nvme_status(req,
> -ENOSPC));
> return;
> }
>
> for (id = 0 ; id < nr_range; id++) {
> struct nvme_copy_range range;
>
> status = nvmet_copy_from_sgl(req, id * sizeof(range),
> &range,
> sizeof(range));
> if (status)
> goto out;
>
> src = (le64_to_cpu(range.slba) <<
> (req->ns->blksize_shift));
> len = (le16_to_cpu(range.nlb) + 1) <<
> (req->ns->blksize_shift);
>
> ret = vfs_copy_file_range(req->ns->file, src,
> req->ns->file,
> pos, len, 0);
>
> if (ret != len) {
> req->cqe->result.u32 = cpu_to_le32(id);
> if (ret < 0)
> status = errno_to_nvme_status(req, ret);
> else
> status = errno_to_nvme_status(req, -EIO);
> goto out;
> }
> pos += ret;
> }
> out:
> nvmet_req_complete(req, status);
> }
>
>
Thanks for snippet will update this in next version.
--
Nitesh Shetty
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
[-- Attachment #3: Type: text/plain, Size: 98 bytes --]
--
dm-devel mailing list
dm-devel@redhat.com
https://listman.redhat.com/mailman/listinfo/dm-devel
WARNING: multiple messages have this Message-ID (diff)
From: Nitesh Shetty <nj.shetty@samsung.com>
To: Chaitanya Kulkarni <chaitanyak@nvidia.com>
Cc: Anuj Gupta <anuj20.g@samsung.com>, Jens Axboe <axboe@kernel.dk>,
Alasdair Kergon <agk@redhat.com>,
Mike Snitzer <snitzer@kernel.org>,
"dm-devel@redhat.com" <dm-devel@redhat.com>,
Keith Busch <kbusch@kernel.org>, Christoph Hellwig <hch@lst.de>,
Sagi Grimberg <sagi@grimberg.me>,
James Smart <james.smart@broadcom.com>,
Alexander Viro <viro@zeniv.linux.org.uk>,
Christian Brauner <brauner@kernel.org>,
"bvanassche@acm.org" <bvanassche@acm.org>,
"hare@suse.de" <hare@suse.de>,
"ming.lei@redhat.com" <ming.lei@redhat.com>,
"dlemoal@kernel.org" <dlemoal@kernel.org>,
"joshi.k@samsung.com" <joshi.k@samsung.com>,
"nitheshshetty@gmail.com" <nitheshshetty@gmail.com>,
"gost.dev@samsung.com" <gost.dev@samsung.com>,
"linux-block@vger.kernel.org" <linux-block@vger.kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"linux-nvme@lists.infradead.org" <linux-nvme@lists.infradead.org>,
"linux-fsdevel@vger.kernel.org" <linux-fsdevel@vger.kernel.org>
Subject: Re: [PATCH v9 6/9] nvmet: add copy command support for bdev and file ns
Date: Tue, 25 Apr 2023 13:56:34 +0530 [thread overview]
Message-ID: <20230425082634.GA23150@green245> (raw)
In-Reply-To: <77ed029d-4058-b7f9-8dd1-6bc4b1c2b0dc@nvidia.com>
[-- Attachment #1: Type: text/plain, Size: 12011 bytes --]
On Tue, Apr 25, 2023 at 06:36:51AM +0000, Chaitanya Kulkarni wrote:
> On 4/11/23 01:10, Anuj Gupta wrote:
> > From: Nitesh Shetty <nj.shetty@samsung.com>
> >
> > Add support for handling target command on target.
>
> what is target command ?
>
> command that you have added is :nvme_cmd_copy
>
acked. It was supposed to be nvme_cmd_copy.
> > For bdev-ns we call into blkdev_issue_copy, which the block layer
> > completes by a offloaded copy request to backend bdev or by emulating the
> > request.
> >
> > For file-ns we call vfs_copy_file_range to service our request.
> >
> > Currently target always shows copy capability by setting
> > NVME_CTRL_ONCS_COPY in controller ONCS.
>
> there is nothing mentioned about target/loop.c in commit log ?
>
acked, will add the description for loop device.
> > Signed-off-by: Nitesh Shetty <nj.shetty@samsung.com>
> > Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
> > ---
> > drivers/nvme/target/admin-cmd.c | 9 +++--
> > drivers/nvme/target/io-cmd-bdev.c | 58 +++++++++++++++++++++++++++++++
> > drivers/nvme/target/io-cmd-file.c | 52 +++++++++++++++++++++++++++
> > drivers/nvme/target/loop.c | 6 ++++
> > drivers/nvme/target/nvmet.h | 1 +
> > 5 files changed, 124 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
> > index 80099df37314..978786ec6a9e 100644
> > --- a/drivers/nvme/target/admin-cmd.c
> > +++ b/drivers/nvme/target/admin-cmd.c
> > @@ -433,8 +433,7 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
> > id->nn = cpu_to_le32(NVMET_MAX_NAMESPACES);
> > id->mnan = cpu_to_le32(NVMET_MAX_NAMESPACES);
> > id->oncs = cpu_to_le16(NVME_CTRL_ONCS_DSM |
> > - NVME_CTRL_ONCS_WRITE_ZEROES);
> > -
> > + NVME_CTRL_ONCS_WRITE_ZEROES | NVME_CTRL_ONCS_COPY);
> > /* XXX: don't report vwc if the underlying device is write through */
> > id->vwc = NVME_CTRL_VWC_PRESENT;
> >
> > @@ -536,6 +535,12 @@ static void nvmet_execute_identify_ns(struct nvmet_req *req)
> >
> > if (req->ns->bdev)
> > nvmet_bdev_set_limits(req->ns->bdev, id);
> > + else {
> > + id->msrc = (u8)to0based(BIO_MAX_VECS - 1);
> > + id->mssrl = cpu_to_le16(BIO_MAX_VECS <<
> > + (PAGE_SHIFT - SECTOR_SHIFT));
> > + id->mcl = cpu_to_le32(le16_to_cpu(id->mssrl));
> > + }
> >
> > /*
> > * We just provide a single LBA format that matches what the
> > diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c
> > index c2d6cea0236b..0af273097aa4 100644
> > --- a/drivers/nvme/target/io-cmd-bdev.c
> > +++ b/drivers/nvme/target/io-cmd-bdev.c
> > @@ -46,6 +46,19 @@ void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id)
> > id->npda = id->npdg;
> > /* NOWS = Namespace Optimal Write Size */
> > id->nows = to0based(bdev_io_opt(bdev) / bdev_logical_block_size(bdev));
> > +
> > + /*Copy limits*/
>
> above comment doesn't make any sense ...
>
acked, will remove it next version.
> > + if (bdev_max_copy_sectors(bdev)) {
> > + id->msrc = id->msrc;
> > + id->mssrl = cpu_to_le16((bdev_max_copy_sectors(bdev) <<
> > + SECTOR_SHIFT) / bdev_logical_block_size(bdev));
> > + id->mcl = cpu_to_le32(id->mssrl);
> > + } else {
> > + id->msrc = (u8)to0based(BIO_MAX_VECS - 1);
> > + id->mssrl = cpu_to_le16((BIO_MAX_VECS << PAGE_SHIFT) /
> > + bdev_logical_block_size(bdev));
> > + id->mcl = cpu_to_le32(id->mssrl);
> > + }
> > }
> >
> > void nvmet_bdev_ns_disable(struct nvmet_ns *ns)
> > @@ -184,6 +197,19 @@ static void nvmet_bio_done(struct bio *bio)
> > nvmet_req_bio_put(req, bio);
> > }
> >
> > +static void nvmet_bdev_copy_end_io(void *private, int comp_len)
> > +{
> > + struct nvmet_req *req = (struct nvmet_req *)private;
> > +
> > + if (comp_len == req->copy_len) {
> > + req->cqe->result.u32 = cpu_to_le32(1);
> > + nvmet_req_complete(req, errno_to_nvme_status(req, 0));
> > + } else {
> > + req->cqe->result.u32 = cpu_to_le32(0);
> > + nvmet_req_complete(req, blk_to_nvme_status(req, BLK_STS_IOERR));
> > + }
> > +}
> > +
>
> please reduce calls for nvmet_req_complete().
>
> +static void nvmet_bdev_copy_end_io(void *private, int comp_len)
> +{
> + struct nvmet_req *req = (struct nvmet_req *)private;
> + u16 status;
> +
> + if (comp_len == req->copy_len) {
> + req->cqe->result.u32 = cpu_to_le32(1);
> + status = errno_to_nvme_status(req, 0));
> + } else {
> + req->cqe->result.u32 = cpu_to_le32(0);
> + status = blk_to_nvme_status(req, BLK_STS_IOERR));
> + }
> + nvmet_req_complete(req, status);
> +}
> +
>
makes sense, will modify this snippet.
> > #ifdef CONFIG_BLK_DEV_INTEGRITY
> > static int nvmet_bdev_alloc_bip(struct nvmet_req *req, struct bio *bio,
> > struct sg_mapping_iter *miter)
> > @@ -450,6 +476,34 @@ static void nvmet_bdev_execute_write_zeroes(struct nvmet_req *req)
> > }
> > }
> >
> > +/* At present we handle only one range entry */
>
> please add explanation why ...
>
Because we aligned copy offload similar to copy_file_range in out recent
revisions, discarding multi range support.
Sure we will update comments to reflect the same.
> > +static void nvmet_bdev_execute_copy(struct nvmet_req *req)
> > +{
> > + struct nvme_copy_range range;
> > + struct nvme_command *cmnd = req->cmd;
>
> don't use cmnd, cmd is used everywhere and matches req->cmd,
> applies to everywhere in this patch...
>
acked
> > + int ret;
>
> wrong return type is should be u16 since nvmet_copy_from_sgl()
> returns u16 if I remember correctly.
>
> > +
> > +
>
acked
> no extra white line between declaration and body of functions
>
acked
> > + ret = nvmet_copy_from_sgl(req, 0, &range, sizeof(range));
> > + if (ret)
> > + goto out;
> > +
> > + ret = blkdev_issue_copy(req->ns->bdev,
> > + le64_to_cpu(cmnd->copy.sdlba) << req->ns->blksize_shift,
> > + req->ns->bdev,
> > + le64_to_cpu(range.slba) << req->ns->blksize_shift,
> > + (le16_to_cpu(range.nlb) + 1) << req->ns->blksize_shift,
> > + nvmet_bdev_copy_end_io, (void *)req, GFP_KERNEL);
> > + if (ret) {
> > + req->cqe->result.u32 = cpu_to_le32(0);
> > + nvmet_req_complete(req, blk_to_nvme_status(req, BLK_STS_IOERR));
> > + }
> > +
> > + return;
> > +out:
> > + nvmet_req_complete(req, errno_to_nvme_status(req, ret));
> > +}
> > +
>
> again one call to nvmet_req_complete() can do the same job.
> consider following totally untested :-
> /* TODO: add detailed comment here why you support one range ? */
> static void nvmet_bdev_execute_copy(struct nvmet_req *req)
> {
> u32 blkshift = req->ns->blksize_shift;
> struct nvme_command *cmnd = req->cmd;
> struct nvme_copy_range range;
> u16 status;
>
> status = nvmet_copy_from_sgl(req, 0, &range, sizeof(range));
> if (status) {
> goto out;
> }
>
> ret = blkdev_issue_copy(req->ns->bdev,
> le64_to_cpu(cmnd->copy.sdlba) << blkshift,
> req->ns->bdev,
> le64_to_cpu(range.slba) << blksize_shift,
> (le16_to_cpu(range.nlb) + 1) <<
> blksize_shift,
> nvmet_bdev_copy_end_io, (void *)req,
> GFP_KERNEL);
> if (ret) {
> req->cqe->result.u32 = cpu_to_le32(0);
> status = blk_to_nvme_status(req, BLK_STS_IOERR);
> out:
> nvmet_req_complete(req, status);
> }
> }
>
acked, thanks for sharing the snippet
> > u16 nvmet_bdev_parse_io_cmd(struct nvmet_req *req)
> > {
> > switch (req->cmd->common.opcode) {
> > @@ -468,6 +522,10 @@ u16 nvmet_bdev_parse_io_cmd(struct nvmet_req *req)
> > case nvme_cmd_write_zeroes:
> > req->execute = nvmet_bdev_execute_write_zeroes;
> > return 0;
> > + case nvme_cmd_copy:
> > + req->execute = nvmet_bdev_execute_copy;
> > + return 0;
> > +
> > default:
> > return nvmet_report_invalid_opcode(req);
> > }
> > diff --git a/drivers/nvme/target/io-cmd-file.c b/drivers/nvme/target/io-cmd-file.c
> > index 2d068439b129..69f198ecec77 100644
> > --- a/drivers/nvme/target/io-cmd-file.c
> > +++ b/drivers/nvme/target/io-cmd-file.c
> > @@ -322,6 +322,49 @@ static void nvmet_file_dsm_work(struct work_struct *w)
> > }
> > }
> >
> > +static void nvmet_file_copy_work(struct work_struct *w)
> > +{
> > + struct nvmet_req *req = container_of(w, struct nvmet_req, f.work);
> > + int nr_range;
> > + loff_t pos;
> > + struct nvme_command *cmnd = req->cmd;
> > + int ret = 0, len = 0, src, id;
>
> reverse tree style for declaration ...
>
acked
> > +
> > + nr_range = cmnd->copy.nr_range + 1;
> > + pos = le64_to_cpu(req->cmd->copy.sdlba) << req->ns->blksize_shift;
>
> you have a cmd variable above and you are still using req->cmd ?
> why create a variable on stack then ? u don't need that variable
> anyways...
>
acked
> > + if (unlikely(pos + req->transfer_len > req->ns->size)) {
> > + nvmet_req_complete(req, errno_to_nvme_status(req, -ENOSPC));
> > + return;
> > + }
> > +
> > + for (id = 0 ; id < nr_range; id++) {
> > + struct nvme_copy_range range;
> > +
> > + ret = nvmet_copy_from_sgl(req, id * sizeof(range), &range,
> > + sizeof(range));
> > + if (ret)
> > + goto out;
> > +
> > + len = (le16_to_cpu(range.nlb) + 1) << (req->ns->blksize_shift);
> > + src = (le64_to_cpu(range.slba) << (req->ns->blksize_shift));
> > + ret = vfs_copy_file_range(req->ns->file, src, req->ns->file,
> > + pos, len, 0);
>
> 5th paramaeter to vfs_copy_file_range() is size_t you have used int
> for len ? also
> vfs_copy_file_range() returns ssize_t you are catching it in int ?
>
acked, will change it to ssize_t.
> > +out:
> > + if (ret != len) {
> > + pos += ret;
> > + req->cqe->result.u32 = cpu_to_le32(id);
> > + nvmet_req_complete(req, ret < 0 ?
> > + errno_to_nvme_status(req, ret) :
> > + errno_to_nvme_status(req, -EIO));
>
> again plz don't add multiple nvmet_req_complete() calls
>
acked
> > + return;
> > +
> > + } else
> > + pos += len;
> > + }
> > +
> > + nvmet_req_complete(req, 0);
> > +
> > +}
>
> wrt above comments consider following totally untested :-
>
> static void nvmet_file_copy_work(struct work_struct *w)
> {
> struct nvmet_req *req = container_of(w, struct nvmet_req, f.work);
> int nr_range = req->cmd->copy.nr_range + 1;
> u16 status = 0;
> int src, id;
> ssize_t ret;
> size_t len;
> loff_t pos;
>
> pos = le64_to_cpu(req->cmd->copy.sdlba) << req->ns->blksize_shift;
> if (unlikely(pos + req->transfer_len > req->ns->size)) {
> nvmet_req_complete(req, errno_to_nvme_status(req,
> -ENOSPC));
> return;
> }
>
> for (id = 0 ; id < nr_range; id++) {
> struct nvme_copy_range range;
>
> status = nvmet_copy_from_sgl(req, id * sizeof(range),
> &range,
> sizeof(range));
> if (status)
> goto out;
>
> src = (le64_to_cpu(range.slba) <<
> (req->ns->blksize_shift));
> len = (le16_to_cpu(range.nlb) + 1) <<
> (req->ns->blksize_shift);
>
> ret = vfs_copy_file_range(req->ns->file, src,
> req->ns->file,
> pos, len, 0);
>
> if (ret != len) {
> req->cqe->result.u32 = cpu_to_le32(id);
> if (ret < 0)
> status = errno_to_nvme_status(req, ret);
> else
> status = errno_to_nvme_status(req, -EIO);
> goto out;
> }
> pos += ret;
> }
> out:
> nvmet_req_complete(req, status);
> }
>
>
Thanks for snippet will update this in next version.
--
Nitesh Shetty
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
next prev parent reply other threads:[~2023-04-26 10:31 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <CGME20230411081134epcas5p317f673eea473cea463be97b41dbfb09c@epcas5p3.samsung.com>
2023-04-11 8:10 ` [dm-devel] [PATCH v9 0/9] Implement copy offload support Anuj Gupta
2023-04-11 8:10 ` Anuj Gupta
2023-04-11 8:10 ` [dm-devel] [PATCH v9 1/9] block: Introduce queue limits for copy-offload support Anuj Gupta
2023-04-11 8:10 ` Anuj Gupta
2023-04-11 8:10 ` [dm-devel] [PATCH v9 2/9] block: Add copy offload support infrastructure Anuj Gupta
2023-04-11 8:10 ` Anuj Gupta
2023-04-11 8:10 ` [dm-devel] [PATCH v9 3/9] block: add emulation for copy Anuj Gupta
2023-04-11 8:10 ` Anuj Gupta
2023-04-11 8:10 ` [dm-devel] [PATCH v9 4/9] fs, block: copy_file_range for def_blk_ops for direct block device Anuj Gupta
2023-04-11 8:10 ` Anuj Gupta
2023-04-11 8:10 ` [dm-devel] [PATCH v9 5/9] nvme: add copy offload support Anuj Gupta
2023-04-11 8:10 ` Anuj Gupta
2023-04-11 8:10 ` [dm-devel] [PATCH v9 6/9] nvmet: add copy command support for bdev and file ns Anuj Gupta
2023-04-11 8:10 ` Anuj Gupta
2023-04-25 6:36 ` [dm-devel] " Chaitanya Kulkarni
2023-04-25 6:36 ` Chaitanya Kulkarni
2023-04-25 8:26 ` Nitesh Shetty [this message]
2023-04-25 8:26 ` Nitesh Shetty
2023-04-11 8:10 ` [dm-devel] [PATCH v9 7/9] dm: Add support for copy offload Anuj Gupta
2023-04-11 8:10 ` Anuj Gupta
2023-04-11 8:10 ` [dm-devel] [PATCH v9 8/9] dm: Enable copy offload for dm-linear target Anuj Gupta
2023-04-11 8:10 ` Anuj Gupta
2023-04-11 8:10 ` [dm-devel] [PATCH v9 9/9] null_blk: add support for copy offload Anuj Gupta
2023-04-11 8:10 ` Anuj Gupta
2023-04-13 6:28 ` [dm-devel] " Chaitanya Kulkarni
2023-04-13 6:28 ` Chaitanya Kulkarni
2023-04-13 10:36 ` [dm-devel] " Nitesh Shetty
2023-04-13 10:36 ` Nitesh Shetty
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230425082634.GA23150@green245 \
--to=nj.shetty@samsung.com \
--cc=agk@redhat.com \
--cc=anuj20.g@samsung.com \
--cc=axboe@kernel.dk \
--cc=brauner@kernel.org \
--cc=bvanassche@acm.org \
--cc=chaitanyak@nvidia.com \
--cc=dlemoal@kernel.org \
--cc=dm-devel@redhat.com \
--cc=gost.dev@samsung.com \
--cc=hch@lst.de \
--cc=james.smart@broadcom.com \
--cc=joshi.k@samsung.com \
--cc=kbusch@kernel.org \
--cc=linux-block@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nvme@lists.infradead.org \
--cc=ming.lei@redhat.com \
--cc=nitheshshetty@gmail.com \
--cc=sagi@grimberg.me \
--cc=snitzer@kernel.org \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.