Block patches
Subsystems (2)
The following changes since commit 358c360feb346dff8f911e2d1dbcdd6319393f1d:
Anthony Liguori (1):
Merge remote branch 'kwolf/for-anthony' into staging
are available in the git repository at:
git://repo.or.cz/qemu/kevin.git for-anthony
Jes Sorensen (4):
Cleanup: bdrv_open() no need to shift total_size just to shift back.
Cleanup: Be consistent and use BDRV_SECTOR_SIZE instead of 512
Cleanup: raw-posix.c: Be more consistent using BDRV_SECTOR_SIZE instead of 512
Cleanup: virtio-blk.c: Be more consistent using BDRV_SECTOR_SIZE instead
Kevin Wolf (3):
qemu-io: Fix error messages
Fix error message in drive_init
block: Assume raw for drives without media
Luiz Capitulino (1):
block: Fix serial number assignment
MORITA Kazutaka (2):
close all the block drivers before the qemu process exits
block: call the snapshot handlers of the protocol drivers
Markus Armbruster (17):
blockdev: Belatedly remove MAX_DRIVES
blockdev: Belatedly remove driveopts
usb: Remove unused usb_device_add() parameter is_hotplug
ide: Remove useless IDEDeviceInfo members unit, drive
ide: Remove redundant IDEState member conf
ide: Split ide_init1() off ide_init2()
ide: Change ide_init_drive() to require valid dinfo argument
ide: Split non-qdev code off ide_init2()
qdev: New qdev_prop_set_string()
qdev: Don't leak string property value on hot unplug
ide: Turn drive serial into a qdev property ide-drive.serial
ide: Fix info qtree for ide-drive.ver
scsi: Turn drive serial into a qdev property scsi-disk.serial
scsi: Fix info qtree for scsi-disk.ver
blockdev: Hide QEMUMachine from drive_init()
qdev: Move declaration of qdev_init_bdrv() into qdev.h
blockdev: Collect block device code in new blockdev.c
Makefile.objs | 2 +- block.c | 91 ++++++--- block.h | 1 + block/raw-posix.c | 20 +- blockdev.c | 600 ++++++++++++++++++++++++++++++++++++++++++++++++++ blockdev.h | 71 ++++++ hw/acpi_piix4.c | 1 + hw/apb_pci.c | 1 + hw/device-hotplug.c | 4 +- hw/fdc.c | 1 - hw/fdc.h | 2 +- hw/ide/cmd646.c | 4 +- hw/ide/core.c | 108 +++++---- hw/ide/internal.h | 13 +- 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 +- hw/ide/qdev.c | 21 ++- 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/pl181.c | 1 - hw/qdev-properties.c | 12 +- hw/qdev.c | 6 + hw/qdev.h | 6 +- hw/scsi-bus.c | 1 - hw/scsi-disk.c | 26 ++- hw/scsi-generic.c | 1 - hw/serial.c | 1 + hw/ssi-sd.c | 1 - hw/usb-hid.c | 1 + hw/usb-msd.c | 4 +- hw/virtio-blk.c | 9 +- hw/virtio-pci.c | 1 - monitor.c | 104 +--------- qemu-char.c | 1 - qemu-io.c | 4 +- savevm.c | 2 +- sysemu.h | 52 ----- vl.c | 499 +----------------------------------------- 48 files changed, 916 insertions(+), 785 deletions(-) create mode 100644 blockdev.c create mode 100644 blockdev.h
PATCH 1/27 Cleanup: bdrv_open() no need to shift total_size just to shift back.
From: Jes Sorensen <[email protected]>
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.
--- block.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
block.c +2 -2
@@ -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,
Signature · 1 line
1.6.6.1
PATCH 2/27 Cleanup: Be consistent and use BDRV_SECTOR_SIZE instead of 512
In reply to Kevin WolfFrom: Jes Sorensen <[email protected]>
Clean up block.c and use BDRV_SECTOR_SIZE rather than hard coded numbers (512) when referring to sector size throughout the code.
--- block.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-)
block.c +7 -6
@@ -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);
Signature · 1 line
1.6.6.1
PATCH 3/27 Cleanup: raw-posix.c: Be more consistent using BDRV_SECTOR_SIZE instead of 512
In reply to Kevin WolfFrom: Jes Sorensen <[email protected]>
Clean up raw-posix.c to be more consistent using BDRV_SECTOR_SIZE instead of hard coded 512 values.
--- block/raw-posix.c | 20 +++++++++++--------- 1 files changed, 11 insertions(+), 9 deletions(-)
block/raw-posix.c +11 -9
@@ -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);
Signature · 1 line
1.6.6.1
PATCH 4/27 Cleanup: virtio-blk.c: Be more consistent using BDRV_SECTOR_SIZE instead
In reply to Kevin WolfFrom: Jes Sorensen <[email protected]>
Clean up virtio-blk.c to be more consistent using BDRV_SECTOR_SIZE instead of hard coded 512 values.
--- hw/virtio-blk.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-)
hw/virtio-blk.c +4 -3
@@ -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);
Signature · 1 line
1.6.6.1
PATCH 5/27 qemu-io: Fix error messages
In reply to Kevin WolfThe 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.
--- qemu-io.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
qemu-io.c +2 -2
@@ -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 ; }
Signature · 1 line
1.6.6.1
PATCH 6/27 blockdev: Belatedly remove MAX_DRIVES
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
Unused since commit 751c6a17.
--- sysemu.h | 1 - vl.c | 2 -- 2 files changed, 0 insertions(+), 3 deletions(-)
sysemu.h +0 -1
@@ -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;
vl.c +0 -2
@@ -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 ;
Signature · 1 line
1.6.6.1
PATCH 7/27 blockdev: Belatedly remove driveopts
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
Unused since commit 9dfd7c7a.
--- sysemu.h | 1 - vl.c | 1 - 2 files changed, 0 insertions(+), 2 deletions(-)
sysemu.h +0 -1
@@ -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);
vl.c +0 -1
@@ -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 ;
Signature · 1 line
1.6.6.1
PATCH 8/27 usb: Remove unused usb_device_add() parameter is_hotplug
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
Unused since commit b3e461d3.
--- vl.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
vl.c +3 -3
@@ -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); } }
Signature · 1 line
1.6.6.1
PATCH 9/27 ide: Remove useless IDEDeviceInfo members unit, drive
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
--- hw/ide/internal.h | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
hw/ide/internal.h +0 -2
@@ -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
Signature · 1 line
1.6.6.1
PATCH 10/27 ide: Remove redundant IDEState member conf
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
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.
--- hw/ide/core.c | 16 +++++++--------- hw/ide/internal.h | 4 +--- hw/ide/qdev.c | 3 +-- 3 files changed, 9 insertions(+), 14 deletions(-)
hw/ide/core.c +7 -9
@@ -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; }
hw/ide/internal.h +1 -3
@@ -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);
hw/ide/qdev.c +1 -2
@@ -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 ; }
Signature · 1 line
1.6.6.1
PATCH 11/27 ide: Split ide_init1() off ide_init2()
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
--- hw/ide/core.c | 32 +++++++++++++++++--------------- 1 files changed, 17 insertions(+), 15 deletions(-)
hw/ide/core.c +17 -15
@@ -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; }
Signature · 1 line
1.6.6.1
PATCH 12/27 ide: Change ide_init_drive() to require valid dinfo argument
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
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.
--- hw/ide/core.c | 47 +++++++++++++++++++++++++---------------------- 1 files changed, 25 insertions(+), 22 deletions(-)
hw/ide/core.c +25 -22
@@ -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,
Signature · 1 line
1.6.6.1
PATCH 13/27 ide: Split non-qdev code off ide_init2()
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
--- 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(-)
hw/ide/cmd646.c +2 -2
@@ -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);
hw/ide/core.c +22 -8
@@ -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; }
hw/ide/internal.h +3 -2
@@ -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 */
hw/ide/isa.c +1 -1
@@ -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 ; };
hw/ide/macio.c +1 -1
@@ -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);
hw/ide/microdrive.c +2 -1
@@ -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 );
hw/ide/mmio.c +1 -1
@@ -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;
hw/ide/piix.c +2 -2
@@ -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 ; }
Signature · 1 line
1.6.6.1
PATCH 14/27 qdev: New qdev_prop_set_string()
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
--- hw/qdev-properties.c | 5 +++++ hw/qdev.h | 1 + 2 files changed, 6 insertions(+), 0 deletions(-)
hw/qdev-properties.c +5 -0
@@ -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 );
hw/qdev.h +1 -0
@@ -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);
Signature · 1 line
1.6.6.1
PATCH 15/27 qdev: Don't leak string property value on hot unplug
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
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.
--- hw/qdev-properties.c | 6 ++++++ hw/qdev.c | 6 ++++++ hw/qdev.h | 1 + 3 files changed, 13 insertions(+), 0 deletions(-)
hw/qdev-properties.c +6 -0
@@ -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 --- */
hw/qdev.c +6 -0
@@ -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); }
hw/qdev.h +1 -0
@@ -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 {
Signature · 1 line
1.6.6.1
PATCH 16/27 ide: Turn drive serial into a qdev property ide-drive.serial
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
It needs to be a qdev property, because it belongs to the drive's guest part.
Bonus: info qtree now shows the serial number.
--- hw/ide/core.c | 11 ++++++----- hw/ide/internal.h | 4 +++- hw/ide/qdev.c | 16 +++++++++++++++- 3 files changed, 24 insertions(+), 7 deletions(-)
hw/ide/core.c +6 -5
@@ -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]); }
hw/ide/internal.h +3 -1
@@ -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);
hw/ide/qdev.c +15 -1
@@ -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(), } };
Signature · 1 line
1.6.6.1
PATCH 17/27 ide: Fix info qtree for ide-drive.ver
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
Show the actual default value instead of <null> when the property has not been set.
--- hw/ide/qdev.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
hw/ide/qdev.c +3 -0
@@ -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); }
Signature · 1 line
1.6.6.1
PATCH 18/27 scsi: Turn drive serial into a qdev property scsi-disk.serial
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
It needs to be a qdev property, because it belongs to the drive's guest part.
Bonus: info qtree now shows the serial number.
--- hw/scsi-disk.c | 17 +++++++++++++---- 1 files changed, 13 insertions(+), 4 deletions(-)
hw/scsi-disk.c +13 -4
@@ -66,6 +66,7 @@ struct SCSIDiskStateuint64_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 (), }, };
Signature · 1 line
1.6.6.1
PATCH 19/27 scsi: Fix info qtree for scsi-disk.ver
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
Show the actual default value instead of <null> when the property has not been set.
--- hw/scsi-disk.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-)
hw/scsi-disk.c +5 -2
@@ -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 ;
Signature · 1 line
1.6.6.1
PATCH 20/27 Fix error message in drive_init
In reply to Kevin WolfThe real error is the return value of bdrv_open. errno might be overwritten or not even set to that value in the first place.
--- vl.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-)
vl.c +4 -2
@@ -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 ; }
Signature · 1 line
1.6.6.1
PATCH 21/27 block: Assume raw for drives without media
In reply to Kevin Wolfqemu -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.
--- block.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
block.c +2 -2
@@ -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" ); }
Signature · 1 line
1.6.6.1
PATCH 22/27 close all the block drivers before the qemu process exits
In reply to Kevin WolfFrom: MORITA Kazutaka <[email protected]>
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.
--- block.c | 9 +++++++++ block.h | 1 + vl.c | 1 + 3 files changed, 11 insertions(+), 0 deletions(-)
block.c +9 -0
@@ -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 */
block.h +1 -0
@@ -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,
vl.c +1 -0
@@ -1991,6 +1991,7 @@ static void main_loop(void)vm_stop (r); } } +bdrv_close_all ();pause_all_vcpus (); }
Signature · 1 line
1.6.6.1
PATCH 23/27 block: call the snapshot handlers of the protocol drivers
In reply to Kevin WolfFrom: MORITA Kazutaka <[email protected]>
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.
--- block.c | 61 +++++++++++++++++++++++++++++++++++++++++++------------------ 1 files changed, 43 insertions(+), 18 deletions(-)
block.c +43 -18
@@ -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
Signature · 1 line
1.6.6.1
PATCH 24/27 blockdev: Hide QEMUMachine from drive_init()
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
To pave the way for moving it out of vl.c.
--- hw/device-hotplug.c | 2 +- hw/usb-msd.c | 2 +- sysemu.h | 3 ++- vl.c | 12 +++++------- 4 files changed, 9 insertions(+), 10 deletions(-)
hw/device-hotplug.c +1 -1
@@ -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 ;
hw/usb-msd.c +1 -1
@@ -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 ;
sysemu.h +2 -1
@@ -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 */
vl.c +5 -7
@@ -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,
Signature · 1 line
1.6.6.1
PATCH 25/27 qdev: Move declaration of qdev_init_bdrv() into qdev.h
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
--- hw/pl181.c | 1 - hw/qdev.h | 2 ++ hw/ssi-sd.c | 1 - sysemu.h | 2 -- 4 files changed, 2 insertions(+), 4 deletions(-)
hw/pl181.c +0 -1
@@ -9,7 +9,6 @@#include "sysbus.h" #include "sd.h" -#include "sysemu.h" //#define DEBUG_PL181 1
hw/qdev.h +2 -0
@@ -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. ***/
hw/ssi-sd.c +0 -1
@@ -9,7 +9,6 @@#include "ssi.h" #include "sd.h" -#include "sysemu.h" //#define DEBUG_SSI_SD 1
sysemu.h +0 -2
@@ -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);
Signature · 1 line
1.6.6.1
PATCH 26/27 blockdev: Collect block device code in new blockdev.c
In reply to Kevin WolfFrom: Markus Armbruster <[email protected]>
Anything that moves hundreds of lines out of vl.c can't be all bad.
--- 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
Makefile.objs +1 -1
@@ -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))
blockdev.c new file +600 -0
600 lines not on this page · raw message
blockdev.h new file +71 -0
71 lines not on this page · raw message
hw/acpi_piix4.c +1 -0
@@ -21,6 +21,7 @@#include "pm_smbus.h" #include "pci.h" #include "acpi.h" +#include "sysemu.h" //#define DEBUG
hw/apb_pci.c +1 -0
@@ -31,6 +31,7 @@#include "pci_host.h" #include "rwhandler.h" #include "apb_pci.h" +#include "sysemu.h" /* debug APB */ //#define DEBUG_APB
hw/device-hotplug.c +0 -2
@@ -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) {
hw/fdc.c +0 -1
@@ -29,7 +29,6 @@#include "hw.h" #include "fdc.h" -#include "block.h" #include "qemu-timer.h" #include "isa.h" #include "sysbus.h"
hw/fdc.h +1 -1
@@ -2,7 +2,7 @@#define HW_FDC_H /* fdc.c */ -#include "sysemu.h" +#include "blockdev.h" #define MAX_FD 2typedef struct FDCtrl FDCtrl ;
hw/ide/core.c +0 -2
@@ -26,8 +26,6 @@#include <hw/pc.h> #include <hw/pci.h> #include <hw/scsi.h> -#include "block.h" -#include "block_int.h" #include "qemu-timer.h" #include "sysemu.h" #include "dma.h"
hw/ide/qdev.c +0 -1
@@ -17,7 +17,6 @@* License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #include <hw/hw.h> -#include "sysemu.h" #include "dma.h" #include <hw/ide/internal.h>
hw/lan9118.c +1 -0
@@ -10,6 +10,7 @@#include "sysbus.h" #include "net.h" #include "devices.h" +#include "sysemu.h" /* For crc32 */ #include <zlib.h>
hw/nand.c +1 -2
@@ -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
hw/omap2.c +2 -0
@@ -17,6 +17,8 @@* You should have received a copy of the GNU General Public License along * with this program; if not, see <http://www.gnu.org/licenses/>. */ + +#include "blockdev.h" #include "hw.h" #include "arm-misc.h" #include "omap.h"
hw/onenand.c +1 -2
@@ -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
hw/parallel.c +1 -0
@@ -26,6 +26,7 @@#include "qemu-char.h" #include "isa.h" #include "pc.h" +#include "sysemu.h" //#define DEBUG_PARALLEL
hw/pc.c +1 -0
@@ -35,6 +35,7 @@#include "elf.h" #include "multiboot.h" #include "mc146818rtc.h" +#include "sysemu.h" /* output Bochs bios info messages */ //#define DEBUG_BIOS
hw/pc_piix.c +1 -0
@@ -32,6 +32,7 @@#include "boards.h" #include "ide.h" #include "kvm.h" +#include "sysemu.h" #define MAX_IDE_BUS 2
hw/pci-hotplug.c +0 -2
@@ -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"
hw/pcmcia.h +1 -1
@@ -1,7 +1,7 @@/* PCMCIA/Cardbus */ #include "qemu-common.h" -#include "sysemu.h" +#include "blockdev.h" typedef struct { qemu_irq irq;
hw/qdev-properties.c +0 -1
@@ -1,4 +1,3 @@ -#include "sysemu.h" #include "net.h" #include "qdev.h" #include "qerror.h"
hw/qdev.h +1 -1
@@ -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"
hw/scsi-bus.c +0 -1
@@ -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 = {
hw/scsi-disk.c +1 -1
@@ -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
hw/scsi-generic.c +0 -1
@@ -13,7 +13,6 @@#include "qemu-common.h" #include "qemu-error.h" -#include "block.h" #include "scsi.h" #ifdef __linux__
hw/serial.c +1 -0
@@ -27,6 +27,7 @@#include "isa.h" #include "pc.h" #include "qemu-timer.h" +#include "sysemu.h" //#define DEBUG_SERIAL
hw/usb-hid.c +1 -0
@@ -25,6 +25,7 @@#include "hw.h" #include "console.h" #include "usb.h" +#include "sysemu.h" /* HID interface requests */ #define GET_REPORT 0xa101
hw/usb-msd.c +1 -1
@@ -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
hw/virtio-blk.c +0 -2
@@ -12,9 +12,7 @@*/ #include <qemu-common.h> -#include <sysemu.h> #include "virtio-blk.h" -#include "block_int.h" #ifdef __linux__# include <scsi/sg.h> #endif
hw/virtio-pci.c +0 -1
@@ -22,7 +22,6 @@#include "qemu-error.h" #include "msix.h" #include "net.h" -#include "block_int.h" #include "loader.h" #include "kvm.h"
monitor.c +1 -103
122 lines not on this page · raw message
qemu-char.c +0 -1
@@ -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"
savevm.c +1 -1
@@ -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"
sysemu.h +0 -49
55 lines not on this page · raw message
vl.c +1 -482
501 lines not on this page · raw message
Signature · 1 line
1.6.6.1
Re: [Qemu-devel] [PATCH 26/27] blockdev: Collect block device code in new blockdev.c
Quoted 3 lines · Kevin Wolf
From: Markus Armbruster <[email protected]>
Anything that moves hundreds of lines out of
vl.ccan't be all bad.
I know I'm late for this train, but why does this patch change the license of the former vl.c code from a BSD-like one to GPLv2? It seems to be contradicting the vl.c paragraph:
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
Signature · 4 lines
Regards, Artyom Tarasenko solaris/sparc under qemu blog: http://tyom.blogspot.com/
Re: [Qemu-devel] [PATCH 26/27] blockdev: Collect block device code in new blockdev.c
Am 15.12.2010 16:04, schrieb Artyom Tarasenko:
Quoted 11 lines · Kevin Wolf
Quoted 3 lines
From: Markus Armbruster <[email protected]>
Anything that moves hundreds of lines out of
vl.ccan't be all bad.I know I'm late for this train, but why does this patch change the license of the former
vl.ccode from a BSD-like one to GPLv2? It seems to be contradicting thevl.cparagraph:* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
Right, I think this needs to fixed. Markus, can you send a patch?
Kevin
Re: [Qemu-devel] [PATCH 26/27] blockdev: Collect block device code in new blockdev.c
Quoted 6 lines · Kevin Wolf
Am 15.12.2010 16:04, schrieb Artyom Tarasenko:
Quoted 5 lines · Kevin Wolf
Quoted 3 lines
From: Markus Armbruster <[email protected]>
Anything that moves hundreds of lines out of
vl.ccan't be all bad.
Quoted 8 lines
Quoted 6 lines
I know I'm late for this train, but why does this patch change the license of the former
vl.ccode from a BSD-like one to GPLv2? It seems to be contradicting thevl.cparagraph:* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.Right, I think this needs to fixed. Markus, can you send a patch?
Ping?
Signature · 4 lines
Regards, Artyom Tarasenko solaris/sparc under qemu blog: http://tyom.blogspot.com/search/label/qemu
PATCH 27/27 block: Fix serial number assignment
In reply to Kevin WolfFrom: Luiz Capitulino <[email protected]>
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.
--- blockdev.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
blockdev.c +1 -1
@@ -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) {
Signature · 1 line
1.6.6.1