[Drbd-dev] Re: [DRBD-cvs] r1743 - in branches/drbd-0.7: . drbd
Jens Axboe
axboe at suse.de
Thu Feb 3 09:38:49 CET 2005
On Wed, Feb 02 2005, Philipp Reisner wrote:
> Am Mittwoch, 2. Februar 2005 11:13 schrieb Lars Marowsky-Bree:
> > On 2005-02-01T18:36:43, Philipp Reisner <philipp.reisner at linbit.com> wrote:
> > > I did not look at the comments, I read the code. And what I read there
> > > was: a BIO has after bio_init() a refcount (bi_cnt) of 1. It is freed
> > > when the refcount drops to zero.
> > >
> > > bio_alloc();
> > > do something with it
> >
> > "submit_bio()" is slightly different from just "something".
>
> in which regard ? We should not free it while we do something
> with it.. that is true for something and for submit_bio() :)
>
> > > bio_put();
> > >
> > > is right.
> > >
> > > What you did is:
> > >
> > > bio_alloc();
> > > bio_get(); // increase to 2
> > > bio_put(); // decreat to 1
> > >
> > > and let it live forever...
> >
> > The cleanup at the end of the bio processing however should drop the bio
> > reference count too. Which is why the comment in bio.h says what it is.
> > Either the comment is wrong (and Jens's very same fix for the md code,
> > too), or you have introduced a race condition into the actlog.
>
> Why do you not simply read the code ?
>
> Right in case you return from the function that alocated the bio, then
> it is a good idea to use the reference counting to make the completion
> handler to free it. This would be something like this:
>
> STATIC int _drbd_md_async_page_io(...)
> {
> struct bio *bio = bio_alloc(GFP_KERNEL, 1);
>
> bio->bi_end_io = drbd_md_io_complete_a;
> submit_bio(rw, bio);
>
> return;
> }
>
> You see, there is no single bio_get() or bio_put() ... What refcount
> will the bio have ? Right it will have one (1), so the bio lives on...
That's because you don't touch the bio after submit_bio(), if you did
you would need to grab a reference to it.
> After some while, when the disk was so nice to write our request the
> bio completion function would be called:
>
> int drbd_md_io_complete_a(struct bio *bio, unsigned int bytes_done, int error)
> {
> if (bio->bi_size)
> return 1;
>
> put_bio(bio);
> return 0;
> }
>
> And here we would decrease the BIOs refcount to 0 and free it.
>
> BUT the function we talk about has SYNCHRONOUS semantics! Otherwise
> it would have never worked with a BIO on the stack... Read carefull:
>
> STATIC int _drbd_md_sync_page_io(drbd_dev *mdev, struct page *page,
> sector_t sector, int rw, int size)
> {
> struct bio *bio = bio_alloc(GFP_KERNEL, 1);
>
> bio->bi_end_io = drbd_md_io_complete;
>
> wait_for_completion(&event);
>
> bio_put(bio);
> return ok;
> }
>
> and the corresponding io-completion function:
>
> int drbd_md_io_complete(struct bio *bio, unsigned int bytes_done, int error)
> {
> if (bio->bi_size)
> return 1;
>
> complete((struct completion*)bio->bi_private);
> return 0;
> }
That matching pair is fine.
> So our _drbd_md_sync_page_io() sleeps in wait_for_completion() until the
> whole action is carried out, and then ... in the same scope where I allocated
> the bio I free it by calling bio_put() ---
> I could do it on the stack -- But I should use bio_init() the...
>
> Jens:
> Please tell Lars that I am right on how the refcounting works.
It seems you are. The md fix is actually leaky, since the bio_end_io
doesn't put the bio. An oversight on my behalf. It's only called only
called on init so no continual leak.
> And, BTW, is there any reason to not have a BIO on the stack ?
> Besides people return from the function before the completion callback
> was called ?
>
> In other words: Might something below me increase the refcount of the
> BIO and keep the reference even after my IO completion function was
> called ?
That's a good point. On-stack objects really interfer with reference
counting, such as used by bios. We had trouble with this and struct
requests in the future as well, so I would really discourage on-stack
bios completely. I'll make sure that there are no in-kernel uses of this
soonish, probably with a little WARN_ON() to catch out of tree uses as
well.
--
Jens Axboe
More information about the drbd-dev
mailing list