From: "Adam J. Richter" <adam@yggdrasil.com>
To: linux-kernel@vger.kernel.org
Cc: akpm@zip.com.au, axboe@suse.de
Subject: bio_chain: proposed solution for bio_alloc failure and large IO simplification
Date: Thu, 13 Jun 2002 18:56:32 -0700 [thread overview]
Message-ID: <200206140156.SAA02512@baldur.yggdrasil.com> (raw)
In the course of working on potential kernel crashes in
ll_rw_kio and fs/mpage.c, I have been thinking that there has got
to be a better way to more efficiently construct large I/O requests,
and I now have an idea of how to do it, although it may at first
seem to be regressing back to struct buffer_head. Currently, most
block IO operations will at best generate IO errors if bio_alloc
starts to fail, and code that attempts to build big block IO's has
to be a bit complex to build bio's that are as big as possible but
still not too big or having too many IO vectors for whatever the
underlying device driver says it is willing to handle.
PROSOSAL: struct bio *bio_chain(struct bio* old);
newbio = bio_chain(oldbio);
would be similar to:
newbio = bio_alloc(GFP_KERNEL, 1);
newbio->bi_bdev = oldbio->bi_bdev;
newbio->bi_rw = oldbio->bi_rw;
submit_bio(oldio);
...except for two important differences:
1. bio_chain NEVER gets a memory allocation failure. If it is
not able to allocate any memory, it fiddles with old->bi_destructor
and waits for the "old" bio to complete, and returns the old bio.
This is important because most current block device drivers will, at
best, generate errors if they fail to allocate a bio.
2. bio_chain will set some kind of hint that newbio is
probably contiguous with oldbio. So, if oldbio is still on the
device queue when newbio is eventually submitted, the merge code
will first check the request that oldbio is in for merging. So,
the merging in that case will be O(1). Also, if bio_chain is also
used to submit newbio and it is able to do the merge, bio_chain can
simply return the bio that was going to be discarded by the merge,
since bio_chain is only defined to return a bio capable of holding
one IO vector and all bio's in a request meet that criterion, and
the bio being discarded by the merge will already have bi_bdev and
bi_rw set to the correct values if it was mergeable in the first
place.
I realize there may be locking issues in implementing this.
Under this scheme, code that wants to build up big bio's
can be much simpler, because it does not have to think about
q->max_phys_segments or q->max_hw_segments (it just has to make sure
that each request is smaller than q->max_sectors). Also, part of the
IO could be started earlier if the device is idle, although that
trade-off may not be worthwhile.
Code that builds up big bio's would look something like this:
/* Allocate a lot of iovecs in the first bio, so that
the merge code is less likely to have to do a memory
allocation */
bio = alloced_bio = bio_alloc(GFP_KERNEL, bio_max_iovecs(q));
if (!bio) { /* Work even if first bio_alloc in loop fails. */
up(&devprivate->backup_bio_mutex);
bio = devprivate->backup_bio;
}
bio->bi_bdev = bdev;
bio->bi_rw = rw;
bio->bi_vcnt = 1;
for(;;) {
bio->bi_sector = sector;
bio->bi_io_vec[0].bv_page = ...;
bio->bi_io_vec[0].bv_offset = ...;
bio->bi_io_vec[0].bv_len = ...;
if (last_one)
break;
bio = bio_chain(bio);
sector += ....;
}
if (alloced_bio)
submit_bio(bio);
else {
devprivate->backup_bio = bio_chain(bio);
down(&devprivate->backup_bio_mutex);
}
The bio_chain calls should be very fast in the normal repeating
case. They will immediately succeed in merging oldbio with the bio that
was submitted before and just return oldbio. Since oldbio already has
all of the correct values set, bio_chain does not need to fill anything
in in this case. So, while the loops is theoretically building up and
destroying bio's, is, really just assembling big bio's, at least in
terms of the CPU costs.
For performance reasons, the semantics of bio_chain could be
restricted further. For example, oldbio could be required to have
bi->bi_vcnt == 1 and bi->bi_idx == 0, and the bio_chain optimization
might only be done if the bio is submitted by bio_chain, not by
submit_bio, or perhaps we could even require that the bio returned by
bio_chain can only be submitted by bio_chain or freed.
By the way, I also want to implement a mechanism like this for
the USB requests to make them also impervious to memory allocation failures
after device initialization.
Adam J. Richter __ ______________ 575 Oroville Road
adam@yggdrasil.com \ / Milpitas, California 95035
+1 408 309-6081 | g g d r a s i l United States of America
"Free Software For The Rest Of Us."
next reply other threads:[~2002-06-14 1:56 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-06-14 1:56 Adam J. Richter [this message]
2002-06-14 2:24 ` Andreas Dilger
2002-06-14 14:57 ` Jens Axboe
2002-06-14 16:52 Adam J. Richter
2002-06-14 23:00 ` Andrew Morton
2002-06-14 23:29 ` William Lee Irwin III
2002-06-14 23:38 ` Andrew Morton
2002-06-15 7:55 ` Jens Axboe
2002-06-14 23:39 Adam J. Richter
2002-06-14 23:58 ` Andrew Morton
2002-06-15 1:38 ` Oliver Xymoron
2002-06-15 7:55 ` Jens Axboe
2002-06-15 0:22 Adam J. Richter
2002-06-15 4:38 Adam J. Richter
2002-06-15 8:45 Adam J. Richter
2002-06-15 8:50 ` Jens Axboe
2002-06-15 8:52 Adam J. Richter
2002-06-15 9:00 ` Jens Axboe
2002-06-15 9:10 Adam J. Richter
2002-06-15 9:14 ` Jens Axboe
2002-06-15 10:30 Adam J. Richter
2002-06-15 19:50 ` Andrew Morton
2002-06-17 6:36 ` Jens Axboe
2002-06-17 7:09 ` Andrew Morton
2002-06-15 20:01 Adam J. Richter
2002-06-15 20:22 ` Andrew Morton
2002-06-15 20:24 Adam J. Richter
2002-06-17 6:37 ` Jens Axboe
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=200206140156.SAA02512@baldur.yggdrasil.com \
--to=adam@yggdrasil.com \
--cc=akpm@zip.com.au \
--cc=axboe@suse.de \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®