bool 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; } shared_perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD; if (resizable) { shared_perm |= BLK_PERM_RESIZE; } if (conf->share_rw) { shared_perm |= BLK_PERM_WRITE; } ret = blk_set_perm(blk, perm, shared_perm, errp); if (ret < 0) { return false; } switch (conf->wce) { case ON_OFF_AUTO_ON: wce = true; break; case ON_OFF_AUTO_OFF: wce = false; break; case ON_OFF_AUTO_AUTO: wce = blk_enable_write_cache(blk); break; default: abort(); } rerror = conf->rerror; if (rerror == BLOCKDEV_ON_ERROR_AUTO) { rerror = blk_get_on_error(blk, true); } werror = conf->werror; if (werror == BLOCKDEV_ON_ERROR_AUTO) { werror = blk_get_on_error(blk, false); } blk_set_enable_write_cache(blk, wce); blk_set_on_error(blk, rerror, werror); return true; }
static void scsi_generic_realize(SCSIDevice *s, Error **errp) { int rc; int sg_version; struct sg_scsi_id scsiid; if (!s->conf.blk) { error_setg(errp, "drive property not set"); return; } if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) { error_setg(errp, "Device doesn't support drive option werror"); return; } if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) { error_setg(errp, "Device doesn't support drive option rerror"); return; } /* check we are using a driver managing SG_IO (version 3 and after */ rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version); if (rc < 0) { error_setg(errp, "cannot get SG_IO version number: %s. " "Is this a SCSI device?", strerror(-rc)); return; } if (sg_version < 30000) { error_setg(errp, "scsi generic interface too old"); return; } /* get LUN of the /dev/sg? */ if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) { error_setg(errp, "SG_GET_SCSI_ID ioctl failed"); return; } /* define device state */ s->type = scsiid.scsi_type; DPRINTF("device type %d\n", s->type); switch (s->type) { case TYPE_TAPE: s->blocksize = get_stream_blocksize(s->conf.blk); if (s->blocksize == -1) { s->blocksize = 0; } break; /* Make a guess for block devices, we'll fix it when the guest sends. * READ CAPACITY. If they don't, they likely would assume these sizes * anyway. (TODO: they could also send MODE SENSE). */ case TYPE_ROM: case TYPE_WORM: s->blocksize = 2048; break; default: s->blocksize = 512; break; } DPRINTF("block size %d\n", s->blocksize); }