From: Anthony Liguori Date: Tue, 15 Jan 2013 22:52:39 +0000 (-0600) Subject: Merge remote-tracking branch 'afaerber/qom-cpu' into staging X-Git-Tag: v1.4.0-rc0~181 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=c94bf1c107df6623e54d48b90fb439a1281a36de;hp=e175bce587936bf479889881488821ea8d61c89c;p=qemu.git Merge remote-tracking branch 'afaerber/qom-cpu' into staging * afaerber/qom-cpu: target-i386: Use switch in check_hw_breakpoints() target-i386: Avoid goto in hw_breakpoint_insert() target-i386: Introduce hw_{local,global}_breakpoint_enabled() target-i386: Define DR7 bit field constants target-i386: Move kvm_check_features_against_host() check to realize time target-i386: cpu_x86_register() consolidate freeing resources target-i386: Move setting defaults out of cpu_x86_parse_featurestr() target-i386: check/enforce: Check all feature words target-i386/cpu.c: Add feature name array for ext4_features target-i386: kvm_check_features_against_host(): Use feature_word_info target-i386/cpu: Introduce FeatureWord typedefs target-i386: Disable kvm_mmu by default kvm: Add fake KVM constants to avoid #ifdefs on KVM-specific code exec: Return CPUState from qemu_get_cpu() xen: Simplify halting of first CPU kvm: Pass CPUState to kvm_init_vcpu() cpu: Move cpu_index field to CPUState cpu: Move numa_node field to CPUState target-mips: Clean up mips_cpu_map_tc() documentation cpu: Move nr_{cores,threads} fields to CPUState Signed-off-by: Anthony Liguori --- diff --git a/hw/pc87312.c b/hw/pc87312.c index 6a17afd45..38af4c1d1 100644 --- a/hw/pc87312.c +++ b/hw/pc87312.c @@ -34,10 +34,6 @@ #define REG_FAR 1 #define REG_PTR 2 -#define FER regs[REG_FER] -#define FAR regs[REG_FAR] -#define PTR regs[REG_PTR] - #define FER_PARALLEL_EN 0x01 #define FER_UART1_EN 0x02 #define FER_UART2_EN 0x04 @@ -66,14 +62,14 @@ static inline bool is_parallel_enabled(PC87312State *s) { - return s->FER & FER_PARALLEL_EN; + return s->regs[REG_FER] & FER_PARALLEL_EN; } static const uint32_t parallel_base[] = { 0x378, 0x3bc, 0x278, 0x00 }; static inline uint32_t get_parallel_iobase(PC87312State *s) { - return parallel_base[s->FAR & FAR_PARALLEL_ADDR]; + return parallel_base[s->regs[REG_FAR] & FAR_PARALLEL_ADDR]; } static const uint32_t parallel_irq[] = { 5, 7, 5, 0 }; @@ -81,9 +77,9 @@ static const uint32_t parallel_irq[] = { 5, 7, 5, 0 }; static inline uint32_t get_parallel_irq(PC87312State *s) { int idx; - idx = (s->FAR & FAR_PARALLEL_ADDR); + idx = (s->regs[REG_FAR] & FAR_PARALLEL_ADDR); if (idx == 0) { - return (s->PTR & PTR_IRQ_5_7) ? 7 : 5; + return (s->regs[REG_PTR] & PTR_IRQ_5_7) ? 7 : 5; } else { return parallel_irq[idx]; } @@ -91,7 +87,7 @@ static inline uint32_t get_parallel_irq(PC87312State *s) static inline bool is_parallel_epp(PC87312State *s) { - return s->PTR & PTR_EPP_MODE; + return s->regs[REG_PTR] & PTR_EPP_MODE; } @@ -105,26 +101,26 @@ static const uint32_t uart_base[2][4] = { static inline uint32_t get_uart_iobase(PC87312State *s, int i) { int idx; - idx = (s->FAR >> (2 * i + 2)) & 0x3; + idx = (s->regs[REG_FAR] >> (2 * i + 2)) & 0x3; if (idx == 0) { return 0x3f8; } else if (idx == 1) { return 0x2f8; } else { - return uart_base[idx & 1][(s->FAR & FAR_UART_3_4) >> 6]; + return uart_base[idx & 1][(s->regs[REG_FAR] & FAR_UART_3_4) >> 6]; } } static inline uint32_t get_uart_irq(PC87312State *s, int i) { int idx; - idx = (s->FAR >> (2 * i + 2)) & 0x3; + idx = (s->regs[REG_FAR] >> (2 * i + 2)) & 0x3; return (idx & 1) ? 3 : 4; } static inline bool is_uart_enabled(PC87312State *s, int i) { - return s->FER & (FER_UART1_EN << i); + return s->regs[REG_FER] & (FER_UART1_EN << i); } @@ -132,12 +128,12 @@ static inline bool is_uart_enabled(PC87312State *s, int i) static inline bool is_fdc_enabled(PC87312State *s) { - return s->FER & FER_FDC_EN; + return s->regs[REG_FER] & FER_FDC_EN; } static inline uint32_t get_fdc_iobase(PC87312State *s) { - return (s->FER & FER_FDC_ADDR) ? 0x370 : 0x3f0; + return (s->regs[REG_FER] & FER_FDC_ADDR) ? 0x370 : 0x3f0; } @@ -145,19 +141,19 @@ static inline uint32_t get_fdc_iobase(PC87312State *s) static inline bool is_ide_enabled(PC87312State *s) { - return s->FER & FER_IDE_EN; + return s->regs[REG_FER] & FER_IDE_EN; } static inline uint32_t get_ide_iobase(PC87312State *s) { - return (s->FER & FER_IDE_ADDR) ? 0x170 : 0x1f0; + return (s->regs[REG_FER] & FER_IDE_ADDR) ? 0x170 : 0x1f0; } static void reconfigure_devices(PC87312State *s) { error_report("pc87312: unsupported device reconfiguration (%02x %02x %02x)", - s->FER, s->FAR, s->PTR); + s->regs[REG_FER], s->regs[REG_FAR], s->regs[REG_PTR]); } static void pc87312_soft_reset(PC87312State *s) @@ -184,9 +180,9 @@ static void pc87312_soft_reset(PC87312State *s) s->read_id_step = 0; s->selected_index = REG_FER; - s->FER = fer_init[s->config & 0x1f]; - s->FAR = far_init[s->config & 0x1f]; - s->PTR = ptr_init[s->config & 0x1f]; + s->regs[REG_FER] = fer_init[s->config & 0x1f]; + s->regs[REG_FAR] = far_init[s->config & 0x1f]; + s->regs[REG_PTR] = ptr_init[s->config & 0x1f]; } static void pc87312_hard_reset(PC87312State *s) @@ -194,7 +190,8 @@ static void pc87312_hard_reset(PC87312State *s) pc87312_soft_reset(s); } -static void pc87312_ioport_write(void *opaque, uint32_t addr, uint32_t val) +static void pc87312_io_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) { PC87312State *s = opaque; @@ -213,7 +210,7 @@ static void pc87312_ioport_write(void *opaque, uint32_t addr, uint32_t val) } } -static uint32_t pc87312_ioport_read(void *opaque, uint32_t addr) +static uint64_t pc87312_io_read(void *opaque, hwaddr addr, unsigned int size) { PC87312State *s = opaque; uint32_t val; @@ -241,6 +238,16 @@ static uint32_t pc87312_ioport_read(void *opaque, uint32_t addr) return val; } +static const MemoryRegionOps pc87312_io_ops = { + .read = pc87312_io_read, + .write = pc87312_io_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 1, + }, +}; + static int pc87312_post_load(void *opaque, int version_id) { PC87312State *s = opaque; @@ -270,6 +277,7 @@ static int pc87312_init(ISADevice *dev) s = PC87312(dev); bus = isa_bus_from_device(dev); pc87312_hard_reset(s); + isa_register_ioport(dev, &s->io, s->iobase); if (is_parallel_enabled(s)) { chr = parallel_hds[0]; @@ -337,11 +345,16 @@ static int pc87312_init(ISADevice *dev) trace_pc87312_info_ide(get_ide_iobase(s)); } - register_ioport_write(s->iobase, 2, 1, pc87312_ioport_write, s); - register_ioport_read(s->iobase, 2, 1, pc87312_ioport_read, s); return 0; } +static void pc87312_initfn(Object *obj) +{ + PC87312State *s = PC87312(obj); + + memory_region_init_io(&s->io, &pc87312_io_ops, s, "pc87312", 2); +} + static const VMStateDescription vmstate_pc87312 = { .name = "pc87312", .version_id = 1, @@ -376,6 +389,7 @@ static const TypeInfo pc87312_type_info = { .name = TYPE_PC87312, .parent = TYPE_ISA_DEVICE, .instance_size = sizeof(PC87312State), + .instance_init = pc87312_initfn, .class_init = pc87312_class_init, }; diff --git a/hw/pc87312.h b/hw/pc87312.h index 7ca7912ba..7b9e6f613 100644 --- a/hw/pc87312.h +++ b/hw/pc87312.h @@ -56,6 +56,8 @@ typedef struct PC87312State { uint32_t base; } ide; + MemoryRegion io; + uint8_t read_id_step; uint8_t selected_index; diff --git a/hw/xen_disk.c b/hw/xen_disk.c index a6a64a245..7fea87156 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -51,6 +51,13 @@ static int max_requests = 32; #define BLOCK_SIZE 512 #define IOCB_COUNT (BLKIF_MAX_SEGMENTS_PER_REQUEST + 2) +struct PersistentGrant { + void *page; + struct XenBlkDev *blkdev; +}; + +typedef struct PersistentGrant PersistentGrant; + struct ioreq { blkif_request_t req; int16_t status; @@ -68,6 +75,7 @@ struct ioreq { int prot; void *page[BLKIF_MAX_SEGMENTS_PER_REQUEST]; void *pages; + int num_unmap; /* aio status */ int aio_inflight; @@ -104,6 +112,12 @@ struct XenBlkDev { int requests_inflight; int requests_finished; + /* Persistent grants extension */ + gboolean feature_persistent; + GTree *persistent_gnts; + unsigned int persistent_gnt_count; + unsigned int max_grants; + /* qemu block driver */ DriveInfo *dinfo; BlockDriverState *bs; @@ -112,6 +126,54 @@ struct XenBlkDev { /* ------------------------------------------------------------- */ +static void ioreq_reset(struct ioreq *ioreq) +{ + memset(&ioreq->req, 0, sizeof(ioreq->req)); + ioreq->status = 0; + ioreq->start = 0; + ioreq->presync = 0; + ioreq->postsync = 0; + ioreq->mapped = 0; + + memset(ioreq->domids, 0, sizeof(ioreq->domids)); + memset(ioreq->refs, 0, sizeof(ioreq->refs)); + ioreq->prot = 0; + memset(ioreq->page, 0, sizeof(ioreq->page)); + ioreq->pages = NULL; + + ioreq->aio_inflight = 0; + ioreq->aio_errors = 0; + + ioreq->blkdev = NULL; + memset(&ioreq->list, 0, sizeof(ioreq->list)); + memset(&ioreq->acct, 0, sizeof(ioreq->acct)); + + qemu_iovec_reset(&ioreq->v); +} + +static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data) +{ + uint ua = GPOINTER_TO_UINT(a); + uint ub = GPOINTER_TO_UINT(b); + return (ua > ub) - (ua < ub); +} + +static void destroy_grant(gpointer pgnt) +{ + PersistentGrant *grant = pgnt; + XenGnttab gnt = grant->blkdev->xendev.gnttabdev; + + if (xc_gnttab_munmap(gnt, grant->page, 1) != 0) { + xen_be_printf(&grant->blkdev->xendev, 0, + "xc_gnttab_munmap failed: %s\n", + strerror(errno)); + } + grant->blkdev->persistent_gnt_count--; + xen_be_printf(&grant->blkdev->xendev, 3, + "unmapped grant %p\n", grant->page); + g_free(grant); +} + static struct ioreq *ioreq_start(struct XenBlkDev *blkdev) { struct ioreq *ioreq = NULL; @@ -129,7 +191,6 @@ static struct ioreq *ioreq_start(struct XenBlkDev *blkdev) /* get one from freelist */ ioreq = QLIST_FIRST(&blkdev->freelist); QLIST_REMOVE(ioreq, list); - qemu_iovec_reset(&ioreq->v); } QLIST_INSERT_HEAD(&blkdev->inflight, ioreq, list); blkdev->requests_inflight++; @@ -153,7 +214,7 @@ static void ioreq_release(struct ioreq *ioreq, bool finish) struct XenBlkDev *blkdev = ioreq->blkdev; QLIST_REMOVE(ioreq, list); - memset(ioreq, 0, sizeof(*ioreq)); + ioreq_reset(ioreq); ioreq->blkdev = blkdev; QLIST_INSERT_HEAD(&blkdev->freelist, ioreq, list); if (finish) { @@ -182,12 +243,11 @@ static int ioreq_parse(struct ioreq *ioreq) case BLKIF_OP_READ: ioreq->prot = PROT_WRITE; /* to memory */ break; - case BLKIF_OP_WRITE_BARRIER: + case BLKIF_OP_FLUSH_DISKCACHE: + ioreq->presync = 1; if (!ioreq->req.nr_segments) { - ioreq->presync = 1; return 0; } - ioreq->presync = ioreq->postsync = 1; /* fall through */ case BLKIF_OP_WRITE: ioreq->prot = PROT_READ; /* from memory */ @@ -241,21 +301,21 @@ static void ioreq_unmap(struct ioreq *ioreq) XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev; int i; - if (ioreq->v.niov == 0 || ioreq->mapped == 0) { + if (ioreq->num_unmap == 0 || ioreq->mapped == 0) { return; } if (batch_maps) { if (!ioreq->pages) { return; } - if (xc_gnttab_munmap(gnt, ioreq->pages, ioreq->v.niov) != 0) { + if (xc_gnttab_munmap(gnt, ioreq->pages, ioreq->num_unmap) != 0) { xen_be_printf(&ioreq->blkdev->xendev, 0, "xc_gnttab_munmap failed: %s\n", strerror(errno)); } - ioreq->blkdev->cnt_map -= ioreq->v.niov; + ioreq->blkdev->cnt_map -= ioreq->num_unmap; ioreq->pages = NULL; } else { - for (i = 0; i < ioreq->v.niov; i++) { + for (i = 0; i < ioreq->num_unmap; i++) { if (!ioreq->page[i]) { continue; } @@ -273,41 +333,120 @@ static void ioreq_unmap(struct ioreq *ioreq) static int ioreq_map(struct ioreq *ioreq) { XenGnttab gnt = ioreq->blkdev->xendev.gnttabdev; - int i; + uint32_t domids[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + uint32_t refs[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + void *page[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + int i, j, new_maps = 0; + PersistentGrant *grant; + /* domids and refs variables will contain the information necessary + * to map the grants that are needed to fulfill this request. + * + * After mapping the needed grants, the page array will contain the + * memory address of each granted page in the order specified in ioreq + * (disregarding if it's a persistent grant or not). + */ if (ioreq->v.niov == 0 || ioreq->mapped == 1) { return 0; } - if (batch_maps) { + if (ioreq->blkdev->feature_persistent) { + for (i = 0; i < ioreq->v.niov; i++) { + grant = g_tree_lookup(ioreq->blkdev->persistent_gnts, + GUINT_TO_POINTER(ioreq->refs[i])); + + if (grant != NULL) { + page[i] = grant->page; + xen_be_printf(&ioreq->blkdev->xendev, 3, + "using persistent-grant %" PRIu32 "\n", + ioreq->refs[i]); + } else { + /* Add the grant to the list of grants that + * should be mapped + */ + domids[new_maps] = ioreq->domids[i]; + refs[new_maps] = ioreq->refs[i]; + page[i] = NULL; + new_maps++; + } + } + /* Set the protection to RW, since grants may be reused later + * with a different protection than the one needed for this request + */ + ioreq->prot = PROT_WRITE | PROT_READ; + } else { + /* All grants in the request should be mapped */ + memcpy(refs, ioreq->refs, sizeof(refs)); + memcpy(domids, ioreq->domids, sizeof(domids)); + memset(page, 0, sizeof(page)); + new_maps = ioreq->v.niov; + } + + if (batch_maps && new_maps) { ioreq->pages = xc_gnttab_map_grant_refs - (gnt, ioreq->v.niov, ioreq->domids, ioreq->refs, ioreq->prot); + (gnt, new_maps, domids, refs, ioreq->prot); if (ioreq->pages == NULL) { xen_be_printf(&ioreq->blkdev->xendev, 0, "can't map %d grant refs (%s, %d maps)\n", - ioreq->v.niov, strerror(errno), ioreq->blkdev->cnt_map); + new_maps, strerror(errno), ioreq->blkdev->cnt_map); return -1; } - for (i = 0; i < ioreq->v.niov; i++) { - ioreq->v.iov[i].iov_base = ioreq->pages + i * XC_PAGE_SIZE + - (uintptr_t)ioreq->v.iov[i].iov_base; + for (i = 0, j = 0; i < ioreq->v.niov; i++) { + if (page[i] == NULL) { + page[i] = ioreq->pages + (j++) * XC_PAGE_SIZE; + } } - ioreq->blkdev->cnt_map += ioreq->v.niov; - } else { - for (i = 0; i < ioreq->v.niov; i++) { + ioreq->blkdev->cnt_map += new_maps; + } else if (new_maps) { + for (i = 0; i < new_maps; i++) { ioreq->page[i] = xc_gnttab_map_grant_ref - (gnt, ioreq->domids[i], ioreq->refs[i], ioreq->prot); + (gnt, domids[i], refs[i], ioreq->prot); if (ioreq->page[i] == NULL) { xen_be_printf(&ioreq->blkdev->xendev, 0, "can't map grant ref %d (%s, %d maps)\n", - ioreq->refs[i], strerror(errno), ioreq->blkdev->cnt_map); + refs[i], strerror(errno), ioreq->blkdev->cnt_map); ioreq_unmap(ioreq); return -1; } - ioreq->v.iov[i].iov_base = ioreq->page[i] + (uintptr_t)ioreq->v.iov[i].iov_base; ioreq->blkdev->cnt_map++; } + for (i = 0, j = 0; i < ioreq->v.niov; i++) { + if (page[i] == NULL) { + page[i] = ioreq->page[j++]; + } + } + } + if (ioreq->blkdev->feature_persistent) { + while ((ioreq->blkdev->persistent_gnt_count < ioreq->blkdev->max_grants) + && new_maps) { + /* Go through the list of newly mapped grants and add as many + * as possible to the list of persistently mapped grants. + * + * Since we start at the end of ioreq->page(s), we only need + * to decrease new_maps to prevent this granted pages from + * being unmapped in ioreq_unmap. + */ + grant = g_malloc0(sizeof(*grant)); + new_maps--; + if (batch_maps) { + grant->page = ioreq->pages + (new_maps) * XC_PAGE_SIZE; + } else { + grant->page = ioreq->page[new_maps]; + } + grant->blkdev = ioreq->blkdev; + xen_be_printf(&ioreq->blkdev->xendev, 3, + "adding grant %" PRIu32 " page: %p\n", + refs[new_maps], grant->page); + g_tree_insert(ioreq->blkdev->persistent_gnts, + GUINT_TO_POINTER(refs[new_maps]), + grant); + ioreq->blkdev->persistent_gnt_count++; + } + } + for (i = 0; i < ioreq->v.niov; i++) { + ioreq->v.iov[i].iov_base += (uintptr_t)page[i]; } ioreq->mapped = 1; + ioreq->num_unmap = new_maps; return 0; } @@ -369,7 +508,7 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) qemu_aio_complete, ioreq); break; case BLKIF_OP_WRITE: - case BLKIF_OP_WRITE_BARRIER: + case BLKIF_OP_FLUSH_DISKCACHE: if (!ioreq->req.nr_segments) { break; } @@ -654,7 +793,8 @@ static int blk_init(struct XenDevice *xendev) blkdev->file_size, blkdev->file_size >> 20); /* fill info */ - xenstore_write_be_int(&blkdev->xendev, "feature-barrier", 1); + xenstore_write_be_int(&blkdev->xendev, "feature-flush-cache", 1); + xenstore_write_be_int(&blkdev->xendev, "feature-persistent", 1); xenstore_write_be_int(&blkdev->xendev, "info", info); xenstore_write_be_int(&blkdev->xendev, "sector-size", blkdev->file_blk); xenstore_write_be_int(&blkdev->xendev, "sectors", @@ -678,6 +818,7 @@ out_error: static int blk_connect(struct XenDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); + int pers; if (xenstore_read_fe_int(&blkdev->xendev, "ring-ref", &blkdev->ring_ref) == -1) { return -1; @@ -686,6 +827,11 @@ static int blk_connect(struct XenDevice *xendev) &blkdev->xendev.remote_port) == -1) { return -1; } + if (xenstore_read_fe_int(&blkdev->xendev, "feature-persistent", &pers)) { + blkdev->feature_persistent = FALSE; + } else { + blkdev->feature_persistent = !!pers; + } blkdev->protocol = BLKIF_PROTOCOL_NATIVE; if (blkdev->xendev.protocol) { @@ -729,6 +875,15 @@ static int blk_connect(struct XenDevice *xendev) } } + if (blkdev->feature_persistent) { + /* Init persistent grants */ + blkdev->max_grants = max_requests * BLKIF_MAX_SEGMENTS_PER_REQUEST; + blkdev->persistent_gnts = g_tree_new_full((GCompareDataFunc)int_cmp, + NULL, NULL, + (GDestroyNotify)destroy_grant); + blkdev->persistent_gnt_count = 0; + } + xen_be_bind_evtchn(&blkdev->xendev); xen_be_printf(&blkdev->xendev, 1, "ok: proto %s, ring-ref %d, " @@ -769,6 +924,11 @@ static int blk_free(struct XenDevice *xendev) blk_disconnect(xendev); } + /* Free persistent grants */ + if (blkdev->feature_persistent) { + g_tree_destroy(blkdev->persistent_gnts); + } + while (!QLIST_EMPTY(&blkdev->freelist)) { ioreq = QLIST_FIRST(&blkdev->freelist); QLIST_REMOVE(ioreq, list); diff --git a/qga/channel-posix.c b/qga/channel-posix.c index ca9e4aaaf..e65dda382 100644 --- a/qga/channel-posix.c +++ b/qga/channel-posix.c @@ -46,6 +46,7 @@ static gboolean ga_channel_listen_accept(GIOChannel *channel, ret = ga_channel_client_add(c, client_fd); if (ret) { g_warning("error setting up connection"); + close(client_fd); goto out; } accepted = true; @@ -140,19 +141,21 @@ static gboolean ga_channel_open(GAChannel *c, const gchar *path, GAChannelMethod ); if (fd == -1) { g_critical("error opening channel: %s", strerror(errno)); - exit(EXIT_FAILURE); + return false; } #ifdef CONFIG_SOLARIS ret = ioctl(fd, I_SETSIG, S_OUTPUT | S_INPUT | S_HIPRI); if (ret == -1) { g_critical("error setting event mask for channel: %s", strerror(errno)); - exit(EXIT_FAILURE); + close(fd); + return false; } #endif ret = ga_channel_client_add(c, fd); if (ret) { g_critical("error adding channel to main loop"); + close(fd); return false; } break; @@ -162,7 +165,7 @@ static gboolean ga_channel_open(GAChannel *c, const gchar *path, GAChannelMethod int fd = qemu_open(path, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd == -1) { g_critical("error opening channel: %s", strerror(errno)); - exit(EXIT_FAILURE); + return false; } tcgetattr(fd, &tio); /* set up serial port for non-canonical, dumb byte streaming */ @@ -182,7 +185,9 @@ static gboolean ga_channel_open(GAChannel *c, const gchar *path, GAChannelMethod tcsetattr(fd, TCSANOW, &tio); ret = ga_channel_client_add(c, fd); if (ret) { - g_error("error adding channel to main loop"); + g_critical("error adding channel to main loop"); + close(fd); + return false; } break; } diff --git a/qga/main.c b/qga/main.c index a9b968c50..db281a508 100644 --- a/qga/main.c +++ b/qga/main.c @@ -261,13 +261,26 @@ void ga_set_response_delimited(GAState *s) s->delimit_response = true; } +static FILE *ga_open_logfile(const char *logfile) +{ + FILE *f; + + f = fopen(logfile, "a"); + if (!f) { + return NULL; + } + + qemu_set_cloexec(fileno(f)); + return f; +} + #ifndef _WIN32 static bool ga_open_pidfile(const char *pidfile) { int pidfd; char pidstr[32]; - pidfd = open(pidfile, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR); + pidfd = qemu_open(pidfile, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR); if (pidfd == -1 || lockf(pidfd, F_TLOCK, 0)) { g_critical("Cannot lock pid file, %s", strerror(errno)); if (pidfd != -1) { @@ -276,7 +289,7 @@ static bool ga_open_pidfile(const char *pidfile) return false; } - if (ftruncate(pidfd, 0) || lseek(pidfd, 0, SEEK_SET)) { + if (ftruncate(pidfd, 0)) { g_critical("Failed to truncate pid file"); goto fail; } @@ -286,10 +299,12 @@ static bool ga_open_pidfile(const char *pidfile) goto fail; } + /* keep pidfile open & locked forever */ return true; fail: unlink(pidfile); + close(pidfd); return false; } #else /* _WIN32 */ @@ -402,7 +417,7 @@ void ga_unset_frozen(GAState *s) * in a frozen state at start up, do it now */ if (s->deferred_options.log_filepath) { - s->log_file = fopen(s->deferred_options.log_filepath, "a"); + s->log_file = ga_open_logfile(s->deferred_options.log_filepath); if (!s->log_file) { s->log_file = stderr; } @@ -605,6 +620,7 @@ static gboolean channel_event_cb(GIOCondition condition, gpointer data) if (!s->virtio) { return false; } + /* fall through */ case G_IO_STATUS_AGAIN: /* virtio causes us to spin here when no process is attached to * host-side chardev. sleep a bit to mitigate this @@ -884,7 +900,7 @@ int main(int argc, char **argv) become_daemon(pid_filepath); } if (log_filepath) { - FILE *log_file = fopen(log_filepath, "a"); + FILE *log_file = ga_open_logfile(log_filepath); if (!log_file) { g_critical("unable to open specified log file: %s", strerror(errno)); diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index ed0eb698c..d91d90325 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -31,7 +31,7 @@ # # Since: 1.1 # ## -{ 'command': 'guest-sync-delimited' +{ 'command': 'guest-sync-delimited', 'data': { 'id': 'int' }, 'returns': 'int' } @@ -69,7 +69,7 @@ # # Since: 0.15.0 ## -{ 'command': 'guest-sync' +{ 'command': 'guest-sync', 'data': { 'id': 'int' }, 'returns': 'int' }