aboutsummaryrefslogtreecommitdiff
path: root/block/accounting.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2017-06-05 14:39:08 +0200
committerFam Zheng <famz@redhat.com>2017-06-16 07:55:00 +0800
commit5b50bf77ce6e773b04a303a2912876c9a1bfca43 (patch)
treea6b8974b2e58fb9a980c0ed19d0cd58de3f427f7 /block/accounting.c
parent9caa6f3dbe20f2c506df6698386fce941fc6238a (diff)
block: make accounting thread-safe
I'm not trying too hard yet. Later, with multiqueue support, this may cause mutex contention or cacheline bouncing. Cc: Alberto Garcia <berto@igalia.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-Id: <20170605123908.18777-20-pbonzini@redhat.com> Reviewed-by: Alberto Garcia <berto@igalia.com> Signed-off-by: Fam Zheng <famz@redhat.com>
Diffstat (limited to 'block/accounting.c')
-rw-r--r--block/accounting.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/block/accounting.c b/block/accounting.c
index ce6dbf7760..87ef5bbfaa 100644
--- a/block/accounting.c
+++ b/block/accounting.c
@@ -34,6 +34,7 @@ static const int qtest_latency_ns = NANOSECONDS_PER_SECOND / 1000;
void block_acct_init(BlockAcctStats *stats)
{
+ qemu_mutex_init(&stats->lock);
if (qtest_enabled()) {
clock_type = QEMU_CLOCK_VIRTUAL;
}
@@ -52,6 +53,7 @@ void block_acct_cleanup(BlockAcctStats *stats)
QSLIST_FOREACH_SAFE(s, &stats->intervals, entries, next) {
g_free(s);
}
+ qemu_mutex_destroy(&stats->lock);
}
void block_acct_add_interval(BlockAcctStats *stats, unsigned interval_length)
@@ -61,12 +63,15 @@ void block_acct_add_interval(BlockAcctStats *stats, unsigned interval_length)
s = g_new0(BlockAcctTimedStats, 1);
s->interval_length = interval_length;
+ s->stats = stats;
+ qemu_mutex_lock(&stats->lock);
QSLIST_INSERT_HEAD(&stats->intervals, s, entries);
for (i = 0; i < BLOCK_MAX_IOTYPE; i++) {
timed_average_init(&s->latency[i], clock_type,
(uint64_t) interval_length * NANOSECONDS_PER_SECOND);
}
+ qemu_mutex_unlock(&stats->lock);
}
BlockAcctTimedStats *block_acct_interval_next(BlockAcctStats *stats,
@@ -102,6 +107,8 @@ static void block_account_one_io(BlockAcctStats *stats, BlockAcctCookie *cookie,
assert(cookie->type < BLOCK_MAX_IOTYPE);
+ qemu_mutex_lock(&stats->lock);
+
if (failed) {
stats->failed_ops[cookie->type]++;
} else {
@@ -117,6 +124,8 @@ static void block_account_one_io(BlockAcctStats *stats, BlockAcctCookie *cookie,
timed_average_account(&s->latency[cookie->type], latency_ns);
}
}
+
+ qemu_mutex_unlock(&stats->lock);
}
void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie)
@@ -137,18 +146,23 @@ void block_acct_invalid(BlockAcctStats *stats, enum BlockAcctType type)
* not. The reason is that invalid requests are accounted during their
* submission, therefore there's no actual I/O involved.
*/
+ qemu_mutex_lock(&stats->lock);
stats->invalid_ops[type]++;
if (stats->account_invalid) {
stats->last_access_time_ns = qemu_clock_get_ns(clock_type);
}
+ qemu_mutex_unlock(&stats->lock);
}
void block_acct_merge_done(BlockAcctStats *stats, enum BlockAcctType type,
int num_requests)
{
assert(type < BLOCK_MAX_IOTYPE);
+
+ qemu_mutex_lock(&stats->lock);
stats->merged[type] += num_requests;
+ qemu_mutex_unlock(&stats->lock);
}
int64_t block_acct_idle_time_ns(BlockAcctStats *stats)
@@ -163,7 +177,9 @@ double block_acct_queue_depth(BlockAcctTimedStats *stats,
assert(type < BLOCK_MAX_IOTYPE);
+ qemu_mutex_lock(&stats->stats->lock);
sum = timed_average_sum(&stats->latency[type], &elapsed);
+ qemu_mutex_unlock(&stats->stats->lock);
return (double) sum / elapsed;
}