hw/block: Request permissions
This makes all device emulations with a qdev drive property request permissions on their BlockBackend. The only thing we block at this point is resizing images for some devices that can't support it. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Acked-by: Fam Zheng <famz@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
39829a01ae
commit
a17c17a274
@ -51,11 +51,31 @@ void blkconf_blocksizes(BlockConf *conf)
|
||||
}
|
||||
}
|
||||
|
||||
void blkconf_apply_backend_options(BlockConf *conf)
|
||||
void blkconf_apply_backend_options(BlockConf *conf, bool readonly,
|
||||
bool resizable, Error **errp)
|
||||
{
|
||||
BlockBackend *blk = conf->blk;
|
||||
BlockdevOnError rerror, werror;
|
||||
uint64_t perm, shared_perm;
|
||||
bool wce;
|
||||
int ret;
|
||||
|
||||
perm = BLK_PERM_CONSISTENT_READ;
|
||||
if (!readonly) {
|
||||
perm |= BLK_PERM_WRITE;
|
||||
}
|
||||
|
||||
/* TODO Remove BLK_PERM_WRITE unless explicitly configured so */
|
||||
shared_perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
|
||||
BLK_PERM_GRAPH_MOD | BLK_PERM_WRITE;
|
||||
if (resizable) {
|
||||
shared_perm |= BLK_PERM_RESIZE;
|
||||
}
|
||||
|
||||
ret = blk_set_perm(blk, perm, shared_perm, errp);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (conf->wce) {
|
||||
case ON_OFF_AUTO_ON: wce = true; break;
|
||||
|
@ -186,6 +186,7 @@ typedef enum FDiskFlags {
|
||||
struct FDrive {
|
||||
FDCtrl *fdctrl;
|
||||
BlockBackend *blk;
|
||||
BlockConf *conf;
|
||||
/* Drive status */
|
||||
FloppyDriveType drive; /* CMOS drive type */
|
||||
uint8_t perpendicular; /* 2.88 MB access mode */
|
||||
@ -472,6 +473,19 @@ static void fd_revalidate(FDrive *drv)
|
||||
static void fd_change_cb(void *opaque, bool load, Error **errp)
|
||||
{
|
||||
FDrive *drive = opaque;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (!load) {
|
||||
blk_set_perm(drive->blk, 0, BLK_PERM_ALL, &error_abort);
|
||||
} else {
|
||||
blkconf_apply_backend_options(drive->conf,
|
||||
blk_is_read_only(drive->blk), false,
|
||||
&local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
drive->media_changed = 1;
|
||||
drive->media_validated = false;
|
||||
@ -508,6 +522,7 @@ static int floppy_drive_init(DeviceState *qdev)
|
||||
FloppyDrive *dev = FLOPPY_DRIVE(qdev);
|
||||
FloppyBus *bus = FLOPPY_BUS(qdev->parent_bus);
|
||||
FDrive *drive;
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
|
||||
if (dev->unit == -1) {
|
||||
@ -533,7 +548,6 @@ static int floppy_drive_init(DeviceState *qdev)
|
||||
|
||||
if (!dev->conf.blk) {
|
||||
/* Anonymous BlockBackend for an empty drive */
|
||||
/* FIXME Use real permissions */
|
||||
dev->conf.blk = blk_new(0, BLK_PERM_ALL);
|
||||
ret = blk_attach_dev(dev->conf.blk, qdev);
|
||||
assert(ret == 0);
|
||||
@ -552,7 +566,13 @@ static int floppy_drive_init(DeviceState *qdev)
|
||||
* blkconf_apply_backend_options(). */
|
||||
dev->conf.rerror = BLOCKDEV_ON_ERROR_AUTO;
|
||||
dev->conf.werror = BLOCKDEV_ON_ERROR_AUTO;
|
||||
blkconf_apply_backend_options(&dev->conf);
|
||||
|
||||
blkconf_apply_backend_options(&dev->conf, blk_is_read_only(dev->conf.blk),
|
||||
false, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 'enospc' is the default for -drive, 'report' is what blk_new() gives us
|
||||
* for empty drives. */
|
||||
@ -566,6 +586,7 @@ static int floppy_drive_init(DeviceState *qdev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
drive->conf = &dev->conf;
|
||||
drive->blk = dev->conf.blk;
|
||||
drive->fdctrl = bus->fdc;
|
||||
|
||||
|
@ -1215,6 +1215,7 @@ static void m25p80_realize(SSISlave *ss, Error **errp)
|
||||
{
|
||||
Flash *s = M25P80(ss);
|
||||
M25P80Class *mc = M25P80_GET_CLASS(s);
|
||||
int ret;
|
||||
|
||||
s->pi = mc->pi;
|
||||
|
||||
@ -1222,6 +1223,13 @@ static void m25p80_realize(SSISlave *ss, Error **errp)
|
||||
s->dirty_page = -1;
|
||||
|
||||
if (s->blk) {
|
||||
uint64_t perm = BLK_PERM_CONSISTENT_READ |
|
||||
(blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE);
|
||||
ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
DB_PRINT_L(0, "Binding to IF_MTD drive\n");
|
||||
s->storage = blk_blockalign(s->blk, s->size);
|
||||
|
||||
|
@ -373,6 +373,8 @@ static void nand_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
int pagesize;
|
||||
NANDFlashState *s = NAND(dev);
|
||||
int ret;
|
||||
|
||||
|
||||
s->buswidth = nand_flash_ids[s->chip_id].width >> 3;
|
||||
s->size = nand_flash_ids[s->chip_id].size << 20;
|
||||
@ -407,6 +409,11 @@ static void nand_realize(DeviceState *dev, Error **errp)
|
||||
error_setg(errp, "Can't use a read-only drive");
|
||||
return;
|
||||
}
|
||||
ret = blk_set_perm(s->blk, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE,
|
||||
BLK_PERM_ALL, errp);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
if (blk_getlength(s->blk) >=
|
||||
(s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
|
||||
pagesize = 0;
|
||||
|
@ -835,6 +835,7 @@ static int nvme_init(PCIDevice *pci_dev)
|
||||
int i;
|
||||
int64_t bs_size;
|
||||
uint8_t *pci_conf;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (!n->conf.blk) {
|
||||
return -1;
|
||||
@ -850,7 +851,12 @@ static int nvme_init(PCIDevice *pci_dev)
|
||||
return -1;
|
||||
}
|
||||
blkconf_blocksizes(&n->conf);
|
||||
blkconf_apply_backend_options(&n->conf);
|
||||
blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
|
||||
false, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pci_conf = pci_dev->config;
|
||||
pci_conf[PCI_INTERRUPT_PIN] = 1;
|
||||
|
@ -778,6 +778,7 @@ static int onenand_initfn(SysBusDevice *sbd)
|
||||
OneNANDState *s = ONE_NAND(dev);
|
||||
uint32_t size = 1 << (24 + ((s->id.dev >> 4) & 7));
|
||||
void *ram;
|
||||
Error *local_err = NULL;
|
||||
|
||||
s->base = (hwaddr)-1;
|
||||
s->rdy = NULL;
|
||||
@ -796,6 +797,12 @@ static int onenand_initfn(SysBusDevice *sbd)
|
||||
error_report("Can't use a read-only drive");
|
||||
return -1;
|
||||
}
|
||||
blk_set_perm(s->blk, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE,
|
||||
BLK_PERM_ALL, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return -1;
|
||||
}
|
||||
s->blk_cur = s->blk;
|
||||
}
|
||||
s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT),
|
||||
|
@ -757,6 +757,18 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
|
||||
pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
|
||||
|
||||
if (pfl->blk) {
|
||||
uint64_t perm;
|
||||
pfl->ro = blk_is_read_only(pfl->blk);
|
||||
perm = BLK_PERM_CONSISTENT_READ | (pfl->ro ? 0 : BLK_PERM_WRITE);
|
||||
ret = blk_set_perm(pfl->blk, perm, BLK_PERM_ALL, errp);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
pfl->ro = 0;
|
||||
}
|
||||
|
||||
if (pfl->blk) {
|
||||
/* read the initial flash content */
|
||||
ret = blk_pread(pfl->blk, 0, pfl->storage, total_len);
|
||||
@ -768,12 +780,6 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
if (pfl->blk) {
|
||||
pfl->ro = blk_is_read_only(pfl->blk);
|
||||
} else {
|
||||
pfl->ro = 0;
|
||||
}
|
||||
|
||||
/* Default to devices being used at their maximum device width. This was
|
||||
* assumed before the device_width support was added.
|
||||
*/
|
||||
|
@ -632,6 +632,19 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
|
||||
vmstate_register_ram(&pfl->orig_mem, DEVICE(pfl));
|
||||
pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem);
|
||||
pfl->chip_len = chip_len;
|
||||
|
||||
if (pfl->blk) {
|
||||
uint64_t perm;
|
||||
pfl->ro = blk_is_read_only(pfl->blk);
|
||||
perm = BLK_PERM_CONSISTENT_READ | (pfl->ro ? 0 : BLK_PERM_WRITE);
|
||||
ret = blk_set_perm(pfl->blk, perm, BLK_PERM_ALL, errp);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
pfl->ro = 0;
|
||||
}
|
||||
|
||||
if (pfl->blk) {
|
||||
/* read the initial flash content */
|
||||
ret = blk_pread(pfl->blk, 0, pfl->storage, chip_len);
|
||||
@ -646,12 +659,6 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
|
||||
pfl->rom_mode = 1;
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
|
||||
|
||||
if (pfl->blk) {
|
||||
pfl->ro = blk_is_read_only(pfl->blk);
|
||||
} else {
|
||||
pfl->ro = 0;
|
||||
}
|
||||
|
||||
pfl->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pflash_timer, pfl);
|
||||
pfl->wcycle = 0;
|
||||
pfl->cmd = 0;
|
||||
|
@ -928,7 +928,13 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
|
||||
blkconf_serial(&conf->conf, &conf->serial);
|
||||
blkconf_apply_backend_options(&conf->conf);
|
||||
blkconf_apply_backend_options(&conf->conf,
|
||||
blk_is_read_only(conf->conf.blk), true,
|
||||
&err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
s->original_wce = blk_enable_write_cache(conf->conf.blk);
|
||||
blkconf_geometry(&conf->conf, NULL, 65535, 255, 255, &err);
|
||||
if (err) {
|
||||
|
@ -79,7 +79,6 @@ static void parse_drive(DeviceState *dev, const char *str, void **ptr,
|
||||
if (!blk) {
|
||||
BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL);
|
||||
if (bs) {
|
||||
/* FIXME Use real permissions */
|
||||
blk = blk_new(0, BLK_PERM_ALL);
|
||||
blk_created = true;
|
||||
|
||||
|
@ -170,7 +170,6 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
|
||||
return -1;
|
||||
} else {
|
||||
/* Anonymous BlockBackend for an empty drive */
|
||||
/* FIXME Use real permissions */
|
||||
dev->conf.blk = blk_new(0, BLK_PERM_ALL);
|
||||
}
|
||||
}
|
||||
@ -197,7 +196,12 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
blkconf_apply_backend_options(&dev->conf);
|
||||
blkconf_apply_backend_options(&dev->conf, kind == IDE_CD, kind != IDE_CD,
|
||||
&err);
|
||||
if (err) {
|
||||
error_report_err(err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ide_init_drive(s, dev->conf.blk, kind,
|
||||
dev->version, dev->serial, dev->model, dev->wwn,
|
||||
|
@ -141,9 +141,17 @@ static void rtas_nvram_store(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
static void spapr_nvram_realize(VIOsPAPRDevice *dev, Error **errp)
|
||||
{
|
||||
sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(dev);
|
||||
int ret;
|
||||
|
||||
if (nvram->blk) {
|
||||
nvram->size = blk_getlength(nvram->blk);
|
||||
|
||||
ret = blk_set_perm(nvram->blk,
|
||||
BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE,
|
||||
BLK_PERM_ALL, errp);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
nvram->size = DEFAULT_NVRAM_SIZE;
|
||||
}
|
||||
|
@ -2328,7 +2328,13 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
}
|
||||
blkconf_apply_backend_options(&dev->conf);
|
||||
blkconf_apply_backend_options(&dev->conf,
|
||||
blk_is_read_only(s->qdev.conf.blk),
|
||||
dev->type == TYPE_DISK, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->qdev.conf.discard_granularity == -1) {
|
||||
s->qdev.conf.discard_granularity =
|
||||
@ -2380,7 +2386,6 @@ static void scsi_cd_realize(SCSIDevice *dev, Error **errp)
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
|
||||
|
||||
if (!dev->conf.blk) {
|
||||
/* FIXME Use real permissions */
|
||||
dev->conf.blk = blk_new(0, BLK_PERM_ALL);
|
||||
}
|
||||
|
||||
|
@ -1887,6 +1887,7 @@ static void sd_instance_finalize(Object *obj)
|
||||
static void sd_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SDState *sd = SD_CARD(dev);
|
||||
int ret;
|
||||
|
||||
if (sd->blk && blk_is_read_only(sd->blk)) {
|
||||
error_setg(errp, "Cannot use read-only drive as SD card");
|
||||
@ -1894,6 +1895,11 @@ static void sd_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
|
||||
if (sd->blk) {
|
||||
ret = blk_set_perm(sd->blk, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE,
|
||||
BLK_PERM_ALL, errp);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
blk_set_dev_ops(sd->blk, &sd_block_ops, sd);
|
||||
}
|
||||
}
|
||||
|
@ -603,7 +603,11 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
|
||||
|
||||
blkconf_serial(&s->conf, &dev->serial);
|
||||
blkconf_blocksizes(&s->conf);
|
||||
blkconf_apply_backend_options(&s->conf);
|
||||
blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hack alert: this pretends to be a block device, but it's really
|
||||
|
@ -73,7 +73,8 @@ void blkconf_geometry(BlockConf *conf, int *trans,
|
||||
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
|
||||
Error **errp);
|
||||
void blkconf_blocksizes(BlockConf *conf);
|
||||
void blkconf_apply_backend_options(BlockConf *conf);
|
||||
void blkconf_apply_backend_options(BlockConf *conf, bool readonly,
|
||||
bool resizable, Error **errp);
|
||||
|
||||
/* Hard disk geometry */
|
||||
|
||||
|
@ -179,7 +179,7 @@ q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: Can't use a read-only drive
|
||||
(qemu) QEMU_PROG: Block node is read-only
|
||||
QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed.
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on
|
||||
@ -201,12 +201,12 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive
|
||||
(qemu) QEMU_PROG: -device ide-drive,drive=disk: Block node is read-only
|
||||
QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
(qemu) QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive
|
||||
(qemu) QEMU_PROG: -device ide-hd,drive=disk: Block node is read-only
|
||||
QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
|
||||
|
||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk
|
||||
|
Loading…
Reference in New Issue
Block a user