Re: [Qemu-block] [PATCH v2 0/9] iotests: Make them work for both Python 2 and 3

2018-10-19 Thread Cleber Rosa



On 10/19/18 3:15 PM, Max Reitz wrote:
> This series prepares the iotests to work with both Python 2 and 3.  In
> some places, it adds version-specific code and decides what to do based
> on the version (for instance, whether to import the StringIO or the
> BytesIO class from 'io' for use with the test runner), but most of the
> time, it just makes code work for both versions in general.
> 

Tested on both Python 2 and 3.

Tested-by: Cleber Rosa 



Re: [Qemu-block] [PATCH v2 9/9] iotests: Unify log outputs between Python 2 and 3

2018-10-19 Thread Cleber Rosa



On 10/19/18 3:15 PM, Max Reitz wrote:
> When dumping an object into the log, there are differences between
> Python 2 and 3.  First, unicode strings are prefixed by 'u' in Python 2
> (they are no longer in 3, because unicode strings are the default
> there).  Second, the order of keys in dicts may differ.  Third,
> especially long numbers are longs in Python 2 and thus get an 'L'
> suffix, which does not happen in Python 3.
> 
> We can get around all of these differences by dumping objects (lists and
> dicts) in a language-independent format, namely JSON.  The JSON
> generator even allows emitting dicts with their keys sorted
> alphabetically.
> 
> This changes the output of all tests that use these logging functions
> (dict keys are ordered now, strings in dicts are now enclosed in double
> quotes instead of single quotes, the 'L' suffix of large integers is
> dropped, and "true" and "false" are now in lower case).
> The quote change necessitates a small change to a filter used in test
> 207.
> 
> Suggested-by: Eduardo Habkost 
> Signed-off-by: Max Reitz 

Reviewed-by: Cleber Rosa 



Re: [Qemu-block] [PATCH v2 8/9] iotests: Modify imports for Python 3

2018-10-19 Thread Cleber Rosa



On 10/19/18 3:15 PM, Max Reitz wrote:
> There are two imports that need to be modified when running the iotests
> under Python 3: One is StringIO, which no longer exists; instead, the
> StringIO class comes from the io module, so import it from there (and
> use the BytesIO class for Python 2).  The other is the ConfigParser,
> which has just been renamed to configparser.
> 
> Signed-off-by: Max Reitz 

Reviewed-by: Cleber Rosa 



Re: [Qemu-block] [PATCH v2 7/9] iotests: 'new' module replacement in 169

2018-10-19 Thread Cleber Rosa



On 10/19/18 3:15 PM, Max Reitz wrote:
> iotest 169 uses the 'new' module to add methods to a class.  This module
> no longer exists in Python 3.  Instead, we can use a lambda.  Best of
> all, this works in 2.7 just as well.
> 
> Signed-off-by: Max Reitz 
> Reviewed-by: Eduardo Habkost 

Reviewed-by: Cleber Rosa 



Re: [Qemu-block] [PATCH v2 6/9] iotests: Explicitly inherit FDs in Python

2018-10-19 Thread Cleber Rosa



On 10/19/18 3:15 PM, Max Reitz wrote:
> Python 3.4 introduced the inheritable attribute for FDs.  At the same
> time, it changed the default so that all FDs are not inheritable by
> default, that only inheritable FDs are inherited to subprocesses, and
> only if close_fds is explicitly set to False.
> 
> Adhere to this by setting close_fds to False when working with
> subprocesses that may want to inherit FDs, and by trying to
> set_inheritable() on FDs that we do want to bequeath to them.
> 
> Signed-off-by: Max Reitz 

Reviewed-by: Cleber Rosa 



Re: [Qemu-block] [PATCH v2 5/9] iotests: Different iterator behavior in Python 3

2018-10-19 Thread Cleber Rosa



On 10/19/18 3:15 PM, Max Reitz wrote:
> In Python 3, several functions now return iterators instead of lists.
> This includes range(), items(), map(), and filter().  This means that if
> we really want a list, we have to wrap those instances with list().  But
> then again, the two instances where this is the case for map() and
> filter(), there are shorter expressions which work without either
> function.
> 
> On the other hand, sometimes we do just want an iterator, in which case
> we have sometimes used xrange() and iteritems() which no longer exist in
> Python 3.  Just change these calls to be range() and items(), works in
> both Python 2 and 3, and is really what we want in 3 (which is what
> matters).  But because it is so simple to do (and to find and remove
> once we completely switch to Python 3), make range() be an alias for
> xrange() in the two affected tests (044 and 163).
> 
> In one instance, we only wanted the first instance of the result of a
> filter() call.  Instead of using next(filter()) which would work only in
> Python 3, or list(filter())[0] which would work everywhere but is a bit
> weird, this instance is changed to use list comprehension with a next()
> wrapped around, which works both in 2.7 and 3.
> 
> Signed-off-by: Max Reitz 

Reviewed-by: Cleber Rosa 



Re: [Qemu-block] [Qemu-devel] [PATCH v2 4/9] iotests: Use // for Python integer division

2018-10-19 Thread Cleber Rosa



On 10/19/18 3:15 PM, Max Reitz wrote:
> In Python 3, / is always a floating-point division.  We usually do not
> want this, and as Python 2.7 understands // as well, change all integer
> divisions to use that.
> 
> Signed-off-by: Max Reitz 

Reviewed-by: Cleber Rosa 



[Qemu-block] [PATCH v4 8/8] kvm: Potential NULL pointer dereference in kvm_arch_init_vcpu()

2018-10-19 Thread Liam Merwick
In kvm_arch_init_vcpu() a call to cpuid_find_entry() can return
NULL so the pointer returned should be checked before dereferencing it.

Signed-off-by: Liam Merwick 
---
 target/i386/kvm.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index dc4047b02fc5..eb19c87a9d25 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -1177,7 +1177,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
 c->ecx = c->edx = 0;
 
 c = cpuid_find_entry(&cpuid_data.cpuid, kvm_base, 0);
-c->eax = MAX(c->eax, KVM_CPUID_SIGNATURE | 0x10);
+if (c) {
+c->eax = MAX(c->eax, KVM_CPUID_SIGNATURE | 0x10);
+   }
 }
 
 cpuid_data.cpuid.nent = cpuid_i;
-- 
1.8.3.1




[Qemu-block] [PATCH v4 5/8] block: Fix potential Null pointer dereferences in vvfat.c

2018-10-19 Thread Liam Merwick
The calls to find_mapping_for_cluster() may return NULL but it
isn't always checked for before dereferencing the value returned.
Additionally, add some asserts to cover cases where NULL can't
be returned but which might not be obvious at first glance.

Signed-off-by: Liam Merwick 
---
 block/vvfat.c | 33 -
 1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/block/vvfat.c b/block/vvfat.c
index fc41841a5c3c..19f6725054a0 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -100,6 +100,7 @@ static inline void array_free(array_t* array)
 /* does not automatically grow */
 static inline void* array_get(array_t* array,unsigned int index) {
 assert(index < array->next);
+assert(array->pointer);
 return array->pointer + index * array->item_size;
 }
 
@@ -108,8 +109,7 @@ static inline int array_ensure_allocated(array_t* array, 
int index)
 if((index + 1) * array->item_size > array->size) {
 int new_size = (index + 32) * array->item_size;
 array->pointer = g_realloc(array->pointer, new_size);
-if (!array->pointer)
-return -1;
+assert(array->pointer);
 memset(array->pointer + array->size, 0, new_size - array->size);
 array->size = new_size;
 array->next = index + 1;
@@ -2261,6 +2261,9 @@ static mapping_t* insert_mapping(BDRVVVFATState* s,
 }
 if (index >= s->mapping.next || mapping->begin > begin) {
 mapping = array_insert(&(s->mapping), index, 1);
+if (mapping == NULL) {
+return NULL;
+}
 mapping->path = NULL;
 adjust_mapping_indices(s, index, +1);
 }
@@ -2428,6 +2431,9 @@ static int commit_direntries(BDRVVVFATState* s,
 direntry_t* direntry = array_get(&(s->directory), dir_index);
 uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
 mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
+if (mapping == NULL) {
+return -1;
+}
 
 int factor = 0x10 * s->sectors_per_cluster;
 int old_cluster_count, new_cluster_count;
@@ -2494,6 +2500,9 @@ DLOG(fprintf(stderr, "commit_direntries for %s, 
parent_mapping_index %d\n", mapp
 direntry = array_get(&(s->directory), first_dir_index + i);
 if (is_directory(direntry) && !is_dot(direntry)) {
 mapping = find_mapping_for_cluster(s, first_cluster);
+if (mapping == NULL) {
+return -1;
+}
 assert(mapping->mode & MODE_DIRECTORY);
 ret = commit_direntries(s, first_dir_index + i,
 array_index(&(s->mapping), mapping));
@@ -2522,6 +2531,10 @@ static int commit_one_file(BDRVVVFATState* s,
 assert(offset < size);
 assert((offset % s->cluster_size) == 0);
 
+if (mapping == NULL) {
+return -1;
+}
+
 for (i = s->cluster_size; i < offset; i += s->cluster_size)
 c = modified_fat_get(s, c);
 
@@ -2668,8 +2681,12 @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s)
 if (commit->action == ACTION_RENAME) {
 mapping_t* mapping = find_mapping_for_cluster(s,
 commit->param.rename.cluster);
-char* old_path = mapping->path;
+char *old_path;
 
+if (mapping == NULL) {
+return -1;
+}
+old_path = mapping->path;
 assert(commit->path);
 mapping->path = commit->path;
 if (rename(old_path, mapping->path))
@@ -2690,10 +2707,15 @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s)
 direntry_t* d = direntry + i;
 
 if (is_file(d) || (is_directory(d) && !is_dot(d))) {
+int l;
+char *new_path;
 mapping_t* m = find_mapping_for_cluster(s,
 begin_of_direntry(d));
-int l = strlen(m->path);
-char* new_path = g_malloc(l + diff + 1);
+if (m == NULL) {
+return -1;
+}
+l = strlen(m->path);
+new_path = g_malloc(l + diff + 1);
 
 assert(!strncmp(m->path, mapping->path, l2));
 
@@ -3193,6 +3215,7 @@ static int enable_write_target(BlockDriverState *bs, 
Error **errp)
 
 backing = bdrv_new_open_driver(&vvfat_write_target, NULL, 
BDRV_O_ALLOW_RDWR,
&error_abort);
+assert(backing);
 *(void**) backing->opaque = s;
 
 bdrv_set_backing_hd(s->bs, backing, &error_abort);
-- 
1.8.3.1




[Qemu-block] [PATCH v4 7/8] qcow2: Read outside array bounds in qcow2_pre_write_overlap_check()

2018-10-19 Thread Liam Merwick
The commit for 0e4e4318eaa5 increments QCOW2_OL_MAX_BITNR but does not
add an array entry for QCOW2_OL_BITMAP_DIRECTORY_BITNR to metadata_ol_names[].
As a result, an array dereference of metadata_ol_names[8] in
qcow2_pre_write_overlap_check() could result in a read outside of the array 
bounds.

Fixes: 0e4e4318eaa5 ('qcow2: add overlap check for bitmap directory')

Cc: Vladimir Sementsov-Ogievskiy 
Signed-off-by: Liam Merwick 
Reviewed-by: Eric Blake 
Reviewed-by: Max Reitz 
---
 block/qcow2-refcount.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 3c539f02e5ec..46082aeac1d6 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -2719,15 +2719,17 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, 
int ign, int64_t offset,
 }
 
 static const char *metadata_ol_names[] = {
-[QCOW2_OL_MAIN_HEADER_BITNR]= "qcow2_header",
-[QCOW2_OL_ACTIVE_L1_BITNR]  = "active L1 table",
-[QCOW2_OL_ACTIVE_L2_BITNR]  = "active L2 table",
-[QCOW2_OL_REFCOUNT_TABLE_BITNR] = "refcount table",
-[QCOW2_OL_REFCOUNT_BLOCK_BITNR] = "refcount block",
-[QCOW2_OL_SNAPSHOT_TABLE_BITNR] = "snapshot table",
-[QCOW2_OL_INACTIVE_L1_BITNR]= "inactive L1 table",
-[QCOW2_OL_INACTIVE_L2_BITNR]= "inactive L2 table",
+[QCOW2_OL_MAIN_HEADER_BITNR]= "qcow2_header",
+[QCOW2_OL_ACTIVE_L1_BITNR]  = "active L1 table",
+[QCOW2_OL_ACTIVE_L2_BITNR]  = "active L2 table",
+[QCOW2_OL_REFCOUNT_TABLE_BITNR] = "refcount table",
+[QCOW2_OL_REFCOUNT_BLOCK_BITNR] = "refcount block",
+[QCOW2_OL_SNAPSHOT_TABLE_BITNR] = "snapshot table",
+[QCOW2_OL_INACTIVE_L1_BITNR]= "inactive L1 table",
+[QCOW2_OL_INACTIVE_L2_BITNR]= "inactive L2 table",
+[QCOW2_OL_BITMAP_DIRECTORY_BITNR]   = "bitmap directory",
 };
+QEMU_BUILD_BUG_ON(QCOW2_OL_MAX_BITNR != ARRAY_SIZE(metadata_ol_names));
 
 /*
  * First performs a check for metadata overlaps (through
-- 
1.8.3.1




[Qemu-block] [PATCH v4 6/8] block: dump_qlist() may dereference a Null pointer

2018-10-19 Thread Liam Merwick
A NULL 'list' passed into function dump_qlist() isn't correctly
validated and can be passed to qlist_first() where it is dereferenced.

Given that dump_qlist() is static, and callers already do the right
thing, just add an assert to catch future potential bugs (plus the
added benefit of suppressing a warning from a static analysis tool
and removing this noise will help us better find real issues).

Signed-off-by: Liam Merwick 
Reviewed-by: Eric Blake 
---
 block/qapi.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/block/qapi.c b/block/qapi.c
index c66f949db839..e81be604217c 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -740,6 +740,8 @@ static void dump_qlist(fprintf_function func_fprintf, void 
*f, int indentation,
 const QListEntry *entry;
 int i = 0;
 
+assert(list);
+
 for (entry = qlist_first(list); entry; entry = qlist_next(entry), i++) {
 QType type = qobject_type(entry->value);
 bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST);
-- 
1.8.3.1




[Qemu-block] [PATCH v4 1/8] configure: Provide option to explicitly disable AVX2

2018-10-19 Thread Liam Merwick
The configure script detects if the compiler has AVX2 support and
automatically sets avx2_opt="yes" which in turn defines CONFIG_AVX2_OPT.
There is no way of explicitly overriding this setting so this commit adds
two command-line options: --enable-avx2 and --disable-avx2.

The default behaviour, when no option is specified, is to maintain the
current behaviour and enable AVX2 if the compiler supports it.

Signed-off-by: Liam Merwick 
Reviewed-by: Darren Kenny 
Reviewed-by: Mark Kanda 
---
 configure | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 9138af37f8a0..3a3e5f7004ce 100755
--- a/configure
+++ b/configure
@@ -428,7 +428,7 @@ usb_redir=""
 opengl=""
 opengl_dmabuf="no"
 cpuid_h="no"
-avx2_opt="no"
+avx2_opt=""
 zlib="yes"
 capstone=""
 lzo=""
@@ -1332,6 +1332,10 @@ for opt do
   ;;
   --disable-glusterfs) glusterfs="no"
   ;;
+  --disable-avx2) avx2_opt="no"
+  ;;
+  --enable-avx2) avx2_opt="yes"
+  ;;
   --enable-glusterfs) glusterfs="yes"
   ;;
   --disable-virtio-blk-data-plane|--enable-virtio-blk-data-plane)
@@ -1706,6 +1710,7 @@ disabled with --disable-FEATURE, default is enabled if 
available:
   libxml2 for Parallels image format
   tcmalloctcmalloc support
   jemallocjemalloc support
+  avx2AVX2 optimization support
   replication replication support
   vhost-vsock virtio sockets device support
   opengl  opengl support
@@ -5094,7 +5099,7 @@ fi
 # There is no point enabling this if cpuid.h is not usable,
 # since we won't be able to select the new routines.
 
-if test $cpuid_h = yes; then
+if test "$cpuid_h" = "yes" -a "$avx2_opt" != "no"; then
   cat > $TMPC << EOF
 #pragma GCC push_options
 #pragma GCC target("avx2")
@@ -5108,6 +5113,8 @@ int main(int argc, char *argv[]) { return bar(argv[0]); }
 EOF
   if compile_object "" ; then
 avx2_opt="yes"
+  else
+avx2_opt="no"
   fi
 fi
 
-- 
1.8.3.1




[Qemu-block] [PATCH v4 4/8] qemu-img: assert block_job_get() does not return NULL in img_commit()

2018-10-19 Thread Liam Merwick
Although the function block_job_get() can return NULL, it would be a
serious bug if it did so (because the job yields before executing anything
(if it started successfully); but otherwise, commit_active_start() would
have returned an error).  However, as a precaution, before dereferencing
the 'job' pointer in img_commit() assert it is not NULL.

Signed-off-by: Liam Merwick 
---
 qemu-img.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/qemu-img.c b/qemu-img.c
index b12f4cd19b0a..457aa152296b 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1029,6 +1029,7 @@ static int img_commit(int argc, char **argv)
 }
 
 job = block_job_get("commit");
+assert(job);
 run_block_job(job, &local_err);
 if (local_err) {
 goto unref_backing;
-- 
1.8.3.1




[Qemu-block] [PATCH v4 0/8] off-by-one and NULL pointer accesses detected by static analysis

2018-10-19 Thread Liam Merwick
Below are a number of fixes to some off-by-one, read outside array bounds, and
NULL pointer accesses detected by an internal Oracle static analysis tool 
(Parfait).
https://labs.oracle.com/pls/apex/f?p=labs:49:P49_PROJECT_ID:13

I have also included a patch to add a command-line option to configure to
select if AVX2 is used or not (keeping the existing behaviour by default).
My motivation was avoiding an issue with the static analysis tool but NetSpectre
was announced as I was working on this and I felt it may have more general uses.

v1 -> v2
Based on feedback from Eric Blake:
patch2: reworded commit message to clarify issue
patch6: Reverted common qlist routines and added assert to qlist_dump instead
patch7: Fixed incorrect logic
patch8: Added QEMU_BUILD_BUG_ON to catch future іnstance at compile-time

v2 -> v3
Based on feedback from Eric Blake:
patch6: removed double space from commit message
patch8: removed unnecessary comment and updated QEMU_BUILD_BUG_ON to use 
ARRAY_SIZE
Added Eric's R-b to patches 6,7,8

v3 -> v4
Based on feedback from Max Reitz:
patch2: Added R-b from John Snow
patch3: fixed blk_get_attached_dev_id() instead of checking return value
patch4: switched to assert()
patch5: numerous changes based on feedback from Max
patch6: updated commit message
patch7: (was patch8): Added Max's R-b
patch8: (new): patch fixing NULL pointer dereference in kvm_arch_init_vcpu()

I also dropped the 'io: potential unnecessary check in 
qio_channel_command_new_spawn()'
patch from v3 - it was correct but of no benefit to staic analysis checking

Liam Merwick (8):
  configure: Provide option to explicitly disable AVX2
  job: Fix off-by-one assert checks for JobSTT and JobVerbTable
  block: Null pointer dereference in blk_root_get_parent_desc()
  qemu-img: assert block_job_get() does not return NULL in img_commit()
  block: Fix potential Null pointer dereferences in vvfat.c
  block: dump_qlist() may dereference a Null pointer
  qcow2: Read outside array bounds in qcow2_pre_write_overlap_check()
  kvm: Potential NULL pointer dereference in kvm_arch_init_vcpu()

 block/block-backend.c  |  6 +-
 block/qapi.c   |  2 ++
 block/qcow2-refcount.c | 18 ++
 block/vvfat.c  | 33 -
 configure  | 11 +--
 dtc|  2 +-
 job.c  |  4 ++--
 qemu-img.c |  1 +
 target/i386/kvm.c  |  4 +++-
 9 files changed, 61 insertions(+), 20 deletions(-)

-- 
1.8.3.1




[Qemu-block] [PATCH v4 3/8] block: Null pointer dereference in blk_root_get_parent_desc()

2018-10-19 Thread Liam Merwick
The dev_id returned by the call to blk_get_attached_dev_id() in
blk_root_get_parent_desc() can be NULL (an internal call to
object_get_canonical_path may have returned NULL).

Instead of just checking this case before before dereferencing,
adjust blk_get_attached_dev_id() to return the empty string if no
object path can be found (similar to the case when blk->dev is NULL
and an empty string is returned).

Signed-off-by: Liam Merwick 
---
 block/block-backend.c | 6 +-
 dtc   | 2 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index dc0cd5772413..e628920f3cd8 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -909,6 +909,7 @@ void *blk_get_attached_dev(BlockBackend *blk)
 char *blk_get_attached_dev_id(BlockBackend *blk)
 {
 DeviceState *dev;
+char *dev_id;
 
 assert(!blk->legacy_dev);
 dev = blk->dev;
@@ -918,7 +919,10 @@ char *blk_get_attached_dev_id(BlockBackend *blk)
 } else if (dev->id) {
 return g_strdup(dev->id);
 }
-return object_get_canonical_path(OBJECT(dev));
+
+dev_id = object_get_canonical_path(OBJECT(dev));
+
+return dev_id ? dev_id : g_strdup("");
 }
 
 /*
diff --git a/dtc b/dtc
index 88f18909db73..e54388015af1 16
--- a/dtc
+++ b/dtc
@@ -1 +1 @@
-Subproject commit 88f18909db731a627456f26d779445f84e449536
+Subproject commit e54388015af1fb4bf04d0bca99caba1074d9cc42
-- 
1.8.3.1




[Qemu-block] [PATCH v4 2/8] job: Fix off-by-one assert checks for JobSTT and JobVerbTable

2018-10-19 Thread Liam Merwick
In the assert checking the array dereference of JobVerbTable[verb]
in job_apply_verb() the check of the index, verb, allows an overrun
because an index equal to the array size is permitted.

Similarly, in the assert check of JobSTT[s0][s1] with index s1
in job_state_transition(), an off-by-one overrun is not flagged
either.

This is not a run-time issue as there are no callers actually
passing in the max value.

Signed-off-by: Liam Merwick 
Reviewed-by: Darren Kenny 
Reviewed-by: Mark Kanda 
Reviewed-by: Eric Blake 
Reviewed-by: John Snow 
---
 job.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/job.c b/job.c
index c65e01bbfa34..da8e4b7bf2f3 100644
--- a/job.c
+++ b/job.c
@@ -159,7 +159,7 @@ bool job_is_internal(Job *job)
 static void job_state_transition(Job *job, JobStatus s1)
 {
 JobStatus s0 = job->status;
-assert(s1 >= 0 && s1 <= JOB_STATUS__MAX);
+assert(s1 >= 0 && s1 < JOB_STATUS__MAX);
 trace_job_state_transition(job, job->ret,
JobSTT[s0][s1] ? "allowed" : "disallowed",
JobStatus_str(s0), JobStatus_str(s1));
@@ -174,7 +174,7 @@ static void job_state_transition(Job *job, JobStatus s1)
 int job_apply_verb(Job *job, JobVerb verb, Error **errp)
 {
 JobStatus s0 = job->status;
-assert(verb >= 0 && verb <= JOB_VERB__MAX);
+assert(verb >= 0 && verb < JOB_VERB__MAX);
 trace_job_apply_verb(job, JobStatus_str(s0), JobVerb_str(verb),
  JobVerbTable[verb][s0] ? "allowed" : "prohibited");
 if (JobVerbTable[verb][s0]) {
-- 
1.8.3.1




Re: [Qemu-block] [Qemu-devel] [PATCH v3 3/8] block: Null pointer dereference in blk_root_get_parent_desc()

2018-10-19 Thread Liam Merwick




On 12/10/18 15:48, Max Reitz wrote:

Hi,

On 31.08.18 20:16, Liam Merwick wrote:

The dev_id returned by the call to blk_get_attached_dev_id() in
blk_root_get_parent_desc() can be NULL (an internal call to
object_get_canonical_path may have returned NULL) so it should
be checked before dereferencing.

Signed-off-by: Liam Merwick 
Reviewed-by: Darren Kenny 
Reviewed-by: Mark Kanda 
---
  block/block-backend.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index fa120630be83..210eee75006a 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -136,7 +136,7 @@ static char *blk_root_get_parent_desc(BdrvChild *child)
  }
  
  dev_id = blk_get_attached_dev_id(blk);

-if (*dev_id) {
+if (dev_id && *dev_id) {
  return dev_id;


I rather think that blk_get_attached_dev_id() needs attention first.  It
returns an explicitly empty string if blk->dev is NULL.  If NULL was a
valid return value, it should just return NULL there.

Besides this caller, there are two callers that pass the dev_id to
qapi_event_send_device_tray_moved().  Now in practice that allows the
string to be NULL, but there is a comment in visit_type_str() that says
one should not pass NULL.

So it's either changing blk_get_attached_dev_id() to return NULL when
there is no valid ID (instead of the empty string, and then we could
save ourselves the check "*dev_id" here and elsewhere), but then we have
to fix all callers.

Or we make it return an empty string if object_get_canonical_path()
returned NULL.



I went with the latter and now (in upcoming v4) check the return value 
from object_get_canonical_path() and return an empty string if it's NULL.


Regards,
Liam



Max


  } else {
  /* TODO Callback into the BB owner for something more detailed */








Re: [Qemu-block] [PATCH v2 8/9] iotests: Modify imports for Python 3

2018-10-19 Thread Eduardo Habkost
On Fri, Oct 19, 2018 at 09:15:22PM +0200, Max Reitz wrote:
> There are two imports that need to be modified when running the iotests
> under Python 3: One is StringIO, which no longer exists; instead, the
> StringIO class comes from the io module, so import it from there (and
> use the BytesIO class for Python 2).  The other is the ConfigParser,
> which has just been renamed to configparser.
> 
> Signed-off-by: Max Reitz 
> ---
>  tests/qemu-iotests/iotests.py| 13 +
>  tests/qemu-iotests/nbd-fault-injector.py |  7 +--
>  2 files changed, 14 insertions(+), 6 deletions(-)
> 
> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> index 7ca94e9278..ed91095505 100644
> --- a/tests/qemu-iotests/iotests.py
> +++ b/tests/qemu-iotests/iotests.py
> @@ -29,6 +29,7 @@ import json
>  import signal
>  import logging
>  import atexit
> +import io
>  
>  sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 
> 'scripts'))
>  import qtest
> @@ -681,15 +682,19 @@ def main(supported_fmts=[], supported_oses=['linux'], 
> supported_cache_modes=[],
>  verify_platform(supported_oses)
>  verify_cache_mode(supported_cache_modes)
>  
> -# We need to filter out the time taken from the output so that 
> qemu-iotest
> -# can reliably diff the results against master output.
> -import StringIO
>  if debug:
>  output = sys.stdout
>  verbosity = 2
>  sys.argv.remove('-d')
>  else:
> -output = StringIO.StringIO()
> +# We need to filter out the time taken from the output so that
> +# qemu-iotest can reliably diff the results against master output.
> +if sys.version_info.major >= 3:
> +output = io.StringIO()
> +else:
> +# StringIO() is for unicode strings, which is not what

Nit: I would change the comment to say "io.StringIO" instead of
"StringIO", to avoid confusion with StringIO.StringIO.

Not a big deal, so:

Reviewed-by: Eduardo Habkost 

> +# 2.x's test runner emits.
> +output = io.BytesIO()
>  
>  logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
>  
> diff --git a/tests/qemu-iotests/nbd-fault-injector.py 
> b/tests/qemu-iotests/nbd-fault-injector.py
> index d45e2e0a6a..6b2d659dee 100755
> --- a/tests/qemu-iotests/nbd-fault-injector.py
> +++ b/tests/qemu-iotests/nbd-fault-injector.py
> @@ -48,7 +48,10 @@ import sys
>  import socket
>  import struct
>  import collections
> -import ConfigParser
> +if sys.version_info.major >= 3:
> +import configparser
> +else:
> +import ConfigParser as configparser
>  
>  FAKE_DISK_SIZE = 8 * 1024 * 1024 * 1024 # 8 GB
>  
> @@ -225,7 +228,7 @@ def parse_config(config):
>  return rules
>  
>  def load_rules(filename):
> -config = ConfigParser.RawConfigParser()
> +config = configparser.RawConfigParser()
>  with open(filename, 'rt') as f:
>  config.readfp(f, filename)
>  return parse_config(config)
> -- 
> 2.17.1
> 

-- 
Eduardo



Re: [Qemu-block] [PATCH v2 6/9] iotests: Explicitly inherit FDs in Python

2018-10-19 Thread Eduardo Habkost
On Fri, Oct 19, 2018 at 09:15:20PM +0200, Max Reitz wrote:
> Python 3.4 introduced the inheritable attribute for FDs.  At the same
> time, it changed the default so that all FDs are not inheritable by
> default, that only inheritable FDs are inherited to subprocesses, and
> only if close_fds is explicitly set to False.
> 
> Adhere to this by setting close_fds to False when working with
> subprocesses that may want to inherit FDs, and by trying to
> set_inheritable() on FDs that we do want to bequeath to them.
> 
> Signed-off-by: Max Reitz 
> ---
>  scripts/qemu.py| 34 +-
>  tests/qemu-iotests/045 |  2 +-
>  tests/qemu-iotests/147 |  2 +-
>  3 files changed, 31 insertions(+), 7 deletions(-)
> 
> diff --git a/scripts/qemu.py b/scripts/qemu.py
> index f099ce7278..fb29b73c30 100644
> --- a/scripts/qemu.py
> +++ b/scripts/qemu.py
> @@ -142,11 +142,19 @@ class QEMUMachine(object):
>  if opts:
>  options.append(opts)
>  
> +# This did not exist before 3.4, but since then it is
> +# mandatory for our purpose
> +if hasattr(os, 'set_inheritable'):
> +os.set_inheritable(fd, True)
> +
>  self._args.append('-add-fd')
>  self._args.append(','.join(options))
>  return self
>  
> -def send_fd_scm(self, fd_file_path):
> +# Exactly one of fd and file_path must be given.
> +# (If it is file_path, the helper will open that file and pass its
> +# own fd)
> +def send_fd_scm(self, fd=None, file_path=None):
>  # In iotest.py, the qmp should always use unix socket.
>  assert self._qmp.is_scm_available()
>  if self._socket_scm_helper is None:
> @@ -154,12 +162,27 @@ class QEMUMachine(object):
>  if not os.path.exists(self._socket_scm_helper):
>  raise QEMUMachineError("%s does not exist" %
> self._socket_scm_helper)
> +
> +# This did not exist before 3.4, but since then it is
> +# mandatory for our purpose
> +if hasattr(os, 'set_inheritable'):
> +os.set_inheritable(self._qmp.get_sock_fd(), True)
> +if fd is not None:

I was going to suggest keeping the existing function parameter,
and using:
  isinstance(fd_file_path, int)
But your solution makes callers more explicit.  This seems to be
a good thing.

Reviewed-by: Eduardo Habkost 


> +os.set_inheritable(fd, True)
> +
>  fd_param = ["%s" % self._socket_scm_helper,
> -"%d" % self._qmp.get_sock_fd(),
> -"%s" % fd_file_path]
> +"%d" % self._qmp.get_sock_fd()]
> +
> +if file_path is not None:
> +assert fd is None
> +fd_param.append(file_path)
> +else:
> +assert fd is not None
> +fd_param.append(str(fd))
> +
>  devnull = open(os.path.devnull, 'rb')
>  proc = subprocess.Popen(fd_param, stdin=devnull, 
> stdout=subprocess.PIPE,
> -stderr=subprocess.STDOUT)
> +stderr=subprocess.STDOUT, close_fds=False)
>  output = proc.communicate()[0]
>  if output:
>  LOG.debug(output)
> @@ -280,7 +303,8 @@ class QEMUMachine(object):
> stdin=devnull,
> stdout=self._qemu_log_file,
> stderr=subprocess.STDOUT,
> -   shell=False)
> +   shell=False,
> +   close_fds=False)
>  self._post_launch()
>  
>  def wait(self):
> diff --git a/tests/qemu-iotests/045 b/tests/qemu-iotests/045
> index 6be8fc4912..55a5d31ca8 100755
> --- a/tests/qemu-iotests/045
> +++ b/tests/qemu-iotests/045
> @@ -140,7 +140,7 @@ class TestSCMFd(iotests.QMPTestCase):
>  os.remove(image0)
>  
>  def _send_fd_by_SCM(self):
> -ret = self.vm.send_fd_scm(image0)
> +ret = self.vm.send_fd_scm(file_path=image0)
>  self.assertEqual(ret, 0, 'Failed to send fd with UNIX SCM')
>  
>  def test_add_fd(self):
> diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147
> index d2081df84b..05b374b7d3 100755
> --- a/tests/qemu-iotests/147
> +++ b/tests/qemu-iotests/147
> @@ -229,7 +229,7 @@ class BuiltinNBD(NBDBlockdevAddBase):
>  sockfd = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
>  sockfd.connect(unix_socket)
>  
> -result = self.vm.send_fd_scm(str(sockfd.fileno()))
> +result = self.vm.send_fd_scm(fd=sockfd.fileno())
>  self.assertEqual(result, 0, 'Failed to send socket FD')
>  
>  result = self.vm.qmp('getfd', fdname='nbd-fifo')
> -- 
> 2.17.1
> 

