block: don't let passthrough IO go into .make_request_fn()
Commit a8821f3f3("block: Improvements to bounce-buffer handling") tries
to make sure that the bio to .make_request_fn won't exceed BIO_MAX_PAGES,
but ignores that passthrough I/O can use blk_queue_bounce() too.
Especially, passthrough IO may not be sector-aligned, and the check
of 'sectors < bio_sectors(*bio_orig)' inside __blk_queue_bounce() may
become true even though the max bvec number doesn't exceed BIO_MAX_PAGES,
then cause the bio splitted, and the original passthrough bio is submited
to generic_make_request().
This patch fixes this issue by checking if the bio is passthrough IO,
and use bio_kmalloc() to allocate the cloned passthrough bio.
Cc: NeilBrown <neilb@suse.com>
Fixes: a8821f3f3("block: Improvements to bounce-buffer handling")
Tested-by: Michele Ballabio <barra_cuda@katamail.com>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
@@ -241,14 +241,24 @@ struct request {
|
||||
struct request *next_rq;
|
||||
};
|
||||
|
||||
static inline bool blk_op_is_scsi(unsigned int op)
|
||||
{
|
||||
return op == REQ_OP_SCSI_IN || op == REQ_OP_SCSI_OUT;
|
||||
}
|
||||
|
||||
static inline bool blk_op_is_private(unsigned int op)
|
||||
{
|
||||
return op == REQ_OP_DRV_IN || op == REQ_OP_DRV_OUT;
|
||||
}
|
||||
|
||||
static inline bool blk_rq_is_scsi(struct request *rq)
|
||||
{
|
||||
return req_op(rq) == REQ_OP_SCSI_IN || req_op(rq) == REQ_OP_SCSI_OUT;
|
||||
return blk_op_is_scsi(req_op(rq));
|
||||
}
|
||||
|
||||
static inline bool blk_rq_is_private(struct request *rq)
|
||||
{
|
||||
return req_op(rq) == REQ_OP_DRV_IN || req_op(rq) == REQ_OP_DRV_OUT;
|
||||
return blk_op_is_private(req_op(rq));
|
||||
}
|
||||
|
||||
static inline bool blk_rq_is_passthrough(struct request *rq)
|
||||
@@ -256,6 +266,13 @@ static inline bool blk_rq_is_passthrough(struct request *rq)
|
||||
return blk_rq_is_scsi(rq) || blk_rq_is_private(rq);
|
||||
}
|
||||
|
||||
static inline bool bio_is_passthrough(struct bio *bio)
|
||||
{
|
||||
unsigned op = bio_op(bio);
|
||||
|
||||
return blk_op_is_scsi(op) || blk_op_is_private(op);
|
||||
}
|
||||
|
||||
static inline unsigned short req_get_ioprio(struct request *req)
|
||||
{
|
||||
return req->ioprio;
|
||||
|
||||
Reference in New Issue
Block a user