Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 340e01248478ba8b78a6d4d1809b1eff > files > 744

kvm-83-270.el5_11.src.rpm

From 1da9bf2f6b56e814f6e26465f79c16c2b7455aca Mon Sep 17 00:00:00 2001
From: Naphtali Sprei <nsprei@redhat.com>
Date: Thu, 15 Apr 2010 11:56:45 -0300
Subject: [PATCH 09/12] read-only: Open backing file read-only where possible

RH-Author: Naphtali Sprei <nsprei@redhat.com>
Message-id: <1271332608-5243-9-git-send-email-nsprei@redhat.com>
Patchwork-id: 8656
O-Subject: [RHEL 5.6 kvm PATCH v4 08/11] read-only: Open backing file read-only
	where possible
Bugzilla: 510630
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Christoph Hellwig <chellwig@redhat.com>
RH-Acked-by: Juan Quintela <quintela@redhat.com>

Open backing file read-only where possible
Upgrade backing file to read-write during commit, back to read-only after commit
If upgrade fail, back to read-only. If also fail, "disconnect" the drive.

based on upstream commit: 4dca4b639cb20fee38f6eec0a391aecc0ad8848d

Signed-off-by: Naphtali Sprei <nsprei@redhat.com>
---
 qemu/block.c     |   78 +++++++++++++++++++++++++++++++++++++++++++++++------
 qemu/block_int.h |    2 +
 2 files changed, 71 insertions(+), 9 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 qemu/block.c     |   78 +++++++++++++++++++++++++++++++++++++++++++++++------
 qemu/block_int.h |    2 +
 2 files changed, 71 insertions(+), 9 deletions(-)

diff --git a/qemu/block.c b/qemu/block.c
index cfbd3da..fb6c657 100644
--- a/qemu/block.c
+++ b/qemu/block.c
@@ -392,6 +392,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
     bs->read_only = 0;
     bs->is_temporary = 0;
     bs->encrypted = 0;
+    bs->open_flags = flags;
 
     if (flags & BDRV_O_SNAPSHOT) {
         BlockDriverState *bs1;
@@ -476,7 +477,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
         ret = -ENOTSUP;
     else
         ret = drv->bdrv_open(bs, filename, open_flags);
-    bs->read_only = !(open_flags & BDRV_O_RDWR);
+    bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
     if (ret < 0) {
         qemu_free(bs->opaque);
         bs->opaque = NULL;
@@ -504,11 +505,19 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
                      filename, bs->backing_file);
         if (bs->backing_format[0] != '\0')
             back_drv = bdrv_find_format(bs->backing_format);
-        open_flags = (flags & (BDRV_O_CACHE_MASK | BDRV_O_RDWR));
+        /* backing files always opened read-only */
+        open_flags &= ~BDRV_O_RDWR;
         ret = bdrv_open2(bs->backing_hd, backing_filename, open_flags,
                          back_drv);
         if (ret < 0)
             goto fail;
+
+        if (bs->is_temporary) {
+            bs->backing_hd->keep_read_only = !(flags & BDRV_O_RDWR);
+        } else {
+            /* base image inherits from "parent" */
+            bs->backing_hd->keep_read_only = bs->keep_read_only;
+        }
     }
 
     /* call the change callback */
@@ -575,17 +584,48 @@ int bdrv_commit(BlockDriverState *bs)
     BlockDriver *drv = bs->drv;
     int64_t i, total_sectors;
     int n, j;
+    int ro, open_flags;
+    int ret = 0, rw_ret = 0;
+    char filename[1024];
+    BlockDriverState *bs_rw, *bs_ro;
     unsigned char sector[512];
 
     if (!drv)
         return -ENOMEDIUM;
 
-    if (bs->read_only) {
-	return -EACCES;
+    if (!bs->backing_hd) {
+        return -ENOTSUP;
     }
 
-    if (!bs->backing_hd) {
-	return -ENOTSUP;
+    if (bs->backing_hd->keep_read_only) {
+        return -EACCES;
+    }
+
+    ro = bs->backing_hd->read_only;
+    strncpy(filename, bs->backing_hd->filename, sizeof(filename));
+    open_flags =  bs->backing_hd->open_flags;
+
+    if (ro) {
+        /* re-open as RW */
+        bdrv_delete(bs->backing_hd);
+        bs->backing_hd = NULL;
+        bs_rw = bdrv_new("");
+        rw_ret = bdrv_open2(bs_rw, filename, open_flags | BDRV_O_RDWR, NULL);
+        if (rw_ret < 0) {
+            bdrv_delete(bs_rw);
+            /* try to re-open read-only */
+            bs_ro = bdrv_new("");
+            ret = bdrv_open2(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL);
+            if (ret < 0) {
+                bdrv_delete(bs_ro);
+                /* drive not functional anymore */
+                bs->drv = NULL;
+                return ret;
+            }
+            bs->backing_hd = bs_ro;
+            return rw_ret;
+        }
+        bs->backing_hd = bs_rw;
     }
 
     total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
@@ -593,11 +633,13 @@ int bdrv_commit(BlockDriverState *bs)
         if (drv->bdrv_is_allocated(bs, i, 65536, &n)) {
             for(j = 0; j < n; j++) {
                 if (bdrv_read(bs, i, sector, 1) != 0) {
-                    return -EIO;
+                    ret = -EIO;
+                    goto ro_cleanup;
                 }
 
                 if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
-                    return -EIO;
+                    ret = -EIO;
+                    goto ro_cleanup;
                 }
                 i++;
 	    }
@@ -607,7 +649,25 @@ int bdrv_commit(BlockDriverState *bs)
     }
 
     if (drv->bdrv_make_empty)
-	return drv->bdrv_make_empty(bs);
+	ret = drv->bdrv_make_empty(bs);
+
+ro_cleanup:
+
+    if (ro) {
+        /* re-open as RO */
+        bdrv_delete(bs->backing_hd);
+        bs->backing_hd = NULL;
+        bs_ro = bdrv_new("");
+        ret = bdrv_open2(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL);
+        if (ret < 0) {
+            bdrv_delete(bs_ro);
+            /* drive not functional anymore */
+            bs->drv = NULL;
+            return ret;
+        }
+        bs->backing_hd = bs_ro;
+        bs->backing_hd->keep_read_only = 0;
+    }
 
     return 0;
 }
diff --git a/qemu/block_int.h b/qemu/block_int.h
index 2f8093c..634c29b 100644
--- a/qemu/block_int.h
+++ b/qemu/block_int.h
@@ -112,6 +112,8 @@ struct BlockDriverState {
     int64_t total_sectors; /* if we are reading a disk image, give its
                               size in sectors */
     int read_only; /* if true, the media is read only */
+    int keep_read_only; /* if true, the media was requested to stay read only */
+    int open_flags; /* flags used to open the file, re-used for re-open */
     int removable; /* if true, the media can be removed */
     int locked;    /* if true, the media cannot temporarily be ejected */
     int encrypted; /* if true, the media is encrypted */
-- 
1.7.0.3