yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone
76daa3
From 04ecb169e46d027d3c5ac0ec2277e10065fa8c9c Mon Sep 17 00:00:00 2001
76daa3
From: Jeffrey Cody <jcody@redhat.com>
76daa3
Date: Wed, 26 Apr 2017 20:08:49 +0200
76daa3
Subject: [PATCH 03/11] block: do not set BDS read_only if copy_on_read enabled
76daa3
76daa3
RH-Author: Jeffrey Cody <jcody@redhat.com>
76daa3
Message-id: <efae6a340b7c2c2e7d70448235287e477ca96baa.1493236824.git.jcody@redhat.com>
76daa3
Patchwork-id: 74897
76daa3
O-Subject: [RHEV-7.4 qemu-kvm-rhev 2/8] block: do not set BDS read_only if copy_on_read enabled
76daa3
Bugzilla: 1189998
76daa3
RH-Acked-by: John Snow <jsnow@redhat.com>
76daa3
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
76daa3
RH-Acked-by: Max Reitz <mreitz@redhat.com>
76daa3
76daa3
A few block drivers will set the BDS read_only flag from their
76daa3
.bdrv_open() function.  This means the bs->read_only flag could
76daa3
be set after we enable copy_on_read, as the BDRV_O_COPY_ON_READ
76daa3
flag check occurs prior to the call to bdrv->bdrv_open().
76daa3
76daa3
This adds an error return to bdrv_set_read_only(), and an error will be
76daa3
return if we try to set the BDS to read_only while copy_on_read is
76daa3
enabled.
76daa3
76daa3
This patch also changes the behavior of vvfat.  Before, vvfat could
76daa3
override the drive 'readonly' flag with its own, internal 'rw' flag.
76daa3
76daa3
For instance, this -drive parameter would result in a writable image:
76daa3
76daa3
"-drive format=vvfat,dir=/tmp/vvfat,rw,if=virtio,readonly=on"
76daa3
76daa3
This is not correct.  Now, attempting to use the above -drive parameter
76daa3
will result in an error (i.e., 'rw' is incompatible with 'readonly=on').
76daa3
76daa3
Signed-off-by: Jeff Cody <jcody@redhat.com>
76daa3
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
76daa3
Reviewed-by: John Snow <jsnow@redhat.com>
76daa3
Message-id: 0c5b4c1cc2c651471b131f21376dfd5ea24d2196.1491597120.git.jcody@redhat.com
76daa3
(cherry picked from commit e2b8247a322cd92945785edf25f09e6b3e8285f9)
76daa3
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
76daa3
---
76daa3
 block.c               | 10 +++++++++-
76daa3
 block/bochs.c         |  5 ++++-
76daa3
 block/cloop.c         |  5 ++++-
76daa3
 block/dmg.c           |  6 +++++-
76daa3
 block/rbd.c           | 11 ++++++++++-
76daa3
 block/vvfat.c         | 19 +++++++++++++++----
76daa3
 include/block/block.h |  2 +-
76daa3
 7 files changed, 48 insertions(+), 10 deletions(-)
76daa3
76daa3
diff --git a/block.c b/block.c
76daa3
index 25a4cfd..4766b8a 100644
76daa3
--- a/block.c
76daa3
+++ b/block.c
76daa3
@@ -192,9 +192,17 @@ void path_combine(char *dest, int dest_size,
76daa3
     }
76daa3
 }
76daa3
 
76daa3
-void bdrv_set_read_only(BlockDriverState *bs, bool read_only)
76daa3
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
76daa3
 {
76daa3
+    /* Do not set read_only if copy_on_read is enabled */
76daa3
+    if (bs->copy_on_read && read_only) {
76daa3
+        error_setg(errp, "Can't set node '%s' to r/o with copy-on-read enabled",
76daa3
+                   bdrv_get_device_or_node_name(bs));
76daa3
+        return -EINVAL;
76daa3
+    }
76daa3
+
76daa3
     bs->read_only = read_only;
76daa3
+    return 0;
76daa3
 }
76daa3
 
76daa3
 void bdrv_get_full_backing_filename_from_filename(const char *backed,
76daa3
diff --git a/block/bochs.c b/block/bochs.c
76daa3
index bdc2831..a759b6e 100644
76daa3
--- a/block/bochs.c
76daa3
+++ b/block/bochs.c
76daa3
@@ -110,7 +110,10 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
76daa3
         return -EINVAL;
76daa3
     }
76daa3
 
76daa3
-    bdrv_set_read_only(bs, true); /* no write support yet */
76daa3
+    ret = bdrv_set_read_only(bs, true, errp); /* no write support yet */
76daa3
+    if (ret < 0) {
76daa3
+        return ret;
76daa3
+    }
76daa3
 
76daa3
     ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
76daa3
     if (ret < 0) {
76daa3
diff --git a/block/cloop.c b/block/cloop.c
76daa3
index 11f17c8..d6597fc 100644
76daa3
--- a/block/cloop.c
76daa3
+++ b/block/cloop.c
76daa3
@@ -72,7 +72,10 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
76daa3
         return -EINVAL;
76daa3
     }
