Diff for /qemu/qemu-img.c between versions 1.1.1.13 and 1.1.1.14

version 1.1.1.13, 2018/04/24 18:56:18 version 1.1.1.14, 2018/04/24 19:17:22
Line 66  static void help(void) Line 66  static void help(void)
            "  'filename' is a disk image filename\n"             "  'filename' is a disk image filename\n"
            "  'fmt' is the disk image format. It is guessed automatically in most cases\n"             "  'fmt' is the disk image format. It is guessed automatically in most cases\n"
            "  'cache' is the cache mode used to write the output disk image, the valid\n"             "  'cache' is the cache mode used to write the output disk image, the valid\n"
            "    options are: 'none', 'writeback' (default), 'writethrough' and 'unsafe'\n"             "    options are: 'none', 'writeback' (default), 'writethrough', 'directsync'\n"
              "    and 'unsafe'\n"
            "  'size' is the disk image size in bytes. Optional suffixes\n"             "  'size' is the disk image size in bytes. Optional suffixes\n"
            "    'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"             "    'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
            "    and T (terabyte, 1024G) are supported. 'b' is ignored.\n"             "    and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
Line 81  static void help(void) Line 82  static void help(void)
            "       rebasing in this case (useful for renaming the backing file)\n"             "       rebasing in this case (useful for renaming the backing file)\n"
            "  '-h' with or without a command shows this help and lists the supported formats\n"             "  '-h' with or without a command shows this help and lists the supported formats\n"
            "  '-p' show progress of command (only certain commands)\n"             "  '-p' show progress of command (only certain commands)\n"
              "  '-S' indicates the consecutive number of bytes that must contain only zeros\n"
              "       for qemu-img to create a sparse image during conversion\n"
            "\n"             "\n"
            "Parameters to snapshot subcommand:\n"             "Parameters to snapshot subcommand:\n"
            "  'snapshot' is the name of the snapshot to create, apply or delete\n"             "  'snapshot' is the name of the snapshot to create, apply or delete\n"
