migration: Move rate_limit_max and rate_limit_used to migration_stats
These way we can make them atomic and use this functions from any place. I also moved all functions that use rate_limit to migration-stats. Functions got renamed, they are not qemu_file anymore. qemu_file_rate_limit -> migration_rate_exceeded qemu_file_set_rate_limit -> migration_rate_set qemu_file_get_rate_limit -> migration_rate_get qemu_file_reset_rate_limit -> migration_rate_reset qemu_file_acct_rate_limit -> migration_rate_account. Reviewed-by: Harsh Prateek Bora <harshpb@linux.ibm.com> Signed-off-by: Juan Quintela <quintela@redhat.com> Message-Id: <20230515195709.63843-6-quintela@redhat.com> Signed-off-by: Juan Quintela <quintela@redhat.com>
This commit is contained in:
parent
de37f8b9c2
commit
e1fde0e038
@ -2166,7 +2166,7 @@ static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ((index < htabslots) && !qemu_file_rate_limit(f));
|
} while ((index < htabslots) && !migration_rate_exceeded(f));
|
||||||
|
|
||||||
if (index >= htabslots) {
|
if (index >= htabslots) {
|
||||||
assert(index == htabslots);
|
assert(index == htabslots);
|
||||||
@ -2237,7 +2237,7 @@ static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr,
|
|||||||
assert(index == htabslots);
|
assert(index == htabslots);
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
} while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final));
|
} while ((examined < htabslots) && (!migration_rate_exceeded(f) || final));
|
||||||
|
|
||||||
if (index >= htabslots) {
|
if (index >= htabslots) {
|
||||||
assert(index == htabslots);
|
assert(index == htabslots);
|
||||||
|
@ -209,7 +209,7 @@ static int cmma_save(QEMUFile *f, void *opaque, int final)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (final ? 1 : qemu_file_rate_limit(f) == 0) {
|
while (final ? 1 : migration_rate_exceeded(f) == 0) {
|
||||||
reallen = sac->get_stattr(sas, &start_gfn, buflen, buf);
|
reallen = sac->get_stattr(sas, &start_gfn, buflen, buf);
|
||||||
if (reallen < 0) {
|
if (reallen < 0) {
|
||||||
g_free(buf);
|
g_free(buf);
|
||||||
|
@ -165,6 +165,16 @@ size_t coroutine_mixed_fn qemu_get_counted_string(QEMUFile *f, char buf[256]);
|
|||||||
|
|
||||||
void qemu_put_counted_string(QEMUFile *f, const char *name);
|
void qemu_put_counted_string(QEMUFile *f, const char *name);
|
||||||
|
|
||||||
int qemu_file_rate_limit(QEMUFile *f);
|
/**
|
||||||
|
* migration_rate_exceeded: Check if we have exceeded rate for this interval
|
||||||
|
*
|
||||||
|
* Checks if we have already transferred more data that we are allowed
|
||||||
|
* in the current interval.
|
||||||
|
*
|
||||||
|
* @f: QEMUFile used for main migration channel
|
||||||
|
*
|
||||||
|
* Returns if we should stop sending data for this interval.
|
||||||
|
*/
|
||||||
|
bool migration_rate_exceeded(QEMUFile *f);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -706,7 +706,7 @@ static void bulk_phase(QEMUFile *f, DBMSaveState *s, bool limit)
|
|||||||
QSIMPLEQ_FOREACH(dbms, &s->dbms_list, entry) {
|
QSIMPLEQ_FOREACH(dbms, &s->dbms_list, entry) {
|
||||||
while (!dbms->bulk_completed) {
|
while (!dbms->bulk_completed) {
|
||||||
bulk_phase_send_chunk(f, s, dbms);
|
bulk_phase_send_chunk(f, s, dbms);
|
||||||
if (limit && qemu_file_rate_limit(f)) {
|
if (limit && migration_rate_exceeded(f)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "block/dirty-bitmap.h"
|
#include "block/dirty-bitmap.h"
|
||||||
#include "migration/misc.h"
|
#include "migration/misc.h"
|
||||||
#include "migration.h"
|
#include "migration.h"
|
||||||
|
#include "migration-stats.h"
|
||||||
#include "migration/register.h"
|
#include "migration/register.h"
|
||||||
#include "qemu-file.h"
|
#include "qemu-file.h"
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
@ -625,7 +626,7 @@ static int flush_blks(QEMUFile *f)
|
|||||||
|
|
||||||
blk_mig_lock();
|
blk_mig_lock();
|
||||||
while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
|
while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
|
||||||
if (qemu_file_rate_limit(f)) {
|
if (migration_rate_exceeded(f)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (blk->ret < 0) {
|
if (blk->ret < 0) {
|
||||||
@ -762,7 +763,7 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
|
|||||||
/* control the rate of transfer */
|
/* control the rate of transfer */
|
||||||
blk_mig_lock();
|
blk_mig_lock();
|
||||||
while (block_mig_state.read_done * BLK_MIG_BLOCK_SIZE <
|
while (block_mig_state.read_done * BLK_MIG_BLOCK_SIZE <
|
||||||
qemu_file_get_rate_limit(f) &&
|
migration_rate_get() &&
|
||||||
block_mig_state.submitted < MAX_PARALLEL_IO &&
|
block_mig_state.submitted < MAX_PARALLEL_IO &&
|
||||||
(block_mig_state.submitted + block_mig_state.read_done) <
|
(block_mig_state.submitted + block_mig_state.read_done) <
|
||||||
MAX_IO_BUFFERS) {
|
MAX_IO_BUFFERS) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# Files needed by unit tests
|
# Files needed by unit tests
|
||||||
migration_files = files(
|
migration_files = files(
|
||||||
|
'migration-stats.c',
|
||||||
'page_cache.c',
|
'page_cache.c',
|
||||||
'xbzrle.c',
|
'xbzrle.c',
|
||||||
'vmstate-types.c',
|
'vmstate-types.c',
|
||||||
@ -18,7 +19,6 @@ softmmu_ss.add(files(
|
|||||||
'fd.c',
|
'fd.c',
|
||||||
'global_state.c',
|
'global_state.c',
|
||||||
'migration-hmp-cmds.c',
|
'migration-hmp-cmds.c',
|
||||||
'migration-stats.c',
|
|
||||||
'migration.c',
|
'migration.c',
|
||||||
'multifd.c',
|
'multifd.c',
|
||||||
'multifd-zlib.c',
|
'multifd-zlib.c',
|
||||||
|
@ -12,6 +12,50 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qemu/stats64.h"
|
#include "qemu/stats64.h"
|
||||||
|
#include "qemu-file.h"
|
||||||
#include "migration-stats.h"
|
#include "migration-stats.h"
|
||||||
|
|
||||||
MigrationAtomicStats mig_stats;
|
MigrationAtomicStats mig_stats;
|
||||||
|
|
||||||
|
bool migration_rate_exceeded(QEMUFile *f)
|
||||||
|
{
|
||||||
|
if (qemu_file_get_error(f)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t rate_limit_used = stat64_get(&mig_stats.rate_limit_used);
|
||||||
|
uint64_t rate_limit_max = stat64_get(&mig_stats.rate_limit_max);
|
||||||
|
|
||||||
|
if (rate_limit_max == RATE_LIMIT_DISABLED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rate_limit_max > 0 && rate_limit_used > rate_limit_max) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t migration_rate_get(void)
|
||||||
|
{
|
||||||
|
return stat64_get(&mig_stats.rate_limit_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define XFER_LIMIT_RATIO (1000 / BUFFER_DELAY)
|
||||||
|
|
||||||
|
void migration_rate_set(uint64_t limit)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* 'limit' is per second. But we check it each BUFER_DELAY miliseconds.
|
||||||
|
*/
|
||||||
|
stat64_set(&mig_stats.rate_limit_max, limit / XFER_LIMIT_RATIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void migration_rate_reset(void)
|
||||||
|
{
|
||||||
|
stat64_set(&mig_stats.rate_limit_used, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void migration_rate_account(uint64_t len)
|
||||||
|
{
|
||||||
|
stat64_add(&mig_stats.rate_limit_used, len);
|
||||||
|
}
|
||||||
|
@ -15,6 +15,12 @@
|
|||||||
|
|
||||||
#include "qemu/stats64.h"
|
#include "qemu/stats64.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Amount of time to allocate to each "chunk" of bandwidth-throttled
|
||||||
|
* data.
|
||||||
|
*/
|
||||||
|
#define BUFFER_DELAY 100
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If rate_limit_max is 0, there is special code to remove the rate
|
* If rate_limit_max is 0, there is special code to remove the rate
|
||||||
* limit.
|
* limit.
|
||||||
@ -75,6 +81,14 @@ typedef struct {
|
|||||||
* Number of bytes sent during precopy stage.
|
* Number of bytes sent during precopy stage.
|
||||||
*/
|
*/
|
||||||
Stat64 precopy_bytes;
|
Stat64 precopy_bytes;
|
||||||
|
/*
|
||||||
|
* Maximum amount of data we can send in a cycle.
|
||||||
|
*/
|
||||||
|
Stat64 rate_limit_max;
|
||||||
|
/*
|
||||||
|
* Amount of data we have sent in the current cycle.
|
||||||
|
*/
|
||||||
|
Stat64 rate_limit_used;
|
||||||
/*
|
/*
|
||||||
* Total number of bytes transferred.
|
* Total number of bytes transferred.
|
||||||
*/
|
*/
|
||||||
@ -87,4 +101,36 @@ typedef struct {
|
|||||||
|
|
||||||
extern MigrationAtomicStats mig_stats;
|
extern MigrationAtomicStats mig_stats;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* migration_rate_account: Increase the number of bytes transferred.
|
||||||
|
*
|
||||||
|
* Report on a number of bytes the have been transferred that need to
|
||||||
|
* be applied to the rate limiting calcuations.
|
||||||
|
*
|
||||||
|
* @len: amount of bytes transferred
|
||||||
|
*/
|
||||||
|
void migration_rate_account(uint64_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* migration_rate_get: Get the maximum amount that can be transferred.
|
||||||
|
*
|
||||||
|
* Returns the maximum number of bytes that can be transferred in a cycle.
|
||||||
|
*/
|
||||||
|
uint64_t migration_rate_get(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* migration_rate_reset: Reset the rate limit counter.
|
||||||
|
*
|
||||||
|
* This is called when we know we start a new transfer cycle.
|
||||||
|
*/
|
||||||
|
void migration_rate_reset(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* migration_rate_set: Set the maximum amount that can be transferred.
|
||||||
|
*
|
||||||
|
* Sets the maximum amount of bytes that can be transferred in one cycle.
|
||||||
|
*
|
||||||
|
* @new_rate: new maximum amount
|
||||||
|
*/
|
||||||
|
void migration_rate_set(uint64_t new_rate);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2120,7 +2120,7 @@ static int postcopy_start(MigrationState *ms)
|
|||||||
* will notice we're in POSTCOPY_ACTIVE and not actually
|
* will notice we're in POSTCOPY_ACTIVE and not actually
|
||||||
* wrap their state up here
|
* wrap their state up here
|
||||||
*/
|
*/
|
||||||
qemu_file_set_rate_limit(ms->to_dst_file, bandwidth);
|
migration_rate_set(bandwidth);
|
||||||
if (migrate_postcopy_ram()) {
|
if (migrate_postcopy_ram()) {
|
||||||
/* Ping just for debugging, helps line traces up */
|
/* Ping just for debugging, helps line traces up */
|
||||||
qemu_savevm_send_ping(ms->to_dst_file, 2);
|
qemu_savevm_send_ping(ms->to_dst_file, 2);
|
||||||
@ -2304,7 +2304,7 @@ static void migration_completion(MigrationState *s)
|
|||||||
* them if migration fails or is cancelled.
|
* them if migration fails or is cancelled.
|
||||||
*/
|
*/
|
||||||
s->block_inactive = !migrate_colo();
|
s->block_inactive = !migrate_colo();
|
||||||
qemu_file_set_rate_limit(s->to_dst_file, RATE_LIMIT_DISABLED);
|
migration_rate_set(RATE_LIMIT_DISABLED);
|
||||||
ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false,
|
ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false,
|
||||||
s->block_inactive);
|
s->block_inactive);
|
||||||
}
|
}
|
||||||
@ -2699,7 +2699,7 @@ static void migration_update_counters(MigrationState *s,
|
|||||||
stat64_get(&mig_stats.dirty_bytes_last_sync) / bandwidth;
|
stat64_get(&mig_stats.dirty_bytes_last_sync) / bandwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_file_reset_rate_limit(s->to_dst_file);
|
migration_rate_reset();
|
||||||
|
|
||||||
update_iteration_initial_status(s);
|
update_iteration_initial_status(s);
|
||||||
|
|
||||||
@ -2852,7 +2852,7 @@ bool migration_rate_limit(void)
|
|||||||
|
|
||||||
bool urgent = false;
|
bool urgent = false;
|
||||||
migration_update_counters(s, now);
|
migration_update_counters(s, now);
|
||||||
if (qemu_file_rate_limit(s->to_dst_file)) {
|
if (migration_rate_exceeded(s->to_dst_file)) {
|
||||||
|
|
||||||
if (qemu_file_get_error(s->to_dst_file)) {
|
if (qemu_file_get_error(s->to_dst_file)) {
|
||||||
return false;
|
return false;
|
||||||
@ -2974,7 +2974,7 @@ static void *migration_thread(void *opaque)
|
|||||||
trace_migration_thread_setup_complete();
|
trace_migration_thread_setup_complete();
|
||||||
|
|
||||||
while (migration_is_active(s)) {
|
while (migration_is_active(s)) {
|
||||||
if (urgent || !qemu_file_rate_limit(s->to_dst_file)) {
|
if (urgent || !migration_rate_exceeded(s->to_dst_file)) {
|
||||||
MigIterateState iter_state = migration_iteration_run(s);
|
MigIterateState iter_state = migration_iteration_run(s);
|
||||||
if (iter_state == MIG_ITERATE_SKIP) {
|
if (iter_state == MIG_ITERATE_SKIP) {
|
||||||
continue;
|
continue;
|
||||||
@ -3048,7 +3048,7 @@ static void *bg_migration_thread(void *opaque)
|
|||||||
rcu_register_thread();
|
rcu_register_thread();
|
||||||
object_ref(OBJECT(s));
|
object_ref(OBJECT(s));
|
||||||
|
|
||||||
qemu_file_set_rate_limit(s->to_dst_file, RATE_LIMIT_DISABLED);
|
migration_rate_set(RATE_LIMIT_DISABLED);
|
||||||
|
|
||||||
setup_start = qemu_clock_get_ms(QEMU_CLOCK_HOST);
|
setup_start = qemu_clock_get_ms(QEMU_CLOCK_HOST);
|
||||||
/*
|
/*
|
||||||
@ -3220,7 +3220,7 @@ void migrate_fd_connect(MigrationState *s, Error *error_in)
|
|||||||
notifier_list_notify(&migration_state_notifiers, s);
|
notifier_list_notify(&migration_state_notifiers, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_file_set_rate_limit(s->to_dst_file, rate_limit);
|
migration_rate_set(rate_limit);
|
||||||
qemu_file_set_blocking(s->to_dst_file, true);
|
qemu_file_set_blocking(s->to_dst_file, true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -431,7 +431,7 @@ static int multifd_send_pages(QEMUFile *f)
|
|||||||
multifd_send_state->pages = p->pages;
|
multifd_send_state->pages = p->pages;
|
||||||
p->pages = pages;
|
p->pages = pages;
|
||||||
transferred = ((uint64_t) pages->num) * p->page_size + p->packet_len;
|
transferred = ((uint64_t) pages->num) * p->page_size + p->packet_len;
|
||||||
qemu_file_acct_rate_limit(f, transferred);
|
migration_rate_account(transferred);
|
||||||
qemu_mutex_unlock(&p->mutex);
|
qemu_mutex_unlock(&p->mutex);
|
||||||
stat64_add(&mig_stats.transferred, transferred);
|
stat64_add(&mig_stats.transferred, transferred);
|
||||||
stat64_add(&mig_stats.multifd_bytes, transferred);
|
stat64_add(&mig_stats.multifd_bytes, transferred);
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "migration/colo.h"
|
#include "migration/colo.h"
|
||||||
#include "migration/misc.h"
|
#include "migration/misc.h"
|
||||||
#include "migration.h"
|
#include "migration.h"
|
||||||
|
#include "migration-stats.h"
|
||||||
#include "qemu-file.h"
|
#include "qemu-file.h"
|
||||||
#include "ram.h"
|
#include "ram.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
@ -1242,8 +1243,7 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
|
|||||||
if (params->has_max_bandwidth) {
|
if (params->has_max_bandwidth) {
|
||||||
s->parameters.max_bandwidth = params->max_bandwidth;
|
s->parameters.max_bandwidth = params->max_bandwidth;
|
||||||
if (s->to_dst_file && !migration_in_postcopy()) {
|
if (s->to_dst_file && !migration_in_postcopy()) {
|
||||||
qemu_file_set_rate_limit(s->to_dst_file,
|
migration_rate_set(s->parameters.max_bandwidth);
|
||||||
s->parameters.max_bandwidth);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1272,8 +1272,7 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
|
|||||||
if (params->has_max_postcopy_bandwidth) {
|
if (params->has_max_postcopy_bandwidth) {
|
||||||
s->parameters.max_postcopy_bandwidth = params->max_postcopy_bandwidth;
|
s->parameters.max_postcopy_bandwidth = params->max_postcopy_bandwidth;
|
||||||
if (s->to_dst_file && migration_in_postcopy()) {
|
if (s->to_dst_file && migration_in_postcopy()) {
|
||||||
qemu_file_set_rate_limit(s->to_dst_file,
|
migration_rate_set(s->parameters.max_postcopy_bandwidth);
|
||||||
s->parameters.max_postcopy_bandwidth);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (params->has_max_cpu_throttle) {
|
if (params->has_max_cpu_throttle) {
|
||||||
|
@ -17,13 +17,6 @@
|
|||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
#include "hw/qdev-properties-system.h"
|
#include "hw/qdev-properties-system.h"
|
||||||
|
|
||||||
/* constants */
|
|
||||||
|
|
||||||
/* Amount of time to allocate to each "chunk" of bandwidth-throttled
|
|
||||||
* data. */
|
|
||||||
#define BUFFER_DELAY 100
|
|
||||||
#define XFER_LIMIT_RATIO (1000 / BUFFER_DELAY)
|
|
||||||
|
|
||||||
/* migration properties */
|
/* migration properties */
|
||||||
|
|
||||||
extern Property migration_properties[];
|
extern Property migration_properties[];
|
||||||
|
@ -41,17 +41,6 @@ struct QEMUFile {
|
|||||||
QIOChannel *ioc;
|
QIOChannel *ioc;
|
||||||
bool is_writable;
|
bool is_writable;
|
||||||
|
|
||||||
/*
|
|
||||||
* Maximum amount of data in bytes to transfer during one
|
|
||||||
* rate limiting time window
|
|
||||||
*/
|
|
||||||
uint64_t rate_limit_max;
|
|
||||||
/*
|
|
||||||
* Total amount of data in bytes queued for transfer
|
|
||||||
* during this rate limiting time window
|
|
||||||
*/
|
|
||||||
uint64_t rate_limit_used;
|
|
||||||
|
|
||||||
/* The sum of bytes transferred on the wire */
|
/* The sum of bytes transferred on the wire */
|
||||||
uint64_t total_transferred;
|
uint64_t total_transferred;
|
||||||
|
|
||||||
@ -303,7 +292,7 @@ void qemu_fflush(QEMUFile *f)
|
|||||||
qemu_file_set_error_obj(f, -EIO, local_error);
|
qemu_file_set_error_obj(f, -EIO, local_error);
|
||||||
} else {
|
} else {
|
||||||
uint64_t size = iov_size(f->iov, f->iovcnt);
|
uint64_t size = iov_size(f->iov, f->iovcnt);
|
||||||
qemu_file_acct_rate_limit(f, size);
|
migration_rate_account(size);
|
||||||
f->total_transferred += size;
|
f->total_transferred += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +345,7 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
|
|||||||
int ret = f->hooks->save_page(f, block_offset,
|
int ret = f->hooks->save_page(f, block_offset,
|
||||||
offset, size, bytes_sent);
|
offset, size, bytes_sent);
|
||||||
if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
|
if (ret != RAM_SAVE_CONTROL_NOT_SUPP) {
|
||||||
qemu_file_acct_rate_limit(f, size);
|
migration_rate_account(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != RAM_SAVE_CONTROL_DELAYED &&
|
if (ret != RAM_SAVE_CONTROL_DELAYED &&
|
||||||
@ -727,43 +716,6 @@ uint64_t qemu_file_transferred(QEMUFile *f)
|
|||||||
return f->total_transferred;
|
return f->total_transferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemu_file_rate_limit(QEMUFile *f)
|
|
||||||
{
|
|
||||||
if (qemu_file_get_error(f)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (f->rate_limit_max == RATE_LIMIT_DISABLED) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (f->rate_limit_used > f->rate_limit_max) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t qemu_file_get_rate_limit(QEMUFile *f)
|
|
||||||
{
|
|
||||||
return f->rate_limit_max;
|
|
||||||
}
|
|
||||||
|
|
||||||
void qemu_file_set_rate_limit(QEMUFile *f, uint64_t limit)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* 'limit' is per second. But we check it each 100 miliseconds.
|
|
||||||
*/
|
|
||||||
f->rate_limit_max = limit / XFER_LIMIT_RATIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
void qemu_file_reset_rate_limit(QEMUFile *f)
|
|
||||||
{
|
|
||||||
f->rate_limit_used = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void qemu_file_acct_rate_limit(QEMUFile *f, uint64_t len)
|
|
||||||
{
|
|
||||||
f->rate_limit_used += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void qemu_put_be16(QEMUFile *f, unsigned int v)
|
void qemu_put_be16(QEMUFile *f, unsigned int v)
|
||||||
{
|
{
|
||||||
qemu_put_byte(f, v >> 8);
|
qemu_put_byte(f, v >> 8);
|
||||||
|
@ -130,17 +130,6 @@ void qemu_file_skip(QEMUFile *f, int size);
|
|||||||
* accounting information tracks the total migration traffic.
|
* accounting information tracks the total migration traffic.
|
||||||
*/
|
*/
|
||||||
void qemu_file_credit_transfer(QEMUFile *f, size_t size);
|
void qemu_file_credit_transfer(QEMUFile *f, size_t size);
|
||||||
void qemu_file_reset_rate_limit(QEMUFile *f);
|
|
||||||
/*
|
|
||||||
* qemu_file_acct_rate_limit:
|
|
||||||
*
|
|
||||||
* Report on a number of bytes the have been transferred
|
|
||||||
* out of band from the main file object I/O methods, and
|
|
||||||
* need to be applied to the rate limiting calcuations
|
|
||||||
*/
|
|
||||||
void qemu_file_acct_rate_limit(QEMUFile *f, uint64_t len);
|
|
||||||
void qemu_file_set_rate_limit(QEMUFile *f, uint64_t new_rate);
|
|
||||||
uint64_t qemu_file_get_rate_limit(QEMUFile *f);
|
|
||||||
int qemu_file_get_error_obj(QEMUFile *f, Error **errp);
|
int qemu_file_get_error_obj(QEMUFile *f, Error **errp);
|
||||||
int qemu_file_get_error_obj_any(QEMUFile *f1, QEMUFile *f2, Error **errp);
|
int qemu_file_get_error_obj_any(QEMUFile *f1, QEMUFile *f2, Error **errp);
|
||||||
void qemu_file_set_error_obj(QEMUFile *f, int ret, Error *err);
|
void qemu_file_set_error_obj(QEMUFile *f, int ret, Error *err);
|
||||||
|
@ -3116,7 +3116,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
|
|||||||
|
|
||||||
t0 = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
t0 = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
|
||||||
i = 0;
|
i = 0;
|
||||||
while ((ret = qemu_file_rate_limit(f)) == 0 ||
|
while ((ret = migration_rate_exceeded(f)) == 0 ||
|
||||||
postcopy_has_request(rs)) {
|
postcopy_has_request(rs)) {
|
||||||
int pages;
|
int pages;
|
||||||
|
|
||||||
|
@ -1338,7 +1338,7 @@ int qemu_savevm_state_iterate(QEMUFile *f, bool postcopy)
|
|||||||
!(se->ops->has_postcopy && se->ops->has_postcopy(se->opaque))) {
|
!(se->ops->has_postcopy && se->ops->has_postcopy(se->opaque))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (qemu_file_rate_limit(f)) {
|
if (migration_rate_exceeded(f)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
trace_savevm_section_start(se->idstr, se->section_id);
|
trace_savevm_section_start(se->idstr, se->section_id);
|
||||||
|
Loading…
Reference in New Issue
Block a user