76daa3
 
76daa3
-    bdrv_set_read_only(bs, true);
76daa3
+    ret = bdrv_set_read_only(bs, true, errp);
76daa3
+    if (ret < 0) {
76daa3
+        return ret;
76daa3
+    }
76daa3
 
76daa3
     /* read header */
76daa3
     ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
76daa3
diff --git a/block/dmg.c b/block/dmg.c
76daa3
index 27ce4a6..900ae5a 100644
76daa3
--- a/block/dmg.c
76daa3
+++ b/block/dmg.c
76daa3
@@ -419,8 +419,12 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
76daa3
         return -EINVAL;
76daa3
     }
76daa3
 
76daa3
+    ret = bdrv_set_read_only(bs, true, errp);
76daa3
+    if (ret < 0) {
76daa3
+        return ret;
76daa3
+    }
76daa3
+
76daa3
     block_module_load_one("dmg-bz2");
76daa3
-    bdrv_set_read_only(bs, true);
76daa3
 
76daa3
     s->n_chunks = 0;
76daa3
     s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
76daa3
diff --git a/block/rbd.c b/block/rbd.c
76daa3
index 6ad2904..1c43171 100644
76daa3
--- a/block/rbd.c
76daa3
+++ b/block/rbd.c
76daa3
@@ -635,13 +635,22 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
76daa3
         goto failed_shutdown;
76daa3
     }
76daa3
 
76daa3
+    /* rbd_open is always r/w */
76daa3
     r = rbd_open(s->io_ctx, s->name, &s->image, s->snap);
76daa3
     if (r < 0) {
76daa3
         error_setg_errno(errp, -r, "error reading header from %s", s->name);
76daa3
         goto failed_open;
76daa3
     }
76daa3
 
76daa3
-    bdrv_set_read_only(bs, (s->snap != NULL));
76daa3
+    /* If we are using an rbd snapshot, we must be r/o, otherwise
76daa3
+     * leave as-is */
76daa3
+    if (s->snap != NULL) {
76daa3
+        r = bdrv_set_read_only(bs, true, &local_err);
76daa3
+        if (r < 0) {
76daa3
+            error_propagate(errp, local_err);
76daa3
+            goto failed_open;
76daa3
+        }
76daa3
+    }
76daa3
 
76daa3
     qemu_opts_del(opts);
76daa3
     return 0;
76daa3
diff --git a/block/vvfat.c b/block/vvfat.c
76daa3
index d4ce6d7..b509d55 100644
76daa3
--- a/block/vvfat.c
76daa3
+++ b/block/vvfat.c
76daa3
@@ -1156,8 +1156,6 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
76daa3
 
76daa3
     s->current_cluster=0xffffffff;
76daa3
 
76daa3
-    /* read only is the default for safety */
76daa3
-    bdrv_set_read_only(bs, true);
76daa3
     s->qcow = NULL;
76daa3
     s->qcow_filename = NULL;
76daa3
     s->fat2 = NULL;
76daa3
@@ -1169,11 +1167,24 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
76daa3
     s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1);
76daa3
 
76daa3
     if (qemu_opt_get_bool(opts, "rw", false)) {
76daa3
-        ret = enable_write_target(bs, errp);
76daa3
+        if (!bdrv_is_read_only(bs)) {
76daa3
+            ret = enable_write_target(bs, errp);
76daa3
+            if (ret < 0) {
76daa3
+                goto fail;
76daa3
+            }
76daa3
+        } else {
76daa3
+            ret = -EPERM;
76daa3
+            error_setg(errp,
76daa3
+                       "Unable to set VVFAT to 'rw' when drive is read-only");
76daa3
+            goto fail;
76daa3
+        }
76daa3
+    } else  {
76daa3
+        /* read only is the default for safety */
76daa3
+        ret = bdrv_set_read_only(bs, true, &local_err);
76daa3
         if (ret < 0) {
76daa3
+            error_propagate(errp, local_err);
76daa3
             goto fail;
76daa3
         }
76daa3
-        bdrv_set_read_only(bs, false);
76daa3
     }
76daa3
 
76daa3
     bs->total_sectors = cyls * heads * secs;
76daa3
diff --git a/include/block/block.h b/include/block/block.h
76daa3
index 16eb909..3525590 100644
76daa3
--- a/include/block/block.h
76daa3
+++ b/include/block/block.h
76daa3
@@ -434,7 +434,7 @@ int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
76daa3
                             int64_t sector_num, int nb_sectors, int *pnum);
76daa3
 
76daa3
 bool bdrv_is_read_only(BlockDriverState *bs);
76daa3
-void bdrv_set_read_only(BlockDriverState *bs, bool read_only);
76daa3
+int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
76daa3
 bool bdrv_is_sg(BlockDriverState *bs);
76daa3
 bool bdrv_is_inserted(BlockDriverState *bs);
76daa3
 int bdrv_media_changed(BlockDriverState *bs);
76daa3
-- 
76daa3
1.8.3.1
76daa3