From 1bc6b705eed02dab9feb0e663219b5623f3d684d Mon Sep 17 00:00:00 2001 From: Jeff Cody Date: Tue, 20 Nov 2012 10:21:10 -0500 Subject: block: add bdrv_reopen() support for raw hdev, floppy, and cdrom For hdev, floppy, and cdrom, the reopen() handlers are the same as for the file reopen handler. For floppy and cdrom types, however, we keep O_NONBLOCK, as in the _open function. Signed-off-by: Jeff Cody Signed-off-by: Stefan Hajnoczi --- block/raw-posix.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/block/raw-posix.c b/block/raw-posix.c index f2f0404f6f..550c81f22b 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -333,6 +333,10 @@ static int raw_reopen_prepare(BDRVReopenState *state, } #endif + if (s->type == FTYPE_FD || s->type == FTYPE_CD) { + raw_s->open_flags |= O_NONBLOCK; + } + raw_parse_flags(state->flags, &raw_s->open_flags); raw_s->fd = -1; @@ -1409,6 +1413,9 @@ static BlockDriver bdrv_host_device = { .bdrv_probe_device = hdev_probe_device, .bdrv_file_open = hdev_open, .bdrv_close = raw_close, + .bdrv_reopen_prepare = raw_reopen_prepare, + .bdrv_reopen_commit = raw_reopen_commit, + .bdrv_reopen_abort = raw_reopen_abort, .bdrv_create = hdev_create, .create_options = raw_create_options, .bdrv_has_zero_init = hdev_has_zero_init, @@ -1530,6 +1537,9 @@ static BlockDriver bdrv_host_floppy = { .bdrv_probe_device = floppy_probe_device, .bdrv_file_open = floppy_open, .bdrv_close = raw_close, + .bdrv_reopen_prepare = raw_reopen_prepare, + .bdrv_reopen_commit = raw_reopen_commit, + .bdrv_reopen_abort = raw_reopen_abort, .bdrv_create = hdev_create, .create_options = raw_create_options, .bdrv_has_zero_init = hdev_has_zero_init, @@ -1629,6 +1639,9 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_probe_device = cdrom_probe_device, .bdrv_file_open = cdrom_open, .bdrv_close = raw_close, + .bdrv_reopen_prepare = raw_reopen_prepare, + .bdrv_reopen_commit = raw_reopen_commit, + .bdrv_reopen_abort = raw_reopen_abort, .bdrv_create = hdev_create, .create_options = raw_create_options, .bdrv_has_zero_init = hdev_has_zero_init, @@ -1748,6 +1761,9 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_probe_device = cdrom_probe_device, .bdrv_file_open = cdrom_open, .bdrv_close = raw_close, + .bdrv_reopen_prepare = raw_reopen_prepare, + .bdrv_reopen_commit = raw_reopen_commit, + .bdrv_reopen_abort = raw_reopen_abort, .bdrv_create = hdev_create, .create_options = raw_create_options, .bdrv_has_zero_init = hdev_has_zero_init, -- cgit v1.2.3 From 8ba2aae32c40f544def6be7ae82be9bcb781e01d Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 20 Nov 2012 16:34:17 +0100 Subject: vdi: don't override libuuid symbols It's poor symbol hygiene to provide a global symbols that collide with a common library like libuuid. If QEMU links against a shared library that depends on uuid_generate() it can end up calling our stub version of the function. This exact scenario happened with GlusterFS libgfapi.so, which depends on libglusterfs.so's uuid_generate(). Scope the uuid stubs for vdi.c only and avoid affecting other shared objects. Signed-off-by: Stefan Hajnoczi Reviewed-by: Kevin Wolf --- block/vdi.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/block/vdi.c b/block/vdi.c index f35b12ec98..c8330b7eae 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -60,9 +60,6 @@ /* TODO: move uuid emulation to some central place in QEMU. */ #include "sysemu.h" /* UUID_FMT */ typedef unsigned char uuid_t[16]; -void uuid_generate(uuid_t out); -int uuid_is_null(const uuid_t uu); -void uuid_unparse(const uuid_t uu, char *out); #endif /* Code configuration options. */ @@ -124,18 +121,18 @@ void uuid_unparse(const uuid_t uu, char *out); #define VDI_IS_ALLOCATED(X) ((X) < VDI_DISCARDED) #if !defined(CONFIG_UUID) -void uuid_generate(uuid_t out) +static inline void uuid_generate(uuid_t out) { memset(out, 0, sizeof(uuid_t)); } -int uuid_is_null(const uuid_t uu) +static inline int uuid_is_null(const uuid_t uu) { uuid_t null_uuid = { 0 }; return memcmp(uu, null_uuid, sizeof(uuid_t)) == 0; } -void uuid_unparse(const uuid_t uu, char *out) +static inline void uuid_unparse(const uuid_t uu, char *out) { snprintf(out, 37, UUID_FMT, uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7], -- cgit v1.2.3 From 08448d5195aeff49bf25fb62b4a6218f079f5284 Mon Sep 17 00:00:00 2001 From: Stefan Priebe Date: Tue, 20 Nov 2012 13:44:55 +0100 Subject: use int64_t for return values from rbd instead of int rbd / rados tends to return pretty often length of writes or discarded blocks. These values might be bigger than int. The steps to reproduce are: mkfs.xfs -f a whole device bigger than int in bytes. mkfs.xfs sends a discard. Important is that you use scsi-hd and set discard_granularity=512. Otherwise rbd disabled discard support. Signed-off-by: Stefan Priebe Signed-off-by: Stefan Hajnoczi --- block/rbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/rbd.c b/block/rbd.c index 0aaacaf859..f3becc7a8b 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -69,7 +69,7 @@ typedef enum { typedef struct RBDAIOCB { BlockDriverAIOCB common; QEMUBH *bh; - int ret; + int64_t ret; QEMUIOVector *qiov; char *bounce; RBDAIOCmd cmd; @@ -86,7 +86,7 @@ typedef struct RADOSCB { int done; int64_t size; char *buf; - int ret; + int64_t ret; } RADOSCB; #define RBD_FD_READ 0 -- cgit v1.2.3 From 038268e2e8087ee2fd8987a77ba580e15f14c147 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 20 Nov 2012 17:27:43 +0100 Subject: ide: Fix crash with too long PRD Without this, s->nsector can become negative and badness happens (trying to malloc huge amount of memory and glib calls abort()) Signed-off-by: Kevin Wolf Signed-off-by: Stefan Hajnoczi --- hw/ide/core.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/ide/core.c b/hw/ide/core.c index 7d6b0fa7b4..c2ab78753a 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -579,6 +579,7 @@ void ide_dma_cb(void *opaque, int ret) IDEState *s = opaque; int n; int64_t sector_num; + bool stay_active = false; if (ret < 0) { int op = BM_STATUS_DMA_RETRY; @@ -594,6 +595,14 @@ void ide_dma_cb(void *opaque, int ret) } n = s->io_buffer_size >> 9; + if (n > s->nsector) { + /* The PRDs were longer than needed for this request. Shorten them so + * we don't get a negative remainder. The Active bit must remain set + * after the request completes. */ + n = s->nsector; + stay_active = true; + } + sector_num = ide_get_sector(s); if (n > 0) { dma_buf_commit(s); @@ -646,6 +655,9 @@ eot: bdrv_acct_done(s->bs, &s->acct); } ide_set_inactive(s); + if (stay_active) { + s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_DMAING); + } } static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd) -- cgit v1.2.3 From 72bcca73c7a67c8506fa737618861ad413dabf38 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 20 Nov 2012 17:27:44 +0100 Subject: ide: Fix status register after short PRDs When failing a request because the length of the regions described by the PRDT was too short for the requested number of sectors, the IDE emulation forgot to update the status register, so that the device would keep the BSY flag set indefinitely. Signed-off-by: Kevin Wolf Signed-off-by: Stefan Hajnoczi --- hw/ide/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/ide/core.c b/hw/ide/core.c index c2ab78753a..8da894f240 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -625,6 +625,7 @@ void ide_dma_cb(void *opaque, int ret) if (s->bus->dma->ops->prepare_buf(s->bus->dma, ide_cmd_is_read(s)) == 0) { /* The PRDs were too short. Reset the Active bit, but don't raise an * interrupt. */ + s->status = READY_STAT | SEEK_STAT; goto eot; } -- cgit v1.2.3