All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Daniel P. Berrange" <berrange@redhat.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] PATCH: v3 Allow control over drive file open mode
Date: Fri, 1 Aug 2008 11:29:52 +0100	[thread overview]
Message-ID: <20080801102949.GN23993@redhat.com> (raw)

This is version 3 of the patch.

The current block driver code will attempt to open a file backing a drive
for read/write with O_RDWR first, and if that fails, fallback to opening
it readonly with O_RDONLY. So if you set file permissions to readonly on
the underlying drive backing store, QEMU will fallback to opening it read
only, and discard any writes.

Xen has a concept of a read-only disks in its configuration format, and
thus it would be desirable to have an explicit option to request that a
drive operate read-only, regardless of whether underlying file permissions
allow write access or not. We'd like to support this in libvirt too for
QEMU/KVM guests. Finally, in some cases it is desirable to see the failure
if the disk can't be opened read-write, rather than falling back to read
only mode - many guests will be more or less inoperable if their root
filesystem is read-only so there's little point booting.

The current block.h file did already have flags defined

  #define BDRV_O_RDONLY      0x0000
  #define BDRV_O_RDWR        0x0002
  #define BDRV_O_ACCESS      0x0003

However the bdrv_open2() method was treating a 'flags' value of 0, as being
effectively RDWR, and nearly all callers pass in 0 even when they expect
to get a writable file, so the O_RDONLY flag was not usable as is.

So this patch does a couple of things:

 - Change the value of the RDONLY flag to be 0x0001  so it can be
   distinguished from 0, which all callers assume means read-write
   will read-only fallback.

 - Adds a new option to the '-drive' command line parameter to specify
   how the file should be opened, and any fallback

     mode=rw  - try to open read-write and return error if this fails.
     mode=ro  - try to open read-only and return error if this fails

   If no 'mode' is provided, it'll try read-write, and fallback to
   read-only. This matches existing behaviour

 - Extends the monitor 'change' command to allow an optional mode to
   be specified, again defaulting to current behaviour. Takes the same
   values as the 'mode' param

   Signed-off-by: Daniel P. Berrange <berrange@redhat.com>


 block-raw-posix.c |    6 +++---
 block-raw-win32.c |    4 ++--
 block.c           |   21 ++++++++++++++-------
 block.h           |    5 ++---
 monitor.c         |   20 ++++++++++++++------
 qemu-doc.texi     |    4 ++++
 qemu-nbd.c        |    3 +++
 vl.c              |   15 ++++++++++++---
 8 files changed, 54 insertions(+), 24 deletions(-)

NB This is against SVN revision 4975, but will likely conflict with 
the other patch currently being discussed onlist wrt to qcow encryption
and passwords. I can trivially rebase it if required.


Daniel

Index: block-raw-win32.c
===================================================================
--- block-raw-win32.c	(revision 4975)
+++ block-raw-win32.c	(working copy)
@@ -90,7 +90,7 @@
 
     s->type = FTYPE_FILE;
 
-    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
+    if (!(flags & BDRV_O_RDONLY)) {
         access_flags = GENERIC_READ | GENERIC_WRITE;
     } else {
         access_flags = GENERIC_READ;
@@ -463,7 +463,7 @@
     }
     s->type = find_device_type(bs, filename);
 
-    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
+    if (!(flags & BDRV_O_RDONLY)) {
         access_flags = GENERIC_READ | GENERIC_WRITE;
     } else {
         access_flags = GENERIC_READ;
Index: vl.c
===================================================================
--- vl.c	(revision 4975)
+++ vl.c	(working copy)
@@ -5399,11 +5399,12 @@
     int max_devs;
     int index;
     int cache;
+    int mode = 0;  /* Default to writable, with fallback to readonly for back-compat */
     int bdrv_flags;
     char *str = arg->opt;
     char *params[] = { "bus", "unit", "if", "index", "cyls", "heads",
                        "secs", "trans", "media", "snapshot", "file",
-                       "cache", "format", NULL };
+                       "cache", "format", "mode", NULL };
 
     if (check_params(buf, sizeof(buf), params, str) < 0) {
          fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
@@ -5585,6 +5586,14 @@
         }
     }
 
+    if (get_param_value(buf, sizeof(buf), "mode", str)) {
+        if (strcmp(buf, "ro") == 0)
+            mode = BDRV_O_RDONLY;
+        else if (strcmp(buf, "rw") == 0)
+            mode = BDRV_O_RDWR;
+    }
+
+
     if (arg->file == NULL)
         get_param_value(file, sizeof(file), "file", str);
     else
