Skip to content

Commit 02db995

Browse files
Ming LeiChristoph Hellwig
authored andcommitted
nvmet: fix building bvec from sg list
There are two mistakes for building bvec from sg list for file backed ns: - use request data length to compute number of io vector, this way doesn't consider sg->offset, and the result may be smaller than required io vectors - bvec->bv_len isn't capped by sg->length This patch fixes this issue by building bvec from sg directly, given the whole IO stack is ready for multi-page bvec. Reported-by: Yi Zhang <yi.zhang@redhat.com> Fixes: 3a85a5d ("nvme-loop: add a NVMe loopback host driver") Signed-off-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
1 parent cc2278c commit 02db995

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

drivers/nvme/target/io-cmd-file.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,11 @@ int nvmet_file_ns_enable(struct nvmet_ns *ns)
7575
return ret;
7676
}
7777

78-
static void nvmet_file_init_bvec(struct bio_vec *bv, struct sg_page_iter *iter)
78+
static void nvmet_file_init_bvec(struct bio_vec *bv, struct scatterlist *sg)
7979
{
80-
bv->bv_page = sg_page_iter_page(iter);
81-
bv->bv_offset = iter->sg->offset;
82-
bv->bv_len = PAGE_SIZE - iter->sg->offset;
80+
bv->bv_page = sg_page(sg);
81+
bv->bv_offset = sg->offset;
82+
bv->bv_len = sg->length;
8383
}
8484

8585
static ssize_t nvmet_file_submit_bvec(struct nvmet_req *req, loff_t pos,
@@ -128,14 +128,14 @@ static void nvmet_file_io_done(struct kiocb *iocb, long ret, long ret2)
128128

129129
static bool nvmet_file_execute_io(struct nvmet_req *req, int ki_flags)
130130
{
131-
ssize_t nr_bvec = DIV_ROUND_UP(req->data_len, PAGE_SIZE);
132-
struct sg_page_iter sg_pg_iter;
131+
ssize_t nr_bvec = req->sg_cnt;
133132
unsigned long bv_cnt = 0;
134133
bool is_sync = false;
135134
size_t len = 0, total_len = 0;
136135
ssize_t ret = 0;
137136
loff_t pos;
138-
137+
int i;
138+
struct scatterlist *sg;
139139

140140
if (req->f.mpool_alloc && nr_bvec > NVMET_MAX_MPOOL_BVEC)
141141
is_sync = true;
@@ -147,8 +147,8 @@ static bool nvmet_file_execute_io(struct nvmet_req *req, int ki_flags)
147147
}
148148

149149
memset(&req->f.iocb, 0, sizeof(struct kiocb));
150-
for_each_sg_page(req->sg, &sg_pg_iter, req->sg_cnt, 0) {
151-
nvmet_file_init_bvec(&req->f.bvec[bv_cnt], &sg_pg_iter);
150+
for_each_sg(req->sg, sg, req->sg_cnt, i) {
151+
nvmet_file_init_bvec(&req->f.bvec[bv_cnt], sg);
152152
len += req->f.bvec[bv_cnt].bv_len;
153153
total_len += req->f.bvec[bv_cnt].bv_len;
154154
bv_cnt++;
@@ -225,7 +225,7 @@ static void nvmet_file_submit_buffered_io(struct nvmet_req *req)
225225

226226
static void nvmet_file_execute_rw(struct nvmet_req *req)
227227
{
228-
ssize_t nr_bvec = DIV_ROUND_UP(req->data_len, PAGE_SIZE);
228+
ssize_t nr_bvec = req->sg_cnt;
229229

230230
if (!req->sg_cnt || !nr_bvec) {
231231
nvmet_req_complete(req, 0);

0 commit comments

Comments
 (0)