* [Qemu-devel] [PATCH] block: add read only to whitelist
@ 2013-05-28 6:44 Fam Zheng
2013-05-28 8:00 ` Kevin Wolf
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Fam Zheng @ 2013-05-28 6:44 UTC (permalink / raw)
To: qemu-devel; +Cc: kwolf, jcody, Fam Zheng, stefanha
We may want to include a driver in the whitelist for read only tasks
such as diagnosing or exporting guest data (with libguestfs as a good
example). This patch introduces the magic prefix ^ to include a driver
to the whitelist, but only enables qemu to open specific image
format readonly, and returns -ENOTSUP for RW opening.
Example: To include vmdk readonly, and others read+write:
./configure --block-drv-whitelist=qcow2,raw,file,qed,^vmdk
Signed-off-by: Fam Zheng <famz@redhat.com>
---
block.c | 43 +++++++++++++++++++++++++++----------------
blockdev.c | 4 ++--
configure | 2 ++
include/block/block.h | 3 ++-
scripts/create_config | 9 ++++++++-
5 files changed, 41 insertions(+), 20 deletions(-)
diff --git a/block.c b/block.c
index 3f87489..e6a7270 100644
--- a/block.c
+++ b/block.c
@@ -328,28 +328,40 @@ BlockDriver *bdrv_find_format(const char *format_name)
return NULL;
}
-static int bdrv_is_whitelisted(BlockDriver *drv)
+static int bdrv_is_whitelisted(BlockDriver *drv, bool read_only)
{
- static const char *whitelist[] = {
- CONFIG_BDRV_WHITELIST
+ static const char *whitelist_rw[] = {
+ CONFIG_BDRV_WHITELIST_RW
+ };
+ static const char *whitelist_ro[] = {
+ CONFIG_BDRV_WHITELIST_RO
};
const char **p;
- if (!whitelist[0])
+ if (!whitelist_rw[0] && !whitelist_ro[0]) {
return 1; /* no whitelist, anything goes */
+ }
- for (p = whitelist; *p; p++) {
+ for (p = whitelist_rw; *p; p++) {
if (!strcmp(drv->format_name, *p)) {
return 1;
}
}
+ if (read_only) {
+ for (p = whitelist_ro; *p; p++) {
+ if (!strcmp(drv->format_name, *p)) {
+ return 1;
+ }
+ }
+ }
return 0;
}
-BlockDriver *bdrv_find_whitelisted_format(const char *format_name)
+BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
+ bool read_only)
{
BlockDriver *drv = bdrv_find_format(format_name);
- return drv && bdrv_is_whitelisted(drv) ? drv : NULL;
+ return drv && bdrv_is_whitelisted(drv, read_only) ? drv : NULL;
}
typedef struct CreateCo {
@@ -684,10 +696,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name);
- if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
- return -ENOTSUP;
- }
-
/* bdrv_open() with directly using a protocol as drv. This layer is already
* opened, so assign it to bs (while file becomes a closed BlockDriverState)
* and return immediately. */
@@ -698,9 +706,15 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
bs->open_flags = flags;
bs->buffer_alignment = 512;
+ open_flags = bdrv_open_flags(bs, flags);
+ bs->read_only = !(open_flags & BDRV_O_RDWR);
+
+ if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, bs->read_only)) {
+ return -ENOTSUP;
+ }
assert(bs->copy_on_read == 0); /* bdrv_new() and bdrv_close() make it so */
- if ((flags & BDRV_O_RDWR) && (flags & BDRV_O_COPY_ON_READ)) {
+ if (!bs->read_only && (flags & BDRV_O_COPY_ON_READ)) {
bdrv_enable_copy_on_read(bs);
}
@@ -714,9 +728,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
bs->opaque = g_malloc0(drv->instance_size);
bs->enable_write_cache = !!(flags & BDRV_O_CACHE_WB);
- open_flags = bdrv_open_flags(bs, flags);
-
- bs->read_only = !(open_flags & BDRV_O_RDWR);
/* Open the image, either directly or using a protocol */
if (drv->bdrv_file_open) {
@@ -801,7 +812,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
/* Find the right block driver */
drvname = qdict_get_try_str(options, "driver");
if (drvname) {
- drv = bdrv_find_whitelisted_format(drvname);
+ drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR));
qdict_del(options, "driver");
} else if (filename) {
drv = bdrv_find_protocol(filename);
diff --git a/blockdev.c b/blockdev.c
index d1ec99a..b9b2d10 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -477,7 +477,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
error_printf("\n");
return NULL;
}
- drv = bdrv_find_whitelisted_format(buf);
+ drv = bdrv_find_whitelisted_format(buf, ro);
if (!drv) {
error_report("'%s' invalid format", buf);
return NULL;
@@ -1096,7 +1096,7 @@ void qmp_change_blockdev(const char *device, const char *filename,
}
if (format) {
- drv = bdrv_find_whitelisted_format(format);
+ drv = bdrv_find_whitelisted_format(format, bs->read_only);
if (!drv) {
error_set(errp, QERR_INVALID_BLOCK_FORMAT, format);
return;
diff --git a/configure b/configure
index eb74510..87bf54c 100755
--- a/configure
+++ b/configure
@@ -1106,6 +1106,8 @@ echo " --enable-cocoa enable Cocoa (default on Mac OS X)"
echo " --audio-drv-list=LIST set audio drivers list:"
echo " Available drivers: $audio_possible_drivers"
echo " --block-drv-whitelist=L set block driver whitelist"
+echo " prefix with ^ to include driver readonly"
+echo " e.g. --block-drv-whitelist=raw,file,^vmdk"
echo " (affects only QEMU, not qemu-img)"
echo " --enable-mixemu enable mixer emulation"
echo " --disable-xen disable xen backend driver support"
diff --git a/include/block/block.h b/include/block/block.h
index 1251c5c..5604418 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -124,7 +124,8 @@ void bdrv_init(void);
void bdrv_init_with_whitelist(void);
BlockDriver *bdrv_find_protocol(const char *filename);
BlockDriver *bdrv_find_format(const char *format_name);
-BlockDriver *bdrv_find_whitelisted_format(const char *format_name);
+BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
+ bool readonly);
int bdrv_create(BlockDriver *drv, const char* filename,
QEMUOptionParameter *options);
int bdrv_create_file(const char* filename, QEMUOptionParameter *options);
diff --git a/scripts/create_config b/scripts/create_config
index c471e8c..2dfda3e 100755
--- a/scripts/create_config
+++ b/scripts/create_config
@@ -35,11 +35,18 @@ case $line in
echo ""
;;
CONFIG_BDRV_WHITELIST=*)
- echo "#define CONFIG_BDRV_WHITELIST \\"
+ echo "#define CONFIG_BDRV_WHITELIST_RW \\"
for drv in ${line#*=}; do
+ [[ "${drv}" = ^* ]] && continue;
echo " \"${drv}\",\\"
done
echo " NULL"
+ echo "#define CONFIG_BDRV_WHITELIST_RO \\"
+ for drv in ${line#*=}; do
+ [[ "${drv}" != ^* ]] && continue;
+ echo " \"${drv#^}\",\\"
+ done
+ echo " NULL"
;;
CONFIG_*=y) # configuration
name=${line%=*}
--
1.8.2.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH] block: add read only to whitelist
2013-05-28 6:44 [Qemu-devel] [PATCH] block: add read only to whitelist Fam Zheng
@ 2013-05-28 8:00 ` Kevin Wolf
2013-05-28 8:02 ` Stefan Hajnoczi
2013-05-28 8:10 ` Paolo Bonzini
2 siblings, 0 replies; 5+ messages in thread
From: Kevin Wolf @ 2013-05-28 8:00 UTC (permalink / raw)
To: Fam Zheng; +Cc: jcody, qemu-devel, stefanha
Am 28.05.2013 um 08:44 hat Fam Zheng geschrieben:
> We may want to include a driver in the whitelist for read only tasks
> such as diagnosing or exporting guest data (with libguestfs as a good
> example). This patch introduces the magic prefix ^ to include a driver
> to the whitelist, but only enables qemu to open specific image
> format readonly, and returns -ENOTSUP for RW opening.
>
> Example: To include vmdk readonly, and others read+write:
> ./configure --block-drv-whitelist=qcow2,raw,file,qed,^vmdk
>
> Signed-off-by: Fam Zheng <famz@redhat.com>
^ looks a bit like "not", so this is potentially confusing syntax. Why
not simply add a second option?
./configure --block-drv-whitelist=qcow2,raw,file,qed \
--block-drv-ro-whitelist=vmdk
Kevin
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH] block: add read only to whitelist
2013-05-28 6:44 [Qemu-devel] [PATCH] block: add read only to whitelist Fam Zheng
2013-05-28 8:00 ` Kevin Wolf
@ 2013-05-28 8:02 ` Stefan Hajnoczi
2013-05-28 8:10 ` Paolo Bonzini
2 siblings, 0 replies; 5+ messages in thread
From: Stefan Hajnoczi @ 2013-05-28 8:02 UTC (permalink / raw)
To: Fam Zheng; +Cc: kwolf, jcody, qemu-devel
On Tue, May 28, 2013 at 02:44:26PM +0800, Fam Zheng wrote:
> We may want to include a driver in the whitelist for read only tasks
> such as diagnosing or exporting guest data (with libguestfs as a good
> example). This patch introduces the magic prefix ^ to include a driver
> to the whitelist, but only enables qemu to open specific image
> format readonly, and returns -ENOTSUP for RW opening.
>
> Example: To include vmdk readonly, and others read+write:
> ./configure --block-drv-whitelist=qcow2,raw,file,qed,^vmdk
This is great, thanks for tackling this. block/vmdk.c isn't suitable
for running real VMs (read-write) since it's not optimized for
concurrent I/O but it is usable for libguestfs (read-only).
> Signed-off-by: Fam Zheng <famz@redhat.com>
> ---
> block.c | 43 +++++++++++++++++++++++++++----------------
> blockdev.c | 4 ++--
> configure | 2 ++
> include/block/block.h | 3 ++-
> scripts/create_config | 9 ++++++++-
> 5 files changed, 41 insertions(+), 20 deletions(-)
>
> diff --git a/block.c b/block.c
> index 3f87489..e6a7270 100644
> --- a/block.c
> +++ b/block.c
> @@ -328,28 +328,40 @@ BlockDriver *bdrv_find_format(const char *format_name)
> return NULL;
> }
>
> -static int bdrv_is_whitelisted(BlockDriver *drv)
> +static int bdrv_is_whitelisted(BlockDriver *drv, bool read_only)
> {
> - static const char *whitelist[] = {
> - CONFIG_BDRV_WHITELIST
> + static const char *whitelist_rw[] = {
> + CONFIG_BDRV_WHITELIST_RW
> + };
> + static const char *whitelist_ro[] = {
> + CONFIG_BDRV_WHITELIST_RO
> };
> const char **p;
Please also make the ./configure lists separate. The funky ^ syntax is
not obvious. Better to have:
./configure --block-drv-whitelist-rw=qcow2,raw,file,qed \
--block-drv-whitelist-ro=vmdk,vpc
>
> - if (!whitelist[0])
> + if (!whitelist_rw[0] && !whitelist_ro[0]) {
> return 1; /* no whitelist, anything goes */
> + }
>
> - for (p = whitelist; *p; p++) {
> + for (p = whitelist_rw; *p; p++) {
> if (!strcmp(drv->format_name, *p)) {
> return 1;
> }
> }
> + if (read_only) {
> + for (p = whitelist_ro; *p; p++) {
> + if (!strcmp(drv->format_name, *p)) {
> + return 1;
> + }
> + }
> + }
> return 0;
> }
>
> -BlockDriver *bdrv_find_whitelisted_format(const char *format_name)
> +BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
> + bool read_only)
> {
> BlockDriver *drv = bdrv_find_format(format_name);
> - return drv && bdrv_is_whitelisted(drv) ? drv : NULL;
> + return drv && bdrv_is_whitelisted(drv, read_only) ? drv : NULL;
> }
>
> typedef struct CreateCo {
> @@ -684,10 +696,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
>
> trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name);
>
> - if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
> - return -ENOTSUP;
> - }
> -
> /* bdrv_open() with directly using a protocol as drv. This layer is already
> * opened, so assign it to bs (while file becomes a closed BlockDriverState)
> * and return immediately. */
if (file != NULL && drv->bdrv_file_open) {
bdrv_swap(file, bs);
return 0;
}
I think your change is okay. You moved the check after this early
return, but file is already opened so we passed the whitelist check
already. This is a little tricky but it seems fine.
Stefan
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH] block: add read only to whitelist
2013-05-28 6:44 [Qemu-devel] [PATCH] block: add read only to whitelist Fam Zheng
2013-05-28 8:00 ` Kevin Wolf
2013-05-28 8:02 ` Stefan Hajnoczi
@ 2013-05-28 8:10 ` Paolo Bonzini
2013-05-28 8:34 ` Fam Zheng
2 siblings, 1 reply; 5+ messages in thread
From: Paolo Bonzini @ 2013-05-28 8:10 UTC (permalink / raw)
To: Fam Zheng; +Cc: kwolf, jcody, qemu-devel, stefanha
Il 28/05/2013 08:44, Fam Zheng ha scritto:
> diff --git a/scripts/create_config b/scripts/create_config
> index c471e8c..2dfda3e 100755
> --- a/scripts/create_config
> +++ b/scripts/create_config
> @@ -35,11 +35,18 @@ case $line in
> echo ""
> ;;
> CONFIG_BDRV_WHITELIST=*)
> - echo "#define CONFIG_BDRV_WHITELIST \\"
> + echo "#define CONFIG_BDRV_WHITELIST_RW \\"
> for drv in ${line#*=}; do
> + [[ "${drv}" = ^* ]] && continue;
I didn't know about this feature. Can you point me to the documentation?
You would need to change the #! header to "#! /bin/bash" if you use it,
but since you have to respin anyway, I'd ask you to use "case" instead. :)
Paolo
> echo " \"${drv}\",\\"
> done
> echo " NULL"
> + echo "#define CONFIG_BDRV_WHITELIST_RO \\"
> + for drv in ${line#*=}; do
> + [[ "${drv}" != ^* ]] && continue;
> + echo " \"${drv#^}\",\\"
> + done
> + echo " NULL"
> ;;
> CONFIG_*=y) # configuration
> name=${line%=*}
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH] block: add read only to whitelist
2013-05-28 8:10 ` Paolo Bonzini
@ 2013-05-28 8:34 ` Fam Zheng
0 siblings, 0 replies; 5+ messages in thread
From: Fam Zheng @ 2013-05-28 8:34 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: kwolf, jcody, qemu-devel, stefanha
On Tue, 05/28 10:10, Paolo Bonzini wrote:
> Il 28/05/2013 08:44, Fam Zheng ha scritto:
> > diff --git a/scripts/create_config b/scripts/create_config
> > index c471e8c..2dfda3e 100755
> > --- a/scripts/create_config
> > +++ b/scripts/create_config
> > @@ -35,11 +35,18 @@ case $line in
> > echo ""
> > ;;
> > CONFIG_BDRV_WHITELIST=*)
> > - echo "#define CONFIG_BDRV_WHITELIST \\"
> > + echo "#define CONFIG_BDRV_WHITELIST_RW \\"
> > for drv in ${line#*=}; do
> > + [[ "${drv}" = ^* ]] && continue;
>
> I didn't know about this feature. Can you point me to the documentation?
Yes, it is bash only, I'd better use a more compatible way.
http://mywiki.wooledge.org/glob
>
> You would need to change the #! header to "#! /bin/bash" if you use it,
> but since you have to respin anyway, I'd ask you to use "case" instead. :)
As Stefan and Kevin pointed out, I'll replace ^ prefix with a separate
configure option, it'll become
CONFIG_BDRV_WHITELIST_RW=*)
...
;;
CONFIG_BDRV_WHITELIST_RO=*)
...
;;
Then I won't need globbing.
--
Fam
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-05-28 8:34 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-28 6:44 [Qemu-devel] [PATCH] block: add read only to whitelist Fam Zheng
2013-05-28 8:00 ` Kevin Wolf
2013-05-28 8:02 ` Stefan Hajnoczi
2013-05-28 8:10 ` Paolo Bonzini
2013-05-28 8:34 ` Fam Zheng
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).