All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Cody <jcody@redhat.com>
To: Fam Zheng <famz@redhat.com>
Cc: kwolf@redhat.com, pbonzini@redhat.com, qemu-devel@nongnu.org,
	stefanha@redhat.com
Subject: Re: [Qemu-devel] [PATCH 3/8] block: implement reference count for BlockDriverState
Date: Thu, 25 Jul 2013 21:50:20 -0400	[thread overview]
Message-ID: <20130726015020.GB14128@localhost.localdomain> (raw)
In-Reply-To: <20130726011332.GC15504@T430s.redhat.com>

On Fri, Jul 26, 2013 at 09:13:32AM +0800, Fam Zheng wrote:
> On Thu, 07/25 09:15, Jeff Cody wrote:
> > On Thu, Jul 25, 2013 at 05:01:41PM +0800, Fam Zheng wrote:
> > > Introduce bdrv_ref/bdrv_unref to manage the lifecycle of
> > > BlockDriverState. They are unused for now but will used to replace
> > > bdrv_delete() later.
> > > 
> > > Signed-off-by: Fam Zheng <famz@redhat.com>
> > > ---
> > >  block.c                   | 22 ++++++++++++++++++++++
> > >  include/block/block.h     |  2 ++
> > >  include/block/block_int.h |  1 +
> > >  3 files changed, 25 insertions(+)
> > > 
> > > diff --git a/block.c b/block.c
> > > index 6cd39fa..6f7ad7f 100644
> > > --- a/block.c
> > > +++ b/block.c
> > > @@ -306,6 +306,7 @@ BlockDriverState *bdrv_new(const char *device_name)
> > >      bdrv_iostatus_disable(bs);
> > >      notifier_list_init(&bs->close_notifiers);
> > >      notifier_with_return_list_init(&bs->before_write_notifiers);
> > > +    bs->refcnt = 1;
> > >  
> > >      return bs;
> > >  }
> > > @@ -1511,6 +1512,9 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
> > >      /* dirty bitmap */
> > >      bs_dest->dirty_bitmap       = bs_src->dirty_bitmap;
> > >  
> > > +    /* reference count */
> > > +    bs_dest->refcnt             = bs_src->refcnt;
> > > +
> > >      /* job */
> > >      bs_dest->in_use             = bs_src->in_use;
> > >      bs_dest->job                = bs_src->job;
> > > @@ -4385,6 +4389,24 @@ int64_t bdrv_get_dirty_count(BlockDriverState *bs)
> > >      }
> > >  }
> > >  
> > > +/* Get a reference to bs */
> > > +void bdrv_ref(BlockDriverState *bs)
> > > +{
> > > +    bs->refcnt++;
> > > +}
> > > +
> > > +/* Release a previously grabbed reference to bs.
> > > + * If after releasing, reference count is zero, the BlockDriverState is
> > > + * deleted. */
> > > +void bdrv_unref(BlockDriverState *bs)
> > > +{
> > > +    assert(bs->refcnt > 0);
> > > +    if (--bs->refcnt == 0) {
> > > +        bdrv_close(bs);
> > > +        bdrv_delete(bs);
> > > +    }
> > > +}
> > 
> > The problem with this is that a caller to bdrv_unref() has no
> > way of knowing after calling bdrv_unref() if bs is still valid.  We
> > can't just set bs to NULL after calling bdrv_unref() as with
> > bdrv_delete(), because now it may not have been freed.
> > 
> By calling bdrv_unref, it means the caller is not going to use bs any
> more.  In other words, bdrv_unref() is a bdrv_delete() as seen by the
> caller, if bs is still valid pointer after unref, it's no longer safe
> for the caller: it can be freed by other code, in any time, but the
> caller can't know.

OK, I can go with that.  I can't think off the top of my head where
this would cause a problem if it is just used in place of current
bdrv_delete(), so long as everyone refs it when they should.