-- 
Eduardo



Re: [Qemu-block] [PATCH v2 4/9] iotests: Use // for Python integer division

2018-10-19 Thread Eduardo Habkost
On Fri, Oct 19, 2018 at 09:15:18PM +0200, Max Reitz wrote:
> In Python 3, / is always a floating-point division.  We usually do not
> want this, and as Python 2.7 understands // as well, change all integer
> divisions to use that.
> 
> Signed-off-by: Max Reitz 

Reviewed-by: Eduardo Habkost 

-- 
Eduardo



Re: [Qemu-block] [PATCH v2 5/9] iotests: Different iterator behavior in Python 3

2018-10-19 Thread Eduardo Habkost
On Fri, Oct 19, 2018 at 09:15:19PM +0200, Max Reitz wrote:
> In Python 3, several functions now return iterators instead of lists.
> This includes range(), items(), map(), and filter().  This means that if
> we really want a list, we have to wrap those instances with list().  But
> then again, the two instances where this is the case for map() and
> filter(), there are shorter expressions which work without either
> function.
> 
> On the other hand, sometimes we do just want an iterator, in which case
> we have sometimes used xrange() and iteritems() which no longer exist in
> Python 3.  Just change these calls to be range() and items(), works in
> both Python 2 and 3, and is really what we want in 3 (which is what
> matters).  But because it is so simple to do (and to find and remove
> once we completely switch to Python 3), make range() be an alias for
> xrange() in the two affected tests (044 and 163).
> 
> In one instance, we only wanted the first instance of the result of a
> filter() call.  Instead of using next(filter()) which would work only in
> Python 3, or list(filter())[0] which would work everywhere but is a bit
> weird, this instance is changed to use list comprehension with a next()
> wrapped around, which works both in 2.7 and 3.

Nit: the expression you put inside next(...) is not a list
comprehension; it's a generator expression.  A list comprehension
expression would generate the full list in advance before you get
the first element.

It would be OK to rewrite the expression using an actual list
comprehension:

drive = [drive for drive in result if drive['device'] == 'drive0'][0]

But the solution you chose is OK, too.

Reviewed-by: Eduardo Habkost 

> 
> Signed-off-by: Max Reitz 
> ---
>  tests/qemu-iotests/044 | 16 ++--
>  tests/qemu-iotests/056 |  2 +-
>  tests/qemu-iotests/065 |  4 ++--
>  tests/qemu-iotests/124 |  4 ++--
>  tests/qemu-iotests/139 |  2 +-
>  tests/qemu-iotests/163 | 11 +++
>  6 files changed, 23 insertions(+), 16 deletions(-)
> 
> diff --git a/tests/qemu-iotests/044 b/tests/qemu-iotests/044
> index 7ef5e46fe9..9ec3dba734 100755
> --- a/tests/qemu-iotests/044
> +++ b/tests/qemu-iotests/044
> @@ -26,6 +26,10 @@ import iotests
>  from iotests import qemu_img, qemu_img_verbose, qemu_io
>  import struct
>  import subprocess
> +import sys
> +
> +if sys.version_info.major == 2:
> +range = xrange
>  
>  test_img = os.path.join(iotests.test_dir, 'test.img')
>  
> @@ -52,23 +56,23 @@ class TestRefcountTableGrowth(iotests.QMPTestCase):
>  # Write a refcount table
>  fd.seek(off_reftable)
>  
> -for i in xrange(0, h.refcount_table_clusters):
> +for i in range(0, h.refcount_table_clusters):
>  sector = b''.join(struct.pack('>Q',
>  off_refblock + i * 64 * 512 + j * 512)
> -for j in xrange(0, 64))
> +for j in range(0, 64))
>  fd.write(sector)
>  
>  # Write the refcount blocks
>  assert(fd.tell() == off_refblock)
>  sector = b''.join(struct.pack('>H', 1) for j in range(0, 64 * 
> 256))
> -for block in xrange(0, h.refcount_table_clusters):
> +for block in range(0, h.refcount_table_clusters):
>  fd.write(sector)
>  
>  # Write the L1 table
>  assert(fd.tell() == off_l1)
>  assert(off_l2 + 512 * h.l1_size == off_data)
>  table = b''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j)
> -for j in xrange(0, h.l1_size))
> +for j in range(0, h.l1_size))
>  fd.write(table)
>  
>  # Write the L2 tables
> @@ -79,14 +83,14 @@ class TestRefcountTableGrowth(iotests.QMPTestCase):
>  off = off_data
>  while remaining > 1024 * 512:
>  pytable = list((1 << 63) | off + 512 * j
> -for j in xrange(0, 1024))
> +for j in range(0, 1024))
>  table = struct.pack('>1024Q', *pytable)
>  fd.write(table)
>  remaining = remaining - 1024 * 512
>  off = off + 1024 * 512
>  
>  table = b''.join(struct.pack('>Q', (1 << 63) | off + 512 * j)
> -for j in xrange(0, remaining // 512))
> +for j in range(0, remaining // 512))
>  fd.write(table)
>  
>  
> diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056
> index 223292175a..3df323984d 100755
> --- a/tests/qemu-iotests/056
> +++ b/tests/qemu-iotests/056
> @@ -32,7 +32,7 @@ target_img = os.path.join(iotests.test_dir, 'target.img')
>  def img_create(img, fmt=iotests.imgfmt, size='64M', **kwargs):
>  fullname = os.path.join(iotests.test_dir, '%s.%s' % (img, fmt))
>  optargs = []
> -for k,v in kwargs.iteritems():
> +for k,v in kwargs.items():
>  optargs = optargs + ['-o', '%s=%s' % (k,v)]
>  args = [

[Qemu-block] [PATCH v2 0/9] iotests: Make them work for both Python 2 and 3

2018-10-19 Thread Max Reitz
This series prepares the iotests to work with both Python 2 and 3.  In
some places, it adds version-specific code and decides what to do based
on the version (for instance, whether to import the StringIO or the
BytesIO class from 'io' for use with the test runner), but most of the
time, it just makes code work for both versions in general.

And when we make the switch to make Python 3 mandatory, we can simply
drop the Python 2 branches.


v2:
- Patch 3: Commit message fix [Philippe]
- Patch 4: Really convert all places that use / [Cleber]
- Patch 5:
  - Use list comprehension expressions where that makes sense [Eduardo]
  - Make 'range' an alias for 'xrange' in 044 and 163 [Cleber]
- Patch 6:
  - %s/3\.2/3.4/g [Cleber]
  - Use hasattr() instead of catching AttributeError [Cleber]
  - Call set_inheritable in send_fd_scm() for both the QMP socket FD and
the FD to be passed (if any) [Eduardo]
- Patch 7: Kept as-is, because it's just the minimal amount of change
- Patch 8: Use io.BytesIO in Python 2 [Cleber]
- Patch 9: Use json.dumps(..., sort_keys=True) instead of homegrown
   stringification function [Eduardo]

(Also kept the order, because one vote against, one vote for, so I go
for what's simplest for me. O:-))


git-backport-diff against v1:

Key:
[] : patches are identical
[] : number of functional differences between upstream/downstream patch
[down] : patch is downstream-only
The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively

001/9:[] [--] 'iotests: Make nbd-fault-injector flush'
002/9:[] [--] 'iotests: Flush in iotests.py's QemuIoInteractive'
003/9:[] [--] 'iotests: Use Python byte strings where appropriate'
004/9:[0014] [FC] 'iotests: Use // for Python integer division'
005/9:[0013] [FC] 'iotests: Different iterator behavior in Python 3'
006/9:[0049] [FC] 'iotests: Explicitly inherit FDs in Python'
007/9:[] [--] 'iotests: 'new' module replacement in 169'
008/9:[0017] [FC] 'iotests: Modify imports for Python 3'
009/9:[1644] [FC] 'iotests: Unify log outputs between Python 2 and 3'


Max Reitz (9):
  iotests: Make nbd-fault-injector flush
  iotests: Flush in iotests.py's QemuIoInteractive
  iotests: Use Python byte strings where appropriate
  iotests: Use // for Python integer division
  iotests: Different iterator behavior in Python 3
  iotests: Explicitly inherit FDs in Python
  iotests: 'new' module replacement in 169
  iotests: Modify imports for Python 3
  iotests: Unify log outputs between Python 2 and 3

 scripts/qemu.py  |  34 +-
 scripts/qtest.py |   2 +-
 tests/qemu-iotests/030   |   2 +-
 tests/qemu-iotests/040   |   4 +-
 tests/qemu-iotests/041   |   4 +-
 tests/qemu-iotests/044   |  24 +-
 tests/qemu-iotests/045   |   2 +-
 tests/qemu-iotests/056   |   2 +-
 tests/qemu-iotests/065   |   4 +-
 tests/qemu-iotests/083.out   |   9 +
 tests/qemu-iotests/093   |  18 +-
 tests/qemu-iotests/124   |   4 +-
 tests/qemu-iotests/136   |   2 +-
 tests/qemu-iotests/139   |   2 +-
 tests/qemu-iotests/147   |   2 +-
 tests/qemu-iotests/149   |  14 +-
 tests/qemu-iotests/151   |  12 +-
 tests/qemu-iotests/163   |  13 +-
 tests/qemu-iotests/169   |   3 +-
 tests/qemu-iotests/194.out   |  22 +-
 tests/qemu-iotests/202.out   |  12 +-
 tests/qemu-iotests/203.out   |  14 +-
 tests/qemu-iotests/206.out   | 218 +-
 tests/qemu-iotests/207   |   6 +-
 tests/qemu-iotests/207.out   |  72 ++--
 tests/qemu-iotests/208.out   |   8 +-
 tests/qemu-iotests/210.out   |  94 ++--
 tests/qemu-iotests/211.out   | 102 ++---
 tests/qemu-iotests/212.out   | 174 
 tests/qemu-iotests/213.out   | 182 
 tests/qemu-iotests/216.out   |   4 +-
 tests/qemu-iotests/218.out   |  20 +-
 tests/qemu-iotests/219.out   | 526 +++
 tests/qemu-iotests/222.out   |  24 +-
 tests/qemu-iotests/iotests.py|  37 +-
 tests/qemu-iotests/nbd-fault-injector.py |  12 +-
 tests/qemu-iotests/qcow2.py  |  10 +-
 tests/qemu-iotests/qed.py|   6 +-
 38 files changed, 879 insertions(+), 821 deletions(-)

-- 
2.17.1




[Qemu-block] [PATCH v2 9/9] iotests: Unify log outputs between Python 2 and 3

2018-10-19 Thread Max Reitz
When dumping an object into the log, there are differences between
Python 2 and 3.  First, unicode strings are prefixed by 'u' in Python 2
(they are no longer in 3, because unicode strings are the default
there).  Second, the order of keys in dicts may differ.  Third,
especially long numbers are longs in Python 2 and thus get an 'L'
suffix, which does not happen in Python 3.

We can get around all of these differences by dumping objects (lists and
dicts) in a language-independent format, namely JSON.  The JSON
generator even allows emitting dicts with their keys sorted
alphabetically.

This changes the output of all tests that use these logging functions
(dict keys are ordered now, strings in dicts are now enclosed in double
quotes instead of single quotes, the 'L' suffix of large integers is
dropped, and "true" and "false" are now in lower case).
The quote change necessitates a small change to a filter used in test
207.

Suggested-by: Eduardo Habkost 
Signed-off-by: Max Reitz 
---
 tests/qemu-iotests/194.out|  22 +-
 tests/qemu-iotests/202.out|  12 +-
 tests/qemu-iotests/203.out|  14 +-
 tests/qemu-iotests/206.out| 218 +++---
 tests/qemu-iotests/207|   2 +-
 tests/qemu-iotests/207.out|  72 ++---
 tests/qemu-iotests/208.out|   8 +-
 tests/qemu-iotests/210.out|  94 +++---
 tests/qemu-iotests/211.out| 102 +++
 tests/qemu-iotests/212.out| 174 +--
 tests/qemu-iotests/213.out| 182 ++--
 tests/qemu-iotests/216.out|   4 +-
 tests/qemu-iotests/218.out|  20 +-
 tests/qemu-iotests/219.out| 526 +-
 tests/qemu-iotests/222.out|  24 +-
 tests/qemu-iotests/iotests.py |  10 +-
 16 files changed, 744 insertions(+), 740 deletions(-)

diff --git a/tests/qemu-iotests/194.out b/tests/qemu-iotests/194.out
index 50ac50da5e..71857853fb 100644
--- a/tests/qemu-iotests/194.out
+++ b/tests/qemu-iotests/194.out
@@ -1,18 +1,18 @@
 Launching VMs...
 Launching NBD server on destination...
-{u'return': {}}
-{u'return': {}}
+{"return": {}}
+{"return": {}}
 Starting `drive-mirror` on source...
-{u'return': {}}
+{"return": {}}
 Waiting for `drive-mirror` to complete...
-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': 
{u'device': u'mirror-job0', u'type': u'mirror', u'speed': 0, u'len': 
1073741824, u'offset': 1073741824}, u'event': u'BLOCK_JOB_READY'}
+{"data": {"device": "mirror-job0", "len": 1073741824, "offset": 1073741824, 
"speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": 
{"microseconds": "USECS", "seconds": "SECS"}}
 Starting migration...
-{u'return': {}}
-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': 
{u'status': u'setup'}, u'event': u'MIGRATION'}
-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': 
{u'status': u'active'}, u'event': u'MIGRATION'}
-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': 
{u'status': u'completed'}, u'event': u'MIGRATION'}
+{"return": {}}
+{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": 
{"microseconds": "USECS", "seconds": "SECS"}}
+{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": 
{"microseconds": "USECS", "seconds": "SECS"}}
+{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": 
{"microseconds": "USECS", "seconds": "SECS"}}
 Gracefully ending the `drive-mirror` job on source...
-{u'return': {}}
-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': 
{u'device': u'mirror-job0', u'type': u'mirror', u'speed': 0, u'len': 
1073741824, u'offset': 1073741824}, u'event': u'BLOCK_JOB_COMPLETED'}
+{"return": {}}
+{"data": {"device": "mirror-job0", "len": 1073741824, "offset": 1073741824, 
"speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": 
{"microseconds": "USECS", "seconds": "SECS"}}
 Stopping the NBD server on destination...
-{u'return': {}}
+{"return": {}}
diff --git a/tests/qemu-iotests/202.out b/tests/qemu-iotests/202.out
index d5ea374e17..9a8619e796 100644
--- a/tests/qemu-iotests/202.out
+++ b/tests/qemu-iotests/202.out
@@ -1,11 +1,11 @@
 Launching VM...
 Adding IOThread...
-{u'return': {}}
+{"return": {}}
 Adding blockdevs...
-{u'return': {}}
-{u'return': {}}
+{"return": {}}
+{"return": {}}
 Setting iothread...
-{u'return': {}}
-{u'return': {}}
+{"return": {}}
+{"return": {}}
 Creating external snapshots...
-{u'return': {}}
+{"return": {}}
diff --git a/tests/qemu-iotests/203.out b/tests/qemu-iotests/203.out
index 1a11f0975c..9d4abba8c5 100644
--- a/tests/qemu-iotests/203.out
+++ b/tests/qemu-iotests/203.out
@@ -1,11 +1,11 @@
 Launching VM...
 Setting IOThreads...
-{u'return': {}}
-{u'return': {}}
+{"return": {}}
+{"return": {}}
 Enabling migration QMP events...
-{u'return': {}}
+{"return": {}}
 Starting migration...
-{u'return': {}}
-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': 
{u'status': u'setup'}, u'event': u'MIGRATION'}
-{u'timestamp': {u'seconds': '

[Qemu-block] [PATCH v2 6/9] iotests: Explicitly inherit FDs in Python

2018-10-19 Thread Max Reitz
Python 3.4 introduced the inheritable attribute for FDs.  At the same
time, it changed the default so that all FDs are not inheritable by
default, that only inheritable FDs are inherited to subprocesses, and
only if close_fds is explicitly set to False.

Adhere to this by setting close_fds to False when working with
subprocesses that may want to inherit FDs, and by trying to
set_inheritable() on FDs that we do want to bequeath to them.

Signed-off-by: Max Reitz 
---
 scripts/qemu.py| 34 +-
 tests/qemu-iotests/045 |  2 +-
 tests/qemu-iotests/147 |  2 +-
 3 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/scripts/qemu.py b/scripts/qemu.py
index f099ce7278..fb29b73c30 100644
--- a/scripts/qemu.py
+++ b/scripts/qemu.py
@@ -142,11 +142,19 @@ class QEMUMachine(object):
 if opts:
 options.append(opts)
 
+# This did not exist before 3.4, but since then it is
+# mandatory for our purpose
+if hasattr(os, 'set_inheritable'):
+os.set_inheritable(fd, True)
+
 self._args.append('-add-fd')
 self._args.append(','.join(options))
 return self
 
-def send_fd_scm(self, fd_file_path):
+# Exactly one of fd and file_path must be given.
+# (If it is file_path, the helper will open that file and pass its
+# own fd)
+def send_fd_scm(self, fd=None, file_path=None):
 # In iotest.py, the qmp should always use unix socket.
 assert self._qmp.is_scm_available()
 if self._socket_scm_helper is None:
@@ -154,12 +162,27 @@ class QEMUMachine(object):
 if not os.path.exists(self._socket_scm_helper):
 raise QEMUMachineError("%s does not exist" %
self._socket_scm_helper)
+
+# This did not exist before 3.4, but since then it is
+# mandatory for our purpose
+if hasattr(os, 'set_inheritable'):
+os.set_inheritable(self._qmp.get_sock_fd(), True)
+if fd is not None:
+os.set_inheritable(fd, True)
+
 fd_param = ["%s" % self._socket_scm_helper,
-"%d" % self._qmp.get_sock_fd(),
-"%s" % fd_file_path]
+"%d" % self._qmp.get_sock_fd()]
+
+if file_path is not None:
+assert fd is None
+fd_param.append(file_path)
+else:
+assert fd is not None
+fd_param.append(str(fd))
+
 devnull = open(os.path.devnull, 'rb')
 proc = subprocess.Popen(fd_param, stdin=devnull, 
stdout=subprocess.PIPE,
-stderr=subprocess.STDOUT)
+stderr=subprocess.STDOUT, close_fds=False)
 output = proc.communicate()[0]
 if output:
 LOG.debug(output)
@@ -280,7 +303,8 @@ class QEMUMachine(object):
stdin=devnull,
stdout=self._qemu_log_file,
stderr=subprocess.STDOUT,
-   shell=False)
+   shell=False,
+   close_fds=False)
 self._post_launch()
 
 def wait(self):
diff --git a/tests/qemu-iotests/045 b/tests/qemu-iotests/045
index 6be8fc4912..55a5d31ca8 100755
--- a/tests/qemu-iotests/045
+++ b/tests/qemu-iotests/045
@@ -140,7 +140,7 @@ class TestSCMFd(iotests.QMPTestCase):
 os.remove(image0)
 
 def _send_fd_by_SCM(self):
-ret = self.vm.send_fd_scm(image0)
+ret = self.vm.send_fd_scm(file_path=image0)
 self.assertEqual(ret, 0, 'Failed to send fd with UNIX SCM')
 
 def test_add_fd(self):
diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147
index d2081df84b..05b374b7d3 100755
--- a/tests/qemu-iotests/147
+++ b/tests/qemu-iotests/147
@@ -229,7 +229,7 @@ class BuiltinNBD(NBDBlockdevAddBase):
 sockfd = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
 sockfd.connect(unix_socket)
 
-result = self.vm.send_fd_scm(str(sockfd.fileno()))
+result = self.vm.send_fd_scm(fd=sockfd.fileno())
 self.assertEqual(result, 0, 'Failed to send socket FD')
 
 result = self.vm.qmp('getfd', fdname='nbd-fifo')
-- 
2.17.1




[Qemu-block] [PATCH v2 5/9] iotests: Different iterator behavior in Python 3

2018-10-19 Thread Max Reitz
In Python 3, several functions now return iterators instead of lists.
This includes range(), items(), map(), and filter().  This means that if
we really want a list, we have to wrap those instances with list().  But
then again, the two instances where this is the case for map() and
filter(), there are shorter expressions which work without either
function.

