diff --git a/block.c b/block.c index fa0de2552bbd9189990aa473cb99b5622e30e3bf..05c83115b3bdb9238ba67be8d2a095f4362484e7 100644 --- a/block.c +++ b/block.c @@ -331,11 +331,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags) int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, BlockDriver *drv) { - int ret, open_flags; + int ret, open_flags, try_rw; char tmp_filename[PATH_MAX]; char backing_filename[PATH_MAX]; - bs->read_only = 0; bs->is_temporary = 0; bs->encrypted = 0; bs->valid_key = 0; @@ -422,9 +421,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, /* Note: for compatibility, we open disk image files as RDWR, and RDONLY as fallback */ + try_rw = !bs->read_only || bs->is_temporary; if (!(flags & BDRV_O_FILE)) - open_flags = BDRV_O_RDWR | - (flags & (BDRV_O_CACHE_MASK|BDRV_O_NATIVE_AIO)); + open_flags = (try_rw ? BDRV_O_RDWR : 0) | + (flags & (BDRV_O_CACHE_MASK|BDRV_O_NATIVE_AIO)); else open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT); ret = drv->bdrv_open(bs, filename, open_flags); @@ -453,6 +453,8 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, /* if there is a backing file, use it */ BlockDriver *back_drv = NULL; bs->backing_hd = bdrv_new(""); + /* pass on read_only property to the backing_hd */ + bs->backing_hd->read_only = bs->read_only; path_combine(backing_filename, sizeof(backing_filename), filename, bs->backing_file); if (bs->backing_format[0] != '\0') @@ -731,6 +733,8 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset) return -ENOMEDIUM; if (!drv->bdrv_truncate) return -ENOTSUP; + if (bs->read_only) + return -EACCES; return drv->bdrv_truncate(bs, offset); } @@ -925,6 +929,13 @@ int bdrv_is_read_only(BlockDriverState *bs) return bs->read_only; } +int bdrv_set_read_only(BlockDriverState *bs, int read_only) +{ + int ret = bs->read_only; + bs->read_only = read_only; + return ret; +} + int bdrv_is_sg(BlockDriverState *bs) { return bs->sg; diff --git a/block.h b/block.h index a966afb090d399f4a4343d384a706e58e6dcc144..302010d953ad68ac532e21d1302d700608d99d7b 100644 --- a/block.h +++ b/block.h @@ -136,6 +136,7 @@ int bdrv_get_type_hint(BlockDriverState *bs); int bdrv_get_translation_hint(BlockDriverState *bs); int bdrv_is_removable(BlockDriverState *bs); int bdrv_is_read_only(BlockDriverState *bs); +int bdrv_set_read_only(BlockDriverState *bs, int read_only); int bdrv_is_sg(BlockDriverState *bs); int bdrv_enable_write_cache(BlockDriverState *bs); int bdrv_is_inserted(BlockDriverState *bs); diff --git a/qemu-config.c b/qemu-config.c index fc73beaef6c7d1f34533ff966e51464fa3160b44..d83d2a697c453e562fd110bb69285c623daebaa5 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -71,6 +71,9 @@ QemuOptsList qemu_drive_opts = { .name = "addr", .type = QEMU_OPT_STRING, .help = "pci address (virtio only)", + },{ + .name = "readonly", + .type = QEMU_OPT_BOOL, }, { /* end if list */ } }, diff --git a/vl.c b/vl.c index 9031911c513eb2fc15564ec3cd37e8b274c65cc8..613cbdb63f0fce0f22936b97f37feb6a53938b0f 100644 --- a/vl.c +++ b/vl.c @@ -2001,6 +2001,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque, int index; int cache; int aio = 0; + int ro = 0; int bdrv_flags, onerror; const char *devaddr; DriveInfo *dinfo; @@ -2032,6 +2033,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque, secs = qemu_opt_get_number(opts, "secs", 0); snapshot = qemu_opt_get_bool(opts, "snapshot", 0); + ro = qemu_opt_get_bool(opts, "readonly", 0); file = qemu_opt_get(opts, "file"); serial = qemu_opt_get(opts, "serial"); @@ -2323,6 +2325,14 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque, bdrv_flags &= ~BDRV_O_NATIVE_AIO; } + if (ro == 1) { + if (type == IF_IDE) { + fprintf(stderr, "qemu: readonly flag not supported for drive with ide interface\n"); + return NULL; + } + (void)bdrv_set_read_only(dinfo->bdrv, 1); + } + if (bdrv_open2(dinfo->bdrv, file, bdrv_flags, drv) < 0) { fprintf(stderr, "qemu: could not open disk image %s: %s\n", file, strerror(errno));