Re: [PATCH v2 02/16] lightnvm: pblk: IO path reorganization

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> On 22 Mar 2019, at 22.48, Igor Konopko <igor.j.konopko@xxxxxxxxx> wrote:
> 
> This patch is made in order to prepare read path for new approach to
> partial read handling (which is needed for multi-page bvec handling)
> The most important change is to move the handling of completed and
> failed bio from the pblk_make_rq() to particular read and write
> functions. This is needed, since after partial read path changes,
> sometimes completed/failed bio will be different from original one, so
> we cannot do this any longer in pblk_make_rq(). Other changes are
> small read path refactor in order to reduce the size of another patch
> with partial read changes. Generally the goal of this patch is not to
> change the functionality, but just to prepare the code for the
> following changes.
> 
> Signed-off-by: Igor Konopko <igor.j.konopko@xxxxxxxxx>
> ---
> drivers/lightnvm/pblk-cache.c |  7 ++--
> drivers/lightnvm/pblk-init.c  | 14 ++------
> drivers/lightnvm/pblk-read.c  | 83 ++++++++++++++++++++-----------------------
> drivers/lightnvm/pblk.h       |  4 +--
> 4 files changed, 47 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/lightnvm/pblk-cache.c b/drivers/lightnvm/pblk-cache.c
> index c9fa26f..d2a3683 100644
> --- a/drivers/lightnvm/pblk-cache.c
> +++ b/drivers/lightnvm/pblk-cache.c
> @@ -18,7 +18,7 @@
> 
> #include "pblk.h"
> 
> -int pblk_write_to_cache(struct pblk *pblk, struct bio *bio, unsigned long flags)
> +void pblk_write_to_cache(struct pblk *pblk, struct bio *bio, unsigned long flags)
> {
> 	struct request_queue *q = pblk->dev->q;
> 	struct pblk_w_ctx w_ctx;
> @@ -43,6 +43,7 @@ int pblk_write_to_cache(struct pblk *pblk, struct bio *bio, unsigned long flags)
> 		goto retry;
> 	case NVM_IO_ERR:
> 		pblk_pipeline_stop(pblk);
> +		bio_io_error(bio);
> 		goto out;
> 	}
> 
> @@ -79,7 +80,9 @@ int pblk_write_to_cache(struct pblk *pblk, struct bio *bio, unsigned long flags)
> out:
> 	generic_end_io_acct(q, REQ_OP_WRITE, &pblk->disk->part0, start_time);
> 	pblk_write_should_kick(pblk);
> -	return ret;
> +
> +	if (ret == NVM_IO_DONE)
> +		bio_endio(bio);
> }
> 
> /*
> diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
> index e2e1193..4211cd1 100644
> --- a/drivers/lightnvm/pblk-init.c
> +++ b/drivers/lightnvm/pblk-init.c
> @@ -50,7 +50,6 @@ struct bio_set pblk_bio_set;
> static blk_qc_t pblk_make_rq(struct request_queue *q, struct bio *bio)
> {
> 	struct pblk *pblk = q->queuedata;
> -	int ret;
> 
> 	if (bio_op(bio) == REQ_OP_DISCARD) {
> 		pblk_discard(pblk, bio);
> @@ -65,7 +64,7 @@ static blk_qc_t pblk_make_rq(struct request_queue *q, struct bio *bio)
> 	 */
> 	if (bio_data_dir(bio) == READ) {
> 		blk_queue_split(q, &bio);
> -		ret = pblk_submit_read(pblk, bio);
> +		pblk_submit_read(pblk, bio);
> 	} else {
> 		/* Prevent deadlock in the case of a modest LUN configuration
> 		 * and large user I/Os. Unless stalled, the rate limiter
> @@ -74,16 +73,7 @@ static blk_qc_t pblk_make_rq(struct request_queue *q, struct bio *bio)
> 		if (pblk_get_secs(bio) > pblk_rl_max_io(&pblk->rl))
> 			blk_queue_split(q, &bio);
> 
> -		ret = pblk_write_to_cache(pblk, bio, PBLK_IOTYPE_USER);
> -	}
> -
> -	switch (ret) {
> -	case NVM_IO_ERR:
> -		bio_io_error(bio);
> -		break;
> -	case NVM_IO_DONE:
> -		bio_endio(bio);
> -		break;
> +		pblk_write_to_cache(pblk, bio, PBLK_IOTYPE_USER);
> 	}
> 
> 	return BLK_QC_T_NONE;
> diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
> index 6569746..597fe6d 100644
> --- a/drivers/lightnvm/pblk-read.c
> +++ b/drivers/lightnvm/pblk-read.c
> @@ -179,7 +179,8 @@ static void pblk_end_user_read(struct bio *bio, int error)
> {
> 	if (error && error != NVM_RSP_WARN_HIGHECC)
> 		bio_io_error(bio);
> -	bio_endio(bio);
> +	else
> +		bio_endio(bio);
> }
> 
> static void __pblk_end_io_read(struct pblk *pblk, struct nvm_rq *rqd,
> @@ -383,7 +384,6 @@ static int pblk_partial_read_bio(struct pblk *pblk, struct nvm_rq *rqd,
> 
> 	/* Free allocated pages in new bio */
> 	pblk_bio_free_pages(pblk, rqd->bio, 0, rqd->bio->bi_vcnt);
> -	__pblk_end_io_read(pblk, rqd, false);
> 	return NVM_IO_ERR;
> }
> 
> @@ -428,7 +428,7 @@ static void pblk_read_rq(struct pblk *pblk, struct nvm_rq *rqd, struct bio *bio,
> 	}
> }
> 
> -int pblk_submit_read(struct pblk *pblk, struct bio *bio)
> +void pblk_submit_read(struct pblk *pblk, struct bio *bio)
> {
> 	struct nvm_tgt_dev *dev = pblk->dev;
> 	struct request_queue *q = dev->q;
> @@ -436,9 +436,9 @@ int pblk_submit_read(struct pblk *pblk, struct bio *bio)
> 	unsigned int nr_secs = pblk_get_secs(bio);
> 	struct pblk_g_ctx *r_ctx;
> 	struct nvm_rq *rqd;
> +	struct bio *int_bio;
> 	unsigned int bio_init_idx;
> 	DECLARE_BITMAP(read_bitmap, NVM_MAX_VLBA);
> -	int ret = NVM_IO_ERR;
> 
> 	generic_start_io_acct(q, REQ_OP_READ, bio_sectors(bio),
> 			      &pblk->disk->part0);
> @@ -449,74 +449,67 @@ int pblk_submit_read(struct pblk *pblk, struct bio *bio)
> 
> 	rqd->opcode = NVM_OP_PREAD;
> 	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.
> 	 */
> 	bio_init_idx = pblk_get_bi_idx(bio);
> 
> -	if (pblk_alloc_rqd_meta(pblk, rqd))
> -		goto fail_rqd_free;
> +	if (pblk_alloc_rqd_meta(pblk, rqd)) {
> +		bio_io_error(bio);
> +		pblk_free_rqd(pblk, rqd, PBLK_READ);
> +		return;
> +	}
> +
> +	/* Clone read bio to deal internally with:
> +	 * -read errors when reading from drive
> +	 * -bio_advance() calls during l2p lookup and cache reads
> +	 */
> +	int_bio = bio_clone_fast(bio, GFP_KERNEL, &pblk_bio_set);
> 
> 	if (nr_secs > 1)
> 		pblk_read_ppalist_rq(pblk, rqd, bio, blba, read_bitmap);
> 	else
> 		pblk_read_rq(pblk, rqd, bio, blba, read_bitmap);
> 
> +	r_ctx->private = bio; /* original bio */
> +	rqd->bio = int_bio; /* internal bio */
> +
> 	if (bitmap_full(read_bitmap, nr_secs)) {
> +		pblk_end_user_read(bio, 0);
> 		atomic_inc(&pblk->inflight_io);
> 		__pblk_end_io_read(pblk, rqd, false);
> -		return NVM_IO_DONE;
> +		return;
> 	}
> 
> -	/* All sectors are to be read from the device */
> -	if (bitmap_empty(read_bitmap, rqd->nr_ppas)) {
> -		struct bio *int_bio = NULL;
> -
> -		/* Clone read bio to deal with read errors internally */
> -		int_bio = bio_clone_fast(bio, GFP_KERNEL, &pblk_bio_set);
> -		if (!int_bio) {
> -			pblk_err(pblk, "could not clone read bio\n");
> -			goto fail_end_io;
> -		}
> -
> -		rqd->bio = int_bio;
> -
> -		if (pblk_submit_io(pblk, rqd)) {
> +	if (!bitmap_empty(read_bitmap, rqd->nr_ppas)) {
> +		/* 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.
> +		 */
> +		bio_put(int_bio);
> +		rqd->bio = NULL;
> +		if (pblk_partial_read_bio(pblk, rqd, bio_init_idx, read_bitmap,
> +					    nr_secs)) {
> 			pblk_err(pblk, "read IO submission failed\n");
> -			ret = NVM_IO_ERR;
> -			goto fail_end_io;
> +			bio_io_error(bio);
> +			__pblk_end_io_read(pblk, rqd, false);
> 		}
> -
> -		return NVM_IO_OK;
> +		return;
> 	}
> 
> -	/* 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.
> -	 */
> -	ret = pblk_partial_read_bio(pblk, rqd, bio_init_idx, read_bitmap,
> -				    nr_secs);
> -	if (ret)
> -		goto fail_meta_free;
> -
> -	return NVM_IO_OK;
> -
> -fail_meta_free:
> -	nvm_dev_dma_free(dev->parent, rqd->meta_list, rqd->dma_meta_list);
> -fail_rqd_free:
> -	pblk_free_rqd(pblk, rqd, PBLK_READ);
> -	return ret;
> -fail_end_io:
> -	__pblk_end_io_read(pblk, rqd, false);
> -	return ret;
> +	/* All sectors are to be read from the device */
> +	if (pblk_submit_io(pblk, rqd)) {
> +		pblk_err(pblk, "read IO submission failed\n");
> +		bio_io_error(bio);
> +		__pblk_end_io_read(pblk, rqd, false);
> +	}
> }
> 
> static int read_ppalist_rq_gc(struct pblk *pblk, struct nvm_rq *rqd,
> diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
> index 381f074..a3c925d 100644
> --- a/drivers/lightnvm/pblk.h
> +++ b/drivers/lightnvm/pblk.h
> @@ -868,7 +868,7 @@ void pblk_get_packed_meta(struct pblk *pblk, struct nvm_rq *rqd);
> /*
>  * pblk user I/O write path
>  */
> -int pblk_write_to_cache(struct pblk *pblk, struct bio *bio,
> +void pblk_write_to_cache(struct pblk *pblk, struct bio *bio,
> 			unsigned long flags);
> int pblk_write_gc_to_cache(struct pblk *pblk, struct pblk_gc_rq *gc_rq);
> 
> @@ -894,7 +894,7 @@ void pblk_write_kick(struct pblk *pblk);
>  * pblk read path
>  */
> extern struct bio_set pblk_bio_set;
> -int pblk_submit_read(struct pblk *pblk, struct bio *bio);
> +void pblk_submit_read(struct pblk *pblk, struct bio *bio);
> int pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq);
> /*
>  * pblk recovery
> --
> 2.9.5

The patch looks sane.


Reviewed-by: Javier González <javier@xxxxxxxxxxx>

Attachment: signature.asc
Description: Message signed with OpenPGP


[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux