cryptospore / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone
a83cc2
From 05efd4675b1241f2cc68fd54c92a8a834699f212 Mon Sep 17 00:00:00 2001
a83cc2
From: "plai@redhat.com" <plai@redhat.com>
a83cc2
Date: Thu, 29 Jul 2021 07:42:21 -0400
a83cc2
Subject: [PATCH 14/39] ratelimit: protect with a mutex
a83cc2
a83cc2
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
a83cc2
RH-MergeRequest: 32: Synchronize with RHEL-AV 8.5 release 27 to RHEL 9
a83cc2
RH-Commit: [6/15] 48586bf5d422cb676a6f2d2cd0abb0822cfc17b2 (mrezanin/centos-src-qemu-kvm)
a83cc2
RH-Bugzilla: 1957194
a83cc2
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
a83cc2
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
a83cc2
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
a83cc2
RH-Acked-by: Andrew Jones <drjones@redhat.com>
a83cc2
a83cc2
Right now, rate limiting is protected by the AioContext mutex, which is
a83cc2
taken for example both by the block jobs and by qmp_block_job_set_speed
a83cc2
(via find_block_job).
a83cc2
a83cc2
We would like to remove the dependency of block layer code on the
a83cc2
AioContext mutex, since most drivers and the core I/O code are already
a83cc2
not relying on it.  However, there is no existing lock that can easily
a83cc2
be taken by both ratelimit_set_speed and ratelimit_calculate_delay,
a83cc2
especially because the latter might run in coroutine context (and
a83cc2
therefore under a CoMutex) but the former will not.
a83cc2
a83cc2
Since concurrent calls to ratelimit_calculate_delay are not possible,
a83cc2
one idea could be to use a seqlock to get a snapshot of slice_ns and
a83cc2
slice_quota.  But for now keep it simple, and just add a mutex to the
a83cc2
RateLimit struct; block jobs are generally not performance critical to
a83cc2
the point of optimizing the clock cycles spent in synchronization.
a83cc2
a83cc2
This also requires the introduction of init/destroy functions, so
a83cc2
add them to the two users of ratelimit.h.
a83cc2
a83cc2
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
a83cc2
(cherry picked from commit 4951967d84a0acbf47895add9158e2d4c6056ea0)
a83cc2
Signed-off-by: Paul Lai <plai@redhat.com>
a83cc2
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
a83cc2
---
a83cc2
 block/block-copy.c       |  2 ++
a83cc2
 blockjob.c               |  3 +++
a83cc2
 include/qemu/ratelimit.h | 14 ++++++++++++++
a83cc2
 3 files changed, 19 insertions(+)
a83cc2
a83cc2
diff --git a/block/block-copy.c b/block/block-copy.c
a83cc2
index 39ae481c8b..9b4af00614 100644
a83cc2
--- a/block/block-copy.c
a83cc2
+++ b/block/block-copy.c
a83cc2
@@ -230,6 +230,7 @@ void block_copy_state_free(BlockCopyState *s)
a83cc2
         return;
a83cc2
     }
a83cc2
 
a83cc2
+    ratelimit_destroy(&s->rate_limit);
a83cc2
     bdrv_release_dirty_bitmap(s->copy_bitmap);
a83cc2
     shres_destroy(s->mem);
a83cc2
     g_free(s);
a83cc2
@@ -289,6 +290,7 @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
a83cc2
         s->copy_size = MAX(s->cluster_size, BLOCK_COPY_MAX_BUFFER);
a83cc2
     }
a83cc2
 
a83cc2
+    ratelimit_init(&s->rate_limit);
a83cc2
     QLIST_INIT(&s->tasks);
a83cc2
     QLIST_INIT(&s->calls);
a83cc2
 
a83cc2
diff --git a/blockjob.c b/blockjob.c
a83cc2
index 207e8c7fd9..46f15befe8 100644
a83cc2
--- a/blockjob.c
a83cc2
+++ b/blockjob.c
a83cc2
@@ -87,6 +87,7 @@ void block_job_free(Job *job)
a83cc2
 
a83cc2
     block_job_remove_all_bdrv(bjob);
a83cc2
     blk_unref(bjob->blk);
a83cc2
+    ratelimit_destroy(&bjob->limit);
a83cc2
     error_free(bjob->blocker);
a83cc2
 }
a83cc2
 
a83cc2
@@ -435,6 +436,8 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
a83cc2
     assert(job->job.driver->free == &block_job_free);
a83cc2
     assert(job->job.driver->user_resume == &block_job_user_resume);
a83cc2
 
a83cc2
+    ratelimit_init(&job->limit);
a83cc2
+
a83cc2
     job->blk = blk;
a83cc2
 
a83cc2
     job->finalize_cancelled_notifier.notify = block_job_event_cancelled;
a83cc2
diff --git a/include/qemu/ratelimit.h b/include/qemu/ratelimit.h
a83cc2
index 01da8d63f1..003ea6d5a3 100644
a83cc2
--- a/include/qemu/ratelimit.h
a83cc2
+++ b/include/qemu/ratelimit.h
a83cc2
@@ -14,9 +14,11 @@
a83cc2
 #ifndef QEMU_RATELIMIT_H
a83cc2
 #define QEMU_RATELIMIT_H
a83cc2
 
a83cc2
+#include "qemu/lockable.h"
a83cc2
 #include "qemu/timer.h"
a83cc2
 
a83cc2
 typedef struct {
a83cc2
+    QemuMutex lock;
a83cc2
     int64_t slice_start_time;
a83cc2
     int64_t slice_end_time;
a83cc2
     uint64_t slice_quota;
a83cc2
@@ -40,6 +42,7 @@ static inline int64_t ratelimit_calculate_delay(RateLimit *limit, uint64_t n)
a83cc2
     int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
a83cc2
     double delay_slices;
a83cc2
 
a83cc2
+    QEMU_LOCK_GUARD(&limit->lock);
a83cc2
     assert(limit->slice_quota && limit->slice_ns);
a83cc2
 
a83cc2
     if (limit->slice_end_time < now) {
a83cc2
@@ -65,9 +68,20 @@ static inline int64_t ratelimit_calculate_delay(RateLimit *limit, uint64_t n)
a83cc2
     return limit->slice_end_time - now;
a83cc2
 }
a83cc2
 
a83cc2
+static inline void ratelimit_init(RateLimit *limit)
a83cc2
+{
a83cc2
+    qemu_mutex_init(&limit->lock);
a83cc2
+}
a83cc2
+
a83cc2
+static inline void ratelimit_destroy(RateLimit *limit)
a83cc2
+{
a83cc2
+    qemu_mutex_destroy(&limit->lock);
a83cc2
+}
a83cc2
+
a83cc2
 static inline void ratelimit_set_speed(RateLimit *limit, uint64_t speed,
a83cc2
                                        uint64_t slice_ns)
a83cc2
 {
a83cc2
+    QEMU_LOCK_GUARD(&limit->lock);
a83cc2
     limit->slice_ns = slice_ns;
a83cc2
     limit->slice_quota = MAX(((double)speed * slice_ns) / 1000000000ULL, 1);
a83cc2
 }
a83cc2
-- 
a83cc2
2.27.0
a83cc2