allow bio code to unmap sg io requests and have blk_execute_rq_nowait bounce bios
Subsystems (4)
RFC PATCH 1/1 allow bio code to unmap sg io requests and have blk_execute_rq_nowait bounce bios
Hey Jens and James,
The inlined patch moves the bounce buffer handling to blk_execute_rq_nowait so the scsi, sg io and cdrom code does not have to handle it. To accomplish this I moved the bio_uncopy_user to a bi_end_io function and bio_unmap_user to a work struct that is schedule from a bi_end_io functions. Did you say you disliked the idea of calling bio_unmap_user from a work struct - don't remember and I lost my emails when I moved? :(
In my patch there is the possiblity of pages being marked dirty after the request has been returned to userspace instead of the pages being dirtied before in the bio_unmap_user. Is this OK?
And, as I work on the adding of BLKERR_* error values in replacement of the dm-multupath/bio sense patch, I was thinking about your comment about having one true make_request function. It seems like if we extended bios to handle more request stuff (like what is needed for SG IO) we could just pass the bio to __make_request - with some modifications to __make_request - instead of doing it request based and moving the blk_queue_bounce call to blk_execute_rq_nowait like I did in my patch. Is this what you were thinking when adding the bio sense code?
Patch was made against James scsi-block-2.6 tree.
drivers/block/ll_rw_blk.c +3 -25
@@ -2193,31 +2193,6 @@ int blk_rq_map_user_iov(request_queue_tEXPORT_SYMBOL (blk_rq_map_user_iov);/** -* blk_rq_unmap_user - unmap a request with user data -* @rq: request to be unmapped -* @bio: bio for the request -* @ulen: length of user buffer -* -* Description: -* Unmap a request previously mapped by blk_rq_map_user(). -*/ -int blk_rq_unmap_user (struct bio *bio,unsigned int ulen) -{ -int ret =0 ; - -if (bio) { -if (bio_flagged (bio,BIO_USER_MAPPED )) -bio_unmap_user (bio); -else - ret =bio_uncopy_user (bio); - } - -return 0 ; -} - -EXPORT_SYMBOL (blk_rq_unmap_user); - -/** * blk_rq_map_kern - map kernel data to a request, for REQ_BLOCK_PC usage * @q: request queue where request should be inserted * @rw: READ or WRITE data
@@ -2257,6 +2232,9 @@ void blk_execute_rq_nowait(request_queue {int where = at_head ?ELEVATOR_INSERT_FRONT :ELEVATOR_INSERT_BACK ; +if (rq->bio) +blk_queue_bounce (q, &rq->bio); + rq->rq_disk = bd_disk; rq->flags |=REQ_NOMERGE ; rq->end_io = done;
drivers/block/scsi_ioctl.c +0 -12
@@ -218,7 +218,6 @@ static int sg_io(struct file *file, requunsigned long start_time;int writing =0 , ret =0 ;struct request *rq; -struct bio *bio;char sense[SCSI_SENSE_BUFFERSIZE ];unsigned char cmd[BLK_MAX_CDB ];
@@ -287,14 +286,6 @@ static int sg_io(struct file *file, requ rq->sense_len =0 ; rq->flags |=REQ_BLOCK_PC ; - bio = rq->bio; - -/* -* bounce this after holding a reference to the original bio, it's -* needed for proper unmapping -*/ -if (rq->bio) -blk_queue_bounce (q, &rq->bio); rq->timeout = (hdr->timeout *HZ ) /1000 ;if (!rq->timeout)
@@ -330,9 +321,6 @@ static int sg_io(struct file *file, requ hdr->sb_len_wr = len; } -if (blk_rq_unmap_user (bio, hdr->dxfer_len)) - ret = -EFAULT ; -/* may not have succeeded, but output values written to control * structure (struct sg_io_hdr). */ out:
drivers/cdrom/cdrom.c +0 -8
@@ -2090,7 +2090,6 @@ static int cdrom_read_cdda_bpc(struct cd {request_queue_t *q = cdi->disk->queue;struct request *rq; -struct bio *bio;unsigned int len;int nr, ret =0 ;
@@ -2131,10 +2130,6 @@ static int cdrom_read_cdda_bpc(struct cd rq->cmd_len =12 ; rq->flags |=REQ_BLOCK_PC ; rq->timeout =60 *HZ ; - bio = rq->bio; - -if (rq->bio) -blk_queue_bounce (q, &rq->bio);if (blk_execute_rq (q, cdi->disk, rq,0 )) {struct request_sense *s = rq->sense;
@@ -2142,9 +2137,6 @@ static int cdrom_read_cdda_bpc(struct cd cdi->last_sense = s->sense_key; } -if (blk_rq_unmap_user (bio, len)) - ret = -EFAULT ; -if (ret)break ;
fs/bio.c +62 -48
189 lines not on this page · raw message
include/linux/bio.h +0 -2
@@ -285,13 +285,11 @@ struct sg_iovec;extern struct bio *bio_map_user_iov (struct request_queue *,struct block_device *,struct sg_iovec *,int ,int ); -extern void bio_unmap_user (struct bio *);extern struct bio *bio_map_kern (struct request_queue *,void *,unsigned int ,unsigned int );extern void bio_set_pages_dirty (struct bio *bio);extern void bio_check_pages_dirty (struct bio *bio);extern struct bio *bio_copy_user (struct request_queue *,unsigned long ,unsigned int ,int ); -extern int bio_uncopy_user (struct bio *);void zero_fill_bio (struct bio *bio);#ifdef CONFIG_HIGHMEM
include/linux/blkdev.h +0 -1
@@ -553,7 +553,6 @@ extern void __blk_stop_queue(request_queextern void blk_run_queue (request_queue_t *);extern void blk_queue_activity_fn (request_queue_t *,activity_fn *,void *);extern int blk_rq_map_user (request_queue_t *,struct request *,void __user *,unsigned int ); -extern int blk_rq_unmap_user (struct bio *,unsigned int );extern int blk_rq_map_kern (request_queue_t *,struct request *,void *,unsigned int ,unsigned int );extern int blk_rq_map_user_iov (request_queue_t *,struct request *,struct sg_iovec *,int ); extern int blk_execute_rq(request_queue_t *, struct gendisk *,
Quoted 8 lines · Mike Christie
And, as I work on the adding of BLKERR_* error values in replacement of the dm-multupath/bio sense patch, I was thinking about your comment about having one true
make_requestfunction. It seems like if we extended bios to handle more request stuff (like what is needed for SG IO) we could just pass the bio to__make_request- with some modifications to__make_request- instead of doing it request based and moving theblk_queue_bouncecall toblk_execute_rq_nowaitlike I did in my patch. Is this what you were thinking when adding the bio sense code?
I mean doing things like sg io and dm-multipath HW handler's manual failover with bios instead of requests could simplify those things, but I am guessing bios were not meant to handle some of the lower level details like SCSI things. Or maybe they are or should be done in a more generic way?
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 12 lines · Jens Axboe
Quoted 8 lines · Mike Christie
Hey Jens and James,
The inlined patch moves the bounce buffer handling to
blk_execute_rq_nowaitso the scsi, sg io and cdrom code does not have to handle it. To accomplish this I moved thebio_uncopy_userto abi_end_iofunction andbio_unmap_userto a work struct that is schedule from abi_end_iofunctions. Did you say you disliked the idea of callingbio_unmap_userfrom a work struct - don't remember and I lost my emails when I moved? :(
Quoted 4 lines
It's probably alright, it cleans up the code a lot. It will cost some extra context switches, but I'm naively hoping that for busy io we will have good batching of the processing anyways.
Doh! I ported sg.c and noticed I messed up. copy_to_user must be called from user context so my patch does not work for that path.