summaryrefslogtreecommitdiff
path: root/drivers/block
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2003-04-24 08:42:43 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2003-04-24 08:42:43 -0700
commit3bec8a5ac61e5fdd925460a20de267ccf2cefcfe (patch)
tree04c5abbaa34cafd7eb1fda98bd1da25ba634e87f /drivers/block
parent2f2ba9da7c2732dbf73b4c56ca4f57c7fa41f459 (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.c17
-rw-r--r--drivers/block/scsi_ioctl.c37
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;