This splits pmem_do_bvec() into pmem_do_read() and pmem_do_write().
pmem_do_write() will be used by pmem zero_page_range() as well. Hence
sharing the same code.

Suggested-by: Christoph Hellwig <h...@infradead.org>
Signed-off-by: Vivek Goyal <vgo...@redhat.com>
---
 drivers/nvdimm/pmem.c | 79 ++++++++++++++++++++++++++-----------------
 1 file changed, 48 insertions(+), 31 deletions(-)

diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index ad8e4df1282b..9ad07cb8c9fc 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -136,9 +136,25 @@ static blk_status_t read_pmem(struct page *page, unsigned 
int off,
        return BLK_STS_OK;
 }
 
-static blk_status_t pmem_do_bvec(struct pmem_device *pmem, struct page *page,
-                       unsigned int len, unsigned int off, unsigned int op,
-                       sector_t sector)
+static blk_status_t pmem_do_read(struct pmem_device *pmem,
+                       struct page *page, unsigned int page_off,
+                       sector_t sector, unsigned int len)
+{
+       blk_status_t rc;
+       phys_addr_t pmem_off = sector * 512 + pmem->data_offset;
+       void *pmem_addr = pmem->virt_addr + pmem_off;
+
+       if (unlikely(is_bad_pmem(&pmem->bb, sector, len)))
+               return BLK_STS_IOERR;
+
+       rc = read_pmem(page, page_off, pmem_addr, len);
+       flush_dcache_page(page);
+       return rc;
+}
+
+static blk_status_t pmem_do_write(struct pmem_device *pmem,
+                       struct page *page, unsigned int page_off,
+                       sector_t sector, unsigned int len)
 {
        blk_status_t rc = BLK_STS_OK;
        bool bad_pmem = false;
@@ -148,39 +164,40 @@ static blk_status_t pmem_do_bvec(struct pmem_device 
*pmem, struct page *page,
        if (unlikely(is_bad_pmem(&pmem->bb, sector, len)))
                bad_pmem = true;
 
-       if (!op_is_write(op)) {
-               if (unlikely(bad_pmem))
-                       rc = BLK_STS_IOERR;
-               else {
-                       rc = read_pmem(page, off, pmem_addr, len);
-                       flush_dcache_page(page);
-               }
-       } else {
-               /*
-                * Note that we write the data both before and after
-                * clearing poison.  The write before clear poison
-                * handles situations where the latest written data is
-                * preserved and the clear poison operation simply marks
-                * the address range as valid without changing the data.
-                * In this case application software can assume that an
-                * interrupted write will either return the new good
-                * data or an error.
-                *
-                * However, if pmem_clear_poison() leaves the data in an
-                * indeterminate state we need to perform the write
-                * after clear poison.
-                */
-               flush_dcache_page(page);
-               write_pmem(pmem_addr, page, off, len);
-               if (unlikely(bad_pmem)) {
-                       rc = pmem_clear_poison(pmem, pmem_off, len);
-                       write_pmem(pmem_addr, page, off, len);
-               }
+       /*
+        * Note that we write the data both before and after
+        * clearing poison.  The write before clear poison
+        * handles situations where the latest written data is
+        * preserved and the clear poison operation simply marks
+        * the address range as valid without changing the data.
+        * In this case application software can assume that an
+        * interrupted write will either return the new good
+        * data or an error.
+        *
+        * However, if pmem_clear_poison() leaves the data in an
+        * indeterminate state we need to perform the write
+        * after clear poison.
+        */
+       flush_dcache_page(page);
+       write_pmem(pmem_addr, page, page_off, len);
+       if (unlikely(bad_pmem)) {
+               rc = pmem_clear_poison(pmem, pmem_off, len);
+               write_pmem(pmem_addr, page, page_off, len);
        }
 
        return rc;
 }
 
+static blk_status_t pmem_do_bvec(struct pmem_device *pmem, struct page *page,
+                       unsigned int len, unsigned int off, unsigned int op,
+                       sector_t sector)
+{
+       if (!op_is_write(op))
+               return pmem_do_read(pmem, page, off, sector, len);
+
+       return pmem_do_write(pmem, page, off, sector, len);
+}
+
 static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio)
 {
        int ret = 0;
-- 
2.20.1
_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-le...@lists.01.org

Reply via email to