Revision 14bafc54
b/blockdev.c | ||
---|---|---|
17 | 17 |
|
18 | 18 |
static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives); |
19 | 19 |
|
20 |
/* |
|
21 |
* We automatically delete the drive when a device using it gets |
|
22 |
* unplugged. Questionable feature, but we can't just drop it. |
|
23 |
* Device models call blockdev_mark_auto_del() to schedule the |
|
24 |
* automatic deletion, and generic qdev code calls blockdev_auto_del() |
|
25 |
* when deletion is actually safe. |
|
26 |
*/ |
|
27 |
void blockdev_mark_auto_del(BlockDriverState *bs) |
|
28 |
{ |
|
29 |
DriveInfo *dinfo = drive_get_by_blockdev(bs); |
|
30 |
|
|
31 |
dinfo->auto_del = 1; |
|
32 |
} |
|
33 |
|
|
34 |
void blockdev_auto_del(BlockDriverState *bs) |
|
35 |
{ |
|
36 |
DriveInfo *dinfo = drive_get_by_blockdev(bs); |
|
37 |
|
|
38 |
if (dinfo->auto_del) { |
|
39 |
drive_uninit(dinfo); |
|
40 |
} |
|
41 |
} |
|
42 |
|
|
20 | 43 |
QemuOpts *drive_add(const char *file, const char *fmt, ...) |
21 | 44 |
{ |
22 | 45 |
va_list ap; |
b/blockdev.h | ||
---|---|---|
13 | 13 |
#include "block.h" |
14 | 14 |
#include "qemu-queue.h" |
15 | 15 |
|
16 |
void blockdev_mark_auto_del(BlockDriverState *bs); |
|
17 |
void blockdev_auto_del(BlockDriverState *bs); |
|
18 |
|
|
16 | 19 |
typedef enum { |
17 | 20 |
IF_NONE, |
18 | 21 |
IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN, |
... | ... | |
28 | 31 |
BlockInterfaceType type; |
29 | 32 |
int bus; |
30 | 33 |
int unit; |
34 |
int auto_del; /* see blockdev_mark_auto_del() */ |
|
31 | 35 |
QemuOpts *opts; |
32 | 36 |
char serial[BLOCK_SERIAL_STRLEN + 1]; |
33 | 37 |
QTAILQ_ENTRY(DriveInfo) next; |
b/hw/qdev-properties.c | ||
---|---|---|
313 | 313 |
return 0; |
314 | 314 |
} |
315 | 315 |
|
316 |
static void free_drive(DeviceState *dev, Property *prop) |
|
317 |
{ |
|
318 |
DriveInfo **ptr = qdev_get_prop_ptr(dev, prop); |
|
319 |
|
|
320 |
if (*ptr) { |
|
321 |
blockdev_auto_del((*ptr)->bdrv); |
|
322 |
} |
|
323 |
} |
|
324 |
|
|
316 | 325 |
static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len) |
317 | 326 |
{ |
318 | 327 |
DriveInfo **ptr = qdev_get_prop_ptr(dev, prop); |
... | ... | |
325 | 334 |
.size = sizeof(DriveInfo*), |
326 | 335 |
.parse = parse_drive, |
327 | 336 |
.print = print_drive, |
337 |
.free = free_drive, |
|
328 | 338 |
}; |
329 | 339 |
|
330 | 340 |
/* --- character device --- */ |
b/hw/scsi-disk.c | ||
---|---|---|
1043 | 1043 |
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); |
1044 | 1044 |
|
1045 | 1045 |
scsi_disk_purge_requests(s); |
1046 |
drive_uninit(s->qdev.conf.dinfo);
|
|
1046 |
blockdev_mark_auto_del(s->qdev.conf.dinfo->bdrv);
|
|
1047 | 1047 |
} |
1048 | 1048 |
|
1049 | 1049 |
static int scsi_disk_initfn(SCSIDevice *dev) |
b/hw/scsi-generic.c | ||
---|---|---|
453 | 453 |
r = DO_UPCAST(SCSIGenericReq, req, QTAILQ_FIRST(&s->qdev.requests)); |
454 | 454 |
scsi_remove_request(r); |
455 | 455 |
} |
456 |
drive_uninit(s->qdev.conf.dinfo);
|
|
456 |
blockdev_mark_auto_del(s->qdev.conf.dinfo->bdrv);
|
|
457 | 457 |
} |
458 | 458 |
|
459 | 459 |
static int scsi_generic_initfn(SCSIDevice *dev) |
b/hw/usb-msd.c | ||
---|---|---|
522 | 522 |
static int usb_msd_initfn(USBDevice *dev) |
523 | 523 |
{ |
524 | 524 |
MSDState *s = DO_UPCAST(MSDState, dev, dev); |
525 |
DriveInfo *dinfo = s->conf.dinfo; |
|
525 | 526 |
|
526 |
if (!s->conf.dinfo || !s->conf.dinfo->bdrv) {
|
|
527 |
if (!dinfo || !dinfo->bdrv) {
|
|
527 | 528 |
error_report("usb-msd: drive property not set"); |
528 | 529 |
return -1; |
529 | 530 |
} |
530 | 531 |
|
532 |
/* |
|
533 |
* Hack alert: this pretends to be a block device, but it's really |
|
534 |
* a SCSI bus that can serve only a single device, which it |
|
535 |
* creates automatically. Two drive properties pointing to the |
|
536 |
* same drive is not good: free_drive() dies for the second one. |
|
537 |
* Zap the one we're not going to use. |
|
538 |
* |
|
539 |
* The hack is probably a bad idea. |
|
540 |
*/ |
|
541 |
s->conf.dinfo = NULL; |
|
542 |
|
|
531 | 543 |
s->dev.speed = USB_SPEED_FULL; |
532 | 544 |
scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete); |
533 |
s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, s->conf.dinfo, 0);
|
|
545 |
s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, dinfo, 0); |
|
534 | 546 |
if (!s->scsi_dev) { |
535 | 547 |
return -1; |
536 | 548 |
} |
537 | 549 |
s->bus.qbus.allow_hotplug = 0; |
538 | 550 |
usb_msd_handle_reset(dev); |
539 | 551 |
|
540 |
if (bdrv_key_required(s->conf.dinfo->bdrv)) {
|
|
552 |
if (bdrv_key_required(dinfo->bdrv)) { |
|
541 | 553 |
if (cur_mon) { |
542 |
monitor_read_bdrv_key_start(cur_mon, s->conf.dinfo->bdrv,
|
|
554 |
monitor_read_bdrv_key_start(cur_mon, dinfo->bdrv, |
|
543 | 555 |
usb_msd_password_cb, s); |
544 | 556 |
s->dev.auto_attach = 0; |
545 | 557 |
} else { |
b/hw/virtio-pci.c | ||
---|---|---|
571 | 571 |
{ |
572 | 572 |
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); |
573 | 573 |
|
574 |
drive_uninit(proxy->block.dinfo);
|
|
574 |
blockdev_mark_auto_del(proxy->block.dinfo->bdrv);
|
|
575 | 575 |
return virtio_exit_pci(pci_dev); |
576 | 576 |
} |
577 | 577 |
|
Also available in: Unified diff