mirror of
https://github.com/qemu/qemu.git
synced 2024-11-25 11:53:39 +08:00
Merge remote-tracking branch 'kwolf/for-anthony' into staging
# By Stefan Hajnoczi (4) and Kevin Wolf (3) # Via Kevin Wolf * kwolf/for-anthony: qcow2: Fix L1 write error handling in qcow2_update_snapshot_refcount qcow2: Return real error in qcow2_update_snapshot_refcount block: clean up I/O throttling wait_time code block: drop duplicated slice extension code block: keep I/O throttling slice time constant block: fix I/O throttling accounting blind spot usb-storage: Forward serial number to scsi-disk
This commit is contained in:
commit
5098699a51
49
block.c
49
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user