Re: [PATCH 00/18] block: Introduce a block graph rwlock

2022-12-12 Thread Kevin Wolf
Am 07.12.2022 um 15:12 hat Emanuele Giuseppe Esposito geschrieben:
> Am 07/12/2022 um 14:18 schrieb Kevin Wolf:
> > This series supersedes the first half of Emanuele's "Protect the block
> > layer with a rwlock: part 1". It introduces the basic infrastructure for
> > protecting the block graph (specifically parent/child links) with a
> > rwlock. Actually taking the reader lock in all necessary places is left
> > for future series.
> > 
> > Compared to Emanuele's series, this one adds patches to make use of
> > clang's Thread Safety Analysis (TSA) feature in order to statically
> > check at compile time that the places where we assert that we hold the
> > lock actually do hold it. Once we cover all relevant places, the check
> > can be extended to verify that all accesses of bs->children and
> > bs->parents hold the lock.
> > 
> > For reference, here is the more detailed version of our plan in
> > Emanuele's words from his series:
> > 
> > The aim is to replace the current AioContext lock with much
> > fine-grained locks, aimed to protect only specific data. Currently
> > the AioContext lock is used pretty much everywhere, and it's not
> > even clear what it is protecting exactly.
> > 
> > The aim of the rwlock is to cover graph modifications: more
> > precisely, when a BlockDriverState parent or child list is modified
> > or read, since it can be concurrently accessed by the main loop and
> > iothreads.
> > 
> > The main assumption is that the main loop is the only one allowed to
> > perform graph modifications, and so far this has always been held by
> > the current code.
> > 
> > The rwlock is inspired from cpus-common.c implementation, and aims
> > to reduce cacheline bouncing by having per-aiocontext counter of
> > readers.  All details and implementation of the lock are in patch 2.
> > 
> > We distinguish between writer (main loop, under BQL) that modifies
> > the graph, and readers (all other coroutines running in various
> > AioContext), that go through the graph edges, reading ->parents
> > and->children.  The writer (main loop)  has an "exclusive" access,
> > so it first waits for current read to finish, and then prevents
> > incoming ones from entering while it has the exclusive access.  The
> > readers (coroutines in multiple AioContext) are free to access the
> > graph as long the writer is not modifying the graph.  In case it is,
> > they go in a CoQueue and sleep until the writer is done.
> > 
> > In this and following series, we try to follow the following locking
> > pattern:
> > 
> > - bdrv_co_* functions that call BlockDriver callbacks always expect
> >   the lock to be taken, therefore they assert.
> > 
> > - blk_co_* functions are called from external code outside the block
> >   layer, which should not have to care about the block layer's
> >   internal locking. Usually they also call blk_wait_while_drained().
> >   Therefore they take the lock internally.
> > 
> > The long term goal of this series is to eventually replace the
> > AioContext lock, so that we can get rid of it once and for all.
> > 
> > Emanuele Giuseppe Esposito (7):
> >   graph-lock: Implement guard macros
> >   async: Register/unregister aiocontext in graph lock list
> >   block: wrlock in bdrv_replace_child_noperm
> >   block: remove unnecessary assert_bdrv_graph_writable()
> >   block: assert that graph read and writes are performed correctly
> >   block-coroutine-wrapper.py: introduce annotations that take the graph
> > rdlock
> >   block: use co_wrapper_mixed_bdrv_rdlock in functions taking the rdlock
> > 
> > Kevin Wolf (10):
> >   block: Factor out bdrv_drain_all_begin_nopoll()
> >   Import clang-tsa.h
> >   clang-tsa: Add TSA_ASSERT() macro
> >   clang-tsa: Add macros for shared locks
> >   configure: Enable -Wthread-safety if present
> >   test-bdrv-drain: Fix incorrrect drain assumptions
> >   block: Fix locking in external_snapshot_prepare()
> >   graph-lock: TSA annotations for lock/unlock functions
> >   Mark assert_bdrv_graph_readable/writable() GRAPH_RD/WRLOCK
> >   block: GRAPH_RDLOCK for functions only called by co_wrappers
> > 
> > Paolo Bonzini (1):
> >   graph-lock: Introduce a lock to protect block graph operations
> > 
> Reviewed-by: Emanuele Giuseppe Esposito 

Thanks, applied to block-next.

Kevin




Re: [PATCH 00/18] block: Introduce a block graph rwlock

2022-12-07 Thread Kevin Wolf
Am 07.12.2022 um 15:12 hat Emanuele Giuseppe Esposito geschrieben:
> > Emanuele Giuseppe Esposito (7):
> >   graph-lock: Implement guard macros
> >   async: Register/unregister aiocontext in graph lock list
> >   block: wrlock in bdrv_replace_child_noperm
> >   block: remove unnecessary assert_bdrv_graph_writable()
> >   block: assert that graph read and writes are performed correctly
> >   block-coroutine-wrapper.py: introduce annotations that take the graph
> > rdlock
> >   block: use co_wrapper_mixed_bdrv_rdlock in functions taking the rdlock
> > 
> > Kevin Wolf (10):
> >   block: Factor out bdrv_drain_all_begin_nopoll()
> >   Import clang-tsa.h
> >   clang-tsa: Add TSA_ASSERT() macro
> >   clang-tsa: Add macros for shared locks
> >   configure: Enable -Wthread-safety if present
> >   test-bdrv-drain: Fix incorrrect drain assumptions
> >   block: Fix locking in external_snapshot_prepare()
> >   graph-lock: TSA annotations for lock/unlock functions
> >   Mark assert_bdrv_graph_readable/writable() GRAPH_RD/WRLOCK
> >   block: GRAPH_RDLOCK for functions only called by co_wrappers
> > 
> > Paolo Bonzini (1):
> >   graph-lock: Introduce a lock to protect block graph operations
> > 
> Reviewed-by: Emanuele Giuseppe Esposito 

