qemu-block
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-block] [PULL 01/31] block: Fix bdrv_next() memory leak


From: Paolo Bonzini
Subject: Re: [Qemu-block] [PULL 01/31] block: Fix bdrv_next() memory leak
Date: Mon, 6 Jun 2016 10:41:13 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0


On 25/05/2016 19:39, Kevin Wolf wrote:
> @@ -395,20 +399,27 @@ int bdrv_all_delete_snapshot(const char *name, 
> BlockDriverState **first_bad_bs,
>  {
>      int ret = 0;
>      BlockDriverState *bs;
> -    BdrvNextIterator *it = NULL;
> +    BdrvNextIterator it;
>      QEMUSnapshotInfo sn1, *snapshot = &sn1;
>  
> -    while (ret == 0 && (it = bdrv_next(it, &bs))) {
> +    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
>          AioContext *ctx = bdrv_get_aio_context(bs);
>  
>          aio_context_acquire(ctx);
>          if (bdrv_can_snapshot(bs) &&
>                  bdrv_snapshot_find(bs, snapshot, name) >= 0) {
>              ret = bdrv_snapshot_delete_by_id_or_name(bs, name, err);
> +            if (ret < 0) {
> +                goto fail;
> +            }

This is redundant with the check below (and the check below is right;
this one is wrong).

Thanks,

Paolo

>          }
>          aio_context_release(ctx);
> +        if (ret < 0) {
> +            goto fail;
> +        }
>      }
>  
> +fail:
>      *first_bad_bs = bs;
>      return ret;
>  }
> @@ -418,9 +429,9 @@ int bdrv_all_goto_snapshot(const char *name, 
> BlockDriverState **first_bad_bs)
>  {
>      int err = 0;
>      BlockDriverState *bs;
> -    BdrvNextIterator *it = NULL;
> +    BdrvNextIterator it;
>  
> -    while (err == 0 && (it = bdrv_next(it, &bs))) {
> +    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
>          AioContext *ctx = bdrv_get_aio_context(bs);
>  
>          aio_context_acquire(ctx);
> @@ -428,8 +439,12 @@ int bdrv_all_goto_snapshot(const char *name, 
> BlockDriverState **first_bad_bs)
>              err = bdrv_snapshot_goto(bs, name);
>          }
>          aio_context_release(ctx);
> +        if (err < 0) {
> +            goto fail;
> +        }
>      }
>  
> +fail:
>      *first_bad_bs = bs;
>      return err;
>  }
> @@ -439,9 +454,9 @@ int bdrv_all_find_snapshot(const char *name, 
> BlockDriverState **first_bad_bs)
>      QEMUSnapshotInfo sn;
>      int err = 0;
>      BlockDriverState *bs;
> -    BdrvNextIterator *it = NULL;
> +    BdrvNextIterator it;
>  
> -    while (err == 0 && (it = bdrv_next(it, &bs))) {
> +    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
>          AioContext *ctx = bdrv_get_aio_context(bs);
>  
>          aio_context_acquire(ctx);
> @@ -449,8 +464,12 @@ int bdrv_all_find_snapshot(const char *name, 
> BlockDriverState **first_bad_bs)
>              err = bdrv_snapshot_find(bs, &sn, name);
>          }
>          aio_context_release(ctx);
> +        if (err < 0) {
> +            goto fail;
> +        }
>      }
>  
> +fail:
>      *first_bad_bs = bs;
>      return err;
>  }
> @@ -462,9 +481,9 @@ int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn,
>  {
>      int err = 0;
>      BlockDriverState *bs;
> -    BdrvNextIterator *it = NULL;
> +    BdrvNextIterator it;
>  
> -    while (err == 0 && (it = bdrv_next(it, &bs))) {
> +    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
>          AioContext *ctx = bdrv_get_aio_context(bs);
>  
>          aio_context_acquire(ctx);
> @@ -476,24 +495,32 @@ int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn,
>              err = bdrv_snapshot_create(bs, sn);
>          }
>          aio_context_release(ctx);
> +        if (err < 0) {
> +            goto fail;
> +        }
>      }
>  
> +fail:
>      *first_bad_bs = bs;
>      return err;
>  }
>  
>  BlockDriverState *bdrv_all_find_vmstate_bs(void)
>  {
> -    bool not_found = true;
>      BlockDriverState *bs;
> -    BdrvNextIterator *it = NULL;
> +    BdrvNextIterator it;
>  
> -    while (not_found && (it = bdrv_next(it, &bs))) {
> +    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
>          AioContext *ctx = bdrv_get_aio_context(bs);
> +        bool found;
>  
>          aio_context_acquire(ctx);
> -        not_found = !bdrv_can_snapshot(bs);
> +        found = bdrv_can_snapshot(bs);
>          aio_context_release(ctx);
> +
> +        if (found) {
> +            break;
> +        }
>      }
>      return bs;
>  }
> diff --git a/blockdev.c b/blockdev.c
> index 40e4e6f..0e37e09 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -4164,9 +4164,9 @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
>  {
>      BlockJobInfoList *head = NULL, **p_next = &head;
>      BlockDriverState *bs;
> -    BdrvNextIterator *it = NULL;
> +    BdrvNextIterator it;
>  
> -    while ((it = bdrv_next(it, &bs))) {
> +    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
>          AioContext *aio_context = bdrv_get_aio_context(bs);
>  
>          aio_context_acquire(aio_context);
> diff --git a/include/block/block.h b/include/block/block.h
> index a8c15e3..770ca26 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -17,7 +17,6 @@ typedef struct BlockJob BlockJob;
>  typedef struct BdrvChild BdrvChild;
>  typedef struct BdrvChildRole BdrvChildRole;
>  typedef struct BlockJobTxn BlockJobTxn;
> -typedef struct BdrvNextIterator BdrvNextIterator;
>  
>  typedef struct BlockDriverInfo {
>      /* in bytes, 0 if irrelevant */
> @@ -402,7 +401,19 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
>                                   Error **errp);
>  bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base);
>  BlockDriverState *bdrv_next_node(BlockDriverState *bs);
> -BdrvNextIterator *bdrv_next(BdrvNextIterator *it, BlockDriverState **bs);
> +
> +typedef struct BdrvNextIterator {
> +    enum {
> +        BDRV_NEXT_BACKEND_ROOTS,
> +        BDRV_NEXT_MONITOR_OWNED,
> +    } phase;
> +    BlockBackend *blk;
> +    BlockDriverState *bs;
> +} BdrvNextIterator;
> +
> +BlockDriverState *bdrv_first(BdrvNextIterator *it);
> +BlockDriverState *bdrv_next(BdrvNextIterator *it);
> +
>  BlockDriverState *bdrv_next_monitor_owned(BlockDriverState *bs);
>  int bdrv_is_encrypted(BlockDriverState *bs);
>  int bdrv_key_required(BlockDriverState *bs);
> diff --git a/migration/block.c b/migration/block.c
> index a7a76a0..e0628d1 100644
> --- a/migration/block.c
> +++ b/migration/block.c
> @@ -383,7 +383,7 @@ static void init_blk_migration(QEMUFile *f)
>      BlockDriverState *bs;
>      BlkMigDevState *bmds;
>      int64_t sectors;
> -    BdrvNextIterator *it = NULL;
> +    BdrvNextIterator it;
>  
>      block_mig_state.submitted = 0;
>      block_mig_state.read_done = 0;
> @@ -394,7 +394,7 @@ static void init_blk_migration(QEMUFile *f)
>      block_mig_state.zero_blocks = migrate_zero_blocks();
>  
>  
> -    while ((it = bdrv_next(it, &bs))) {
> +    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
>          if (bdrv_is_read_only(bs)) {
>              continue;
>          }
> diff --git a/monitor.c b/monitor.c
> index 6a32b9b..404d594 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -3432,12 +3432,12 @@ static void vm_completion(ReadLineState *rs, const 
> char *str)
>  {
>      size_t len;
>      BlockDriverState *bs;
> -    BdrvNextIterator *it = NULL;
> +    BdrvNextIterator it;
>  
>      len = strlen(str);
>      readline_set_completion_index(rs, len);
>  
> -    while ((it = bdrv_next(it, &bs))) {
> +    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
>          SnapshotInfoList *snapshots, *snapshot;
>          AioContext *ctx = bdrv_get_aio_context(bs);
>          bool ok = false;
> diff --git a/qmp.c b/qmp.c
> index 8f8ae3a..3165f87 100644
> --- a/qmp.c
> +++ b/qmp.c
> @@ -181,7 +181,7 @@ void qmp_cont(Error **errp)
>      Error *local_err = NULL;
>      BlockBackend *blk;
>      BlockDriverState *bs;
> -    BdrvNextIterator *it;
> +    BdrvNextIterator it;
>  
>      /* if there is a dump in background, we should wait until the dump
>       * finished */
> @@ -201,8 +201,7 @@ void qmp_cont(Error **errp)
>          blk_iostatus_reset(blk);
>      }
>  
> -    it = NULL;
> -    while ((it = bdrv_next(it, &bs))) {
> +    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
>          bdrv_add_key(bs, NULL, &local_err);
>          if (local_err) {
>              error_propagate(errp, local_err);
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]