@@ -5682,7 +5691,7 @@
     }
     if (!file[0])
         return 0;
-    bdrv_flags = 0;
+    bdrv_flags = mode;
     if (snapshot)
         bdrv_flags |= BDRV_O_SNAPSHOT;
     if (!cache)
@@ -7605,7 +7614,7 @@
            "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
 	   "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
            "       [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
-           "       [,cache=on|off][,format=f]\n"
+           "       [,cache=on|off][,format=f][,mode=ro|rw]\n"
 	   "                use 'file' as a drive image\n"
            "-mtdblock file  use 'file' as on-board Flash memory image\n"
            "-sd file        use 'file' as SecureDigital card image\n"
Index: block-raw-posix.c
===================================================================
--- block-raw-posix.c	(revision 4975)
+++ block-raw-posix.c	(working copy)
@@ -103,7 +103,7 @@
     s->lseek_err_cnt = 0;
 
     open_flags = O_BINARY;
-    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
+    if (!(flags & BDRV_O_RDONLY)) {
         open_flags |= O_RDWR;
     } else {
         open_flags |= O_RDONLY;
@@ -117,7 +117,7 @@
 #endif
 
     s->type = FTYPE_FILE;
-
+    fprintf(stderr, "Open raw %d %d %s\n", open_flags, flags, filename);
     fd = open(filename, open_flags, 0644);
     if (fd < 0) {
         ret = -errno;
@@ -896,7 +896,7 @@
     }
 #endif
     open_flags = O_BINARY;
-    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
+    if (!(flags & BDRV_O_RDONLY)) {
         open_flags |= O_RDWR;
     } else {
         open_flags |= O_RDONLY;
Index: qemu-nbd.c
===================================================================
--- qemu-nbd.c	(revision 4975)
+++ qemu-nbd.c	(working copy)
@@ -332,6 +332,9 @@
     if (bs == NULL)
         return 1;
 
+    if (readonly)
+        flags |= BDRV_O_RDONLY;
+
     if (bdrv_open(bs, argv[optind], flags) == -1)
         return 1;
 
Index: qemu-doc.texi
===================================================================
--- qemu-doc.texi	(revision 4975)
+++ qemu-doc.texi	(working copy)
@@ -268,6 +268,10 @@
 @var{snapshot} is "on" or "off" and allows to enable snapshot for given drive (see @option{-snapshot}).
 @item cache=@var{cache}
 @var{cache} is "on" or "off" and allows to disable host cache to access data.
+@item mode=@var{mode}
+@var{mode} is "rw" to open the file read-write, or "ro" to open the file read-only.
+If neither is specified, an attempt will be made to open read-write, falling back
+to read-only if this fails.
 @item format=@var{format}
 Specify which disk @var{format} will be used rather than detecting
 the format.  Can be used to specifiy format=raw to avoid interpreting
Index: monitor.c
===================================================================
--- monitor.c	(revision 4975)
+++ monitor.c	(working copy)
@@ -396,11 +396,19 @@
     eject_device(bs, force);
 }
 
-static void do_change_block(const char *device, const char *filename, const char *fmt)
+static void do_change_block(const char *device, const char *filename, const char *fmt, const char *mode)
 {
     BlockDriverState *bs;
     BlockDriver *drv = NULL;
+    int flags = 0;
 
+    if (mode) {
+        if (strcmp(mode, "ro") == 0)
+            flags = BDRV_O_RDONLY;
+        else if (strcmp(mode, "rw") == 0)
+            flags = BDRV_O_RDWR;
+    }
+
     bs = bdrv_find(device);
     if (!bs) {
         term_printf("device not found\n");
@@ -415,7 +423,7 @@
     }
     if (eject_device(bs, 0) < 0)
         return;
-    bdrv_open2(bs, filename, 0, drv);
+    bdrv_open2(bs, filename, flags, drv);
     qemu_key_check(bs, filename);
 }
 
@@ -434,12 +442,12 @@
     }
 }
 
-static void do_change(const char *device, const char *target, const char *fmt)
+static void do_change(const char *device, const char *target, const char *fmt, const char *mode)
 {
     if (strcmp(device, "vnc") == 0) {
 	do_change_vnc(target);
     } else {
-	do_change_block(device, target, fmt);
+	do_change_block(device, target, fmt, mode);
     }
 }
 
