Diff for /qemu/block.c between versions 1.1.1.14 and 1.1.1.17

version 1.1.1.14, 2018/04/24 17:34:32 version 1.1.1.17, 2018/04/24 18:16:35
Line 452  int bdrv_open2(BlockDriverState *bs, con Line 452  int bdrv_open2(BlockDriverState *bs, con
             (flags & (BDRV_O_CACHE_MASK|BDRV_O_NATIVE_AIO));              (flags & (BDRV_O_CACHE_MASK|BDRV_O_NATIVE_AIO));
     else      else
         open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);          open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
   
       bs->open_flags = open_flags;
     if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv))      if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv))
         ret = -ENOTSUP;          ret = -ENOTSUP;
     else      else
Line 691  int bdrv_pread(BlockDriverState *bs, int Line 693  int bdrv_pread(BlockDriverState *bs, int
     uint8_t tmp_buf[BDRV_SECTOR_SIZE];      uint8_t tmp_buf[BDRV_SECTOR_SIZE];
     int len, nb_sectors, count;      int len, nb_sectors, count;
     int64_t sector_num;      int64_t sector_num;
       int ret;
   
     count = count1;      count = count1;
     /* first read to align to sector start */      /* first read to align to sector start */
Line 699  int bdrv_pread(BlockDriverState *bs, int Line 702  int bdrv_pread(BlockDriverState *bs, int
         len = count;          len = count;
     sector_num = offset >> BDRV_SECTOR_BITS;      sector_num = offset >> BDRV_SECTOR_BITS;
     if (len > 0) {      if (len > 0) {
         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)          if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
             return -EIO;              return ret;
         memcpy(buf, tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), len);          memcpy(buf, tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), len);
         count -= len;          count -= len;
         if (count == 0)          if (count == 0)
Line 712  int bdrv_pread(BlockDriverState *bs, int Line 715  int bdrv_pread(BlockDriverState *bs, int
     /* read the sectors "in place" */      /* read the sectors "in place" */
     nb_sectors = count >> BDRV_SECTOR_BITS;      nb_sectors = count >> BDRV_SECTOR_BITS;
     if (nb_sectors > 0) {      if (nb_sectors > 0) {
         if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)          if ((ret = bdrv_read(bs, sector_num, buf, nb_sectors)) < 0)
             return -EIO;              return ret;
         sector_num += nb_sectors;          sector_num += nb_sectors;
         len = nb_sectors << BDRV_SECTOR_BITS;          len = nb_sectors << BDRV_SECTOR_BITS;
         buf += len;          buf += len;
Line 722  int bdrv_pread(BlockDriverState *bs, int Line 725  int bdrv_pread(BlockDriverState *bs, int
   
     /* add data from the last sector */      /* add data from the last sector */
     if (count > 0) {      if (count > 0) {
         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)          if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
             return -EIO;              return ret;
         memcpy(buf, tmp_buf, count);          memcpy(buf, tmp_buf, count);
     }      }
     return count1;      return count1;
Line 735  int bdrv_pwrite(BlockDriverState *bs, in Line 738  int bdrv_pwrite(BlockDriverState *bs, in
     uint8_t tmp_buf[BDRV_SECTOR_SIZE];      uint8_t tmp_buf[BDRV_SECTOR_SIZE];
     int len, nb_sectors, count;      int len, nb_sectors, count;
     int64_t sector_num;      int64_t sector_num;
       int ret;
   
     count = count1;      count = count1;
     /* first write to align to sector start */      /* first write to align to sector start */
Line 743  int bdrv_pwrite(BlockDriverState *bs, in Line 747  int bdrv_pwrite(BlockDriverState *bs, in
         len = count;          len = count;
     sector_num = offset >> BDRV_SECTOR_BITS;      sector_num = offset >> BDRV_SECTOR_BITS;
     if (len > 0) {      if (len > 0) {
         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)          if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
             return -EIO;              return ret;
         memcpy(tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), buf, len);          memcpy(tmp_buf + (offset & (BDRV_SECTOR_SIZE - 1)), buf, len);
         if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)          if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
             return -EIO;              return ret;
         count -= len;          count -= len;
         if (count == 0)          if (count == 0)
             return count1;              return count1;
Line 758  int bdrv_pwrite(BlockDriverState *bs, in Line 762  int bdrv_pwrite(BlockDriverState *bs, in
     /* write the sectors "in place" */      /* write the sectors "in place" */
     nb_sectors = count >> BDRV_SECTOR_BITS;      nb_sectors = count >> BDRV_SECTOR_BITS;
     if (nb_sectors > 0) {      if (nb_sectors > 0) {
         if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)          if ((ret = bdrv_write(bs, sector_num, buf, nb_sectors)) < 0)
             return -EIO;              return ret;
         sector_num += nb_sectors;          sector_num += nb_sectors;
         len = nb_sectors << BDRV_SECTOR_BITS;          len = nb_sectors << BDRV_SECTOR_BITS;
         buf += len;          buf += len;
Line 768  int bdrv_pwrite(BlockDriverState *bs, in Line 772  int bdrv_pwrite(BlockDriverState *bs, in
   
     /* add data from the last sector */      /* add data from the last sector */
     if (count > 0) {      if (count > 0) {
         if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)          if ((ret = bdrv_read(bs, sector_num, tmp_buf, 1)) < 0)
             return -EIO;              return ret;
         memcpy(tmp_buf, buf, count);          memcpy(tmp_buf, buf, count);
         if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)          if ((ret = bdrv_write(bs, sector_num, tmp_buf, 1)) < 0)
             return -EIO;              return ret;
     }      }
     return count1;      return count1;
 }  }
   
   /*
    * Writes to the file and ensures that no writes are reordered across this
    * request (acts as a barrier)
    *
    * Returns 0 on success, -errno in error cases.
    */
   int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset,
       const void *buf, int count)
   {
       int ret;
   
       ret = bdrv_pwrite(bs, offset, buf, count);
       if (ret < 0) {
           return ret;
       }
   
       /* No flush needed for cache=writethrough, it uses O_DSYNC */
       if ((bs->open_flags & BDRV_O_CACHE_MASK) != 0) {
           bdrv_flush(bs);
       }
   
       return 0;
   }
   
   /*
    * Writes to the file and ensures that no writes are reordered across this
    * request (acts as a barrier)
    *
    * Returns 0 on success, -errno in error cases.
    */
   int bdrv_write_sync(BlockDriverState *bs, int64_t sector_num,
       const uint8_t *buf, int nb_sectors)
   {
       return bdrv_pwrite_sync(bs, BDRV_SECTOR_SIZE * sector_num,
           buf, BDRV_SECTOR_SIZE * nb_sectors);
   }
   
 /**  /**
  * Truncate file to 'offset' bytes (needed only for file protocols)   * Truncate file to 'offset' bytes (needed only for file protocols)
  */   */
Line 1606  static void multiwrite_user_cb(Multiwrit Line 1647  static void multiwrite_user_cb(Multiwrit
   
     for (i = 0; i < mcb->num_callbacks; i++) {      for (i = 0; i < mcb->num_callbacks; i++) {
         mcb->callbacks[i].cb(mcb->callbacks[i].opaque, mcb->error);          mcb->callbacks[i].cb(mcb->callbacks[i].opaque, mcb->error);
           if (mcb->callbacks[i].free_qiov) {
               qemu_iovec_destroy(mcb->callbacks[i].free_qiov);
           }
         qemu_free(mcb->callbacks[i].free_qiov);          qemu_free(mcb->callbacks[i].free_qiov);
         qemu_free(mcb->callbacks[i].free_buf);          qemu_vfree(mcb->callbacks[i].free_buf);
     }      }
 }  }
   
Line 1615  static void multiwrite_cb(void *opaque,  Line 1659  static void multiwrite_cb(void *opaque, 
 {  {
     MultiwriteCB *mcb = opaque;      MultiwriteCB *mcb = opaque;
   
     if (ret < 0) {      if (ret < 0 && !mcb->error) {
         mcb->error = ret;          mcb->error = ret;
         multiwrite_user_cb(mcb);  
     }      }
   
     mcb->num_requests--;      mcb->num_requests--;
     if (mcb->num_requests == 0) {      if (mcb->num_requests == 0) {
         if (mcb->error == 0) {          multiwrite_user_cb(mcb);
             multiwrite_user_cb(mcb);  
         }  
         qemu_free(mcb);          qemu_free(mcb);
     }      }
 }  }
   
 static int multiwrite_req_compare(const void *a, const void *b)  static int multiwrite_req_compare(const void *a, const void *b)
 {  {
     return (((BlockRequest*) a)->sector - ((BlockRequest*) b)->sector);      const BlockRequest *req1 = a, *req2 = b;
   
       /*
        * Note that we can't simply subtract req2->sector from req1->sector
        * here as that could overflow the return value.
        */
       if (req1->sector > req2->sector) {
           return 1;
       } else if (req1->sector < req2->sector) {
           return -1;
       } else {
           return 0;
       }
 }  }
   
 /*  /*
Line 1667  static int multiwrite_merge(BlockDriverS Line 1720  static int multiwrite_merge(BlockDriverS
             merge = bs->drv->bdrv_merge_requests(bs, &reqs[outidx], &reqs[i]);              merge = bs->drv->bdrv_merge_requests(bs, &reqs[outidx], &reqs[i]);
         }          }
   
           if (reqs[outidx].qiov->niov + reqs[i].qiov->niov + 1 > IOV_MAX) {
               merge = 0;
           }
   
         if (merge) {          if (merge) {
             size_t size;              size_t size;
             QEMUIOVector *qiov = qemu_mallocz(sizeof(*qiov));              QEMUIOVector *qiov = qemu_mallocz(sizeof(*qiov));
Line 1690  static int multiwrite_merge(BlockDriverS Line 1747  static int multiwrite_merge(BlockDriverS
             // Add the second request              // Add the second request
             qemu_iovec_concat(qiov, reqs[i].qiov, reqs[i].qiov->size);              qemu_iovec_concat(qiov, reqs[i].qiov, reqs[i].qiov->size);
   
             reqs[outidx].nb_sectors += reqs[i].nb_sectors;              reqs[outidx].nb_sectors = qiov->size >> 9;
             reqs[outidx].qiov = qiov;              reqs[outidx].qiov = qiov;
   
             mcb->callbacks[i].free_qiov = reqs[outidx].qiov;              mcb->callbacks[i].free_qiov = reqs[outidx].qiov;
Line 1742  int bdrv_aio_multiwrite(BlockDriverState Line 1799  int bdrv_aio_multiwrite(BlockDriverState
     // Check for mergable requests      // Check for mergable requests
     num_reqs = multiwrite_merge(bs, reqs, num_reqs, mcb);      num_reqs = multiwrite_merge(bs, reqs, num_reqs, mcb);
   
     // Run the aio requests      /*
        * Run the aio requests. As soon as one request can't be submitted
        * successfully, fail all requests that are not yet submitted (we must
        * return failure for all requests anyway)
        *
        * num_requests cannot be set to the right value immediately: If
        * bdrv_aio_writev fails for some request, num_requests would be too high
        * and therefore multiwrite_cb() would never recognize the multiwrite
        * request as completed. We also cannot use the loop variable i to set it
        * when the first request fails because the callback may already have been
        * called for previously submitted requests. Thus, num_requests must be
        * incremented for each request that is submitted.
        *
        * The problem that callbacks may be called early also means that we need
        * to take care that num_requests doesn't become 0 before all requests are
        * submitted - multiwrite_cb() would consider the multiwrite request
        * completed. A dummy request that is "completed" by a manual call to
        * multiwrite_cb() takes care of this.
        */
       mcb->num_requests = 1;
   
     for (i = 0; i < num_reqs; i++) {      for (i = 0; i < num_reqs; i++) {
           mcb->num_requests++;
         acb = bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,          acb = bdrv_aio_writev(bs, reqs[i].sector, reqs[i].qiov,
             reqs[i].nb_sectors, multiwrite_cb, mcb);              reqs[i].nb_sectors, multiwrite_cb, mcb);
   
Line 1751  int bdrv_aio_multiwrite(BlockDriverState Line 1829  int bdrv_aio_multiwrite(BlockDriverState
             // We can only fail the whole thing if no request has been              // We can only fail the whole thing if no request has been
             // submitted yet. Otherwise we'll wait for the submitted AIOs to              // submitted yet. Otherwise we'll wait for the submitted AIOs to
             // complete and report the error in the callback.              // complete and report the error in the callback.
             if (mcb->num_requests == 0) {              if (i == 0) {
                 reqs[i].error = EIO;  
                 goto fail;                  goto fail;
             } else {              } else {
                 mcb->error = EIO;                  multiwrite_cb(mcb, -EIO);
                 break;                  break;
             }              }
         } else {  
             mcb->num_requests++;  
         }          }
     }      }
   
       /* Complete the dummy request */
       multiwrite_cb(mcb, 0);
   
     return 0;      return 0;
   
 fail:  fail:
     free(mcb);      for (i = 0; i < mcb->num_callbacks; i++) {
           reqs[i].error = -EIO;
       }
       qemu_free(mcb);
     return -1;      return -1;
 }  }
   

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


unix.superglobalmegacorp.com