Grab device locks when moving data through block devices in the host->guest
direction.
Also protect the aio_list by a separate lock.
Index: kvm-userspace.io/qemu/block-qcow.c
===================================================================
--- kvm-userspace.io.orig/qemu/block-qcow.c
+++ kvm-userspace.io/qemu/block-qcow.c
@@ -543,7 +543,9 @@ static void qcow_aio_read_cb(void *opaqu
acb->hd_aiocb = NULL;
if (ret < 0) {
fail:
+ qemu_aio_lock(bs);
acb->common.cb(acb->common.opaque, ret);
+ qemu_aio_unlock(bs);
qemu_aio_release(acb);
return;
}
@@ -568,7 +570,9 @@ static void qcow_aio_read_cb(void *opaqu
if (acb->nb_sectors == 0) {
/* request completed */
+ qemu_aio_lock(bs);
acb->common.cb(acb->common.opaque, 0);
+ qemu_aio_unlock(bs);
qemu_aio_release(acb);
return;
}
@@ -646,7 +650,9 @@ static void qcow_aio_write_cb(void *opaq
if (ret < 0) {
fail:
+ qemu_aio_lock(bs);
acb->common.cb(acb->common.opaque, ret);
+ qemu_aio_unlock(bs);
qemu_aio_release(acb);
return;
}
@@ -657,7 +663,9 @@ static void qcow_aio_write_cb(void *opaq
if (acb->nb_sectors == 0) {
/* request completed */
+ qemu_aio_lock(bs);
acb->common.cb(acb->common.opaque, 0);
+ qemu_aio_unlock(bs);
qemu_aio_release(acb);
return;
}
Index: kvm-userspace.io/qemu/block-raw-posix.c
===================================================================
--- kvm-userspace.io.orig/qemu/block-raw-posix.c
+++ kvm-userspace.io/qemu/block-raw-posix.c
@@ -260,11 +260,14 @@ static void aio_signal_handler(int signu
#endif
}
+qemu_mutex_t aio_list_lock;
+
void qemu_aio_init(void)
{
struct sigaction act;
aio_initialized = 1;
+ qemu_mutex_init(&aio_list_lock);
sigfillset(&act.sa_mask);
act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
@@ -291,6 +294,7 @@ void qemu_aio_poll(void)
int ret;
for(;;) {
+ qemu_mutex_lock(&aio_list_lock);
pacb = &first_aio;
for(;;) {
acb = *pacb;
@@ -300,7 +304,9 @@ void qemu_aio_poll(void)
if (ret == ECANCELED) {
/* remove the request */
*pacb = acb->next;
+ qemu_mutex_unlock(&aio_list_lock);
qemu_aio_release(acb);
+ break;
} else if (ret != EINPROGRESS) {
/* end of aio */
if (ret == 0) {
@@ -314,8 +320,11 @@ void qemu_aio_poll(void)
}
/* remove the request */
*pacb = acb->next;
+ qemu_mutex_unlock(&aio_list_lock);
/* call the callback */
+ qemu_aio_lock(acb->common.bs);
acb->common.cb(acb->common.opaque, ret);
+ qemu_aio_unlock(acb->common.bs);
qemu_aio_release(acb);
break;
} else {
@@ -323,7 +332,8 @@ void qemu_aio_poll(void)
}
}
}
- the_end: ;
+ the_end:
+ qemu_mutex_unlock(&aio_list_lock);
}
/* Wait for all IO requests to complete. */
@@ -331,6 +341,7 @@ void qemu_aio_flush(void)
{
qemu_aio_wait_start();
qemu_aio_poll();
+ /* FIXME: first_aio is protected by aio_list_lock. */
while (first_aio) {
qemu_aio_wait();
}
@@ -410,8 +421,10 @@ static RawAIOCB *raw_aio_setup(BlockDriv
else
acb->aiocb.aio_nbytes = nb_sectors * 512;
acb->aiocb.aio_offset = sector_num * 512;
+ qemu_mutex_lock(&aio_list_lock);
acb->next = first_aio;
first_aio = acb;
+ qemu_mutex_unlock(&aio_list_lock);
return acb;
}
@@ -451,7 +464,6 @@ static void raw_aio_cancel(BlockDriverAI
{
int ret;
RawAIOCB *acb = (RawAIOCB *)blockacb;
- RawAIOCB **pacb;
ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
if (ret == AIO_NOTCANCELED) {
@@ -459,7 +471,9 @@ static void raw_aio_cancel(BlockDriverAI
it */
while (aio_error(&acb->aiocb) == EINPROGRESS);
}
+ /* qemu_aio_poll will remove it from the queue */
+#if 0
/* remove the callback from the queue */
pacb = &first_aio;
for(;;) {
@@ -467,11 +481,14 @@ static void raw_aio_cancel(BlockDriverAI
break;
} else if (*pacb == acb) {
*pacb = acb->next;
+ qemu_mutex_unlock(&aio_list_lock);
qemu_aio_release(acb);
+ qemu_mutex_lock(&aio_list_lock);
break;
}
pacb = &acb->next;
}
+#endif
}
static void raw_close(BlockDriverState *bs)
Index: kvm-userspace.io/qemu/block.c
===================================================================
--- kvm-userspace.io.orig/qemu/block.c
+++ kvm-userspace.io/qemu/block.c
@@ -501,6 +501,21 @@ int bdrv_commit(BlockDriverState *bs)
return 0;
}
+void qemu_aio_lock(BlockDriverState *bs)
+{
+ if (!bs->qemu_dev) {
+ unsigned long *ptr = 0;
+ printf("bs->drv = NULL\n");
+ *ptr = 0;
+ }
+ qemu_mutex_lock(&bs->qemu_dev->lock);
+}
+
+void qemu_aio_unlock(BlockDriverState *bs)
+{
+ qemu_mutex_unlock(&bs->qemu_dev->lock);
+}
+
/* return < 0 if error. See bdrv_write() for the return codes */
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
@@ -1326,7 +1341,9 @@ static void bdrv_aio_cancel_em(BlockDriv
static void bdrv_aio_bh_cb(void *opaque)
{
BlockDriverAIOCBSync *acb = opaque;
+ qemu_aio_lock(acb->common.bs);
acb->common.cb(acb->common.opaque, acb->ret);
+ qemu_aio_unlock(acb->common.bs);
qemu_aio_release(acb);
}
@@ -1365,6 +1382,7 @@ static BlockDriverAIOCB *bdrv_aio_write_
static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
{
BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
+ /* FIXME: the bh list needs a lock */
qemu_bh_cancel(acb->bh);
qemu_aio_release(acb);
}
@@ -1459,7 +1477,6 @@ void *qemu_aio_get(BlockDriverState *bs,
void qemu_aio_release(void *p)
{
- BlockDriverAIOCB *acb = p;
qemu_free(p);
}
Index: kvm-userspace.io/qemu/block.h
===================================================================
--- kvm-userspace.io.orig/qemu/block.h
+++ kvm-userspace.io/qemu/block.h
@@ -96,6 +96,9 @@ void qemu_aio_wait_start(void);
void qemu_aio_wait(void);
void qemu_aio_wait_end(void);
+void qemu_aio_lock(BlockDriverState *bs);
+void qemu_aio_unlock(BlockDriverState *bs);
+
int qemu_key_check(BlockDriverState *bs, const char *name);
/* Ensure contents are flushed to disk. */
Index: kvm-userspace.io/qemu/block_int.h
===================================================================
--- kvm-userspace.io.orig/qemu/block_int.h
+++ kvm-userspace.io/qemu/block_int.h
@@ -130,6 +130,7 @@ struct BlockDriverState {
char device_name[32];
/* PCI devfn of parent */
int devfn;
+ QEMUDevice *qemu_dev;
BlockDriverState *next;
};
Index: kvm-userspace.io/qemu/block-qcow2.c
===================================================================
--- kvm-userspace.io.orig/qemu/block-qcow2.c
+++ kvm-userspace.io/qemu/block-qcow2.c
@@ -812,7 +812,9 @@ static void qcow_aio_read_cb(void *opaqu
acb->hd_aiocb = NULL;
if (ret < 0) {
fail:
+ qemu_aio_lock(bs);
acb->common.cb(acb->common.opaque, ret);
+ qemu_aio_unlock(bs);
qemu_aio_release(acb);
return;
}
@@ -837,7 +839,9 @@ static void qcow_aio_read_cb(void *opaqu
if (acb->nb_sectors == 0) {
/* request completed */
+ qemu_aio_lock(bs);
acb->common.cb(acb->common.opaque, 0);
+ qemu_aio_unlock(bs);
qemu_aio_release(acb);
return;
}
@@ -933,7 +937,9 @@ static void qcow_aio_write_cb(void *opaq
if (ret < 0) {
fail:
+ qemu_aio_lock(bs);
acb->common.cb(acb->common.opaque, ret);
+ qemu_aio_unlock(bs);
qemu_aio_release(acb);
return;
}
@@ -944,7 +950,9 @@ static void qcow_aio_write_cb(void *opaq
if (acb->nb_sectors == 0) {
/* request completed */
+ qemu_aio_lock(bs);
acb->common.cb(acb->common.opaque, 0);
+ qemu_aio_unlock(bs);
qemu_aio_release(acb);
return;
}
Index: kvm-userspace.io/qemu/hw/ide.c
===================================================================
--- kvm-userspace.io.orig/qemu/hw/ide.c
+++ kvm-userspace.io/qemu/hw/ide.c
@@ -2983,8 +2983,10 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
ide_init_ioport(&d->ide_if[2], 0x170, 0x376, &d->dev.qemu_dev);
for (i = 0; i < 4; i++)
- if (hd_table[i])
+ if (hd_table[i]) {
+ hd_table[i]->qemu_dev = &d->dev.qemu_dev;
hd_table[i]->devfn = d->dev.devfn;
+ }
register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
}
Index: kvm-userspace.io/qemu/hw/lsi53c895a.c
===================================================================
--- kvm-userspace.io.orig/qemu/hw/lsi53c895a.c
+++ kvm-userspace.io/qemu/hw/lsi53c895a.c
@@ -594,6 +594,7 @@ static void lsi_command_complete(void *o
{
LSIState *s = (LSIState *)opaque;
int out;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
out = (s->sstat1 & PHASE_MASK) == PHASE_DO;
if (reason == SCSI_REASON_DONE) {
@@ -735,6 +736,8 @@ static void lsi_do_msgout(LSIState *s)
uint8_t msg;
int len;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
+
DPRINTF("MSG out len=%d\n", s->dbc);
while (s->dbc) {
msg = lsi_get_msgbyte(s);
@@ -1217,6 +1220,8 @@ static uint8_t lsi_reg_readb(LSIState *s
case addr + 2: return (s->name >> 16) & 0xff; \
case addr + 3: return (s->name >> 24) & 0xff;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
+
#ifdef DEBUG_LSI_REG
DPRINTF("Read reg %x\n", offset);
#endif
@@ -1383,6 +1388,8 @@ static void lsi_reg_writeb(LSIState *s,
case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break; \
case addr + 3: s->name &= 0x00ffffff; s->name |= val << 24; break;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
+
#ifdef DEBUG_LSI_REG
DPRINTF("Write reg %x = %02x\n", offset, val);
#endif
@@ -1592,6 +1599,7 @@ static void lsi_mmio_writeb(void *opaque
{
LSIState *s = (LSIState *)opaque;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
lsi_reg_writeb(s, addr & 0xff, val);
}
@@ -1599,6 +1607,7 @@ static void lsi_mmio_writew(void *opaque
{
LSIState *s = (LSIState *)opaque;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
addr &= 0xff;
lsi_reg_writeb(s, addr, val & 0xff);
lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
@@ -1608,6 +1617,7 @@ static void lsi_mmio_writel(void *opaque
{
LSIState *s = (LSIState *)opaque;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
addr &= 0xff;
lsi_reg_writeb(s, addr, val & 0xff);
lsi_reg_writeb(s, addr + 1, (val >> 8) & 0xff);
@@ -1619,6 +1629,7 @@ static uint32_t lsi_mmio_readb(void *opa
{
LSIState *s = (LSIState *)opaque;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
return lsi_reg_readb(s, addr & 0xff);
}
@@ -1627,6 +1638,7 @@ static uint32_t lsi_mmio_readw(void *opa
LSIState *s = (LSIState *)opaque;
uint32_t val;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
addr &= 0xff;
val = lsi_reg_readb(s, addr);
val |= lsi_reg_readb(s, addr + 1) << 8;
@@ -1662,6 +1674,7 @@ static void lsi_ram_writeb(void *opaque,
LSIState *s = (LSIState *)opaque;
uint32_t newval;
int shift;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
addr &= 0x1fff;
newval = s->script_ram[addr >> 2];
@@ -1675,6 +1688,7 @@ static void lsi_ram_writew(void *opaque,
{
LSIState *s = (LSIState *)opaque;
uint32_t newval;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
addr &= 0x1fff;
newval = s->script_ram[addr >> 2];
@@ -1690,6 +1704,7 @@ static void lsi_ram_writew(void *opaque,
static void lsi_ram_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
LSIState *s = (LSIState *)opaque;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
addr &= 0x1fff;
s->script_ram[addr >> 2] = val;
@@ -1699,6 +1714,7 @@ static uint32_t lsi_ram_readb(void *opaq
{
LSIState *s = (LSIState *)opaque;
uint32_t val;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
addr &= 0x1fff;
val = s->script_ram[addr >> 2];
@@ -1710,6 +1726,7 @@ static uint32_t lsi_ram_readw(void *opaq
{
LSIState *s = (LSIState *)opaque;
uint32_t val;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
addr &= 0x1fff;
val = s->script_ram[addr >> 2];
@@ -1721,6 +1738,7 @@ static uint32_t lsi_ram_readw(void *opaq
static uint32_t lsi_ram_readl(void *opaque, target_phys_addr_t addr)
{
LSIState *s = (LSIState *)opaque;
+ assert_is_locked(&s->pci_dev.qemu_dev.lock);
addr &= 0x1fff;
return le32_to_cpu(s->script_ram[addr >> 2]);
@@ -1850,6 +1868,7 @@ void lsi_scsi_attach(void *opaque, Block
if (s->scsi_dev[id] == NULL)
s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s);
bd->devfn = s->pci_dev.devfn;
+ bd->qemu_dev = &s->pci_dev.qemu_dev;
}
int lsi_scsi_uninit(PCIDevice *d)
--
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
kvm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel