From 715c54071a43ab978dc12b9da22a5016203ed284 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 9 Feb 2016 09:28:58 +1000 Subject: [PATCH] pseries: Simplify handling of the hash page table fd When migrating the 'pseries' machine type with KVM, we use a special fd to access the hash page table stored within KVM. Usually, this fd is opened at the beginning of migration, and kept open until the migration is complete. However, if there is a guest reset during the migration, the fd can become stale and we need to re-open it. At the moment we use an 'htab_fd_stale' flag in sPAPRMachineState to signal this, which is checked in the migration iterators. But that's rather ugly. It's simpler to just close and invalidate the fd on reset, and lazily re-open it in migration if necessary. This patch implements that change. This requires a small addition to the machine state's instance_init, so that htab_fd is initialized to -1 (telling the migration code it needs to open it) instead of 0, which could be a valid fd. Signed-off-by: David Gibson Reviewed-by: Alexey Kardashevskiy --- hw/ppc/spapr.c | 86 ++++++++++++++++++++++++-------------------------- include/hw/ppc/spapr.h | 1 - 2 files changed, 41 insertions(+), 46 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 5bd8fd3ef8..c3157154e0 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1024,6 +1024,32 @@ static void emulate_spapr_hypercall(PowerPCCPU *cpu) #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) +/* + * Get the fd to access the kernel htab, re-opening it if necessary + */ +static int get_htab_fd(sPAPRMachineState *spapr) +{ + if (spapr->htab_fd >= 0) { + return spapr->htab_fd; + } + + spapr->htab_fd = kvmppc_get_htab_fd(false); + if (spapr->htab_fd < 0) { + error_report("Unable to open fd for reading hash table from KVM: %s", + strerror(errno)); + } + + return spapr->htab_fd; +} + +static void close_htab_fd(sPAPRMachineState *spapr) +{ + if (spapr->htab_fd >= 0) { + close(spapr->htab_fd); + } + spapr->htab_fd = -1; +} + static void spapr_alloc_htab(sPAPRMachineState *spapr) { long shift; @@ -1085,10 +1111,7 @@ static void spapr_reset_htab(sPAPRMachineState *spapr) error_setg(&error_abort, "Requested HTAB allocation failed during reset"); } - /* Tell readers to update their file descriptor */ - if (spapr->htab_fd >= 0) { - spapr->htab_fd_stale = true; - } + close_htab_fd(spapr); } else { memset(spapr->htab, 0, HTAB_SIZE(spapr)); @@ -1121,28 +1144,6 @@ static int find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque) return 0; } -/* - * A guest reset will cause spapr->htab_fd to become stale if being used. - * Reopen the file descriptor to make sure the whole HTAB is properly read. - */ -static int spapr_check_htab_fd(sPAPRMachineState *spapr) -{ - int rc = 0; - - if (spapr->htab_fd_stale) { - close(spapr->htab_fd); - spapr->htab_fd = kvmppc_get_htab_fd(false); - if (spapr->htab_fd < 0) { - error_report("Unable to open fd for reading hash table from KVM: " - "%s", strerror(errno)); - rc = -1; - } - spapr->htab_fd_stale = false; - } - - return rc; -} - static void ppc_spapr_reset(void) { sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); @@ -1313,14 +1314,6 @@ static int htab_save_setup(QEMUFile *f, void *opaque) spapr->htab_first_pass = true; } else { assert(kvm_enabled()); - - spapr->htab_fd = kvmppc_get_htab_fd(false); - spapr->htab_fd_stale = false; - if (spapr->htab_fd < 0) { - fprintf(stderr, "Unable to open fd for reading hash table from KVM: %s\n", - strerror(errno)); - return -1; - } } @@ -1460,6 +1453,7 @@ static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr, static int htab_save_iterate(QEMUFile *f, void *opaque) { sPAPRMachineState *spapr = opaque; + int fd; int rc = 0; /* Iteration header */ @@ -1468,13 +1462,12 @@ static int htab_save_iterate(QEMUFile *f, void *opaque) if (!spapr->htab) { assert(kvm_enabled()); - rc = spapr_check_htab_fd(spapr); - if (rc < 0) { - return rc; + fd = get_htab_fd(spapr); + if (fd < 0) { + return fd; } - rc = kvmppc_save_htab(f, spapr->htab_fd, - MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); + rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); if (rc < 0) { return rc; } @@ -1495,6 +1488,7 @@ static int htab_save_iterate(QEMUFile *f, void *opaque) static int htab_save_complete(QEMUFile *f, void *opaque) { sPAPRMachineState *spapr = opaque; + int fd; /* Iteration header */ qemu_put_be32(f, 0); @@ -1504,17 +1498,16 @@ static int htab_save_complete(QEMUFile *f, void *opaque) assert(kvm_enabled()); - rc = spapr_check_htab_fd(spapr); - if (rc < 0) { - return rc; + fd = get_htab_fd(spapr); + if (fd < 0) { + return fd; } - rc = kvmppc_save_htab(f, spapr->htab_fd, MAX_KVM_BUF_SIZE, -1); + rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); if (rc < 0) { return rc; } - close(spapr->htab_fd); - spapr->htab_fd = -1; + close_htab_fd(spapr); } else { htab_save_later_pass(f, spapr, -1); } @@ -2125,6 +2118,9 @@ static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) static void spapr_machine_initfn(Object *obj) { + sPAPRMachineState *spapr = SPAPR_MACHINE(obj); + + spapr->htab_fd = -1; object_property_add_str(obj, "kvm-type", spapr_get_kvm_type, spapr_set_kvm_type, NULL); object_property_set_description(obj, "kvm-type", diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 1f9e722545..098d85d1a1 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -72,7 +72,6 @@ struct sPAPRMachineState { int htab_save_index; bool htab_first_pass; int htab_fd; - bool htab_fd_stale; /* RTAS state */ QTAILQ_HEAD(, sPAPRConfigureConnectorState) ccs_list; -- 2.11.0