summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block.c19
-rw-r--r--block.h1
-rw-r--r--qemu-config.c3
-rw-r--r--vl.c10
4 files changed, 29 insertions, 4 deletions
diff --git a/block.c b/block.c
index fa0de2552b..05c83115b3 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 a966afb090..302010d953 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 fc73beaef6..d83d2a697c 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 9031911c51..613cbdb63f 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));