From ebde595ce63369921dbbe1bd16fec0b230050d67 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 9 Nov 2015 18:16:46 +0800 Subject: block: Add more types for tracked request We'll track more request types besides read and write, change the boolean field to an enum. Signed-off-by: Fam Zheng Reviewed-by: Kevin Wolf Message-id: 1447064214-29930-2-git-send-email-famz@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/block_int.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/block/block_int.h b/include/block/block_int.h index 603145a21d..ac034069ff 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -60,11 +60,19 @@ #define BLOCK_PROBE_BUF_SIZE 512 +enum BdrvTrackedRequestType { + BDRV_TRACKED_READ, + BDRV_TRACKED_WRITE, + BDRV_TRACKED_FLUSH, + BDRV_TRACKED_IOCTL, + BDRV_TRACKED_DISCARD, +}; + typedef struct BdrvTrackedRequest { BlockDriverState *bs; int64_t offset; unsigned int bytes; - bool is_write; + enum BdrvTrackedRequestType type; bool serialising; int64_t overlap_offset; -- cgit v1.2.3 From 8b45f6878d291646cadc4786ae807e6a42c188b4 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 9 Nov 2015 18:16:50 +0800 Subject: block: Add ioctl parameter fields to BlockRequest The two fields that will be used by ioctl handling code later are added as union, because it's used exclusively by ioctl code which dosn't need the four fields in the other struct of the union. Signed-off-by: Fam Zheng Reviewed-by: Kevin Wolf Message-id: 1447064214-29930-6-git-send-email-famz@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/block.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/block/block.h b/include/block/block.h index 610db923d5..c8b40b739f 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -335,10 +335,18 @@ void bdrv_aio_cancel_async(BlockAIOCB *acb); typedef struct BlockRequest { /* Fields to be filled by multiwrite caller */ - int64_t sector; - int nb_sectors; - int flags; - QEMUIOVector *qiov; + union { + struct { + int64_t sector; + int nb_sectors; + int flags; + QEMUIOVector *qiov; + }; + struct { + int req; + void *buf; + }; + }; BlockCompletionFunc *cb; void *opaque; -- cgit v1.2.3 From 83c98d7b924eab36a0a2c7813731dbef439a91d3 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 9 Nov 2015 18:16:52 +0800 Subject: block: Drop BlockDriver.bdrv_ioctl Now the callback is not used any more, drop the field along with all implementations in block drivers, which are iscsi and raw. Signed-off-by: Fam Zheng Reviewed-by: Kevin Wolf Message-id: 1447064214-29930-8-git-send-email-famz@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/block_int.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/block/block_int.h b/include/block/block_int.h index ac034069ff..84991d9973 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -227,7 +227,6 @@ struct BlockDriver { void (*bdrv_lock_medium)(BlockDriverState *bs, bool locked); /* to control generic scsi devices */ - int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf); BlockAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf, BlockCompletionFunc *cb, void *opaque); -- cgit v1.2.3 From 67da1dc5ce696c7b309b1db100da7d94292847b7 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 9 Nov 2015 18:16:53 +0800 Subject: block: Introduce BlockDriver.bdrv_drain callback Drivers can have internal request sources that generate IO, like the need_check_timer in QED. Since we want quiesced periods that contain nested event loops in block layer, we need to have a way to disable such event sources. Block drivers must implement the "bdrv_drain" callback if it has any internal sources that can generate I/O activity, like a timer or a worker thread (even in a library) that can schedule QEMUBH in an asynchronous callback. Update the comments of bdrv_drain and bdrv_drained_begin accordingly. Like bdrv_requests_pending(), we should consider all the children of bs. Before, the while loop just works, as bdrv_requests_pending() already tracks its children; now we mustn't miss the callback, so recurse down explicitly. Signed-off-by: Fam Zheng Reviewed-by: Paolo Bonzini Message-id: 1447064214-29930-9-git-send-email-famz@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/block_int.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/block/block_int.h b/include/block/block_int.h index 84991d9973..3a24913a7e 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -295,6 +295,12 @@ struct BlockDriver { */ int (*bdrv_probe_geometry)(BlockDriverState *bs, HDGeometry *geo); + /** + * Drain and stop any internal sources of requests in the driver, and + * remain so until next I/O callback (e.g. bdrv_co_writev) is called. + */ + void (*bdrv_drain)(BlockDriverState *bs); + QLIST_ENTRY(BlockDriver) list; }; -- cgit v1.2.3 From df9a681dc9ad41c9cdeb9ecc5d060ba9abd27e01 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Mon, 9 Nov 2015 18:16:54 +0800 Subject: qed: Implement .bdrv_drain The "need_check_timer" is used to clear the "NEED_CHECK" flag in the image header after a grace period once metadata update has finished. In compliance to the bdrv_drain semantics we should make sure it remains deleted once .bdrv_drain is called. We cannot reuse qed_need_check_timer_cb because here it doesn't satisfy the assertion. Do the "plug" and "flush" calls manually. Signed-off-by: Fam Zheng Reviewed-by: Kevin Wolf Message-id: 1447064214-29930-10-git-send-email-famz@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/block.h | 1 - include/block/block_int.h | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/block/block.h b/include/block/block.h index c8b40b739f..92f6f6a95a 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -501,7 +501,6 @@ void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap, int64_t cur_sector, int nr_sectors); void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap, int64_t cur_sector, int nr_sectors); -void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap); void bdrv_dirty_iter_init(BdrvDirtyBitmap *bitmap, struct HBitmapIter *hbi); void bdrv_set_dirty_iter(struct HBitmapIter *hbi, int64_t offset); int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap); diff --git a/include/block/block_int.h b/include/block/block_int.h index 3a24913a7e..695393e6e6 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -693,4 +693,7 @@ void blk_dev_resize_cb(BlockBackend *blk); void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, int nr_sectors); bool bdrv_requests_pending(BlockDriverState *bs); +void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out); +void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in); + #endif /* BLOCK_INT_H */ -- cgit v1.2.3 From 18930ba3d17866fff6df52ae6d2e54ce5c5ca04b Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Thu, 5 Nov 2015 18:13:11 -0500 Subject: blockjob: Introduce reference count and fix reference to job->bs Add reference count to block job, meanwhile move the ownership of the reference to job->bs from the caller (which is released in two completion callbacks) to the block job itself. It is necessary for block_job_complete_sync to work, because block job shouldn't live longer than its bs, as asserted in bdrv_delete. Now block_job_complete_sync can be simplified. Signed-off-by: Fam Zheng Signed-off-by: John Snow Message-id: 1446765200-3054-6-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/blockjob.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/block/blockjob.h b/include/block/blockjob.h index 289b13f0c0..b649a402a0 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -130,6 +130,9 @@ struct BlockJob { /** The opaque value that is passed to the completion function. */ void *opaque; + + /** Reference count of the block job */ + int refcnt; }; /** @@ -174,12 +177,21 @@ void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns); void block_job_yield(BlockJob *job); /** - * block_job_release: + * block_job_ref: + * @bs: The block device. + * + * Grab a reference to the block job. Should be paired with block_job_unref. + */ +void block_job_ref(BlockJob *job); + +/** + * block_job_unref: * @bs: The block device. * - * Release job resources when an error occurred or job completed. + * Release reference to the block job and release resources if it is the last + * reference. */ -void block_job_release(BlockDriverState *bs); +void block_job_unref(BlockJob *job); /** * block_job_completed: -- cgit v1.2.3 From 57901ecb8e02f03464d5f37bb6edf82e5076812d Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Thu, 5 Nov 2015 18:13:12 -0500 Subject: blockjob: Add .commit and .abort block job actions Reviewed-by: Max Reitz Reviewed-by: John Snow Signed-off-by: Fam Zheng Signed-off-by: John Snow Message-id: 1446765200-3054-7-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/blockjob.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'include') diff --git a/include/block/blockjob.h b/include/block/blockjob.h index b649a402a0..ed856d72bf 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -50,6 +50,26 @@ typedef struct BlockJobDriver { * manually. */ void (*complete)(BlockJob *job, Error **errp); + + /** + * If the callback is not NULL, it will be invoked when all the jobs + * belonging to the same transaction complete; or upon this job's + * completion if it is not in a transaction. Skipped if NULL. + * + * All jobs will complete with a call to either .commit() or .abort() but + * never both. + */ + void (*commit)(BlockJob *job); + + /** + * If the callback is not NULL, it will be invoked when any job in the + * same transaction fails; or upon this job's failure (due to error or + * cancellation) if it is not in a transaction. Skipped if NULL. + * + * All jobs will complete with a call to either .commit() or .abort() but + * never both. + */ + void (*abort)(BlockJob *job); } BlockJobDriver; /** -- cgit v1.2.3 From a689dbf2df74a55d43e3fc4d6aec30ed67ca998f Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Thu, 5 Nov 2015 18:13:13 -0500 Subject: blockjob: Add "completed" and "ret" in BlockJob They are set when block_job_completed is called. Signed-off-by: Fam Zheng Reviewed-by: John Snow Reviewed-by: Max Reitz Signed-off-by: John Snow Message-id: 1446765200-3054-8-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/blockjob.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include') diff --git a/include/block/blockjob.h b/include/block/blockjob.h index ed856d72bf..c70d55a644 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -153,6 +153,15 @@ struct BlockJob { /** Reference count of the block job */ int refcnt; + + /* True if this job has reported completion by calling block_job_completed. + */ + bool completed; + + /* ret code passed to block_job_completed. + */ + int ret; + }; /** -- cgit v1.2.3 From c55a832fdddec2c350b585ade0476501f616608d Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Thu, 5 Nov 2015 18:13:15 -0500 Subject: block: Add block job transactions Sometimes block jobs must execute as a transaction group. Finishing jobs wait until all other jobs are ready to complete successfully. Failure or cancellation of one job cancels the other jobs in the group. Signed-off-by: Stefan Hajnoczi Reviewed-by: Max Reitz Signed-off-by: Fam Zheng Signed-off-by: John Snow Message-id: 1446765200-3054-10-git-send-email-jsnow@redhat.com [Rewrite the implementation which is now contained in block_job_completed. --Fam] Signed-off-by: Fam Zheng Reviewed-by: Max Reitz Signed-off-by: John Snow Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/block.h | 1 + include/block/blockjob.h | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) (limited to 'include') diff --git a/include/block/block.h b/include/block/block.h index 92f6f6a95a..73edb1a79c 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -14,6 +14,7 @@ typedef struct BlockDriver BlockDriver; typedef struct BlockJob BlockJob; typedef struct BdrvChild BdrvChild; typedef struct BdrvChildRole BdrvChildRole; +typedef struct BlockJobTxn BlockJobTxn; typedef struct BlockDriverInfo { /* in bytes, 0 if irrelevant */ diff --git a/include/block/blockjob.h b/include/block/blockjob.h index c70d55a644..d84ccd8d2c 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -162,6 +162,9 @@ struct BlockJob { */ int ret; + /** Non-NULL if this job is part of a transaction */ + BlockJobTxn *txn; + QLIST_ENTRY(BlockJob) txn_list; }; /** @@ -405,4 +408,39 @@ void block_job_defer_to_main_loop(BlockJob *job, BlockJobDeferToMainLoopFn *fn, void *opaque); +/** + * block_job_txn_new: + * + * Allocate and return a new block job transaction. Jobs can be added to the + * transaction using block_job_txn_add_job(). + * + * The transaction is automatically freed when the last job completes or is + * cancelled. + * + * All jobs in the transaction either complete successfully or fail/cancel as a + * group. Jobs wait for each other before completing. Cancelling one job + * cancels all jobs in the transaction. + */ +BlockJobTxn *block_job_txn_new(void); + +/** + * block_job_txn_unref: + * + * Release a reference that was previously acquired with block_job_txn_add_job + * or block_job_txn_new. If it's the last reference to the object, it will be + * freed. + */ +void block_job_txn_unref(BlockJobTxn *txn); + +/** + * block_job_txn_add_job: + * @txn: The transaction (may be NULL) + * @job: Job to add to the transaction + * + * Add @job to the transaction. The @job must not already be in a transaction. + * The caller must call either block_job_txn_unref() or block_job_completed() + * to release the reference that is automatically grabbed here. + */ +void block_job_txn_add_job(BlockJobTxn *txn, BlockJob *job); + #endif -- cgit v1.2.3 From 78f51fde88d1925b5ae51ba789339baa9ff72ad1 Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 5 Nov 2015 18:13:17 -0500 Subject: block: Add BlockJobTxn support to backup_run Allow a BlockJobTxn to be passed into backup_run, which will allow the job to join a transactional group if present. Propagate this new parameter outward into new QMP helper functions in blockdev.c to allow transaction commands to pass forward their BlockJobTxn object in a forthcoming patch. [split up from a patch originally by Stefan and Fam. --js] Signed-off-by: Stefan Hajnoczi Signed-off-by: Fam Zheng Signed-off-by: John Snow Signed-off-by: John Snow Message-id: 1446765200-3054-12-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/block_int.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/block/block_int.h b/include/block/block_int.h index 695393e6e6..4012e36437 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -669,6 +669,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target, * @on_target_error: The action to take upon error writing to the target. * @cb: Completion function for the job. * @opaque: Opaque pointer value passed to @cb. + * @txn: Transaction that this job is part of (may be NULL). * * Start a backup operation on @bs. Clusters in @bs are written to @target * until the job is cancelled or manually completed. @@ -679,7 +680,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target, BlockdevOnError on_source_error, BlockdevOnError on_target_error, BlockCompletionFunc *cb, void *opaque, - Error **errp); + BlockJobTxn *txn, Error **errp); void blk_set_bs(BlockBackend *blk, BlockDriverState *bs); -- cgit v1.2.3 From bd797fc15b4290e02c219b7cd6289a33cd6cd18b Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Wed, 28 Oct 2015 17:33:01 +0200 Subject: util: Infrastructure for computing recent averages This module computes the average of a set of values within a time window, keeping also track of the minimum and maximum values. In order to produce more accurate results it works internally by creating two time windows of the same period, offsetted by half of that period. Values are accounted on both windows and the data is always returned from the oldest one. [Add missing util/replay.o to test-timed-average dependencies to fix the build. --Stefan] Signed-off-by: Alberto Garcia Message-id: 201b09c21bbc9c329779d2b2365ee2b9c80dceeb.1446044837.git.berto@igalia.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/qemu/timed-average.h | 63 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 include/qemu/timed-average.h (limited to 'include') diff --git a/include/qemu/timed-average.h b/include/qemu/timed-average.h new file mode 100644 index 0000000000..f1cdddc48b --- /dev/null +++ b/include/qemu/timed-average.h @@ -0,0 +1,63 @@ +/* + * QEMU timed average computation + * + * Copyright (C) Nodalink, EURL. 2014 + * Copyright (C) Igalia, S.L. 2015 + * + * Authors: + * BenoƮt Canet + * Alberto Garcia + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) version 3 or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef TIMED_AVERAGE_H +#define TIMED_AVERAGE_H + +#include + +#include "qemu/timer.h" + +typedef struct TimedAverageWindow TimedAverageWindow; +typedef struct TimedAverage TimedAverage; + +/* All fields of both structures are private */ + +struct TimedAverageWindow { + uint64_t min; /* minimum value accounted in the window */ + uint64_t max; /* maximum value accounted in the window */ + uint64_t sum; /* sum of all values */ + uint64_t count; /* number of values */ + int64_t expiration; /* the end of the current window in ns */ +}; + +struct TimedAverage { + uint64_t period; /* period in nanoseconds */ + TimedAverageWindow windows[2]; /* two overlapping windows of with + * an offset of period / 2 between them */ + unsigned current; /* the current window index: it's also the + * oldest window index */ + QEMUClockType clock_type; /* the clock used */ +}; + +void timed_average_init(TimedAverage *ta, QEMUClockType clock_type, + uint64_t period); + +void timed_average_account(TimedAverage *ta, uint64_t value); + +uint64_t timed_average_min(TimedAverage *ta); +uint64_t timed_average_avg(TimedAverage *ta); +uint64_t timed_average_max(TimedAverage *ta); + +#endif -- cgit v1.2.3 From cb38fffbc968e797ae32039b1e2c47b940b30cb4 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Wed, 28 Oct 2015 17:33:02 +0200 Subject: block: Add idle_time_ns to BlockDeviceStats This patch adds the new field 'idle_time_ns' to the BlockDeviceStats structure, indicating the time that has passed since the previous I/O operation. It also adds the block_acct_idle_time_ns() call, to ensure that all references to the clock type used for accounting are in the same place. This will later allow us to use a different clock for iotests. Signed-off-by: Alberto Garcia Message-id: 7d8cfcf931453e1a2443e6626e8c1edc347c7c8a.1446044837.git.berto@igalia.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/accounting.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/block/accounting.h b/include/block/accounting.h index 66637cdfed..4b2b999bd0 100644 --- a/include/block/accounting.h +++ b/include/block/accounting.h @@ -40,6 +40,7 @@ typedef struct BlockAcctStats { uint64_t nr_ops[BLOCK_MAX_IOTYPE]; uint64_t total_time_ns[BLOCK_MAX_IOTYPE]; uint64_t merged[BLOCK_MAX_IOTYPE]; + int64_t last_access_time_ns; } BlockAcctStats; typedef struct BlockAcctCookie { @@ -53,5 +54,6 @@ void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie, void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie); void block_acct_merge_done(BlockAcctStats *stats, enum BlockAcctType type, int num_requests); +int64_t block_acct_idle_time_ns(BlockAcctStats *stats); #endif -- cgit v1.2.3 From 7ee12dafe96a86dfa96af38cea1289305e429a55 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Wed, 28 Oct 2015 17:33:03 +0200 Subject: block: Add statistics for failed and invalid I/O operations This patch adds the block_acct_failed() and block_acct_invalid() functions to allow keeping track of failed and invalid I/O operations. The number of failed and invalid operations is exposed in BlockDeviceStats. We don't keep track of the time spent on invalid operations because they are cancelled immediately when they are started. Signed-off-by: Alberto Garcia Message-id: a7256ccb883a86356b1c6c46b5a29ed5448546a5.1446044837.git.berto@igalia.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/accounting.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/block/accounting.h b/include/block/accounting.h index 4b2b999bd0..b50e3cc8d2 100644 --- a/include/block/accounting.h +++ b/include/block/accounting.h @@ -38,6 +38,8 @@ enum BlockAcctType { typedef struct BlockAcctStats { uint64_t nr_bytes[BLOCK_MAX_IOTYPE]; uint64_t nr_ops[BLOCK_MAX_IOTYPE]; + uint64_t invalid_ops[BLOCK_MAX_IOTYPE]; + uint64_t failed_ops[BLOCK_MAX_IOTYPE]; uint64_t total_time_ns[BLOCK_MAX_IOTYPE]; uint64_t merged[BLOCK_MAX_IOTYPE]; int64_t last_access_time_ns; @@ -52,6 +54,8 @@ typedef struct BlockAcctCookie { void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie, int64_t bytes, enum BlockAcctType type); void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie); +void block_acct_failed(BlockAcctStats *stats, BlockAcctCookie *cookie); +void block_acct_invalid(BlockAcctStats *stats, enum BlockAcctType type); void block_acct_merge_done(BlockAcctStats *stats, enum BlockAcctType type, int num_requests); int64_t block_acct_idle_time_ns(BlockAcctStats *stats); -- cgit v1.2.3 From 362e9299b34b3101aaa20f20363441c9f055fa5e Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Wed, 28 Oct 2015 17:33:04 +0200 Subject: block: Allow configuring whether to account failed and invalid ops This patch adds two options, "stats-account-invalid" and "stats-account-failed", that can be used to decide whether invalid and failed I/O operations must be used when collecting statistics for latency and last access time. Signed-off-by: Alberto Garcia Reviewed-by: Stefan Hajnoczi Message-id: ebc7e5966511a342cad428a392c5f5ad56b15213.1446044837.git.berto@igalia.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/accounting.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/block/accounting.h b/include/block/accounting.h index b50e3cc8d2..0d9b076955 100644 --- a/include/block/accounting.h +++ b/include/block/accounting.h @@ -25,6 +25,7 @@ #define BLOCK_ACCOUNTING_H #include +#include #include "qemu/typedefs.h" @@ -43,6 +44,8 @@ typedef struct BlockAcctStats { uint64_t total_time_ns[BLOCK_MAX_IOTYPE]; uint64_t merged[BLOCK_MAX_IOTYPE]; int64_t last_access_time_ns; + bool account_invalid; + bool account_failed; } BlockAcctStats; typedef struct BlockAcctCookie { @@ -51,6 +54,8 @@ typedef struct BlockAcctCookie { enum BlockAcctType type; } BlockAcctCookie; +void block_acct_init(BlockAcctStats *stats, bool account_invalid, + bool account_failed); void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie, int64_t bytes, enum BlockAcctType type); void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie); -- cgit v1.2.3 From 979e9b03fc8c85d3b78a14410c64cbb16d348095 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Wed, 28 Oct 2015 17:33:05 +0200 Subject: block: Compute minimum, maximum and average I/O latencies This patch keeps track of the minimum, maximum and average latencies of I/O operations during a certain interval of time. The values are exposed in the BlockDeviceTimedStats structure. An option to define the intervals to collect these statistics will be added in a separate patch. Signed-off-by: Alberto Garcia Message-id: c7382dc89622c64f918d09f32815827772628f8e.1446044837.git.berto@igalia.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/accounting.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'include') diff --git a/include/block/accounting.h b/include/block/accounting.h index 0d9b076955..1dd582a99a 100644 --- a/include/block/accounting.h +++ b/include/block/accounting.h @@ -28,6 +28,9 @@ #include #include "qemu/typedefs.h" +#include "qemu/timed-average.h" + +typedef struct BlockAcctTimedStats BlockAcctTimedStats; enum BlockAcctType { BLOCK_ACCT_READ, @@ -36,6 +39,12 @@ enum BlockAcctType { BLOCK_MAX_IOTYPE, }; +struct BlockAcctTimedStats { + TimedAverage latency[BLOCK_MAX_IOTYPE]; + unsigned interval_length; /* in seconds */ + QSLIST_ENTRY(BlockAcctTimedStats) entries; +}; + typedef struct BlockAcctStats { uint64_t nr_bytes[BLOCK_MAX_IOTYPE]; uint64_t nr_ops[BLOCK_MAX_IOTYPE]; @@ -44,6 +53,7 @@ typedef struct BlockAcctStats { uint64_t total_time_ns[BLOCK_MAX_IOTYPE]; uint64_t merged[BLOCK_MAX_IOTYPE]; int64_t last_access_time_ns; + QSLIST_HEAD(, BlockAcctTimedStats) intervals; bool account_invalid; bool account_failed; } BlockAcctStats; @@ -56,6 +66,10 @@ typedef struct BlockAcctCookie { void block_acct_init(BlockAcctStats *stats, bool account_invalid, bool account_failed); +void block_acct_cleanup(BlockAcctStats *stats); +void block_acct_add_interval(BlockAcctStats *stats, unsigned interval_length); +BlockAcctTimedStats *block_acct_interval_next(BlockAcctStats *stats, + BlockAcctTimedStats *s); void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie, int64_t bytes, enum BlockAcctType type); void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie); -- cgit v1.2.3 From 96e4dedaff9922f87e4ec351d51d3f093198382a Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Wed, 28 Oct 2015 17:33:06 +0200 Subject: block: Add average I/O queue depth to BlockDeviceTimedStats This patch adds two new fields to BlockDeviceTimedStats that track the average number of pending read and write requests for a block device. The values are calculated for the period of time defined for that interval. Signed-off-by: Alberto Garcia Message-id: fd31fef53e2714f2f30d59ed58ca2f67ec9ab926.1446044837.git.berto@igalia.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/accounting.h | 2 ++ include/qemu/timed-average.h | 1 + 2 files changed, 3 insertions(+) (limited to 'include') diff --git a/include/block/accounting.h b/include/block/accounting.h index 1dd582a99a..482926b8ec 100644 --- a/include/block/accounting.h +++ b/include/block/accounting.h @@ -78,5 +78,7 @@ void block_acct_invalid(BlockAcctStats *stats, enum BlockAcctType type); void block_acct_merge_done(BlockAcctStats *stats, enum BlockAcctType type, int num_requests); int64_t block_acct_idle_time_ns(BlockAcctStats *stats); +double block_acct_queue_depth(BlockAcctTimedStats *stats, + enum BlockAcctType type); #endif diff --git a/include/qemu/timed-average.h b/include/qemu/timed-average.h index f1cdddc48b..364bf88f70 100644 --- a/include/qemu/timed-average.h +++ b/include/qemu/timed-average.h @@ -59,5 +59,6 @@ void timed_average_account(TimedAverage *ta, uint64_t value); uint64_t timed_average_min(TimedAverage *ta); uint64_t timed_average_avg(TimedAverage *ta); uint64_t timed_average_max(TimedAverage *ta); +uint64_t timed_average_sum(TimedAverage *ta, uint64_t *elapsed); #endif -- cgit v1.2.3 From aece5edc96f211eec6febdafc9bbbb99315a2efd Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Wed, 28 Oct 2015 17:33:18 +0200 Subject: block: Update copyright of the accounting code Signed-off-by: Alberto Garcia Message-id: 80a2278e3ec2dafd5daab20a7cb2d6a9b83371e4.1446044838.git.berto@igalia.com Signed-off-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/block/accounting.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/block/accounting.h b/include/block/accounting.h index 482926b8ec..0f46cb4ec1 100644 --- a/include/block/accounting.h +++ b/include/block/accounting.h @@ -2,6 +2,7 @@ * QEMU System Emulator block accounting * * Copyright (c) 2011 Christoph Hellwig + * Copyright (c) 2015 Igalia, S.L. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal -- cgit v1.2.3