From: Jens Axboe <axboe@suse.de>
To: Bartlomiej Zolnierkiewicz <B.Zolnierkiewicz@elka.pw.edu.pl>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>,
Andre Hedrick <andre@linux-ide.org>,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH] 2.5.67-ac2 direct-IO for IDE taskfile ioctl (1/4)
Date: Thu, 24 Apr 2003 10:23:31 +0200 [thread overview]
Message-ID: <20030424082331.GE8775@suse.de> (raw)
In-Reply-To: <Pine.SOL.4.30.0304231937390.10502-100000@mion.elka.pw.edu.pl>
On Wed, Apr 23 2003, Bartlomiej Zolnierkiewicz wrote:
> 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 && writing)
> + bio->bi_rw |= (1 << BIO_RW);
I think it's cleaner to have bio_map_user() set the direction bit,
instead of having every user do it. It also uncovered an old bug where
blk_queue_bounce() is called without the direction bit set in the bio,
uh oh...
Here's my preferred version. You also had the incremental bio processing
as a prereq for this bio addition, I removed that for now as well.
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.1216 -> 1.1217
# drivers/block/ll_rw_blk.c 1.167 -> 1.168
# include/linux/blkdev.h 1.100 -> 1.101
# fs/bio.c 1.41 -> 1.42
# drivers/block/scsi_ioctl.c 1.22 -> 1.23
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/04/24 axboe@smithers.home.kernel.dk 1.1217
# - 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
# --------------------------------------------
#
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c Thu Apr 24 10:23:09 2003
+++ b/drivers/block/ll_rw_blk.c Thu Apr 24 10:23:09 2003
@@ -2196,6 +2196,21 @@
}
}
+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_run_queue);
EXPORT_SYMBOL(blk_run_queues);
+
+EXPORT_SYMBOL(blk_rq_bio_prep);
diff -Nru a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
--- a/drivers/block/scsi_ioctl.c Thu Apr 24 10:23:09 2003
+++ b/drivers/block/scsi_ioctl.c Thu Apr 24 10:23:09 2003
@@ -193,18 +193,6 @@
* 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 @@
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 @@
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 @@
* 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;
diff -Nru a/fs/bio.c b/fs/bio.c
--- a/fs/bio.c Thu Apr 24 10:23:09 2003
+++ b/fs/bio.c Thu Apr 24 10:23:09 2003
@@ -434,19 +434,9 @@
return len;
}
-/**
- * bio_map_user - map user address into bio
- * @bdev: destination block device
- * @uaddr: start of user address
- * @len: length in bytes
- * @write_to_vm: bool indicating writing to pages or not
- *
- * Map the user space address into a bio suitable for io to a block
- * device. Caller should check the size of the returned bio, we might
- * not have mapped the entire range specified.
- */
-struct bio *bio_map_user(struct block_device *bdev, unsigned long uaddr,
- unsigned int len, int write_to_vm)
+static struct bio *__bio_map_user(struct block_device *bdev,
+ unsigned long uaddr, unsigned int len,
+ int write_to_vm)
{
unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
unsigned long start = uaddr >> PAGE_SHIFT;
@@ -510,8 +500,11 @@
kfree(pages);
/*
- * check if the mapped pages need bouncing for an isa host.
+ * set data direction, and check if mapped pages need bouncing
*/
+ if (!write_to_vm)
+ bio->bi_rw |= (1 << BIO_RW);
+
blk_queue_bounce(q, &bio);
return bio;
out:
@@ -521,17 +514,42 @@
}
/**
- * bio_unmap_user - unmap a bio
- * @bio: the bio being unmapped
- * @write_to_vm: bool indicating whether pages were written to
- *
- * Unmap a bio previously mapped by bio_map_user(). The @write_to_vm
- * must be the same as passed into bio_map_user(). Must be called with
- * a process context.
+ * bio_map_user - map user address into bio
+ * @bdev: destination block device
+ * @uaddr: start of user address
+ * @len: length in bytes
+ * @write_to_vm: bool indicating writing to pages or not
*
- * bio_unmap_user() may sleep.
+ * Map the user space address into a bio suitable for io to a block
+ * device.
*/
-void bio_unmap_user(struct bio *bio, int write_to_vm)
+struct bio *bio_map_user(struct block_device *bdev, unsigned long uaddr,
+ unsigned int len, int write_to_vm)
+{
+ struct bio *bio;
+
+ bio = __bio_map_user(bdev, uaddr, len, write_to_vm);
+
+ if (bio) {
+ if (bio->bi_size < len) {
+ bio_endio(bio, bio->bi_size, 0);
+ bio_unmap_user(bio, 0);
+ return NULL;
+ }
+
+ /*
+ * 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);
+ }
+
+ return bio;
+}
+
+static void __bio_unmap_user(struct bio *bio, int write_to_vm)
{
struct bio_vec *bvec;
int i;
@@ -558,6 +576,23 @@
page_cache_release(bvec->bv_page);
}
+ bio_put(bio);
+}
+
+/**
+ * bio_unmap_user - unmap a bio
+ * @bio: the bio being unmapped
+ * @write_to_vm: bool indicating whether pages were written to
+ *
+ * Unmap a bio previously mapped by bio_map_user(). The @write_to_vm
+ * must be the same as passed into bio_map_user(). Must be called with
+ * a process context.
+ *
+ * bio_unmap_user() may sleep.
+ */
+void bio_unmap_user(struct bio *bio, int write_to_vm)
+{
+ __bio_unmap_user(bio, write_to_vm);
bio_put(bio);
}
diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h Thu Apr 24 10:23:09 2003
+++ b/include/linux/blkdev.h Thu Apr 24 10:23:09 2003
@@ -391,6 +391,8 @@
extern void blk_queue_invalidate_tags(request_queue_t *);
extern void blk_congestion_wait(int rw, long timeout);
+extern void blk_rq_bio_prep(request_queue_t *, struct request *, struct bio *);
+
#define MAX_PHYS_SEGMENTS 128
#define MAX_HW_SEGMENTS 128
#define MAX_SECTORS 255
--
Jens Axboe
next prev parent reply other threads:[~2003-04-24 8:11 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-04-23 17:37 [PATCH] 2.5.67-ac2 direct-IO for IDE taskfile ioctl (0/4) Bartlomiej Zolnierkiewicz
2003-04-23 17:38 ` [PATCH] 2.5.67-ac2 direct-IO for IDE taskfile ioctl (1/4) Bartlomiej Zolnierkiewicz
2003-04-24 8:23 ` Jens Axboe [this message]
2003-04-24 14:46 ` Bartlomiej Zolnierkiewicz
2003-04-24 15:47 ` [PATCH] 2.5.68 fix mismatched access_ok() checks in sg_io() Bartlomiej Zolnierkiewicz
2003-04-24 17:31 ` Jens Axboe
2003-04-23 17:39 ` [PATCH] 2.5.67-ac2 direct-IO for IDE taskfile ioctl (2/4) Bartlomiej Zolnierkiewicz
2003-04-23 17:39 ` [PATCH] 2.5.67-ac2 direct-IO for IDE taskfile ioctl (3/4) Bartlomiej Zolnierkiewicz
2003-04-23 17:40 ` [PATCH] 2.5.67-ac2 direct-IO for IDE taskfile ioctl (4/4) Bartlomiej Zolnierkiewicz
2003-04-24 7:56 ` Jens Axboe
2003-04-23 18:24 ` [PATCH] 2.5.67-ac2 direct-IO for IDE taskfile ioctl (0/4) [resend] Bartlomiej Zolnierkiewicz
2003-04-23 22:35 ` [PATCH] 2.5.67-ac2 direct-IO for IDE taskfile ioctl (0/4) Andrew Morton
2003-04-23 22:09 ` Alan Cox
2003-04-23 22:58 ` Bartlomiej Zolnierkiewicz
2003-04-23 23:13 ` Andries Brouwer
2003-04-23 23:20 ` Andrew Morton
2003-04-24 0:02 ` Bartlomiej Zolnierkiewicz
2003-04-24 6:55 ` Jens Axboe
2003-04-24 2:27 ` Andre Hedrick
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20030424082331.GE8775@suse.de \
--to=axboe@suse.de \
--cc=B.Zolnierkiewicz@elka.pw.edu.pl \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=andre@linux-ide.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.