Re: bio_chain: proposed solution for bio_alloc failure and large IO

Andrew Morton (akpm@zip.com.au)
Sat, 15 Jun 2002 12:50:12 -0700


"Adam J. Richter" wrote:
>
> ...
> newbio = q->one_more_bvec(q, bio, page, offset, len);
>

That's a comfortable interface. Or maybe just:

struct bio *bio_add_bvec(bio, page, offset, len);

Couple of points:

- It's tricky to determine how many bvecs are available in
a bio. There is no straightforward "how big is it" field
in struct bio.

- AFAIK, there are no established conventions for BIO assembly.
We have conventions which state what the various fields do
while the BIO is being processed by the block layer, but not
for when the client is assembling the BIO.

What I did, and what I'd suggest as a convention is:

During BIO assembly, bi_vcnt indicates the maximum number of
bvecs which the BIO can hold. And bi_idx indexes the next-free
bvec within the BIO.

If you do this, *now* you have enough information to write
bio_add_bvec:

struct bio *bio_add_bvec(bio, page, offset, len)
{
if (block layer says bio is maximum size) ||
(bio->bi_idx == bio->bi_vcnt) {
bio->bi_vcnt = bio->bi_idx;
bio->bi_idx = 0;
submit_bio(bio); /* Caller has set up bi_end_io() */
bio = NULL;
} else {
bio->bi_io_vec[bio->bi_idx].page = page;
...
bio->bi_idx++;
}
return bio;
}

It returns NULL if the bio was sent so that the caller gets
to allocate the new BIO. If you want to allocate the new BIO
here you'll need to pass in gfp_flags and the new bio's
desired size as well. And copy that size into bi_vcnt.

ll_rw_kio() can be adapted to the above convention too, which will
simplify it a little.

-
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/