Diff for /qemu/block-qcow.c between versions 1.1.1.4 and 1.1.1.5

version 1.1.1.4, 2018/04/24 16:44:47 version 1.1.1.5, 2018/04/24 16:47:11
Line 1 Line 1
 /*  /*
  * Block driver for the QCOW format   * Block driver for the QCOW format
  *    *
  * Copyright (c) 2004-2006 Fabrice Bellard   * Copyright (c) 2004-2006 Fabrice Bellard
  *    *
  * Permission is hereby granted, free of charge, to any person obtaining a copy   * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal   * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights   * in the Software without restriction, including without limitation the rights
Line 21 Line 21
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.   * THE SOFTWARE.
  */   */
 #include "vl.h"  #include "qemu-common.h"
 #include "block_int.h"  #include "block_int.h"
 #include <zlib.h>  #include <zlib.h>
 #include "aes.h"  #include "aes.h"
Line 80  static int decompress_cluster(BDRVQcowSt Line 80  static int decompress_cluster(BDRVQcowSt
 static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)  static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
 {  {
     const QCowHeader *cow_header = (const void *)buf;      const QCowHeader *cow_header = (const void *)buf;
       
     if (buf_size >= sizeof(QCowHeader) &&      if (buf_size >= sizeof(QCowHeader) &&
         be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&          be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&
         be32_to_cpu(cow_header->version) == QCOW_VERSION)           be32_to_cpu(cow_header->version) == QCOW_VERSION)
         return 100;          return 100;
     else      else
         return 0;          return 0;
Line 108  static int qcow_open(BlockDriverState *b Line 108  static int qcow_open(BlockDriverState *b
     be64_to_cpus(&header.size);      be64_to_cpus(&header.size);
     be32_to_cpus(&header.crypt_method);      be32_to_cpus(&header.crypt_method);
     be64_to_cpus(&header.l1_table_offset);      be64_to_cpus(&header.l1_table_offset);
       
     if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION)      if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION)
         goto fail;          goto fail;
     if (header.size <= 1 || header.cluster_bits < 9)      if (header.size <= 1 || header.cluster_bits < 9)
Line 134  static int qcow_open(BlockDriverState *b Line 134  static int qcow_open(BlockDriverState *b
     s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));      s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
     if (!s->l1_table)      if (!s->l1_table)
         goto fail;          goto fail;
     if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=       if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
         s->l1_size * sizeof(uint64_t))          s->l1_size * sizeof(uint64_t))
         goto fail;          goto fail;
     for(i = 0;i < s->l1_size; i++) {      for(i = 0;i < s->l1_size; i++) {
Line 151  static int qcow_open(BlockDriverState *b Line 151  static int qcow_open(BlockDriverState *b
     if (!s->cluster_data)      if (!s->cluster_data)
         goto fail;          goto fail;
     s->cluster_cache_offset = -1;      s->cluster_cache_offset = -1;
       
     /* read the backing file name */      /* read the backing file name */
     if (header.backing_file_offset != 0) {      if (header.backing_file_offset != 0) {
         len = header.backing_file_size;          len = header.backing_file_size;
Line 177  static int qcow_set_key(BlockDriverState Line 177  static int qcow_set_key(BlockDriverState
     BDRVQcowState *s = bs->opaque;      BDRVQcowState *s = bs->opaque;
     uint8_t keybuf[16];      uint8_t keybuf[16];
     int len, i;      int len, i;
       
     memset(keybuf, 0, 16);      memset(keybuf, 0, 16);
     len = strlen(key);      len = strlen(key);
     if (len > 16)      if (len > 16)
Line 231  static void encrypt_sectors(BDRVQcowStat Line 231  static void encrypt_sectors(BDRVQcowStat
     for(i = 0; i < nb_sectors; i++) {      for(i = 0; i < nb_sectors; i++) {
         ivec.ll[0] = cpu_to_le64(sector_num);          ivec.ll[0] = cpu_to_le64(sector_num);
         ivec.ll[1] = 0;          ivec.ll[1] = 0;
         AES_cbc_encrypt(in_buf, out_buf, 512, key,           AES_cbc_encrypt(in_buf, out_buf, 512, key,
                         ivec.b, enc);                          ivec.b, enc);
         sector_num++;          sector_num++;
         in_buf += 512;          in_buf += 512;
Line 248  static void encrypt_sectors(BDRVQcowStat Line 248  static void encrypt_sectors(BDRVQcowStat
  *   *
  * 2 to allocate a compressed cluster of size   * 2 to allocate a compressed cluster of size
  * 'compressed_size'. 'compressed_size' must be > 0 and <   * 'compressed_size'. 'compressed_size' must be > 0 and <
  * cluster_size    * cluster_size
  *   *
  * return 0 if not allocated.   * return 0 if not allocated.
  */   */
Line 262  static uint64_t get_cluster_offset(Block Line 262  static uint64_t get_cluster_offset(Block
     uint64_t l2_offset, *l2_table, cluster_offset, tmp;      uint64_t l2_offset, *l2_table, cluster_offset, tmp;
     uint32_t min_count;      uint32_t min_count;
     int new_l2_table;      int new_l2_table;
       
     l1_index = offset >> (s->l2_bits + s->cluster_bits);      l1_index = offset >> (s->l2_bits + s->cluster_bits);
     l2_offset = s->l1_table[l1_index];      l2_offset = s->l1_table[l1_index];
     new_l2_table = 0;      new_l2_table = 0;
Line 276  static uint64_t get_cluster_offset(Block Line 276  static uint64_t get_cluster_offset(Block
         /* update the L1 entry */          /* update the L1 entry */
         s->l1_table[l1_index] = l2_offset;          s->l1_table[l1_index] = l2_offset;
         tmp = cpu_to_be64(l2_offset);          tmp = cpu_to_be64(l2_offset);
         if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp),           if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp),
                         &tmp, sizeof(tmp)) != sizeof(tmp))                          &tmp, sizeof(tmp)) != sizeof(tmp))
             return 0;              return 0;
         new_l2_table = 1;          new_l2_table = 1;
Line 309  static uint64_t get_cluster_offset(Block Line 309  static uint64_t get_cluster_offset(Block
             s->l2_size * sizeof(uint64_t))              s->l2_size * sizeof(uint64_t))
             return 0;              return 0;
     } else {      } else {
         if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=           if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
             s->l2_size * sizeof(uint64_t))              s->l2_size * sizeof(uint64_t))
             return 0;              return 0;
     }      }
Line 318  static uint64_t get_cluster_offset(Block Line 318  static uint64_t get_cluster_offset(Block
  found:   found:
     l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);      l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
     cluster_offset = be64_to_cpu(l2_table[l2_index]);      cluster_offset = be64_to_cpu(l2_table[l2_index]);
     if (!cluster_offset ||       if (!cluster_offset ||
         ((cluster_offset & QCOW_OFLAG_COMPRESSED) && allocate == 1)) {          ((cluster_offset & QCOW_OFLAG_COMPRESSED) && allocate == 1)) {
         if (!allocate)          if (!allocate)
             return 0;              return 0;
Line 331  static uint64_t get_cluster_offset(Block Line 331  static uint64_t get_cluster_offset(Block
             if (decompress_cluster(s, cluster_offset) < 0)              if (decompress_cluster(s, cluster_offset) < 0)
                 return 0;                  return 0;
             cluster_offset = bdrv_getlength(s->hd);              cluster_offset = bdrv_getlength(s->hd);
             cluster_offset = (cluster_offset + s->cluster_size - 1) &               cluster_offset = (cluster_offset + s->cluster_size - 1) &
                 ~(s->cluster_size - 1);                  ~(s->cluster_size - 1);
             /* write the cluster content */              /* write the cluster content */
             if (bdrv_pwrite(s->hd, cluster_offset, s->cluster_cache, s->cluster_size) !=               if (bdrv_pwrite(s->hd, cluster_offset, s->cluster_cache, s->cluster_size) !=
                 s->cluster_size)                  s->cluster_size)
                 return -1;                  return -1;
         } else {          } else {
             cluster_offset = bdrv_getlength(s->hd);              cluster_offset = bdrv_getlength(s->hd);
             if (allocate == 1) {              if (allocate == 1) {
                 /* round to cluster size */                  /* round to cluster size */
                 cluster_offset = (cluster_offset + s->cluster_size - 1) &                   cluster_offset = (cluster_offset + s->cluster_size - 1) &
                     ~(s->cluster_size - 1);                      ~(s->cluster_size - 1);
                 bdrv_truncate(s->hd, cluster_offset + s->cluster_size);                  bdrv_truncate(s->hd, cluster_offset + s->cluster_size);
                 /* if encrypted, we must initialize the cluster                  /* if encrypted, we must initialize the cluster
                    content which won't be written */                     content which won't be written */
                 if (s->crypt_method &&                   if (s->crypt_method &&
                     (n_end - n_start) < s->cluster_sectors) {                      (n_end - n_start) < s->cluster_sectors) {
                     uint64_t start_sect;                      uint64_t start_sect;
                     start_sect = (offset & ~(s->cluster_size - 1)) >> 9;                      start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
                     memset(s->cluster_data + 512, 0x00, 512);                      memset(s->cluster_data + 512, 0x00, 512);
                     for(i = 0; i < s->cluster_sectors; i++) {                      for(i = 0; i < s->cluster_sectors; i++) {
                         if (i < n_start || i >= n_end) {                          if (i < n_start || i >= n_end) {
                             encrypt_sectors(s, start_sect + i,                               encrypt_sectors(s, start_sect + i,
                                             s->cluster_data,                                               s->cluster_data,
                                             s->cluster_data + 512, 1, 1,                                              s->cluster_data + 512, 1, 1,
                                             &s->aes_encrypt_key);                                              &s->aes_encrypt_key);
                             if (bdrv_pwrite(s->hd, cluster_offset + i * 512,                               if (bdrv_pwrite(s->hd, cluster_offset + i * 512,
                                             s->cluster_data, 512) != 512)                                              s->cluster_data, 512) != 512)
                                 return -1;                                  return -1;
                         }                          }
                     }                      }
                 }                  }
             } else {              } else {
                 cluster_offset |= QCOW_OFLAG_COMPRESSED |                   cluster_offset |= QCOW_OFLAG_COMPRESSED |
                     (uint64_t)compressed_size << (63 - s->cluster_bits);                      (uint64_t)compressed_size << (63 - s->cluster_bits);
             }              }
         }          }
         /* update L2 table */          /* update L2 table */
         tmp = cpu_to_be64(cluster_offset);          tmp = cpu_to_be64(cluster_offset);
         l2_table[l2_index] = tmp;          l2_table[l2_index] = tmp;
         if (bdrv_pwrite(s->hd,           if (bdrv_pwrite(s->hd,
                         l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))                          l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))
             return 0;              return 0;
     }      }
     return cluster_offset;      return cluster_offset;
 }  }
   
 static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num,   static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num,
                              int nb_sectors, int *pnum)                               int nb_sectors, int *pnum)
 {  {
     BDRVQcowState *s = bs->opaque;      BDRVQcowState *s = bs->opaque;
Line 420  static int decompress_buffer(uint8_t *ou Line 420  static int decompress_buffer(uint8_t *ou
     inflateEnd(strm);      inflateEnd(strm);
     return 0;      return 0;
 }  }
                                 
 static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)  static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
 {  {
     int ret, csize;      int ret, csize;
Line 431  static int decompress_cluster(BDRVQcowSt Line 431  static int decompress_cluster(BDRVQcowSt
         csize = cluster_offset >> (63 - s->cluster_bits);          csize = cluster_offset >> (63 - s->cluster_bits);
         csize &= (s->cluster_size - 1);          csize &= (s->cluster_size - 1);
         ret = bdrv_pread(s->hd, coffset, s->cluster_data, csize);          ret = bdrv_pread(s->hd, coffset, s->cluster_data, csize);
         if (ret != csize)           if (ret != csize)
             return -1;              return -1;
         if (decompress_buffer(s->cluster_cache, s->cluster_size,          if (decompress_buffer(s->cluster_cache, s->cluster_size,
                               s->cluster_data, csize) < 0) {                                s->cluster_data, csize) < 0) {
Line 444  static int decompress_cluster(BDRVQcowSt Line 444  static int decompress_cluster(BDRVQcowSt
   
 #if 0  #if 0
   
 static int qcow_read(BlockDriverState *bs, int64_t sector_num,   static int qcow_read(BlockDriverState *bs, int64_t sector_num,
                      uint8_t *buf, int nb_sectors)                       uint8_t *buf, int nb_sectors)
 {  {
     BDRVQcowState *s = bs->opaque;      BDRVQcowState *s = bs->opaque;
     int ret, index_in_cluster, n;      int ret, index_in_cluster, n;
     uint64_t cluster_offset;      uint64_t cluster_offset;
       
     while (nb_sectors > 0) {      while (nb_sectors > 0) {
         cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);          cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
         index_in_cluster = sector_num & (s->cluster_sectors - 1);          index_in_cluster = sector_num & (s->cluster_sectors - 1);
Line 472  static int qcow_read(BlockDriverState *b Line 472  static int qcow_read(BlockDriverState *b
             memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);              memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
         } else {          } else {
             ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);              ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
             if (ret != n * 512)               if (ret != n * 512)
                 return -1;                  return -1;
             if (s->crypt_method) {              if (s->crypt_method) {
                 encrypt_sectors(s, sector_num, buf, buf, n, 0,                   encrypt_sectors(s, sector_num, buf, buf, n, 0,
                                 &s->aes_decrypt_key);                                  &s->aes_decrypt_key);
             }              }
         }          }
Line 487  static int qcow_read(BlockDriverState *b Line 487  static int qcow_read(BlockDriverState *b
 }  }
 #endif  #endif
   
 static int qcow_write(BlockDriverState *bs, int64_t sector_num,   static int qcow_write(BlockDriverState *bs, int64_t sector_num,
                      const uint8_t *buf, int nb_sectors)                       const uint8_t *buf, int nb_sectors)
 {  {
     BDRVQcowState *s = bs->opaque;      BDRVQcowState *s = bs->opaque;
     int ret, index_in_cluster, n;      int ret, index_in_cluster, n;
     uint64_t cluster_offset;      uint64_t cluster_offset;
       
     while (nb_sectors > 0) {      while (nb_sectors > 0) {
         index_in_cluster = sector_num & (s->cluster_sectors - 1);          index_in_cluster = sector_num & (s->cluster_sectors - 1);
         n = s->cluster_sectors - index_in_cluster;          n = s->cluster_sectors - index_in_cluster;
         if (n > nb_sectors)          if (n > nb_sectors)
             n = nb_sectors;              n = nb_sectors;
         cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,           cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,
                                             index_in_cluster,                                               index_in_cluster,
                                             index_in_cluster + n);                                              index_in_cluster + n);
         if (!cluster_offset)          if (!cluster_offset)
             return -1;              return -1;
         if (s->crypt_method) {          if (s->crypt_method) {
             encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,              encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
                             &s->aes_encrypt_key);                              &s->aes_encrypt_key);
             ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512,               ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512,
                               s->cluster_data, n * 512);                                s->cluster_data, n * 512);
         } else {          } else {
             ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);              ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
         }          }
         if (ret != n * 512)           if (ret != n * 512)
             return -1;              return -1;
         nb_sectors -= n;          nb_sectors -= n;
         sector_num += n;          sector_num += n;
Line 529  typedef struct QCowAIOCB { Line 529  typedef struct QCowAIOCB {
     int nb_sectors;      int nb_sectors;
     int n;      int n;
     uint64_t cluster_offset;      uint64_t cluster_offset;
     uint8_t *cluster_data;       uint8_t *cluster_data;
     BlockDriverAIOCB *hd_aiocb;      BlockDriverAIOCB *hd_aiocb;
 } QCowAIOCB;  } QCowAIOCB;
   
Line 556  static void qcow_aio_read_cb(void *opaqu Line 556  static void qcow_aio_read_cb(void *opaqu
         /* nothing to do */          /* nothing to do */
     } else {      } else {
         if (s->crypt_method) {          if (s->crypt_method) {
             encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf,               encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf,
                             acb->n, 0,                               acb->n, 0,
                             &s->aes_decrypt_key);                              &s->aes_decrypt_key);
         }          }
     }      }
Line 572  static void qcow_aio_read_cb(void *opaqu Line 572  static void qcow_aio_read_cb(void *opaqu
         qemu_aio_release(acb);          qemu_aio_release(acb);
         return;          return;
     }      }
       
     /* prepare next AIO request */      /* prepare next AIO request */
     acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9,       acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9,
                                              0, 0, 0, 0);                                               0, 0, 0, 0);
     index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);      index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
     acb->n = s->cluster_sectors - index_in_cluster;      acb->n = s->cluster_sectors - index_in_cluster;
Line 597  static void qcow_aio_read_cb(void *opaqu Line 597  static void qcow_aio_read_cb(void *opaqu
         /* add AIO support for compressed blocks ? */          /* add AIO support for compressed blocks ? */
         if (decompress_cluster(s, acb->cluster_offset) < 0)          if (decompress_cluster(s, acb->cluster_offset) < 0)
             goto fail;              goto fail;
         memcpy(acb->buf,           memcpy(acb->buf,
                s->cluster_cache + index_in_cluster * 512, 512 * acb->n);                 s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
         goto redo;          goto redo;
     } else {      } else {
Line 606  static void qcow_aio_read_cb(void *opaqu Line 606  static void qcow_aio_read_cb(void *opaqu
             goto fail;              goto fail;
         }          }
         acb->hd_aiocb = bdrv_aio_read(s->hd,          acb->hd_aiocb = bdrv_aio_read(s->hd,
                             (acb->cluster_offset >> 9) + index_in_cluster,                               (acb->cluster_offset >> 9) + index_in_cluster,
                             acb->buf, acb->n, qcow_aio_read_cb, acb);                              acb->buf, acb->n, qcow_aio_read_cb, acb);
         if (acb->hd_aiocb == NULL)          if (acb->hd_aiocb == NULL)
             goto fail;              goto fail;
Line 627  static BlockDriverAIOCB *qcow_aio_read(B Line 627  static BlockDriverAIOCB *qcow_aio_read(B
     acb->buf = buf;      acb->buf = buf;
     acb->nb_sectors = nb_sectors;      acb->nb_sectors = nb_sectors;
     acb->n = 0;      acb->n = 0;
     acb->cluster_offset = 0;          acb->cluster_offset = 0;
   
     qcow_aio_read_cb(acb, 0);      qcow_aio_read_cb(acb, 0);
     return &acb->common;      return &acb->common;
Line 661  static void qcow_aio_write_cb(void *opaq Line 661  static void qcow_aio_write_cb(void *opaq
         qemu_aio_release(acb);          qemu_aio_release(acb);
         return;          return;
     }      }
       
     index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);      index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
     acb->n = s->cluster_sectors - index_in_cluster;      acb->n = s->cluster_sectors - index_in_cluster;
     if (acb->n > acb->nb_sectors)      if (acb->n > acb->nb_sectors)
         acb->n = acb->nb_sectors;          acb->n = acb->nb_sectors;
     cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0,       cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0,
                                         index_in_cluster,                                           index_in_cluster,
                                         index_in_cluster + acb->n);                                          index_in_cluster + acb->n);
     if (!cluster_offset || (cluster_offset & 511) != 0) {      if (!cluster_offset || (cluster_offset & 511) != 0) {
         ret = -EIO;          ret = -EIO;
Line 681  static void qcow_aio_write_cb(void *opaq Line 681  static void qcow_aio_write_cb(void *opaq
                 goto fail;                  goto fail;
             }              }
         }          }
         encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf,           encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf,
                         acb->n, 1, &s->aes_encrypt_key);                          acb->n, 1, &s->aes_encrypt_key);
         src_buf = acb->cluster_data;          src_buf = acb->cluster_data;
     } else {      } else {
         src_buf = acb->buf;          src_buf = acb->buf;
     }      }
     acb->hd_aiocb = bdrv_aio_write(s->hd,      acb->hd_aiocb = bdrv_aio_write(s->hd,
                                    (cluster_offset >> 9) + index_in_cluster,                                      (cluster_offset >> 9) + index_in_cluster,
                                    src_buf, acb->n,                                      src_buf, acb->n,
                                    qcow_aio_write_cb, acb);                                     qcow_aio_write_cb, acb);
     if (acb->hd_aiocb == NULL)      if (acb->hd_aiocb == NULL)
         goto fail;          goto fail;
Line 701  static BlockDriverAIOCB *qcow_aio_write( Line 701  static BlockDriverAIOCB *qcow_aio_write(
 {  {
     BDRVQcowState *s = bs->opaque;      BDRVQcowState *s = bs->opaque;
     QCowAIOCB *acb;      QCowAIOCB *acb;
       
     s->cluster_cache_offset = -1; /* disable compressed cache */      s->cluster_cache_offset = -1; /* disable compressed cache */
   
     acb = qemu_aio_get(bs, cb, opaque);      acb = qemu_aio_get(bs, cb, opaque);
Line 712  static BlockDriverAIOCB *qcow_aio_write( Line 712  static BlockDriverAIOCB *qcow_aio_write(
     acb->buf = (uint8_t *)buf;      acb->buf = (uint8_t *)buf;
     acb->nb_sectors = nb_sectors;      acb->nb_sectors = nb_sectors;
     acb->n = 0;      acb->n = 0;
       
     qcow_aio_write_cb(acb, 0);      qcow_aio_write_cb(acb, 0);
     return &acb->common;      return &acb->common;
 }  }
Line 769  static int qcow_create(const char *filen Line 769  static int qcow_create(const char *filen
     l1_size = ((total_size * 512) + (1LL << shift) - 1) >> shift;      l1_size = ((total_size * 512) + (1LL << shift) - 1) >> shift;
   
     header.l1_table_offset = cpu_to_be64(header_size);      header.l1_table_offset = cpu_to_be64(header_size);
     if (flags) {      if (flags & BLOCK_FLAG_ENCRYPT) {
         header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);          header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
     } else {      } else {
         header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);          header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
     }      }
       
     /* write all the data */      /* write all the data */
     write(fd, &header, sizeof(header));      write(fd, &header, sizeof(header));
     if (backing_file) {      if (backing_file) {
Line 811  static int qcow_make_empty(BlockDriverSt Line 811  static int qcow_make_empty(BlockDriverSt
   
 /* XXX: put compressed sectors first, then all the cluster aligned  /* XXX: put compressed sectors first, then all the cluster aligned
    tables to avoid losing bytes in alignment */     tables to avoid losing bytes in alignment */
 static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,   static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
                                  const uint8_t *buf, int nb_sectors)                                   const uint8_t *buf, int nb_sectors)
 {  {
     BDRVQcowState *s = bs->opaque;      BDRVQcowState *s = bs->opaque;
Line 830  static int qcow_write_compressed(BlockDr Line 830  static int qcow_write_compressed(BlockDr
     /* best compression, small window, no zlib header */      /* best compression, small window, no zlib header */
     memset(&strm, 0, sizeof(strm));      memset(&strm, 0, sizeof(strm));
     ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,      ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,
                        Z_DEFLATED, -12,                          Z_DEFLATED, -12,
                        9, Z_DEFAULT_STRATEGY);                         9, Z_DEFAULT_STRATEGY);
     if (ret != 0) {      if (ret != 0) {
         qemu_free(out_buf);          qemu_free(out_buf);
Line 856  static int qcow_write_compressed(BlockDr Line 856  static int qcow_write_compressed(BlockDr
         /* could not compress: write normal cluster */          /* could not compress: write normal cluster */
         qcow_write(bs, sector_num, buf, s->cluster_sectors);          qcow_write(bs, sector_num, buf, s->cluster_sectors);
     } else {      } else {
         cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,           cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
                                             out_len, 0, 0);                                              out_len, 0, 0);
         cluster_offset &= s->cluster_offset_mask;          cluster_offset &= s->cluster_offset_mask;
         if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {          if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
Line 864  static int qcow_write_compressed(BlockDr Line 864  static int qcow_write_compressed(BlockDr
             return -1;              return -1;
         }          }
     }      }
       
     qemu_free(out_buf);      qemu_free(out_buf);
     return 0;      return 0;
 }  }

Removed from v.1.1.1.4  
changed lines
  Added in v.1.1.1.5


unix.superglobalmegacorp.com