aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-07-14 11:48:46 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-07-14 11:48:46 +0100
commit9358450e98ed4a5350df4754863d116ff2e6186c (patch)
treec151c42717ff86db6b01c9b596eda9d9c9703ac2 /include
parent5bb2399f9b08198b6c03db10dd46e5a88caa2968 (diff)
parent543d7a42baf39c09db754ba9eca1d386e5958110 (diff)
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches # gpg: Signature made Wed 13 Jul 2016 12:46:17 BST # gpg: using RSA key 0x7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: (34 commits) iotests: Make 157 actually format-agnostic vvfat: Fix qcow write target driver specification hmp: show all of snapshot info on every block dev in output of 'info snapshots' hmp: use snapshot name to determine whether a snapshot is 'fully available' qemu-iotests: Test naming of throttling groups blockdev: Fix regression with the default naming of throttling groups vmdk: fix metadata write regression Improve block job rate limiting for small bandwidth values qcow2: Fix qcow2_get_cluster_offset() qemu-io: Use correct range limitations qcow2: Avoid making the L1 table too big qemu-img: Use strerror() for generic resize error block: Remove BB options from blockdev-add qemu-iotests: Test setting WCE with qdev block/qdev: Allow configuring rerror/werror with qdev properties commit: Fix use of error handling policy block/qdev: Allow configuring WCE with qdev properties block/qdev: Allow node name for drive properties coroutine: move entry argument to qemu_coroutine_create test-coroutine: prepare for the next patch ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'include')
-rw-r--r--include/block/block_int.h47
-rw-r--r--include/block/blockjob.h23
-rw-r--r--include/hw/block/block.h13
-rw-r--r--include/hw/qdev-properties.h4
-rw-r--r--include/qapi/qmp/qerror.h3
-rw-r--r--include/qemu/coroutine.h10
-rw-r--r--include/qemu/coroutine_int.h4
-rw-r--r--include/qemu/main-loop.h4
-rw-r--r--include/qemu/osdep.h3
-rw-r--r--include/qemu/ratelimit.h43
10 files changed, 106 insertions, 48 deletions
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 47b9aac71b..805414619d 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -639,11 +639,13 @@ int is_windows_drive(const char *filename);
/**
* stream_start:
+ * @job_id: The id of the newly-created job, or %NULL to use the
+ * device name of @bs.
* @bs: Block device to operate on.
* @base: Block device that will become the new base, or %NULL to
* flatten the whole backing file chain onto @bs.
- * @base_id: The file name that will be written to @bs as the new
- * backing file if the job completes. Ignored if @base is %NULL.
+ * @backing_file_str: The file name that will be written to @bs as the
+ * the new backing file if the job completes. Ignored if @base is %NULL.
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
* @on_error: The action to take upon error.
* @cb: Completion function for the job.
@@ -654,15 +656,18 @@ int is_windows_drive(const char *filename);
* in @bs, but allocated in any image between @base and @bs (both
* exclusive) will be written to @bs. At the end of a successful
* streaming job, the backing file of @bs will be changed to
- * @base_id in the written image and to @base in the live BlockDriverState.
+ * @backing_file_str in the written image and to @base in the live
+ * BlockDriverState.
*/
-void stream_start(BlockDriverState *bs, BlockDriverState *base,
- const char *base_id, int64_t speed, BlockdevOnError on_error,
- BlockCompletionFunc *cb,
- void *opaque, Error **errp);
+void stream_start(const char *job_id, BlockDriverState *bs,
+ BlockDriverState *base, const char *backing_file_str,
+ int64_t speed, BlockdevOnError on_error,
+ BlockCompletionFunc *cb, void *opaque, Error **errp);
/**
* commit_start:
+ * @job_id: The id of the newly-created job, or %NULL to use the
+ * device name of @bs.
* @bs: Active block device.
* @top: Top block device to be committed.
* @base: Block device that will be written into, and become the new top.
@@ -674,12 +679,14 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base,
* @errp: Error object.
*
*/
-void commit_start(BlockDriverState *bs, BlockDriverState *base,
- BlockDriverState *top, int64_t speed,
- BlockdevOnError on_error, BlockCompletionFunc *cb,
- void *opaque, const char *backing_file_str, Error **errp);
+void commit_start(const char *job_id, BlockDriverState *bs,
+ BlockDriverState *base, BlockDriverState *top, int64_t speed,
+ BlockdevOnError on_error, BlockCompletionFunc *cb,
+ void *opaque, const char *backing_file_str, Error **errp);
/**
* commit_active_start:
+ * @job_id: The id of the newly-created job, or %NULL to use the
+ * device name of @bs.
* @bs: Active block device to be committed.
* @base: Block device that will be written into, and become the new top.
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
@@ -689,13 +696,15 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
* @errp: Error object.
*
*/
-void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
- int64_t speed,
+void commit_active_start(const char *job_id, BlockDriverState *bs,
+ BlockDriverState *base, int64_t speed,
BlockdevOnError on_error,
BlockCompletionFunc *cb,
void *opaque, Error **errp);
/*
* mirror_start:
+ * @job_id: The id of the newly-created job, or %NULL to use the
+ * device name of @bs.
* @bs: Block device to operate on.
* @target: Block device to write to.
* @replaces: Block graph node name to replace once the mirror is done. Can
@@ -717,8 +726,8 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
* manually completed. At the end of a successful mirroring job,
* @bs will be switched to read from @target.
*/
-void mirror_start(BlockDriverState *bs, BlockDriverState *target,
- const char *replaces,
+void mirror_start(const char *job_id, BlockDriverState *bs,
+ BlockDriverState *target, const char *replaces,
int64_t speed, uint32_t granularity, int64_t buf_size,
MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
BlockdevOnError on_source_error,
@@ -729,6 +738,8 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
/*
* backup_start:
+ * @job_id: The id of the newly-created job, or %NULL to use the
+ * device name of @bs.
* @bs: Block device to operate on.
* @target: Block device to write to.
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
@@ -743,9 +754,9 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
* Start a backup operation on @bs. Clusters in @bs are written to @target
* until the job is cancelled or manually completed.
*/
-void backup_start(BlockDriverState *bs, BlockDriverState *target,
- int64_t speed, MirrorSyncMode sync_mode,
- BdrvDirtyBitmap *sync_bitmap,
+void backup_start(const char *job_id, BlockDriverState *bs,
+ BlockDriverState *target, int64_t speed,
+ MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
BlockCompletionFunc *cb, void *opaque,
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index f7f5687cf4..4ddb4ae2e1 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -107,10 +107,7 @@ struct BlockJob {
BlockBackend *blk;
/**
- * The ID of the block job. Currently the BlockBackend name of the BDS
- * owning the job at the time when the job is started.
- *
- * TODO Decouple block job IDs from BlockBackend names
+ * The ID of the block job.
*/
char *id;
@@ -215,7 +212,19 @@ struct BlockJob {
BlockJob *block_job_next(BlockJob *job);
/**
+ * block_job_get:
+ * @id: The id of the block job.
+ *
+ * Get the block job identified by @id (which must not be %NULL).
+ *
+ * Returns the requested job, or %NULL if it doesn't exist.
+ */
+BlockJob *block_job_get(const char *id);
+
+/**
* block_job_create:
+ * @job_id: The id of the newly-created job, or %NULL to have one
+ * generated automatically.
* @job_type: The class object for the newly-created job.
* @bs: The block
* @speed: The maximum speed, in bytes per second, or 0 for unlimited.
@@ -232,9 +241,9 @@ BlockJob *block_job_next(BlockJob *job);
* This function is not part of the public job interface; it should be
* called from a wrapper that is specific to the job type.
*/
-void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
- int64_t speed, BlockCompletionFunc *cb,
- void *opaque, Error **errp);
+void *block_job_create(const char *job_id, const BlockJobDriver *driver,
+ BlockDriverState *bs, int64_t speed,
+ BlockCompletionFunc *cb, void *opaque, Error **errp);
/**
* block_job_sleep_ns:
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
index 87c87ed92a..df9d207d81 100644
--- a/include/hw/block/block.h
+++ b/include/hw/block/block.h
@@ -25,6 +25,9 @@ typedef struct BlockConf {
uint32_t discard_granularity;
/* geometry, not all devices use this */
uint32_t cyls, heads, secs;
+ OnOffAuto wce;
+ BlockdevOnError rerror;
+ BlockdevOnError werror;
} BlockConf;
static inline unsigned int get_physical_block_exp(BlockConf *conf)
@@ -49,13 +52,20 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0), \
DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0), \
DEFINE_PROP_UINT32("discard_granularity", _state, \
- _conf.discard_granularity, -1)
+ _conf.discard_granularity, -1), \
+ DEFINE_PROP_ON_OFF_AUTO("write-cache", _state, _conf.wce, ON_OFF_AUTO_AUTO)
#define DEFINE_BLOCK_CHS_PROPERTIES(_state, _conf) \
DEFINE_PROP_UINT32("cyls", _state, _conf.cyls, 0), \
DEFINE_PROP_UINT32("heads", _state, _conf.heads, 0), \
DEFINE_PROP_UINT32("secs", _state, _conf.secs, 0)
+#define DEFINE_BLOCK_ERROR_PROPERTIES(_state, _conf) \
+ DEFINE_PROP_BLOCKDEV_ON_ERROR("rerror", _state, _conf.rerror, \
+ BLOCKDEV_ON_ERROR_AUTO), \
+ DEFINE_PROP_BLOCKDEV_ON_ERROR("werror", _state, _conf.werror, \
+ BLOCKDEV_ON_ERROR_AUTO)
+
/* Configuration helpers */
void blkconf_serial(BlockConf *conf, char **serial);
@@ -63,6 +73,7 @@ void blkconf_geometry(BlockConf *conf, int *trans,
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
Error **errp);
void blkconf_blocksizes(BlockConf *conf);
+void blkconf_apply_backend_options(BlockConf *conf);
/* Hard disk geometry */
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 034b75acc5..2a9d2f90e6 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -20,6 +20,7 @@ extern PropertyInfo qdev_prop_ptr;
extern PropertyInfo qdev_prop_macaddr;
extern PropertyInfo qdev_prop_on_off_auto;
extern PropertyInfo qdev_prop_losttickpolicy;
+extern PropertyInfo qdev_prop_blockdev_on_error;
extern PropertyInfo qdev_prop_bios_chs_trans;
extern PropertyInfo qdev_prop_fdc_drive_type;
extern PropertyInfo qdev_prop_drive;
@@ -161,6 +162,9 @@ extern PropertyInfo qdev_prop_arraylen;
#define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \
LostTickPolicy)
+#define DEFINE_PROP_BLOCKDEV_ON_ERROR(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blockdev_on_error, \
+ BlockdevOnError)
#define DEFINE_PROP_BIOS_CHS_TRANS(_n, _s, _f, _d) \
DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_bios_chs_trans, int)
#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f) \
diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h
index d08652aaa5..6586c9fa62 100644
--- a/include/qapi/qmp/qerror.h
+++ b/include/qapi/qmp/qerror.h
@@ -19,9 +19,6 @@
#define QERR_BASE_NOT_FOUND \
"Base '%s' not found"
-#define QERR_BLOCK_JOB_NOT_READY \
- "The active block job for device '%s' cannot be completed"
-
#define QERR_BUS_NO_HOTPLUG \
"Bus '%s' does not support hotplugging"
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index 305fe76c29..ac8d4c9cc8 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -61,16 +61,14 @@ typedef void coroutine_fn CoroutineEntry(void *opaque);
* Create a new coroutine
*
* Use qemu_coroutine_enter() to actually transfer control to the coroutine.
+ * The opaque argument is passed as the argument to the entry point.
*/
-Coroutine *qemu_coroutine_create(CoroutineEntry *entry);
+Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque);
/**
* Transfer control to a coroutine
- *
- * The opaque argument is passed as the argument to the entry point when
- * entering the coroutine for the first time. It is subsequently ignored.
*/
-void qemu_coroutine_enter(Coroutine *coroutine, void *opaque);
+void qemu_coroutine_enter(Coroutine *coroutine);
/**
* Transfer control back to a coroutine's caller
@@ -102,7 +100,7 @@ bool qemu_in_coroutine(void);
* are built.
*/
typedef struct CoQueue {
- QTAILQ_HEAD(, Coroutine) entries;
+ QSIMPLEQ_HEAD(, Coroutine) entries;
} CoQueue;
/**
diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h
index 42d6838401..581a7f5140 100644
--- a/include/qemu/coroutine_int.h
+++ b/include/qemu/coroutine_int.h
@@ -41,8 +41,8 @@ struct Coroutine {
QSLIST_ENTRY(Coroutine) pool_next;
/* Coroutines that should be woken up when we yield or terminate */
- QTAILQ_HEAD(, Coroutine) co_queue_wakeup;
- QTAILQ_ENTRY(Coroutine) co_queue_next;
+ QSIMPLEQ_HEAD(, Coroutine) co_queue_wakeup;
+ QSIMPLEQ_ENTRY(Coroutine) co_queue_next;
};
Coroutine *qemu_coroutine_new(void);
diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
index 3fa7cfe574..470f600bbc 100644
--- a/include/qemu/main-loop.h
+++ b/include/qemu/main-loop.h
@@ -64,11 +64,11 @@ int qemu_init_main_loop(Error **errp);
*
* void enter_co_bh(void *opaque) {
* QEMUCoroutine *co = opaque;
- * qemu_coroutine_enter(co, NULL);
+ * qemu_coroutine_enter(co);
* }
*
* ...
- * QEMUCoroutine *co = qemu_coroutine_create(coroutine_entry);
+ * QEMUCoroutine *co = qemu_coroutine_create(coroutine_entry, NULL);
* QEMUBH *start_bh = qemu_bh_new(enter_co_bh, co);
* qemu_bh_schedule(start_bh);
* while (...) {
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index e63da2831a..7361006c50 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -278,6 +278,9 @@ int qemu_madvise(void *addr, size_t len, int advice);
int qemu_open(const char *name, int flags, ...);
int qemu_close(int fd);
+#ifndef _WIN32
+int qemu_dup(int fd);
+#endif
#if defined(__HAIKU__) && defined(__i386__)
#define FMT_pid "%ld"
diff --git a/include/qemu/ratelimit.h b/include/qemu/ratelimit.h
index 1e3cb13b28..8da1232574 100644
--- a/include/qemu/ratelimit.h
+++ b/include/qemu/ratelimit.h
@@ -15,34 +15,59 @@
#define QEMU_RATELIMIT_H
typedef struct {
- int64_t next_slice_time;
+ int64_t slice_start_time;
+ int64_t slice_end_time;
uint64_t slice_quota;
uint64_t slice_ns;
uint64_t dispatched;
} RateLimit;
+/** Calculate and return delay for next request in ns
+ *
+ * Record that we sent @p n data units. If we may send more data units
+ * in the current time slice, return 0 (i.e. no delay). Otherwise
+ * return the amount of time (in ns) until the start of the next time
+ * slice that will permit sending the next chunk of data.
+ *
+ * Recording sent data units even after exceeding the quota is
+ * permitted; the time slice will be extended accordingly.
+ */
static inline int64_t ratelimit_calculate_delay(RateLimit *limit, uint64_t n)
{
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
+ uint64_t delay_slices;
- if (limit->next_slice_time < now) {
- limit->next_slice_time = now + limit->slice_ns;
+ assert(limit->slice_quota && limit->slice_ns);
+
+ if (limit->slice_end_time < now) {
+ /* Previous, possibly extended, time slice finished; reset the
+ * accounting. */
+ limit->slice_start_time = now;
+ limit->slice_end_time = now + limit->slice_ns;
limit->dispatched = 0;
}
- if (limit->dispatched == 0 || limit->dispatched + n <= limit->slice_quota) {
- limit->dispatched += n;
+
+ limit->dispatched += n;
+ if (limit->dispatched < limit->slice_quota) {
+ /* We may send further data within the current time slice, no
+ * need to delay the next request. */
return 0;
- } else {
- limit->dispatched = n;
- return limit->next_slice_time - now;
}
+
+ /* Quota exceeded. Calculate the next time slice we may start
+ * sending data again. */
+ delay_slices = (limit->dispatched + limit->slice_quota - 1) /
+ limit->slice_quota;
+ limit->slice_end_time = limit->slice_start_time +
+ delay_slices * limit->slice_ns;
+ return limit->slice_end_time - now;
}
static inline void ratelimit_set_speed(RateLimit *limit, uint64_t speed,
uint64_t slice_ns)
{
limit->slice_ns = slice_ns;
- limit->slice_quota = ((double)speed * slice_ns)/1000000000ULL;
+ limit->slice_quota = MAX(((double)speed * slice_ns) / 1000000000ULL, 1);
}
#endif