}
 
 static void pblk_read_ppalist_rq(struct pblk *pblk, struct nvm_rq *rqd,
-                                sector_t blba, unsigned long *read_bitmap)
+                                struct bio *bio, sector_t blba,
+                                unsigned long *read_bitmap)
 {
        struct pblk_sec_meta *meta_list = rqd->meta_list;
-       struct bio *bio = rqd->bio;
        struct ppa_addr ppas[PBLK_MAX_REQ_ADDRS];
        int nr_secs = rqd->nr_ppas;
        bool advanced_bio = false;
        WARN_ONCE(bio->bi_status, "pblk: corrupted read bio\n");
 #endif
        bio_endio(bio);
-       bio_put(bio);
 }
 
 static void __pblk_end_io_read(struct pblk *pblk, struct nvm_rq *rqd,
 {
        struct nvm_tgt_dev *dev = pblk->dev;
        struct pblk_g_ctx *r_ctx = nvm_rq_to_pdu(rqd);
-       struct bio *bio = rqd->bio;
+       struct bio *int_bio = rqd->bio;
        unsigned long start_time = r_ctx->start_time;
 
        generic_end_io_acct(dev->q, READ, &pblk->disk->part0, start_time);
 
        if (rqd->error)
                pblk_log_read_err(pblk, rqd);
-#ifdef CONFIG_NVM_DEBUG
-       else
-               WARN_ONCE(bio->bi_status, "pblk: corrupted read error\n");
-#endif
 
        pblk_read_check_seq(pblk, rqd, r_ctx->lba);
 
-       bio_put(bio);
-       if (r_ctx->private)
-               pblk_end_user_read((struct bio *)r_ctx->private);
+       if (int_bio)
+               bio_put(int_bio);
 
        if (put_line)
                pblk_read_put_rqd_kref(pblk, rqd);
 static void pblk_end_io_read(struct nvm_rq *rqd)
 {
        struct pblk *pblk = rqd->private;
+       struct pblk_g_ctx *r_ctx = nvm_rq_to_pdu(rqd);
+       struct bio *bio = (struct bio *)r_ctx->private;
 
+       pblk_end_user_read(bio);
        __pblk_end_io_read(pblk, rqd, true);
 }
 
-static int pblk_partial_read_bio(struct pblk *pblk, struct nvm_rq *rqd,
-                                unsigned int bio_init_idx,
-                                unsigned long *read_bitmap)
+static int pblk_partial_read(struct pblk *pblk, struct nvm_rq *rqd,
+                            struct bio *orig_bio, unsigned int bio_init_idx,
+                            unsigned long *read_bitmap)
 {
-       struct bio *new_bio, *bio = rqd->bio;
        struct pblk_sec_meta *meta_list = rqd->meta_list;
+       struct bio *new_bio;
        struct bio_vec src_bv, dst_bv;
        void *ppa_ptr = NULL;
        void *src_p, *dst_p;
        new_bio = bio_alloc(GFP_KERNEL, nr_holes);
 
        if (pblk_bio_add_pages(pblk, new_bio, GFP_KERNEL, nr_holes))
-               goto err_add_pages;
+               goto fail_add_pages;
 
        if (nr_holes != new_bio->bi_vcnt) {
                pr_err("pblk: malformed bio\n");
-               goto err;
+               goto fail;
        }
 
        for (i = 0; i < nr_secs; i++)
        if (ret) {
                bio_put(rqd->bio);
                pr_err("pblk: sync read IO submission failed\n");
-               goto err;
+               goto fail;
        }
 
        if (rqd->error) {
                meta_list[hole].lba = lba_list_media[i];
 
                src_bv = new_bio->bi_io_vec[i++];
-               dst_bv = bio->bi_io_vec[bio_init_idx + hole];
+               dst_bv = orig_bio->bi_io_vec[bio_init_idx + hole];
 
                src_p = kmap_atomic(src_bv.bv_page);
                dst_p = kmap_atomic(dst_bv.bv_page);
 
        bio_put(new_bio);
 
-       /* Complete the original bio and associated request */
-       bio_endio(bio);
-       rqd->bio = bio;
+       /* restore original request */
+       rqd->bio = NULL;
        rqd->nr_ppas = nr_secs;
 
        __pblk_end_io_read(pblk, rqd, false);
-       return NVM_IO_OK;
+       return NVM_IO_DONE;
 
-err:
+fail:
        /* Free allocated pages in new bio */
        pblk_bio_free_pages(pblk, new_bio, 0, new_bio->bi_vcnt);
-err_add_pages:
+fail_add_pages:
        pr_err("pblk: failed to perform partial read\n");
        __pblk_end_io_read(pblk, rqd, false);
        return NVM_IO_ERR;
 }
 
-static void pblk_read_rq(struct pblk *pblk, struct nvm_rq *rqd,
+static void pblk_read_rq(struct pblk *pblk, struct nvm_rq *rqd, struct bio *bio,
                         sector_t lba, unsigned long *read_bitmap)
 {
        struct pblk_sec_meta *meta_list = rqd->meta_list;
-       struct bio *bio = rqd->bio;
        struct ppa_addr ppa;
 
        pblk_lookup_l2p_seq(pblk, &ppa, lba, 1);
        rqd = pblk_alloc_rqd(pblk, PBLK_READ);
 
        rqd->opcode = NVM_OP_PREAD;
-       rqd->bio = bio;
        rqd->nr_ppas = nr_secs;
+       rqd->bio = NULL; /* cloned bio if needed */
        rqd->private = pblk;
        rqd->end_io = pblk_end_io_read;
 
        r_ctx = nvm_rq_to_pdu(rqd);
        r_ctx->start_time = jiffies;
        r_ctx->lba = blba;
+       r_ctx->private = bio; /* original bio */
 
        /* Save the index for this bio's start. This is needed in case
         * we need to fill a partial read.
                rqd->ppa_list = rqd->meta_list + pblk_dma_meta_size;
                rqd->dma_ppa_list = rqd->dma_meta_list + pblk_dma_meta_size;
 
-               pblk_read_ppalist_rq(pblk, rqd, blba, &read_bitmap);
+               pblk_read_ppalist_rq(pblk, rqd, bio, blba, &read_bitmap);
        } else {
-               pblk_read_rq(pblk, rqd, blba, &read_bitmap);
+               pblk_read_rq(pblk, rqd, bio, blba, &read_bitmap);
        }
 
-       bio_get(bio);
        if (bitmap_full(&read_bitmap, nr_secs)) {
-               bio_endio(bio);
                atomic_inc(&pblk->inflight_io);
                __pblk_end_io_read(pblk, rqd, false);
-               return NVM_IO_OK;
+               return NVM_IO_DONE;
        }
 
        /* All sectors are to be read from the device */
                }
 
                rqd->bio = int_bio;
-               r_ctx->private = bio;
 
                if (pblk_submit_io(pblk, rqd)) {
                        pr_err("pblk: read IO submission failed\n");
                        ret = NVM_IO_ERR;
-                       if (int_bio)
-                               bio_put(int_bio);
                        goto fail_end_io;
                }
 
        /* The read bio request could be partially filled by the write buffer,
         * but there are some holes that need to be read from the drive.
         */
-       return pblk_partial_read_bio(pblk, rqd, bio_init_idx, &read_bitmap);
+       return pblk_partial_read(pblk, rqd, bio, bio_init_idx, &read_bitmap);
 
 fail_rqd_free:
        pblk_free_rqd(pblk, rqd, PBLK_READ);