}
}
-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;
struct FDrive {
FDCtrl *fdctrl;
BlockBackend *blk;
+ BlockConf *conf;
/* Drive status */
FloppyDriveType drive; /* CMOS drive type */
uint8_t perpendicular; /* 2.88 MB access mode */
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;
FloppyDrive *dev = FLOPPY_DRIVE(qdev);
FloppyBus *bus = FLOPPY_BUS(qdev->parent_bus);
FDrive *drive;
+ Error *local_err = NULL;
int ret;
if (dev->unit == -1) {
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);
* 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. */
return -1;
}
+ drive->conf = &dev->conf;
drive->blk = dev->conf.blk;
drive->fdctrl = bus->fdc;
{
Flash *s = M25P80(ss);
M25P80Class *mc = M25P80_GET_CLASS(s);
+ int ret;
s->pi = mc->pi;
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);
{
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;
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;
int i;
int64_t bs_size;
uint8_t *pci_conf;
+ Error *local_err = NULL;
if (!n->conf.blk) {
return -1;
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;
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;
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),
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);
}
}
- 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.
*/
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);
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;
}
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) {
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;
return -1;
} else {
/* Anonymous BlockBackend for an empty drive */
- /* FIXME Use real permissions */
dev->conf.blk = blk_new(0, BLK_PERM_ALL);
}
}
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,
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;
}
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 =
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
if (!dev->conf.blk) {
- /* FIXME Use real permissions */
dev->conf.blk = blk_new(0, BLK_PERM_ALL);
}
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");
}
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);
}
}
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
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 */
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
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