diff options
| author | Jens Axboe <axboe@suse.de> | 2003-04-24 08:42:43 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-04-24 08:42:43 -0700 |
| commit | 3bec8a5ac61e5fdd925460a20de267ccf2cefcfe (patch) | |
| tree | 04c5abbaa34cafd7eb1fda98bd1da25ba634e87f /drivers/block | |
| parent | 2f2ba9da7c2732dbf73b4c56ca4f57c7fa41f459 (diff) | |
[PATCH] cleanup bio_map_user and helper
Bart did this patch, I changed it a bit. Basically it cleans the mapping
interface up a bit, and adds a little helper to set up the request from
the bio.
In addition, it fixes a long standing bug where bio_map_user() would
call blk_queue_bounce() without the direction bit being set, auch.
- Abstract out bio request preparation
- Have bio_map_user() set data direction (fixes bug where blk_queue_bounce()
is called without it set)
- Split bio_map_user() in two
Diffstat (limited to 'drivers/block')
| -rw-r--r-- | drivers/block/ll_rw_blk.c | 17 | ||||
| -rw-r--r-- | drivers/block/scsi_ioctl.c | 37 |
2 files changed, 22 insertions, 32 deletions
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 832189677065..ec0b1e827ae0 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -2196,6 +2196,21 @@ void end_request(struct request *req, int uptodate) } } +void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio) +{ + /* first three bits are identical in rq->flags and bio->bi_rw */ + rq->flags |= (bio->bi_rw & 7); + + rq->nr_phys_segments = bio_phys_segments(q, bio); + rq->nr_hw_segments = bio_hw_segments(q, bio); + rq->current_nr_sectors = bio_cur_sectors(bio); + rq->hard_cur_sectors = rq->current_nr_sectors; + rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio); + rq->buffer = bio_data(bio); + + rq->bio = rq->biotail = bio; +} + int __init blk_dev_init(void) { int total_ram = nr_free_pages() << (PAGE_SHIFT - 10); @@ -2285,3 +2300,5 @@ EXPORT_SYMBOL(blk_stop_queue); EXPORT_SYMBOL(__blk_stop_queue); EXPORT_SYMBOL(blk_run_queue); EXPORT_SYMBOL(blk_run_queues); + +EXPORT_SYMBOL(blk_rq_bio_prep); diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index 4adc5f7004a9..0e4fd3232c4c 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c @@ -193,18 +193,6 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, * be a write to vm. */ bio = bio_map_user(bdev, uaddr, hdr.dxfer_len, reading); - if (bio) { - if (writing) - bio->bi_rw |= (1 << BIO_RW); - - nr_sectors = (bio->bi_size + 511) >> 9; - - if (bio->bi_size < hdr.dxfer_len) { - bio_endio(bio, bio->bi_size, 0); - bio_unmap_user(bio, 0); - bio = NULL; - } - } /* * if bio setup failed, fall back to slow approach @@ -243,21 +231,10 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, rq->hard_nr_sectors = rq->nr_sectors = nr_sectors; rq->hard_cur_sectors = rq->current_nr_sectors = nr_sectors; - if (bio) { - /* - * subtle -- if bio_map_user() ended up bouncing a bio, it - * would normally disappear when its bi_end_io is run. - * however, we need it for the unmap, so grab an extra - * reference to it - */ - bio_get(bio); + rq->bio = rq->biotail = bio; - rq->nr_phys_segments = bio_phys_segments(q, bio); - rq->nr_hw_segments = bio_hw_segments(q, bio); - rq->current_nr_sectors = bio_cur_sectors(bio); - rq->hard_cur_sectors = rq->current_nr_sectors; - rq->buffer = bio_data(bio); - } + if (bio) + blk_rq_bio_prep(q, rq, bio); rq->data_len = hdr.dxfer_len; rq->data = buffer; @@ -268,8 +245,6 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, if (!rq->timeout) rq->timeout = BLK_DEFAULT_TIMEOUT; - rq->bio = rq->biotail = bio; - start_time = jiffies; /* ignore return value. All information is passed back to caller @@ -277,11 +252,9 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, * N.B. a non-zero SCSI status is _not_ necessarily an error. */ blk_do_rq(q, bdev, rq); - - if (bio) { + + if (bio) bio_unmap_user(bio, reading); - bio_put(bio); - } /* write to all output members */ hdr.status = rq->errors; |