Thanks!

> ^ I am curious to see if I am allowed to have my r-b also on my patches :)

That's actually a good question. I wondered myself whether I should add
my R-b to patches that I picked up from you, but which already have my
S-o-b now, of course, and are possibly modified by me.

I would say you're allowed as long as you actually reviewed them in the
version I sent to make sure that I didn't mess them up. :-)
And similarly I'll probably add my R-b on patches that contain code from
you.

Kevin




Re: [PATCH 00/18] block: Introduce a block graph rwlock

2022-12-07 Thread Emanuele Giuseppe Esposito



Am 07/12/2022 um 14:18 schrieb Kevin Wolf:
> This series supersedes the first half of Emanuele's "Protect the block
> layer with a rwlock: part 1". It introduces the basic infrastructure for
> protecting the block graph (specifically parent/child links) with a
> rwlock. Actually taking the reader lock in all necessary places is left
> for future series.
> 
> Compared to Emanuele's series, this one adds patches to make use of
> clang's Thread Safety Analysis (TSA) feature in order to statically
> check at compile time that the places where we assert that we hold the
> lock actually do hold it. Once we cover all relevant places, the check
> can be extended to verify that all accesses of bs->children and
> bs->parents hold the lock.
> 
> For reference, here is the more detailed version of our plan in
> Emanuele's words from his series:
> 
> The aim is to replace the current AioContext lock with much
> fine-grained locks, aimed to protect only specific data. Currently
> the AioContext lock is used pretty much everywhere, and it's not
> even clear what it is protecting exactly.
> 
> The aim of the rwlock is to cover graph modifications: more
> precisely, when a BlockDriverState parent or child list is modified
> or read, since it can be concurrently accessed by the main loop and
> iothreads.
> 
> The main assumption is that the main loop is the only one allowed to
> perform graph modifications, and so far this has always been held by
> the current code.
> 
> The rwlock is inspired from cpus-common.c implementation, and aims
> to reduce cacheline bouncing by having per-aiocontext counter of
> readers.  All details and implementation of the lock are in patch 2.
> 
> We distinguish between writer (main loop, under BQL) that modifies
> the graph, and readers (all other coroutines running in various
> AioContext), that go through the graph edges, reading ->parents
> and->children.  The writer (main loop)  has an "exclusive" access,
> so it first waits for current read to finish, and then prevents
> incoming ones from entering while it has the exclusive access.  The
> readers (coroutines in multiple AioContext) are free to access the
> graph as long the writer is not modifying the graph.  In case it is,
> they go in a CoQueue and sleep until the writer is done.
> 
> In this and following series, we try to follow the following locking
> pattern:
> 
> - bdrv_co_* functions that call BlockDriver callbacks always expect
>   the lock to be taken, therefore they assert.
> 
> - blk_co_* functions are called from external code outside the block
>   layer, which should not have to care about the block layer's
>   internal locking. Usually they also call blk_wait_while_drained().
>   Therefore they take the lock internally.
> 
> The long term goal of this series is to eventually replace the
> AioContext lock, so that we can get rid of it once and for all.
> 
> Emanuele Giuseppe Esposito (7):
>   graph-lock: Implement guard macros
>   async: Register/unregister aiocontext in graph lock list
>   block: wrlock in bdrv_replace_child_noperm
>   block: remove unnecessary assert_bdrv_graph_writable()
>   block: assert that graph read and writes are performed correctly
>   block-coroutine-wrapper.py: introduce annotations that take the graph
> rdlock
>   block: use co_wrapper_mixed_bdrv_rdlock in functions taking the rdlock
> 
> Kevin Wolf (10):
>   block: Factor out bdrv_drain_all_begin_nopoll()
>   Import clang-tsa.h
>   clang-tsa: Add TSA_ASSERT() macro
>   clang-tsa: Add macros for shared locks
>   configure: Enable -Wthread-safety if present
>   test-bdrv-drain: Fix incorrrect drain assumptions
>   block: Fix locking in external_snapshot_prepare()
>   graph-lock: TSA annotations for lock/unlock functions
>   Mark assert_bdrv_graph_readable/writable() GRAPH_RD/WRLOCK
>   block: GRAPH_RDLOCK for functions only called by co_wrappers
> 
> Paolo Bonzini (1):
>   graph-lock: Introduce a lock to protect block graph operations
> 
Reviewed-by: Emanuele Giuseppe Esposito 

^ I am curious to see if I am allowed to have my r-b also on my patches :)

>  configure  |   1 +
>  block/coroutines.h |  19 +-
>  include/block/aio.h|   9 +
>  include/block/block-common.h   |   9 +-
>  include/block/block-global-state.h |   1 +
>  include/block/block-io.h   |  53 +++--
>  include/block/block_int-common.h   |  24 +--
>  include/block/block_int-global-state.h |  17 --
>  include/block/block_int.h  |   1 +
>  include/block/graph-lock.h | 280 +
>  include/qemu/clang-tsa.h   | 114 ++
>  block.c|  24 ++-
>  block/graph-lock.c | 275 
>  block/io.c |  21 +-
>  blockdev.c