[PATCH v4] nvme: fix corruption for passthrough meta/data

Kanchan Joshi joshi.k at samsung.com
Fri Oct 13 05:59:45 PDT 2023


On 10/13/2023 3:44 PM, Kanchan Joshi wrote:
> On 10/13/2023 10:56 AM, Christoph Hellwig wrote:
>> On Fri, Oct 13, 2023 at 10:44:58AM +0530, Kanchan Joshi wrote:
>>> Changes since v3:
>>> - Block only unprivileged user
>>
>> That's not really what at least I had in mind.  I'd much rather
>> completely disable unprivileged passthrough for now as an easy
>> backportable patch.  And then only re-enable it later in a way
>> where it does require using SGLs for all data transfers.
>>
> 
> I did not get how forcing SGLs can solve the issue at hand.
> The problem happened because (i) user specified short buffer/len, and
> (ii) kernel allocated buffer. Whether the buffer is fed to device using
> PRP or SGL does not seem to solve the large DMA problem.
> 

FWIW, this is the test-patch I wrote to force passthrough to use SGL.

---
  drivers/nvme/host/ioctl.c | 2 ++
  drivers/nvme/host/nvme.h  | 1 +
  drivers/nvme/host/pci.c   | 8 +++++---
  3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index d8ff796fd5f2..508a813b349e 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -202,6 +202,8 @@ static int nvme_map_user_request(struct request 
*req, u64 ubuffer,
                 }
                 *metap = meta;
         }
+       /* force sgl for data transfer */
+       nvme_req(req)->flags |= NVME_REQ_FORCE_SGL;

         return ret;

diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index f35647c470af..9fe91d25cfdd 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -184,6 +184,7 @@ enum {
         NVME_REQ_CANCELLED              = (1 << 0),
         NVME_REQ_USERCMD                = (1 << 1),
         NVME_MPATH_IO_STATS             = (1 << 2),
+       NVME_REQ_FORCE_SGL              = (1 << 3),
  };

  static inline struct nvme_request *nvme_req(struct request *req)
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 60a08dfe8d75..e28d3b7b14ef 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -772,18 +772,20 @@ static blk_status_t nvme_map_data(struct nvme_dev 
*dev, struct request *req,
         struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
         blk_status_t ret = BLK_STS_RESOURCE;
         int rc;
+       bool force_sgl = nvme_req(req)->flags & NVME_REQ_FORCE_SGL;

         if (blk_rq_nr_phys_segments(req) == 1) {
                 struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
                 struct bio_vec bv = req_bvec(req);

                 if (!is_pci_p2pdma_page(bv.bv_page)) {
-                       if (bv.bv_offset + bv.bv_len <= 
NVME_CTRL_PAGE_SIZE * 2)
+                       if (!force_sgl &&
+                           bv.bv_offset + bv.bv_len <= 
NVME_CTRL_PAGE_SIZE * 2)
                                 return nvme_setup_prp_simple(dev, req,
                                                              &cmnd->rw, 
&bv);

-                       if (nvmeq->qid && sgl_threshold &&
-                           nvme_ctrl_sgl_supported(&dev->ctrl))
+                       if (nvmeq->qid && 
nvme_ctrl_sgl_supported(&dev->ctrl)
+                           && (sgl_threshold || force_sgl))
                                 return nvme_setup_sgl_simple(dev, req,
                                                              &cmnd->rw, 
&bv);
                 }




More information about the Linux-nvme mailing list