@@ -1374,8 +1382,8 @@
       "", "quit the emulator" },
     { "eject", "-fB", do_eject,
       "[-f] device", "eject a removable medium (use -f to force it)" },
-    { "change", "BFs?", do_change,
-      "device filename [format]", "change a removable medium, optional format" },
+    { "change", "BFs?s?", do_change,
+      "device filename [format] [mode]", "change a removable medium, optional format and mode" },
     { "screendump", "F", do_screen_dump,
       "filename", "save screen into PPM image 'filename'" },
     { "logfile", "F", do_logfile,
Index: block.c
===================================================================
--- block.c	(revision 4975)
+++ block.c	(working copy)
@@ -381,17 +381,24 @@
     bs->opaque = qemu_mallocz(drv->instance_size);
     if (bs->opaque == NULL && drv->instance_size > 0)
         return -1;
-    /* Note: for compatibility, we open disk image files as RDWR, and
-       RDONLY as fallback */
+    /* If BDRV_O_RDONLY is set open in read only mode
+     * If BDRV_O_RDWR is set open in read write mode
+     * If neither is set, try read-write and fallback to read only
+     */
     if (!(flags & BDRV_O_FILE))
-        open_flags = BDRV_O_RDWR | (flags & BDRV_O_DIRECT);
+        open_flags = (flags & (BDRV_O_DIRECT | BDRV_O_RDONLY | BDRV_O_RDWR));
     else
         open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
     ret = drv->bdrv_open(bs, filename, open_flags);
-    if (ret == -EACCES && !(flags & BDRV_O_FILE)) {
-        ret = drv->bdrv_open(bs, filename, BDRV_O_RDONLY);
+
+    /* Trying fallback to read only mode here.. */
+    if (ret == -EACCES &&
+	!(flags & (BDRV_O_RDWR | BDRV_O_RDONLY))) {
+        open_flags |= BDRV_O_RDONLY;
+        ret = drv->bdrv_open(bs, filename, open_flags);
+    }
+    if (ret == 0 && (flags & BDRV_O_RDONLY))
         bs->read_only = 1;
-    }
     if (ret < 0) {
         qemu_free(bs->opaque);
         bs->opaque = NULL;
@@ -416,7 +423,7 @@
         }
         path_combine(backing_filename, sizeof(backing_filename),
                      filename, bs->backing_file);
-        if (bdrv_open(bs->backing_hd, backing_filename, 0) < 0)
+        if (bdrv_open(bs->backing_hd, backing_filename, flags & (BDRV_O_RDONLY | BDRV_O_RDWR)) < 0)
             goto fail;
     }
 
Index: block.h
===================================================================
--- block.h	(revision 4975)
+++ block.h	(working copy)
@@ -36,9 +36,8 @@
     uint64_t vm_clock_nsec; /* VM clock relative to boot */
 } QEMUSnapshotInfo;
 
-#define BDRV_O_RDONLY      0x0000
-#define BDRV_O_RDWR        0x0002
-#define BDRV_O_ACCESS      0x0003
+#define BDRV_O_RDONLY      0x0001 /* Open as read-only */
+#define BDRV_O_RDWR        0x0002 /* Open as read-write */
 #define BDRV_O_CREAT       0x0004 /* create an empty file */
 #define BDRV_O_SNAPSHOT    0x0008 /* open the file read only and save writes in a snapshot */
 #define BDRV_O_FILE        0x0010 /* open as a raw file (do not try to


-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

             reply	other threads:[~2008-08-01 10:30 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-01 10:29 Daniel P. Berrange [this message]
2008-08-01 15:10 ` [Qemu-devel] PATCH: v3 Allow control over drive file open mode Anthony Liguori
2008-08-01 16:15   ` Daniel P. Berrange
2008-08-01 16:23     ` Andreas Färber
2008-08-01 17:06     ` Jamie Lokier
2008-08-01 16:57   ` Ian Jackson
2008-08-01 17:14     ` Anthony Liguori
2008-08-01 17:27       ` Jamie Lokier
2008-08-11 16:05       ` Ian Jackson
2008-08-12 11:42         ` Kevin Wolf
2008-08-12 13:31         ` Anthony Liguori
2008-08-12 23:56           ` Jamie Lokier

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=20080801102949.GN23993@redhat.com \
    --to=berrange@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.