On the other hand, sometimes we do just want an iterator, in which case
we have sometimes used xrange() and iteritems() which no longer exist in
Python 3.  Just change these calls to be range() and items(), works in
both Python 2 and 3, and is really what we want in 3 (which is what
matters).  But because it is so simple to do (and to find and remove
once we completely switch to Python 3), make range() be an alias for
xrange() in the two affected tests (044 and 163).

In one instance, we only wanted the first instance of the result of a
filter() call.  Instead of using next(filter()) which would work only in
Python 3, or list(filter())[0] which would work everywhere but is a bit
weird, this instance is changed to use list comprehension with a next()
wrapped around, which works both in 2.7 and 3.

Signed-off-by: Max Reitz 
---
 tests/qemu-iotests/044 | 16 ++--
 tests/qemu-iotests/056 |  2 +-
 tests/qemu-iotests/065 |  4 ++--
 tests/qemu-iotests/124 |  4 ++--
 tests/qemu-iotests/139 |  2 +-
 tests/qemu-iotests/163 | 11 +++
 6 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/tests/qemu-iotests/044 b/tests/qemu-iotests/044
index 7ef5e46fe9..9ec3dba734 100755
--- a/tests/qemu-iotests/044
+++ b/tests/qemu-iotests/044
@@ -26,6 +26,10 @@ import iotests
 from iotests import qemu_img, qemu_img_verbose, qemu_io
 import struct
 import subprocess
+import sys
+
+if sys.version_info.major == 2:
+range = xrange
 
 test_img = os.path.join(iotests.test_dir, 'test.img')
 
@@ -52,23 +56,23 @@ class TestRefcountTableGrowth(iotests.QMPTestCase):
 # Write a refcount table
 fd.seek(off_reftable)
 
-for i in xrange(0, h.refcount_table_clusters):
+for i in range(0, h.refcount_table_clusters):
 sector = b''.join(struct.pack('>Q',
 off_refblock + i * 64 * 512 + j * 512)
-for j in xrange(0, 64))
+for j in range(0, 64))
 fd.write(sector)
 
 # Write the refcount blocks
 assert(fd.tell() == off_refblock)
 sector = b''.join(struct.pack('>H', 1) for j in range(0, 64 * 256))
-for block in xrange(0, h.refcount_table_clusters):
+for block in range(0, h.refcount_table_clusters):
 fd.write(sector)
 
 # Write the L1 table
 assert(fd.tell() == off_l1)
 assert(off_l2 + 512 * h.l1_size == off_data)
 table = b''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j)
-for j in xrange(0, h.l1_size))
+for j in range(0, h.l1_size))
 fd.write(table)
 
 # Write the L2 tables
