func: static int init_blk_migration(QEMUFile *f)
  
  {
  
      BlockDriverState *bs;
  
      BlkMigDevState *bmds;
  
      int64_t sectors;
  
      BdrvNextIterator it;
  
      int i, num_bs = 0;
  
      struct {
  
          BlkMigDevState *bmds;
  
          BlockDriverState *bs;
  
      } *bmds_bs;
  
      Error *local_err = NULL;
  
      int ret;
  
  
  
      block_mig_state.submitted = 0;
  
      block_mig_state.read_done = 0;
  
      block_mig_state.transferred = 0;
  
      block_mig_state.total_sector_sum = 0;
  
      block_mig_state.prev_progress = -1;
  
      block_mig_state.bulk_completed = 0;
  
      block_mig_state.zero_blocks = migrate_zero_blocks();
  
  
  
      for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
  
          num_bs++;
  
      }
  
      bmds_bs = g_malloc0(num_bs * sizeof(*bmds_bs));
  
  
  
      for (i = 0, bs = bdrv_first(&it); bs; bs = bdrv_next(&it), i++) {
  
          if (bdrv_is_read_only(bs)) {
  
              continue;
  
          }
  
  
  
          sectors = bdrv_nb_sectors(bs);
  
          if (sectors <= 0) {
  
              ret = sectors;
  
  
              goto out;
  
          }
  
  
  
          bmds = g_new0(BlkMigDevState, 1);
  
          bmds->blk = blk_new(BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
  
          bmds->blk_name = g_strdup(bdrv_get_device_name(bs));
  
          bmds->bulk_completed = 0;
  
          bmds->total_sectors = sectors;
  
          bmds->completed_sectors = 0;
  
          bmds->shared_base = migrate_use_block_incremental();
  
  
  
          assert(i < num_bs);
  
          bmds_bs[i].bmds = bmds;
  
          bmds_bs[i].bs = bs;
  
  
  
          block_mig_state.total_sector_sum += sectors;
  
  
  
          if (bmds->shared_base) {
  
              DPRINTF("Start migration for %s with shared base image\n",
  
                      bdrv_get_device_name(bs));
  
          } else {
  
              DPRINTF("Start full migration for %s\n", bdrv_get_device_name(bs));
  
          }
  
  
  
          QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
  
      }
  
  
  
      /* Can only insert new BDSes now because doing so while iterating block
  
       * devices may end up in a deadlock (iterating the new BDSes, too). */
  
      for (i = 0; i < num_bs; i++) {
  
          BlkMigDevState *bmds = bmds_bs[i].bmds;
  
          BlockDriverState *bs = bmds_bs[i].bs;
  
  
  
          if (bmds) {
  
              ret = blk_insert_bs(bmds->blk, bs, &local_err);
  
              if (ret < 0) {
  
                  error_report_err(local_err);
  
                  goto out;
  
              }
  
  
  
              alloc_aio_bitmap(bmds);
  
              error_setg(&bmds->blocker, "block device is in use by migration");
  
              bdrv_op_block_all(bs, bmds->blocker);
  
          }
  
      }
  
  
  
      ret = 0;
  
  out:
  
      g_free(bmds_bs);
  
      return ret;
  
  }