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 <f...@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