@@ -79,14 +83,14 @@ class TestRefcountTableGrowth(iotests.QMPTestCase):
 off = off_data
 while remaining > 1024 * 512:
 pytable = list((1 << 63) | off + 512 * j
-for j in xrange(0, 1024))
+for j in range(0, 1024))
 table = struct.pack('>1024Q', *pytable)
 fd.write(table)
 remaining = remaining - 1024 * 512
 off = off + 1024 * 512
 
 table = b''.join(struct.pack('>Q', (1 << 63) | off + 512 * j)
-for j in xrange(0, remaining // 512))
+for j in range(0, remaining // 512))
 fd.write(table)
 
 
diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056
index 223292175a..3df323984d 100755
--- a/tests/qemu-iotests/056
+++ b/tests/qemu-iotests/056
@@ -32,7 +32,7 @@ target_img = os.path.join(iotests.test_dir, 'target.img')
 def img_create(img, fmt=iotests.imgfmt, size='64M', **kwargs):
 fullname = os.path.join(iotests.test_dir, '%s.%s' % (img, fmt))
 optargs = []
-for k,v in kwargs.iteritems():
+for k,v in kwargs.items():
 optargs = optargs + ['-o', '%s=%s' % (k,v)]
 args = ['create', '-f', fmt] + optargs + [fullname, size]
 iotests.qemu_img(*args)
diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065
index 72aa9707c7..8bac383ea7 100755
--- a/tests/qemu-iotests/065
+++ b/tests/qemu-iotests/065
@@ -59,7 +59,7 @@ class TestQemuImgInfo(TestImageInfoSpecific):
 :data.index('')]
 for field in data:
 self.assertTrue(re.match('^ {4}[^ ]', field) is not None)
-data = map(lambda line: line.strip(), data)
+data = [line.strip() for line in data]
 self.assertEqual(data, self.human_compare)
 
 class TestQMP(TestImageInfoSpecific):
@@ -80,7 +80,7 @@ class TestQMP(TestImageInfoSpecific):
 
 def test_qmp

[Qemu-block] [PATCH v2 3/9] iotests: Use Python byte strings where appropriate

2018-10-19 Thread Max Reitz
Since byte strings are no longer the default in Python 3, we have to
explicitly use them where we need to, which is mostly when working with
structures.  It also means that we need to open a file in binary mode
when we want to use structures.

On the other hand, we have to accomodate for the fact that some
functions (still) work with byte strings but we want to use unicode
strings (in Python 3 at least, and it does not matter in Python 2).
This includes base64 encoding, but it is most notable when working with
the subprocess module: Either we set universal_newlines to True so that
the default streams are opened in text mode (hence this parameter is
aliased as "text" as of 3.7), or, if that is not possible, we have to
decode the output to a normal string.

Signed-off-by: Max Reitz 
Reviewed-by: Eduardo Habkost 
---
 scripts/qtest.py |  2 +-
 tests/qemu-iotests/044   |  8 
 tests/qemu-iotests/149   |  8 +---
 tests/qemu-iotests/207   |  4 ++--
 tests/qemu-iotests/iotests.py| 11 +++
 tests/qemu-iotests/nbd-fault-injector.py |  4 ++--
 tests/qemu-iotests/qcow2.py  | 10 +-
 7 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/scripts/qtest.py b/scripts/qtest.py
index df0daf26ca..adf1fe3f26 100644
--- a/scripts/qtest.py
+++ b/scripts/qtest.py
@@ -64,7 +64,7 @@ class QEMUQtestProtocol(object):
 
 @param qtest_cmd: qtest command text to be sent
 """
-self._sock.sendall(qtest_cmd + "\n")
+self._sock.sendall((qtest_cmd + "\n").encode('utf-8'))
 
 def close(self):
 self._sock.close()
diff --git a/tests/qemu-iotests/044 b/tests/qemu-iotests/044
index 11ea0f4d35..69e736f687 100755
--- a/tests/qemu-iotests/044
+++ b/tests/qemu-iotests/044
@@ -53,21 +53,21 @@ class TestRefcountTableGrowth(iotests.QMPTestCase):
 fd.seek(off_reftable)
 
 for i in xrange(0, h.refcount_table_clusters):
-sector = ''.join(struct.pack('>Q',
+sector = b''.join(struct.pack('>Q',
 off_refblock + i * 64 * 512 + j * 512)
 for j in xrange(0, 64))
 fd.write(sector)
 
 # Write the refcount blocks
 assert(fd.tell() == off_refblock)
-sector = ''.join(struct.pack('>H', 1) for j in xrange(0, 64 * 256))
+sector = b''.join(struct.pack('>H', 1) for j in range(0, 64 * 256))
 for block in xrange(0, h.refcount_table_clusters):
 fd.write(sector)
 
 # Write the L1 table
 assert(fd.tell() == off_l1)
 assert(off_l2 + 512 * h.l1_size == off_data)
-table = ''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j)
+table = b''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j)
 for j in xrange(0, h.l1_size))
 fd.write(table)
 
@@ -85,7 +85,7 @@ class TestRefcountTableGrowth(iotests.QMPTestCase):
 remaining = remaining - 1024 * 512
 off = off + 1024 * 512
 
-table = ''.join(struct.pack('>Q', (1 << 63) | off + 512 * j)
+table = b''.join(struct.pack('>Q', (1 << 63) | off + 512 * j)
 for j in xrange(0, remaining / 512))
 fd.write(table)
 
diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149
index 9e0cad76f9..1225334cb8 100755
--- a/tests/qemu-iotests/149
+++ b/tests/qemu-iotests/149
@@ -79,7 +79,7 @@ class LUKSConfig(object):
 
 def first_password_base64(self):
 (pw, slot) = self.first_password()
-return base64.b64encode(pw)
+return base64.b64encode(pw.encode('ascii')).decode('ascii')
 
 def active_slots(self):
 slots = []
@@ -98,7 +98,8 @@ def verify_passwordless_sudo():
 proc = subprocess.Popen(args,
 stdin=subprocess.PIPE,
 stdout=subprocess.PIPE,
-stderr=subprocess.STDOUT)
+stderr=subprocess.STDOUT,
+universal_newlines=True)
 
 msg = proc.communicate()[0]
 
@@ -116,7 +117,8 @@ def cryptsetup(args, password=None):
 proc = subprocess.Popen(fullargs,
 stdin=subprocess.PIPE,
 stdout=subprocess.PIPE,
-stderr=subprocess.STDOUT)
+stderr=subprocess.STDOUT,
+universal_newlines=True)
 
 msg = proc.communicate(password)[0]
 
diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
index 444ae233ae..2d86a3da37 100755
--- a/tests/qemu-iotests/207
+++ b/tests/qemu-iotests/207
@@ -109,7 +109,7 @@ with iotests.FilePath('t.img') as disk_path, \
 md5_key = subprocess.check_output(
 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' +
 'cut -d" " -f3 | base64 -d | md5sum -b | cut -d" "

[Qemu-block] [PATCH v2 8/9] iotests: Modify imports for Python 3

2018-10-19 Thread Max Reitz
There are two imports that need to be modified when running the iotests
under Python 3: One is StringIO, which no longer exists; instead, the
StringIO class comes from the io module, so import it from there (and
use the BytesIO class for Python 2).  The other is the ConfigParser,
which has just been renamed to configparser.

Signed-off-by: Max Reitz 
---
 tests/qemu-iotests/iotests.py| 13 +
 tests/qemu-iotests/nbd-fault-injector.py |  7 +--
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 7ca94e9278..ed91095505 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -29,6 +29,7 @@ import json
 import signal
 import logging
 import atexit
+import io
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scripts'))
 import qtest
@@ -681,15 +682,19 @@ def main(supported_fmts=[], supported_oses=['linux'], 
supported_cache_modes=[],
 verify_platform(supported_oses)
 verify_cache_mode(supported_cache_modes)
 
-# We need to filter out the time taken from the output so that qemu-iotest
-# can reliably diff the results against master output.
-import StringIO
 if debug:
 output = sys.stdout
 verbosity = 2
 sys.argv.remove('-d')
 else:
-output = StringIO.StringIO()
+# We need to filter out the time taken from the output so that
+# qemu-iotest can reliably diff the results against master output.
+if sys.version_info.major >= 3:
+output = io.StringIO()
+else:
+# StringIO() is for unicode strings, which is not what
+# 2.x's test runner emits.
+output = io.BytesIO()
 
 logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
 
diff --git a/tests/qemu-iotests/nbd-fault-injector.py 
b/tests/qemu-iotests/nbd-fault-injector.py
index d45e2e0a6a..6b2d659dee 100755
--- a/tests/qemu-iotests/nbd-fault-injector.py
+++ b/tests/qemu-iotests/nbd-fault-injector.py
@@ -48,7 +48,10 @@ import sys
 import socket
 import struct
 import collections
-import ConfigParser
+if sys.version_info.major >= 3:
+import configparser
+else:
+import ConfigParser as configparser
 
 FAKE_DISK_SIZE = 8 * 1024 * 1024 * 1024 # 8 GB
 
@@ -225,7 +228,7 @@ def parse_config(config):
 return rules
 
 def load_rules(filename):
-config = ConfigParser.RawConfigParser()
+config = configparser.RawConfigParser()
 with open(filename, 'rt') as f:
 config.readfp(f, filename)
 return parse_config(config)
-- 
2.17.1




[Qemu-block] [PATCH v2 7/9] iotests: 'new' module replacement in 169

2018-10-19 Thread Max Reitz
iotest 169 uses the 'new' module to add methods to a class.  This module
no longer exists in Python 3.  Instead, we can use a lambda.  Best of
all, this works in 2.7 just as well.

Signed-off-by: Max Reitz 
Reviewed-by: Eduardo Habkost 
---
 tests/qemu-iotests/169 | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/tests/qemu-iotests/169 b/tests/qemu-iotests/169
index f243db9955..e5614b159d 100755
--- a/tests/qemu-iotests/169
+++ b/tests/qemu-iotests/169
@@ -23,7 +23,6 @@ import iotests
 import time
 import itertools
 import operator
-import new
 from iotests import qemu_img
 
 
@@ -144,7 +143,7 @@ class TestDirtyBitmapMigration(iotests.QMPTestCase):
 
 def inject_test_case(klass, name, method, *args, **kwargs):
 mc = operator.methodcaller(method, *args, **kwargs)
-setattr(klass, 'test_' + name, new.instancemethod(mc, None, klass))
+setattr(klass, 'test_' + name, lambda self: mc(self))
 
 for cmb in list(itertools.product((True, False), repeat=4)):
 name = ('_' if cmb[0] else '_not_') + 'persistent_'
-- 
2.17.1




[Qemu-block] [PATCH v2 4/9] iotests: Use // for Python integer division

2018-10-19 Thread Max Reitz
In Python 3, / is always a floating-point division.  We usually do not
want this, and as Python 2.7 understands // as well, change all integer
divisions to use that.

Signed-off-by: Max Reitz 
---
 tests/qemu-iotests/030|  2 +-
 tests/qemu-iotests/040|  4 ++--
 tests/qemu-iotests/041|  4 ++--
 tests/qemu-iotests/044|  2 +-
 tests/qemu-iotests/093| 18 +-
 tests/qemu-iotests/136|  2 +-
 tests/qemu-iotests/149|  6 +++---
 tests/qemu-iotests/151| 12 ++--
 tests/qemu-iotests/163|  2 +-
 tests/qemu-iotests/iotests.py |  2 +-
 tests/qemu-iotests/qed.py |  6 +++---
 11 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index 1dbc2ddc49..276e06b5ba 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -521,7 +521,7 @@ new_state = "2"
 state = "2"
 event = "%s"
 new_state = "1"
-''' % (event, errno, self.STREAM_BUFFER_SIZE / 512, event, event))
+''' % (event, errno, self.STREAM_BUFFER_SIZE // 512, event, event))
 file.close()
 
 class TestEIO(TestErrors):
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
index 1cb1ceeb33..b81133a474 100755
--- a/tests/qemu-iotests/040
+++ b/tests/qemu-iotests/040
@@ -195,7 +195,7 @@ class TestSingleDrive(ImageCommitTestCase):
 
 self.assert_no_active_block_jobs()
 result = self.vm.qmp('block-commit', device='drive0', top=mid_img,
- base=backing_img, speed=(self.image_len / 4))
+ base=backing_img, speed=(self.image_len // 4))
 self.assert_qmp(result, 'return', {})
 result = self.vm.qmp('device_del', id='scsi0')
 self.assert_qmp(result, 'return', {})
@@ -225,7 +225,7 @@ class TestSingleDrive(ImageCommitTestCase):
 
 self.assert_no_active_block_jobs()
 result = self.vm.qmp('block-commit', device='drive0', top=mid_img,
- base=backing_img, speed=(self.image_len / 4))
+ base=backing_img, speed=(self.image_len // 4))
 self.assert_qmp(result, 'return', {})
 
 result = self.vm.qmp('query-block')
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index 9336ab6ff5..3615011d98 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -404,7 +404,7 @@ new_state = "2"
 state = "2"
 event = "%s"
 new_state = "1"
-''' % (event, errno, self.MIRROR_GRANULARITY / 512, event, event))
+''' % (event, errno, self.MIRROR_GRANULARITY // 512, event, event))
 file.close()
 
 def setUp(self):
@@ -569,7 +569,7 @@ new_state = "2"
 state = "2"
 event = "%s"
 new_state = "1"
-''' % (event, errno, self.MIRROR_GRANULARITY / 512, event, event))
+''' % (event, errno, self.MIRROR_GRANULARITY // 512, event, event))
 file.close()
 
 def setUp(self):
diff --git a/tests/qemu-iotests/044 b/tests/qemu-iotests/044
index 69e736f687..7ef5e46fe9 100755
--- a/tests/qemu-iotests/044
+++ b/tests/qemu-iotests/044
@@ -86,7 +86,7 @@ class TestRefcountTableGrowth(iotests.QMPTestCase):
 off = off + 1024 * 512
 
 table = b''.join(struct.pack('>Q', (1 << 63) | off + 512 * j)
-for j in xrange(0, remaining / 512))
+for j in xrange(0, remaining // 512))
 fd.write(table)
 
 
diff --git a/tests/qemu-iotests/093 b/tests/qemu-iotests/093
index 9d1971a56c..d88fbc182e 100755
--- a/tests/qemu-iotests/093
+++ b/tests/qemu-iotests/093
@@ -69,18 +69,18 @@ class ThrottleTestCase(iotests.QMPTestCase):
 # in. The throttled requests won't be executed until we
 # advance the virtual clock.
 rq_size = 512
-rd_nr = max(params['bps'] / rq_size / 2,
-params['bps_rd'] / rq_size,
-params['iops'] / 2,
+rd_nr = max(params['bps'] // rq_size // 2,
+params['bps_rd'] // rq_size,
+params['iops'] // 2,
 params['iops_rd'])
 rd_nr *= seconds * 2
-rd_nr /= ndrives
-wr_nr = max(params['bps'] / rq_size / 2,
-params['bps_wr'] / rq_size,
-params['iops'] / 2,
+rd_nr //= ndrives
+wr_nr = max(params['bps'] // rq_size // 2,
+params['bps_wr'] // rq_size,
+params['iops'] // 2,
 params['iops_wr'])
 wr_nr *= seconds * 2
-wr_nr /= ndrives
+wr_nr //= ndrives
 
 # Send I/O requests to all drives
 for i in range(rd_nr):
@@ -196,7 +196,7 @@ class ThrottleTestCase(iotests.QMPTestCase):
 self.configure_throttle(ndrives, settings)
 
 # Wait for the bucket to empty so we can do bursts
-wait_ns = nsec_per_sec * burst_length * burst_rate / rate
+wait_ns = nsec_per_sec * burst_length * burst_rate // rate
 self.vm.qtest("clock_step %d" % wai

[Qemu-block] [PATCH v2 1/9] iotests: Make nbd-fault-injector flush

2018-10-19 Thread Max Reitz
When closing a connection, make the nbd-fault-injector flush the socket.
Without this, the output is a bit unreliable with Python 3.

Signed-off-by: Max Reitz 
Reviewed-by: Eduardo Habkost 
Reviewed-by: Cleber Rosa 
Reviewed-by: Eric Blake 
---
 tests/qemu-iotests/083.out   | 9 +
 tests/qemu-iotests/nbd-fault-injector.py | 1 +
 2 files changed, 10 insertions(+)

diff --git a/tests/qemu-iotests/083.out b/tests/qemu-iotests/083.out
index be6079d27e..f9af8bb691 100644
--- a/tests/qemu-iotests/083.out
+++ b/tests/qemu-iotests/083.out
@@ -41,6 +41,7 @@ can't open device nbd+tcp://127.0.0.1:PORT/foo
 
 === Check disconnect after neg2 ===
 
+Unable to read from socket: Connection reset by peer
 Connection closed
 read failed: Input/output error
 
@@ -54,6 +55,7 @@ can't open device nbd+tcp://127.0.0.1:PORT/foo
 
 === Check disconnect before request ===
 
+Unable to read from socket: Connection reset by peer
 Connection closed
 read failed: Input/output error
 
@@ -116,6 +118,7 @@ can't open device nbd+tcp://127.0.0.1:PORT/
 
 === Check disconnect after neg-classic ===
 
+Unable to read from socket: Connection reset by peer
 Connection closed
 read failed: Input/output error
 
@@ -161,6 +164,8 @@ can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
 
 === Check disconnect after neg2 ===
 
+Unable to read from socket: Connection reset by peer
+Connection closed
 read failed: Input/output error
 
 === Check disconnect 8 neg2 ===
@@ -173,6 +178,8 @@ can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
 
 === Check disconnect before request ===
 
+Unable to read from socket: Connection reset by peer
+Connection closed
 read failed: Input/output error
 
 === Check disconnect after request ===
@@ -234,6 +241,8 @@ can't open device nbd+unix:///?socket=TEST_DIR/nbd.sock
 
 === Check disconnect after neg-classic ===
 
+Unable to read from socket: Connection reset by peer
+Connection closed
 read failed: Input/output error
 
 *** done
diff --git a/tests/qemu-iotests/nbd-fault-injector.py 
b/tests/qemu-iotests/nbd-fault-injector.py
index f9193c0fae..439a090eb6 100755
--- a/tests/qemu-iotests/nbd-fault-injector.py
+++ b/tests/qemu-iotests/nbd-fault-injector.py
@@ -112,6 +112,7 @@ class FaultInjectionSocket(object):
 if rule.match(event, io):
 if rule.when == 0 or bufsize is None:
 print('Closing connection on rule match %s' % rule.name)
+self.sock.flush()
 sys.exit(0)
 if rule.when != -1:
 return rule.when
-- 
2.17.1




[Qemu-block] [PATCH v2 2/9] iotests: Flush in iotests.py's QemuIoInteractive

2018-10-19 Thread Max Reitz
After issuing a command, flush the pipe.  This does not change anything
in Python 2, but it makes a difference in Python 3.

Signed-off-by: Max Reitz 
Reviewed-by: Eduardo Habkost 
Reviewed-by: Cleber Rosa 
---
 tests/qemu-iotests/iotests.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 4e67fbbe96..10f2d17419 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -178,6 +178,7 @@ class QemuIoInteractive:
 cmd = cmd.strip()
 assert cmd != 'q' and cmd != 'quit'
 self._p.stdin.write(cmd + '\n')
+self._p.stdin.flush()
 return self._read_output()
 
 
-- 
2.17.1




Re: [Qemu-block] [PATCH v4 03/11] rbd: Close image in qemu_rbd_open() error path

2018-10-19 Thread Eric Blake

On 10/19/18 11:30 AM, Kevin Wolf wrote:

Commit e2b8247a322 introduced an error path in qemu_rbd_open() after
calling rbd_open(), but neglected to close the image again in this error
path. The error path should contain everything that the regular close
function qemu_rbd_close() contains.

This adds the missing rbd_close() call.

Signed-off-by: Kevin Wolf 
---
  block/rbd.c | 1 +
  1 file changed, 1 insertion(+)



Reviewed-by: Eric Blake 


diff --git a/block/rbd.c b/block/rbd.c
index 014c68d629..27c9a1e81c 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -787,6 +787,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict 
*options, int flags,
   "automatically marking the image read-only.");
  r = bdrv_set_read_only(bs, true, &local_err);
  if (r < 0) {
+rbd_close(s->image);
  error_propagate(errp, local_err);
  goto failed_open;
  }



--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org



[Qemu-block] [PATCH v2 0/5] Various option help readability improvement suggestions

2018-10-19 Thread Max Reitz
I noticed that with the (more or less) recent series from Marc-André the
output of qemu-img amend -f qcow2 -o help changed to this:

$ ./qemu-img amend -f qcow2 -o help
Creation options for 'qcow2':
qcow2-create-opts.backing_file=str - File name of a base image
qcow2-create-opts.backing_fmt=str - Image format of the base image
qcow2-create-opts.cluster_size=size - qcow2 cluster size
qcow2-create-opts.compat=str - Compatibility level (0.10 or 1.1)
[...]

The types are a nice addition, but I didn't like having the list name
printed in every single line (in fact, the list name does not make any
sense here at all, because there already is a caption which reads
"Creation options for 'qcow2'"), and I did not like the use of '=' for
types.

In general, I don't like the robot-y appearance, which is even worse in
things like -device virtio-blk,help, which gives you this (among
other lines):

> virtio-blk-pci.iothread=link

Sadly, there isn't much we can do about the "link", so this
series doesn't improve on that point.

What this series does do, however, is it changes these lists not to
print the list name on every single line, but only as a caption (and for
option lists, this caption is option, because the caller may want to
print a custom caption that is more expressive -- as is the case for
qemu-img amend -o help).

Consequentially, all list items are indented by two spaces to make clear
they belong to the caption.  I can already see that some people might
disagree on having this indentation, but I like it, so I have it in this
series.

Furthermore, types are now enclosed by angle brackets, and the alignment
we originally had for descriptions is restored (although now after 24
instead of 16 characters, because every option name is now accompanied
by indentation and a type).


Thus, after this series, the amend output looks like this:

$ ./qemu-img amend -f qcow2 -o help
Creation options for 'qcow2':
  backing_file= - File name of a base image
  backing_fmt=  - Image format of the base image
  cluster_size=- qcow2 cluster size
  compat=   - Compatibility level (0.10 or 1.1)
[...]


virtio-blk's list presents itself like so:

$ x86_64-softmmu/qemu-system-x86_64 -device virtio-blk,help
virtio-blk-pci options:
  iothread=>
  request-merging= - on/off
  secs=
[...]


And now we even print something when there are no options:

$ x86_64-softmmu/qemu-system-x86_64 -object can-bus,help
There are no options for can-bus.

(Before this series, there just is no output.)


As a side effect, patch 1 fixes iotest 082.


v2:
- Patch 1:
  - Abandon the "$name: $type" formatting in favor of "$name=<$type>"
[Marc-André, at least the "abandon" part]
  - Restore description alignment [Kevin]
  - Do the alignment when generating each line's GString instead of when
printing them.  This results in less lines modified and allows the
compiler to optimize the printf("%s\n", x) to puts(x).
- Patch 3:
  - Same changes as above, with the addition of also separating the
description with " - " instead of enclosing it in parentheses (to
match the other places)
  - Also, we never did align the descriptions here, so this is not
"restore" but "introduce description alignment".
- Patch 4:
  - Same as patch 1, but again with the catch of s/restore/introduce/.


git-backport-diff against v1:

Key:
[] : patches are identical
[] : number of functional differences between upstream/downstream patch
[down] : patch is downstream-only
The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively

001/5:[0963] [FC] 'option: Make option help nicer to read'
002/5:[] [--] 'chardev: Indent list of chardevs'
003/5:[0008] [FC] 'qdev-monitor: Make device options help nicer'
004/5:[0007] [FC] 'object: Make option help nicer to read'
005/5:[] [--] 'fw_cfg: Drop newline in @file description'


Max Reitz (5):
  option: Make option help nicer to read
  chardev: Indent list of chardevs
  qdev-monitor: Make device options help nicer
  object: Make option help nicer to read
  fw_cfg: Drop newline in @file description

 include/qemu/option.h  |   2 +-
 chardev/char.c |   2 +-
 qdev-monitor.c |  13 +-
 qemu-img.c |   4 +-
 util/qemu-option.c |  32 +-
 vl.c   |  15 +-
 tests/qemu-iotests/082.out | 956 ++---
 7 files changed, 530 insertions(+), 494 deletions(-)

-- 
2.17.1




[Qemu-block] [PATCH v2 1/5] option: Make option help nicer to read

2018-10-19 Thread Max Reitz
This adds some whitespace into the option help (including indentation)
and puts angle brackets around the type names.  Furthermore, the list
name is no longer printed as part of every line, but only once in
advance, and only if the caller did not print a caption already.

This patch also restores the description alignment we had before commit
9cbef9d68ee1d8d0, just at 24 instead of 16 characters like we used to.
This increase is because now we have the type and two spaces of
indentation before the description, and with a usual type name length of
three chracters, this sums up to eight additional characters -- which
means that we now need 24 characters to get the same amount of padding
for most options.  Also, 24 is a third of 80, which makes it kind of a
round number in terminal terms.

Finally, this patch amends the reference output of iotest 082 to match
the changes (and thus makes it pass again).

Signed-off-by: Max Reitz 
---
 include/qemu/option.h  |   2 +-
 qemu-img.c |   4 +-
 util/qemu-option.c |  32 +-
 tests/qemu-iotests/082.out | 956 ++---
 4 files changed, 507 insertions(+), 487 deletions(-)

diff --git a/include/qemu/option.h b/include/qemu/option.h
index 3dfb4493cc..844587cab3 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -132,7 +132,7 @@ typedef int (*qemu_opts_loopfunc)(void *opaque, QemuOpts 
*opts, Error **errp);
 int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
   void *opaque, Error **errp);
 void qemu_opts_print(QemuOpts *opts, const char *sep);
-void qemu_opts_print_help(QemuOptsList *list);
+void qemu_opts_print_help(QemuOptsList *list, bool print_caption);
 void qemu_opts_free(QemuOptsList *list);
 QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list);
 
diff --git a/qemu-img.c b/qemu-img.c
index b12f4cd19b..4c96db7ba4 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -269,7 +269,7 @@ static int print_block_option_help(const char *filename, 
const char *fmt)
 }
 
 printf("Supported options:\n");
-qemu_opts_print_help(create_opts);
+qemu_opts_print_help(create_opts, false);
 qemu_opts_free(create_opts);
 return 0;
 }
@@ -3773,7 +3773,7 @@ static int print_amend_option_help(const char *format)
 assert(drv->create_opts);
 
 printf("Creation options for '%s':\n", format);
-qemu_opts_print_help(drv->create_opts);
+qemu_opts_print_help(drv->create_opts, false);
 printf("\nNote that not all of these options may be amendable.\n");
 return 0;
 }
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 9a5f263294..de42e2a406 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -224,7 +224,14 @@ static const char *opt_type_to_string(enum QemuOptType 
type)
 g_assert_not_reached();
 }
 
-void qemu_opts_print_help(QemuOptsList *list)
+/**
+ * Print the list of options available in the given list.  If
+ * @print_caption is true, a caption (including the list name, if it
+ * exists) is printed.  The options itself will be indented, so
+ * @print_caption should only be set to false if the caller prints its
+ * own custom caption (so that the indentation makes sense).
+ */
+void qemu_opts_print_help(QemuOptsList *list, bool print_caption)
 {
 QemuOptDesc *desc;
 int i;
@@ -234,12 +241,12 @@ void qemu_opts_print_help(QemuOptsList *list)
 desc = list->desc;
 while (desc && desc->name) {
 GString *str = g_string_new(NULL);
-if (list->name) {
-g_string_append_printf(str, "%s.", list->name);
-}
-g_string_append_printf(str, "%s=%s", desc->name,
+g_string_append_printf(str, "  %s=<%s>", desc->name,
opt_type_to_string(desc->type));
 if (desc->help) {
+if (str->len < 24) {
+g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
+}
 g_string_append_printf(str, " - %s", desc->help);
 }
 g_ptr_array_add(array, g_string_free(str, false));
@@ -247,6 +254,19 @@ void qemu_opts_print_help(QemuOptsList *list)
 }
 
 g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
+if (print_caption && array->len > 0) {
+if (list->name) {
+printf("%s options:\n", list->name);
+} else {
+printf("Options:\n");
+}
+} else if (array->len == 0) {
+if (list->name) {
+printf("There are no options for %s.\n", list->name);
+} else {
+printf("No options available.\n");
+}
+}
 for (i = 0; i < array->len; i++) {
 printf("%s\n", (char *)array->pdata[i]);
 }
@@ -930,7 +950,7 @@ QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const 
char *params,
 opts = opts_parse(list, params, permit_abbrev, false, &invalidp, &err);
 if (err) {
 if (invalidp && has_help_option(params)) {
-qemu_opts_print_help(list);
+qemu

[Qemu-block] [PATCH v2 2/5] chardev: Indent list of chardevs

2018-10-19 Thread Max Reitz
Following the example of qemu_opts_print_help(), indent all entries in
the list of character devices.

Signed-off-by: Max Reitz 
---
 chardev/char.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/chardev/char.c b/chardev/char.c
index e115166995..10d44aaefc 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -569,7 +569,7 @@ help_string_append(const char *name, void *opaque)
 {
 GString *str = opaque;
 
-g_string_append_printf(str, "\n%s", name);
+g_string_append_printf(str, "\n  %s", name);
 }
 
 static const char *chardev_alias_translate(const char *name)
-- 
2.17.1




[Qemu-block] [PATCH v2 5/5] fw_cfg: Drop newline in @file description

2018-10-19 Thread Max Reitz
There is no good reason why there should be a newline in this
description, so remove it.

Signed-off-by: Max Reitz 
Reviewed-by: Philippe Mathieu-Daudé 
---
 vl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/vl.c b/vl.c
index ecddbb6b8e..6604648570 100644
--- a/vl.c
+++ b/vl.c
@@ -529,7 +529,7 @@ static QemuOptsList qemu_fw_cfg_opts = {
 }, {
 .name = "file",
 .type = QEMU_OPT_STRING,
-.help = "Sets the name of the file from which\n"
+.help = "Sets the name of the file from which "
 "the fw_cfg blob will be loaded",
 }, {
 .name = "string",
-- 
2.17.1




[Qemu-block] [PATCH v2 4/5] object: Make option help nicer to read

2018-10-19 Thread Max Reitz
Just like in qemu_opts_print_help(), print the object name as a caption
instead of on every single line, indent all options, add angle brackets
around types, and align the descriptions after 24 characters.

Also, indent every object name in the list of available objects.

Signed-off-by: Max Reitz 
---
 vl.c | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/vl.c b/vl.c
index ac3ed17de4..ecddbb6b8e 100644
--- a/vl.c
+++ b/vl.c
@@ -2707,7 +2707,7 @@ static bool object_create_initial(const char *type, 
QemuOpts *opts)
 list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false);
 for (l = list; l != NULL; l = l->next) {
 ObjectClass *oc = OBJECT_CLASS(l->data);
-printf("%s\n", object_class_get_name(oc));
+printf("  %s\n", object_class_get_name(oc));
 }
 g_slist_free(list);
 exit(0);
@@ -2729,14 +2729,21 @@ static bool object_create_initial(const char *type, 
QemuOpts *opts)
 }
 
 str = g_string_new(NULL);
-g_string_append_printf(str, "%s.%s=%s", type,
-   prop->name, prop->type);
+g_string_append_printf(str, "  %s=<%s>", prop->name, prop->type);
 if (prop->description) {
+if (str->len < 24) {
+g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
+}
 g_string_append_printf(str, " - %s", prop->description);
 }
 g_ptr_array_add(array, g_string_free(str, false));
 }
 g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
+if (array->len > 0) {
+printf("%s options:\n", type);
+} else {
+printf("There are no options for %s.\n", type);
+}
 for (i = 0; i < array->len; i++) {
 printf("%s\n", (char *)array->pdata[i]);
 }
-- 
2.17.1




[Qemu-block] [PATCH v2 3/5] qdev-monitor: Make device options help nicer

2018-10-19 Thread Max Reitz
Just like in qemu_opts_print_help(), print the device name as a caption
instead of on every single line, indent all options, add angle brackets
around types, and align the descriptions after 24 characters.  Also,
separate the descriptions with " - " instead of putting them in
parentheses, because that is what we do everywhere else.  This does look
a bit funny here because basically all bits have the description
"on/off", but funny does not mean it is less readable.

Signed-off-by: Max Reitz 
---
 qdev-monitor.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/qdev-monitor.c b/qdev-monitor.c
index 802c18a74e..07147c63bf 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -285,10 +285,19 @@ int qdev_device_help(QemuOpts *opts)
 goto error;
 }
 
+if (prop_list) {
+out_printf("%s options:\n", driver);
+} else {
+out_printf("There are no options for %s.\n", driver);
+}
 for (prop = prop_list; prop; prop = prop->next) {
-out_printf("%s.%s=%s", driver, prop->value->name, prop->value->type);
+int len;
+out_printf("  %s=<%s>%n", prop->value->name, prop->value->type, &len);
 if (prop->value->has_description) {
-out_printf(" (%s)\n", prop->value->description);
+if (len < 24) {
+out_printf("%*s", 24 - len, "");
+}
+out_printf(" - %s\n", prop->value->description);
 } else {
 out_printf("\n");
 }
-- 
2.17.1




[Qemu-block] [PATCH v4 03/11] rbd: Close image in qemu_rbd_open() error path

2018-10-19 Thread Kevin Wolf
Commit e2b8247a322 introduced an error path in qemu_rbd_open() after
calling rbd_open(), but neglected to close the image again in this error
path. The error path should contain everything that the regular close
function qemu_rbd_close() contains.

This adds the missing rbd_close() call.

Signed-off-by: Kevin Wolf 
---
 block/rbd.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/block/rbd.c b/block/rbd.c
index 014c68d629..27c9a1e81c 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -787,6 +787,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict 
*options, int flags,
  "automatically marking the image read-only.");
 r = bdrv_set_read_only(bs, true, &local_err);
 if (r < 0) {
+rbd_close(s->image);
 error_propagate(errp, local_err);
 goto failed_open;
 }
-- 
2.19.1




[Qemu-block] [PATCH v4 09/11] iscsi: Support auto-read-only option

2018-10-19 Thread Kevin Wolf
If read-only=off, but auto-read-only=on is given, open the volume
read-write if we have the permissions, but instead of erroring out for
read-only volumes, just degrade to read-only.

Signed-off-by: Kevin Wolf 
Reviewed-by: Eric Blake 
---
 block/iscsi.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/block/iscsi.c b/block/iscsi.c
index bb69faf34a..130ae26f5f 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1878,9 +1878,11 @@ static int iscsi_open(BlockDriverState *bs, QDict 
*options, int flags,
 /* Check the write protect flag of the LUN if we want to write */
 if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&
 iscsilun->write_protected) {
-error_setg(errp, "Cannot open a write protected LUN as read-write");
-ret = -EACCES;
-goto out;
+ret = bdrv_apply_auto_read_only(bs, "LUN is write protected", errp);
+if (ret < 0) {
+goto out;
+}
+flags &= ~BDRV_O_RDWR;
 }
 
 iscsi_readcapacity_sync(iscsilun, &local_err);
-- 
2.19.1




[Qemu-block] [PATCH v4 08/11] gluster: Support auto-read-only option

2018-10-19 Thread Kevin Wolf
If read-only=off, but auto-read-only=on is given, open the file
read-write if we have the permissions, but instead of erroring out for
read-only files, just degrade to read-only.

Signed-off-by: Kevin Wolf 
Reviewed-by: Niels de Vos 
---
 block/gluster.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/block/gluster.c b/block/gluster.c
index 4fd55a9cc5..5e300c96c8 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -849,8 +849,16 @@ static int qemu_gluster_open(BlockDriverState *bs,  QDict 
*options,
 qemu_gluster_parse_flags(bdrv_flags, &open_flags);
 
 s->fd = glfs_open(s->glfs, gconf->path, open_flags);
-if (!s->fd) {
-ret = -errno;
+ret = s->fd ? 0 : -errno;
+
+if (ret == -EACCES || ret == -EROFS) {
+/* Try to degrade to read-only, but if it doesn't work, still use the
+ * normal error message. */
+if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
+open_flags = (open_flags & ~O_RDWR) | O_RDONLY;
+s->fd = glfs_open(s->glfs, gconf->path, open_flags);
+ret = s->fd ? 0 : -errno;
+}
 }
 
 s->supports_seek_data = qemu_gluster_test_seek(s->fd);
-- 
2.19.1




[Qemu-block] [PATCH v4 05/11] nbd: Support auto-read-only option

2018-10-19 Thread Kevin Wolf
If read-only=off, but auto-read-only=on is given, open a read-write NBD
connection if the server provides a read-write export, but instead of
erroring out for read-only exports, just degrade to read-only.

Signed-off-by: Kevin Wolf 
Reviewed-by: Eric Blake 
---
 block/nbd-client.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/block/nbd-client.c b/block/nbd-client.c
index 9686ecbd5e..76e9ca3abe 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -992,11 +992,11 @@ int nbd_client_init(BlockDriverState *bs,
 logout("Failed to negotiate with the NBD server\n");
 return ret;
 }
-if (client->info.flags & NBD_FLAG_READ_ONLY &&
-!bdrv_is_read_only(bs)) {
-error_setg(errp,
-   "request for write access conflicts with read-only export");
-return -EACCES;
+if (client->info.flags & NBD_FLAG_READ_ONLY) {
+ret = bdrv_apply_auto_read_only(bs, "NBD export is read-only", errp);
+if (ret < 0) {
+return ret;
+}
 }
 if (client->info.flags & NBD_FLAG_SEND_FUA) {
 bs->supported_write_flags = BDRV_REQ_FUA;
-- 
2.19.1




[Qemu-block] [PATCH v4 04/11] block: Require auto-read-only for existing fallbacks

2018-10-19 Thread Kevin Wolf
Some block drivers have traditionally changed their node to read-only
mode without asking the user. This behaviour has been marked deprecated
since 2.11, expecting users to provide an explicit read-only=on option.

Now that we have auto-read-only=on, enable these drivers to make use of
the option.

This is the only use of bdrv_set_read_only(), so we can make it a bit
more specific and turn it into a bdrv_apply_auto_read_only() that is
more convenient for drivers to use.

Signed-off-by: Kevin Wolf 
Reviewed-by: Eric Blake 
---
 include/block/block.h |  3 ++-
 block.c   | 42 +++---
 block/bochs.c | 17 ++---
 block/cloop.c | 16 +---
 block/dmg.c   | 16 +---
 block/rbd.c   | 15 ---
 block/vvfat.c | 10 ++
 7 files changed, 51 insertions(+), 68 deletions(-)

diff --git a/include/block/block.h b/include/block/block.h
index 580b3716c3..7f5453b45b 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -438,7 +438,8 @@ int bdrv_is_allocated_above(BlockDriverState *top, 
BlockDriverState *base,
 bool bdrv_is_read_only(BlockDriverState *bs);
 int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
bool ignore_allow_rdw, Error **errp);
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp);
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
+  Error **errp);
 bool bdrv_is_writable(BlockDriverState *bs);
 bool bdrv_is_sg(BlockDriverState *bs);
 bool bdrv_is_inserted(BlockDriverState *bs);
diff --git a/block.c b/block.c
index ed73522cc6..a97e324f39 100644
--- a/block.c
+++ b/block.c
@@ -266,29 +266,41 @@ int bdrv_can_set_read_only(BlockDriverState *bs, bool 
read_only,
 return 0;
 }
 
-/* TODO Remove (deprecated since 2.11)
- * Block drivers are not supposed to automatically change bs->read_only.
- * Instead, they should just check whether they can provide what the user
- * explicitly requested and error out if read-write is requested, but they can
- * only provide read-only access. */
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
+/*
+ * Called by a driver that can only provide a read-only image.
+ *
+ * Returns 0 if the node is already read-only or it could switch the node to
+ * read-only because BDRV_O_AUTO_RDONLY is set.
+ *
+ * Returns -EACCES if the node is read-write and BDRV_O_AUTO_RDONLY is not set
+ * or bdrv_can_set_read_only() forbids making the node read-only. If @errmsg
+ * is not NULL, it is used as the error message for the Error object.
+ */
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
+  Error **errp)
 {
 int ret = 0;
 
-ret = bdrv_can_set_read_only(bs, read_only, false, errp);
-if (ret < 0) {
-return ret;
+if (!(bs->open_flags & BDRV_O_RDWR)) {
+return 0;
+}
+if (!(bs->open_flags & BDRV_O_AUTO_RDONLY)) {
+goto fail;
 }
 
-bs->read_only = read_only;
-
-if (read_only) {
-bs->open_flags &= ~BDRV_O_RDWR;
-} else {
-bs->open_flags |= BDRV_O_RDWR;
+ret = bdrv_can_set_read_only(bs, true, false, NULL);
+if (ret < 0) {
+goto fail;
 }
 
+bs->read_only = true;
+bs->open_flags &= ~BDRV_O_RDWR;
+
 return 0;
+
+fail:
+error_setg(errp, "%s", errmsg ?: "Image is read-only");
+return -EACCES;
 }
 
 void bdrv_get_full_backing_filename_from_filename(const char *backed,
diff --git a/block/bochs.c b/block/bochs.c
index 50c630047b..22e7d44211 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -105,23 +105,18 @@ static int bochs_open(BlockDriverState *bs, QDict 
*options, int flags,
 struct bochs_header bochs;
 int ret;
 
+/* No write support yet */
+ret = bdrv_apply_auto_read_only(bs, NULL, errp);
+if (ret < 0) {
+return ret;
+}
+
 bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
false, errp);
 if (!bs->file) {
 return -EINVAL;
 }
 
-if (!bdrv_is_read_only(bs)) {
-error_report("Opening bochs images without an explicit read-only=on "
- "option is deprecated. Future versions will refuse to "
- "open the image instead of automatically marking the "
- "image read-only.");
-ret = bdrv_set_read_only(bs, true, errp); /* no write support yet */
-if (ret < 0) {
-return ret;
-}
-}
-
 ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
 if (ret < 0) {
 return ret;
diff --git a/block/cloop.c b/block/cloop.c
index 2be68987bd..df2b85f723 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -67,23 +67,17 @@ static int cloop_open(BlockDriverState *bs, QDict *options, 
int flags,
 uint32_t offsets_size, max_compressed_block_size = 1, i;
 int re

[Qemu-block] [PATCH v4 02/11] block: Add auto-read-only option

2018-10-19 Thread Kevin Wolf
If a management application builds the block graph node by node, the
protocol layer doesn't inherit its read-only option from the format
layer any more, so it must be set explicitly.

Backing files should work on read-only storage, but at the same time, a
block job like commit should be able to reopen them read-write if they
are on read-write storage. However, without option inheritance, reopen
only changes the read-only option for the root node (typically the
format layer), but not the protocol layer, so reopening fails (the
format layer wants to get write permissions, but the protocol layer is
still read-only).

A simple workaround for the problem in the management tool would be to
open the protocol layer always read-write and to make only the format
layer read-only for backing files. However, sometimes the file is
actually stored on read-only storage and we don't know whether the image
can be opened read-write (for example, for NBD it depends on the server
we're trying to connect to). This adds an option that makes QEMU try to
open the image read-write, but allows it to degrade to a read-only mode
without returning an error.

The documentation for this option is consciously phrased in a way that
allows QEMU to switch to a better model eventually: Instead of trying
when the image is first opened, making the read-only flag dynamic and
changing it automatically whenever the first BLK_PERM_WRITE user is
attached or the last one is detached would be much more useful
behaviour.

Unfortunately, this more useful behaviour is also a lot harder to
implement, and libvirt needs a solution now before it can switch to
-blockdev, so let's start with this easier approach for now.

Instead of adding a new auto-read-only option, turning the existing
read-only into an enum (with a bool alternate for compatibility) was
considered, but it complicated the implementation to the point that it
didn't seem to be worth it.

Signed-off-by: Kevin Wolf 
Reviewed-by: Eric Blake 
---
 qapi/block-core.json  |  7 +++
 include/block/block.h |  2 ++
 block.c   | 17 +
 block/vvfat.c |  1 +
 4 files changed, 27 insertions(+)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index cfb37f8c1d..2ac4e69e68 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -3651,6 +3651,12 @@
 # either generally or in certain configurations. In this case,
 # the default value does not work and the option must be
 # specified explicitly.
+# @auto-read-only: if true and @read-only is false, QEMU may automatically
+#  decide not to open the image read-write as requested, but
+#  fall back to read-only instead (and switch between the modes
+#  later), e.g. depending on whether the image file is writable
+#  or whether a writing user is attached to the node
+#  (default: false, since 3.1)
 # @detect-zeroes: detect and optimize zero writes (Since 2.1)
 # (default: off)
 # @force-share:   force share all permission on added nodes.
@@ -3666,6 +3672,7 @@
 '*discard': 'BlockdevDiscardOptions',
 '*cache': 'BlockdevCacheOptions',
 '*read-only': 'bool',
+'*auto-read-only': 'bool',
 '*force-share': 'bool',
 '*detect-zeroes': 'BlockdevDetectZeroesOptions' },
   'discriminator': 'driver',
diff --git a/include/block/block.h b/include/block/block.h
index b189cf422e..580b3716c3 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -115,6 +115,7 @@ typedef struct HDGeometry {
   select an appropriate protocol driver,
   ignoring the format layer */
 #define BDRV_O_NO_IO   0x1 /* don't initialize for I/O */
+#define BDRV_O_AUTO_RDONLY 0x2 /* degrade to read-only if opening 
read-write fails */
 
 #define BDRV_O_CACHE_MASK  (BDRV_O_NOCACHE | BDRV_O_NO_FLUSH)
 
@@ -125,6 +126,7 @@ typedef struct HDGeometry {
 #define BDRV_OPT_CACHE_DIRECT   "cache.direct"
 #define BDRV_OPT_CACHE_NO_FLUSH "cache.no-flush"
 #define BDRV_OPT_READ_ONLY  "read-only"
+#define BDRV_OPT_AUTO_READ_ONLY "auto-read-only"
 #define BDRV_OPT_DISCARD"discard"
 #define BDRV_OPT_FORCE_SHARE"force-share"
 
diff --git a/block.c b/block.c
index d7bd6d29b4..ed73522cc6 100644
--- a/block.c
+++ b/block.c
@@ -930,6 +930,7 @@ static void bdrv_inherited_options(int *child_flags, QDict 
*child_options,
 
 /* Inherit the read-only option from the parent if it's not set */
 qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
+qdict_copy_default(child_options, parent_options, BDRV_OPT_AUTO_READ_ONLY);
 
 /* Our block drivers take care to send flushes and respect unmap policy,
  * so we can default to enable both on lower layers regardless of the
@@ -1053,6 +1054,7 @@ static void bdrv_backing_options(int *child

[Qemu-block] [PATCH v4 06/11] file-posix: Support auto-read-only option

2018-10-19 Thread Kevin Wolf
If read-only=off, but auto-read-only=on is given, open the file
read-write if we have the permissions, but instead of erroring out for
read-only files, just degrade to read-only.

Signed-off-by: Kevin Wolf 
Reviewed-by: Eric Blake 
---
 block/file-posix.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/block/file-posix.c b/block/file-posix.c
index 2da3a76355..0c1b81ce4b 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -527,9 +527,22 @@ static int raw_open_common(BlockDriverState *bs, QDict 
*options,
 
 s->fd = -1;
 fd = qemu_open(filename, s->open_flags, 0644);
-if (fd < 0) {
-ret = -errno;
-error_setg_errno(errp, errno, "Could not open '%s'", filename);
+ret = fd < 0 ? -errno : 0;
+
+if (ret == -EACCES || ret == -EROFS) {
+/* Try to degrade to read-only, but if it doesn't work, still use the
+ * normal error message. */
+if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
+bdrv_flags &= ~BDRV_O_RDWR;
+raw_parse_flags(bdrv_flags, &s->open_flags);
+assert(!(s->open_flags & O_CREAT));
+fd = qemu_open(filename, s->open_flags);
+ret = fd < 0 ? -errno : 0;
+}
+}
+
+if (ret < 0) {
+error_setg_errno(errp, -ret, "Could not open '%s'", filename);
 if (ret == -EROFS) {
 ret = -EACCES;
 }
-- 
2.19.1




[Qemu-block] [PATCH v4 00/11] block: Add auto-read-only option

2018-10-19 Thread Kevin Wolf
See patch 2 for an explanation of the motivation.

v4:
- Split fix for missing rbd_close() into a separate patch [Eric]
- Added qemu-iotests case

v3:
- Clarified QAPI schema documentation that auto-read-only can only
  degrade read-write to read-only, not the other way round [Eric]
- Don't refuse to set copy-on-read=on and auto-read-only=on at the same
  time; only complain when actually trying to degrade to read-only
- Let bdrv_apply_auto_read_only() return -EACCESS on all errors
- Fixed file-posix and gluster implementations [Eric, Niels]
- Added a patch to make auto-read-only=on the default for human user
  interfaces (-drive/-hda/...)

v2:
- Turn bdrv_set_read_only() into bdrv_apply_auto_read_only()
- Support the option in a lot more block drivers

Kevin Wolf (11):
  block: Update flags in bdrv_set_read_only()
  block: Add auto-read-only option
  rbd: Close image in qemu_rbd_open() error path
  block: Require auto-read-only for existing fallbacks
  nbd: Support auto-read-only option
  file-posix: Support auto-read-only option
  curl: Support auto-read-only option
  gluster: Support auto-read-only option
  iscsi: Support auto-read-only option
  block: Make auto-read-only=on default for -drive
  qemu-iotests: Test auto-read-only with -drive and -blockdev

 qapi/block-core.json   |   7 ++
 include/block/block.h  |   5 +-
 block.c|  54 +++---
 block/bochs.c  |  17 ++---
 block/cloop.c  |  16 ++--
 block/curl.c   |   8 +-
 block/dmg.c|  16 ++--
 block/file-posix.c |  19 -
 block/gluster.c|  12 ++-
 block/iscsi.c  |   8 +-
 block/nbd-client.c |  10 +--
 block/rbd.c|  14 +---
 block/vvfat.c  |  11 +--
 blockdev.c |   1 +
 tests/qemu-iotests/232 | 147 +
 tests/qemu-iotests/232.out |  59 +++
 tests/qemu-iotests/group   |   1 +
 17 files changed, 327 insertions(+), 78 deletions(-)
 create mode 100755 tests/qemu-iotests/232
 create mode 100644 tests/qemu-iotests/232.out

-- 
2.19.1




[Qemu-block] [PATCH v4 07/11] curl: Support auto-read-only option

2018-10-19 Thread Kevin Wolf
If read-only=off, but auto-read-only=on is given, just degrade to
read-only.

Signed-off-by: Kevin Wolf 
Reviewed-by: Eric Blake 
---
 block/curl.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/block/curl.c b/block/curl.c
index fabb2b4da7..db5d2bd8ef 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -684,10 +684,10 @@ static int curl_open(BlockDriverState *bs, QDict 
*options, int flags,
 const char *protocol_delimiter;
 int ret;
 
-
-if (flags & BDRV_O_RDWR) {
-error_setg(errp, "curl block device does not support writes");
-return -EROFS;
+ret = bdrv_apply_auto_read_only(bs, "curl driver does not support writes",
+errp);
+if (ret < 0) {
+return ret;
 }
 
 if (!libcurl_initialized) {
-- 
2.19.1




[Qemu-block] [PATCH v4 01/11] block: Update flags in bdrv_set_read_only()

2018-10-19 Thread Kevin Wolf
To fully change the read-only state of a node, we must not only change
bs->read_only, but also update bs->open_flags.

Signed-off-by: Kevin Wolf 
Reviewed-by: Eric Blake 
Reviewed-by: Alberto Garcia 
---
 block.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/block.c b/block.c
index 0d6e5f1a76..d7bd6d29b4 100644
--- a/block.c
+++ b/block.c
@@ -281,6 +281,13 @@ int bdrv_set_read_only(BlockDriverState *bs, bool 
read_only, Error **errp)
 }
 
 bs->read_only = read_only;
+
+if (read_only) {
+bs->open_flags &= ~BDRV_O_RDWR;
+} else {
+bs->open_flags |= BDRV_O_RDWR;
+}
+
 return 0;
 }
 
-- 
2.19.1




Re: [Qemu-block] [Qemu-devel] [PATCH 1/9] iotests: Make nbd-fault-injector flush

2018-10-19 Thread Eric Blake

On 10/19/18 4:48 AM, Max Reitz wrote:

On 16.10.18 20:07, Eric Blake wrote:

On 10/15/18 9:14 AM, Max Reitz wrote:

When closing a connection, make the nbd-fault-injector flush the socket.
Without this, the output is a bit unreliable with Python 3.

Signed-off-by: Max Reitz 
---
   tests/qemu-iotests/083.out   | 9 +
   tests/qemu-iotests/nbd-fault-injector.py | 1 +
   2 files changed, 10 insertions(+)


I already had a complaint that the error message in 083.out should NOT
be printing a message


You mean the NBD server itself, right?


Yes, the NBD server should not be printing the redundant error messages 
that 083.out exposes.





   (whether the server is python 2 and auto-flushes,
or python 3 and needs an explicit flush, the message itself is
pointless, and the test is racy as a result).  We may need to revisit
this patch when that thread is resolved.

https://lists.gnu.org/archive/html/qemu-devel/2018-08/msg01041.html


Well, it's not like the flush hurts either way. :-)


True. On that grounds:

Reviewed-by: Eric Blake 

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org



Re: [Qemu-block] [Qemu-devel] [PATCH 7/9] iotests: 'new' module replacement in 169

2018-10-19 Thread Eduardo Habkost
On Fri, Oct 19, 2018 at 11:46:59AM +0200, Max Reitz wrote:
[...]
> I mean, my personal goal is not to touch this beyond what I need to
> because it's black magic to me anyway, so I'm happy with what works.

I agree with this approach, and your original patch looks good
enough to me.

-- 
Eduardo



[Qemu-block] [PATCH v3 15/15] block: Assert that flags are up-to-date in bdrv_reopen_prepare()

2018-10-19 Thread Alberto Garcia
Towards the end of bdrv_reopen_queue_child(), before starting to
process the children, the update_flags_from_options() function is
called in order to have BDRVReopenState.flags in sync with the options
from the QDict.

This is necessary because during the reopen process flags must be
updated for all nodes in the queue so bdrv_is_writable_after_reopen()
and the permission checks work correctly.

Because of that, calling update_flags_from_options() again in
bdrv_reopen_prepare() doesn't really change the flags (they are
already up-to-date). But we need to call it in order to remove those
options from QemuOpts and that way indicate that they have been
processed.

Signed-off-by: Alberto Garcia 
---
 block.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/block.c b/block.c
index 0a0de2dc78..1d1cf3fb5f 100644
--- a/block.c
+++ b/block.c
@@ -3143,6 +3143,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, 
BlockReopenQueue *queue,
 Error **errp)
 {
 int ret = -1;
+int old_flags;
 Error *local_err = NULL;
 BlockDriver *drv;
 QemuOpts *opts;
@@ -3168,7 +3169,12 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, 
BlockReopenQueue *queue,
 goto error;
 }
 
+/* This was already called in bdrv_reopen_queue_child() so the flags
+ * are up-to-date. This time we simply want to remove the options from
+ * QemuOpts in order to indicate that they have been processed. */
+old_flags = reopen_state->flags;
 update_flags_from_options(&reopen_state->flags, opts);
+assert(old_flags == reopen_state->flags);
 
 discard = qemu_opt_get_del(opts, "discard");
 if (discard != NULL) {
-- 
2.11.0




[Qemu-block] [PATCH v3 13/15] block: Stop passing flags to bdrv_reopen_queue_child()

2018-10-19 Thread Alberto Garcia
Now that all callers are passing the new options using the QDict we no
longer need the 'flags' parameter.

This patch makes the following changes:

   1) The update_options_from_flags() call is no longer necessary
  so it can be removed.

   2) The update_flags_from_options() call is now used in all cases,
  and is moved down a few lines so it happens after the options
  QDict contains the final set of values.

   3) The flags parameter is removed. Now the flags are initialized
  using the current value (for the top-level node) or the parent
  flags (after inherit_options()). In both cases the initial
  values are updated to reflect the new options in the QDict. This
  happens in bdrv_reopen_queue_child() (as explained above) and in
  bdrv_reopen_prepare().

Signed-off-by: Alberto Garcia 
---
 block.c | 48 +++-
 1 file changed, 19 insertions(+), 29 deletions(-)

diff --git a/block.c b/block.c
index c142773358..039f03703b 100644
--- a/block.c
+++ b/block.c
@@ -2876,7 +2876,6 @@ BlockDriverState *bdrv_open(const char *filename, const 
char *reference,
 static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
  BlockDriverState *bs,
  QDict *options,
- int flags,
  const BdrvChildRole *role,
  QDict *parent_options,
  int parent_flags)
@@ -2885,7 +2884,9 @@ static BlockReopenQueue 
*bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
 
 BlockReopenQueueEntry *bs_entry;
 BdrvChild *child;
-QDict *old_options, *explicit_options;
+QDict *old_options, *explicit_options, *options_copy;
+int flags;
+QemuOpts *opts;
 
 /* Make sure that the caller remembered to use a drained section. This is
  * important to avoid graph changes between the recursive queuing here and
@@ -2911,22 +2912,11 @@ static BlockReopenQueue 
*bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
 /*
  * Precedence of options:
  * 1. Explicitly passed in options (highest)
- * 2. Set in flags (only for top level)
- * 3. Retained from explicitly set options of bs
- * 4. Inherited from parent node
- * 5. Retained from effective options of bs
+ * 2. Retained from explicitly set options of bs
+ * 3. Inherited from parent node
+ * 4. Retained from effective options of bs
  */
 
-if (!parent_options) {
-/*
- * Any setting represented by flags is always updated. If the
- * corresponding QDict option is set, it takes precedence. Otherwise
- * the flag is translated into a QDict option. The old setting of bs is
- * not considered.
- */
-update_options_from_flags(options, flags);
-}
-
 /* Old explicitly set values (don't overwrite by inherited value) */
 if (bs_entry) {
 old_options = qdict_clone_shallow(bs_entry->state.explicit_options);
@@ -2940,16 +2930,10 @@ static BlockReopenQueue 
*bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
 
 /* Inherit from parent node */
 if (parent_options) {
-QemuOpts *opts;
-QDict *options_copy;
-assert(!flags);
+flags = 0;
 role->inherit_options(&flags, options, parent_flags, parent_options);
-options_copy = qdict_clone_shallow(options);
-opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
-qemu_opts_absorb_qdict(opts, options_copy, NULL);
-update_flags_from_options(&flags, opts);
-qemu_opts_del(opts);
-qobject_unref(options_copy);
+} else {
+flags = bdrv_get_flags(bs);
 }
 
 /* Old values are used for options that aren't set yet */
@@ -2957,6 +2941,14 @@ static BlockReopenQueue 
*bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
 bdrv_join_options(bs, options, old_options);
 qobject_unref(old_options);
 
+/* We have the final set of options so let's update the flags */
+options_copy = qdict_clone_shallow(options);
+opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
+qemu_opts_absorb_qdict(opts, options_copy, NULL);
+update_flags_from_options(&flags, opts);
+qemu_opts_del(opts);
+qobject_unref(options_copy);
+
 /* bdrv_open_inherit() sets and clears some additional flags internally */
 flags &= ~BDRV_O_PROTOCOL;
 if (flags & BDRV_O_RDWR) {
@@ -2996,7 +2988,7 @@ static BlockReopenQueue 
*bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
 qdict_extract_subqdict(options, &new_child_options, child_key_dot);
 g_free(child_key_dot);
 
-bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options, 0,
+bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options,
 

[Qemu-block] [PATCH v3 00/15] Don't pass flags to bdrv_reopen_queue()

2018-10-19 Thread Alberto Garcia
Hi all,

when reopening a BlockDriverState using bdrv_reopen() and friends the
new options can be specified either with a QDict or with flags. Both
methods overlap and that makes the semantics and the implementation
unnecessarily complicated.

This series removes the 'flags' parameter from these functions, so
from now on all option changes must be specified using a QDict. Apart
from simplifying the API, a few bugs are fixed along the way. See the
individual patches for more details.

This was tested with the current master (09558375a634e17cea6cfbfec88).

Regards,

Berto

v3:
- Patch 1 [from v2] has been removed and all other patch numbers are
  shifted.
- Patches 10 and 13: Fixed rebase conflicts after the patch removal.
- Patch 14: Replacement for the removed patch using a different approach.
- Patch 15: Document a non-obvious call to update_flags_from_options()

v2: https://lists.gnu.org/archive/html/qemu-block/2018-10/msg00534.html
- Patches 4 and 9: Fixed trivial rebase conflict
- Patch 11: Update messages [Max]
- Patch 12: Add comment and use bdrv_is_read_only() instead of
using the flags directly [Max]
- Patch 14: Remove inner block and move all variable declarations to
the beginning of the function [Max]

v1: https://lists.gnu.org/archive/html/qemu-block/2018-09/msg00483.html
- Initial version

Output of backport-diff against v2:

Key:
[] : patches are identical
[] : number of functional differences between upstream/downstream patch
[down] : patch is downstream-only
The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively

001/15:[] [--] 'block: Add bdrv_reopen_set_read_only()'
002/15:[] [--] 'block: Use bdrv_reopen_set_read_only() in 
bdrv_backing_update_filename()'
003/15:[] [--] 'block: Use bdrv_reopen_set_read_only() in 
commit_start/complete()'
004/15:[] [--] 'block: Use bdrv_reopen_set_read_only() in bdrv_commit()'
005/15:[] [--] 'block: Use bdrv_reopen_set_read_only() in 
stream_start/complete()'
006/15:[] [--] 'block: Use bdrv_reopen_set_read_only() in 
qmp_change_backing_file()'
007/15:[] [--] 'block: Use bdrv_reopen_set_read_only() in 
external_snapshot_commit()'
008/15:[] [--] 'block: Use bdrv_reopen_set_read_only() in the mirror driver'
009/15:[] [--] 'block: Drop bdrv_reopen()'
010/15:[] [-C] 'qemu-io: Put flag changes in the options QDict in 
reopen_f()'
011/15:[] [--] 'block: Clean up reopen_backing_file() in 
block/replication.c'
012/15:[] [--] 'block: Remove flags parameter from bdrv_reopen_queue()'
013/15:[0022] [FC] 'block: Stop passing flags to bdrv_reopen_queue_child()'
014/15:[down] 'block: Remove assertions from update_flags_from_options()'
015/15:[down] 'block: Assert that flags are up-to-date in bdrv_reopen_prepare()'

Alberto Garcia (15):
  block: Add bdrv_reopen_set_read_only()
  block: Use bdrv_reopen_set_read_only() in
bdrv_backing_update_filename()
  block: Use bdrv_reopen_set_read_only() in commit_start/complete()
  block: Use bdrv_reopen_set_read_only() in bdrv_commit()
  block: Use bdrv_reopen_set_read_only() in stream_start/complete()
  block: Use bdrv_reopen_set_read_only() in qmp_change_backing_file()
  block: Use bdrv_reopen_set_read_only() in external_snapshot_commit()
  block: Use bdrv_reopen_set_read_only() in the mirror driver
  block: Drop bdrv_reopen()
  qemu-io: Put flag changes in the options QDict in reopen_f()
  block: Clean up reopen_backing_file() in block/replication.c
  block: Remove flags parameter from bdrv_reopen_queue()
  block: Stop passing flags to bdrv_reopen_queue_child()
  block: Remove assertions from update_flags_from_options()
  block: Assert that flags are up-to-date in bdrv_reopen_prepare()

 block.c| 88 --
 block/commit.c | 23 +---
 block/mirror.c | 19 ++
 block/replication.c| 43 ++
 block/stream.c | 20 +--
 blockdev.c | 11 ++
 include/block/block.h  |  6 ++--
 qemu-io-cmds.c | 29 +--
 tests/qemu-iotests/133 | 17 +
 tests/qemu-iotests/133.out | 14 
 10 files changed, 153 insertions(+), 117 deletions(-)

-- 
2.11.0




[Qemu-block] [PATCH v3 12/15] block: Remove flags parameter from bdrv_reopen_queue()

2018-10-19 Thread Alberto Garcia
Now that all callers are passing all flag changes as QDict options,
the flags parameter is no longer necessary, so we can get rid of it.

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
---
 block.c   | 5 +++--
 block/replication.c   | 6 ++
 include/block/block.h | 3 +--
 qemu-io-cmds.c| 2 +-
 4 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/block.c b/block.c
index edb880a66b..c142773358 100644
--- a/block.c
+++ b/block.c
@@ -3005,8 +3005,9 @@ static BlockReopenQueue 
*bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
 
 BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
 BlockDriverState *bs,
-QDict *options, int flags)
+QDict *options)
 {
+int flags = bdrv_get_flags(bs);
 return bdrv_reopen_queue_child(bs_queue, bs, options, flags,
NULL, NULL, 0);
 }
@@ -3080,7 +3081,7 @@ int bdrv_reopen_set_read_only(BlockDriverState *bs, bool 
read_only,
 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, read_only);
 
 bdrv_subtree_drained_begin(bs);
-queue = bdrv_reopen_queue(NULL, bs, opts, bdrv_get_flags(bs));
+queue = bdrv_reopen_queue(NULL, bs, opts);
 ret = bdrv_reopen_multiple(bdrv_get_aio_context(bs), queue, errp);
 bdrv_subtree_drained_end(bs);
 
diff --git a/block/replication.c b/block/replication.c
index 481a225924..fdbfe47fa4 100644
--- a/block/replication.c
+++ b/block/replication.c
@@ -393,19 +393,17 @@ static void reopen_backing_file(BlockDriverState *bs, 
bool writable,
 bdrv_subtree_drained_begin(s->secondary_disk->bs);
 
 if (s->orig_hidden_read_only) {
-int flags = bdrv_get_flags(s->hidden_disk->bs);
 QDict *opts = qdict_new();
 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable);
 reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs,
- opts, flags);
+ opts);
 }
 
 if (s->orig_secondary_read_only) {
-int flags = bdrv_get_flags(s->secondary_disk->bs);
 QDict *opts = qdict_new();
 qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable);
 reopen_queue = bdrv_reopen_queue(reopen_queue, s->secondary_disk->bs,
- opts, flags);
+ opts);
 }
 
 if (reopen_queue) {
diff --git a/include/block/block.h b/include/block/block.h
index 3649136689..38d5c1adf4 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -297,8 +297,7 @@ BlockDriverState *bdrv_open(const char *filename, const 
char *reference,
 BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
int flags, Error **errp);
 BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
-BlockDriverState *bs,
-QDict *options, int flags);
+BlockDriverState *bs, QDict *options);
 int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error 
**errp);
 int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
   Error **errp);
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index b49a816cc8..e272e5c80b 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -2075,7 +2075,7 @@ static int reopen_f(BlockBackend *blk, int argc, char 
**argv)
 }
 
 bdrv_subtree_drained_begin(bs);
-brq = bdrv_reopen_queue(NULL, bs, opts, flags);
+brq = bdrv_reopen_queue(NULL, bs, opts);
 bdrv_reopen_multiple(bdrv_get_aio_context(bs), brq, &local_err);
 bdrv_subtree_drained_end(bs);
 
-- 
2.11.0




[Qemu-block] [PATCH v3 05/15] block: Use bdrv_reopen_set_read_only() in stream_start/complete()

2018-10-19 Thread Alberto Garcia
This patch replaces the bdrv_reopen() calls that set and remove the
BDRV_O_RDWR flag with the new bdrv_reopen_set_read_only() function.

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
---
 block/stream.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/block/stream.c b/block/stream.c
index 81a7ec8ece..262d280ccd 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -34,7 +34,7 @@ typedef struct StreamBlockJob {
 BlockDriverState *base;
 BlockdevOnError on_error;
 char *backing_file_str;
-int bs_flags;
+bool bs_read_only;
 } StreamBlockJob;
 
 static int coroutine_fn stream_populate(BlockBackend *blk,
@@ -89,10 +89,10 @@ static void stream_clean(Job *job)
 BlockDriverState *bs = blk_bs(bjob->blk);
 
 /* Reopen the image back in read-only mode if necessary */
-if (s->bs_flags != bdrv_get_flags(bs)) {
+if (s->bs_read_only) {
 /* Give up write permissions before making it read-only */
 blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort);
-bdrv_reopen(bs, s->bs_flags, NULL);
+bdrv_reopen_set_read_only(bs, true, NULL);
 }
 
 g_free(s->backing_file_str);
@@ -226,12 +226,12 @@ void stream_start(const char *job_id, BlockDriverState 
*bs,
 {
 StreamBlockJob *s;
 BlockDriverState *iter;
-int orig_bs_flags;
+int bs_read_only;
 
 /* Make sure that the image is opened in read-write mode */
-orig_bs_flags = bdrv_get_flags(bs);
-if (!(orig_bs_flags & BDRV_O_RDWR)) {
-if (bdrv_reopen(bs, orig_bs_flags | BDRV_O_RDWR, errp) != 0) {
+bs_read_only = bdrv_is_read_only(bs);
+if (bs_read_only) {
+if (bdrv_reopen_set_read_only(bs, false, errp) != 0) {
 return;
 }
 }
@@ -261,7 +261,7 @@ void stream_start(const char *job_id, BlockDriverState *bs,
 
 s->base = base;
 s->backing_file_str = g_strdup(backing_file_str);
-s->bs_flags = orig_bs_flags;
+s->bs_read_only = bs_read_only;
 
 s->on_error = on_error;
 trace_stream_start(bs, base, s);
@@ -269,7 +269,7 @@ void stream_start(const char *job_id, BlockDriverState *bs,
 return;
 
 fail:
-if (orig_bs_flags != bdrv_get_flags(bs)) {
-bdrv_reopen(bs, orig_bs_flags, NULL);
+if (bs_read_only) {
+bdrv_reopen_set_read_only(bs, true, NULL);
 }
 }
-- 
2.11.0




[Qemu-block] [PATCH v3 10/15] qemu-io: Put flag changes in the options QDict in reopen_f()

2018-10-19 Thread Alberto Garcia
When reopen_f() puts a block device in the reopen queue, some of the
new options are passed using a QDict, but others ("read-only" and the
cache options) are passed as flags.

This patch puts those flags in the QDict. This way the flags parameter
becomes redundant and we'll be able to get rid of it in a subsequent
patch.

Signed-off-by: Alberto Garcia 
---
 qemu-io-cmds.c | 27 ++-
 tests/qemu-iotests/133 |  9 +
 tests/qemu-iotests/133.out |  8 
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index db0b3ee5ef..b49a816cc8 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -10,6 +10,7 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
 #include "qemu-io.h"
 #include "sysemu/block-backend.h"
 #include "block/block.h"
@@ -1978,6 +1979,7 @@ static int reopen_f(BlockBackend *blk, int argc, char 
**argv)
 int flags = bs->open_flags;
 bool writethrough = !blk_enable_write_cache(blk);
 bool has_rw_option = false;
+bool has_cache_option = false;
 
 BlockReopenQueue *brq;
 Error *local_err = NULL;
@@ -1989,6 +1991,7 @@ static int reopen_f(BlockBackend *blk, int argc, char 
**argv)
 error_report("Invalid cache option: %s", optarg);
 return -EINVAL;
 }
+has_cache_option = true;
 break;
 case 'o':
 if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
@@ -2046,9 +2049,31 @@ static int reopen_f(BlockBackend *blk, int argc, char 
**argv)
 }
 
 qopts = qemu_opts_find(&reopen_opts, NULL);
-opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : NULL;
+opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
 qemu_opts_reset(&reopen_opts);
 
+if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
+if (has_rw_option) {
+error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
+qobject_unref(opts);
+return -EINVAL;
+}
+} else {
+qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
+}
+
+if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
+qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
+if (has_cache_option) {
+error_report("Cannot set both -c and the cache options");
+qobject_unref(opts);
+return -EINVAL;
+}
+} else {
+qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
+qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
+}
+
 bdrv_subtree_drained_begin(bs);
 brq = bdrv_reopen_queue(NULL, bs, opts, flags);
 bdrv_reopen_multiple(bdrv_get_aio_context(bs), brq, &local_err);
diff --git a/tests/qemu-iotests/133 b/tests/qemu-iotests/133
index af6b3e1dd4..14e6b3b972 100755
--- a/tests/qemu-iotests/133
+++ b/tests/qemu-iotests/133
@@ -92,6 +92,15 @@ echo
 IMGOPTSSYNTAX=false $QEMU_IO -f null-co -c 'reopen' -c 'info' \
 "json:{'driver': 'null-co', 'size': 65536}"
 
+echo
+echo "=== Check that mixing -c/-r/-w and their corresponding options is 
forbidden ==="
+echo
+
+$QEMU_IO -c 'reopen -r -o read-only=on' $TEST_IMG
+$QEMU_IO -c 'reopen -w -o read-only=on' $TEST_IMG
+$QEMU_IO -c 'reopen -c none -o cache.direct=on' $TEST_IMG
+$QEMU_IO -c 'reopen -c writeback -o cache.direct=on' $TEST_IMG
+$QEMU_IO -c 'reopen -c directsync -o cache.no-flush=on' $TEST_IMG
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/133.out b/tests/qemu-iotests/133.out
index f4a85aeb63..48a9d087f0 100644
--- a/tests/qemu-iotests/133.out
+++ b/tests/qemu-iotests/133.out
@@ -24,4 +24,12 @@ Cannot change the option 'driver'
 
 format name: null-co
 format name: null-co
+
+=== Check that mixing -c/-r/-w and their corresponding options is forbidden ===
+
+Cannot set both -r/-w and 'read-only'
+Cannot set both -r/-w and 'read-only'
+Cannot set both -c and the cache options
+Cannot set both -c and the cache options
+Cannot set both -c and the cache options
 *** done
-- 
2.11.0




[Qemu-block] [PATCH v3 06/15] block: Use bdrv_reopen_set_read_only() in qmp_change_backing_file()

2018-10-19 Thread Alberto Garcia
This patch replaces the bdrv_reopen() calls that set and remove the
BDRV_O_RDWR flag with the new bdrv_reopen_set_read_only() function.

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
---
 blockdev.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index a8755bd908..f64569795c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -4064,7 +4064,6 @@ void qmp_change_backing_file(const char *device,
 BlockDriverState *image_bs = NULL;
 Error *local_err = NULL;
 bool ro;
-int open_flags;
 int ret;
 
 bs = qmp_get_root_bs(device, errp);
@@ -4106,13 +4105,10 @@ void qmp_change_backing_file(const char *device,
 }
 
 /* if not r/w, reopen to make r/w */
-open_flags = image_bs->open_flags;
 ro = bdrv_is_read_only(image_bs);
 
 if (ro) {
-bdrv_reopen(image_bs, open_flags | BDRV_O_RDWR, &local_err);
-if (local_err) {
-error_propagate(errp, local_err);
+if (bdrv_reopen_set_read_only(image_bs, false, errp) != 0) {
 goto out;
 }
 }
@@ -4128,7 +4124,7 @@ void qmp_change_backing_file(const char *device,
 }
 
 if (ro) {
-bdrv_reopen(image_bs, open_flags, &local_err);
+bdrv_reopen_set_read_only(image_bs, true, &local_err);
 error_propagate(errp, local_err);
 }
 
-- 
2.11.0




[Qemu-block] [PATCH v3 11/15] block: Clean up reopen_backing_file() in block/replication.c

2018-10-19 Thread Alberto Garcia
This function is used to put the hidden and secondary disks in
read-write mode before launching the backup job, and back in read-only
mode afterwards.

This patch does the following changes:

  - Use an options QDict with the "read-only" option instead of
passing the changes as flags only.

  - Simplify the code (it was unnecessarily complicated and verbose).

  - Fix a bug due to which the secondary disk was not being put back
in read-only mode when writable=false (because in this case
orig_secondary_flags always had the BDRV_O_RDWR flag set).

  - Stop clearing the BDRV_O_INACTIVE flag.

The flags parameter to bdrv_reopen_queue() becomes redundant and we'll
be able to get rid of it in a subsequent patch.

Signed-off-by: Alberto Garcia 
---
 block/replication.c | 45 +
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/block/replication.c b/block/replication.c
index 6349d6958e..481a225924 100644
--- a/block/replication.c
+++ b/block/replication.c
@@ -20,6 +20,7 @@
 #include "block/block_backup.h"
 #include "sysemu/block-backend.h"
 #include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
 #include "replication.h"
 
 typedef enum {
@@ -39,8 +40,8 @@ typedef struct BDRVReplicationState {
 char *top_id;
 ReplicationState *rs;
 Error *blocker;
-int orig_hidden_flags;
-int orig_secondary_flags;
+bool orig_hidden_read_only;
+bool orig_secondary_read_only;
 int error;
 } BDRVReplicationState;
 
@@ -371,44 +372,40 @@ static void secondary_do_checkpoint(BDRVReplicationState 
*s, Error **errp)
 }
 }
 
+/* This function is supposed to be called twice:
+ * first with writable = true, then with writable = false.
+ * The first call puts s->hidden_disk and s->secondary_disk in
+ * r/w mode, and the second puts them back in their original state.
+ */
 static void reopen_backing_file(BlockDriverState *bs, bool writable,
 Error **errp)
 {
 BDRVReplicationState *s = bs->opaque;
 BlockReopenQueue *reopen_queue = NULL;
-int orig_hidden_flags, orig_secondary_flags;
-int new_hidden_flags, new_secondary_flags;
 Error *local_err = NULL;
 
 if (writable) {
-orig_hidden_flags = s->orig_hidden_flags =
-bdrv_get_flags(s->hidden_disk->bs);
-new_hidden_flags = (orig_hidden_flags | BDRV_O_RDWR) &
-~BDRV_O_INACTIVE;
-orig_secondary_flags = s->orig_secondary_flags =
-bdrv_get_flags(s->secondary_disk->bs);
-new_secondary_flags = (orig_secondary_flags | BDRV_O_RDWR) &
- ~BDRV_O_INACTIVE;
-} else {
-orig_hidden_flags = (s->orig_hidden_flags | BDRV_O_RDWR) &
-~BDRV_O_INACTIVE;
-new_hidden_flags = s->orig_hidden_flags;
-orig_secondary_flags = (s->orig_secondary_flags | BDRV_O_RDWR) &
-~BDRV_O_INACTIVE;
-new_secondary_flags = s->orig_secondary_flags;
+s->orig_hidden_read_only = bdrv_is_read_only(s->hidden_disk->bs);
+s->orig_secondary_read_only = bdrv_is_read_only(s->secondary_disk->bs);
 }
 
 bdrv_subtree_drained_begin(s->hidden_disk->bs);
 bdrv_subtree_drained_begin(s->secondary_disk->bs);
 
-if (orig_hidden_flags != new_hidden_flags) {
-reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs, 
NULL,
- new_hidden_flags);
+if (s->orig_hidden_read_only) {
+int flags = bdrv_get_flags(s->hidden_disk->bs);
+QDict *opts = qdict_new();
+qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable);
+reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs,
+ opts, flags);
 }
 
-if (!(orig_secondary_flags & BDRV_O_RDWR)) {
+if (s->orig_secondary_read_only) {
+int flags = bdrv_get_flags(s->secondary_disk->bs);
+QDict *opts = qdict_new();
+qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable);
 reopen_queue = bdrv_reopen_queue(reopen_queue, s->secondary_disk->bs,
- NULL, new_secondary_flags);
+ opts, flags);
 }
 
 if (reopen_queue) {
-- 
2.11.0




[Qemu-block] [PATCH v3 07/15] block: Use bdrv_reopen_set_read_only() in external_snapshot_commit()

2018-10-19 Thread Alberto Garcia
This patch replaces the bdrv_reopen() call that set and remove the
BDRV_O_RDWR flag with the new bdrv_reopen_set_read_only() function.

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
---
 blockdev.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index f64569795c..7a57572e1a 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1701,8 +1701,7 @@ static void external_snapshot_commit(BlkActionState 
*common)
  * bdrv_reopen_multiple() across all the entries at once, because we
  * don't want to abort all of them if one of them fails the reopen */
 if (!atomic_read(&state->old_bs->copy_on_read)) {
-bdrv_reopen(state->old_bs, state->old_bs->open_flags & ~BDRV_O_RDWR,
-NULL);
+bdrv_reopen_set_read_only(state->old_bs, true, NULL);
 }
 
 aio_context_release(aio_context);
-- 
2.11.0




[Qemu-block] [PATCH v3 14/15] block: Remove assertions from update_flags_from_options()

2018-10-19 Thread Alberto Garcia
This function takes three options (cache.direct, cache.no-flush and
read-only) from a QemuOpts object and updates the flags accordingly.

If any of those options is not set (because it was missing from the
original QDict or because it had an invalid value) then the function
aborts with a failed assertion:

   $ qemu-io -c 'reopen -o read-only=foo' hd.qcow2
   block.c:1126: update_flags_from_options: Assertion `qemu_opt_find(opts, 
BDRV_OPT_CACHE_DIRECT)' failed.
   Aborted

This assertion is unnecessary, and it forces any caller of
bdrv_reopen() to pass all the aforementioned three options. This may
have made sense in order to remove ambiguity when bdrv_reopen() was
taking both flags and options, but that's not the case anymore.

It's also unnecessary if we want to validate the option values,
because bdrv_reopen_prepare() already takes care of that, as we can
see if we remove the assertions:

   $ qemu-io -c 'reopen -o read-only=foo' hd.qcow2
   Parameter 'read-only' expects 'on' or 'off'

Signed-off-by: Alberto Garcia 
---
 block.c| 3 ---
 tests/qemu-iotests/133 | 8 
 tests/qemu-iotests/133.out | 6 ++
 3 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/block.c b/block.c
index 039f03703b..0a0de2dc78 100644
--- a/block.c
+++ b/block.c
@@ -1118,19 +1118,16 @@ static void update_flags_from_options(int *flags, 
QemuOpts *opts)
 {
 *flags &= ~BDRV_O_CACHE_MASK;
 
-assert(qemu_opt_find(opts, BDRV_OPT_CACHE_NO_FLUSH));
 if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) {
 *flags |= BDRV_O_NO_FLUSH;
 }
 
-assert(qemu_opt_find(opts, BDRV_OPT_CACHE_DIRECT));
 if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_DIRECT, false)) {
 *flags |= BDRV_O_NOCACHE;
 }
 
 *flags &= ~BDRV_O_RDWR;
 
-assert(qemu_opt_find(opts, BDRV_OPT_READ_ONLY));
 if (!qemu_opt_get_bool_del(opts, BDRV_OPT_READ_ONLY, false)) {
 *flags |= BDRV_O_RDWR;
 }
diff --git a/tests/qemu-iotests/133 b/tests/qemu-iotests/133
index 14e6b3b972..59d5e2ea25 100755
--- a/tests/qemu-iotests/133
+++ b/tests/qemu-iotests/133
@@ -101,6 +101,14 @@ $QEMU_IO -c 'reopen -w -o read-only=on' $TEST_IMG
 $QEMU_IO -c 'reopen -c none -o cache.direct=on' $TEST_IMG
 $QEMU_IO -c 'reopen -c writeback -o cache.direct=on' $TEST_IMG
 $QEMU_IO -c 'reopen -c directsync -o cache.no-flush=on' $TEST_IMG
+
+echo
+echo "=== Check that invalid options are handled correctly ==="
+echo
+
+$QEMU_IO -c 'reopen -o read-only=foo' $TEST_IMG
+$QEMU_IO -c 'reopen -o cache.no-flush=bar' $TEST_IMG
+$QEMU_IO -c 'reopen -o cache.direct=baz' $TEST_IMG
 # success, all done
 echo "*** done"
 rm -f $seq.full
diff --git a/tests/qemu-iotests/133.out b/tests/qemu-iotests/133.out
index 48a9d087f0..551096a9c4 100644
--- a/tests/qemu-iotests/133.out
+++ b/tests/qemu-iotests/133.out
@@ -32,4 +32,10 @@ Cannot set both -r/-w and 'read-only'
 Cannot set both -c and the cache options
 Cannot set both -c and the cache options
 Cannot set both -c and the cache options
+
+=== Check that invalid options are handled correctly ===
+
+Parameter 'read-only' expects 'on' or 'off'
+Parameter 'cache.no-flush' expects 'on' or 'off'
+Parameter 'cache.direct' expects 'on' or 'off'
 *** done
-- 
2.11.0




[Qemu-block] [PATCH v3 04/15] block: Use bdrv_reopen_set_read_only() in bdrv_commit()

2018-10-19 Thread Alberto Garcia
This patch replaces the bdrv_reopen() calls that set and remove the
BDRV_O_RDWR flag with the new bdrv_reopen_set_read_only() function.

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
---
 block/commit.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/block/commit.c b/block/commit.c
index a53c2d04b0..53148e610b 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -391,7 +391,7 @@ int bdrv_commit(BlockDriverState *bs)
 BlockDriverState *commit_top_bs = NULL;
 BlockDriver *drv = bs->drv;
 int64_t offset, length, backing_length;
-int ro, open_flags;
+int ro;
 int64_t n;
 int ret = 0;
 uint8_t *buf = NULL;
@@ -410,10 +410,9 @@ int bdrv_commit(BlockDriverState *bs)
 }
 
 ro = bs->backing->bs->read_only;
-open_flags =  bs->backing->bs->open_flags;
 
 if (ro) {
-if (bdrv_reopen(bs->backing->bs, open_flags | BDRV_O_RDWR, NULL)) {
+if (bdrv_reopen_set_read_only(bs->backing->bs, false, NULL)) {
 return -EACCES;
 }
 }
@@ -523,7 +522,7 @@ ro_cleanup:
 
 if (ro) {
 /* ignoring error return here */
-bdrv_reopen(bs->backing->bs, open_flags & ~BDRV_O_RDWR, NULL);
+bdrv_reopen_set_read_only(bs->backing->bs, true, NULL);
 }
 
 return ret;
-- 
2.11.0




[Qemu-block] [PATCH v3 03/15] block: Use bdrv_reopen_set_read_only() in commit_start/complete()

2018-10-19 Thread Alberto Garcia
This patch replaces the bdrv_reopen() calls that set and remove the
BDRV_O_RDWR flag with the new bdrv_reopen_set_read_only() function.

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
---
 block/commit.c | 16 ++--
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/block/commit.c b/block/commit.c
index a2da5740b0..a53c2d04b0 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -38,7 +38,7 @@ typedef struct CommitBlockJob {
 BlockBackend *base;
 BlockDriverState *base_bs;
 BlockdevOnError on_error;
-int base_flags;
+bool base_read_only;
 char *backing_file_str;
 } CommitBlockJob;
 
@@ -124,8 +124,8 @@ static void commit_clean(Job *job)
 /* restore base open flags here if appropriate (e.g., change the base back
  * to r/o). These reopens do not need to be atomic, since we won't abort
  * even on failure here */
-if (s->base_flags != bdrv_get_flags(s->base_bs)) {
-bdrv_reopen(s->base_bs, s->base_flags, NULL);
+if (s->base_read_only) {
+bdrv_reopen_set_read_only(s->base_bs, true, NULL);
 }
 
 g_free(s->backing_file_str);
@@ -264,7 +264,6 @@ void commit_start(const char *job_id, BlockDriverState *bs,
   const char *filter_node_name, Error **errp)
 {
 CommitBlockJob *s;
-int orig_base_flags;
 BlockDriverState *iter;
 BlockDriverState *commit_top_bs = NULL;
 Error *local_err = NULL;
@@ -283,11 +282,9 @@ void commit_start(const char *job_id, BlockDriverState *bs,
 }
 
 /* convert base to r/w, if necessary */
-orig_base_flags = bdrv_get_flags(base);
-if (!(orig_base_flags & BDRV_O_RDWR)) {
-bdrv_reopen(base, orig_base_flags | BDRV_O_RDWR, &local_err);
-if (local_err != NULL) {
-error_propagate(errp, local_err);
+s->base_read_only = bdrv_is_read_only(base);
+if (s->base_read_only) {
+if (bdrv_reopen_set_read_only(base, false, errp) != 0) {
 goto fail;
 }
 }
@@ -363,7 +360,6 @@ void commit_start(const char *job_id, BlockDriverState *bs,
 goto fail;
 }
 
-s->base_flags = orig_base_flags;
 s->backing_file_str = g_strdup(backing_file_str);
 s->on_error = on_error;
 
-- 
2.11.0




[Qemu-block] [PATCH v3 08/15] block: Use bdrv_reopen_set_read_only() in the mirror driver

2018-10-19 Thread Alberto Garcia
The 'block-commit' QMP command is implemented internally using two
different drivers. If the source image is the active layer then the
mirror driver is used (commit_active_start()), otherwise the commit
driver is used (commit_start()).

In both cases the destination image must be put temporarily in
read-write mode. This is done correctly in the latter case, but what
commit_active_start() does is copy all flags instead.

This patch replaces the bdrv_reopen() calls in that function with
bdrv_reopen_set_read_only() so that only the read-only status is
changed.

A similar change is made in mirror_exit(), which is also used by the
'drive-mirror' and 'blockdev-mirror' commands.

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
---
 block/mirror.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index 56d9ef7474..41b6cbaad6 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -672,9 +672,10 @@ static int mirror_exit_common(Job *job)
 
 if (s->should_complete && !abort) {
 BlockDriverState *to_replace = s->to_replace ?: src;
+bool ro = bdrv_is_read_only(to_replace);
 
-if (bdrv_get_flags(target_bs) != bdrv_get_flags(to_replace)) {
-bdrv_reopen(target_bs, bdrv_get_flags(to_replace), NULL);
+if (ro != bdrv_is_read_only(target_bs)) {
+bdrv_reopen_set_read_only(target_bs, ro, NULL);
 }
 
 /* The mirror job has no requests in flight any more, but we need to
@@ -1692,13 +1693,15 @@ void commit_active_start(const char *job_id, 
BlockDriverState *bs,
  BlockCompletionFunc *cb, void *opaque,
  bool auto_complete, Error **errp)
 {
-int orig_base_flags;
+bool base_read_only;
 Error *local_err = NULL;
 
-orig_base_flags = bdrv_get_flags(base);
+base_read_only = bdrv_is_read_only(base);
 
-if (bdrv_reopen(base, bs->open_flags, errp)) {
-return;
+if (base_read_only) {
+if (bdrv_reopen_set_read_only(base, false, errp) < 0) {
+return;
+}
 }
 
 mirror_start_job(job_id, bs, creation_flags, base, NULL, speed, 0, 0,
@@ -1717,6 +1720,8 @@ void commit_active_start(const char *job_id, 
BlockDriverState *bs,
 error_restore_flags:
 /* ignore error and errp for bdrv_reopen, because we want to propagate
  * the original error */
-bdrv_reopen(base, orig_base_flags, NULL);
+if (base_read_only) {
+bdrv_reopen_set_read_only(base, true, NULL);
+}
 return;
 }
-- 
2.11.0




[Qemu-block] [PATCH v3 02/15] block: Use bdrv_reopen_set_read_only() in bdrv_backing_update_filename()

2018-10-19 Thread Alberto Garcia
This patch replaces the bdrv_reopen() calls that set and remove the
BDRV_O_RDWR flag with the new bdrv_reopen_set_read_only() function.

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
---
 block.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/block.c b/block.c
index d09019d9c9..744509f683 100644
--- a/block.c
+++ b/block.c
@@ -1058,11 +1058,11 @@ static int bdrv_backing_update_filename(BdrvChild *c, 
BlockDriverState *base,
 const char *filename, Error **errp)
 {
 BlockDriverState *parent = c->opaque;
-int orig_flags = bdrv_get_flags(parent);
+bool read_only = bdrv_is_read_only(parent);
 int ret;
 
-if (!(orig_flags & BDRV_O_RDWR)) {
-ret = bdrv_reopen(parent, orig_flags | BDRV_O_RDWR, errp);
+if (read_only) {
+ret = bdrv_reopen_set_read_only(parent, false, errp);
 if (ret < 0) {
 return ret;
 }
@@ -1074,8 +1074,8 @@ static int bdrv_backing_update_filename(BdrvChild *c, 
BlockDriverState *base,
 error_setg_errno(errp, -ret, "Could not update backing file link");
 }
 
-if (!(orig_flags & BDRV_O_RDWR)) {
-bdrv_reopen(parent, orig_flags, NULL);
+if (read_only) {
+bdrv_reopen_set_read_only(parent, true, NULL);
 }
 
 return ret;
-- 
2.11.0




[Qemu-block] [PATCH v3 09/15] block: Drop bdrv_reopen()

2018-10-19 Thread Alberto Garcia
No one is using this function anymore, so we can safely remove it.

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
---
 block.c   | 21 -
 include/block/block.h |  1 -
 2 files changed, 22 deletions(-)

diff --git a/block.c b/block.c
index 744509f683..edb880a66b 100644
--- a/block.c
+++ b/block.c
@@ -3070,27 +3070,6 @@ cleanup:
 return ret;
 }
 
-
-/* Reopen a single BlockDriverState with the specified flags. */
-int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp)
-{
-int ret = -1;
-Error *local_err = NULL;
-BlockReopenQueue *queue;
-
-bdrv_subtree_drained_begin(bs);
-
-queue = bdrv_reopen_queue(NULL, bs, NULL, bdrv_flags);
-ret = bdrv_reopen_multiple(bdrv_get_aio_context(bs), queue, &local_err);
-if (local_err != NULL) {
-error_propagate(errp, local_err);
-}
-
-bdrv_subtree_drained_end(bs);
-
-return ret;
-}
-
 int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
   Error **errp)
 {
diff --git a/include/block/block.h b/include/block/block.h
index 97317fdfb6..3649136689 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -300,7 +300,6 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue 
*bs_queue,
 BlockDriverState *bs,
 QDict *options, int flags);
 int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error 
**errp);
-int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp);
 int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
   Error **errp);
 int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
-- 
2.11.0




[Qemu-block] [PATCH v3 01/15] block: Add bdrv_reopen_set_read_only()

2018-10-19 Thread Alberto Garcia
Most callers of bdrv_reopen() only use it to switch a BlockDriverState
between read-only and read-write, so this patch adds a new function
that does just that.

We also want to get rid of the flags parameter in the bdrv_reopen()
API, so this function sets the "read-only" option and passes the
original flags (which will then be updated in bdrv_reopen_prepare()).

Signed-off-by: Alberto Garcia 
Reviewed-by: Max Reitz 
---
 block.c   | 17 +
 include/block/block.h |  2 ++
 2 files changed, 19 insertions(+)

diff --git a/block.c b/block.c
index 7710b399a3..d09019d9c9 100644
--- a/block.c
+++ b/block.c
@@ -3091,6 +3091,23 @@ int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, 
Error **errp)
 return ret;
 }
 
+int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
+  Error **errp)
+{
+int ret;
+BlockReopenQueue *queue;
+QDict *opts = qdict_new();
+
+qdict_put_bool(opts, BDRV_OPT_READ_ONLY, read_only);
+
+bdrv_subtree_drained_begin(bs);
+queue = bdrv_reopen_queue(NULL, bs, opts, bdrv_get_flags(bs));
+ret = bdrv_reopen_multiple(bdrv_get_aio_context(bs), queue, errp);
+bdrv_subtree_drained_end(bs);
+
+return ret;
+}
+
 static BlockReopenQueueEntry *find_parent_in_reopen_queue(BlockReopenQueue *q,
   BdrvChild *c)
 {
diff --git a/include/block/block.h b/include/block/block.h
index b189cf422e..97317fdfb6 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -301,6 +301,8 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue 
*bs_queue,
 QDict *options, int flags);
 int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error 
**errp);
 int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp);
+int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
+  Error **errp);
 int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
 BlockReopenQueue *queue, Error **errp);
 void bdrv_reopen_commit(BDRVReopenState *reopen_state);
-- 
2.11.0




Re: [Qemu-block] [Qemu-devel] [PATCH] block: drop moderated sheepdog mailing list from MAINTAINERS file

2018-10-19 Thread Philippe Mathieu-Daudé
On 19/10/2018 13:25, Daniel P. Berrangé wrote:
> Paolo, I think this is a patch for your misc patches queue.

It looks to me than this is more block/trivial than the busy misc queue.

> 
> On Wed, Mar 21, 2018 at 03:31:24PM +, Daniel P. Berrangé wrote:
>> The sheepdog mailing list is setup to stop and queue messages from
>> non-subscribers, pending moderator approval. Unfortunately it seems
>> that the moderation queue is not actively dealt with. Even when messages
>> are approved, the sender is never added to the whitelist, so every
>> future mail the same sender continues to get stopped for moderation.
>>
>> MAINTAINERS entries should be responsive and not uneccessarily block
>> mails from QEMU contributors, so drop the sheepdog mailing list.
>>
>> Signed-off-by: Daniel P. Berrangé 
>> ---
>>  MAINTAINERS | 1 -
>>  1 file changed, 1 deletion(-)
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 354a18ce49..7eea869dcd 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -1871,7 +1871,6 @@ M: Hitoshi Mitake 
>>  M: Liu Yuan 
>>  M: Jeff Cody 
>>  L: qemu-block@nongnu.org
>> -L: sheep...@lists.wpkg.org
>>  S: Supported
>>  F: block/sheepdog.c
>>  T: git git://github.com/codyprime/qemu-kvm-jtc.git block
>> -- 
>> 2.14.3
>>
> 
> Regards,
> Daniel
> 



[Qemu-block] [PATCH] block: Make more block drivers compile-time configurable

2018-10-19 Thread Markus Armbruster
From: Jeff Cody 

This adds configure options to control the following block drivers:

* Bochs
* Cloop
* Dmg
* Qcow (V1)
* Vdi
* Vvfat
* qed
* parallels
* sheepdog

Each of these defaults to being enabled.

Signed-off-by: Jeff Cody 
Signed-off-by: Markus Armbruster 
---

Hmm, we got quite a few --enable-BLOCK-DRIVER now.  Perhaps a single
list-valued option similar --target-list would be better.  Could be
done on top.

 block/Makefile.objs | 22 ---
 configure   | 91 +
 2 files changed, 107 insertions(+), 6 deletions(-)

diff --git a/block/Makefile.objs b/block/Makefile.objs
index c8337bf186..1cad9fc4f1 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -1,10 +1,18 @@
-block-obj-y += raw-format.o qcow.o vdi.o vmdk.o cloop.o bochs.o vpc.o vvfat.o 
dmg.o
+block-obj-y += raw-format.o vmdk.o vpc.o
+block-obj-$(CONFIG_QCOW1) += qcow.o
+block-obj-$(CONFIG_VDI) += vdi.o
+block-obj-$(CONFIG_CLOOP) += cloop.o
+block-obj-$(CONFIG_BOCHS) += bochs.o
+block-obj-$(CONFIG_VVFAT) += vvfat.o
+block-obj-$(CONFIG_DMG) += dmg.o
+
 block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o 
qcow2-cache.o qcow2-bitmap.o
-block-obj-y += qed.o qed-l2-cache.o qed-table.o qed-cluster.o
-block-obj-y += qed-check.o
+block-obj-$(CONFIG_QED) += qed.o qed-l2-cache.o qed-table.o qed-cluster.o
+block-obj-$(CONFIG_QED) += qed-check.o
 block-obj-y += vhdx.o vhdx-endian.o vhdx-log.o
 block-obj-y += quorum.o
-block-obj-y += parallels.o blkdebug.o blkverify.o blkreplay.o
+block-obj-y += blkdebug.o blkverify.o blkreplay.o
+block-obj-$(CONFIG_PARALLELS) += parallels.o
 block-obj-y += blklogwrites.o
 block-obj-y += block-backend.o snapshot.o qapi.o
 block-obj-$(CONFIG_WIN32) += file-win32.o win32-aio.o
@@ -14,7 +22,8 @@ block-obj-y += null.o mirror.o commit.o io.o create.o
 block-obj-y += throttle-groups.o
 block-obj-$(CONFIG_LINUX) += nvme.o
 
-block-obj-y += nbd.o nbd-client.o sheepdog.o
+block-obj-y += nbd.o nbd-client.o
+block-obj-$(CONFIG_SHEEPDOG) += sheepdog.o
 block-obj-$(CONFIG_LIBISCSI) += iscsi.o
 block-obj-$(if $(CONFIG_LIBISCSI),y,n) += iscsi-opts.o
 block-obj-$(CONFIG_LIBNFS) += nfs.o
@@ -45,7 +54,8 @@ gluster.o-libs := $(GLUSTERFS_LIBS)
 vxhs.o-libs:= $(VXHS_LIBS)
 ssh.o-cflags   := $(LIBSSH2_CFLAGS)
 ssh.o-libs := $(LIBSSH2_LIBS)
-block-obj-$(if $(CONFIG_BZIP2),m,n) += dmg-bz2.o
+block-obj-dmg-bz2$(if $(CONFIG_BZIP2),m,n) += dmg-bz2.o
+block-obj-$(CONFIG_DMG) += $(block-obj-dmg-bz2-y)
 dmg-bz2.o-libs := $(BZIP2_LIBS)
 qcow.o-libs:= -lz
 linux-aio.o-libs   := -laio
diff --git a/configure b/configure
index 9138af37f8..c413186c67 100755
--- a/configure
+++ b/configure
@@ -473,6 +473,15 @@ tcmalloc="no"
 jemalloc="no"
 replication="yes"
 vxhs=""
+bochs="yes"
+cloop="yes"
+dmg="yes"
+qcow1="yes"
+vdi="yes"
+vvfat="yes"
+qed="yes"
+parallels="yes"
+sheepdog="yes"
 libxml2=""
 docker="no"
 debug_mutex="no"
@@ -1413,6 +1422,42 @@ for opt do
   ;;
   --enable-vxhs) vxhs="yes"
   ;;
+  --disable-bochs) bochs="no"
+  ;;
+  --enable-bochs) bochs="yes"
+  ;;
+  --disable-cloop) cloop="no"
+  ;;
+  --enable-cloop) cloop="yes"
+  ;;
+  --disable-dmg) dmg="no"
+  ;;
+  --enable-dmg) dmg="yes"
+  ;;
+  --disable-qcow1) qcow1="no"
+  ;;
+  --enable-qcow1) qcow1="yes"
+  ;;
+  --disable-vdi) vdi="no"
+  ;;
+  --enable-vdi) vdi="yes"
+  ;;
+  --disable-vvfat) vvfat="no"
+  ;;
+  --enable-vvfat) vvfat="yes"
+  ;;
+  --disable-qed) qed="no"
+  ;;
+  --enable-qed) qed="yes"
+  ;;
+  --disable-parallels) parallels="no"
+  ;;
+  --enable-parallels) parallels="yes"
+  ;;
+  --disable-sheepdog) sheepdog="no"
+  ;;
+  --enable-sheepdog) sheepdog="yes"
+  ;;
   --disable-vhost-user) vhost_user="no"
   ;;
   --enable-vhost-user)
@@ -1714,6 +1759,15 @@ disabled with --disable-FEATURE, default is enabled if 
available:
   qom-cast-debug  cast debugging support
   tools   build qemu-io, qemu-nbd and qemu-image tools
   vxhsVeritas HyperScale vDisk backend support
+  bochs   bochs image format support
+  cloop   cloop image format support
+  dmg dmg image format support
+  qcow1   qcow v1 image format support
+  vdi vdi image format support
+  vvfat   vvfat image format support
+  qed qed image format support
+  parallels   parallels image format support
+  sheepdogsheepdog block driver support
   crypto-afalgLinux AF_ALG crypto backend driver
   vhost-user  vhost-user support
   capstonecapstone disassembler support
@@ -6067,6 +6121,15 @@ echo "jemalloc support  $jemalloc"
 echo "avx2 optimization $avx2_opt"
 echo "replication support $replication"
 echo "VxHS block device $vxhs"
+echo "bochs support $bochs"
+echo "cloop support $cloop"
+echo "dmg support   $dmg"
+echo "qcow v1 support   $qcow1"
+echo "vdi support   $vdi"
+echo "vvfat support $vvfat"
+echo "qed support   $qed"
+echo "parallels support $paral

Re: [Qemu-block] [PATCH] block: drop moderated sheepdog mailing list from MAINTAINERS file

2018-10-19 Thread Daniel P . Berrangé
Paolo, I think this is a patch for your misc patches queue.

On Wed, Mar 21, 2018 at 03:31:24PM +, Daniel P. Berrangé wrote:
> The sheepdog mailing list is setup to stop and queue messages from
> non-subscribers, pending moderator approval. Unfortunately it seems
> that the moderation queue is not actively dealt with. Even when messages
> are approved, the sender is never added to the whitelist, so every
> future mail the same sender continues to get stopped for moderation.
> 
> MAINTAINERS entries should be responsive and not uneccessarily block
> mails from QEMU contributors, so drop the sheepdog mailing list.
> 
> Signed-off-by: Daniel P. Berrangé 
> ---
>  MAINTAINERS | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 354a18ce49..7eea869dcd 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1871,7 +1871,6 @@ M: Hitoshi Mitake 
>  M: Liu Yuan 
>  M: Jeff Cody 
>  L: qemu-block@nongnu.org
> -L: sheep...@lists.wpkg.org
>  S: Supported
>  F: block/sheepdog.c
>  T: git git://github.com/codyprime/qemu-kvm-jtc.git block
> -- 
> 2.14.3
> 

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|



Re: [Qemu-block] [Qemu-devel] [PATCH 1/5] option: Make option help nicer to read

2018-10-19 Thread Max Reitz
On 17.10.18 08:50, Markus Armbruster wrote:
> Max Reitz  writes:
> 
>> This adds some whitespace into the option help (including indentation)
>> and replaces '=' by ': ' (not least because '=' should be used for
>> values, not types).  Furthermore, the list name is no longer printed as
>> part of every line, but only once in advance, and only if the caller did
>> not print a caption already.
>>
>> Signed-off-by: Max Reitz 
>> ---
>>  include/qemu/option.h  |   2 +-
>>  qemu-img.c |   4 +-
>>  util/qemu-option.c |  31 +-
>>  tests/qemu-iotests/082.out | 956 ++---
>>  4 files changed, 505 insertions(+), 488 deletions(-)
> 
> 082 fails for me in master (dddb37495b8).  If this patch fixes the
> failure, its commit message should mention it.

Ah, yeah, totally forgot that...

Max

> 091 and 142 also fail, but look unrelated.




signature.asc
Description: OpenPGP digital signature


Re: [Qemu-block] [PATCH 1/5] option: Make option help nicer to read

2018-10-19 Thread Max Reitz
On 16.10.18 14:12, Kevin Wolf wrote:
> Am 15.10.2018 um 19:28 hat Max Reitz geschrieben:
>> This adds some whitespace into the option help (including indentation)
>> and replaces '=' by ': ' (not least because '=' should be used for
>> values, not types).  Furthermore, the list name is no longer printed as
>> part of every line, but only once in advance, and only if the caller did
>> not print a caption already.
>>
>> Signed-off-by: Max Reitz 
> 
> If this isn't a bike shedding series, then what is? So...

Sure it is.

>> --- a/tests/qemu-iotests/082.out
>> +++ b/tests/qemu-iotests/082.out
>> @@ -44,171 +44,171 @@ cluster_size: 8192
>>  
>>  Testing: create -f qcow2 -o help TEST_DIR/t.qcow2 128M
>>  Supported options:
>> -size Virtual disk size
>> -compat   Compatibility level (0.10 or 1.1)
>> -backing_file File name of a base image
>> -backing_fmt  Image format of the base image
>> -encryption   Encrypt the image with format 'aes'. (Deprecated in favor 
>> of encrypt.format=aes)
>> -encrypt.format   Encrypt the image, format choices: 'aes', 'luks'
>> -encrypt.key-secret ID of secret providing qcow AES key or LUKS passphrase
>> -encrypt.cipher-alg Name of encryption cipher algorithm
>> -encrypt.cipher-mode Name of encryption cipher mode
>> -encrypt.ivgen-alg Name of IV generator algorithm
>> -encrypt.ivgen-hash-alg Name of IV generator hash algorithm
>> -encrypt.hash-alg Name of encryption hash algorithm
>> -encrypt.iter-time Time to spend in PBKDF in milliseconds
>> -cluster_size qcow2 cluster size
>> -preallocationPreallocation mode (allowed values: off, metadata, falloc, 
>> full)
>> -lazy_refcounts   Postpone refcount updates
>> -refcount_bitsWidth of a reference count entry in bits
>> -nocowTurn off copy-on-write (valid only on btrfs)
>> +  backing_file: str - File name of a base image
>> +  backing_fmt: str - Image format of the base image
>> +  cluster_size: size - qcow2 cluster size
>> +  compat: str - Compatibility level (0.10 or 1.1)
>> +  encrypt.cipher-alg: str - Name of encryption cipher algorithm
>> +  encrypt.cipher-mode: str - Name of encryption cipher mode
>> +  encrypt.format: str - Encrypt the image, format choices: 'aes', 'luks'
>> +  encrypt.hash-alg: str - Name of encryption hash algorithm
>> +  encrypt.iter-time: num - Time to spend in PBKDF in milliseconds
>> +  encrypt.ivgen-alg: str - Name of IV generator algorithm
>> +  encrypt.ivgen-hash-alg: str - Name of IV generator hash algorithm
>> +  encrypt.key-secret: str - ID of secret providing qcow AES key or LUKS 
>> passphrase
>> +  encryption: bool (on/off) - Encrypt the image with format 'aes'. 
>> (Deprecated in favor of encrypt.format=aes)
>> +  lazy_refcounts: bool (on/off) - Postpone refcount updates
>> +  nocow: bool (on/off) - Turn off copy-on-write (valid only on btrfs)
>> +  preallocation: str - Preallocation mode (allowed values: off, metadata, 
>> falloc, full)
>> +  refcount_bits: num - Width of a reference count entry in bits
>> +  size: size - Virtual disk size
> 
> I like the result of this series better than what we have in current
> master. Looking at this patch, however, I must also say that I like the
> original state better than both.

I don't disagree.  But having the types is indeed a worthy improvement.

> How about aligning the description to the same column again to combine
> the best of both worlds?

That sounds good to me.

Max



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-block] [Qemu-devel] [PATCH 1/5] option: Make option help nicer to read

2018-10-19 Thread Max Reitz
On 16.10.18 08:46, Marc-André Lureau wrote:
> Hi
> 
> On Mon, Oct 15, 2018 at 9:34 PM Max Reitz  wrote:
>>
>> This adds some whitespace into the option help (including indentation)
>> and replaces '=' by ': ' (not least because '=' should be used for
>> values, not types).
> 
> Without strong preference, I like the '=' better: it's the expected
> syntax for the command line argument. (also, --help and man pages
> describe options with "foo=type", not "foo: type")

Define "strong".  I do believe that types are different from values, and
that '=' is reserved for values and never used with types.

It's not like I'll die when we keep '=', though, but it's definitely not
what I'd use.  Maybe "foo=", but that feels overly cluttered when
compared to "foo: str".  (Especially when it comes to things like
"iothread=>".)

>> Furthermore, the list name is no longer printed as
>> part of every line, but only once in advance, and only if the caller did
>> not print a caption already.
>>
>> Signed-off-by: Max Reitz 
> 
> looks good to me otherwise

Well, if '=' is the only trouble, that's good. :-)

Max



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-block] [Qemu-devel] [PATCH 1/9] iotests: Make nbd-fault-injector flush

2018-10-19 Thread Max Reitz
On 16.10.18 20:07, Eric Blake wrote:
> On 10/15/18 9:14 AM, Max Reitz wrote:
>> When closing a connection, make the nbd-fault-injector flush the socket.
>> Without this, the output is a bit unreliable with Python 3.
>>
>> Signed-off-by: Max Reitz 
>> ---
>>   tests/qemu-iotests/083.out   | 9 +
>>   tests/qemu-iotests/nbd-fault-injector.py | 1 +
>>   2 files changed, 10 insertions(+)
> 
> I already had a complaint that the error message in 083.out should NOT
> be printing a message

You mean the NBD server itself, right?

>   (whether the server is python 2 and auto-flushes,
> or python 3 and needs an explicit flush, the message itself is
> pointless, and the test is racy as a result).  We may need to revisit
> this patch when that thread is resolved.
> 
> https://lists.gnu.org/archive/html/qemu-devel/2018-08/msg01041.html

Well, it's not like the flush hurts either way. :-)

Max

> That said, I'm not opposed to this patch, if it gets iotests to be more
> useful in the meantime.
> 
>>
>> diff --git a/tests/qemu-iotests/083.out b/tests/qemu-iotests/083.out
>> index be6079d27e..f9af8bb691 100644
>> --- a/tests/qemu-iotests/083.out
>> +++ b/tests/qemu-iotests/083.out
>> @@ -41,6 +41,7 @@ can't open device nbd+tcp://127.0.0.1:PORT/foo
>>     === Check disconnect after neg2 ===
>>   +Unable to read from socket: Connection reset by peer
>>   Connection closed
>>   read failed: Input/output error
>>   @@ -54,6 +55,7 @@ can't open device nbd+tcp://127.0.0.1:PORT/foo
>>     === Check disconnect before request ===
>>   +Unable to read from socket: Connection reset by peer
>>   Connection closed
>>   read failed: Input/output error
>>   @@ -116,6 +118,7 @@ can't open device nbd+tcp://127.0.0.1:PORT/
>>     === Check disconnect after neg-classic ===
>>   +Unable to read from socket: Connection reset by peer
>>   Connection closed
>>   read failed: Input/output error
>>   @@ -161,6 +164,8 @@ can't open device
>> nbd+unix:///foo?socket=TEST_DIR/nbd.sock
>>     === Check disconnect after neg2 ===
>>   +Unable to read from socket: Connection reset by peer
>> +Connection closed
>>   read failed: Input/output error
>>     === Check disconnect 8 neg2 ===
>> @@ -173,6 +178,8 @@ can't open device
>> nbd+unix:///foo?socket=TEST_DIR/nbd.sock
>>     === Check disconnect before request ===
>>   +Unable to read from socket: Connection reset by peer
>> +Connection closed
>>   read failed: Input/output error
>>     === Check disconnect after request ===
>> @@ -234,6 +241,8 @@ can't open device
>> nbd+unix:///?socket=TEST_DIR/nbd.sock
>>     === Check disconnect after neg-classic ===
>>   +Unable to read from socket: Connection reset by peer
>> +Connection closed
>>   read failed: Input/output error
>>     *** done
>> diff --git a/tests/qemu-iotests/nbd-fault-injector.py
>> b/tests/qemu-iotests/nbd-fault-injector.py
>> index f9193c0fae..439a090eb6 100755
>> --- a/tests/qemu-iotests/nbd-fault-injector.py
>> +++ b/tests/qemu-iotests/nbd-fault-injector.py
>> @@ -112,6 +112,7 @@ class FaultInjectionSocket(object):
>>   if rule.match(event, io):
>>   if rule.when == 0 or bufsize is None:
>>   print('Closing connection on rule match %s' %
>> rule.name)
>> +    self.sock.flush()
>>   sys.exit(0)
>>   if rule.when != -1:
>>   return rule.when
>>
> 




signature.asc
Description: OpenPGP digital signature


Re: [Qemu-block] [Qemu-devel] [PATCH 7/9] iotests: 'new' module replacement in 169

2018-10-19 Thread Max Reitz
On 16.10.18 03:01, Cleber Rosa wrote:
> 
> 
> On 10/15/18 7:57 PM, Eduardo Habkost wrote:
>> On Mon, Oct 15, 2018 at 07:38:45PM -0400, Cleber Rosa wrote:
>>>
>>>
>>> On 10/15/18 10:14 AM, Max Reitz wrote:
 iotest 169 uses the 'new' module to add methods to a class.  This module
 no longer exists in Python 3.  Instead, we can use a lambda.  Best of
 all, this works in 2.7 just as well.

 Signed-off-by: Max Reitz 
 ---
  tests/qemu-iotests/169 | 3 +--
  1 file changed, 1 insertion(+), 2 deletions(-)

 diff --git a/tests/qemu-iotests/169 b/tests/qemu-iotests/169
 index f243db9955..e5614b159d 100755
 --- a/tests/qemu-iotests/169
 +++ b/tests/qemu-iotests/169
 @@ -23,7 +23,6 @@ import iotests
  import time
  import itertools
  import operator
 -import new
  from iotests import qemu_img
  
  
 @@ -144,7 +143,7 @@ class TestDirtyBitmapMigration(iotests.QMPTestCase):
  
  def inject_test_case(klass, name, method, *args, **kwargs):
  mc = operator.methodcaller(method, *args, **kwargs)
 -setattr(klass, 'test_' + name, new.instancemethod(mc, None, klass))
 +setattr(klass, 'test_' + name, lambda self: mc(self))
  
  for cmb in list(itertools.product((True, False), repeat=4)):
  name = ('_' if cmb[0] else '_not_') + 'persistent_'

>>>
>>> This can be simplified with:
>>>
>>> diff --git a/tests/qemu-iotests/169 b/tests/qemu-iotests/169
>>> index e5614b159d..2199f14ae7 100755
>>> --- a/tests/qemu-iotests/169
>>> +++ b/tests/qemu-iotests/169
>>> @@ -22,7 +22,6 @@ import os
>>>  import iotests
>>>  import time
>>>  import itertools
>>> -import operator
>>>  from iotests import qemu_img
>>>
>>>
>>> @@ -141,18 +140,15 @@ class TestDirtyBitmapMigration(iotests.QMPTestCase):
>>>  self.check_bitmap(self.vm_b, sha256 if persistent else False)
>>>
>>>
>>> -def inject_test_case(klass, name, method, *args, **kwargs):
>>> -mc = operator.methodcaller(method, *args, **kwargs)
>>> -setattr(klass, 'test_' + name, lambda self: mc(self))
>>> -
>>>  for cmb in list(itertools.product((True, False), repeat=4)):
>>>  name = ('_' if cmb[0] else '_not_') + 'persistent_'
>>>  name += ('_' if cmb[1] else '_not_') + 'migbitmap_'
>>>  name += '_online' if cmb[2] else '_offline'
>>>  name += '_shared' if cmb[3] else '_nonshared'
>>>
>>> -inject_test_case(TestDirtyBitmapMigration, name, 'do_test_migration',
>>> - *list(cmb))
>>> +setattr(TestDirtyBitmapMigration, 'test_' + name,
>>> +lambda self: TestDirtyBitmapMigration.do_test_migration(
>>> +self, *list(cmb)))
>>
>> I'm not fond of the long multi-line lambda expression, but I love
>> that you got rid of operator.methodcaller().  :)
>>
>> However, this doesn't seem to work: `*list(cmb)` will be
>> evaluated only when the lambda is called, and `cmb` will be
>> always `(False, False, False, False)`.
>>
>> I was going to suggest defining a nested function inside
>> inject_test_case() to replace operator.methodcaller(), but then I
>> thought it was not worth it.
>>
> 
> You're right! I missed that.  Anyway, another possibility:
> 
> diff --git a/tests/qemu-iotests/169 b/tests/qemu-iotests/169
> index e5614b159d..cd0d9c289c 100755
> --- a/tests/qemu-iotests/169
> +++ b/tests/qemu-iotests/169
> @@ -22,7 +22,7 @@ import os
>  import iotests
>  import time
>  import itertools
> -import operator
> +import functools
>  from iotests import qemu_img
> 
> 
> @@ -140,20 +140,15 @@ class TestDirtyBitmapMigration(iotests.QMPTestCase):
>  self.vm_b.launch()
>  self.check_bitmap(self.vm_b, sha256 if persistent else False)
> 
> -
> -def inject_test_case(klass, name, method, *args, **kwargs):
> -mc = operator.methodcaller(method, *args, **kwargs)
> -setattr(klass, 'test_' + name, lambda self: mc(self))
> -
> -for cmb in list(itertools.product((True, False), repeat=4)):
> +for cmb in itertools.product((True, False), repeat=4):
>  name = ('_' if cmb[0] else '_not_') + 'persistent_'
>  name += ('_' if cmb[1] else '_not_') + 'migbitmap_'
>  name += '_online' if cmb[2] else '_offline'
>  name += '_shared' if cmb[3] else '_nonshared'
> 
> -inject_test_case(TestDirtyBitmapMigration, name, 'do_test_migration',
> - *list(cmb))
> -
> +test =
> functools.partialmethod(TestDirtyBitmapMigration.do_test_migration,
> +   *cmb)
> +setattr(TestDirtyBitmapMigration, 'test_' + name, test)

I'm not sure how that is any simpler, though (apart from the inlining). :-)

I mean, my personal goal is not to touch this beyond what I need to
because it's black magic to me anyway, so I'm happy with what works.

Max



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-block] [Qemu-devel] [PATCH 6/9] iotests: Explicitly inherit FDs in Python

2018-10-19 Thread Max Reitz
On 16.10.18 01:18, Cleber Rosa wrote:
> 
> 
> On 10/15/18 10:14 AM, Max Reitz wrote:
>> Python 3.2 introduced the inheritable attribute for FDs.  At the same
>> time, it changed the default so that all FDs are not inheritable by
>> default, that only inheritable FDs are inherited to subprocesses, and
>> only if close_fds is explicitly set to False.
>>
> 
> It's actually a change that was introduced in 3.4:
> 
> https://docs.python.org/3/library/os.html#inheritance-of-file-descriptors

Oops, don't know how I got that wrong.

>> Adhere to this by setting close_fds to False when working with
>> subprocesses that may want to inherit FDs, and by trying to
>> set_inheritable() on FDs that we do want to bequeath to them.
>>
>> Signed-off-by: Max Reitz 
>> ---
>>  scripts/qemu.py| 13 +++--
>>  scripts/qmp/qmp.py |  7 +++
>>  tests/qemu-iotests/147 |  7 +++
>>  3 files changed, 25 insertions(+), 2 deletions(-)
>>
>> diff --git a/scripts/qemu.py b/scripts/qemu.py
>> index f099ce7278..28366c4a67 100644
>> --- a/scripts/qemu.py
>> +++ b/scripts/qemu.py
>> @@ -142,10 +142,18 @@ class QEMUMachine(object):
>>  if opts:
>>  options.append(opts)
>>  
>> +# This did not exist before 3.2, but since then it is
>> +# mandatory for our purpose
>> +try:
> 
> Version should be 3.4 here as well.

Yes, will fix everywhere.

>> +os.set_inheritable(fd, True)
>> +except AttributeError:
>> +pass
>> +
> 
> Doing hasattr(os, "set_inheritable") is cheaper.
> 
> - Cleber.

Nice, I'll use that then.

Max

>>  self._args.append('-add-fd')
>>  self._args.append(','.join(options))
>>  return self
>>  
>> +# The caller needs to make sure the FD is inheritable
>>  def send_fd_scm(self, fd_file_path):
>>  # In iotest.py, the qmp should always use unix socket.
>>  assert self._qmp.is_scm_available()
>> @@ -159,7 +167,7 @@ class QEMUMachine(object):
>>  "%s" % fd_file_path]
>>  devnull = open(os.path.devnull, 'rb')
>>  proc = subprocess.Popen(fd_param, stdin=devnull, 
>> stdout=subprocess.PIPE,
>> -stderr=subprocess.STDOUT)
>> +stderr=subprocess.STDOUT, close_fds=False)
>>  output = proc.communicate()[0]
>>  if output:
>>  LOG.debug(output)
>> @@ -280,7 +288,8 @@ class QEMUMachine(object):
>> stdin=devnull,
>> stdout=self._qemu_log_file,
>> stderr=subprocess.STDOUT,
>> -   shell=False)
>> +   shell=False,
>> +   close_fds=False)
>>  self._post_launch()
>>  
>>  def wait(self):
>> diff --git a/scripts/qmp/qmp.py b/scripts/qmp/qmp.py
>> index 5c8cf6a056..009be8345b 100644
>> --- a/scripts/qmp/qmp.py
>> +++ b/scripts/qmp/qmp.py
>> @@ -10,6 +10,7 @@
>>  
>>  import json
>>  import errno
>> +import os
>>  import socket
>>  import logging
>>  
>> @@ -253,4 +254,10 @@ class QEMUMonitorProtocol(object):
>>  return self.__sock.fileno()
>>  
>>  def is_scm_available(self):
>> +# This did not exist before 3.2, but since then it is
>> +# mandatory for our purpose
>> +try:
>> +os.set_inheritable(self.get_sock_fd(), True)
>> +except AttributeError:
>> +pass
>>  return self.__sock.family == socket.AF_UNIX
>> diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147
>> index d2081df84b..b58455645b 100755
>> --- a/tests/qemu-iotests/147
>> +++ b/tests/qemu-iotests/147
>> @@ -229,6 +229,13 @@ class BuiltinNBD(NBDBlockdevAddBase):
>>  sockfd = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
>>  sockfd.connect(unix_socket)
>>  
>> +# This did not exist before 3.2, but since then it is
>> +# mandatory for our purpose
>> +try:
>> +os.set_inheritable(sockfd.fileno(), True)
>> +except AttributeError:
>> +pass
>> +
>>  result = self.vm.send_fd_scm(str(sockfd.fileno()))
>>  self.assertEqual(result, 0, 'Failed to send socket FD')
>>  
>>
> 




signature.asc
Description: OpenPGP digital signature


Re: [Qemu-block] [Qemu-devel] [PATCH 5/9] iotests: Different iterator behavior in Python 3

2018-10-19 Thread Max Reitz
On 16.10.18 00:39, Cleber Rosa wrote:
> 
> 
> On 10/15/18 10:14 AM, Max Reitz wrote:
>> In Python 3, several functions now return iterators instead of lists.
>> This includes range(), items(), map(), and filter().  This means that if
>> we really want a list, we have to wrap those instances with list().  On
>> the other hand, sometimes we do just want an iterator, in which case we
>> have sometimes used xrange() and iteritems() which no longer exist in
>> Python 3.  Just change these calls to be range() and items(), which
>> costs a bit of performance in Python 2, but will do the right thing in
>> Python 3 (which is what is important).
>>
>> In one instance, we only wanted the first instance of the result of a
>> filter() call.  Instead of using next(filter()) which would work only in
>> Python 3, or list(filter())[0] which would work everywhere but is a bit
>> weird, this instance is changed to a single-line for with next() wrapped
>> around, which works both in 2.7 and 3.
>>
>> Signed-off-by: Max Reitz 
>> ---
>>  tests/qemu-iotests/044 | 12 ++--
>>  tests/qemu-iotests/056 |  2 +-
>>  tests/qemu-iotests/065 |  4 ++--
>>  tests/qemu-iotests/124 |  4 ++--
>>  tests/qemu-iotests/139 |  2 +-
>>  tests/qemu-iotests/163 |  6 +++---
>>  6 files changed, 15 insertions(+), 15 deletions(-)
>>
> 
> You have 2 files here which use xrange (which is a manageable size, and
> whose occurrences involve a moderate size of items) to also consider:
> 
> if sys.version_info.major == 2:
>range = xrange

I don't think it's necessary, but it's so easy to grep for
"sys.version_info" once we want to completely switch to Python 3 that I
can't find good arguments against it. O:-)

Max

> Defaulting to the Python 3 names, but behaving the same across Python 2
> and 3.
> 
> To do the same for dict.iteritems() => dict.items() requires a lot more
> code, so I'd stay away from it for now.  Also, it looks like most of
> those dicts are small in size (**kwargs and the like).
> 
> Other than that suggestion,
> 
> Reviewed-by: Cleber Rosa 
> 




signature.asc
Description: OpenPGP digital signature


Re: [Qemu-block] [Qemu-devel] [PATCH 9/9] iotests: Unify log outputs between Python 2 and 3

2018-10-19 Thread Max Reitz
On 16.10.18 00:26, Eduardo Habkost wrote:
> On Mon, Oct 15, 2018 at 04:14:53PM +0200, Max Reitz wrote:
>> When dumping an object into the log, there are differences between
>> Python 2 and 3.  First, unicode strings are prefixed by 'u' in Python 2
>> (they are no longer in 3, because unicode strings are the default
>> there).  [...]
> 
> This could be addressed using JSON.  See below[1].
> 
>> [...] Second, the order of keys in dicts may differ.  [...]
> 
> Can be addressed using json.dumps(..., sort_keys=True).

Ah.  Nice. :-)

>> [...] Third,
>> especially long numbers are longs in Python 2 and thus get an 'L'
>> suffix, which does not happen in Python 3.
> 
> print() doesn't add a L suffix on Python 2.7 on my system:
> 
> Python 2.7.15 (default, May 15 2018, 15:37:31)
> [GCC 7.3.1 20180303 (Red Hat 7.3.1-5)] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
 print(999L)
> 999
> 
> So I assume this happens only for QMP commands.

It happens for dicts:

>>> print L

>>> print {'foo':L}
{'foo': L}

> It would be addressed if using JSON, too.

OK.

>> To get around these differences, this patch introduces functions to
>> convert an object to a string that looks the same regardless of the
>> Python version: In Python 2, they decode unicode strings to byte strings
>> (normal str); in Python 3, they encode byte strings to unicode strings
>> (normal str).  They also manually convert lists and dicts to strings,
>> which allows sorting the dicts by key, so we are no longer at the mercy
>> of the internal implementation when it comes to how the keys appear in
>> the output.
>>
>> This changes the output of all tests that use these logging functions.
>>
>> Signed-off-by: Max Reitz 
>> ---
>>  tests/qemu-iotests/194.out|  22 +-
>>  tests/qemu-iotests/202.out|  12 +-
>>  tests/qemu-iotests/203.out|  14 +-
>>  tests/qemu-iotests/206.out| 144 +-
>>  tests/qemu-iotests/207.out|  52 ++--
>>  tests/qemu-iotests/208.out|   8 +-
>>  tests/qemu-iotests/210.out|  72 ++---
>>  tests/qemu-iotests/211.out|  66 ++---
>>  tests/qemu-iotests/212.out| 102 +++
>>  tests/qemu-iotests/213.out| 124 
>>  tests/qemu-iotests/216.out|   4 +-
>>  tests/qemu-iotests/218.out|  20 +-
>>  tests/qemu-iotests/219.out| 526 +-
>>  tests/qemu-iotests/222.out|  24 +-
>>  tests/qemu-iotests/iotests.py |  42 ++-
>>  15 files changed, 634 insertions(+), 598 deletions(-)
> [...]
>> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
>> index a64ea90fb4..f8dbc8cc71 100644
>> --- a/tests/qemu-iotests/iotests.py
>> +++ b/tests/qemu-iotests/iotests.py
>> @@ -250,10 +250,45 @@ def filter_img_info(output, filename):
>>  lines.append(line)
>>  return '\n'.join(lines)
>>  
>> +def log_to_string_repr(obj):
>> +# Normal Python 3 strings are the unicode strings from Python 2;
>> +# and normal Python 2 strings are byte strings in Python 3.  Thus,
>> +# we convert bytes -> str in py3 and unicode -> str in py2.
>> +if sys.version_info.major >= 3:
>> +if type(obj) is bytes:
>> +return repr(obj.decode('utf-8'))
>> +else:
>> +if type(obj) is unicode:
>> +return repr(obj.encode('utf-8'))
>> +elif type(obj) is long:
>> +return str(obj) # repr() would include an 'L' suffix
>> +
>> +if type(obj) is list:
>> +return '[' + ', '.join(map(log_to_string_repr, obj)) + ']'
>> +elif type(obj) is dict:
>> +return '{' + ', '.join(map(lambda k: log_to_string_repr(k) + ': ' +
>> + log_to_string_repr(obj[k]),
>> +   sorted(obj.keys( + '}'
>> +else:
>> +return repr(obj)
> 
> I assume this function exists only because of QMP logging,
> correct?

In practice probably yes.

> I would just use json.dumps() at qmp_log(), see below[1].

However, there is not just qmp_log(), there are places that dump objects
directly into log().

>> +
>> +def log_to_string(obj):
>> +if type(obj) is str:
>> +return obj
>> +
>> +if sys.version_info.major >= 3:
>> +if type(obj) is bytes:
>> +return obj.decode('utf-8')
> 
> Do you know how many of existing log() calls actually pass a byte
> string as argument?

Frankly I hope none.

>> +else:
>> +if type(obj) is unicode:
>> +return obj.encode('utf-8')
> 
> Is this really necessary?  The existing code just calls
> print(msg) and it works, doesn't it?

True.  But the main issue is that we still need to return immediately
for byte strings and Unicode strings, but the type "bytes" only exists
in 3.x and "un

Re: [Qemu-block] [PATCH 8/9] iotests: Modify imports for Python 3

2018-10-19 Thread Max Reitz
On 16.10.18 02:12, Eduardo Habkost wrote:
> On Mon, Oct 15, 2018 at 08:05:02PM -0400, Cleber Rosa wrote:
>>
>>
>> On 10/15/18 5:17 PM, Eduardo Habkost wrote:
>>> On Mon, Oct 15, 2018 at 04:14:52PM +0200, Max Reitz wrote:
 There are two imports that need to be modified when running the iotests
 under Python 3: One is StringIO, which no longer exists; instead, the
 StringIO class comes from the io module, so import it from there.  The
 other is the ConfigParser, which has just been renamed to configparser.

 Signed-off-by: Max Reitz 
 ---
  tests/qemu-iotests/iotests.py| 8 ++--
  tests/qemu-iotests/nbd-fault-injector.py | 7 +--
  2 files changed, 11 insertions(+), 4 deletions(-)

 diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
 index 7ca94e9278..a64ea90fb4 100644
 --- a/tests/qemu-iotests/iotests.py
 +++ b/tests/qemu-iotests/iotests.py
 @@ -683,13 +683,17 @@ def main(supported_fmts=[], 
 supported_oses=['linux'], supported_cache_modes=[],
  
  # We need to filter out the time taken from the output so that 
 qemu-iotest
  # can reliably diff the results against master output.
 -import StringIO
 +if sys.version_info.major >= 3:
 +from io import StringIO
 +else:
 +from StringIO import StringIO
>>>
>>> Considering that io.StringIO exists on Python 2.7, a comment
>>> explaining why exactly it doesn't work would be nice.

Oh, it does exist?  I didn't know. O:-)

So I suppose it's because the test runner emits just normal strings,
which in 2.x are byte strings; but io's StringIO always expects Unicode
strings.  StringIO, OTOH, accepts both (and returns Unicode strings once
you put a Unicode string into it).

>> Another possibility, that I find self explanatory:
>>
>> import io
>>
>> if sys.version_info.major >= 3:
>>output = io.StringIO()
>> else:
>>output = io.BytesIO()
> 
> Looks nice and clean.
> 
> But I'm not sure all output sent to `output` when running with
> Python 2 will be byte strings.  What if `unittest.TextTestRunner`
> tries to write unicode strings to `output`?

Hm.  It doesn't look this way to me in practice.  And considering that
it only really prints a test summary, I don't think there are edge cases
where it behaves differently.

So I think using BytesIO() in 2.x is better.

Max



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-block] [Qemu-devel] [PATCH 0/9] iotests: Make them work for both Python 2 and 3

2018-10-19 Thread Max Reitz
On 16.10.18 00:19, Philippe Mathieu-Daudé wrote:
> Hi Max,
> 
> On 15/10/2018 16:14, Max Reitz wrote:
>> This series prepares the iotests to work with both Python 2 and 3.  In
>> some places, it adds version-specific code and decides what to do based
>> on the version (for instance, whether to import the StringIO class from
>> the 'io' or the 'StringIO' module), but most of the time, it just makes
>> code work for both versions in general.
>>
>> And when we make the switch to make Python 3 mandatory, we can simply
>> drop the Python 2 branches.
>>
>>
>> Max Reitz (9):
>>   iotests: Make nbd-fault-injector flush
>>   iotests: Flush in iotests.py's QemuIoInteractive
>>   iotests: Use Python byte strings where appropriate
>>   iotests: Use // for Python integer division
>>   iotests: Different iterator behavior in Python 3
>>   iotests: Explicitly inherit FDs in Python
>>   iotests: 'new' module replacement in 169
>>   iotests: Modify imports for Python 3
>>   iotests: Unify log outputs between Python 2 and 3
> 
> You forgot:
> 
> MAINTAINERS: Add myself in the Python scripts section
> 
> ;)

Aw, please, no.  You do know I don't really know Python? ;-)

Max



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-block] [Qemu-devel] [PATCH 4/9] iotests: Use // for Python integer division

2018-10-19 Thread Max Reitz
On 15.10.18 23:13, Cleber Rosa wrote:
> 
> 
> On 10/15/18 10:14 AM, Max Reitz wrote:
>> In Python 3, / is always a floating-point division.  We usually do not
>> want this, and as Python 2.7 understands // as well, change all integer
>> divisions to use that.
>>
>> Signed-off-by: Max Reitz 
>> ---
>>  tests/qemu-iotests/040|  4 ++--
>>  tests/qemu-iotests/044|  2 +-
>>  tests/qemu-iotests/093| 18 +-
>>  tests/qemu-iotests/149|  6 +++---
>>  tests/qemu-iotests/151| 12 ++--
>>  tests/qemu-iotests/163|  2 +-
>>  tests/qemu-iotests/iotests.py |  2 +-
>>  7 files changed, 23 insertions(+), 23 deletions(-)
>>
>> diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
>> index 1cb1ceeb33..b81133a474 100755
>> --- a/tests/qemu-iotests/040
>> +++ b/tests/qemu-iotests/040
>> @@ -195,7 +195,7 @@ class TestSingleDrive(ImageCommitTestCase):
>>  
>>  self.assert_no_active_block_jobs()
>>  result = self.vm.qmp('block-commit', device='drive0', top=mid_img,
>> - base=backing_img, speed=(self.image_len / 4))
>> + base=backing_img, speed=(self.image_len // 4))
>>  self.assert_qmp(result, 'return', {})
>>  result = self.vm.qmp('device_del', id='scsi0')
>>  self.assert_qmp(result, 'return', {})
>> @@ -225,7 +225,7 @@ class TestSingleDrive(ImageCommitTestCase):
>>  
>>  self.assert_no_active_block_jobs()
>>  result = self.vm.qmp('block-commit', device='drive0', top=mid_img,
>> - base=backing_img, speed=(self.image_len / 4))
>> + base=backing_img, speed=(self.image_len // 4))
>>  self.assert_qmp(result, 'return', {})
>>  
>>  result = self.vm.qmp('query-block')
>> diff --git a/tests/qemu-iotests/044 b/tests/qemu-iotests/044
>> index 69e736f687..7ef5e46fe9 100755
>> --- a/tests/qemu-iotests/044
>> +++ b/tests/qemu-iotests/044
>> @@ -86,7 +86,7 @@ class TestRefcountTableGrowth(iotests.QMPTestCase):
>>  off = off + 1024 * 512
>>  
>>  table = b''.join(struct.pack('>Q', (1 << 63) | off + 512 * j)
>> -for j in xrange(0, remaining / 512))
>> +for j in xrange(0, remaining // 512))
>>  fd.write(table)
>>  
>>  
>> diff --git a/tests/qemu-iotests/093 b/tests/qemu-iotests/093
>> index 9d1971a56c..d88fbc182e 100755
>> --- a/tests/qemu-iotests/093
>> +++ b/tests/qemu-iotests/093
>> @@ -69,18 +69,18 @@ class ThrottleTestCase(iotests.QMPTestCase):
>>  # in. The throttled requests won't be executed until we
>>  # advance the virtual clock.
>>  rq_size = 512
>> -rd_nr = max(params['bps'] / rq_size / 2,
>> -params['bps_rd'] / rq_size,
>> -params['iops'] / 2,
>> +rd_nr = max(params['bps'] // rq_size // 2,
>> +params['bps_rd'] // rq_size,
>> +params['iops'] // 2,
>>  params['iops_rd'])
>>  rd_nr *= seconds * 2
>> -rd_nr /= ndrives
>> -wr_nr = max(params['bps'] / rq_size / 2,
>> -params['bps_wr'] / rq_size,
>> -params['iops'] / 2,
>> +rd_nr //= ndrives
>> +wr_nr = max(params['bps'] // rq_size // 2,
>> +params['bps_wr'] // rq_size,
>> +params['iops'] // 2,
>>  params['iops_wr'])
>>  wr_nr *= seconds * 2
>> -wr_nr /= ndrives
>> +wr_nr //= ndrives
>>  
>>  # Send I/O requests to all drives
>>  for i in range(rd_nr):
>> @@ -196,7 +196,7 @@ class ThrottleTestCase(iotests.QMPTestCase):
>>  self.configure_throttle(ndrives, settings)
>>  
>>  # Wait for the bucket to empty so we can do bursts
>> -wait_ns = nsec_per_sec * burst_length * burst_rate / rate
>> +wait_ns = nsec_per_sec * burst_length * burst_rate // rate
>>  self.vm.qtest("clock_step %d" % wait_ns)
>>  
>>  # Test I/O at the max burst rate
>> diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149
>> index 1225334cb8..4f363f295f 100755
>> --- a/tests/qemu-iotests/149
>> +++ b/tests/qemu-iotests/149
>> @@ -314,13 +314,13 @@ def test_once(config, qemu_img=False):
>>  image_size = 4 * oneTB
>>  if qemu_img:
>>  iotests.log("# Create image")
>> -qemu_img_create(config, image_size / oneMB)
>> +qemu_img_create(config, image_size // oneMB)
>>  else:
>>  iotests.log("# Create image")
>> -create_image(config, image_size / oneMB)
>> +create_image(config, image_size // oneMB)
>>  
>>  lowOffsetMB = 100
>> -highOffsetMB = 3 * oneTB / oneMB
>> +highOffsetMB = 3 * oneTB // oneMB
>>  
>>  try:
>>  if not qemu_img:
>> diff --git a/tests/qemu-iotests/151 b/tests/qemu-iotests/151
>> index fe53b9f446..1bb74d67c4 100

Re: [Qemu-block] [PATCH 6/9] iotests: Explicitly inherit FDs in Python

2018-10-19 Thread Max Reitz
On 15.10.18 22:30, Eduardo Habkost wrote:
> On Mon, Oct 15, 2018 at 04:14:50PM +0200, Max Reitz wrote:
>> Python 3.2 introduced the inheritable attribute for FDs.  At the same
>> time, it changed the default so that all FDs are not inheritable by
>> default, that only inheritable FDs are inherited to subprocesses, and
>> only if close_fds is explicitly set to False.
>>
>> Adhere to this by setting close_fds to False when working with
>> subprocesses that may want to inherit FDs, and by trying to
>> set_inheritable() on FDs that we do want to bequeath to them.
>>
>> Signed-off-by: Max Reitz 
>> ---
>>  scripts/qemu.py| 13 +++--
>>  scripts/qmp/qmp.py |  7 +++
>>  tests/qemu-iotests/147 |  7 +++
>>  3 files changed, 25 insertions(+), 2 deletions(-)
>>
>> diff --git a/scripts/qemu.py b/scripts/qemu.py
>> index f099ce7278..28366c4a67 100644
>> --- a/scripts/qemu.py
>> +++ b/scripts/qemu.py
>> @@ -142,10 +142,18 @@ class QEMUMachine(object):
>>  if opts:
>>  options.append(opts)
>>  
>> +# This did not exist before 3.2, but since then it is
>> +# mandatory for our purpose
>> +try:
>> +os.set_inheritable(fd, True)
>> +except AttributeError:
>> +pass
>> +
> 
> This is add_fd(), so calling set_inheritable() automatically here
> makes sense.
> 
>>  self._args.append('-add-fd')
>>  self._args.append(','.join(options))
>>  return self
>>  
>> +# The caller needs to make sure the FD is inheritable
>>  def send_fd_scm(self, fd_file_path):
>>  # In iotest.py, the qmp should always use unix socket.
>>  assert self._qmp.is_scm_available()
>> @@ -159,7 +167,7 @@ class QEMUMachine(object):
>>  "%s" % fd_file_path]
>>  devnull = open(os.path.devnull, 'rb')
>>  proc = subprocess.Popen(fd_param, stdin=devnull, 
>> stdout=subprocess.PIPE,
>> -stderr=subprocess.STDOUT)
>> +stderr=subprocess.STDOUT, close_fds=False)
>>  output = proc.communicate()[0]
>>  if output:
>>  LOG.debug(output)
>> @@ -280,7 +288,8 @@ class QEMUMachine(object):
>> stdin=devnull,
>> stdout=self._qemu_log_file,
>> stderr=subprocess.STDOUT,
>> -   shell=False)
>> +   shell=False,
>> +   close_fds=False)
>>  self._post_launch()
>>  
>>  def wait(self):
>> diff --git a/scripts/qmp/qmp.py b/scripts/qmp/qmp.py
>> index 5c8cf6a056..009be8345b 100644
>> --- a/scripts/qmp/qmp.py
>> +++ b/scripts/qmp/qmp.py
>> @@ -10,6 +10,7 @@
>>  
>>  import json
>>  import errno
>> +import os
>>  import socket
>>  import logging
>>  
>> @@ -253,4 +254,10 @@ class QEMUMonitorProtocol(object):
>>  return self.__sock.fileno()
>>  
>>  def is_scm_available(self):
>> +# This did not exist before 3.2, but since then it is
>> +# mandatory for our purpose
>> +try:
>> +os.set_inheritable(self.get_sock_fd(), True)
>> +except AttributeError:
>> +pass
> 
> Why did you decide to place this code inside is_scm_available()?
> 
> For reference, this is the only caller of is_scm_available():
> 
> def send_fd_scm(self, fd_file_path):
> # In iotest.py, the qmp should always use unix socket.
> assert self._qmp.is_scm_available()
> ...
> 
> In addition to making a method called is_*() have an unexpected
> side-effect,

True.  My idea was that a function that asks for SCM to be available
might as well make it available.

>  the method won't be called at all if running with
> debugging disabled.

Well, I sure hope we don't disable debugging in the iotests.  We use
assert quite a number of times there.

On the other hand, someone might want to use this outside of the iotests
but I don't even know whether that works, considering the SCM helper
program is part of the iotests.

> I suggest simply placing the os.set_inheritable() call inside
> send_fd_scm(), as close as possible to the subprocess.Popen()
> call.

Yes, I think you're right.  I didn't want to put it into send_fd_scm(),
because that method is only there to send some FD over QMP/SCM; it isn't
really supposed to send the QMP socket FD somewhere.  But sending
something over QMP/SCM is different from bequeathing something to a
child process (the socket_scm_helper).  And since send_fd_scm() needs to
bequeath the QMP socket FD to that helper, it should be responsible for
making it inheritable.

And maybe even more importantly, whether the socket allows for SCM
really has nothing to do with whether it's inheritable.  So it's
actually just wrong to put it here.

>>  return self.__sock.family == socket.AF_UNIX
>> diff --git a/tes

Re: [Qemu-block] [PATCH 5/9] iotests: Different iterator behavior in Python 3

2018-10-19 Thread Max Reitz
On 15.10.18 22:07, Eduardo Habkost wrote:
> On Mon, Oct 15, 2018 at 04:14:49PM +0200, Max Reitz wrote:
>> In Python 3, several functions now return iterators instead of lists.
>> This includes range(), items(), map(), and filter().  This means that if
>> we really want a list, we have to wrap those instances with list().  On
>> the other hand, sometimes we do just want an iterator, in which case we
>> have sometimes used xrange() and iteritems() which no longer exist in
>> Python 3.  Just change these calls to be range() and items(), which
>> costs a bit of performance in Python 2, but will do the right thing in
>> Python 3 (which is what is important).
>>
>> In one instance, we only wanted the first instance of the result of a
>> filter() call.  Instead of using next(filter()) which would work only in
>> Python 3, or list(filter())[0] which would work everywhere but is a bit
>> weird, this instance is changed to a single-line for with next() wrapped
>> around, which works both in 2.7 and 3.
>>
>> Signed-off-by: Max Reitz 
> 
> Reviewed-by: Eduardo Habkost 
> 
> Minor comments below:

[...]

>> diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065
>> index 72aa9707c7..a339bf6069 100755
>> --- a/tests/qemu-iotests/065
>> +++ b/tests/qemu-iotests/065
>> @@ -59,7 +59,7 @@ class TestQemuImgInfo(TestImageInfoSpecific):
>>  :data.index('')]
>>  for field in data:
>>  self.assertTrue(re.match('^ {4}[^ ]', field) is not None)
>> -data = map(lambda line: line.strip(), data)
>> +data = list(map(lambda line: line.strip(), data))
> 
> I would find this more readable:
> 
> data = [line.strip() for line in data]
> 
> Not a blocker, though.

Yes, I agree, that looks better.

>>  self.assertEqual(data, self.human_compare)
>>  
>>  class TestQMP(TestImageInfoSpecific):
>> @@ -80,7 +80,7 @@ class TestQMP(TestImageInfoSpecific):
>>  
>>  def test_qmp(self):
>>  result = self.vm.qmp('query-block')['return']
>> -drive = filter(lambda drive: drive['device'] == 'drive0', result)[0]
>> +drive = next(drive for drive in result if drive['device'] == 
>> 'drive0')
> 
> I didn't understand what you meant by "single-line for" on the
> commit message, until I saw the generator expression here.  :)

Maybe I should at least put quotes around the "for", because the
combination of "for with" really makes it difficult to read...

> This will raise an exception if there's no drive0 in the list,
> but that was already true on the original code.
> 
> 
>>  data = drive['inserted']['image']['format-specific']
>>  self.assertEqual(data['type'], iotests.imgfmt)
>>  self.assertEqual(data['data'], self.compare)
>> diff --git a/tests/qemu-iotests/124 b/tests/qemu-iotests/124
>> index 3ea4ac53f5..9f189e3b54 100755
>> --- a/tests/qemu-iotests/124
>> +++ b/tests/qemu-iotests/124
>> @@ -39,7 +39,7 @@ def try_remove(img):
>>  def transaction_action(action, **kwargs):
>>  return {
>>  'type': action,
>> -'data': dict((k.replace('_', '-'), v) for k, v in 
>> kwargs.iteritems())
>> +'data': dict((k.replace('_', '-'), v) for k, v in kwargs.items())
>>  }
>>  
>>  
>> @@ -134,7 +134,7 @@ class TestIncrementalBackupBase(iotests.QMPTestCase):
>>  def img_create(self, img, fmt=iotests.imgfmt, size='64M',
>> parent=None, parentFormat=None, **kwargs):
>>  optargs = []
>> -for k,v in kwargs.iteritems():
>> +for k,v in kwargs.items():
>>  optargs = optargs + ['-o', '%s=%s' % (k,v)]
>>  args = ['create', '-f', fmt] + optargs + [img, size]
>>  if parent:
>> diff --git a/tests/qemu-iotests/139 b/tests/qemu-iotests/139
>> index cc7fe337f3..e00f10b8c8 100755
>> --- a/tests/qemu-iotests/139
>> +++ b/tests/qemu-iotests/139
>> @@ -51,7 +51,7 @@ class TestBlockdevDel(iotests.QMPTestCase):
>>  # Check whether a BlockDriverState exists
>>  def checkBlockDriverState(self, node, must_exist = True):
>>  result = self.vm.qmp('query-named-block-nodes')
>> -nodes = filter(lambda x: x['node-name'] == node, result['return'])
>> +nodes = list(filter(lambda x: x['node-name'] == node, 
>> result['return']))
> 
> I'd prefer a list expression:
> 
> nodes = [x for x in result['return'] if x['node-name'] == node]
> 
> Also not a blocker.

I don't mind either way, so why not.

Max



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-block] [PATCH 3/9] iotests: Use Python byte strings where appropriate

2018-10-19 Thread Max Reitz
On 15.10.18 21:53, Eduardo Habkost wrote:
> On Mon, Oct 15, 2018 at 04:14:47PM +0200, Max Reitz wrote:
>> Since byte strings are no longer the default in Python 3, we have to
>> explicitly use them where we need to, which is mostly when working with
>> structures.  It also means that we need to open a file in binary mode
>> when we want to use structures.
>>
>> On the other hand, we have to accomodate for the fact that some
>> functions (still) work with byte strings but we want to use unicode
>> strings (in Python 3 at least, and it does not matter in Python 2).
>> This includes base64 encoding, but it is most notable when working with
>> the subprocess module: Either we set univeral_newlines to True so that
>> the default streams are opened in text mode (hence this parameter is
>> aliased as "text" as of 3.7), or, if that is not possible, we have to
>> decode the output to a normal string.
>>
>> Signed-off-by: Max Reitz 
> [...]
>> diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149
>> index 9e0cad76f9..1225334cb8 100755
>> --- a/tests/qemu-iotests/149
>> +++ b/tests/qemu-iotests/149
>> @@ -79,7 +79,7 @@ class LUKSConfig(object):
>>  
>>  def first_password_base64(self):
>>  (pw, slot) = self.first_password()
>> -return base64.b64encode(pw)
>> +return base64.b64encode(pw.encode('ascii')).decode('ascii')
> 
> Would we want to have a test case for non-ascii passwords in the
> future?  In that case you would probably need to make
> self.passwords[] contain byte strings instead of text.

I remember someone once providing a non-ASCII initial password to some
system for me.  I remember the system was running Windows, and I was
running Linux, so the system expected ISO-8859-1, while I was sending UTF-8.

The moral of the story is that you probably don't want non-ASCII
passwords.  And if we do want to test them, well, we'll need to decide
on an encoding then (or use byte strings, as you suggest).

> In either case, using 'ascii' as the encoding everywhere will
> ensure the code will not try to be too smart about string
> encodings if that happens.  I like that.
> 
> Reviewed-by: Eduardo Habkost 

Thanks for reviewing!

Max



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-block] [PATCH 8/9] iotests: Modify imports for Python 3

2018-10-19 Thread Max Reitz
On 15.10.18 20:59, Cleber Rosa wrote:
> 
> 
> On 10/15/18 10:14 AM, Max Reitz wrote:
>> There are two imports that need to be modified when running the iotests
>> under Python 3: One is StringIO, which no longer exists; instead, the
>> StringIO class comes from the io module, so import it from there.  The
>> other is the ConfigParser, which has just been renamed to configparser.
>>
>> Signed-off-by: Max Reitz 
>> ---
>>  tests/qemu-iotests/iotests.py| 8 ++--
>>  tests/qemu-iotests/nbd-fault-injector.py | 7 +--
>>  2 files changed, 11 insertions(+), 4 deletions(-)
>>
>> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
>> index 7ca94e9278..a64ea90fb4 100644
>> --- a/tests/qemu-iotests/iotests.py
>> +++ b/tests/qemu-iotests/iotests.py
>> @@ -683,13 +683,17 @@ def main(supported_fmts=[], supported_oses=['linux'], 
>> supported_cache_modes=[],
>>  
>>  # We need to filter out the time taken from the output so that 
>> qemu-iotest
>>  # can reliably diff the results against master output.
>> -import StringIO
>> +if sys.version_info.major >= 3:
>> +from io import StringIO
>> +else:
>> +from StringIO import StringIO
>> +
>>  if debug:
>>  output = sys.stdout
>>  verbosity = 2
>>  sys.argv.remove('-d')
>>  else:
>> -output = StringIO.StringIO()
>> +output = StringIO()
>>  
>>  logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
>>  
>> diff --git a/tests/qemu-iotests/nbd-fault-injector.py 
>> b/tests/qemu-iotests/nbd-fault-injector.py
>> index d45e2e0a6a..6b2d659dee 100755
>> --- a/tests/qemu-iotests/nbd-fault-injector.py
>> +++ b/tests/qemu-iotests/nbd-fault-injector.py
>> @@ -48,7 +48,10 @@ import sys
>>  import socket
>>  import struct
>>  import collections
>> -import ConfigParser
>> +if sys.version_info.major >= 3:
>> +import configparser
>> +else:
>> +import ConfigParser as configparser
>>  
>>  FAKE_DISK_SIZE = 8 * 1024 * 1024 * 1024 # 8 GB
>>  
>> @@ -225,7 +228,7 @@ def parse_config(config):
>>  return rules
>>  
>>  def load_rules(filename):
>> -config = ConfigParser.RawConfigParser()
>> +config = configparser.RawConfigParser()
>>  with open(filename, 'rt') as f:
>>  config.readfp(f, filename)
>>  return parse_config(config)
>>
> 
> This may be a type of culture clash (on my side, due to not enough QEMU
> culture), but shouldn't this be applied before anything else on this series?
> 
> I mean, PATCH 1/9 is supposed to fix the reliability aspects of
> nbd-fault-injector under Python 3, but without this patch, it won't
> actually run on Python 3.

I don't mind, I followed no specific order.  Well, patch 9 is patch 9
because it is the largest one, so I didn't want to discourage people
before the end of the series. :-)

Max



signature.asc
Description: OpenPGP digital signature