Re: [Qemu-devel] [PATCH 3/4] block-backend: shift in-flight counter to BB from BDS

2017-08-09 Thread Kevin Wolf
Am 08.08.2017 um 19:57 hat John Snow geschrieben:
> From: Kevin Wolf 
> 
> This allows us to detect errors in cache flushing (ENOMEDIUM)
> without choking on a null dereference because we assume that
> blk_bs(bb) is always defined.
> 
> Signed-off-by: Kevin Wolf 
> Signed-off-by: John Snow 
> ---
>  block.c   |  2 +-
>  block/block-backend.c | 40 ++--
>  2 files changed, 35 insertions(+), 7 deletions(-)
> 
> diff --git a/block.c b/block.c
> index ce9cce7..834b836 100644
> --- a/block.c
> +++ b/block.c
> @@ -4476,7 +4476,7 @@ out:
>  
>  AioContext *bdrv_get_aio_context(BlockDriverState *bs)
>  {
> -return bs->aio_context;
> +return bs ? bs->aio_context : qemu_get_aio_context();
>  }

This should probably be a separate patch; it's not really related to
moving the in-flight counter, but fixes another NULL dereference in
blk_aio_prwv().

>  void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co)
> diff --git a/block/block-backend.c b/block/block-backend.c
> index 968438c..efd7e92 100644
> --- a/block/block-backend.c
> +++ b/block/block-backend.c
> @@ -68,6 +68,9 @@ struct BlockBackend {
>  NotifierList remove_bs_notifiers, insert_bs_notifiers;
>  
>  int quiesce_counter;
> +
> +/* Number of in-flight requests. Accessed with atomic ops. */
> +unsigned int in_flight;
>  };
>  
>  typedef struct BlockBackendAIOCB {
> @@ -1109,6 +1112,16 @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags 
> flags)
>  return bdrv_make_zero(blk->root, flags);
>  }
>  
> +static void blk_inc_in_flight(BlockBackend *blk)
> +{
> +atomic_inc(&blk->in_flight);
> +}
> +
> +static void blk_dec_in_flight(BlockBackend *blk)
> +{
> +atomic_dec(&blk->in_flight);
> +}
> +
>  static void error_callback_bh(void *opaque)
>  {
>  struct BlockBackendAIOCB *acb = opaque;
> @@ -1147,7 +1160,7 @@ static const AIOCBInfo blk_aio_em_aiocb_info = {
>  static void blk_aio_complete(BlkAioEmAIOCB *acb)
>  {
>  if (acb->has_returned) {
> -bdrv_dec_in_flight(acb->common.bs);
> +blk_dec_in_flight(acb->rwco.blk);
>  acb->common.cb(acb->common.opaque, acb->rwco.ret);
>  qemu_aio_unref(acb);
>  }
> @@ -1168,7 +1181,7 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, 
> int64_t offset, int bytes,
>  BlkAioEmAIOCB *acb;
>  Coroutine *co;
>  
> -bdrv_inc_in_flight(blk_bs(blk));
> +blk_inc_in_flight(blk);
>  acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
>  acb->rwco = (BlkRwCo) {
>  .blk= blk,
> @@ -1405,14 +1418,28 @@ int blk_flush(BlockBackend *blk)
>  
>  void blk_drain(BlockBackend *blk)
>  {
> -if (blk_bs(blk)) {
> -bdrv_drain(blk_bs(blk));
> +AioContext *ctx = blk_get_aio_context(blk);
> +
> +while (atomic_read(&blk->in_flight)) {
> +aio_context_acquire(ctx);
> +aio_poll(ctx, false);
> +aio_context_release(ctx);
> +
> +if (blk_bs(blk)) {
> +bdrv_drain(blk_bs(blk));
> +}
>  }
>  }
>  
>  void blk_drain_all(void)
>  {
> -bdrv_drain_all();
> +BlockBackend *blk = NULL;
> +
> +bdrv_drain_all_begin();
> +while ((blk = blk_all_next(blk)) != NULL) {
> +blk_drain(blk);
> +}
> +bdrv_drain_all_end();
>  }

We still need to check that everyone who should call blk_drain_all()
rather than bdrv_drain_all() actually does so.

>  void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
> @@ -1453,10 +1480,11 @@ static void send_qmp_error_event(BlockBackend *blk,
>   bool is_read, int error)
>  {
>  IoOperationType optype;
> +BlockDriverState *bs = blk_bs(blk);
>  
>  optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
>  qapi_event_send_block_io_error(blk_name(blk),
> -   bdrv_get_node_name(blk_bs(blk)), optype,
> +   bs ? bdrv_get_node_name(bs) : "", optype,
> action, blk_iostatus_is_enabled(blk),
> error == ENOSPC, strerror(error),
> &error_abort);

And this is another independent NULL dereference fix.

Kevin



Re: [Qemu-devel] [PATCH 3/4] block-backend: shift in-flight counter to BB from BDS

2017-08-08 Thread John Snow


On 08/08/2017 02:34 PM, Paolo Bonzini wrote:
> 
> 
> - Original Message -
>> From: "John Snow" 
>> To: qemu-bl...@nongnu.org
>> Cc: kw...@redhat.com, qemu-devel@nongnu.org, dgilb...@redhat.com, 
>> stefa...@redhat.com, pbonz...@redhat.com,
>> p...@redhat.com, "John Snow" 
>> Sent: Tuesday, August 8, 2017 7:57:10 PM
>> Subject: [PATCH 3/4] block-backend: shift in-flight counter to BB from BDS
>>
>> From: Kevin Wolf 
>>
>> This allows us to detect errors in cache flushing (ENOMEDIUM)
>> without choking on a null dereference because we assume that
>> blk_bs(bb) is always defined.
>>
>> Signed-off-by: Kevin Wolf 
>> Signed-off-by: John Snow 
> 
> This is not enough, as discussed in the thread.
> 
> Paolo
> 

Sure, I amended Kevin's later fix and rolled it into one patch and split
the tests out. The cover letter states that this is busted, but I wanted
it on the list instead of buried in a now-unrelated thread.

So now it's here as a patch, can we keep discussion here instead of on
the other thread?

--John



Re: [Qemu-devel] [PATCH 3/4] block-backend: shift in-flight counter to BB from BDS

2017-08-08 Thread Paolo Bonzini


- Original Message -
> From: "John Snow" 
> To: qemu-bl...@nongnu.org
> Cc: kw...@redhat.com, qemu-devel@nongnu.org, dgilb...@redhat.com, 
> stefa...@redhat.com, pbonz...@redhat.com,
> p...@redhat.com, "John Snow" 
> Sent: Tuesday, August 8, 2017 7:57:10 PM
> Subject: [PATCH 3/4] block-backend: shift in-flight counter to BB from BDS
> 
> From: Kevin Wolf 
> 
> This allows us to detect errors in cache flushing (ENOMEDIUM)
> without choking on a null dereference because we assume that
> blk_bs(bb) is always defined.
> 
> Signed-off-by: Kevin Wolf 
> Signed-off-by: John Snow 

This is not enough, as discussed in the thread.

Paolo

> ---
>  block.c   |  2 +-
>  block/block-backend.c | 40 ++--
>  2 files changed, 35 insertions(+), 7 deletions(-)
> 
> diff --git a/block.c b/block.c
> index ce9cce7..834b836 100644
> --- a/block.c
> +++ b/block.c
> @@ -4476,7 +4476,7 @@ out:
>  
>  AioContext *bdrv_get_aio_context(BlockDriverState *bs)
>  {
> -return bs->aio_context;
> +return bs ? bs->aio_context : qemu_get_aio_context();
>  }
>  
>  void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co)
> diff --git a/block/block-backend.c b/block/block-backend.c
> index 968438c..efd7e92 100644
> --- a/block/block-backend.c
> +++ b/block/block-backend.c
> @@ -68,6 +68,9 @@ struct BlockBackend {
>  NotifierList remove_bs_notifiers, insert_bs_notifiers;
>  
>  int quiesce_counter;
> +
> +/* Number of in-flight requests. Accessed with atomic ops. */
> +unsigned int in_flight;
>  };
>  
>  typedef struct BlockBackendAIOCB {
> @@ -1109,6 +1112,16 @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags
> flags)
>  return bdrv_make_zero(blk->root, flags);
>  }
>  
> +static void blk_inc_in_flight(BlockBackend *blk)
> +{
> +atomic_inc(&blk->in_flight);
> +}
> +
> +static void blk_dec_in_flight(BlockBackend *blk)
> +{
> +atomic_dec(&blk->in_flight);
> +}
> +
>  static void error_callback_bh(void *opaque)
>  {
>  struct BlockBackendAIOCB *acb = opaque;
> @@ -1147,7 +1160,7 @@ static const AIOCBInfo blk_aio_em_aiocb_info = {
>  static void blk_aio_complete(BlkAioEmAIOCB *acb)
>  {
>  if (acb->has_returned) {
> -bdrv_dec_in_flight(acb->common.bs);
> +blk_dec_in_flight(acb->rwco.blk);
>  acb->common.cb(acb->common.opaque, acb->rwco.ret);
>  qemu_aio_unref(acb);
>  }
> @@ -1168,7 +1181,7 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk,
> int64_t offset, int bytes,
>  BlkAioEmAIOCB *acb;
>  Coroutine *co;
>  
> -bdrv_inc_in_flight(blk_bs(blk));
> +blk_inc_in_flight(blk);
>  acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
>  acb->rwco = (BlkRwCo) {
>  .blk= blk,
> @@ -1405,14 +1418,28 @@ int blk_flush(BlockBackend *blk)
>  
>  void blk_drain(BlockBackend *blk)
>  {
> -if (blk_bs(blk)) {
> -bdrv_drain(blk_bs(blk));
> +AioContext *ctx = blk_get_aio_context(blk);
> +
> +while (atomic_read(&blk->in_flight)) {
> +aio_context_acquire(ctx);
> +aio_poll(ctx, false);
> +aio_context_release(ctx);
> +
> +if (blk_bs(blk)) {
> +bdrv_drain(blk_bs(blk));
> +}
>  }
>  }
>  
>  void blk_drain_all(void)
>  {
> -bdrv_drain_all();
> +BlockBackend *blk = NULL;
> +
> +bdrv_drain_all_begin();
> +while ((blk = blk_all_next(blk)) != NULL) {
> +blk_drain(blk);
> +}
> +bdrv_drain_all_end();
>  }
>  
>  void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
> @@ -1453,10 +1480,11 @@ static void send_qmp_error_event(BlockBackend *blk,
>   bool is_read, int error)
>  {
>  IoOperationType optype;
> +BlockDriverState *bs = blk_bs(blk);
>  
>  optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
>  qapi_event_send_block_io_error(blk_name(blk),
> -   bdrv_get_node_name(blk_bs(blk)), optype,
> +   bs ? bdrv_get_node_name(bs) : "", optype,
> action, blk_iostatus_is_enabled(blk),
> error == ENOSPC, strerror(error),
> &error_abort);
> --
> 2.9.4
> 
> 



[Qemu-devel] [PATCH 3/4] block-backend: shift in-flight counter to BB from BDS

2017-08-08 Thread John Snow
From: Kevin Wolf 

This allows us to detect errors in cache flushing (ENOMEDIUM)
without choking on a null dereference because we assume that
blk_bs(bb) is always defined.

Signed-off-by: Kevin Wolf 
Signed-off-by: John Snow 
---
 block.c   |  2 +-
 block/block-backend.c | 40 ++--
 2 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/block.c b/block.c
index ce9cce7..834b836 100644
--- a/block.c
+++ b/block.c
@@ -4476,7 +4476,7 @@ out:
 
 AioContext *bdrv_get_aio_context(BlockDriverState *bs)
 {
-return bs->aio_context;
+return bs ? bs->aio_context : qemu_get_aio_context();
 }
 
 void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co)
diff --git a/block/block-backend.c b/block/block-backend.c
index 968438c..efd7e92 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -68,6 +68,9 @@ struct BlockBackend {
 NotifierList remove_bs_notifiers, insert_bs_notifiers;
 
 int quiesce_counter;
+
+/* Number of in-flight requests. Accessed with atomic ops. */
+unsigned int in_flight;
 };
 
 typedef struct BlockBackendAIOCB {
@@ -1109,6 +1112,16 @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags 
flags)
 return bdrv_make_zero(blk->root, flags);
 }
 
+static void blk_inc_in_flight(BlockBackend *blk)
+{
+atomic_inc(&blk->in_flight);
+}
+
+static void blk_dec_in_flight(BlockBackend *blk)
+{
+atomic_dec(&blk->in_flight);
+}
+
 static void error_callback_bh(void *opaque)
 {
 struct BlockBackendAIOCB *acb = opaque;
@@ -1147,7 +1160,7 @@ static const AIOCBInfo blk_aio_em_aiocb_info = {
 static void blk_aio_complete(BlkAioEmAIOCB *acb)
 {
 if (acb->has_returned) {
-bdrv_dec_in_flight(acb->common.bs);
+blk_dec_in_flight(acb->rwco.blk);
 acb->common.cb(acb->common.opaque, acb->rwco.ret);
 qemu_aio_unref(acb);
 }
@@ -1168,7 +1181,7 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, 
int64_t offset, int bytes,
 BlkAioEmAIOCB *acb;
 Coroutine *co;
 
-bdrv_inc_in_flight(blk_bs(blk));
+blk_inc_in_flight(blk);
 acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
 acb->rwco = (BlkRwCo) {
 .blk= blk,
@@ -1405,14 +1418,28 @@ int blk_flush(BlockBackend *blk)
 
 void blk_drain(BlockBackend *blk)
 {
-if (blk_bs(blk)) {
-bdrv_drain(blk_bs(blk));
+AioContext *ctx = blk_get_aio_context(blk);
+
+while (atomic_read(&blk->in_flight)) {
+aio_context_acquire(ctx);
+aio_poll(ctx, false);
+aio_context_release(ctx);
+
+if (blk_bs(blk)) {
+bdrv_drain(blk_bs(blk));
+}
 }
 }
 
 void blk_drain_all(void)
 {
-bdrv_drain_all();
+BlockBackend *blk = NULL;
+
+bdrv_drain_all_begin();
+while ((blk = blk_all_next(blk)) != NULL) {
+blk_drain(blk);
+}
+bdrv_drain_all_end();
 }
 
 void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
@@ -1453,10 +1480,11 @@ static void send_qmp_error_event(BlockBackend *blk,
  bool is_read, int error)
 {
 IoOperationType optype;
+BlockDriverState *bs = blk_bs(blk);
 
 optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
 qapi_event_send_block_io_error(blk_name(blk),
-   bdrv_get_node_name(blk_bs(blk)), optype,
+   bs ? bdrv_get_node_name(bs) : "", optype,
action, blk_iostatus_is_enabled(blk),
error == ENOSPC, strerror(error),
&error_abort);
-- 
2.9.4