Line 183  static int read_password(char *buf, int  Line 186  static int read_password(char *buf, int 
 }  }
 #endif  #endif
   
 static int set_cache_flag(const char *mode, int *flags)  
 {  
     *flags &= ~BDRV_O_CACHE_MASK;  
   
     if (!strcmp(mode, "none") || !strcmp(mode, "off")) {  
         *flags |= BDRV_O_CACHE_WB;  
         *flags |= BDRV_O_NOCACHE;  
     } else if (!strcmp(mode, "writeback")) {  
         *flags |= BDRV_O_CACHE_WB;  
     } else if (!strcmp(mode, "unsafe")) {  
         *flags |= BDRV_O_CACHE_WB;  
         *flags |= BDRV_O_NO_FLUSH;  
     } else if (!strcmp(mode, "writethrough")) {  
         /* this is the default */  
     } else {  
         return -1;  
     }  
   
     return 0;  
 }  
   
 static int print_block_option_help(const char *filename, const char *fmt)  static int print_block_option_help(const char *filename, const char *fmt)
 {  {
     BlockDriver *drv, *proto_drv;      BlockDriver *drv, *proto_drv;
Line 350  static int img_create(int argc, char **a Line 332  static int img_create(int argc, char **a
     /* Get image size, if specified */      /* Get image size, if specified */
     if (optind < argc) {      if (optind < argc) {
         int64_t sval;          int64_t sval;
         sval = strtosz_suffix(argv[optind++], NULL, STRTOSZ_DEFSUFFIX_B);          char *end;
         if (sval < 0) {          sval = strtosz_suffix(argv[optind++], &end, STRTOSZ_DEFSUFFIX_B);
           if (sval < 0 || *end) {
             error_report("Invalid image size specified! You may use k, M, G or "              error_report("Invalid image size specified! You may use k, M, G or "
                   "T suffixes for ");                    "T suffixes for ");
             error_report("kilobytes, megabytes, gigabytes and terabytes.");              error_report("kilobytes, megabytes, gigabytes and terabytes.");
Line 495  static int img_commit(int argc, char **a Line 478  static int img_commit(int argc, char **a
     filename = argv[optind++];      filename = argv[optind++];
   
     flags = BDRV_O_RDWR;      flags = BDRV_O_RDWR;
     ret = set_cache_flag(cache, &flags);      ret = bdrv_parse_cache_flags(cache, &flags);
     if (ret < 0) {      if (ret < 0) {
         error_report("Invalid cache option: %s", cache);          error_report("Invalid cache option: %s", cache);
         return -1;          return -1;
Line 591  static int is_allocated_sectors(const ui Line 574  static int is_allocated_sectors(const ui
 }  }
   
 /*  /*
    * Like is_allocated_sectors, but if the buffer starts with a used sector,
    * up to 'min' consecutive sectors containing zeros are ignored. This avoids
    * breaking up write requests for only small sparse areas.
    */
   static int is_allocated_sectors_min(const uint8_t *buf, int n, int *pnum,
       int min)
   {
       int ret;
       int num_checked, num_used;
   
       if (n < min) {
           min = n;
       }
   
       ret = is_allocated_sectors(buf, n, pnum);
       if (!ret) {
           return ret;
       }
   
       num_used = *pnum;
       buf += BDRV_SECTOR_SIZE * *pnum;
       n -= *pnum;
       num_checked = num_used;
   
       while (n > 0) {
           ret = is_allocated_sectors(buf, n, pnum);
   
           buf += BDRV_SECTOR_SIZE * *pnum;
           n -= *pnum;
           num_checked += *pnum;
           if (ret) {
               num_used = num_checked;
           } else if (*pnum >= min) {
               break;
           }
       }
   
       *pnum = num_used;
       return 1;
   }
   
   /*
  * Compares two buffers sector by sector. Returns 0 if the first sector of both   * Compares two buffers sector by sector. Returns 0 if the first sector of both
  * buffers matches, non-zero otherwise.   * buffers matches, non-zero otherwise.
  *   *
Line 640  static int img_convert(int argc, char ** Line 665  static int img_convert(int argc, char **
     char *options = NULL;      char *options = NULL;
     const char *snapshot_name = NULL;      const char *snapshot_name = NULL;
     float local_progress;      float local_progress;
       int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
   
     fmt = NULL;      fmt = NULL;
     out_fmt = "raw";      out_fmt = "raw";
Line 647  static int img_convert(int argc, char ** Line 673  static int img_convert(int argc, char **
     out_baseimg = NULL;      out_baseimg = NULL;
     compress = 0;      compress = 0;
     for(;;) {      for(;;) {
         c = getopt(argc, argv, "f:O:B:s:hce6o:pt:");          c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:");
         if (c == -1) {          if (c == -1) {
             break;              break;
         }          }
Line 682  static int img_convert(int argc, char ** Line 708  static int img_convert(int argc, char **
         case 's':          case 's':
             snapshot_name = optarg;              snapshot_name = optarg;
             break;              break;
           case 'S':
           {
               int64_t sval;
               char *end;
               sval = strtosz_suffix(optarg, &end, STRTOSZ_DEFSUFFIX_B);
               if (sval < 0 || *end) {
                   error_report("Invalid minimum zero buffer size for sparse output specified");
                   return 1;
               }
   
               min_sparse = sval / BDRV_SECTOR_SIZE;
               break;
           }
         case 'p':          case 'p':
             progress = 1;              progress = 1;
             break;              break;
Line 713  static int img_convert(int argc, char ** Line 752  static int img_convert(int argc, char **
     qemu_progress_init(progress, 2.0);      qemu_progress_init(progress, 2.0);
     qemu_progress_print(0, 100);      qemu_progress_print(0, 100);
   
     bs = qemu_mallocz(bs_n * sizeof(BlockDriverState *));      bs = g_malloc0(bs_n * sizeof(BlockDriverState *));
   
     total_sectors = 0;      total_sectors = 0;
     for (bs_i = 0; bs_i < bs_n; bs_i++) {      for (bs_i = 0; bs_i < bs_n; bs_i++) {
Line 787  static int img_convert(int argc, char ** Line 826  static int img_convert(int argc, char **
     if (compress) {      if (compress) {
         QEMUOptionParameter *encryption =          QEMUOptionParameter *encryption =
             get_option_parameter(param, BLOCK_OPT_ENCRYPT);              get_option_parameter(param, BLOCK_OPT_ENCRYPT);
           QEMUOptionParameter *preallocation =
               get_option_parameter(param, BLOCK_OPT_PREALLOC);
   
         if (!drv->bdrv_write_compressed) {          if (!drv->bdrv_write_compressed) {
             error_report("Compression not supported for this file format");              error_report("Compression not supported for this file format");
Line 800  static int img_convert(int argc, char ** Line 841  static int img_convert(int argc, char **
             ret = -1;              ret = -1;
             goto out;              goto out;
         }          }
   
           if (preallocation && preallocation->value.s
               && strcmp(preallocation->value.s, "off"))
           {
               error_report("Compression and preallocation not supported at "
                            "the same time");
               ret = -1;
               goto out;
           }
     }      }
   
     /* Create the new image */      /* Create the new image */
Line 819  static int img_convert(int argc, char ** Line 869  static int img_convert(int argc, char **
     }      }
   
     flags = BDRV_O_RDWR;      flags = BDRV_O_RDWR;
     ret = set_cache_flag(cache, &flags);      ret = bdrv_parse_cache_flags(cache, &flags);
     if (ret < 0) {      if (ret < 0) {
         error_report("Invalid cache option: %s", cache);          error_report("Invalid cache option: %s", cache);
         return -1;          return -1;
Line 834  static int img_convert(int argc, char ** Line 884  static int img_convert(int argc, char **
     bs_i = 0;      bs_i = 0;
     bs_offset = 0;      bs_offset = 0;
     bdrv_get_geometry(bs[0], &bs_sectors);      bdrv_get_geometry(bs[0], &bs_sectors);
     buf = qemu_malloc(IO_BUF_SIZE);      buf = qemu_blockalign(out_bs, IO_BUF_SIZE);
   
     if (compress) {      if (compress) {
         ret = bdrv_get_info(out_bs, &bdi);          ret = bdrv_get_info(out_bs, &bdi);
Line 890  static int img_convert(int argc, char ** Line 940  static int img_convert(int argc, char **
   
                 ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow);                  ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow);
                 if (ret < 0) {                  if (ret < 0) {
                     error_report("error while reading");                      error_report("error while reading sector %" PRId64 ": %s",
                                    bs_num, strerror(-ret));
                     goto out;                      goto out;
                 }                  }
   
Line 908  static int img_convert(int argc, char ** Line 959  static int img_convert(int argc, char **
                 ret = bdrv_write_compressed(out_bs, sector_num, buf,                  ret = bdrv_write_compressed(out_bs, sector_num, buf,
                                             cluster_sectors);                                              cluster_sectors);
                 if (ret != 0) {                  if (ret != 0) {
                     error_report("error while compressing sector %" PRId64,                      error_report("error while compressing sector %" PRId64
                           sector_num);                                   ": %s", sector_num, strerror(-ret));
                     goto out;                      goto out;
                 }                  }
             }              }
Line 972  static int img_convert(int argc, char ** Line 1023  static int img_convert(int argc, char **
   
             ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);              ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
             if (ret < 0) {              if (ret < 0) {
                 error_report("error while reading");                  error_report("error while reading sector %" PRId64 ": %s",
                                sector_num - bs_offset, strerror(-ret));
                 goto out;                  goto out;
             }              }
             /* NOTE: at the same time we convert, we do not write zero              /* NOTE: at the same time we convert, we do not write zero
Line 988  static int img_convert(int argc, char ** Line 1040  static int img_convert(int argc, char **
                    sectors that are entirely 0, since whatever data was                     sectors that are entirely 0, since whatever data was
                    already there is garbage, not 0s. */                     already there is garbage, not 0s. */
                 if (!has_zero_init || out_baseimg ||                  if (!has_zero_init || out_baseimg ||
                     is_allocated_sectors(buf1, n, &n1)) {                      is_allocated_sectors_min(buf1, n, &n1, min_sparse)) {
                     ret = bdrv_write(out_bs, sector_num, buf1, n1);                      ret = bdrv_write(out_bs, sector_num, buf1, n1);
                     if (ret < 0) {                      if (ret < 0) {
                         error_report("error while writing");                          error_report("error while writing sector %" PRId64
                                        ": %s", sector_num, strerror(-ret));
                         goto out;                          goto out;
                     }                      }
                 }                  }
Line 1006  out: Line 1059  out:
     qemu_progress_end();      qemu_progress_end();
     free_option_parameters(create_options);      free_option_parameters(create_options);
     free_option_parameters(param);      free_option_parameters(param);
     qemu_free(buf);      qemu_vfree(buf);
     if (out_bs) {      if (out_bs) {
         bdrv_delete(out_bs);          bdrv_delete(out_bs);
     }      }
Line 1016  out: Line 1069  out:
                 bdrv_delete(bs[bs_i]);                  bdrv_delete(bs[bs_i]);
             }              }
         }          }
         qemu_free(bs);          g_free(bs);
     }      }
     if (ret) {      if (ret) {
         return 1;          return 1;
Line 1040  static void dump_snapshots(BlockDriverSt Line 1093  static void dump_snapshots(BlockDriverSt
         sn = &sn_tab[i];          sn = &sn_tab[i];
         printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));          printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
     }      }
     qemu_free(sn_tab);      g_free(sn_tab);
 }  }
   
 static int img_info(int argc, char **argv)  static int img_info(int argc, char **argv)
Line 1291  static int img_rebase(int argc, char **a Line 1344  static int img_rebase(int argc, char **a
     qemu_progress_print(0, 100);      qemu_progress_print(0, 100);
   
     flags = BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);      flags = BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
     ret = set_cache_flag(cache, &flags);      ret = bdrv_parse_cache_flags(cache, &flags);
     if (ret < 0) {      if (ret < 0) {
         error_report("Invalid cache option: %s", cache);          error_report("Invalid cache option: %s", cache);
         return -1;          return -1;
Line 1367  static int img_rebase(int argc, char **a Line 1420  static int img_rebase(int argc, char **a
      */       */
     if (!unsafe) {      if (!unsafe) {
         uint64_t num_sectors;          uint64_t num_sectors;
           uint64_t old_backing_num_sectors;
           uint64_t new_backing_num_sectors;
         uint64_t sector;          uint64_t sector;
         int n;          int n;
         uint8_t * buf_old;          uint8_t * buf_old;
         uint8_t * buf_new;          uint8_t * buf_new;
         float local_progress;          float local_progress;
   
         buf_old = qemu_malloc(IO_BUF_SIZE);          buf_old = qemu_blockalign(bs, IO_BUF_SIZE);
         buf_new = qemu_malloc(IO_BUF_SIZE);          buf_new = qemu_blockalign(bs, IO_BUF_SIZE);
   
         bdrv_get_geometry(bs, &num_sectors);          bdrv_get_geometry(bs, &num_sectors);
           bdrv_get_geometry(bs_old_backing, &old_backing_num_sectors);
           bdrv_get_geometry(bs_new_backing, &new_backing_num_sectors);
   
         local_progress = (float)100 /          local_progress = (float)100 /
             (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512));              (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512));
Line 1395  static int img_rebase(int argc, char **a Line 1452  static int img_rebase(int argc, char **a
                 continue;                  continue;
             }              }
   
             /* Read old and new backing file */              /*
             ret = bdrv_read(bs_old_backing, sector, buf_old, n);               * Read old and new backing file and take into consideration that
             if (ret < 0) {               * backing files may be smaller than the COW image.
                 error_report("error while reading from old backing file");               */
                 goto out;              if (sector >= old_backing_num_sectors) {
                   memset(buf_old, 0, n * BDRV_SECTOR_SIZE);
               } else {
                   if (sector + n > old_backing_num_sectors) {
                       n = old_backing_num_sectors - sector;
                   }
   
                   ret = bdrv_read(bs_old_backing, sector, buf_old, n);
                   if (ret < 0) {
                       error_report("error while reading from old backing file");
                       goto out;
                   }
             }              }
             ret = bdrv_read(bs_new_backing, sector, buf_new, n);  
             if (ret < 0) {              if (sector >= new_backing_num_sectors) {
                 error_report("error while reading from new backing file");                  memset(buf_new, 0, n * BDRV_SECTOR_SIZE);
                 goto out;              } else {
                   if (sector + n > new_backing_num_sectors) {
                       n = new_backing_num_sectors - sector;
                   }
   
                   ret = bdrv_read(bs_new_backing, sector, buf_new, n);
                   if (ret < 0) {
                       error_report("error while reading from new backing file");
                       goto out;
                   }
             }              }
   
             /* If they differ, we need to write to the COW file */              /* If they differ, we need to write to the COW file */
Line 1430  static int img_rebase(int argc, char **a Line 1507  static int img_rebase(int argc, char **a
             qemu_progress_print(local_progress, 100);              qemu_progress_print(local_progress, 100);
         }          }
   
         qemu_free(buf_old);          qemu_vfree(buf_old);
         qemu_free(buf_new);          qemu_vfree(buf_new);
     }      }
   
     /*      /*

Removed from v.1.1.1.13  
changed lines
  Added in v.1.1.1.14


unix.superglobalmegacorp.com