func: static int img_commit(int argc, char **argv)
  
  {
  
      int c, ret, flags;
  
      const char *filename, *fmt, *cache, *base;
  
      BlockBackend *blk;
  
      BlockDriverState *bs, *base_bs;
  
      bool progress = false, quiet = false, drop = false;
  
      bool writethrough;
  
      Error *local_err = NULL;
  
      CommonBlockJobCBInfo cbi;
  
      bool image_opts = false;
  
      AioContext *aio_context;
  
  
  
      fmt = NULL;
  
      cache = BDRV_DEFAULT_CACHE;
  
      base = NULL;
  
      for(;;) {
  
          static const struct option long_options[] = {
  
              {"help", no_argument, 0, 'h'},
  
              {"object", required_argument, 0, OPTION_OBJECT},
  
              {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
  
              {0, 0, 0, 0}
  
          };
  
          c = getopt_long(argc, argv, "f:ht:b:dpq",
  
                          long_options, NULL);
  
          if (c == -1) {
  
              break;
  
          }
  
          switch(c) {
  
          case '?':
  
          case 'h':
  
              help();
  
              break;
  
          case 'f':
  
              fmt = optarg;
  
              break;
  
          case 't':
  
              cache = optarg;
  
              break;
  
          case 'b':
  
              base = optarg;
  
              /* -b implies -d */
  
              drop = true;
  
              break;
  
          case 'd':
  
              drop = true;
  
              break;
  
          case 'p':
  
              progress = true;
  
              break;
  
          case 'q':
  
              quiet = true;
  
              break;
  
          case OPTION_OBJECT: {
  
              QemuOpts *opts;
  
              opts = qemu_opts_parse_noisily(&qemu_object_opts,
  
                                             optarg, true);
  
              if (!opts) {
  
                  return 1;
  
              }
  
          }   break;
  
          case OPTION_IMAGE_OPTS:
  
              image_opts = true;
  
              break;
  
          }
  
      }
  
  
  
      /* Progress is not shown in Quiet mode */
  
      if (quiet) {
  
          progress = false;
  
      }
  
  
  
      if (optind != argc - 1) {
  
          error_exit("Expecting one image file name");
  
      }
  
      filename = argv[optind++];
  
  
  
      if (qemu_opts_foreach(&qemu_object_opts,
  
                            user_creatable_add_opts_foreach,
  
                            NULL, NULL)) {
  
          return 1;
  
      }
  
  
  
      flags = BDRV_O_RDWR | BDRV_O_UNMAP;
  
      ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
  
      if (ret < 0) {
  
          error_report("Invalid cache option: %s", cache);
  
          return 1;
  
      }
  
  
  
      blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet);
  
      if (!blk) {
  
          return 1;
  
      }
  
      bs = blk_bs(blk);
  
  
  
      qemu_progress_init(progress, 1.f);
  
      qemu_progress_print(0.f, 100);
  
  
  
      if (base) {
  
          base_bs = bdrv_find_backing_image(bs, base);
  
          if (!base_bs) {
  
              error_setg(&local_err, QERR_BASE_NOT_FOUND, base);
  
              goto done;
  
          }
  
      } else {
  
          /* This is different from QMP, which by default uses the deepest file in
  
           * the backing chain (i.e., the very base); however, the traditional
  
           * behavior of qemu-img commit is using the immediate backing file. */
  
          base_bs = backing_bs(bs);
  
          if (!base_bs) {
  
              error_setg(&local_err, "Image does not have a backing file");
  
              goto done;
  
          }
  
      }
  
  
  
      cbi = (CommonBlockJobCBInfo){
  
          .errp = &local_err,
  
          .bs   = bs,
  
      };
  
  
  
      aio_context = bdrv_get_aio_context(bs);
  
      aio_context_acquire(aio_context);
  
      commit_active_start("commit", bs, base_bs, BLOCK_JOB_DEFAULT, 0,
  
                          BLOCKDEV_ON_ERROR_REPORT, common_block_job_cb, &cbi,
  
                          &local_err, false);
  
      aio_context_release(aio_context);
  
      if (local_err) {
  
          goto done;
  
      }
  
  
  
      /* When the block job completes, the BlockBackend reference will point to
  
       * the old backing file. In order to avoid that the top image is already
  
       * deleted, so we can still empty it afterwards, increment the reference
  
       * counter here preemptively. */
  
      if (!drop) {
  
          bdrv_ref(bs);
  
      }
  
  
  
      run_block_job(bs->job, &local_err);
  
      if (local_err) {
  
          goto unref_backing;
  
      }
  
  
  
      if (!drop && bs->drv->bdrv_make_empty) {
  
          ret = bs->drv->bdrv_make_empty(bs);
  
          if (ret) {
  
              error_setg_errno(&local_err, -ret, "Could not empty %s",
  
                               filename);
  
              goto unref_backing;
  
          }
  
      }
  
  
  
  unref_backing:
  
      if (!drop) {
  
          bdrv_unref(bs);
  
      }
  
  
  
  done:
  
      qemu_progress_end();
  
  
  
      blk_unref(blk);
  
  
  
      if (local_err) {
  
          error_report_err(local_err);
  
          return 1;
  
      }
  
  
  
      qprintf(quiet, "Image committed.\n");
  
      return 0;
  
  }
  