But then going with a bdrv_delete() equivalency model, I don't know if
it is appropriate to call bdrv_unref() in bdrv_detach_dev() (in patch
5/8).  Maybe all that is really needed there is some more cleanup in
the places that call bdrv_detach_dev(), and then it would be OK.
> 
> > Maybe bdrv_unref should either return the current bs pointer, or
> > alternatively accept as its argument a pointer to the BDS pointer:
> > 
> > void bdrv_unref(BlockDriverState **bs)
> > {
> >     assert(*bs->refcnt > 0);
> >     if (--*bs->refcnt == 0) {
> >         bdrv_close(*bs);
> >         bdrv_delete(*bs);
> >         *bs = NULL;
> >     }
> > }
> > 
> > Of course, all callers would need to then check for NULL.
> > 
> > Also, do we need to call bdrv_close() in here?  In bdrv_delete(),
> > bdrv_close() is called prior to the free.
> > 
> Yes, it can be omited.
> 
> > > +
> > >  void bdrv_set_in_use(BlockDriverState *bs, int in_use)
> > >  {
> > >      assert(bs->in_use != in_use);
> > > diff --git a/include/block/block.h b/include/block/block.h
> > > index 742fce5..b33ef62 100644
> > > --- a/include/block/block.h
> > > +++ b/include/block/block.h
> > > @@ -356,6 +356,8 @@ int64_t bdrv_get_dirty_count(BlockDriverState *bs);
> > >  void bdrv_enable_copy_on_read(BlockDriverState *bs);
> > >  void bdrv_disable_copy_on_read(BlockDriverState *bs);
> > >  
> > > +void bdrv_ref(BlockDriverState *bs);
> > > +void bdrv_unref(BlockDriverState *bs);
> > >  void bdrv_set_in_use(BlockDriverState *bs, int in_use);
> > >  int bdrv_in_use(BlockDriverState *bs);
> > >  
> > > diff --git a/include/block/block_int.h b/include/block/block_int.h
> > > index c6ac871..a282d56 100644
> > > --- a/include/block/block_int.h
> > > +++ b/include/block/block_int.h
> > > @@ -294,6 +294,7 @@ struct BlockDriverState {
> > >      BlockDeviceIoStatus iostatus;
> > >      char device_name[32];
> > >      HBitmap *dirty_bitmap;
> > > +    int refcnt;
> > >      int in_use; /* users other than guest access, eg. block migration */
> > >      QTAILQ_ENTRY(BlockDriverState) list;
> > >  
> > > -- 
> > > 1.8.3.2
> > > 
> > > 
> 
> -- 
> Fam

  reply	other threads:[~2013-07-26  1:50 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-25  9:01 [Qemu-devel] [PATCH 0/8] Implement reference count for BlockDriverState Fam Zheng
2013-07-25  9:01 ` [Qemu-devel] [PATCH 1/8] vvfat: use bdrv_new() to allocate BlockDriverState Fam Zheng
2013-07-25  9:01 ` [Qemu-devel] [PATCH 2/8] iscsi: use bdrv_new() instead of stack structure Fam Zheng
2013-07-25  9:01 ` [Qemu-devel] [PATCH 3/8] block: implement reference count for BlockDriverState Fam Zheng
2013-07-25 13:15   ` Jeff Cody
2013-07-26  1:13     ` Fam Zheng
2013-07-26  1:50       ` Jeff Cody [this message]
2013-07-26  1:56         ` Fam Zheng
2013-07-25  9:01 ` [Qemu-devel] [PATCH 4/8] block: make bdrv_delete() static Fam Zheng
2013-07-25  9:01 ` [Qemu-devel] [PATCH 5/8] block: use BlockDriverState refcnt for device attach/detach Fam Zheng
2013-07-25 12:49   ` Jeff Cody
2013-07-25  9:01 ` [Qemu-devel] [PATCH 6/8] migration: omit drive ref as we have bdrv_ref now Fam Zheng
2013-07-25  9:01 ` [Qemu-devel] [PATCH 7/8] xen_disk: simplify blk_disconnect with refcnt Fam Zheng
2013-07-25 12:56   ` Jeff Cody
2013-07-26  1:30     ` Jeff Cody
2013-07-25  9:01 ` [Qemu-devel] [PATCH 8/8] nbd: use BlockDriverState refcnt Fam Zheng
2013-07-25 13:01   ` Jeff Cody
2013-07-26  1:29     ` Jeff Cody

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=20130726015020.GB14128@localhost.localdomain \
    --to=jcody@redhat.com \
    --cc=famz@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /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.