From 3e82990b52d5afeb4957dd9b87be83d752e369b9 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 27 May 2010 16:20:30 +0200 Subject: Cleanup: bdrv_open() no need to shift total_size just to shift back. In bdrv_open() there is no need to shift total_size >> 9 just to multiply it by 512 again just a few lines later, since this is the only place the variable is used. Mask with BDRV_SECTOR_MASK to protect against case where we are passed a corrupted image. Signed-off-by: Jes Sorensen Signed-off-by: Kevin Wolf --- block.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block.c b/block.c index 39724c17d3..8385b4fe4f 100644 --- a/block.c +++ b/block.c @@ -522,7 +522,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, bdrv_delete(bs1); return ret; } - total_size = bdrv_getlength(bs1) >> BDRV_SECTOR_BITS; + total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK; if (bs1->drv && bs1->drv->protocol_name) is_protocol = 1; @@ -541,7 +541,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, bdrv_qcow2 = bdrv_find_format("qcow2"); options = parse_option_parameters("", bdrv_qcow2->create_options, NULL); - set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size * 512); + set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size); set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename); if (drv) { set_option_parameter(options, BLOCK_OPT_BACKING_FMT, -- cgit v1.2.3 From eb5a316514144bc1def4cb9b88fb996420ca80cc Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 27 May 2010 16:20:31 +0200 Subject: Cleanup: Be consistent and use BDRV_SECTOR_SIZE instead of 512 Clean up block.c and use BDRV_SECTOR_SIZE rather than hard coded numbers (512) when referring to sector size throughout the code. Signed-off-by: Jes Sorensen Signed-off-by: Kevin Wolf --- block.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/block.c b/block.c index 8385b4fe4f..9c43332f4f 100644 --- a/block.c +++ b/block.c @@ -684,7 +684,7 @@ int bdrv_commit(BlockDriverState *bs) int64_t i, total_sectors; int n, j, ro, open_flags; int ret = 0, rw_ret = 0; - unsigned char sector[512]; + unsigned char sector[BDRV_SECTOR_SIZE]; char filename[1024]; BlockDriverState *bs_rw, *bs_ro; @@ -824,7 +824,8 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset, static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num, int nb_sectors) { - return bdrv_check_byte_request(bs, sector_num * 512, nb_sectors * 512); + return bdrv_check_byte_request(bs, sector_num * BDRV_SECTOR_SIZE, + nb_sectors * BDRV_SECTOR_SIZE); } /* return < 0 if error. See bdrv_write() for the return codes */ @@ -1059,7 +1060,7 @@ struct partition { static int guess_disk_lchs(BlockDriverState *bs, int *pcylinders, int *pheads, int *psectors) { - uint8_t buf[512]; + uint8_t buf[BDRV_SECTOR_SIZE]; int ret, i, heads, sectors, cylinders; struct partition *p; uint32_t nr_sects; @@ -1535,7 +1536,7 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs) "} }", bs->rd_bytes, bs->wr_bytes, bs->rd_ops, bs->wr_ops, - bs->wr_highest_sector * 512); + bs->wr_highest_sector * (long)BDRV_SECTOR_SIZE); dict = qobject_to_qdict(res); if (*bs->device_name) { @@ -2197,7 +2198,7 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, async_ret = NOT_DONE; iov.iov_base = (void *)buf; - iov.iov_len = nb_sectors * 512; + iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE; qemu_iovec_init_external(&qiov, &iov, 1); acb = bdrv_aio_readv(bs, sector_num, &qiov, nb_sectors, bdrv_rw_em_cb, &async_ret); @@ -2228,7 +2229,7 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num, async_ret = NOT_DONE; iov.iov_base = (void *)buf; - iov.iov_len = nb_sectors * 512; + iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE; qemu_iovec_init_external(&qiov, &iov, 1); acb = bdrv_aio_writev(bs, sector_num, &qiov, nb_sectors, bdrv_rw_em_cb, &async_ret); -- cgit v1.2.3 From 9040385dcc0a4b32ca8ceeda6dc679aea56e3832 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 27 May 2010 16:20:32 +0200 Subject: Cleanup: raw-posix.c: Be more consistent using BDRV_SECTOR_SIZE instead of 512 Clean up raw-posix.c to be more consistent using BDRV_SECTOR_SIZE instead of hard coded 512 values. Signed-off-by: Jes Sorensen Signed-off-by: Kevin Wolf --- block/raw-posix.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/block/raw-posix.c b/block/raw-posix.c index 7541ed2abe..3f0701b8a4 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -392,8 +392,9 @@ static int raw_read(BlockDriverState *bs, int64_t sector_num, { int ret; - ret = raw_pread(bs, sector_num * 512, buf, nb_sectors * 512); - if (ret == (nb_sectors * 512)) + ret = raw_pread(bs, sector_num * BDRV_SECTOR_SIZE, buf, + nb_sectors * BDRV_SECTOR_SIZE); + if (ret == (nb_sectors * BDRV_SECTOR_SIZE)) ret = 0; return ret; } @@ -480,8 +481,9 @@ static int raw_write(BlockDriverState *bs, int64_t sector_num, const uint8_t *buf, int nb_sectors) { int ret; - ret = raw_pwrite(bs, sector_num * 512, buf, nb_sectors * 512); - if (ret == (nb_sectors * 512)) + ret = raw_pwrite(bs, sector_num * BDRV_SECTOR_SIZE, buf, + nb_sectors * BDRV_SECTOR_SIZE); + if (ret == (nb_sectors * BDRV_SECTOR_SIZE)) ret = 0; return ret; } @@ -494,7 +496,7 @@ static int qiov_is_aligned(QEMUIOVector *qiov) int i; for (i = 0; i < qiov->niov; i++) { - if ((uintptr_t) qiov->iov[i].iov_base % 512) { + if ((uintptr_t) qiov->iov[i].iov_base % BDRV_SECTOR_SIZE) { return 0; } } @@ -703,7 +705,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options) /* Read out options */ while (options && options->name) { if (!strcmp(options->name, BLOCK_OPT_SIZE)) { - total_size = options->value.n / 512; + total_size = options->value.n / BDRV_SECTOR_SIZE; } options++; } @@ -713,7 +715,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options) if (fd < 0) { result = -errno; } else { - if (ftruncate(fd, total_size * 512) != 0) { + if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) { result = -errno; } if (close(fd) != 0) { @@ -976,7 +978,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options) /* Read out options */ while (options && options->name) { if (!strcmp(options->name, "size")) { - total_size = options->value.n / 512; + total_size = options->value.n / BDRV_SECTOR_SIZE; } options++; } @@ -989,7 +991,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options) ret = -errno; else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode)) ret = -ENODEV; - else if (lseek(fd, 0, SEEK_END) < total_size * 512) + else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE) ret = -ENOSPC; close(fd); -- cgit v1.2.3 From 1573a35d99fe60f98d30f50e9187040586c2b801 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 27 May 2010 16:20:33 +0200 Subject: Cleanup: virtio-blk.c: Be more consistent using BDRV_SECTOR_SIZE instead Clean up virtio-blk.c to be more consistent using BDRV_SECTOR_SIZE instead of hard coded 512 values. Signed-off-by: Jes Sorensen Signed-off-by: Kevin Wolf --- hw/virtio-blk.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 5d7f1a2200..80d51c4c0c 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -277,7 +277,7 @@ static void virtio_blk_handle_write(BlockRequest *blkreq, int *num_writes, } blkreq[*num_writes].sector = req->out->sector; - blkreq[*num_writes].nb_sectors = req->qiov.size / 512; + blkreq[*num_writes].nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE; blkreq[*num_writes].qiov = &req->qiov; blkreq[*num_writes].cb = virtio_blk_rw_complete; blkreq[*num_writes].opaque = req; @@ -296,7 +296,8 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req) } acb = bdrv_aio_readv(req->dev->bs, req->out->sector, &req->qiov, - req->qiov.size / 512, virtio_blk_rw_complete, req); + req->qiov.size / BDRV_SECTOR_SIZE, + virtio_blk_rw_complete, req); if (!acb) { virtio_blk_rw_complete(req, -EIO); } @@ -505,7 +506,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf) s->bs = conf->dinfo->bdrv; s->conf = conf; s->rq = NULL; - s->sector_mask = (s->conf->logical_block_size / 512) - 1; + s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1; bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs); s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output); -- cgit v1.2.3 From 0923c577f993d61eeaf41f66db1e1010fa113976 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 28 May 2010 20:10:48 +0200 Subject: qemu-io: Fix error messages The truncate and getlength commands passed a negative error number to strerror. They also happen to be the two functions that are lacking a newline at the end of their error message. Signed-off-by: Kevin Wolf --- qemu-io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu-io.c b/qemu-io.c index 72a45247da..7c6120b6ac 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -1317,7 +1317,7 @@ truncate_f(int argc, char **argv) ret = bdrv_truncate(bs, offset); if (ret < 0) { - printf("truncate: %s", strerror(ret)); + printf("truncate: %s\n", strerror(-ret)); return 0; } @@ -1342,7 +1342,7 @@ length_f(int argc, char **argv) size = bdrv_getlength(bs); if (size < 0) { - printf("getlength: %s", strerror(size)); + printf("getlength: %s\n", strerror(-size)); return 0; } -- cgit v1.2.3 From 1a43782e34e148a00a0bb8f5de56f2d93a0f0320 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 28 May 2010 15:38:42 +0200 Subject: blockdev: Belatedly remove MAX_DRIVES Unused since commit 751c6a17. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- sysemu.h | 1 - vl.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/sysemu.h b/sysemu.h index 879446ab9e..063319c8f5 100644 --- a/sysemu.h +++ b/sysemu.h @@ -176,7 +176,6 @@ typedef struct DriveInfo { #define MAX_IDE_DEVS 2 #define MAX_SCSI_DEVS 7 -#define MAX_DRIVES 32 extern QTAILQ_HEAD(drivelist, DriveInfo) drives; extern QTAILQ_HEAD(driveoptlist, DriveOpt) driveopts; diff --git a/vl.c b/vl.c index 7121cd0264..f8d3034ec8 100644 --- a/vl.c +++ b/vl.c @@ -172,8 +172,6 @@ int main(int argc, char **argv) static const char *data_dir; const char *bios_name = NULL; -/* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available - to store the VM snapshots */ struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives); struct driveoptlist driveopts = QTAILQ_HEAD_INITIALIZER(driveopts); enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; -- cgit v1.2.3 From f274776028ddb026f8891cabaf59bd58dbfc31bd Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 28 May 2010 15:38:43 +0200 Subject: blockdev: Belatedly remove driveopts Unused since commit 9dfd7c7a. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- sysemu.h | 1 - vl.c | 1 - 2 files changed, 2 deletions(-) diff --git a/sysemu.h b/sysemu.h index 063319c8f5..fd83b7dc1c 100644 --- a/sysemu.h +++ b/sysemu.h @@ -178,7 +178,6 @@ typedef struct DriveInfo { #define MAX_SCSI_DEVS 7 extern QTAILQ_HEAD(drivelist, DriveInfo) drives; -extern QTAILQ_HEAD(driveoptlist, DriveOpt) driveopts; extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); extern DriveInfo *drive_get_by_id(const char *id); diff --git a/vl.c b/vl.c index f8d3034ec8..9283469ceb 100644 --- a/vl.c +++ b/vl.c @@ -173,7 +173,6 @@ int main(int argc, char **argv) static const char *data_dir; const char *bios_name = NULL; struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives); -struct driveoptlist driveopts = QTAILQ_HEAD_INITIALIZER(driveopts); enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; DisplayType display_type = DT_DEFAULT; const char* keyboard_layout = NULL; -- cgit v1.2.3 From fb08000cee257bbd3f3a043933a6474d870c665f Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 28 May 2010 15:38:44 +0200 Subject: usb: Remove unused usb_device_add() parameter is_hotplug Unused since commit b3e461d3. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- vl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vl.c b/vl.c index 9283469ceb..76a9b25569 100644 --- a/vl.c +++ b/vl.c @@ -1315,7 +1315,7 @@ static void smp_parse(const char *optarg) /***********************************************************/ /* USB devices */ -static int usb_device_add(const char *devname, int is_hotplug) +static int usb_device_add(const char *devname) { const char *p; USBDevice *dev = NULL; @@ -1367,7 +1367,7 @@ static int usb_device_del(const char *devname) static int usb_parse(const char *cmdline) { int r; - r = usb_device_add(cmdline, 0); + r = usb_device_add(cmdline); if (r < 0) { fprintf(stderr, "qemu: could not add USB device '%s'\n", cmdline); } @@ -1377,7 +1377,7 @@ static int usb_parse(const char *cmdline) void do_usb_add(Monitor *mon, const QDict *qdict) { const char *devname = qdict_get_str(qdict, "devname"); - if (usb_device_add(devname, 1) < 0) { + if (usb_device_add(devname) < 0) { error_report("could not add USB device '%s'", devname); } } -- cgit v1.2.3 From 124964b54e0c50706385691142795b6e43dad817 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 28 May 2010 15:38:45 +0200 Subject: ide: Remove useless IDEDeviceInfo members unit, drive Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- hw/ide/internal.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 2efc7846bc..b4554cee32 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -464,8 +464,6 @@ typedef int (*ide_qdev_initfn)(IDEDevice *dev); struct IDEDeviceInfo { DeviceInfo qdev; ide_qdev_initfn init; - uint32_t unit; - DriveInfo *drive; }; #define BM_STATUS_DMAING 0x01 -- cgit v1.2.3 From 57dac7ef8aeabcd17b1ceee2296917bc48ccd526 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 28 May 2010 15:38:46 +0200 Subject: ide: Remove redundant IDEState member conf Commit 428c149b added IDEState member conf to let commit 0009baf1 find the BlockConf from there. It exists only for qdev drives, created via ide_drive_initfn(), not for drives created via ide_init2(). But for a qdev drive, we can just as well reach its IDEDevice, which contains the BlockConf. Do that, and revert the parts of commit 428c149b that add IDEState member conf. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- hw/ide/core.c | 16 +++++++--------- hw/ide/internal.h | 4 +--- hw/ide/qdev.c | 3 +-- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index 066fecb0c0..c3334b121e 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -98,6 +98,7 @@ static void ide_identify(IDEState *s) { uint16_t *p; unsigned int oldsize; + IDEDevice *dev; if (s->identify_set) { memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data)); @@ -165,8 +166,9 @@ static void ide_identify(IDEState *s) put_le16(p + 101, s->nb_sectors >> 16); put_le16(p + 102, s->nb_sectors >> 32); put_le16(p + 103, s->nb_sectors >> 48); - if (s->conf && s->conf->physical_block_size) - put_le16(p + 106, 0x6000 | get_physical_block_exp(s->conf)); + dev = s->unit ? s->bus->slave : s->bus->master; + if (dev && dev->conf.physical_block_size) + put_le16(p + 106, 0x6000 | get_physical_block_exp(&dev->conf)); memcpy(s->identify_data, p, sizeof(s->identify_data)); s->identify_set = 1; @@ -2594,8 +2596,7 @@ void ide_bus_reset(IDEBus *bus) ide_clear_hob(bus); } -void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf, - const char *version) +void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version) { int cylinders, heads, secs; uint64_t nb_sectors; @@ -2620,9 +2621,6 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf, } strncpy(s->drive_serial_str, drive_get_serial(s->bs), sizeof(s->drive_serial_str)); - if (conf) { - s->conf = conf; - } } if (strlen(s->drive_serial_str) == 0) snprintf(s->drive_serial_str, sizeof(s->drive_serial_str), @@ -2653,9 +2651,9 @@ void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1, s->sector_write_timer = qemu_new_timer(vm_clock, ide_sector_write_timer_cb, s); if (i == 0) - ide_init_drive(s, hd0, NULL, NULL); + ide_init_drive(s, hd0, NULL); if (i == 1) - ide_init_drive(s, hd1, NULL, NULL); + ide_init_drive(s, hd1, NULL); } bus->irq = irq; } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index b4554cee32..cf7101924d 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -398,7 +398,6 @@ struct IDEState { /* set for lba48 access */ uint8_t lba48; BlockDriverState *bs; - BlockConf *conf; char version[9]; /* ATAPI specific */ uint8_t sense_key; @@ -555,8 +554,7 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr); void ide_data_writel(void *opaque, uint32_t addr, uint32_t val); uint32_t ide_data_readl(void *opaque, uint32_t addr); -void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf, - const char *version); +void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version); void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1, qemu_irq irq); void ide_init_ioport(IDEBus *bus, int iobase, int iobase2); diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index b18693d945..9ebb906cc3 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -99,8 +99,7 @@ typedef struct IDEDrive { static int ide_drive_initfn(IDEDevice *dev) { IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus); - ide_init_drive(bus->ifs + dev->unit, dev->conf.dinfo, &dev->conf, - dev->version); + ide_init_drive(bus->ifs + dev->unit, dev->conf.dinfo, dev->version); return 0; } -- cgit v1.2.3 From d459da0ed4bcdc38d5aaaa78f0c83fdeac6dd190 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 28 May 2010 15:38:47 +0200 Subject: ide: Split ide_init1() off ide_init2() Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- hw/ide/core.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index c3334b121e..443ff10135 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2633,27 +2633,29 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version) ide_reset(s); } +static void ide_init1(IDEBus *bus, int unit, DriveInfo *dinfo) +{ + static int drive_serial = 1; + IDEState *s = &bus->ifs[unit]; + + s->bus = bus; + s->unit = unit; + s->drive_serial = drive_serial++; + s->io_buffer = qemu_blockalign(s->bs, IDE_DMA_BUF_SECTORS*512 + 4); + s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4; + s->smart_selftest_data = qemu_blockalign(s->bs, 512); + s->sector_write_timer = qemu_new_timer(vm_clock, + ide_sector_write_timer_cb, s); + ide_init_drive(s, dinfo, NULL); +} + void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1, qemu_irq irq) { - IDEState *s; - static int drive_serial = 1; int i; for(i = 0; i < 2; i++) { - s = bus->ifs + i; - s->bus = bus; - s->unit = i; - s->drive_serial = drive_serial++; - s->io_buffer = qemu_blockalign(s->bs, IDE_DMA_BUF_SECTORS*512 + 4); - s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4; - s->smart_selftest_data = qemu_blockalign(s->bs, 512); - s->sector_write_timer = qemu_new_timer(vm_clock, - ide_sector_write_timer_cb, s); - if (i == 0) - ide_init_drive(s, hd0, NULL); - if (i == 1) - ide_init_drive(s, hd1, NULL); + ide_init1(bus, i, i == 0 ? hd0 : hd1); } bus->irq = irq; } -- cgit v1.2.3 From 870111c8ed95df62a101eae0acd08c84233a6341 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 1 Jun 2010 20:32:28 +0200 Subject: ide: Change ide_init_drive() to require valid dinfo argument IDEState members drive_serial_str and version are now left empty until an actual drive is connected. Before, they got a default value that was overwritten when a drive got connected. Doesn't matter, because they're used only while a drive is connected. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- hw/ide/core.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index 443ff10135..cb7af388f1 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2601,30 +2601,29 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version) int cylinders, heads, secs; uint64_t nb_sectors; - if (dinfo && dinfo->bdrv) { - s->bs = dinfo->bdrv; - bdrv_get_geometry(s->bs, &nb_sectors); - bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs); - s->cylinders = cylinders; - s->heads = heads; - s->sectors = secs; - s->nb_sectors = nb_sectors; - /* The SMART values should be preserved across power cycles - but they aren't. */ - s->smart_enabled = 1; - s->smart_autosave = 1; - s->smart_errors = 0; - s->smart_selftest_count = 0; - if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { - s->is_cdrom = 1; - bdrv_set_change_cb(s->bs, cdrom_change_cb, s); - } - strncpy(s->drive_serial_str, drive_get_serial(s->bs), - sizeof(s->drive_serial_str)); + s->bs = dinfo->bdrv; + bdrv_get_geometry(s->bs, &nb_sectors); + bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs); + s->cylinders = cylinders; + s->heads = heads; + s->sectors = secs; + s->nb_sectors = nb_sectors; + /* The SMART values should be preserved across power cycles + but they aren't. */ + s->smart_enabled = 1; + s->smart_autosave = 1; + s->smart_errors = 0; + s->smart_selftest_count = 0; + if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { + s->is_cdrom = 1; + bdrv_set_change_cb(s->bs, cdrom_change_cb, s); } - if (strlen(s->drive_serial_str) == 0) + strncpy(s->drive_serial_str, drive_get_serial(s->bs), + sizeof(s->drive_serial_str)); + if (!*s->drive_serial_str) { snprintf(s->drive_serial_str, sizeof(s->drive_serial_str), "QM%05d", s->drive_serial); + } if (version) { pstrcpy(s->version, sizeof(s->version), version); } else { @@ -2646,7 +2645,11 @@ static void ide_init1(IDEBus *bus, int unit, DriveInfo *dinfo) s->smart_selftest_data = qemu_blockalign(s->bs, 512); s->sector_write_timer = qemu_new_timer(vm_clock, ide_sector_write_timer_cb, s); - ide_init_drive(s, dinfo, NULL); + if (dinfo) { + ide_init_drive(s, dinfo, NULL); + } else { + ide_reset(s); + } } void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1, -- cgit v1.2.3 From 57234ee40d314f91cf5bd16a926f30a6985e06e2 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 1 Jun 2010 20:32:29 +0200 Subject: ide: Split non-qdev code off ide_init2() Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- hw/ide/cmd646.c | 4 ++-- hw/ide/core.c | 30 ++++++++++++++++++++++-------- hw/ide/internal.h | 5 +++-- hw/ide/isa.c | 2 +- hw/ide/macio.c | 2 +- hw/ide/microdrive.c | 3 ++- hw/ide/mmio.c | 2 +- hw/ide/piix.c | 4 ++-- 8 files changed, 34 insertions(+), 18 deletions(-) diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index cdcc9bf1aa..559147ff43 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -260,8 +260,8 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev) irq = qemu_allocate_irqs(cmd646_set_irq, d, 2); ide_bus_new(&d->bus[0], &d->dev.qdev); ide_bus_new(&d->bus[1], &d->dev.qdev); - ide_init2(&d->bus[0], NULL, NULL, irq[0]); - ide_init2(&d->bus[1], NULL, NULL, irq[1]); + ide_init2(&d->bus[0], irq[0]); + ide_init2(&d->bus[1], irq[1]); vmstate_register(0, &vmstate_ide_pci, d); qemu_register_reset(cmd646_reset, d); diff --git a/hw/ide/core.c b/hw/ide/core.c index cb7af388f1..d3328cd02f 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2632,7 +2632,7 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version) ide_reset(s); } -static void ide_init1(IDEBus *bus, int unit, DriveInfo *dinfo) +static void ide_init1(IDEBus *bus, int unit) { static int drive_serial = 1; IDEState *s = &bus->ifs[unit]; @@ -2645,20 +2645,34 @@ static void ide_init1(IDEBus *bus, int unit, DriveInfo *dinfo) s->smart_selftest_data = qemu_blockalign(s->bs, 512); s->sector_write_timer = qemu_new_timer(vm_clock, ide_sector_write_timer_cb, s); - if (dinfo) { - ide_init_drive(s, dinfo, NULL); - } else { - ide_reset(s); +} + +void ide_init2(IDEBus *bus, qemu_irq irq) +{ + int i; + + for(i = 0; i < 2; i++) { + ide_init1(bus, i); + ide_reset(&bus->ifs[i]); } + bus->irq = irq; } -void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1, - qemu_irq irq) +/* TODO convert users to qdev and remove */ +void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, + DriveInfo *hd1, qemu_irq irq) { int i; + DriveInfo *dinfo; for(i = 0; i < 2; i++) { - ide_init1(bus, i, i == 0 ? hd0 : hd1); + dinfo = i == 0 ? hd0 : hd1; + ide_init1(bus, i); + if (dinfo) { + ide_init_drive(&bus->ifs[i], dinfo, NULL); + } else { + ide_reset(&bus->ifs[i]); + } } bus->irq = irq; } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index cf7101924d..6b0024d4c9 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -555,8 +555,9 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val); uint32_t ide_data_readl(void *opaque, uint32_t addr); void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version); -void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1, - qemu_irq irq); +void ide_init2(IDEBus *bus, qemu_irq irq); +void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, + DriveInfo *hd1, qemu_irq irq); void ide_init_ioport(IDEBus *bus, int iobase, int iobase2); /* hw/ide/qdev.c */ diff --git a/hw/ide/isa.c b/hw/ide/isa.c index dff7c796f7..b6c6347289 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -70,7 +70,7 @@ static int isa_ide_initfn(ISADevice *dev) ide_bus_new(&s->bus, &s->dev.qdev); ide_init_ioport(&s->bus, s->iobase, s->iobase2); isa_init_irq(dev, &s->irq, s->isairq); - ide_init2(&s->bus, NULL, NULL, s->irq); + ide_init2(&s->bus, s->irq); vmstate_register(0, &vmstate_ide_isa, s); return 0; }; diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 639f3f6a65..f76c0fa31c 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -314,7 +314,7 @@ int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq, int pmac_ide_memory; d = qemu_mallocz(sizeof(MACIOIDEState)); - ide_init2(&d->bus, hd_table[0], hd_table[1], irq); + ide_init2_with_non_qdev_drives(&d->bus, hd_table[0], hd_table[1], irq); if (dbdma) DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, pmac_ide_flush, d); diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index bfdb8c8b05..a7beac552a 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -539,7 +539,8 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv) md->card.cis = dscm1xxxx_cis; md->card.cis_len = sizeof(dscm1xxxx_cis); - ide_init2(&md->bus, bdrv, NULL, qemu_allocate_irqs(md_set_irq, md, 1)[0]); + ide_init2_with_non_qdev_drives(&md->bus, bdrv, NULL, + qemu_allocate_irqs(md_set_irq, md, 1)[0]); md->bus.ifs[0].is_cf = 1; md->bus.ifs[0].mdata_size = METADATA_SIZE; md->bus.ifs[0].mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE); diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c index cca883f613..e75cccf56e 100644 --- a/hw/ide/mmio.c +++ b/hw/ide/mmio.c @@ -125,7 +125,7 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2, MMIOState *s = qemu_mallocz(sizeof(MMIOState)); int mem1, mem2; - ide_init2(&s->bus, hd0, hd1, irq); + ide_init2_with_non_qdev_drives(&s->bus, hd0, hd1, irq); s->shift = shift; diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 4fa38519ef..dad6e86ff6 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -135,8 +135,8 @@ static int pci_piix_ide_initfn(PCIIDEState *d) ide_init_ioport(&d->bus[0], 0x1f0, 0x3f6); ide_init_ioport(&d->bus[1], 0x170, 0x376); - ide_init2(&d->bus[0], NULL, NULL, isa_reserve_irq(14)); - ide_init2(&d->bus[1], NULL, NULL, isa_reserve_irq(15)); + ide_init2(&d->bus[0], isa_reserve_irq(14)); + ide_init2(&d->bus[1], isa_reserve_irq(15)); return 0; } -- cgit v1.2.3 From cc98467327e13adca8f65b5a841c08930ee68220 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 1 Jun 2010 20:32:30 +0200 Subject: qdev: New qdev_prop_set_string() Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- hw/qdev-properties.c | 5 +++++ hw/qdev.h | 1 + 2 files changed, 6 insertions(+) diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 9ffdba792c..b6ee50fe2d 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -617,6 +617,11 @@ void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value) qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64); } +void qdev_prop_set_string(DeviceState *dev, const char *name, char *value) +{ + qdev_prop_set(dev, name, &value, PROP_TYPE_STRING); +} + void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value) { qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE); diff --git a/hw/qdev.h b/hw/qdev.h index a44060e54c..7c25a9414e 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -268,6 +268,7 @@ void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value); void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value); void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value); void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value); +void qdev_prop_set_string(DeviceState *dev, const char *name, char *value); void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value); void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value); void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value); -- cgit v1.2.3 From d21357df9a2a6b7e6bb2f579d04877f3bd65c557 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 1 Jun 2010 20:32:31 +0200 Subject: qdev: Don't leak string property value on hot unplug parse_string() qemu_strdup()s the property value. It is never freed. It needs to be freed along with the device. Otherwise, the value of scsi-disk property "ver" gets leaked when hot-unplugging the disk, for instance. Call new PropertyInfo method free() from qdev_free(). Implement it for qdev_prop_string. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- hw/qdev-properties.c | 6 ++++++ hw/qdev.c | 6 ++++++ hw/qdev.h | 1 + 3 files changed, 13 insertions(+) diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index b6ee50fe2d..48a6b45cda 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -260,6 +260,11 @@ static int parse_string(DeviceState *dev, Property *prop, const char *str) return 0; } +static void free_string(DeviceState *dev, Property *prop) +{ + qemu_free(*(char **)qdev_get_prop_ptr(dev, prop)); +} + static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len) { char **ptr = qdev_get_prop_ptr(dev, prop); @@ -274,6 +279,7 @@ PropertyInfo qdev_prop_string = { .size = sizeof(char*), .parse = parse_string, .print = print_string, + .free = free_string, }; /* --- drive --- */ diff --git a/hw/qdev.c b/hw/qdev.c index aa2ce0121d..29f6e9fcd5 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -334,6 +334,7 @@ void qdev_init_nofail(DeviceState *dev) void qdev_free(DeviceState *dev) { BusState *bus; + Property *prop; if (dev->state == DEV_STATE_INITIALIZED) { while (dev->num_child_bus) { @@ -349,6 +350,11 @@ void qdev_free(DeviceState *dev) } qemu_unregister_reset(qdev_reset, dev); QLIST_REMOVE(dev, sibling); + for (prop = dev->info->props; prop && prop->name; prop++) { + if (prop->info->free) { + prop->info->free(dev, prop); + } + } qemu_free(dev); } diff --git a/hw/qdev.h b/hw/qdev.h index 7c25a9414e..51a24e271c 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -98,6 +98,7 @@ struct PropertyInfo { enum PropertyType type; int (*parse)(DeviceState *dev, Property *prop, const char *str); int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len); + void (*free)(DeviceState *dev, Property *prop); }; typedef struct GlobalProperty { -- cgit v1.2.3 From 6ced55a57d7f6e647d683b5c41df0c176594f824 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 1 Jun 2010 20:32:32 +0200 Subject: ide: Turn drive serial into a qdev property ide-drive.serial It needs to be a qdev property, because it belongs to the drive's guest part. Bonus: info qtree now shows the serial number. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- hw/ide/core.c | 11 ++++++----- hw/ide/internal.h | 4 +++- hw/ide/qdev.c | 16 +++++++++++++++- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index d3328cd02f..70af1b6043 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2596,7 +2596,8 @@ void ide_bus_reset(IDEBus *bus) ide_clear_hob(bus); } -void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version) +void ide_init_drive(IDEState *s, DriveInfo *dinfo, + const char *version, const char *serial) { int cylinders, heads, secs; uint64_t nb_sectors; @@ -2618,9 +2619,9 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version) s->is_cdrom = 1; bdrv_set_change_cb(s->bs, cdrom_change_cb, s); } - strncpy(s->drive_serial_str, drive_get_serial(s->bs), - sizeof(s->drive_serial_str)); - if (!*s->drive_serial_str) { + if (serial && *serial) { + strncpy(s->drive_serial_str, serial, sizeof(s->drive_serial_str)); + } else { snprintf(s->drive_serial_str, sizeof(s->drive_serial_str), "QM%05d", s->drive_serial); } @@ -2669,7 +2670,7 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, dinfo = i == 0 ? hd0 : hd1; ide_init1(bus, i); if (dinfo) { - ide_init_drive(&bus->ifs[i], dinfo, NULL); + ide_init_drive(&bus->ifs[i], dinfo, NULL, dinfo->serial); } else { ide_reset(&bus->ifs[i]); } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 6b0024d4c9..eef1ee141d 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -457,6 +457,7 @@ struct IDEDevice { uint32_t unit; BlockConf conf; char *version; + char *serial; }; typedef int (*ide_qdev_initfn)(IDEDevice *dev); @@ -554,7 +555,8 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr); void ide_data_writel(void *opaque, uint32_t addr, uint32_t val); uint32_t ide_data_readl(void *opaque, uint32_t addr); -void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version); +void ide_init_drive(IDEState *s, DriveInfo *dinfo, + const char *version, const char *serial); void ide_init2(IDEBus *bus, qemu_irq irq); void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1, qemu_irq irq); diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 9ebb906cc3..5e549d9d2f 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -99,7 +99,20 @@ typedef struct IDEDrive { static int ide_drive_initfn(IDEDevice *dev) { IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus); - ide_init_drive(bus->ifs + dev->unit, dev->conf.dinfo, dev->version); + IDEState *s = bus->ifs + dev->unit; + const char *serial; + + serial = dev->serial; + if (!serial) { + /* try to fall back to value set with legacy -drive serial=... */ + serial = dev->conf.dinfo->serial; + } + + ide_init_drive(s, dev->conf.dinfo, dev->version, serial); + + if (!dev->serial) { + dev->serial = qemu_strdup(s->drive_serial_str); + } return 0; } @@ -111,6 +124,7 @@ static IDEDeviceInfo ide_drive_info = { DEFINE_PROP_UINT32("unit", IDEDrive, dev.unit, -1), DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf), DEFINE_PROP_STRING("ver", IDEDrive, dev.version), + DEFINE_PROP_STRING("serial", IDEDrive, dev.serial), DEFINE_PROP_END_OF_LIST(), } }; -- cgit v1.2.3 From 03432407256b8e39d76c9e6cd39dc553e7b646d8 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 1 Jun 2010 20:32:33 +0200 Subject: ide: Fix info qtree for ide-drive.ver Show the actual default value instead of when the property has not been set. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- hw/ide/qdev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 5e549d9d2f..6231d7716c 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -110,6 +110,9 @@ static int ide_drive_initfn(IDEDevice *dev) ide_init_drive(s, dev->conf.dinfo, dev->version, serial); + if (!dev->version) { + dev->version = qemu_strdup(s->version); + } if (!dev->serial) { dev->serial = qemu_strdup(s->drive_serial_str); } -- cgit v1.2.3 From a0fef654f6dec1348a074a17a6b809d0ba77b34e Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 1 Jun 2010 20:32:34 +0200 Subject: scsi: Turn drive serial into a qdev property scsi-disk.serial It needs to be a qdev property, because it belongs to the drive's guest part. Bonus: info qtree now shows the serial number. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- hw/scsi-disk.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 4d209197ce..e8c066adff 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -66,6 +66,7 @@ struct SCSIDiskState uint64_t max_lba; QEMUBH *bh; char *version; + char *serial; }; static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun) @@ -359,9 +360,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) case 0x80: /* Device serial number, optional */ { - const char *serial = req->dev->conf.dinfo->serial ? - req->dev->conf.dinfo->serial : "0"; - int l = strlen(serial); + int l = strlen(s->serial); if (l > req->cmd.xfer) l = req->cmd.xfer; @@ -371,7 +370,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) DPRINTF("Inquiry EVPD[Serial number] " "buffer size %zd\n", req->cmd.xfer); outbuf[buflen++] = l; - memcpy(outbuf+buflen, serial, l); + memcpy(outbuf+buflen, s->serial, l); buflen += l; break; } @@ -1058,6 +1057,15 @@ static int scsi_disk_initfn(SCSIDevice *dev) } s->bs = s->qdev.conf.dinfo->bdrv; + if (!s->serial) { + if (*dev->conf.dinfo->serial) { + /* try to fall back to value set with legacy -drive serial=... */ + s->serial = qemu_strdup(dev->conf.dinfo->serial); + } else { + s->serial = qemu_strdup("0"); + } + } + if (bdrv_is_sg(s->bs)) { error_report("scsi-disk: unwanted /dev/sg*"); return -1; @@ -1090,6 +1098,7 @@ static SCSIDeviceInfo scsi_disk_info = { .qdev.props = (Property[]) { DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf), DEFINE_PROP_STRING("ver", SCSIDiskState, version), + DEFINE_PROP_STRING("serial", SCSIDiskState, serial), DEFINE_PROP_END_OF_LIST(), }, }; -- cgit v1.2.3 From 552fee931bf52bf60f4210f607a78f415000f015 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 1 Jun 2010 20:32:35 +0200 Subject: scsi: Fix info qtree for scsi-disk.ver Show the actual default value instead of when the property has not been set. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- hw/scsi-disk.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index e8c066adff..a3559d1fcd 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -462,8 +462,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf) } memcpy(&outbuf[8], "QEMU ", 8); memset(&outbuf[32], 0, 4); - memcpy(&outbuf[32], s->version ? s->version : QEMU_VERSION, - MIN(4, strlen(s->version ? s->version : QEMU_VERSION))); + memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version))); /* * We claim conformance to SPC-3, which is required for guests * to ask for modern features like READ CAPACITY(16) or the @@ -1066,6 +1065,10 @@ static int scsi_disk_initfn(SCSIDevice *dev) } } + if (!s->version) { + s->version = qemu_strdup(QEMU_VERSION); + } + if (bdrv_is_sg(s->bs)) { error_report("scsi-disk: unwanted /dev/sg*"); return -1; -- cgit v1.2.3 From 236f1f672ca4b5dea70c0c101036224297c53895 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 1 Jun 2010 13:20:57 +0200 Subject: Fix error message in drive_init The real error is the return value of bdrv_open. errno might be overwritten or not even set to that value in the first place. Signed-off-by: Kevin Wolf --- vl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vl.c b/vl.c index 76a9b25569..2769d1a4bc 100644 --- a/vl.c +++ b/vl.c @@ -789,6 +789,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque, const char *devaddr; DriveInfo *dinfo; int snapshot = 0; + int ret; *fatal_error = 1; @@ -1119,9 +1120,10 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque, bdrv_flags |= ro ? 0 : BDRV_O_RDWR; - if (bdrv_open(dinfo->bdrv, file, bdrv_flags, drv) < 0) { + ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv); + if (ret < 0) { fprintf(stderr, "qemu: could not open disk image %s: %s\n", - file, strerror(errno)); + file, strerror(-ret)); return NULL; } -- cgit v1.2.3 From 08a00559f00975cebcb3f844fe7c708d65b6a3b3 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 1 Jun 2010 18:37:31 +0200 Subject: block: Assume raw for drives without media qemu -cdrom /dev/cdrom with an empty CD-ROM drive doesn't work any more because we try to guess the format and when this fails (because there is no medium) we exit with an error message. This patch should restore the old behaviour by assuming raw format for such drives. Signed-off-by: Kevin Wolf --- block.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block.c b/block.c index 9c43332f4f..ecd98675a5 100644 --- a/block.c +++ b/block.c @@ -331,8 +331,8 @@ static BlockDriver *find_image_format(const char *filename) if (ret < 0) return NULL; - /* Return the raw BlockDriver * to scsi-generic devices */ - if (bs->sg) { + /* Return the raw BlockDriver * to scsi-generic devices or empty drives */ + if (bs->sg || !bdrv_is_inserted(bs)) { bdrv_delete(bs); return bdrv_find_format("raw"); } -- cgit v1.2.3 From 2bc93fed76c89f7adaa0e5bb357dcdc6c2b097a8 Mon Sep 17 00:00:00 2001 From: MORITA Kazutaka Date: Fri, 28 May 2010 11:44:57 +0900 Subject: close all the block drivers before the qemu process exits This patch calls the close handler of the block driver before the qemu process exits. This is necessary because the sheepdog block driver releases the lock of VM images in the close handler. Signed-off-by: MORITA Kazutaka Signed-off-by: Kevin Wolf --- block.c | 9 +++++++++ block.h | 1 + vl.c | 1 + 3 files changed, 11 insertions(+) diff --git a/block.c b/block.c index ecd98675a5..b1ef85c8da 100644 --- a/block.c +++ b/block.c @@ -648,6 +648,15 @@ void bdrv_close(BlockDriverState *bs) } } +void bdrv_close_all(void) +{ + BlockDriverState *bs; + + QTAILQ_FOREACH(bs, &bdrv_states, list) { + bdrv_close(bs); + } +} + void bdrv_delete(BlockDriverState *bs) { /* remove from list, if necessary */ diff --git a/block.h b/block.h index 756670d22f..25744b134f 100644 --- a/block.h +++ b/block.h @@ -123,6 +123,7 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs, /* Ensure contents are flushed to disk. */ void bdrv_flush(BlockDriverState *bs); void bdrv_flush_all(void); +void bdrv_close_all(void); int bdrv_has_zero_init(BlockDriverState *bs); int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, diff --git a/vl.c b/vl.c index 2769d1a4bc..551138f0cc 100644 --- a/vl.c +++ b/vl.c @@ -1991,6 +1991,7 @@ static void main_loop(void) vm_stop(r); } } + bdrv_close_all(); pause_all_vcpus(); } -- cgit v1.2.3 From 7cdb1f6d305e1000b5f882257cbee71b8bb08ef5 Mon Sep 17 00:00:00 2001 From: MORITA Kazutaka Date: Fri, 28 May 2010 11:44:58 +0900 Subject: block: call the snapshot handlers of the protocol drivers When snapshot handlers are not defined in the format driver, it is better to call the ones of the protocol driver. This enables us to implement snapshot support in the protocol driver. We need to call bdrv_close() and bdrv_open() handlers of the format driver before and after bdrv_snapshot_goto() call of the protocol. It is because the contents of the block driver state may need to be changed after loading vmstate. Signed-off-by: MORITA Kazutaka Signed-off-by: Kevin Wolf --- block.c | 61 +++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/block.c b/block.c index b1ef85c8da..cacf11bd99 100644 --- a/block.c +++ b/block.c @@ -1631,9 +1631,11 @@ int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, BlockDriver *drv = bs->drv; if (!drv) return -ENOMEDIUM; - if (!drv->bdrv_save_vmstate) - return -ENOTSUP; - return drv->bdrv_save_vmstate(bs, buf, pos, size); + if (drv->bdrv_save_vmstate) + return drv->bdrv_save_vmstate(bs, buf, pos, size); + if (bs->file) + return bdrv_save_vmstate(bs->file, buf, pos, size); + return -ENOTSUP; } int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf, @@ -1642,9 +1644,11 @@ int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf, BlockDriver *drv = bs->drv; if (!drv) return -ENOMEDIUM; - if (!drv->bdrv_load_vmstate) - return -ENOTSUP; - return drv->bdrv_load_vmstate(bs, buf, pos, size); + if (drv->bdrv_load_vmstate) + return drv->bdrv_load_vmstate(bs, buf, pos, size); + if (bs->file) + return bdrv_load_vmstate(bs->file, buf, pos, size); + return -ENOTSUP; } void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event) @@ -1668,20 +1672,37 @@ int bdrv_snapshot_create(BlockDriverState *bs, BlockDriver *drv = bs->drv; if (!drv) return -ENOMEDIUM; - if (!drv->bdrv_snapshot_create) - return -ENOTSUP; - return drv->bdrv_snapshot_create(bs, sn_info); + if (drv->bdrv_snapshot_create) + return drv->bdrv_snapshot_create(bs, sn_info); + if (bs->file) + return bdrv_snapshot_create(bs->file, sn_info); + return -ENOTSUP; } int bdrv_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) { BlockDriver *drv = bs->drv; + int ret, open_ret; + if (!drv) return -ENOMEDIUM; - if (!drv->bdrv_snapshot_goto) - return -ENOTSUP; - return drv->bdrv_snapshot_goto(bs, snapshot_id); + if (drv->bdrv_snapshot_goto) + return drv->bdrv_snapshot_goto(bs, snapshot_id); + + if (bs->file) { + drv->bdrv_close(bs); + ret = bdrv_snapshot_goto(bs->file, snapshot_id); + open_ret = drv->bdrv_open(bs, bs->open_flags); + if (open_ret < 0) { + bdrv_delete(bs->file); + bs->drv = NULL; + return open_ret; + } + return ret; + } + + return -ENOTSUP; } int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id) @@ -1689,9 +1710,11 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id) BlockDriver *drv = bs->drv; if (!drv) return -ENOMEDIUM; - if (!drv->bdrv_snapshot_delete) - return -ENOTSUP; - return drv->bdrv_snapshot_delete(bs, snapshot_id); + if (drv->bdrv_snapshot_delete) + return drv->bdrv_snapshot_delete(bs, snapshot_id); + if (bs->file) + return bdrv_snapshot_delete(bs->file, snapshot_id); + return -ENOTSUP; } int bdrv_snapshot_list(BlockDriverState *bs, @@ -1700,9 +1723,11 @@ int bdrv_snapshot_list(BlockDriverState *bs, BlockDriver *drv = bs->drv; if (!drv) return -ENOMEDIUM; - if (!drv->bdrv_snapshot_list) - return -ENOTSUP; - return drv->bdrv_snapshot_list(bs, psn_info); + if (drv->bdrv_snapshot_list) + return drv->bdrv_snapshot_list(bs, psn_info); + if (bs->file) + return bdrv_snapshot_list(bs->file, psn_info); + return -ENOTSUP; } #define NB_SUFFIXES 4 -- cgit v1.2.3 From a803cb8eb8ada1add74f1b393b8a553a7e7f3acf Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 2 Jun 2010 13:31:55 +0200 Subject: blockdev: Hide QEMUMachine from drive_init() To pave the way for moving it out of vl.c. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- hw/device-hotplug.c | 2 +- hw/usb-msd.c | 2 +- sysemu.h | 3 ++- vl.c | 12 +++++------- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c index 9cc8376691..a3fe99ea77 100644 --- a/hw/device-hotplug.c +++ b/hw/device-hotplug.c @@ -38,7 +38,7 @@ DriveInfo *add_init_drive(const char *optstr) if (!opts) return NULL; - dinfo = drive_init(opts, current_machine, &fatal_error); + dinfo = drive_init(opts, current_machine->use_scsi, &fatal_error); if (!dinfo) { qemu_opts_del(opts); return NULL; diff --git a/hw/usb-msd.c b/hw/usb-msd.c index c1c2537475..0ba4a64d7c 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -584,7 +584,7 @@ static USBDevice *usb_msd_init(const char *filename) qemu_opt_set(opts, "if", "none"); /* create host drive */ - dinfo = drive_init(opts, NULL, &fatal_error); + dinfo = drive_init(opts, 0, &fatal_error); if (!dinfo) { qemu_opts_del(opts); return NULL; diff --git a/sysemu.h b/sysemu.h index fd83b7dc1c..46a1b2f87f 100644 --- a/sysemu.h +++ b/sysemu.h @@ -191,7 +191,8 @@ extern BlockInterfaceErrorAction drive_get_on_error( BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type); extern QemuOpts *drive_add(const char *file, const char *fmt, ...); -extern DriveInfo *drive_init(QemuOpts *arg, void *machine, int *fatal_error); +extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi, + int *fatal_error); /* device-hotplug */ diff --git a/vl.c b/vl.c index 551138f0cc..db1fefd3ff 100644 --- a/vl.c +++ b/vl.c @@ -767,8 +767,7 @@ static int parse_block_error_action(const char *buf, int is_read) } } -DriveInfo *drive_init(QemuOpts *opts, void *opaque, - int *fatal_error) +DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error) { const char *buf; const char *file = NULL; @@ -780,7 +779,6 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque, int bus_id, unit_id; int cyls, heads, secs, translation; BlockDriver *drv = NULL; - QEMUMachine *machine = opaque; int max_devs; int index; int ro = 0; @@ -795,7 +793,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque, translation = BIOS_ATA_TRANSLATION_AUTO; - if (machine && machine->use_scsi) { + if (default_to_scsi) { type = IF_SCSI; max_devs = MAX_SCSI_DEVS; pstrcpy(devname, sizeof(devname), "scsi"); @@ -1135,10 +1133,10 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque, static int drive_init_func(QemuOpts *opts, void *opaque) { - QEMUMachine *machine = opaque; + int *use_scsi = opaque; int fatal_error = 0; - if (drive_init(opts, machine, &fatal_error) == NULL) { + if (drive_init(opts, *use_scsi, &fatal_error) == NULL) { if (fatal_error) return 1; } @@ -3641,7 +3639,7 @@ int main(int argc, char **argv, char **envp) /* open the virtual block devices */ if (snapshot) qemu_opts_foreach(&qemu_drive_opts, drive_enable_snapshot, NULL, 0); - if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, machine, 1) != 0) + if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0) exit(1); register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL, -- cgit v1.2.3 From 7b370f513002b340a383fac961dc8c6fdf39eddc Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 2 Jun 2010 13:31:56 +0200 Subject: qdev: Move declaration of qdev_init_bdrv() into qdev.h Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- hw/pl181.c | 1 - hw/qdev.h | 2 ++ hw/ssi-sd.c | 1 - sysemu.h | 2 -- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/pl181.c b/hw/pl181.c index 1924053330..85cadc4fe1 100644 --- a/hw/pl181.c +++ b/hw/pl181.c @@ -9,7 +9,6 @@ #include "sysbus.h" #include "sd.h" -#include "sysemu.h" //#define DEBUG_PL181 1 diff --git a/hw/qdev.h b/hw/qdev.h index 51a24e271c..0ad6c9567d 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -125,6 +125,8 @@ void qdev_machine_creation_done(void); qemu_irq qdev_get_gpio_in(DeviceState *dev, int n); void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); +BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type); + BusState *qdev_get_child_bus(DeviceState *dev, const char *name); /*** Device API. ***/ diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c index 5e74e5d7ce..96b33edcbd 100644 --- a/hw/ssi-sd.c +++ b/hw/ssi-sd.c @@ -9,7 +9,6 @@ #include "ssi.h" #include "sd.h" -#include "sysemu.h" //#define DEBUG_SSI_SD 1 diff --git a/sysemu.h b/sysemu.h index 46a1b2f87f..dce13c1a05 100644 --- a/sysemu.h +++ b/sysemu.h @@ -188,8 +188,6 @@ extern const char *drive_get_serial(BlockDriverState *bdrv); extern BlockInterfaceErrorAction drive_get_on_error( BlockDriverState *bdrv, int is_read); -BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type); - extern QemuOpts *drive_add(const char *file, const char *fmt, ...); extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi, int *fatal_error); -- cgit v1.2.3 From 666daa68234b5b1758652633cab07d5ca6046a5b Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 2 Jun 2010 18:48:27 +0200 Subject: blockdev: Collect block device code in new blockdev.c Anything that moves hundreds of lines out of vl.c can't be all bad. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- Makefile.objs | 2 +- blockdev.c | 600 +++++++++++++++++++++++++++++++++++++++++++++++++++ blockdev.h | 71 ++++++ hw/acpi_piix4.c | 1 + hw/apb_pci.c | 1 + hw/device-hotplug.c | 2 - hw/fdc.c | 1 - hw/fdc.h | 2 +- hw/ide/core.c | 2 - hw/ide/qdev.c | 1 - hw/lan9118.c | 1 + hw/nand.c | 3 +- hw/omap2.c | 2 + hw/onenand.c | 3 +- hw/parallel.c | 1 + hw/pc.c | 1 + hw/pc_piix.c | 1 + hw/pci-hotplug.c | 2 - hw/pcmcia.h | 2 +- hw/qdev-properties.c | 1 - hw/qdev.h | 2 +- hw/scsi-bus.c | 1 - hw/scsi-disk.c | 2 +- hw/scsi-generic.c | 1 - hw/serial.c | 1 + hw/usb-hid.c | 1 + hw/usb-msd.c | 2 +- hw/virtio-blk.c | 2 - hw/virtio-pci.c | 1 - monitor.c | 104 +-------- qemu-char.c | 1 - savevm.c | 2 +- sysemu.h | 49 ----- vl.c | 483 +---------------------------------------- 34 files changed, 692 insertions(+), 660 deletions(-) create mode 100644 blockdev.c create mode 100644 blockdev.h diff --git a/Makefile.objs b/Makefile.objs index 9796dcbd16..54dec26f4f 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -44,7 +44,7 @@ fsdev-obj-$(CONFIG_LINUX) += $(addprefix fsdev/, $(fsdev-nested-y)) # system emulation, i.e. a single QEMU executable should support all # CPUs and machines. -common-obj-y = $(block-obj-y) +common-obj-y = $(block-obj-y) blockdev.o common-obj-y += $(net-obj-y) common-obj-y += $(qobject-obj-y) common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX)) diff --git a/blockdev.c b/blockdev.c new file mode 100644 index 0000000000..bd9783affd --- /dev/null +++ b/blockdev.c @@ -0,0 +1,600 @@ +/* + * QEMU host block devices + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ + +#include "block.h" +#include "blockdev.h" +#include "monitor.h" +#include "qerror.h" +#include "qemu-option.h" +#include "qemu-config.h" +#include "sysemu.h" + +struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives); + +QemuOpts *drive_add(const char *file, const char *fmt, ...) +{ + va_list ap; + char optstr[1024]; + QemuOpts *opts; + + va_start(ap, fmt); + vsnprintf(optstr, sizeof(optstr), fmt, ap); + va_end(ap); + + opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0); + if (!opts) { + return NULL; + } + if (file) + qemu_opt_set(opts, "file", file); + return opts; +} + +DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) +{ + DriveInfo *dinfo; + + /* seek interface, bus and unit */ + + QTAILQ_FOREACH(dinfo, &drives, next) { + if (dinfo->type == type && + dinfo->bus == bus && + dinfo->unit == unit) + return dinfo; + } + + return NULL; +} + +DriveInfo *drive_get_by_id(const char *id) +{ + DriveInfo *dinfo; + + QTAILQ_FOREACH(dinfo, &drives, next) { + if (strcmp(id, dinfo->id)) + continue; + return dinfo; + } + return NULL; +} + +int drive_get_max_bus(BlockInterfaceType type) +{ + int max_bus; + DriveInfo *dinfo; + + max_bus = -1; + QTAILQ_FOREACH(dinfo, &drives, next) { + if(dinfo->type == type && + dinfo->bus > max_bus) + max_bus = dinfo->bus; + } + return max_bus; +} + +const char *drive_get_serial(BlockDriverState *bdrv) +{ + DriveInfo *dinfo; + + QTAILQ_FOREACH(dinfo, &drives, next) { + if (dinfo->bdrv == bdrv) + return dinfo->serial; + } + + return "\0"; +} + +BlockInterfaceErrorAction drive_get_on_error( + BlockDriverState *bdrv, int is_read) +{ + DriveInfo *dinfo; + + QTAILQ_FOREACH(dinfo, &drives, next) { + if (dinfo->bdrv == bdrv) + return is_read ? dinfo->on_read_error : dinfo->on_write_error; + } + + return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC; +} + +static void bdrv_format_print(void *opaque, const char *name) +{ + fprintf(stderr, " %s", name); +} + +void drive_uninit(DriveInfo *dinfo) +{ + qemu_opts_del(dinfo->opts); + bdrv_delete(dinfo->bdrv); + QTAILQ_REMOVE(&drives, dinfo, next); + qemu_free(dinfo); +} + +static int parse_block_error_action(const char *buf, int is_read) +{ + if (!strcmp(buf, "ignore")) { + return BLOCK_ERR_IGNORE; + } else if (!is_read && !strcmp(buf, "enospc")) { + return BLOCK_ERR_STOP_ENOSPC; + } else if (!strcmp(buf, "stop")) { + return BLOCK_ERR_STOP_ANY; + } else if (!strcmp(buf, "report")) { + return BLOCK_ERR_REPORT; + } else { + fprintf(stderr, "qemu: '%s' invalid %s error action\n", + buf, is_read ? "read" : "write"); + return -1; + } +} + +DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error) +{ + const char *buf; + const char *file = NULL; + char devname[128]; + const char *serial; + const char *mediastr = ""; + BlockInterfaceType type; + enum { MEDIA_DISK, MEDIA_CDROM } media; + int bus_id, unit_id; + int cyls, heads, secs, translation; + BlockDriver *drv = NULL; + int max_devs; + int index; + int ro = 0; + int bdrv_flags = 0; + int on_read_error, on_write_error; + const char *devaddr; + DriveInfo *dinfo; + int snapshot = 0; + int ret; + + *fatal_error = 1; + + translation = BIOS_ATA_TRANSLATION_AUTO; + + if (default_to_scsi) { + type = IF_SCSI; + max_devs = MAX_SCSI_DEVS; + pstrcpy(devname, sizeof(devname), "scsi"); + } else { + type = IF_IDE; + max_devs = MAX_IDE_DEVS; + pstrcpy(devname, sizeof(devname), "ide"); + } + media = MEDIA_DISK; + + /* extract parameters */ + bus_id = qemu_opt_get_number(opts, "bus", 0); + unit_id = qemu_opt_get_number(opts, "unit", -1); + index = qemu_opt_get_number(opts, "index", -1); + + cyls = qemu_opt_get_number(opts, "cyls", 0); + heads = qemu_opt_get_number(opts, "heads", 0); + secs = qemu_opt_get_number(opts, "secs", 0); + + snapshot = qemu_opt_get_bool(opts, "snapshot", 0); + ro = qemu_opt_get_bool(opts, "readonly", 0); + + file = qemu_opt_get(opts, "file"); + serial = qemu_opt_get(opts, "serial"); + + if ((buf = qemu_opt_get(opts, "if")) != NULL) { + pstrcpy(devname, sizeof(devname), buf); + if (!strcmp(buf, "ide")) { + type = IF_IDE; + max_devs = MAX_IDE_DEVS; + } else if (!strcmp(buf, "scsi")) { + type = IF_SCSI; + max_devs = MAX_SCSI_DEVS; + } else if (!strcmp(buf, "floppy")) { + type = IF_FLOPPY; + max_devs = 0; + } else if (!strcmp(buf, "pflash")) { + type = IF_PFLASH; + max_devs = 0; + } else if (!strcmp(buf, "mtd")) { + type = IF_MTD; + max_devs = 0; + } else if (!strcmp(buf, "sd")) { + type = IF_SD; + max_devs = 0; + } else if (!strcmp(buf, "virtio")) { + type = IF_VIRTIO; + max_devs = 0; + } else if (!strcmp(buf, "xen")) { + type = IF_XEN; + max_devs = 0; + } else if (!strcmp(buf, "none")) { + type = IF_NONE; + max_devs = 0; + } else { + fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf); + return NULL; + } + } + + if (cyls || heads || secs) { + if (cyls < 1 || (type == IF_IDE && cyls > 16383)) { + fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf); + return NULL; + } + if (heads < 1 || (type == IF_IDE && heads > 16)) { + fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf); + return NULL; + } + if (secs < 1 || (type == IF_IDE && secs > 63)) { + fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf); + return NULL; + } + } + + if ((buf = qemu_opt_get(opts, "trans")) != NULL) { + if (!cyls) { + fprintf(stderr, + "qemu: '%s' trans must be used with cyls,heads and secs\n", + buf); + return NULL; + } + if (!strcmp(buf, "none")) + translation = BIOS_ATA_TRANSLATION_NONE; + else if (!strcmp(buf, "lba")) + translation = BIOS_ATA_TRANSLATION_LBA; + else if (!strcmp(buf, "auto")) + translation = BIOS_ATA_TRANSLATION_AUTO; + else { + fprintf(stderr, "qemu: '%s' invalid translation type\n", buf); + return NULL; + } + } + + if ((buf = qemu_opt_get(opts, "media")) != NULL) { + if (!strcmp(buf, "disk")) { + media = MEDIA_DISK; + } else if (!strcmp(buf, "cdrom")) { + if (cyls || secs || heads) { + fprintf(stderr, + "qemu: '%s' invalid physical CHS format\n", buf); + return NULL; + } + media = MEDIA_CDROM; + } else { + fprintf(stderr, "qemu: '%s' invalid media\n", buf); + return NULL; + } + } + + if ((buf = qemu_opt_get(opts, "cache")) != NULL) { + if (!strcmp(buf, "off") || !strcmp(buf, "none")) { + bdrv_flags |= BDRV_O_NOCACHE; + } else if (!strcmp(buf, "writeback")) { + bdrv_flags |= BDRV_O_CACHE_WB; + } else if (!strcmp(buf, "unsafe")) { + bdrv_flags |= BDRV_O_CACHE_WB; + bdrv_flags |= BDRV_O_NO_FLUSH; + } else if (!strcmp(buf, "writethrough")) { + /* this is the default */ + } else { + fprintf(stderr, "qemu: invalid cache option\n"); + return NULL; + } + } + +#ifdef CONFIG_LINUX_AIO + if ((buf = qemu_opt_get(opts, "aio")) != NULL) { + if (!strcmp(buf, "native")) { + bdrv_flags |= BDRV_O_NATIVE_AIO; + } else if (!strcmp(buf, "threads")) { + /* this is the default */ + } else { + fprintf(stderr, "qemu: invalid aio option\n"); + return NULL; + } + } +#endif + + if ((buf = qemu_opt_get(opts, "format")) != NULL) { + if (strcmp(buf, "?") == 0) { + fprintf(stderr, "qemu: Supported formats:"); + bdrv_iterate_format(bdrv_format_print, NULL); + fprintf(stderr, "\n"); + return NULL; + } + drv = bdrv_find_whitelisted_format(buf); + if (!drv) { + fprintf(stderr, "qemu: '%s' invalid format\n", buf); + return NULL; + } + } + + on_write_error = BLOCK_ERR_STOP_ENOSPC; + if ((buf = qemu_opt_get(opts, "werror")) != NULL) { + if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) { + fprintf(stderr, "werror is no supported by this format\n"); + return NULL; + } + + on_write_error = parse_block_error_action(buf, 0); + if (on_write_error < 0) { + return NULL; + } + } + + on_read_error = BLOCK_ERR_REPORT; + if ((buf = qemu_opt_get(opts, "rerror")) != NULL) { + if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) { + fprintf(stderr, "rerror is no supported by this format\n"); + return NULL; + } + + on_read_error = parse_block_error_action(buf, 1); + if (on_read_error < 0) { + return NULL; + } + } + + if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) { + if (type != IF_VIRTIO) { + fprintf(stderr, "addr is not supported\n"); + return NULL; + } + } + + /* compute bus and unit according index */ + + if (index != -1) { + if (bus_id != 0 || unit_id != -1) { + fprintf(stderr, + "qemu: index cannot be used with bus and unit\n"); + return NULL; + } + if (max_devs == 0) + { + unit_id = index; + bus_id = 0; + } else { + unit_id = index % max_devs; + bus_id = index / max_devs; + } + } + + /* if user doesn't specify a unit_id, + * try to find the first free + */ + + if (unit_id == -1) { + unit_id = 0; + while (drive_get(type, bus_id, unit_id) != NULL) { + unit_id++; + if (max_devs && unit_id >= max_devs) { + unit_id -= max_devs; + bus_id++; + } + } + } + + /* check unit id */ + + if (max_devs && unit_id >= max_devs) { + fprintf(stderr, "qemu: unit %d too big (max is %d)\n", + unit_id, max_devs - 1); + return NULL; + } + + /* + * ignore multiple definitions + */ + + if (drive_get(type, bus_id, unit_id) != NULL) { + *fatal_error = 0; + return NULL; + } + + /* init */ + + dinfo = qemu_mallocz(sizeof(*dinfo)); + if ((buf = qemu_opts_id(opts)) != NULL) { + dinfo->id = qemu_strdup(buf); + } else { + /* no id supplied -> create one */ + dinfo->id = qemu_mallocz(32); + if (type == IF_IDE || type == IF_SCSI) + mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd"; + if (max_devs) + snprintf(dinfo->id, 32, "%s%i%s%i", + devname, bus_id, mediastr, unit_id); + else + snprintf(dinfo->id, 32, "%s%s%i", + devname, mediastr, unit_id); + } + dinfo->bdrv = bdrv_new(dinfo->id); + dinfo->devaddr = devaddr; + dinfo->type = type; + dinfo->bus = bus_id; + dinfo->unit = unit_id; + dinfo->on_read_error = on_read_error; + dinfo->on_write_error = on_write_error; + dinfo->opts = opts; + if (serial) + strncpy(dinfo->serial, serial, sizeof(serial)); + QTAILQ_INSERT_TAIL(&drives, dinfo, next); + + switch(type) { + case IF_IDE: + case IF_SCSI: + case IF_XEN: + case IF_NONE: + switch(media) { + case MEDIA_DISK: + if (cyls != 0) { + bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs); + bdrv_set_translation_hint(dinfo->bdrv, translation); + } + break; + case MEDIA_CDROM: + bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM); + break; + } + break; + case IF_SD: + /* FIXME: This isn't really a floppy, but it's a reasonable + approximation. */ + case IF_FLOPPY: + bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY); + break; + case IF_PFLASH: + case IF_MTD: + break; + case IF_VIRTIO: + /* add virtio block device */ + opts = qemu_opts_create(&qemu_device_opts, NULL, 0); + qemu_opt_set(opts, "driver", "virtio-blk-pci"); + qemu_opt_set(opts, "drive", dinfo->id); + if (devaddr) + qemu_opt_set(opts, "addr", devaddr); + break; + case IF_COUNT: + abort(); + } + if (!file) { + *fatal_error = 0; + return NULL; + } + if (snapshot) { + /* always use cache=unsafe with snapshot */ + bdrv_flags &= ~BDRV_O_CACHE_MASK; + bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH); + } + + if (media == MEDIA_CDROM) { + /* CDROM is fine for any interface, don't check. */ + ro = 1; + } else if (ro == 1) { + if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) { + fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n"); + return NULL; + } + } + + bdrv_flags |= ro ? 0 : BDRV_O_RDWR; + + ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv); + if (ret < 0) { + fprintf(stderr, "qemu: could not open disk image %s: %s\n", + file, strerror(-ret)); + return NULL; + } + + if (bdrv_key_required(dinfo->bdrv)) + autostart = 0; + *fatal_error = 0; + return dinfo; +} + +void do_commit(Monitor *mon, const QDict *qdict) +{ + int all_devices; + DriveInfo *dinfo; + const char *device = qdict_get_str(qdict, "device"); + + all_devices = !strcmp(device, "all"); + QTAILQ_FOREACH(dinfo, &drives, next) { + if (!all_devices) + if (strcmp(bdrv_get_device_name(dinfo->bdrv), device)) + continue; + bdrv_commit(dinfo->bdrv); + } +} + +static int eject_device(Monitor *mon, BlockDriverState *bs, int force) +{ + if (bdrv_is_inserted(bs)) { + if (!force) { + if (!bdrv_is_removable(bs)) { + qerror_report(QERR_DEVICE_NOT_REMOVABLE, + bdrv_get_device_name(bs)); + return -1; + } + if (bdrv_is_locked(bs)) { + qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs)); + return -1; + } + } + bdrv_close(bs); + } + return 0; +} + +int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + BlockDriverState *bs; + int force = qdict_get_int(qdict, "force"); + const char *filename = qdict_get_str(qdict, "device"); + + bs = bdrv_find(filename); + if (!bs) { + qerror_report(QERR_DEVICE_NOT_FOUND, filename); + return -1; + } + return eject_device(mon, bs, force); +} + +int do_block_set_passwd(Monitor *mon, const QDict *qdict, + QObject **ret_data) +{ + BlockDriverState *bs; + int err; + + bs = bdrv_find(qdict_get_str(qdict, "device")); + if (!bs) { + qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device")); + return -1; + } + + err = bdrv_set_key(bs, qdict_get_str(qdict, "password")); + if (err == -EINVAL) { + qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs)); + return -1; + } else if (err < 0) { + qerror_report(QERR_INVALID_PASSWORD); + return -1; + } + + return 0; +} + +int do_change_block(Monitor *mon, const char *device, + const char *filename, const char *fmt) +{ + BlockDriverState *bs; + BlockDriver *drv = NULL; + int bdrv_flags; + + bs = bdrv_find(device); + if (!bs) { + qerror_report(QERR_DEVICE_NOT_FOUND, device); + return -1; + } + if (fmt) { + drv = bdrv_find_whitelisted_format(fmt); + if (!drv) { + qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt); + return -1; + } + } + if (eject_device(mon, bs, 0) < 0) { + return -1; + } + bdrv_flags = bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM ? 0 : BDRV_O_RDWR; + if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) { + qerror_report(QERR_OPEN_FILE_FAILED, filename); + return -1; + } + return monitor_read_bdrv_key_start(mon, bs, NULL, NULL); +} diff --git a/blockdev.h b/blockdev.h new file mode 100644 index 0000000000..dfc9de19ae --- /dev/null +++ b/blockdev.h @@ -0,0 +1,71 @@ +/* + * QEMU host block devices + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ + +#ifndef BLOCKDEV_H +#define BLOCKDEV_H + +#include "block.h" +#include "qemu-queue.h" + +typedef enum { + IF_NONE, + IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN, + IF_COUNT +} BlockInterfaceType; + +typedef enum { + BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC, + BLOCK_ERR_STOP_ANY +} BlockInterfaceErrorAction; + +#define BLOCK_SERIAL_STRLEN 20 + +typedef struct DriveInfo { + BlockDriverState *bdrv; + char *id; + const char *devaddr; + BlockInterfaceType type; + int bus; + int unit; + QemuOpts *opts; + BlockInterfaceErrorAction on_read_error; + BlockInterfaceErrorAction on_write_error; + char serial[BLOCK_SERIAL_STRLEN + 1]; + QTAILQ_ENTRY(DriveInfo) next; +} DriveInfo; + +#define MAX_IDE_DEVS 2 +#define MAX_SCSI_DEVS 7 + +extern QTAILQ_HEAD(drivelist, DriveInfo) drives; + +extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); +extern DriveInfo *drive_get_by_id(const char *id); +extern int drive_get_max_bus(BlockInterfaceType type); +extern void drive_uninit(DriveInfo *dinfo); +extern const char *drive_get_serial(BlockDriverState *bdrv); + +extern BlockInterfaceErrorAction drive_get_on_error( + BlockDriverState *bdrv, int is_read); + +extern QemuOpts *drive_add(const char *file, const char *fmt, ...); +extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi, + int *fatal_error); + +/* device-hotplug */ + +DriveInfo *add_init_drive(const char *opts); + +void do_commit(Monitor *mon, const QDict *qdict); +int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data); +int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data); +int do_change_block(Monitor *mon, const char *device, + const char *filename, const char *fmt); + +#endif diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 0fce958d07..a87286b917 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -21,6 +21,7 @@ #include "pm_smbus.h" #include "pci.h" #include "acpi.h" +#include "sysemu.h" //#define DEBUG diff --git a/hw/apb_pci.c b/hw/apb_pci.c index b53e3c3bf9..31c8d705a2 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -31,6 +31,7 @@ #include "pci_host.h" #include "rwhandler.h" #include "apb_pci.h" +#include "sysemu.h" /* debug APB */ //#define DEBUG_APB diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c index a3fe99ea77..c1a9a561d7 100644 --- a/hw/device-hotplug.c +++ b/hw/device-hotplug.c @@ -25,8 +25,6 @@ #include "hw.h" #include "boards.h" #include "net.h" -#include "block_int.h" -#include "sysemu.h" DriveInfo *add_init_drive(const char *optstr) { diff --git a/hw/fdc.c b/hw/fdc.c index 6306496383..b97895786a 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -29,7 +29,6 @@ #include "hw.h" #include "fdc.h" -#include "block.h" #include "qemu-timer.h" #include "isa.h" #include "sysbus.h" diff --git a/hw/fdc.h b/hw/fdc.h index c48b5e04df..b6b3772592 100644 --- a/hw/fdc.h +++ b/hw/fdc.h @@ -2,7 +2,7 @@ #define HW_FDC_H /* fdc.c */ -#include "sysemu.h" +#include "blockdev.h" #define MAX_FD 2 typedef struct FDCtrl FDCtrl; diff --git a/hw/ide/core.c b/hw/ide/core.c index 70af1b6043..045d18db2b 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -26,8 +26,6 @@ #include #include #include -#include "block.h" -#include "block_int.h" #include "qemu-timer.h" #include "sysemu.h" #include "dma.h" diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 6231d7716c..0f9f22e30f 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -17,7 +17,6 @@ * License along with this library; if not, see . */ #include -#include "sysemu.h" #include "dma.h" #include diff --git a/hw/lan9118.c b/hw/lan9118.c index 16d33304d5..b996dc4f0c 100644 --- a/hw/lan9118.c +++ b/hw/lan9118.c @@ -10,6 +10,7 @@ #include "sysbus.h" #include "net.h" #include "devices.h" +#include "sysemu.h" /* For crc32 */ #include diff --git a/hw/nand.c b/hw/nand.c index 40d5a6a736..cd7444f9a5 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -13,9 +13,8 @@ # include "hw.h" # include "flash.h" -# include "block.h" +# include "blockdev.h" /* FIXME: Pass block device as an argument. */ -# include "sysemu.h" # define NAND_CMD_READ0 0x00 # define NAND_CMD_READ1 0x01 diff --git a/hw/omap2.c b/hw/omap2.c index bd1b35e661..666c15adb2 100644 --- a/hw/omap2.c +++ b/hw/omap2.c @@ -17,6 +17,8 @@ * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ + +#include "blockdev.h" #include "hw.h" #include "arm-misc.h" #include "omap.h" diff --git a/hw/onenand.c b/hw/onenand.c index c1e7e4d608..4118db922d 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -21,8 +21,7 @@ #include "qemu-common.h" #include "flash.h" #include "irq.h" -#include "sysemu.h" -#include "block.h" +#include "blockdev.h" /* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */ #define PAGE_SHIFT 11 diff --git a/hw/parallel.c b/hw/parallel.c index be8e2d5479..6b11672e15 100644 --- a/hw/parallel.c +++ b/hw/parallel.c @@ -26,6 +26,7 @@ #include "qemu-char.h" #include "isa.h" #include "pc.h" +#include "sysemu.h" //#define DEBUG_PARALLEL diff --git a/hw/pc.c b/hw/pc.c index 9b85c424ed..6e7c468906 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -35,6 +35,7 @@ #include "elf.h" #include "multiboot.h" #include "mc146818rtc.h" +#include "sysemu.h" /* output Bochs bios info messages */ //#define DEBUG_BIOS diff --git a/hw/pc_piix.c b/hw/pc_piix.c index 70f563a67e..dc46846923 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -32,6 +32,7 @@ #include "boards.h" #include "ide.h" #include "kvm.h" +#include "sysemu.h" #define MAX_IDE_BUS 2 diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c index a8f3df1701..c39e640089 100644 --- a/hw/pci-hotplug.c +++ b/hw/pci-hotplug.c @@ -26,10 +26,8 @@ #include "boards.h" #include "pci.h" #include "net.h" -#include "sysemu.h" #include "pc.h" #include "monitor.h" -#include "block_int.h" #include "scsi.h" #include "virtio-blk.h" #include "qemu-config.h" diff --git a/hw/pcmcia.h b/hw/pcmcia.h index cf2db9d325..360292395b 100644 --- a/hw/pcmcia.h +++ b/hw/pcmcia.h @@ -1,7 +1,7 @@ /* PCMCIA/Cardbus */ #include "qemu-common.h" -#include "sysemu.h" +#include "blockdev.h" typedef struct { qemu_irq irq; diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 48a6b45cda..5a8739debe 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -1,4 +1,3 @@ -#include "sysemu.h" #include "net.h" #include "qdev.h" #include "qerror.h" diff --git a/hw/qdev.h b/hw/qdev.h index 0ad6c9567d..be5ad671cc 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -2,7 +2,7 @@ #define QDEV_H #include "hw.h" -#include "sysemu.h" +#include "blockdev.h" #include "qemu-queue.h" #include "qemu-char.h" #include "qemu-option.h" diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 383240bc07..055a94d255 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -2,7 +2,6 @@ #include "qemu-error.h" #include "scsi.h" #include "scsi-defs.h" -#include "block.h" #include "qdev.h" static struct BusInfo scsi_bus_info = { diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index a3559d1fcd..a9bf7d261a 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -33,9 +33,9 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0) #include "qemu-common.h" #include "qemu-error.h" -#include "block.h" #include "scsi.h" #include "scsi-defs.h" +#include "sysemu.h" #define SCSI_DMA_BUF_SIZE 131072 #define SCSI_MAX_INQUIRY_LEN 256 diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index c9aa853cc4..e31060e944 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -13,7 +13,6 @@ #include "qemu-common.h" #include "qemu-error.h" -#include "block.h" #include "scsi.h" #ifdef __linux__ diff --git a/hw/serial.c b/hw/serial.c index 9102edb77b..c7e4e77cb0 100644 --- a/hw/serial.c +++ b/hw/serial.c @@ -27,6 +27,7 @@ #include "isa.h" #include "pc.h" #include "qemu-timer.h" +#include "sysemu.h" //#define DEBUG_SERIAL diff --git a/hw/usb-hid.c b/hw/usb-hid.c index 8e6c6e0322..228d0a052a 100644 --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@ -25,6 +25,7 @@ #include "hw.h" #include "console.h" #include "usb.h" +#include "sysemu.h" /* HID interface requests */ #define GET_REPORT 0xa101 diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 0ba4a64d7c..003bd8a4cd 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -11,10 +11,10 @@ #include "qemu-option.h" #include "qemu-config.h" #include "usb.h" -#include "block.h" #include "scsi.h" #include "console.h" #include "monitor.h" +#include "sysemu.h" //#define DEBUG_MSD diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 80d51c4c0c..cdcb492c14 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -12,9 +12,7 @@ */ #include -#include #include "virtio-blk.h" -#include "block_int.h" #ifdef __linux__ # include #endif diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 7ddf612282..e101fa0a7d 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -22,7 +22,6 @@ #include "qemu-error.h" #include "msix.h" #include "net.h" -#include "block_int.h" #include "loader.h" #include "kvm.h" diff --git a/monitor.c b/monitor.c index 15b53b9aaf..57f24ff088 100644 --- a/monitor.c +++ b/monitor.c @@ -38,7 +38,7 @@ #include "monitor.h" #include "readline.h" #include "console.h" -#include "block.h" +#include "blockdev.h" #include "audio/audio.h" #include "disas.h" #include "balloon.h" @@ -530,21 +530,6 @@ static void do_help_cmd(Monitor *mon, const QDict *qdict) help_cmd(mon, qdict_get_try_str(qdict, "name")); } -static void do_commit(Monitor *mon, const QDict *qdict) -{ - int all_devices; - DriveInfo *dinfo; - const char *device = qdict_get_str(qdict, "device"); - - all_devices = !strcmp(device, "all"); - QTAILQ_FOREACH(dinfo, &drives, next) { - if (!all_devices) - if (strcmp(bdrv_get_device_name(dinfo->bdrv), device)) - continue; - bdrv_commit(dinfo->bdrv); - } -} - static void user_monitor_complete(void *opaque, QObject *ret_data) { MonitorCompletionData *data = (MonitorCompletionData *)opaque; @@ -949,93 +934,6 @@ static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data) return 0; } -static int eject_device(Monitor *mon, BlockDriverState *bs, int force) -{ - if (bdrv_is_inserted(bs)) { - if (!force) { - if (!bdrv_is_removable(bs)) { - qerror_report(QERR_DEVICE_NOT_REMOVABLE, - bdrv_get_device_name(bs)); - return -1; - } - if (bdrv_is_locked(bs)) { - qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs)); - return -1; - } - } - bdrv_close(bs); - } - return 0; -} - -static int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data) -{ - BlockDriverState *bs; - int force = qdict_get_int(qdict, "force"); - const char *filename = qdict_get_str(qdict, "device"); - - bs = bdrv_find(filename); - if (!bs) { - qerror_report(QERR_DEVICE_NOT_FOUND, filename); - return -1; - } - return eject_device(mon, bs, force); -} - -static int do_block_set_passwd(Monitor *mon, const QDict *qdict, - QObject **ret_data) -{ - BlockDriverState *bs; - int err; - - bs = bdrv_find(qdict_get_str(qdict, "device")); - if (!bs) { - qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device")); - return -1; - } - - err = bdrv_set_key(bs, qdict_get_str(qdict, "password")); - if (err == -EINVAL) { - qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs)); - return -1; - } else if (err < 0) { - qerror_report(QERR_INVALID_PASSWORD); - return -1; - } - - return 0; -} - -static int do_change_block(Monitor *mon, const char *device, - const char *filename, const char *fmt) -{ - BlockDriverState *bs; - BlockDriver *drv = NULL; - int bdrv_flags; - - bs = bdrv_find(device); - if (!bs) { - qerror_report(QERR_DEVICE_NOT_FOUND, device); - return -1; - } - if (fmt) { - drv = bdrv_find_whitelisted_format(fmt); - if (!drv) { - qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt); - return -1; - } - } - if (eject_device(mon, bs, 0) < 0) { - return -1; - } - bdrv_flags = bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM ? 0 : BDRV_O_RDWR; - if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) { - qerror_report(QERR_OPEN_FILE_FAILED, filename); - return -1; - } - return monitor_read_bdrv_key_start(mon, bs, NULL, NULL); -} - static int change_vnc_password(const char *password) { if (vnc_display_password(NULL, password) < 0) { diff --git a/qemu-char.c b/qemu-char.c index faaf6248b5..87628ea33f 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -28,7 +28,6 @@ #include "sysemu.h" #include "qemu-timer.h" #include "qemu-char.h" -#include "block.h" #include "hw/usb.h" #include "hw/baum.h" #include "hw/msmouse.h" diff --git a/savevm.c b/savevm.c index af92ba2982..1173a22e65 100644 --- a/savevm.c +++ b/savevm.c @@ -77,7 +77,7 @@ #include "sysemu.h" #include "qemu-timer.h" #include "qemu-char.h" -#include "block.h" +#include "blockdev.h" #include "audio/audio.h" #include "migration.h" #include "qemu_socket.h" diff --git a/sysemu.h b/sysemu.h index dce13c1a05..5fa45ed97a 100644 --- a/sysemu.h +++ b/sysemu.h @@ -147,55 +147,6 @@ extern int nb_option_roms; extern const char *prom_envs[MAX_PROM_ENVS]; extern unsigned int nb_prom_envs; -typedef enum { - IF_NONE, - IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN, - IF_COUNT -} BlockInterfaceType; - -typedef enum { - BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC, - BLOCK_ERR_STOP_ANY -} BlockInterfaceErrorAction; - -#define BLOCK_SERIAL_STRLEN 20 - -typedef struct DriveInfo { - BlockDriverState *bdrv; - char *id; - const char *devaddr; - BlockInterfaceType type; - int bus; - int unit; - QemuOpts *opts; - BlockInterfaceErrorAction on_read_error; - BlockInterfaceErrorAction on_write_error; - char serial[BLOCK_SERIAL_STRLEN + 1]; - QTAILQ_ENTRY(DriveInfo) next; -} DriveInfo; - -#define MAX_IDE_DEVS 2 -#define MAX_SCSI_DEVS 7 - -extern QTAILQ_HEAD(drivelist, DriveInfo) drives; - -extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); -extern DriveInfo *drive_get_by_id(const char *id); -extern int drive_get_max_bus(BlockInterfaceType type); -extern void drive_uninit(DriveInfo *dinfo); -extern const char *drive_get_serial(BlockDriverState *bdrv); - -extern BlockInterfaceErrorAction drive_get_on_error( - BlockDriverState *bdrv, int is_read); - -extern QemuOpts *drive_add(const char *file, const char *fmt, ...); -extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi, - int *fatal_error); - -/* device-hotplug */ - -DriveInfo *add_init_drive(const char *opts); - /* pci-hotplug */ void pci_device_hot_add(Monitor *mon, const QDict *qdict); void drive_hot_add(Monitor *mon, const QDict *qdict); diff --git a/vl.c b/vl.c index db1fefd3ff..0a9862f240 100644 --- a/vl.c +++ b/vl.c @@ -140,7 +140,7 @@ int main(int argc, char **argv) #include "qemu-char.h" #include "cache-utils.h" #include "block.h" -#include "block_int.h" +#include "blockdev.h" #include "block-migration.h" #include "dma.h" #include "audio/audio.h" @@ -172,7 +172,6 @@ int main(int argc, char **argv) static const char *data_dir; const char *bios_name = NULL; -struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives); enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; DisplayType display_type = DT_DEFAULT; const char* keyboard_layout = NULL; @@ -651,486 +650,6 @@ static int bt_parse(const char *opt) #define MTD_ALIAS "if=mtd" #define SD_ALIAS "index=0,if=sd" -QemuOpts *drive_add(const char *file, const char *fmt, ...) -{ - va_list ap; - char optstr[1024]; - QemuOpts *opts; - - va_start(ap, fmt); - vsnprintf(optstr, sizeof(optstr), fmt, ap); - va_end(ap); - - opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0); - if (!opts) { - return NULL; - } - if (file) - qemu_opt_set(opts, "file", file); - return opts; -} - -DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit) -{ - DriveInfo *dinfo; - - /* seek interface, bus and unit */ - - QTAILQ_FOREACH(dinfo, &drives, next) { - if (dinfo->type == type && - dinfo->bus == bus && - dinfo->unit == unit) - return dinfo; - } - - return NULL; -} - -DriveInfo *drive_get_by_id(const char *id) -{ - DriveInfo *dinfo; - - QTAILQ_FOREACH(dinfo, &drives, next) { - if (strcmp(id, dinfo->id)) - continue; - return dinfo; - } - return NULL; -} - -int drive_get_max_bus(BlockInterfaceType type) -{ - int max_bus; - DriveInfo *dinfo; - - max_bus = -1; - QTAILQ_FOREACH(dinfo, &drives, next) { - if(dinfo->type == type && - dinfo->bus > max_bus) - max_bus = dinfo->bus; - } - return max_bus; -} - -const char *drive_get_serial(BlockDriverState *bdrv) -{ - DriveInfo *dinfo; - - QTAILQ_FOREACH(dinfo, &drives, next) { - if (dinfo->bdrv == bdrv) - return dinfo->serial; - } - - return "\0"; -} - -BlockInterfaceErrorAction drive_get_on_error( - BlockDriverState *bdrv, int is_read) -{ - DriveInfo *dinfo; - - QTAILQ_FOREACH(dinfo, &drives, next) { - if (dinfo->bdrv == bdrv) - return is_read ? dinfo->on_read_error : dinfo->on_write_error; - } - - return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC; -} - -static void bdrv_format_print(void *opaque, const char *name) -{ - fprintf(stderr, " %s", name); -} - -void drive_uninit(DriveInfo *dinfo) -{ - qemu_opts_del(dinfo->opts); - bdrv_delete(dinfo->bdrv); - QTAILQ_REMOVE(&drives, dinfo, next); - qemu_free(dinfo); -} - -static int parse_block_error_action(const char *buf, int is_read) -{ - if (!strcmp(buf, "ignore")) { - return BLOCK_ERR_IGNORE; - } else if (!is_read && !strcmp(buf, "enospc")) { - return BLOCK_ERR_STOP_ENOSPC; - } else if (!strcmp(buf, "stop")) { - return BLOCK_ERR_STOP_ANY; - } else if (!strcmp(buf, "report")) { - return BLOCK_ERR_REPORT; - } else { - fprintf(stderr, "qemu: '%s' invalid %s error action\n", - buf, is_read ? "read" : "write"); - return -1; - } -} - -DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error) -{ - const char *buf; - const char *file = NULL; - char devname[128]; - const char *serial; - const char *mediastr = ""; - BlockInterfaceType type; - enum { MEDIA_DISK, MEDIA_CDROM } media; - int bus_id, unit_id; - int cyls, heads, secs, translation; - BlockDriver *drv = NULL; - int max_devs; - int index; - int ro = 0; - int bdrv_flags = 0; - int on_read_error, on_write_error; - const char *devaddr; - DriveInfo *dinfo; - int snapshot = 0; - int ret; - - *fatal_error = 1; - - translation = BIOS_ATA_TRANSLATION_AUTO; - - if (default_to_scsi) { - type = IF_SCSI; - max_devs = MAX_SCSI_DEVS; - pstrcpy(devname, sizeof(devname), "scsi"); - } else { - type = IF_IDE; - max_devs = MAX_IDE_DEVS; - pstrcpy(devname, sizeof(devname), "ide"); - } - media = MEDIA_DISK; - - /* extract parameters */ - bus_id = qemu_opt_get_number(opts, "bus", 0); - unit_id = qemu_opt_get_number(opts, "unit", -1); - index = qemu_opt_get_number(opts, "index", -1); - - cyls = qemu_opt_get_number(opts, "cyls", 0); - heads = qemu_opt_get_number(opts, "heads", 0); - secs = qemu_opt_get_number(opts, "secs", 0); - - snapshot = qemu_opt_get_bool(opts, "snapshot", 0); - ro = qemu_opt_get_bool(opts, "readonly", 0); - - file = qemu_opt_get(opts, "file"); - serial = qemu_opt_get(opts, "serial"); - - if ((buf = qemu_opt_get(opts, "if")) != NULL) { - pstrcpy(devname, sizeof(devname), buf); - if (!strcmp(buf, "ide")) { - type = IF_IDE; - max_devs = MAX_IDE_DEVS; - } else if (!strcmp(buf, "scsi")) { - type = IF_SCSI; - max_devs = MAX_SCSI_DEVS; - } else if (!strcmp(buf, "floppy")) { - type = IF_FLOPPY; - max_devs = 0; - } else if (!strcmp(buf, "pflash")) { - type = IF_PFLASH; - max_devs = 0; - } else if (!strcmp(buf, "mtd")) { - type = IF_MTD; - max_devs = 0; - } else if (!strcmp(buf, "sd")) { - type = IF_SD; - max_devs = 0; - } else if (!strcmp(buf, "virtio")) { - type = IF_VIRTIO; - max_devs = 0; - } else if (!strcmp(buf, "xen")) { - type = IF_XEN; - max_devs = 0; - } else if (!strcmp(buf, "none")) { - type = IF_NONE; - max_devs = 0; - } else { - fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf); - return NULL; - } - } - - if (cyls || heads || secs) { - if (cyls < 1 || (type == IF_IDE && cyls > 16383)) { - fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf); - return NULL; - } - if (heads < 1 || (type == IF_IDE && heads > 16)) { - fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf); - return NULL; - } - if (secs < 1 || (type == IF_IDE && secs > 63)) { - fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf); - return NULL; - } - } - - if ((buf = qemu_opt_get(opts, "trans")) != NULL) { - if (!cyls) { - fprintf(stderr, - "qemu: '%s' trans must be used with cyls,heads and secs\n", - buf); - return NULL; - } - if (!strcmp(buf, "none")) - translation = BIOS_ATA_TRANSLATION_NONE; - else if (!strcmp(buf, "lba")) - translation = BIOS_ATA_TRANSLATION_LBA; - else if (!strcmp(buf, "auto")) - translation = BIOS_ATA_TRANSLATION_AUTO; - else { - fprintf(stderr, "qemu: '%s' invalid translation type\n", buf); - return NULL; - } - } - - if ((buf = qemu_opt_get(opts, "media")) != NULL) { - if (!strcmp(buf, "disk")) { - media = MEDIA_DISK; - } else if (!strcmp(buf, "cdrom")) { - if (cyls || secs || heads) { - fprintf(stderr, - "qemu: '%s' invalid physical CHS format\n", buf); - return NULL; - } - media = MEDIA_CDROM; - } else { - fprintf(stderr, "qemu: '%s' invalid media\n", buf); - return NULL; - } - } - - if ((buf = qemu_opt_get(opts, "cache")) != NULL) { - if (!strcmp(buf, "off") || !strcmp(buf, "none")) { - bdrv_flags |= BDRV_O_NOCACHE; - } else if (!strcmp(buf, "writeback")) { - bdrv_flags |= BDRV_O_CACHE_WB; - } else if (!strcmp(buf, "unsafe")) { - bdrv_flags |= BDRV_O_CACHE_WB; - bdrv_flags |= BDRV_O_NO_FLUSH; - } else if (!strcmp(buf, "writethrough")) { - /* this is the default */ - } else { - fprintf(stderr, "qemu: invalid cache option\n"); - return NULL; - } - } - -#ifdef CONFIG_LINUX_AIO - if ((buf = qemu_opt_get(opts, "aio")) != NULL) { - if (!strcmp(buf, "native")) { - bdrv_flags |= BDRV_O_NATIVE_AIO; - } else if (!strcmp(buf, "threads")) { - /* this is the default */ - } else { - fprintf(stderr, "qemu: invalid aio option\n"); - return NULL; - } - } -#endif - - if ((buf = qemu_opt_get(opts, "format")) != NULL) { - if (strcmp(buf, "?") == 0) { - fprintf(stderr, "qemu: Supported formats:"); - bdrv_iterate_format(bdrv_format_print, NULL); - fprintf(stderr, "\n"); - return NULL; - } - drv = bdrv_find_whitelisted_format(buf); - if (!drv) { - fprintf(stderr, "qemu: '%s' invalid format\n", buf); - return NULL; - } - } - - on_write_error = BLOCK_ERR_STOP_ENOSPC; - if ((buf = qemu_opt_get(opts, "werror")) != NULL) { - if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) { - fprintf(stderr, "werror is no supported by this format\n"); - return NULL; - } - - on_write_error = parse_block_error_action(buf, 0); - if (on_write_error < 0) { - return NULL; - } - } - - on_read_error = BLOCK_ERR_REPORT; - if ((buf = qemu_opt_get(opts, "rerror")) != NULL) { - if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) { - fprintf(stderr, "rerror is no supported by this format\n"); - return NULL; - } - - on_read_error = parse_block_error_action(buf, 1); - if (on_read_error < 0) { - return NULL; - } - } - - if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) { - if (type != IF_VIRTIO) { - fprintf(stderr, "addr is not supported\n"); - return NULL; - } - } - - /* compute bus and unit according index */ - - if (index != -1) { - if (bus_id != 0 || unit_id != -1) { - fprintf(stderr, - "qemu: index cannot be used with bus and unit\n"); - return NULL; - } - if (max_devs == 0) - { - unit_id = index; - bus_id = 0; - } else { - unit_id = index % max_devs; - bus_id = index / max_devs; - } - } - - /* if user doesn't specify a unit_id, - * try to find the first free - */ - - if (unit_id == -1) { - unit_id = 0; - while (drive_get(type, bus_id, unit_id) != NULL) { - unit_id++; - if (max_devs && unit_id >= max_devs) { - unit_id -= max_devs; - bus_id++; - } - } - } - - /* check unit id */ - - if (max_devs && unit_id >= max_devs) { - fprintf(stderr, "qemu: unit %d too big (max is %d)\n", - unit_id, max_devs - 1); - return NULL; - } - - /* - * ignore multiple definitions - */ - - if (drive_get(type, bus_id, unit_id) != NULL) { - *fatal_error = 0; - return NULL; - } - - /* init */ - - dinfo = qemu_mallocz(sizeof(*dinfo)); - if ((buf = qemu_opts_id(opts)) != NULL) { - dinfo->id = qemu_strdup(buf); - } else { - /* no id supplied -> create one */ - dinfo->id = qemu_mallocz(32); - if (type == IF_IDE || type == IF_SCSI) - mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd"; - if (max_devs) - snprintf(dinfo->id, 32, "%s%i%s%i", - devname, bus_id, mediastr, unit_id); - else - snprintf(dinfo->id, 32, "%s%s%i", - devname, mediastr, unit_id); - } - dinfo->bdrv = bdrv_new(dinfo->id); - dinfo->devaddr = devaddr; - dinfo->type = type; - dinfo->bus = bus_id; - dinfo->unit = unit_id; - dinfo->on_read_error = on_read_error; - dinfo->on_write_error = on_write_error; - dinfo->opts = opts; - if (serial) - strncpy(dinfo->serial, serial, sizeof(serial)); - QTAILQ_INSERT_TAIL(&drives, dinfo, next); - - switch(type) { - case IF_IDE: - case IF_SCSI: - case IF_XEN: - case IF_NONE: - switch(media) { - case MEDIA_DISK: - if (cyls != 0) { - bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs); - bdrv_set_translation_hint(dinfo->bdrv, translation); - } - break; - case MEDIA_CDROM: - bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM); - break; - } - break; - case IF_SD: - /* FIXME: This isn't really a floppy, but it's a reasonable - approximation. */ - case IF_FLOPPY: - bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY); - break; - case IF_PFLASH: - case IF_MTD: - break; - case IF_VIRTIO: - /* add virtio block device */ - opts = qemu_opts_create(&qemu_device_opts, NULL, 0); - qemu_opt_set(opts, "driver", "virtio-blk-pci"); - qemu_opt_set(opts, "drive", dinfo->id); - if (devaddr) - qemu_opt_set(opts, "addr", devaddr); - break; - case IF_COUNT: - abort(); - } - if (!file) { - *fatal_error = 0; - return NULL; - } - if (snapshot) { - /* always use cache=unsafe with snapshot */ - bdrv_flags &= ~BDRV_O_CACHE_MASK; - bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH); - } - - if (media == MEDIA_CDROM) { - /* CDROM is fine for any interface, don't check. */ - ro = 1; - } else if (ro == 1) { - if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) { - fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n"); - return NULL; - } - } - - bdrv_flags |= ro ? 0 : BDRV_O_RDWR; - - ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv); - if (ret < 0) { - fprintf(stderr, "qemu: could not open disk image %s: %s\n", - file, strerror(-ret)); - return NULL; - } - - if (bdrv_key_required(dinfo->bdrv)) - autostart = 0; - *fatal_error = 0; - return dinfo; -} - static int drive_init_func(QemuOpts *opts, void *opaque) { int *use_scsi = opaque; -- cgit v1.2.3 From 653dbec7c97cb51d19636423902719e5850da265 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Wed, 2 Jun 2010 17:46:31 -0300 Subject: block: Fix serial number assignment We should use 'dinfo->serial' length, 'serial' is a pointer, so the serial number length is currently limited to the pointer size. This fixes https://bugs.launchpad.net/qemu/+bug/584143 and is also valid for stable. Signed-off-by: Luiz Capitulino Signed-off-by: Kevin Wolf --- blockdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockdev.c b/blockdev.c index bd9783affd..642ce756ac 100644 --- a/blockdev.c +++ b/blockdev.c @@ -422,7 +422,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error) dinfo->on_write_error = on_write_error; dinfo->opts = opts; if (serial) - strncpy(dinfo->serial, serial, sizeof(serial)); + strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1); QTAILQ_INSERT_TAIL(&drives, dinfo, next); switch(type) { -- cgit v1.2.3