diff --git a/block.c b/block.c index 0ae2e93982..602d8a443e 100644 --- a/block.c +++ b/block.c @@ -140,8 +140,6 @@ void bdrv_io_limits_disable(BlockDriverState *bs) bs->slice_start = 0; bs->slice_end = 0; - bs->slice_time = 0; - memset(&bs->io_base, 0, sizeof(bs->io_base)); } static void bdrv_block_timer(void *opaque) @@ -1433,11 +1431,10 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest, bs_dest->enable_write_cache = bs_src->enable_write_cache; /* i/o timing parameters */ - bs_dest->slice_time = bs_src->slice_time; bs_dest->slice_start = bs_src->slice_start; bs_dest->slice_end = bs_src->slice_end; + bs_dest->slice_submitted = bs_src->slice_submitted; bs_dest->io_limits = bs_src->io_limits; - bs_dest->io_base = bs_src->io_base; bs_dest->throttled_reqs = bs_src->throttled_reqs; bs_dest->block_timer = bs_src->block_timer; bs_dest->io_limits_enabled = bs_src->io_limits_enabled; @@ -3750,6 +3747,7 @@ static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors, bool is_write, double elapsed_time, uint64_t *wait) { uint64_t bps_limit = 0; + uint64_t extension; double bytes_limit, bytes_base, bytes_res; double slice_time, wait_time; @@ -3768,9 +3766,9 @@ static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors, slice_time = bs->slice_end - bs->slice_start; slice_time /= (NANOSECONDS_PER_SECOND); bytes_limit = bps_limit * slice_time; - bytes_base = bs->nr_bytes[is_write] - bs->io_base.bytes[is_write]; + bytes_base = bs->slice_submitted.bytes[is_write]; if (bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]) { - bytes_base += bs->nr_bytes[!is_write] - bs->io_base.bytes[!is_write]; + bytes_base += bs->slice_submitted.bytes[!is_write]; } /* bytes_base: the bytes of data which have been read/written; and @@ -3797,10 +3795,12 @@ static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors, * info can be kept until the timer fire, so it is increased and tuned * based on the result of experiment. */ - bs->slice_time = wait_time * BLOCK_IO_SLICE_TIME * 10; - bs->slice_end += bs->slice_time - 3 * BLOCK_IO_SLICE_TIME; + extension = wait_time * NANOSECONDS_PER_SECOND; + extension = DIV_ROUND_UP(extension, BLOCK_IO_SLICE_TIME) * + BLOCK_IO_SLICE_TIME; + bs->slice_end += extension; if (wait) { - *wait = wait_time * BLOCK_IO_SLICE_TIME * 10; + *wait = wait_time * NANOSECONDS_PER_SECOND; } return true; @@ -3828,9 +3828,9 @@ static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write, slice_time = bs->slice_end - bs->slice_start; slice_time /= (NANOSECONDS_PER_SECOND); ios_limit = iops_limit * slice_time; - ios_base = bs->nr_ops[is_write] - bs->io_base.ios[is_write]; + ios_base = bs->slice_submitted.ios[is_write]; if (bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]) { - ios_base += bs->nr_ops[!is_write] - bs->io_base.ios[!is_write]; + ios_base += bs->slice_submitted.ios[!is_write]; } if (ios_base + 1 <= ios_limit) { @@ -3841,7 +3841,7 @@ static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write, return false; } - /* Calc approx time to dispatch */ + /* Calc approx time to dispatch, in seconds */ wait_time = (ios_base + 1) / iops_limit; if (wait_time > elapsed_time) { wait_time = wait_time - elapsed_time; @@ -3849,10 +3849,10 @@ static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write, wait_time = 0; } - bs->slice_time = wait_time * BLOCK_IO_SLICE_TIME * 10; - bs->slice_end += bs->slice_time - 3 * BLOCK_IO_SLICE_TIME; + /* Exceeded current slice, extend it by another slice time */ + bs->slice_end += BLOCK_IO_SLICE_TIME; if (wait) { - *wait = wait_time * BLOCK_IO_SLICE_TIME * 10; + *wait = wait_time * NANOSECONDS_PER_SECOND; } return true; @@ -3867,19 +3867,10 @@ static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors, int bps_ret, iops_ret; now = qemu_get_clock_ns(vm_clock); - if ((bs->slice_start < now) - && (bs->slice_end > now)) { - bs->slice_end = now + bs->slice_time; - } else { - bs->slice_time = 5 * BLOCK_IO_SLICE_TIME; + if (now > bs->slice_end) { bs->slice_start = now; - bs->slice_end = now + bs->slice_time; - - bs->io_base.bytes[is_write] = bs->nr_bytes[is_write]; - bs->io_base.bytes[!is_write] = bs->nr_bytes[!is_write]; - - bs->io_base.ios[is_write] = bs->nr_ops[is_write]; - bs->io_base.ios[!is_write] = bs->nr_ops[!is_write]; + bs->slice_end = now + BLOCK_IO_SLICE_TIME; + memset(&bs->slice_submitted, 0, sizeof(bs->slice_submitted)); } elapsed_time = now - bs->slice_start; @@ -3907,6 +3898,10 @@ static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors, *wait = 0; } + bs->slice_submitted.bytes[is_write] += (int64_t)nb_sectors * + BDRV_SECTOR_SIZE; + bs->slice_submitted.ios[is_write]++; + return false; } diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index c38e970bf2..b32738f8d9 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -747,10 +747,9 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, if (l1_table_offset != s->l1_table_offset) { l1_table = g_malloc0(align_offset(l1_size2, 512)); l1_allocated = 1; - if (bdrv_pread(bs->file, l1_table_offset, - l1_table, l1_size2) != l1_size2) - { - ret = -EIO; + + ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size2); + if (ret < 0) { goto fail; } @@ -802,7 +801,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, } if (refcount < 0) { - ret = -EIO; + ret = refcount; goto fail; } } @@ -833,7 +832,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, refcount = get_refcount(bs, l2_offset >> s->cluster_bits); } if (refcount < 0) { - ret = -EIO; + ret = refcount; goto fail; } else if (refcount == 1) { l2_offset |= QCOW_OFLAG_COPIED; @@ -852,14 +851,16 @@ fail: } /* Update L1 only if it isn't deleted anyway (addend = -1) */ - if (addend >= 0 && l1_modified) { - for(i = 0; i < l1_size; i++) + if (ret == 0 && addend >= 0 && l1_modified) { + for (i = 0; i < l1_size; i++) { cpu_to_be64s(&l1_table[i]); - if (bdrv_pwrite_sync(bs->file, l1_table_offset, l1_table, - l1_size2) < 0) - goto fail; - for(i = 0; i < l1_size; i++) + } + + ret = bdrv_pwrite_sync(bs->file, l1_table_offset, l1_table, l1_size2); + + for (i = 0; i < l1_size; i++) { be64_to_cpus(&l1_table[i]); + } } if (l1_allocated) g_free(l1_table); diff --git a/blockdev.c b/blockdev.c index 8cdc9ce16a..6dc999d802 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1069,7 +1069,6 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, } bs->io_limits = io_limits; - bs->slice_time = BLOCK_IO_SLICE_TIME; if (!bs->io_limits_enabled && bdrv_io_limits_enabled(bs)) { bdrv_io_limits_enable(bs); diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c index f38df30540..180ee07fef 100644 --- a/hw/pci/pci-hotplug.c +++ b/hw/pci/pci-hotplug.c @@ -99,7 +99,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter, dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1); dinfo->bus = scsibus->busnr; scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, - false, -1); + false, -1, NULL); if (!scsidev) { return -1; } diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 08787c2a9b..ac2093a5ef 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -207,7 +207,8 @@ static int scsi_qdev_exit(DeviceState *qdev) /* handle legacy '-drive if=scsi,...' cmd line args */ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, - int unit, bool removable, int bootindex) + int unit, bool removable, int bootindex, + const char *serial) { const char *driver; DeviceState *dev; @@ -221,6 +222,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, if (object_property_find(OBJECT(dev), "removable", NULL)) { qdev_prop_set_bit(dev, "removable", removable); } + if (serial) { + qdev_prop_set_string(dev, "serial", serial); + } if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) { qdev_free(dev); return NULL; @@ -243,7 +247,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus) continue; } qemu_opts_loc_restore(dinfo->opts); - if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1)) { + if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1, NULL)) { res = -1; break; } diff --git a/hw/scsi.h b/hw/scsi.h index 33e2e0bdf1..02a1497d7a 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -160,7 +160,8 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d) } SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, - int unit, bool removable, int bootindex); + int unit, bool removable, int bootindex, + const char *serial); int scsi_bus_legacy_handle_cmdline(SCSIBus *bus); /* diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index d3f01aa2a7..21651b3637 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -625,7 +625,7 @@ static int usb_msd_initfn_storage(USBDevice *dev) usb_desc_init(dev); scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_storage); scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable, - s->conf.bootindex); + s->conf.bootindex, s->serial); if (!scsi_dev) { return -1; } diff --git a/include/block/block_int.h b/include/block/block_int.h index 0986a2d6ac..9aa98b5d12 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -252,11 +252,10 @@ struct BlockDriverState { unsigned int copy_on_read_in_flight; /* the time for latest disk I/O */ - int64_t slice_time; int64_t slice_start; int64_t slice_end; BlockIOLimit io_limits; - BlockIOBaseValue io_base; + BlockIOBaseValue slice_submitted; CoQueue throttled_reqs; QEMUTimer *block_timer; bool io_limits_enabled;