On Fri, Oct 03, 2014 at 06:47:42PM +0100, Dr. David Alan Gilbert (git) wrote: > From: "Dr. David Alan Gilbert" <dgilb...@redhat.com> > > On receiving MIG_RPCOMM_REQPAGES look up the address and > queue the page. > > Signed-off-by: Dr. David Alan Gilbert <dgilb...@redhat.com> > --- > arch_init.c | 52 > +++++++++++++++++++++++++++++++++++++++++++ > include/migration/migration.h | 21 +++++++++++++++++ > include/qemu/typedefs.h | 3 ++- > migration.c | 34 +++++++++++++++++++++++++++- > 4 files changed, 108 insertions(+), 2 deletions(-) > > diff --git a/arch_init.c b/arch_init.c > index 4a03171..72f9e17 100644 > --- a/arch_init.c > +++ b/arch_init.c > @@ -660,6 +660,58 @@ static int ram_save_page(QEMUFile *f, RAMBlock* block, > ram_addr_t offset, > } > > /* > + * Queue the pages for transmission, e.g. a request from postcopy destination > + * ms: MigrationStatus in which the queue is held > + * rbname: The RAMBlock the request is for - may be NULL (to mean reuse > last) > + * start: Offset from the start of the RAMBlock > + * len: Length (in bytes) to send > + * Return: 0 on success > + */ > +int ram_save_queue_pages(MigrationState *ms, const char *rbname, > + ram_addr_t start, ram_addr_t len) > +{ > + RAMBlock *ramblock; > + > + if (!rbname) { > + /* Reuse last RAMBlock */ > + ramblock = ms->last_req_rb; > + > + if (!ramblock) { > + error_report("ram_save_queue_pages no previous block"); > + return -1;
This should be an assert() shouldn't it? > + } > + } else { > + ramblock = ram_find_block(rbname); > + > + if (!ramblock) { > + error_report("ram_save_queue_pages no block '%s'", rbname); > + return -1; > + } And maybe this one too - I would have expected the rb names to have already been validated on the source machine at this stage. > + } > + DPRINTF("ram_save_queue_pages: Block %s start %zx len %zx", > + ramblock->idstr, start, len); > + > + if (start+len > ramblock->length) { > + error_report("%s request overrun start=%zx len=%zx blocklen=%zx", > + __func__, start, len, ramblock->length); > + return -1; > + } > + > + struct MigrationSrcPageRequest *new_entry = > + g_malloc0(sizeof(struct MigrationSrcPageRequest)); > + new_entry->rb = ramblock; > + new_entry->offset = start; > + new_entry->len = len; > + ms->last_req_rb = ramblock; > + > + qemu_mutex_lock(&ms->src_page_req_mutex); > + QSIMPLEQ_INSERT_TAIL(&ms->src_page_requests, new_entry, next_req); > + qemu_mutex_unlock(&ms->src_page_req_mutex); > + > + return 0; > +} > + > +/* > * ram_find_and_save_block: Finds a page to send and sends it to f > * > * Returns: The number of bytes written. > diff --git a/include/migration/migration.h b/include/migration/migration.h > index 5e0d30d..5bc01d5 100644 > --- a/include/migration/migration.h > +++ b/include/migration/migration.h > @@ -102,6 +102,18 @@ MigrationIncomingState > *migration_incoming_get_current(void); > MigrationIncomingState *migration_incoming_state_init(QEMUFile *f); > void migration_incoming_state_destroy(void); > > +/* > + * An outstanding page request, on the source, having been received > + * and queued > + */ > +struct MigrationSrcPageRequest { > + RAMBlock *rb; > + hwaddr offset; > + hwaddr len; > + > + QSIMPLEQ_ENTRY(MigrationSrcPageRequest) next_req; > +}; > + > struct MigrationState > { > int64_t bandwidth_limit; > @@ -138,6 +150,12 @@ struct MigrationState > * of the postcopy phase > */ > unsigned long *sentmap; > + > + /* Queue of outstanding page requests from the destination */ > + QemuMutex src_page_req_mutex; > + QSIMPLEQ_HEAD(src_page_requests, MigrationSrcPageRequest) > src_page_requests; > + /* The RAMBlock used in the last src_page_request */ > + RAMBlock *last_req_rb; > }; > > void process_incoming_migration(QEMUFile *f); > @@ -273,4 +291,7 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t > block_offset, > ram_addr_t offset, size_t size, > int *bytes_sent); > > +int ram_save_queue_pages(MigrationState *ms, const char *rbname, > + ram_addr_t start, ram_addr_t len); > + > #endif > diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h > index 79f57c0..24c2207 100644 > --- a/include/qemu/typedefs.h > +++ b/include/qemu/typedefs.h > @@ -8,6 +8,7 @@ typedef struct QEMUTimerListGroup QEMUTimerListGroup; > typedef struct QEMUFile QEMUFile; > typedef struct QEMUBH QEMUBH; > > +typedef struct AdapterInfo AdapterInfo; > typedef struct AioContext AioContext; > > typedef struct Visitor Visitor; > @@ -80,6 +81,6 @@ typedef struct FWCfgState FWCfgState; > typedef struct PcGuestInfo PcGuestInfo; > typedef struct PostcopyPMI PostcopyPMI; > typedef struct Range Range; > -typedef struct AdapterInfo AdapterInfo; > +typedef struct RAMBlock RAMBlock; > > #endif /* QEMU_TYPEDEFS_H */ > diff --git a/migration.c b/migration.c > index cfdaa52..63d7699 100644 > --- a/migration.c > +++ b/migration.c > @@ -26,6 +26,8 @@ > #include "qemu/thread.h" > #include "qmp-commands.h" > #include "trace.h" > +#include "exec/memory.h" > +#include "exec/address-spaces.h" > > //#define DEBUG_MIGRATION > > @@ -504,6 +506,15 @@ static void migrate_fd_cleanup(void *opaque) > > migrate_fd_cleanup_src_rp(s); > > + /* This queue generally should be empty - but in the case of a failed > + * migration might have some droppings in. > + */ > + struct MigrationSrcPageRequest *mspr, *next_mspr; > + QSIMPLEQ_FOREACH_SAFE(mspr, &s->src_page_requests, next_req, next_mspr) { > + QSIMPLEQ_REMOVE_HEAD(&s->src_page_requests, next_req); > + g_free(mspr); > + } > + > if (s->file) { > trace_migrate_fd_cleanup(); > qemu_mutex_unlock_iothread(); > @@ -610,6 +621,9 @@ MigrationState *migrate_init(const MigrationParams > *params) > s->state = MIG_STATE_SETUP; > trace_migrate_set_state(MIG_STATE_SETUP); > > + qemu_mutex_init(&s->src_page_req_mutex); > + QSIMPLEQ_INIT(&s->src_page_requests); > + > s->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); > return s; > } > @@ -823,7 +837,25 @@ static void source_return_path_bad(MigrationState *s) > static void migrate_handle_rp_reqpages(MigrationState *ms, const char* > rbname, > ram_addr_t start, ram_addr_t len) > { > - DPRINTF("migrate_handle_rp_reqpages: at %zx for len %zx", start, len); > + DPRINTF("migrate_handle_rp_reqpages: in %s start %zx len %zx", > + rbname, start, len); > + > + /* Round everything up to our host page size */ > + long our_host_ps = sysconf(_SC_PAGESIZE); > + if (start & (our_host_ps-1)) { > + long roundings = start & (our_host_ps-1); > + start -= roundings; > + len += roundings; > + } > + if (len & (our_host_ps-1)) { > + long roundings = len & (our_host_ps-1); > + len -= roundings; > + len += our_host_ps; > + } > + > + if (ram_save_queue_pages(ms, rbname, start, len)) { > + source_return_path_bad(ms); > + } > } > > /* -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
pgpmjOVB7r_1j.pgp
Description: PGP signature