qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Naphtali Sprei <nsprei@redhat.com>
To: qemu-devel@nongnu.org
Cc: Naphtali Sprei <nsprei@redhat.com>
Subject: [Qemu-devel] [PATCH v2 resend 3/4] Block: readonly changes
Date: Fri,  5 Feb 2010 00:04:28 +0200	[thread overview]
Message-ID: <1265321069-4105-4-git-send-email-nsprei@redhat.com> (raw)
In-Reply-To: <1265321069-4105-3-git-send-email-nsprei@redhat.com>

Open backing file for read-only
During commit upgrade to read-write and back at end to read-only

Signed-off-by: Naphtali Sprei <nsprei@redhat.com>
---
 block.c     |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 block_int.h |    1 +
 2 files changed, 61 insertions(+), 8 deletions(-)

diff --git a/block.c b/block.c
index 66564de..4a9df91 100644
--- a/block.c
+++ b/block.c
@@ -451,7 +451,6 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
     if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))
         bs->enable_write_cache = 1;
 
-    bs->read_only = (flags & BDRV_O_RDWR) == 0;
     if (!(flags & BDRV_O_FILE)) {
         open_flags = (flags & (BDRV_O_RDWR | BDRV_O_CACHE_MASK|BDRV_O_NATIVE_AIO));
         if (bs->is_temporary) { /* snapshot should be writeable */
@@ -466,6 +465,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
         goto free_and_fail;
     }
 
+    bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
     if (drv->bdrv_getlength) {
         bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
     }
@@ -482,13 +482,28 @@ 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 &= ~BDRV_O_RDWR; /* clear RW, then restore from orig */
+        if (bs->is_temporary) {
+            open_flags |= (flags & BDRV_O_RDWR);
+        }
+        
         ret = bdrv_open2(bs->backing_hd, backing_filename, open_flags,
                          back_drv);
-        bs->backing_hd->read_only =  (open_flags & BDRV_O_RDWR) == 0;
+        if (ret < 0) {
+            open_flags &= ~BDRV_O_RDWR;  /* Fall-back to read-only for the backing file */
+            ret = bdrv_open2(bs->backing_hd, backing_filename, open_flags,
+                             back_drv);
+        }
         if (ret < 0) {
             bdrv_close(bs);
             return ret;
         }
+        if (!bs->is_temporary) {
+            bs->backing_hd->keep_read_only = bs->keep_read_only; /* base image inherits from "parent" and open read-only */
+        } else {
+            bs->backing_hd->keep_read_only = !(flags & BDRV_O_RDWR);
+        }
     }
 
     if (!bdrv_key_required(bs)) {
@@ -564,19 +579,38 @@ int bdrv_commit(BlockDriverState *bs)
 {
     BlockDriver *drv = bs->drv;
     int64_t i, total_sectors;
-    int n, j;
+    int n, j, ro, open_flags;
     int ret = 0;
     unsigned char sector[512];
+    char filename[1024];
+    BlockDriverState *bs_rw, *bs_ro;
 
     if (!drv)
         return -ENOMEDIUM;
+    
+    if (!bs->backing_hd) {
+	return -ENOTSUP;
+    }
 
-    if (bs->read_only) {
+    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 (!bs->backing_hd) {
-	return -ENOTSUP;
+    if (ro) { /* re-open as RW */
+        bdrv_close(bs->backing_hd);
+        qemu_free(bs->backing_hd);
+
+        bs_rw = bdrv_new("");
+        ret = bdrv_open2(bs_rw, filename, open_flags | BDRV_O_RDWR, NULL);
+        if (ret < 0) {
+            bdrv_delete(bs_rw);
+            return -EACCES;
+        }
+        bs->backing_hd = bs_rw;
     }
 
     total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
@@ -584,11 +618,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++;
 	    }
@@ -608,6 +644,22 @@ int bdrv_commit(BlockDriverState *bs)
      */
     if (bs->backing_hd)
         bdrv_flush(bs->backing_hd);
+
+ro_cleanup:
+
+    if (ro) { /* re-open as RO */
+        bdrv_close(bs->backing_hd);
+        qemu_free(bs->backing_hd);
+        bs_ro = bdrv_new("");
+        ret = bdrv_open2(bs_ro, filename, open_flags & ~BDRV_O_RDWR, NULL);
+        if (ret < 0) {
+            bdrv_delete(bs_ro);
+            return -EACCES;
+        }
+        bs->backing_hd = bs_ro;
+        bs->backing_hd->keep_read_only = 0;
+    }
+
     return ret;
 }
 
diff --git a/block_int.h b/block_int.h
index 9144d37..02fae5b 100644
--- a/block_int.h
+++ b/block_int.h
@@ -130,6 +130,7 @@ 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 */
     int removable; /* if true, the media can be removed */
     int locked;    /* if true, the media cannot temporarily be ejected */
-- 
1.6.3.3

  reply	other threads:[~2010-02-04 22:04 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-04 22:04 [Qemu-devel] [PATCH v2 resend 0/4] block: more read-only changes, related to backing files Naphtali Sprei
2010-02-04 22:04 ` [Qemu-devel] [PATCH v2 resend 1/4] Add open_flags to BlockDriverState Will be used later Naphtali Sprei
2010-02-04 22:04   ` [Qemu-devel] [PATCH v2 resend 2/4] qemu-img: Fix qemu-img can't create qcow image based on read-only image Naphtali Sprei
2010-02-04 22:04     ` Naphtali Sprei [this message]
2010-02-04 22:04       ` [Qemu-devel] [PATCH v2 resend 4/4] Open backing file read-only also for snapshot mode Naphtali Sprei
2010-02-05  8:20       ` [Qemu-devel] [PATCH v2 resend 3/4] Block: readonly changes Kevin Wolf
2010-02-05  2:45     ` [Qemu-devel] [PATCH v2 resend 2/4] qemu-img: Fix qemu-img can't create qcow image based on read-only image Sheng Yang
2010-02-05  2:46 ` [Qemu-devel] [PATCH v2 resend 0/4] block: more read-only changes, related to backing files Sheng Yang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1265321069-4105-4-git-send-email-nsprei@redhat.com \
    --to=nsprei@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).