1 | The following changes since commit 5704c36d25ee84e7129722cb0db53df9faefe943: | 1 | The following changes since commit 4f59102571fce49af180cfc6d4cdd2b5df7bdb14: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/kraxel/tags/fixes-31-20181112-pull-request' into staging (2018-11-12 15:55:40 +0000) | 3 | Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-oct-01-2019' into staging (2019-10-01 16:21:42 +0100) |
4 | 4 | ||
5 | are available in the Git repository at: | 5 | are available in the Git repository at: |
6 | 6 | ||
7 | git://repo.or.cz/qemu/kevin.git tags/for-upstream | 7 | git://repo.or.cz/qemu/kevin.git tags/for-upstream |
8 | 8 | ||
9 | for you to fetch changes up to 1a42e5d8298d1b0f90d2254e7d559391dd3a45ca: | 9 | for you to fetch changes up to 7e693a0500455edab21754573c32b7146138cffd: |
10 | 10 | ||
11 | Merge remote-tracking branch 'mreitz/tags/pull-block-2018-11-12' into queue-block (2018-11-12 17:57:32 +0100) | 11 | iotests: Remove Python 2 compatibility code (2019-10-04 11:59:16 +0200) |
12 | 12 | ||
13 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
14 | Block layer patches: | 14 | Block layer patches: |
15 | 15 | ||
16 | - file-posix: Don't waste a file descriptor for locking, don't lock the | 16 | - Fix internal snapshots with typical -blockdev setups |
17 | same bit multiple times | 17 | - iotests: Require Python 3.6 or later |
18 | - nvme: Fix double free and memory leak | ||
19 | - Misc error handling fixes | ||
20 | - Added NULL checks found by static analysis | ||
21 | - Allow more block drivers to not be included in the qemu build | ||
22 | 18 | ||
23 | ---------------------------------------------------------------- | 19 | ---------------------------------------------------------------- |
24 | Fam Zheng (4): | 20 | Kevin Wolf (4): |
25 | file-posix: Use error API properly | 21 | block/snapshot: Restrict set of snapshot nodes |
26 | file-posix: Skip effectiveless OFD lock operations | 22 | iotests: Test internal snapshots with -blockdev |
27 | file-posix: Drop s->lock_fd | 23 | iotests: Require Python 3.6 or later |
28 | tests: Add unit tests for image locking | 24 | iotests: Remove Python 2 compatibility code |
29 | 25 | ||
30 | Jeff Cody (1): | 26 | block/snapshot.c | 26 ++++-- |
31 | block: Make more block drivers compile-time configurable | 27 | tests/qemu-iotests/044 | 3 - |
28 | tests/qemu-iotests/163 | 3 - | ||
29 | tests/qemu-iotests/267 | 168 ++++++++++++++++++++++++++++++++++++ | ||
30 | tests/qemu-iotests/267.out | 182 +++++++++++++++++++++++++++++++++++++++ | ||
31 | tests/qemu-iotests/check | 13 ++- | ||
32 | tests/qemu-iotests/common.filter | 11 ++- | ||
33 | tests/qemu-iotests/group | 1 + | ||
34 | tests/qemu-iotests/iotests.py | 13 +-- | ||
35 | 9 files changed, 392 insertions(+), 28 deletions(-) | ||
36 | create mode 100755 tests/qemu-iotests/267 | ||
37 | create mode 100644 tests/qemu-iotests/267.out | ||
32 | 38 | ||
33 | Kevin Wolf (1): | ||
34 | Merge remote-tracking branch 'mreitz/tags/pull-block-2018-11-12' into queue-block | ||
35 | |||
36 | Li Qiang (2): | ||
37 | nvme: don't unref ctrl_mem when device unrealized | ||
38 | nvme: free cmbuf in nvme_exit | ||
39 | |||
40 | Liam Merwick (5): | ||
41 | job: Fix off-by-one assert checks for JobSTT and JobVerbTable | ||
42 | block: Null pointer dereference in blk_root_get_parent_desc() | ||
43 | qemu-img: assert block_job_get() does not return NULL in img_commit() | ||
44 | block: Fix potential Null pointer dereferences in vvfat.c | ||
45 | qcow2: Read outside array bounds in qcow2_pre_write_overlap_check() | ||
46 | |||
47 | Peter Maydell (1): | ||
48 | blockdev: Consistently use snapshot_node_name in external_snapshot_prepare() | ||
49 | |||
50 | zhenwei pi (1): | ||
51 | blockdev: handle error on block latency histogram set error | ||
52 | |||
53 | configure | 91 ++++++++++++++++++++++++++ | ||
54 | block/block-backend.c | 3 +- | ||
55 | block/file-posix.c | 122 ++++++++++++++++++++--------------- | ||
56 | block/qcow2-refcount.c | 18 +++--- | ||
57 | block/vvfat.c | 46 ++++++++----- | ||
58 | blockdev.c | 21 ++++-- | ||
59 | hw/block/nvme.c | 6 +- | ||
60 | job.c | 4 +- | ||
61 | qemu-img.c | 1 + | ||
62 | tests/test-image-locking.c | 157 +++++++++++++++++++++++++++++++++++++++++++++ | ||
63 | block/Makefile.objs | 22 +++++-- | ||
64 | tests/Makefile.include | 2 + | ||
65 | 12 files changed, 400 insertions(+), 93 deletions(-) | ||
66 | create mode 100644 tests/test-image-locking.c | ||
67 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Fam Zheng <famz@redhat.com> | ||
2 | 1 | ||
3 | Use error_report for situations that affect user operation (i.e. we're | ||
4 | actually returning error), and warn_report/warn_report_err when some | ||
5 | less critical error happened but the user operation can still carry on. | ||
6 | |||
7 | For raw_normalize_devicepath, add Error parameter to propagate to | ||
8 | its callers. | ||
9 | |||
10 | Suggested-by: Markus Armbruster <armbru@redhat.com> | ||
11 | Signed-off-by: Fam Zheng <famz@redhat.com> | ||
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
13 | --- | ||
14 | block/file-posix.c | 39 ++++++++++++++++----------------------- | ||
15 | 1 file changed, 16 insertions(+), 23 deletions(-) | ||
16 | |||
17 | diff --git a/block/file-posix.c b/block/file-posix.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/block/file-posix.c | ||
20 | +++ b/block/file-posix.c | ||
21 | @@ -XXX,XX +XXX,XX @@ static int cdrom_reopen(BlockDriverState *bs); | ||
22 | #endif | ||
23 | |||
24 | #if defined(__NetBSD__) | ||
25 | -static int raw_normalize_devicepath(const char **filename) | ||
26 | +static int raw_normalize_devicepath(const char **filename, Error **errp) | ||
27 | { | ||
28 | static char namebuf[PATH_MAX]; | ||
29 | const char *dp, *fname; | ||
30 | @@ -XXX,XX +XXX,XX @@ static int raw_normalize_devicepath(const char **filename) | ||
31 | fname = *filename; | ||
32 | dp = strrchr(fname, '/'); | ||
33 | if (lstat(fname, &sb) < 0) { | ||
34 | - fprintf(stderr, "%s: stat failed: %s\n", | ||
35 | - fname, strerror(errno)); | ||
36 | + error_setg_errno(errp, errno, "%s: stat failed", fname); | ||
37 | return -errno; | ||
38 | } | ||
39 | |||
40 | @@ -XXX,XX +XXX,XX @@ static int raw_normalize_devicepath(const char **filename) | ||
41 | snprintf(namebuf, PATH_MAX, "%.*s/r%s", | ||
42 | (int)(dp - fname), fname, dp + 1); | ||
43 | } | ||
44 | - fprintf(stderr, "%s is a block device", fname); | ||
45 | *filename = namebuf; | ||
46 | - fprintf(stderr, ", using %s\n", *filename); | ||
47 | + warn_report("%s is a block device, using %s", fname, *filename); | ||
48 | |||
49 | return 0; | ||
50 | } | ||
51 | #else | ||
52 | -static int raw_normalize_devicepath(const char **filename) | ||
53 | +static int raw_normalize_devicepath(const char **filename, Error **errp) | ||
54 | { | ||
55 | return 0; | ||
56 | } | ||
57 | @@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options, | ||
58 | |||
59 | filename = qemu_opt_get(opts, "filename"); | ||
60 | |||
61 | - ret = raw_normalize_devicepath(&filename); | ||
62 | + ret = raw_normalize_devicepath(&filename, errp); | ||
63 | if (ret != 0) { | ||
64 | - error_setg_errno(errp, -ret, "Could not normalize device path"); | ||
65 | goto fail; | ||
66 | } | ||
67 | |||
68 | @@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options, | ||
69 | case ON_OFF_AUTO_ON: | ||
70 | s->use_lock = true; | ||
71 | if (!qemu_has_ofd_lock()) { | ||
72 | - fprintf(stderr, | ||
73 | - "File lock requested but OFD locking syscall is " | ||
74 | - "unavailable, falling back to POSIX file locks.\n" | ||
75 | - "Due to the implementation, locks can be lost " | ||
76 | - "unexpectedly.\n"); | ||
77 | + warn_report("File lock requested but OFD locking syscall is " | ||
78 | + "unavailable, falling back to POSIX file locks"); | ||
79 | + error_printf("Due to the implementation, locks can be lost " | ||
80 | + "unexpectedly.\n"); | ||
81 | } | ||
82 | break; | ||
83 | case ON_OFF_AUTO_OFF: | ||
84 | @@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs, | ||
85 | /* Theoretically the above call only unlocks bytes and it cannot | ||
86 | * fail. Something weird happened, report it. | ||
87 | */ | ||
88 | - error_report_err(local_err); | ||
89 | + warn_report_err(local_err); | ||
90 | } | ||
91 | break; | ||
92 | case RAW_PL_COMMIT: | ||
93 | @@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs, | ||
94 | /* Theoretically the above call only unlocks bytes and it cannot | ||
95 | * fail. Something weird happened, report it. | ||
96 | */ | ||
97 | - error_report_err(local_err); | ||
98 | + warn_report_err(local_err); | ||
99 | } | ||
100 | break; | ||
101 | } | ||
102 | @@ -XXX,XX +XXX,XX @@ static int raw_reopen_prepare(BDRVReopenState *state, | ||
103 | /* If we cannot use fcntl, or fcntl failed, fall back to qemu_open() */ | ||
104 | if (rs->fd == -1) { | ||
105 | const char *normalized_filename = state->bs->filename; | ||
106 | - ret = raw_normalize_devicepath(&normalized_filename); | ||
107 | - if (ret < 0) { | ||
108 | - error_setg_errno(errp, -ret, "Could not normalize device path"); | ||
109 | - } else { | ||
110 | + ret = raw_normalize_devicepath(&normalized_filename, errp); | ||
111 | + if (ret >= 0) { | ||
112 | assert(!(rs->open_flags & O_CREAT)); | ||
113 | rs->fd = qemu_open(normalized_filename, rs->open_flags); | ||
114 | if (rs->fd == -1) { | ||
115 | @@ -XXX,XX +XXX,XX @@ static int aio_worker(void *arg) | ||
116 | ret = handle_aiocb_truncate(aiocb); | ||
117 | break; | ||
118 | default: | ||
119 | - fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type); | ||
120 | + error_report("invalid aio request (0x%x)", aiocb->aio_type); | ||
121 | ret = -EINVAL; | ||
122 | break; | ||
123 | } | ||
124 | @@ -XXX,XX +XXX,XX @@ out_unlock: | ||
125 | * not mean the whole creation operation has failed. So | ||
126 | * report it the user for their convenience, but do not report | ||
127 | * it to the caller. */ | ||
128 | - error_report_err(local_err); | ||
129 | + warn_report_err(local_err); | ||
130 | } | ||
131 | |||
132 | out_close: | ||
133 | @@ -XXX,XX +XXX,XX @@ static int coroutine_fn hdev_co_create_opts(const char *filename, QemuOpts *opts | ||
134 | |||
135 | (void)has_prefix; | ||
136 | |||
137 | - ret = raw_normalize_devicepath(&filename); | ||
138 | + ret = raw_normalize_devicepath(&filename, errp); | ||
139 | if (ret < 0) { | ||
140 | - error_setg_errno(errp, -ret, "Could not normalize device path"); | ||
141 | return ret; | ||
142 | } | ||
143 | |||
144 | -- | ||
145 | 2.19.1 | ||
146 | |||
147 | diff view generated by jsdifflib |
1 | From: Liam Merwick <Liam.Merwick@oracle.com> | 1 | Nodes involved in internal snapshots were those that were returned by |
---|---|---|---|
2 | bdrv_next(), inserted and not read-only. bdrv_next() in turn returns all | ||
3 | nodes that are either the root node of a BlockBackend or monitor-owned | ||
4 | nodes. | ||
2 | 5 | ||
3 | The calls to find_mapping_for_cluster() may return NULL but it | 6 | With the typical -drive use, this worked well enough. However, in the |
4 | isn't always checked for before dereferencing the value returned. | 7 | typical -blockdev case, the user defines one node per option, making all |
5 | Additionally, add some asserts to cover cases where NULL can't | 8 | nodes monitor-owned nodes. This includes protocol nodes etc. which often |
6 | be returned but which might not be obvious at first glance. | 9 | are not snapshottable, so "savevm" only returns an error. |
7 | 10 | ||
8 | Signed-off-by: Liam Merwick <Liam.Merwick@oracle.com> | 11 | Change the conditions so that internal snapshot still include all nodes |
9 | Message-id: 1541453919-25973-5-git-send-email-Liam.Merwick@oracle.com | 12 | that have a BlockBackend attached (we definitely want to snapshot |
10 | [mreitz: Dropped superfluous check of "mapping" following an assertion | 13 | anything attached to a guest device and probably also the built-in NBD |
11 | that it is not NULL, and fixed some indentation] | 14 | server; snapshotting block job BlockBackends is more of an accident, but |
12 | Signed-off-by: Max Reitz <mreitz@redhat.com> | 15 | a preexisting one), but other monitor-owned nodes are only included if |
16 | they have no parents. | ||
17 | |||
18 | This makes internal snapshots usable again with typical -blockdev | ||
19 | configurations. | ||
20 | |||
21 | Cc: qemu-stable@nongnu.org | ||
22 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
23 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
24 | Reviewed-by: Peter Krempa <pkrempa@redhat.com> | ||
25 | Tested-by: Peter Krempa <pkrempa@redhat.com> | ||
13 | --- | 26 | --- |
14 | block/vvfat.c | 46 ++++++++++++++++++++++++++++++---------------- | 27 | block/snapshot.c | 26 +++++++++++++++++++------- |
15 | 1 file changed, 30 insertions(+), 16 deletions(-) | 28 | 1 file changed, 19 insertions(+), 7 deletions(-) |
16 | 29 | ||
17 | diff --git a/block/vvfat.c b/block/vvfat.c | 30 | diff --git a/block/snapshot.c b/block/snapshot.c |
18 | index XXXXXXX..XXXXXXX 100644 | 31 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/block/vvfat.c | 32 | --- a/block/snapshot.c |
20 | +++ b/block/vvfat.c | 33 | +++ b/block/snapshot.c |
21 | @@ -XXX,XX +XXX,XX @@ static inline void array_free(array_t* array) | 34 | @@ -XXX,XX +XXX,XX @@ |
22 | /* does not automatically grow */ | 35 | #include "qapi/qmp/qerror.h" |
23 | static inline void* array_get(array_t* array,unsigned int index) { | 36 | #include "qapi/qmp/qstring.h" |
24 | assert(index < array->next); | 37 | #include "qemu/option.h" |
25 | + assert(array->pointer); | 38 | +#include "sysemu/block-backend.h" |
26 | return array->pointer + index * array->item_size; | 39 | |
40 | QemuOptsList internal_snapshot_opts = { | ||
41 | .name = "snapshot", | ||
42 | @@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs, | ||
43 | return ret; | ||
27 | } | 44 | } |
28 | 45 | ||
29 | -static inline int array_ensure_allocated(array_t* array, int index) | 46 | +static bool bdrv_all_snapshots_includes_bs(BlockDriverState *bs) |
30 | +static inline void array_ensure_allocated(array_t *array, int index) | 47 | +{ |
31 | { | 48 | + if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) { |
32 | if((index + 1) * array->item_size > array->size) { | 49 | + return false; |
33 | int new_size = (index + 32) * array->item_size; | ||
34 | array->pointer = g_realloc(array->pointer, new_size); | ||
35 | - if (!array->pointer) | ||
36 | - return -1; | ||
37 | + assert(array->pointer); | ||
38 | memset(array->pointer + array->size, 0, new_size - array->size); | ||
39 | array->size = new_size; | ||
40 | array->next = index + 1; | ||
41 | } | ||
42 | - | ||
43 | - return 0; | ||
44 | } | ||
45 | |||
46 | static inline void* array_get_next(array_t* array) { | ||
47 | unsigned int next = array->next; | ||
48 | |||
49 | - if (array_ensure_allocated(array, next) < 0) | ||
50 | - return NULL; | ||
51 | - | ||
52 | + array_ensure_allocated(array, next); | ||
53 | array->next = next + 1; | ||
54 | return array_get(array, next); | ||
55 | } | ||
56 | @@ -XXX,XX +XXX,XX @@ static int commit_direntries(BDRVVVFATState* s, | ||
57 | direntry_t* direntry = array_get(&(s->directory), dir_index); | ||
58 | uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry); | ||
59 | mapping_t* mapping = find_mapping_for_cluster(s, first_cluster); | ||
60 | - | ||
61 | int factor = 0x10 * s->sectors_per_cluster; | ||
62 | int old_cluster_count, new_cluster_count; | ||
63 | - int current_dir_index = mapping->info.dir.first_dir_index; | ||
64 | - int first_dir_index = current_dir_index; | ||
65 | + int current_dir_index; | ||
66 | + int first_dir_index; | ||
67 | int ret, i; | ||
68 | uint32_t c; | ||
69 | |||
70 | -DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapping->path, parent_mapping_index)); | ||
71 | - | ||
72 | assert(direntry); | ||
73 | assert(mapping); | ||
74 | assert(mapping->begin == first_cluster); | ||
75 | @@ -XXX,XX +XXX,XX @@ DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapp | ||
76 | assert(mapping->mode & MODE_DIRECTORY); | ||
77 | assert(dir_index == 0 || is_directory(direntry)); | ||
78 | |||
79 | + DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", | ||
80 | + mapping->path, parent_mapping_index)); | ||
81 | + | ||
82 | + current_dir_index = mapping->info.dir.first_dir_index; | ||
83 | + first_dir_index = current_dir_index; | ||
84 | mapping->info.dir.parent_mapping_index = parent_mapping_index; | ||
85 | |||
86 | if (first_cluster == 0) { | ||
87 | @@ -XXX,XX +XXX,XX @@ DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapp | ||
88 | direntry = array_get(&(s->directory), first_dir_index + i); | ||
89 | if (is_directory(direntry) && !is_dot(direntry)) { | ||
90 | mapping = find_mapping_for_cluster(s, first_cluster); | ||
91 | + if (mapping == NULL) { | ||
92 | + return -1; | ||
93 | + } | ||
94 | assert(mapping->mode & MODE_DIRECTORY); | ||
95 | ret = commit_direntries(s, first_dir_index + i, | ||
96 | array_index(&(s->mapping), mapping)); | ||
97 | @@ -XXX,XX +XXX,XX @@ static int commit_one_file(BDRVVVFATState* s, | ||
98 | assert(offset < size); | ||
99 | assert((offset % s->cluster_size) == 0); | ||
100 | |||
101 | + if (mapping == NULL) { | ||
102 | + return -1; | ||
103 | + } | 50 | + } |
104 | + | 51 | + |
105 | for (i = s->cluster_size; i < offset; i += s->cluster_size) | 52 | + /* Include all nodes that are either in use by a BlockBackend, or that |
106 | c = modified_fat_get(s, c); | 53 | + * aren't attached to any node, but owned by the monitor. */ |
107 | 54 | + return bdrv_has_blk(bs) || QLIST_EMPTY(&bs->parents); | |
108 | @@ -XXX,XX +XXX,XX @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s) | 55 | +} |
109 | if (commit->action == ACTION_RENAME) { | 56 | |
110 | mapping_t* mapping = find_mapping_for_cluster(s, | 57 | /* Group operations. All block drivers are involved. |
111 | commit->param.rename.cluster); | 58 | * These functions will properly handle dataplane (take aio_context_acquire |
112 | - char* old_path = mapping->path; | 59 | @@ -XXX,XX +XXX,XX @@ bool bdrv_all_can_snapshot(BlockDriverState **first_bad_bs) |
113 | + char *old_path; | 60 | AioContext *ctx = bdrv_get_aio_context(bs); |
114 | 61 | ||
115 | + if (mapping == NULL) { | 62 | aio_context_acquire(ctx); |
116 | + return -1; | 63 | - if (bdrv_is_inserted(bs) && !bdrv_is_read_only(bs)) { |
117 | + } | 64 | + if (bdrv_all_snapshots_includes_bs(bs)) { |
118 | + old_path = mapping->path; | 65 | ok = bdrv_can_snapshot(bs); |
119 | assert(commit->path); | 66 | } |
120 | mapping->path = commit->path; | 67 | aio_context_release(ctx); |
121 | if (rename(old_path, mapping->path)) | 68 | @@ -XXX,XX +XXX,XX @@ int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bad_bs, |
122 | @@ -XXX,XX +XXX,XX @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s) | 69 | AioContext *ctx = bdrv_get_aio_context(bs); |
123 | direntry_t* d = direntry + i; | 70 | |
124 | 71 | aio_context_acquire(ctx); | |
125 | if (is_file(d) || (is_directory(d) && !is_dot(d))) { | 72 | - if (bdrv_can_snapshot(bs) && |
126 | + int l; | 73 | - bdrv_snapshot_find(bs, snapshot, name) >= 0) { |
127 | + char *new_path; | 74 | + if (bdrv_all_snapshots_includes_bs(bs) && |
128 | mapping_t* m = find_mapping_for_cluster(s, | 75 | + bdrv_snapshot_find(bs, snapshot, name) >= 0) |
129 | begin_of_direntry(d)); | 76 | + { |
130 | - int l = strlen(m->path); | 77 | ret = bdrv_snapshot_delete(bs, snapshot->id_str, |
131 | - char* new_path = g_malloc(l + diff + 1); | 78 | snapshot->name, err); |
132 | + if (m == NULL) { | 79 | } |
133 | + return -1; | 80 | @@ -XXX,XX +XXX,XX @@ int bdrv_all_goto_snapshot(const char *name, BlockDriverState **first_bad_bs, |
134 | + } | 81 | AioContext *ctx = bdrv_get_aio_context(bs); |
135 | + l = strlen(m->path); | 82 | |
136 | + new_path = g_malloc(l + diff + 1); | 83 | aio_context_acquire(ctx); |
137 | 84 | - if (bdrv_can_snapshot(bs)) { | |
138 | assert(!strncmp(m->path, mapping->path, l2)); | 85 | + if (bdrv_all_snapshots_includes_bs(bs)) { |
139 | 86 | ret = bdrv_snapshot_goto(bs, name, errp); | |
87 | } | ||
88 | aio_context_release(ctx); | ||
89 | @@ -XXX,XX +XXX,XX @@ int bdrv_all_find_snapshot(const char *name, BlockDriverState **first_bad_bs) | ||
90 | AioContext *ctx = bdrv_get_aio_context(bs); | ||
91 | |||
92 | aio_context_acquire(ctx); | ||
93 | - if (bdrv_can_snapshot(bs)) { | ||
94 | + if (bdrv_all_snapshots_includes_bs(bs)) { | ||
95 | err = bdrv_snapshot_find(bs, &sn, name); | ||
96 | } | ||
97 | aio_context_release(ctx); | ||
98 | @@ -XXX,XX +XXX,XX @@ int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn, | ||
99 | if (bs == vm_state_bs) { | ||
100 | sn->vm_state_size = vm_state_size; | ||
101 | err = bdrv_snapshot_create(bs, sn); | ||
102 | - } else if (bdrv_can_snapshot(bs)) { | ||
103 | + } else if (bdrv_all_snapshots_includes_bs(bs)) { | ||
104 | sn->vm_state_size = 0; | ||
105 | err = bdrv_snapshot_create(bs, sn); | ||
106 | } | ||
107 | @@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_all_find_vmstate_bs(void) | ||
108 | bool found; | ||
109 | |||
110 | aio_context_acquire(ctx); | ||
111 | - found = bdrv_can_snapshot(bs); | ||
112 | + found = bdrv_all_snapshots_includes_bs(bs) && bdrv_can_snapshot(bs); | ||
113 | aio_context_release(ctx); | ||
114 | |||
115 | if (found) { | ||
140 | -- | 116 | -- |
141 | 2.19.1 | 117 | 2.20.1 |
142 | 118 | ||
143 | 119 | diff view generated by jsdifflib |
1 | From: Fam Zheng <famz@redhat.com> | 1 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
---|---|---|---|
2 | Reviewed-by: Peter Krempa <pkrempa@redhat.com> | ||
3 | Tested-by: Peter Krempa <pkrempa@redhat.com> | ||
4 | --- | ||
5 | tests/qemu-iotests/267 | 168 ++++++++++++++++++++++++++++ | ||
6 | tests/qemu-iotests/267.out | 182 +++++++++++++++++++++++++++++++ | ||
7 | tests/qemu-iotests/common.filter | 11 +- | ||
8 | tests/qemu-iotests/group | 1 + | ||
9 | 4 files changed, 358 insertions(+), 4 deletions(-) | ||
10 | create mode 100755 tests/qemu-iotests/267 | ||
11 | create mode 100644 tests/qemu-iotests/267.out | ||
2 | 12 | ||
3 | Signed-off-by: Fam Zheng <famz@redhat.com> | 13 | diff --git a/tests/qemu-iotests/267 b/tests/qemu-iotests/267 |
4 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 14 | new file mode 100755 |
5 | --- | 15 | index XXXXXXX..XXXXXXX |
6 | tests/test-image-locking.c | 157 +++++++++++++++++++++++++++++++++++++ | 16 | --- /dev/null |
7 | tests/Makefile.include | 2 + | 17 | +++ b/tests/qemu-iotests/267 |
8 | 2 files changed, 159 insertions(+) | 18 | @@ -XXX,XX +XXX,XX @@ |
9 | create mode 100644 tests/test-image-locking.c | 19 | +#!/usr/bin/env bash |
10 | 20 | +# | |
11 | diff --git a/tests/test-image-locking.c b/tests/test-image-locking.c | 21 | +# Test which nodes are involved in internal snapshots |
22 | +# | ||
23 | +# Copyright (C) 2019 Red Hat, Inc. | ||
24 | +# | ||
25 | +# This program is free software; you can redistribute it and/or modify | ||
26 | +# it under the terms of the GNU General Public License as published by | ||
27 | +# the Free Software Foundation; either version 2 of the License, or | ||
28 | +# (at your option) any later version. | ||
29 | +# | ||
30 | +# This program is distributed in the hope that it will be useful, | ||
31 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
32 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
33 | +# GNU General Public License for more details. | ||
34 | +# | ||
35 | +# You should have received a copy of the GNU General Public License | ||
36 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
37 | +# | ||
38 | + | ||
39 | +# creator | ||
40 | +owner=kwolf@redhat.com | ||
41 | + | ||
42 | +seq=`basename $0` | ||
43 | +echo "QA output created by $seq" | ||
44 | + | ||
45 | +status=1 # failure is the default! | ||
46 | + | ||
47 | +_cleanup() | ||
48 | +{ | ||
49 | + _cleanup_test_img | ||
50 | + rm -f "$TEST_DIR/nbd" | ||
51 | +} | ||
52 | +trap "_cleanup; exit \$status" 0 1 2 3 15 | ||
53 | + | ||
54 | +# get standard environment, filters and checks | ||
55 | +. ./common.rc | ||
56 | +. ./common.filter | ||
57 | + | ||
58 | +_supported_fmt qcow2 | ||
59 | +_supported_proto file | ||
60 | +_supported_os Linux | ||
61 | + | ||
62 | +# Internal snapshots are (currently) impossible with refcount_bits=1 | ||
63 | +_unsupported_imgopts 'refcount_bits=1[^0-9]' | ||
64 | + | ||
65 | +do_run_qemu() | ||
66 | +{ | ||
67 | + echo Testing: "$@" | ||
68 | + ( | ||
69 | + if ! test -t 0; then | ||
70 | + while read cmd; do | ||
71 | + echo $cmd | ||
72 | + done | ||
73 | + fi | ||
74 | + echo quit | ||
75 | + ) | $QEMU -nographic -monitor stdio -nodefaults "$@" | ||
76 | + echo | ||
77 | +} | ||
78 | + | ||
79 | +run_qemu() | ||
80 | +{ | ||
81 | + do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_hmp | | ||
82 | + _filter_generated_node_ids | _filter_imgfmt | _filter_vmstate_size | ||
83 | +} | ||
84 | + | ||
85 | +size=128M | ||
86 | + | ||
87 | +run_test() | ||
88 | +{ | ||
89 | + _make_test_img $size | ||
90 | + printf "savevm snap0\ninfo snapshots\nloadvm snap0\n" | run_qemu "$@" | _filter_date | ||
91 | +} | ||
92 | + | ||
93 | + | ||
94 | +echo | ||
95 | +echo "=== No block devices at all ===" | ||
96 | +echo | ||
97 | + | ||
98 | +run_test | ||
99 | + | ||
100 | +echo | ||
101 | +echo "=== -drive if=none ===" | ||
102 | +echo | ||
103 | + | ||
104 | +run_test -drive driver=file,file="$TEST_IMG",if=none | ||
105 | +run_test -drive driver=$IMGFMT,file="$TEST_IMG",if=none | ||
106 | +run_test -drive driver=$IMGFMT,file="$TEST_IMG",if=none -device virtio-blk,drive=none0 | ||
107 | + | ||
108 | +echo | ||
109 | +echo "=== -drive if=virtio ===" | ||
110 | +echo | ||
111 | + | ||
112 | +run_test -drive driver=file,file="$TEST_IMG",if=virtio | ||
113 | +run_test -drive driver=$IMGFMT,file="$TEST_IMG",if=virtio | ||
114 | + | ||
115 | +echo | ||
116 | +echo "=== Simple -blockdev ===" | ||
117 | +echo | ||
118 | + | ||
119 | +run_test -blockdev driver=file,filename="$TEST_IMG",node-name=file | ||
120 | +run_test -blockdev driver=file,filename="$TEST_IMG",node-name=file \ | ||
121 | + -blockdev driver=$IMGFMT,file=file,node-name=fmt | ||
122 | +run_test -blockdev driver=file,filename="$TEST_IMG",node-name=file \ | ||
123 | + -blockdev driver=raw,file=file,node-name=raw \ | ||
124 | + -blockdev driver=$IMGFMT,file=raw,node-name=fmt | ||
125 | + | ||
126 | +echo | ||
127 | +echo "=== -blockdev with a filter on top ===" | ||
128 | +echo | ||
129 | + | ||
130 | +run_test -blockdev driver=file,filename="$TEST_IMG",node-name=file \ | ||
131 | + -blockdev driver=$IMGFMT,file=file,node-name=fmt \ | ||
132 | + -blockdev driver=copy-on-read,file=fmt,node-name=filter | ||
133 | + | ||
134 | +echo | ||
135 | +echo "=== -blockdev with a backing file ===" | ||
136 | +echo | ||
137 | + | ||
138 | +TEST_IMG="$TEST_IMG.base" _make_test_img $size | ||
139 | + | ||
140 | +IMGOPTS="backing_file=$TEST_IMG.base" \ | ||
141 | +run_test -blockdev driver=file,filename="$TEST_IMG.base",node-name=backing-file \ | ||
142 | + -blockdev driver=file,filename="$TEST_IMG",node-name=file \ | ||
143 | + -blockdev driver=$IMGFMT,file=file,backing=backing-file,node-name=fmt | ||
144 | + | ||
145 | +IMGOPTS="backing_file=$TEST_IMG.base" \ | ||
146 | +run_test -blockdev driver=file,filename="$TEST_IMG.base",node-name=backing-file \ | ||
147 | + -blockdev driver=$IMGFMT,file=backing-file,node-name=backing-fmt \ | ||
148 | + -blockdev driver=file,filename="$TEST_IMG",node-name=file \ | ||
149 | + -blockdev driver=$IMGFMT,file=file,backing=backing-fmt,node-name=fmt | ||
150 | + | ||
151 | +# A snapshot should be present on the overlay, but not the backing file | ||
152 | +echo Internal snapshots on overlay: | ||
153 | +$QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | _filter_vmstate_size | ||
154 | + | ||
155 | +echo Internal snapshots on backing file: | ||
156 | +$QEMU_IMG snapshot -l "$TEST_IMG.base" | _filter_date | _filter_vmstate_size | ||
157 | + | ||
158 | +echo | ||
159 | +echo "=== -blockdev with NBD server on the backing file ===" | ||
160 | +echo | ||
161 | + | ||
162 | +IMGOPTS="backing_file=$TEST_IMG.base" _make_test_img $size | ||
163 | +cat <<EOF | | ||
164 | +nbd_server_start unix:$TEST_DIR/nbd | ||
165 | +nbd_server_add -w backing-fmt | ||
166 | +savevm snap0 | ||
167 | +info snapshots | ||
168 | +loadvm snap0 | ||
169 | +EOF | ||
170 | +run_qemu -blockdev driver=file,filename="$TEST_IMG.base",node-name=backing-file \ | ||
171 | + -blockdev driver=$IMGFMT,file=backing-file,node-name=backing-fmt \ | ||
172 | + -blockdev driver=file,filename="$TEST_IMG",node-name=file \ | ||
173 | + -blockdev driver=$IMGFMT,file=file,backing=backing-fmt,node-name=fmt | | ||
174 | + _filter_date | ||
175 | + | ||
176 | +# This time, a snapshot should be created on both files | ||
177 | +echo Internal snapshots on overlay: | ||
178 | +$QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | _filter_vmstate_size | ||
179 | + | ||
180 | +echo Internal snapshots on backing file: | ||
181 | +$QEMU_IMG snapshot -l "$TEST_IMG.base" | _filter_date | _filter_vmstate_size | ||
182 | + | ||
183 | +# success, all done | ||
184 | +echo "*** done" | ||
185 | +rm -f $seq.full | ||
186 | +status=0 | ||
187 | diff --git a/tests/qemu-iotests/267.out b/tests/qemu-iotests/267.out | ||
12 | new file mode 100644 | 188 | new file mode 100644 |
13 | index XXXXXXX..XXXXXXX | 189 | index XXXXXXX..XXXXXXX |
14 | --- /dev/null | 190 | --- /dev/null |
15 | +++ b/tests/test-image-locking.c | 191 | +++ b/tests/qemu-iotests/267.out |
16 | @@ -XXX,XX +XXX,XX @@ | 192 | @@ -XXX,XX +XXX,XX @@ |
17 | +/* | 193 | +QA output created by 267 |
18 | + * Image locking tests | 194 | + |
19 | + * | 195 | +=== No block devices at all === |
20 | + * Copyright (c) 2018 Red Hat Inc. | 196 | + |
21 | + * | 197 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 |
22 | + * Author: Fam Zheng <famz@redhat.com> | 198 | +Testing: |
23 | + * | 199 | +QEMU X.Y.Z monitor - type 'help' for more information |
24 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | 200 | +(qemu) savevm snap0 |
25 | + * of this software and associated documentation files (the "Software"), to deal | 201 | +Error: No block device can accept snapshots |
26 | + * in the Software without restriction, including without limitation the rights | 202 | +(qemu) info snapshots |
27 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 203 | +No available block device supports snapshots |
28 | + * copies of the Software, and to permit persons to whom the Software is | 204 | +(qemu) loadvm snap0 |
29 | + * furnished to do so, subject to the following conditions: | 205 | +Error: No block device supports snapshots |
30 | + * | 206 | +(qemu) quit |
31 | + * The above copyright notice and this permission notice shall be included in | 207 | + |
32 | + * all copies or substantial portions of the Software. | 208 | + |
33 | + * | 209 | +=== -drive if=none === |
34 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 210 | + |
35 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 211 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 |
36 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | 212 | +Testing: -drive driver=file,file=TEST_DIR/t.IMGFMT,if=none |
37 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 213 | +QEMU X.Y.Z monitor - type 'help' for more information |
38 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 214 | +(qemu) savevm snap0 |
39 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 215 | +Error: Device 'none0' is writable but does not support snapshots |
40 | + * THE SOFTWARE. | 216 | +(qemu) info snapshots |
41 | + */ | 217 | +No available block device supports snapshots |
42 | + | 218 | +(qemu) loadvm snap0 |
43 | +#include "qemu/osdep.h" | 219 | +Error: Device 'none0' is writable but does not support snapshots |
44 | +#include "block/block.h" | 220 | +(qemu) quit |
45 | +#include "sysemu/block-backend.h" | 221 | + |
46 | +#include "qapi/error.h" | 222 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 |
47 | +#include "qapi/qmp/qdict.h" | 223 | +Testing: -drive driver=IMGFMT,file=TEST_DIR/t.IMGFMT,if=none |
48 | + | 224 | +QEMU X.Y.Z monitor - type 'help' for more information |
49 | +static BlockBackend *open_image(const char *path, | 225 | +(qemu) savevm snap0 |
50 | + uint64_t perm, uint64_t shared_perm, | 226 | +(qemu) info snapshots |
51 | + Error **errp) | 227 | +List of snapshots present on all disks: |
228 | +ID TAG VM SIZE DATE VM CLOCK | ||
229 | +-- snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
230 | +(qemu) loadvm snap0 | ||
231 | +(qemu) quit | ||
232 | + | ||
233 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
234 | +Testing: -drive driver=IMGFMT,file=TEST_DIR/t.IMGFMT,if=none -device virtio-blk,drive=none0 | ||
235 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
236 | +(qemu) savevm snap0 | ||
237 | +(qemu) info snapshots | ||
238 | +List of snapshots present on all disks: | ||
239 | +ID TAG VM SIZE DATE VM CLOCK | ||
240 | +-- snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
241 | +(qemu) loadvm snap0 | ||
242 | +(qemu) quit | ||
243 | + | ||
244 | + | ||
245 | +=== -drive if=virtio === | ||
246 | + | ||
247 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
248 | +Testing: -drive driver=file,file=TEST_DIR/t.IMGFMT,if=virtio | ||
249 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
250 | +(qemu) savevm snap0 | ||
251 | +Error: Device 'virtio0' is writable but does not support snapshots | ||
252 | +(qemu) info snapshots | ||
253 | +No available block device supports snapshots | ||
254 | +(qemu) loadvm snap0 | ||
255 | +Error: Device 'virtio0' is writable but does not support snapshots | ||
256 | +(qemu) quit | ||
257 | + | ||
258 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
259 | +Testing: -drive driver=IMGFMT,file=TEST_DIR/t.IMGFMT,if=virtio | ||
260 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
261 | +(qemu) savevm snap0 | ||
262 | +(qemu) info snapshots | ||
263 | +List of snapshots present on all disks: | ||
264 | +ID TAG VM SIZE DATE VM CLOCK | ||
265 | +-- snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
266 | +(qemu) loadvm snap0 | ||
267 | +(qemu) quit | ||
268 | + | ||
269 | + | ||
270 | +=== Simple -blockdev === | ||
271 | + | ||
272 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
273 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file | ||
274 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
275 | +(qemu) savevm snap0 | ||
276 | +Error: Device '' is writable but does not support snapshots | ||
277 | +(qemu) info snapshots | ||
278 | +No available block device supports snapshots | ||
279 | +(qemu) loadvm snap0 | ||
280 | +Error: Device '' is writable but does not support snapshots | ||
281 | +(qemu) quit | ||
282 | + | ||
283 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
284 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file -blockdev driver=IMGFMT,file=file,node-name=fmt | ||
285 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
286 | +(qemu) savevm snap0 | ||
287 | +(qemu) info snapshots | ||
288 | +List of snapshots present on all disks: | ||
289 | +ID TAG VM SIZE DATE VM CLOCK | ||
290 | +-- snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
291 | +(qemu) loadvm snap0 | ||
292 | +(qemu) quit | ||
293 | + | ||
294 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
295 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file -blockdev driver=raw,file=file,node-name=raw -blockdev driver=IMGFMT,file=raw,node-name=fmt | ||
296 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
297 | +(qemu) savevm snap0 | ||
298 | +(qemu) info snapshots | ||
299 | +List of snapshots present on all disks: | ||
300 | +ID TAG VM SIZE DATE VM CLOCK | ||
301 | +-- snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
302 | +(qemu) loadvm snap0 | ||
303 | +(qemu) quit | ||
304 | + | ||
305 | + | ||
306 | +=== -blockdev with a filter on top === | ||
307 | + | ||
308 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 | ||
309 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file -blockdev driver=IMGFMT,file=file,node-name=fmt -blockdev driver=copy-on-read,file=fmt,node-name=filter | ||
310 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
311 | +(qemu) savevm snap0 | ||
312 | +(qemu) info snapshots | ||
313 | +List of snapshots present on all disks: | ||
314 | +ID TAG VM SIZE DATE VM CLOCK | ||
315 | +-- snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
316 | +(qemu) loadvm snap0 | ||
317 | +(qemu) quit | ||
318 | + | ||
319 | + | ||
320 | +=== -blockdev with a backing file === | ||
321 | + | ||
322 | +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 | ||
323 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base | ||
324 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT.base,node-name=backing-file -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file -blockdev driver=IMGFMT,file=file,backing=backing-file,node-name=fmt | ||
325 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
326 | +(qemu) savevm snap0 | ||
327 | +(qemu) info snapshots | ||
328 | +List of snapshots present on all disks: | ||
329 | +ID TAG VM SIZE DATE VM CLOCK | ||
330 | +-- snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
331 | +(qemu) loadvm snap0 | ||
332 | +(qemu) quit | ||
333 | + | ||
334 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base | ||
335 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT.base,node-name=backing-file -blockdev driver=IMGFMT,file=backing-file,node-name=backing-fmt -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file -blockdev driver=IMGFMT,file=file,backing=backing-fmt,node-name=fmt | ||
336 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
337 | +(qemu) savevm snap0 | ||
338 | +(qemu) info snapshots | ||
339 | +List of snapshots present on all disks: | ||
340 | +ID TAG VM SIZE DATE VM CLOCK | ||
341 | +-- snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
342 | +(qemu) loadvm snap0 | ||
343 | +(qemu) quit | ||
344 | + | ||
345 | +Internal snapshots on overlay: | ||
346 | +Snapshot list: | ||
347 | +ID TAG VM SIZE DATE VM CLOCK | ||
348 | +1 snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
349 | +Internal snapshots on backing file: | ||
350 | + | ||
351 | +=== -blockdev with NBD server on the backing file === | ||
352 | + | ||
353 | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base | ||
354 | +Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT.base,node-name=backing-file -blockdev driver=IMGFMT,file=backing-file,node-name=backing-fmt -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=file -blockdev driver=IMGFMT,file=file,backing=backing-fmt,node-name=fmt | ||
355 | +QEMU X.Y.Z monitor - type 'help' for more information | ||
356 | +(qemu) nbd_server_start unix:TEST_DIR/nbd | ||
357 | +(qemu) nbd_server_add -w backing-fmt | ||
358 | +(qemu) savevm snap0 | ||
359 | +(qemu) info snapshots | ||
360 | +List of snapshots present on all disks: | ||
361 | +ID TAG VM SIZE DATE VM CLOCK | ||
362 | +-- snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
363 | +(qemu) loadvm snap0 | ||
364 | +(qemu) quit | ||
365 | + | ||
366 | +Internal snapshots on overlay: | ||
367 | +Snapshot list: | ||
368 | +ID TAG VM SIZE DATE VM CLOCK | ||
369 | +1 snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
370 | +Internal snapshots on backing file: | ||
371 | +Snapshot list: | ||
372 | +ID TAG VM SIZE DATE VM CLOCK | ||
373 | +1 snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 | ||
374 | +*** done | ||
375 | diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter | ||
376 | index XXXXXXX..XXXXXXX 100644 | ||
377 | --- a/tests/qemu-iotests/common.filter | ||
378 | +++ b/tests/qemu-iotests/common.filter | ||
379 | @@ -XXX,XX +XXX,XX @@ | ||
380 | # standard filters | ||
381 | # | ||
382 | |||
383 | -# ctime(3) dates | ||
384 | -# | ||
385 | _filter_date() | ||
386 | { | ||
387 | - $SED \ | ||
388 | - -e 's/[A-Z][a-z][a-z] [A-z][a-z][a-z] *[0-9][0-9]* [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9][0-9][0-9]$/DATE/' | ||
389 | + $SED -re 's/[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/yyyy-mm-dd hh:mm:ss/' | ||
390 | +} | ||
391 | + | ||
392 | +_filter_vmstate_size() | ||
52 | +{ | 393 | +{ |
53 | + Error *local_err = NULL; | 394 | + $SED -r -e 's/[0-9. ]{5} [KMGT]iB/ SIZE/' \ |
54 | + BlockBackend *blk; | 395 | + -e 's/[0-9. ]{5} B/ SIZE/' |
55 | + QDict *options = qdict_new(); | 396 | } |
56 | + | 397 | |
57 | + qdict_put_str(options, "driver", "raw"); | 398 | _filter_generated_node_ids() |
58 | + blk = blk_new_open(path, NULL, options, BDRV_O_RDWR, &local_err); | 399 | diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group |
59 | + if (blk) { | ||
60 | + g_assert_null(local_err); | ||
61 | + if (blk_set_perm(blk, perm, shared_perm, errp)) { | ||
62 | + blk_unref(blk); | ||
63 | + blk = NULL; | ||
64 | + } | ||
65 | + } else { | ||
66 | + error_propagate(errp, local_err); | ||
67 | + } | ||
68 | + return blk; | ||
69 | +} | ||
70 | + | ||
71 | +static void check_locked_bytes(int fd, uint64_t perm_locks, | ||
72 | + uint64_t shared_perm_locks) | ||
73 | +{ | ||
74 | + int i; | ||
75 | + | ||
76 | + if (!perm_locks && !shared_perm_locks) { | ||
77 | + g_assert(!qemu_lock_fd_test(fd, 0, 0, true)); | ||
78 | + return; | ||
79 | + } | ||
80 | + for (i = 0; (1ULL << i) <= BLK_PERM_ALL; i++) { | ||
81 | + uint64_t bit = (1ULL << i); | ||
82 | + bool perm_expected = !!(bit & perm_locks); | ||
83 | + bool shared_perm_expected = !!(bit & shared_perm_locks); | ||
84 | + g_assert_cmpint(perm_expected, ==, | ||
85 | + !!qemu_lock_fd_test(fd, 100 + i, 1, true)); | ||
86 | + g_assert_cmpint(shared_perm_expected, ==, | ||
87 | + !!qemu_lock_fd_test(fd, 200 + i, 1, true)); | ||
88 | + } | ||
89 | +} | ||
90 | + | ||
91 | +static void test_image_locking_basic(void) | ||
92 | +{ | ||
93 | + BlockBackend *blk1, *blk2, *blk3; | ||
94 | + char img_path[] = "/tmp/qtest.XXXXXX"; | ||
95 | + uint64_t perm, shared_perm; | ||
96 | + | ||
97 | + int fd = mkstemp(img_path); | ||
98 | + assert(fd >= 0); | ||
99 | + | ||
100 | + perm = BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ; | ||
101 | + shared_perm = BLK_PERM_ALL; | ||
102 | + blk1 = open_image(img_path, perm, shared_perm, &error_abort); | ||
103 | + g_assert(blk1); | ||
104 | + | ||
105 | + check_locked_bytes(fd, perm, ~shared_perm); | ||
106 | + | ||
107 | + /* compatible perm between blk1 and blk2 */ | ||
108 | + blk2 = open_image(img_path, perm | BLK_PERM_RESIZE, shared_perm, NULL); | ||
109 | + g_assert(blk2); | ||
110 | + check_locked_bytes(fd, perm | BLK_PERM_RESIZE, ~shared_perm); | ||
111 | + | ||
112 | + /* incompatible perm with already open blk1 and blk2 */ | ||
113 | + blk3 = open_image(img_path, perm, BLK_PERM_WRITE_UNCHANGED, NULL); | ||
114 | + g_assert_null(blk3); | ||
115 | + | ||
116 | + blk_unref(blk2); | ||
117 | + | ||
118 | + /* Check that extra bytes in blk2 are correctly unlocked */ | ||
119 | + check_locked_bytes(fd, perm, ~shared_perm); | ||
120 | + | ||
121 | + blk_unref(blk1); | ||
122 | + | ||
123 | + /* Image is unused, no lock there */ | ||
124 | + check_locked_bytes(fd, 0, 0); | ||
125 | + blk3 = open_image(img_path, perm, BLK_PERM_WRITE_UNCHANGED, &error_abort); | ||
126 | + g_assert(blk3); | ||
127 | + blk_unref(blk3); | ||
128 | + close(fd); | ||
129 | + unlink(img_path); | ||
130 | +} | ||
131 | + | ||
132 | +static void test_set_perm_abort(void) | ||
133 | +{ | ||
134 | + BlockBackend *blk1, *blk2; | ||
135 | + char img_path[] = "/tmp/qtest.XXXXXX"; | ||
136 | + uint64_t perm, shared_perm; | ||
137 | + int r; | ||
138 | + int fd = mkstemp(img_path); | ||
139 | + assert(fd >= 0); | ||
140 | + | ||
141 | + perm = BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ; | ||
142 | + shared_perm = BLK_PERM_ALL; | ||
143 | + blk1 = open_image(img_path, perm, shared_perm, &error_abort); | ||
144 | + g_assert(blk1); | ||
145 | + | ||
146 | + blk2 = open_image(img_path, perm, shared_perm, &error_abort); | ||
147 | + g_assert(blk2); | ||
148 | + | ||
149 | + check_locked_bytes(fd, perm, ~shared_perm); | ||
150 | + | ||
151 | + /* A failed blk_set_perm mustn't change perm status (locked bytes) */ | ||
152 | + r = blk_set_perm(blk2, perm | BLK_PERM_RESIZE, BLK_PERM_WRITE_UNCHANGED, | ||
153 | + NULL); | ||
154 | + g_assert_cmpint(r, !=, 0); | ||
155 | + check_locked_bytes(fd, perm, ~shared_perm); | ||
156 | + blk_unref(blk1); | ||
157 | + blk_unref(blk2); | ||
158 | +} | ||
159 | + | ||
160 | +int main(int argc, char **argv) | ||
161 | +{ | ||
162 | + bdrv_init(); | ||
163 | + qemu_init_main_loop(&error_abort); | ||
164 | + | ||
165 | + g_test_init(&argc, &argv, NULL); | ||
166 | + | ||
167 | + if (qemu_has_ofd_lock()) { | ||
168 | + g_test_add_func("/image-locking/basic", test_image_locking_basic); | ||
169 | + g_test_add_func("/image-locking/set-perm-abort", test_set_perm_abort); | ||
170 | + } | ||
171 | + | ||
172 | + return g_test_run(); | ||
173 | +} | ||
174 | diff --git a/tests/Makefile.include b/tests/Makefile.include | ||
175 | index XXXXXXX..XXXXXXX 100644 | 400 | index XXXXXXX..XXXXXXX 100644 |
176 | --- a/tests/Makefile.include | 401 | --- a/tests/qemu-iotests/group |
177 | +++ b/tests/Makefile.include | 402 | +++ b/tests/qemu-iotests/group |
178 | @@ -XXX,XX +XXX,XX @@ check-unit-y += tests/test-bdrv-drain$(EXESUF) | 403 | @@ -XXX,XX +XXX,XX @@ |
179 | check-unit-y += tests/test-blockjob$(EXESUF) | 404 | 263 rw quick |
180 | check-unit-y += tests/test-blockjob-txn$(EXESUF) | 405 | 265 rw auto quick |
181 | check-unit-y += tests/test-block-backend$(EXESUF) | 406 | 266 rw quick |
182 | +check-unit-y += tests/test-image-locking$(EXESUF) | 407 | +267 rw auto quick snapshot |
183 | check-unit-y += tests/test-x86-cpuid$(EXESUF) | ||
184 | # all code tested by test-x86-cpuid is inside topology.h | ||
185 | ifeq ($(CONFIG_SOFTMMU),y) | ||
186 | @@ -XXX,XX +XXX,XX @@ tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(te | ||
187 | tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y) | ||
188 | tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y) | ||
189 | tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y) | ||
190 | +tests/test-image-locking$(EXESUF): tests/test-image-locking.o $(test-block-obj-y) $(test-util-obj-y) | ||
191 | tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y) | ||
192 | tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y) | ||
193 | tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) $(test-crypto-obj-y) | ||
194 | -- | 408 | -- |
195 | 2.19.1 | 409 | 2.20.1 |
196 | 410 | ||
197 | 411 | diff view generated by jsdifflib |
1 | From: Jeff Cody <jcody@redhat.com> | 1 | Running iotests is not required to build QEMU, so we can have stricter |
---|---|---|---|
2 | version requirements for Python here and can make use of new features | ||
3 | and drop compatibility code earlier. | ||
2 | 4 | ||
3 | This adds configure options to control the following block drivers: | 5 | This makes qemu-iotests skip all Python tests if a Python version before |
6 | 3.6 is used for the build. | ||
4 | 7 | ||
5 | * Bochs | 8 | Suggested-by: Eduardo Habkost <ehabkost@redhat.com> |
6 | * Cloop | 9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
7 | * Dmg | 10 | Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> |
8 | * Qcow (V1) | 11 | Reviewed-by: Thomas Huth <thuth@redhat.com> |
9 | * Vdi | 12 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
10 | * Vvfat | 13 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> |
11 | * qed | 14 | --- |
12 | * parallels | 15 | tests/qemu-iotests/check | 13 ++++++++++++- |
13 | * sheepdog | 16 | 1 file changed, 12 insertions(+), 1 deletion(-) |
14 | 17 | ||
15 | Each of these defaults to being enabled. | 18 | diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check |
16 | |||
17 | Signed-off-by: Jeff Cody <jcody@redhat.com> | ||
18 | Signed-off-by: Markus Armbruster <armbru@redhat.com> | ||
19 | Message-id: 20181107063644.2254-1-armbru@redhat.com | ||
20 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
21 | --- | ||
22 | configure | 91 +++++++++++++++++++++++++++++++++++++++++++++ | ||
23 | block/Makefile.objs | 22 ++++++++--- | ||
24 | 2 files changed, 107 insertions(+), 6 deletions(-) | ||
25 | |||
26 | diff --git a/configure b/configure | ||
27 | index XXXXXXX..XXXXXXX 100755 | 19 | index XXXXXXX..XXXXXXX 100755 |
28 | --- a/configure | 20 | --- a/tests/qemu-iotests/check |
29 | +++ b/configure | 21 | +++ b/tests/qemu-iotests/check |
30 | @@ -XXX,XX +XXX,XX @@ tcmalloc="no" | 22 | @@ -XXX,XX +XXX,XX @@ then |
31 | jemalloc="no" | 23 | export SOCKET_SCM_HELPER="$build_iotests/socket_scm_helper" |
32 | replication="yes" | ||
33 | vxhs="" | ||
34 | +bochs="yes" | ||
35 | +cloop="yes" | ||
36 | +dmg="yes" | ||
37 | +qcow1="yes" | ||
38 | +vdi="yes" | ||
39 | +vvfat="yes" | ||
40 | +qed="yes" | ||
41 | +parallels="yes" | ||
42 | +sheepdog="yes" | ||
43 | libxml2="" | ||
44 | docker="no" | ||
45 | debug_mutex="no" | ||
46 | @@ -XXX,XX +XXX,XX @@ for opt do | ||
47 | ;; | ||
48 | --enable-vxhs) vxhs="yes" | ||
49 | ;; | ||
50 | + --disable-bochs) bochs="no" | ||
51 | + ;; | ||
52 | + --enable-bochs) bochs="yes" | ||
53 | + ;; | ||
54 | + --disable-cloop) cloop="no" | ||
55 | + ;; | ||
56 | + --enable-cloop) cloop="yes" | ||
57 | + ;; | ||
58 | + --disable-dmg) dmg="no" | ||
59 | + ;; | ||
60 | + --enable-dmg) dmg="yes" | ||
61 | + ;; | ||
62 | + --disable-qcow1) qcow1="no" | ||
63 | + ;; | ||
64 | + --enable-qcow1) qcow1="yes" | ||
65 | + ;; | ||
66 | + --disable-vdi) vdi="no" | ||
67 | + ;; | ||
68 | + --enable-vdi) vdi="yes" | ||
69 | + ;; | ||
70 | + --disable-vvfat) vvfat="no" | ||
71 | + ;; | ||
72 | + --enable-vvfat) vvfat="yes" | ||
73 | + ;; | ||
74 | + --disable-qed) qed="no" | ||
75 | + ;; | ||
76 | + --enable-qed) qed="yes" | ||
77 | + ;; | ||
78 | + --disable-parallels) parallels="no" | ||
79 | + ;; | ||
80 | + --enable-parallels) parallels="yes" | ||
81 | + ;; | ||
82 | + --disable-sheepdog) sheepdog="no" | ||
83 | + ;; | ||
84 | + --enable-sheepdog) sheepdog="yes" | ||
85 | + ;; | ||
86 | --disable-vhost-user) vhost_user="no" | ||
87 | ;; | ||
88 | --enable-vhost-user) | ||
89 | @@ -XXX,XX +XXX,XX @@ disabled with --disable-FEATURE, default is enabled if available: | ||
90 | qom-cast-debug cast debugging support | ||
91 | tools build qemu-io, qemu-nbd and qemu-image tools | ||
92 | vxhs Veritas HyperScale vDisk backend support | ||
93 | + bochs bochs image format support | ||
94 | + cloop cloop image format support | ||
95 | + dmg dmg image format support | ||
96 | + qcow1 qcow v1 image format support | ||
97 | + vdi vdi image format support | ||
98 | + vvfat vvfat image format support | ||
99 | + qed qed image format support | ||
100 | + parallels parallels image format support | ||
101 | + sheepdog sheepdog block driver support | ||
102 | crypto-afalg Linux AF_ALG crypto backend driver | ||
103 | vhost-user vhost-user support | ||
104 | capstone capstone disassembler support | ||
105 | @@ -XXX,XX +XXX,XX @@ echo "jemalloc support $jemalloc" | ||
106 | echo "avx2 optimization $avx2_opt" | ||
107 | echo "replication support $replication" | ||
108 | echo "VxHS block device $vxhs" | ||
109 | +echo "bochs support $bochs" | ||
110 | +echo "cloop support $cloop" | ||
111 | +echo "dmg support $dmg" | ||
112 | +echo "qcow v1 support $qcow1" | ||
113 | +echo "vdi support $vdi" | ||
114 | +echo "vvfat support $vvfat" | ||
115 | +echo "qed support $qed" | ||
116 | +echo "parallels support $parallels" | ||
117 | +echo "sheepdog support $sheepdog" | ||
118 | echo "capstone $capstone" | ||
119 | echo "docker $docker" | ||
120 | echo "libpmem support $libpmem" | ||
121 | @@ -XXX,XX +XXX,XX @@ if test "$libpmem" = "yes" ; then | ||
122 | echo "CONFIG_LIBPMEM=y" >> $config_host_mak | ||
123 | fi | 24 | fi |
124 | 25 | ||
125 | +if test "$bochs" = "yes" ; then | 26 | +python_usable=false |
126 | + echo "CONFIG_BOCHS=y" >> $config_host_mak | 27 | +if $PYTHON -c 'import sys; sys.exit(0 if sys.version_info >= (3,6) else 1)' |
127 | +fi | 28 | +then |
128 | +if test "$cloop" = "yes" ; then | 29 | + python_usable=true |
129 | + echo "CONFIG_CLOOP=y" >> $config_host_mak | ||
130 | +fi | ||
131 | +if test "$dmg" = "yes" ; then | ||
132 | + echo "CONFIG_DMG=y" >> $config_host_mak | ||
133 | +fi | ||
134 | +if test "$qcow1" = "yes" ; then | ||
135 | + echo "CONFIG_QCOW1=y" >> $config_host_mak | ||
136 | +fi | ||
137 | +if test "$vdi" = "yes" ; then | ||
138 | + echo "CONFIG_VDI=y" >> $config_host_mak | ||
139 | +fi | ||
140 | +if test "$vvfat" = "yes" ; then | ||
141 | + echo "CONFIG_VVFAT=y" >> $config_host_mak | ||
142 | +fi | ||
143 | +if test "$qed" = "yes" ; then | ||
144 | + echo "CONFIG_QED=y" >> $config_host_mak | ||
145 | +fi | ||
146 | +if test "$parallels" = "yes" ; then | ||
147 | + echo "CONFIG_PARALLELS=y" >> $config_host_mak | ||
148 | +fi | ||
149 | +if test "$sheepdog" = "yes" ; then | ||
150 | + echo "CONFIG_SHEEPDOG=y" >> $config_host_mak | ||
151 | +fi | 30 | +fi |
152 | + | 31 | + |
153 | if test "$tcg_interpreter" = "yes"; then | 32 | default_machine=$($QEMU_PROG -machine help | sed -n '/(default)/ s/ .*//p') |
154 | QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/tci $QEMU_INCLUDES" | 33 | default_alias_machine=$($QEMU_PROG -machine help | \ |
155 | elif test "$ARCH" = "sparc64" ; then | 34 | sed -n "/(alias of $default_machine)/ { s/ .*//p; q; }") |
156 | diff --git a/block/Makefile.objs b/block/Makefile.objs | 35 | @@ -XXX,XX +XXX,XX @@ do |
157 | index XXXXXXX..XXXXXXX 100644 | 36 | start=$(_wallclock) |
158 | --- a/block/Makefile.objs | 37 | |
159 | +++ b/block/Makefile.objs | 38 | if [ "$(head -n 1 "$source_iotests/$seq")" == "#!/usr/bin/env python" ]; then |
160 | @@ -XXX,XX +XXX,XX @@ | 39 | - run_command="$PYTHON $seq" |
161 | -block-obj-y += raw-format.o qcow.o vdi.o vmdk.o cloop.o bochs.o vpc.o vvfat.o dmg.o | 40 | + if $python_usable; then |
162 | +block-obj-y += raw-format.o vmdk.o vpc.o | 41 | + run_command="$PYTHON $seq" |
163 | +block-obj-$(CONFIG_QCOW1) += qcow.o | 42 | + else |
164 | +block-obj-$(CONFIG_VDI) += vdi.o | 43 | + run_command="false" |
165 | +block-obj-$(CONFIG_CLOOP) += cloop.o | 44 | + echo "Unsupported Python version" > $seq.notrun |
166 | +block-obj-$(CONFIG_BOCHS) += bochs.o | 45 | + fi |
167 | +block-obj-$(CONFIG_VVFAT) += vvfat.o | 46 | else |
168 | +block-obj-$(CONFIG_DMG) += dmg.o | 47 | run_command="./$seq" |
169 | + | 48 | fi |
170 | block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o qcow2-bitmap.o | ||
171 | -block-obj-y += qed.o qed-l2-cache.o qed-table.o qed-cluster.o | ||
172 | -block-obj-y += qed-check.o | ||
173 | +block-obj-$(CONFIG_QED) += qed.o qed-l2-cache.o qed-table.o qed-cluster.o | ||
174 | +block-obj-$(CONFIG_QED) += qed-check.o | ||
175 | block-obj-y += vhdx.o vhdx-endian.o vhdx-log.o | ||
176 | block-obj-y += quorum.o | ||
177 | -block-obj-y += parallels.o blkdebug.o blkverify.o blkreplay.o | ||
178 | +block-obj-y += blkdebug.o blkverify.o blkreplay.o | ||
179 | +block-obj-$(CONFIG_PARALLELS) += parallels.o | ||
180 | block-obj-y += blklogwrites.o | ||
181 | block-obj-y += block-backend.o snapshot.o qapi.o | ||
182 | block-obj-$(CONFIG_WIN32) += file-win32.o win32-aio.o | ||
183 | @@ -XXX,XX +XXX,XX @@ block-obj-y += null.o mirror.o commit.o io.o create.o | ||
184 | block-obj-y += throttle-groups.o | ||
185 | block-obj-$(CONFIG_LINUX) += nvme.o | ||
186 | |||
187 | -block-obj-y += nbd.o nbd-client.o sheepdog.o | ||
188 | +block-obj-y += nbd.o nbd-client.o | ||
189 | +block-obj-$(CONFIG_SHEEPDOG) += sheepdog.o | ||
190 | block-obj-$(CONFIG_LIBISCSI) += iscsi.o | ||
191 | block-obj-$(if $(CONFIG_LIBISCSI),y,n) += iscsi-opts.o | ||
192 | block-obj-$(CONFIG_LIBNFS) += nfs.o | ||
193 | @@ -XXX,XX +XXX,XX @@ gluster.o-libs := $(GLUSTERFS_LIBS) | ||
194 | vxhs.o-libs := $(VXHS_LIBS) | ||
195 | ssh.o-cflags := $(LIBSSH2_CFLAGS) | ||
196 | ssh.o-libs := $(LIBSSH2_LIBS) | ||
197 | -block-obj-$(if $(CONFIG_BZIP2),m,n) += dmg-bz2.o | ||
198 | +block-obj-dmg-bz2-$(CONFIG_BZIP2) += dmg-bz2.o | ||
199 | +block-obj-$(if $(CONFIG_DMG),m,n) += $(block-obj-dmg-bz2-y) | ||
200 | dmg-bz2.o-libs := $(BZIP2_LIBS) | ||
201 | qcow.o-libs := -lz | ||
202 | linux-aio.o-libs := -laio | ||
203 | -- | 49 | -- |
204 | 2.19.1 | 50 | 2.20.1 |
205 | 51 | ||
206 | 52 | diff view generated by jsdifflib |
1 | From: zhenwei pi <pizhenwei@bytedance.com> | 1 | Some scripts check the Python version number and have two code paths to |
---|---|---|---|
2 | accomodate both Python 2 and 3. Remove the code specific to Python 2 and | ||
3 | assert the minimum version of 3.6 instead (check skips Python tests in | ||
4 | this case, so the assertion would only ever trigger if a Python script | ||
5 | is executed manually). | ||
2 | 6 | ||
3 | Function block_latency_histogram_set may return error, but qapi ignore this. | 7 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> |
4 | This can be reproduced easily by qmp command: | 8 | Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> |
5 | virsh qemu-monitor-command INSTANCE '{"execute":"x-block-latency-histogram-set", | 9 | Reviewed-by: Thomas Huth <thuth@redhat.com> |
6 | "arguments":{"device":"drive-virtio-disk1","boundaries":[10,200,40]}}' | 10 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
7 | In fact this command does not work, but we still get success result. | 11 | Reviewed-by: John Snow <jsnow@redhat.com> |
12 | Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
13 | --- | ||
14 | tests/qemu-iotests/044 | 3 --- | ||
15 | tests/qemu-iotests/163 | 3 --- | ||
16 | tests/qemu-iotests/iotests.py | 13 +++---------- | ||
17 | 3 files changed, 3 insertions(+), 16 deletions(-) | ||
8 | 18 | ||
9 | qmp_x_block_latency_histogram_set is a batch setting API, report error ASAP. | 19 | diff --git a/tests/qemu-iotests/044 b/tests/qemu-iotests/044 |
10 | 20 | index XXXXXXX..XXXXXXX 100755 | |
11 | Signed-off-by: zhenwei pi <pizhenwei@bytedance.com> | 21 | --- a/tests/qemu-iotests/044 |
12 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | 22 | +++ b/tests/qemu-iotests/044 |
13 | --- | 23 | @@ -XXX,XX +XXX,XX @@ import struct |
14 | blockdev.c | 19 ++++++++++++++++--- | 24 | import subprocess |
15 | 1 file changed, 16 insertions(+), 3 deletions(-) | 25 | import sys |
16 | 26 | ||
17 | diff --git a/blockdev.c b/blockdev.c | 27 | -if sys.version_info.major == 2: |
28 | - range = xrange | ||
29 | - | ||
30 | test_img = os.path.join(iotests.test_dir, 'test.img') | ||
31 | |||
32 | class TestRefcountTableGrowth(iotests.QMPTestCase): | ||
33 | diff --git a/tests/qemu-iotests/163 b/tests/qemu-iotests/163 | ||
34 | index XXXXXXX..XXXXXXX 100755 | ||
35 | --- a/tests/qemu-iotests/163 | ||
36 | +++ b/tests/qemu-iotests/163 | ||
37 | @@ -XXX,XX +XXX,XX @@ | ||
38 | import os, random, iotests, struct, qcow2, sys | ||
39 | from iotests import qemu_img, qemu_io, image_size | ||
40 | |||
41 | -if sys.version_info.major == 2: | ||
42 | - range = xrange | ||
43 | - | ||
44 | test_img = os.path.join(iotests.test_dir, 'test.img') | ||
45 | check_img = os.path.join(iotests.test_dir, 'check.img') | ||
46 | |||
47 | diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py | ||
18 | index XXXXXXX..XXXXXXX 100644 | 48 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/blockdev.c | 49 | --- a/tests/qemu-iotests/iotests.py |
20 | +++ b/blockdev.c | 50 | +++ b/tests/qemu-iotests/iotests.py |
21 | @@ -XXX,XX +XXX,XX @@ void qmp_x_block_latency_histogram_set( | 51 | @@ -XXX,XX +XXX,XX @@ from collections import OrderedDict |
22 | { | 52 | sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) |
23 | BlockBackend *blk = blk_by_name(device); | 53 | from qemu import qtest |
24 | BlockAcctStats *stats; | 54 | |
25 | + int ret; | 55 | +assert sys.version_info >= (3,6) |
26 | 56 | ||
27 | if (!blk) { | 57 | # This will not work if arguments contain spaces but is necessary if we |
28 | error_setg(errp, "Device '%s' not found", device); | 58 | # want to support the override options that ./check supports. |
29 | @@ -XXX,XX +XXX,XX @@ void qmp_x_block_latency_histogram_set( | 59 | @@ -XXX,XX +XXX,XX @@ def image_size(img): |
30 | } | 60 | return json.loads(r)['virtual-size'] |
31 | 61 | ||
32 | if (has_boundaries || has_boundaries_read) { | 62 | def is_str(val): |
33 | - block_latency_histogram_set( | 63 | - if sys.version_info.major >= 3: |
34 | + ret = block_latency_histogram_set( | 64 | - return isinstance(val, str) |
35 | stats, BLOCK_ACCT_READ, | 65 | - else: |
36 | has_boundaries_read ? boundaries_read : boundaries); | 66 | - return isinstance(val, str) or isinstance(val, unicode) |
37 | + if (ret) { | 67 | + return isinstance(val, str) |
38 | + error_setg(errp, "Device '%s' set read boundaries fail", device); | 68 | |
39 | + return; | 69 | test_dir_re = re.compile(r"%s" % test_dir) |
40 | + } | 70 | def filter_test_dir(msg): |
41 | } | 71 | @@ -XXX,XX +XXX,XX @@ def execute_test(test_function=None, |
42 | 72 | else: | |
43 | if (has_boundaries || has_boundaries_write) { | 73 | # We need to filter out the time taken from the output so that |
44 | - block_latency_histogram_set( | 74 | # qemu-iotest can reliably diff the results against master output. |
45 | + ret = block_latency_histogram_set( | 75 | - if sys.version_info.major >= 3: |
46 | stats, BLOCK_ACCT_WRITE, | 76 | - output = io.StringIO() |
47 | has_boundaries_write ? boundaries_write : boundaries); | 77 | - else: |
48 | + if (ret) { | 78 | - # io.StringIO is for unicode strings, which is not what |
49 | + error_setg(errp, "Device '%s' set write boundaries fail", device); | 79 | - # 2.x's test runner emits. |
50 | + return; | 80 | - output = io.BytesIO() |
51 | + } | 81 | + output = io.StringIO() |
52 | } | 82 | |
53 | 83 | logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN)) | |
54 | if (has_boundaries || has_boundaries_flush) { | ||
55 | - block_latency_histogram_set( | ||
56 | + ret = block_latency_histogram_set( | ||
57 | stats, BLOCK_ACCT_FLUSH, | ||
58 | has_boundaries_flush ? boundaries_flush : boundaries); | ||
59 | + if (ret) { | ||
60 | + error_setg(errp, "Device '%s' set flush boundaries fail", device); | ||
61 | + return; | ||
62 | + } | ||
63 | } | ||
64 | } | ||
65 | 84 | ||
66 | -- | 85 | -- |
67 | 2.19.1 | 86 | 2.20.1 |
68 | 87 | ||
69 | 88 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Peter Maydell <peter.maydell@linaro.org> | ||
2 | 1 | ||
3 | In the function external_snapshot_prepare() we have a | ||
4 | BlockdevSnapshotSync struct, which has the usual combination | ||
5 | of has_snapshot_node_name and snapshot_node_name fields for an | ||
6 | optional field. We set up a local variable | ||
7 | const char *snapshot_node_name = | ||
8 | s->has_snapshot_node_name ? s->snapshot_node_name : NULL; | ||
9 | |||
10 | and then mostly use "if (!snapshot_node_name)" for checking | ||
11 | whether we have a snapshot node name. The exception is that in | ||
12 | one place we check s->has_snapshot_node_name instead. This | ||
13 | confuses Coverity (CID 1396473), which thinks it might be | ||
14 | possible to get here with s->has_snapshot_node_name true but | ||
15 | snapshot_node_name NULL, and warns that the call to | ||
16 | qdict_put_str() will segfault in that case. | ||
17 | |||
18 | Make the code consistent and unconfuse Coverity by using | ||
19 | the same check for this conditional that we do in the rest | ||
20 | of the surrounding code. | ||
21 | |||
22 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
23 | Reviewed-by: Alberto Garcia <berto@igalia.com> | ||
24 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
25 | --- | ||
26 | blockdev.c | 2 +- | ||
27 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
28 | |||
29 | diff --git a/blockdev.c b/blockdev.c | ||
30 | index XXXXXXX..XXXXXXX 100644 | ||
31 | --- a/blockdev.c | ||
32 | +++ b/blockdev.c | ||
33 | @@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common, | ||
34 | } | ||
35 | |||
36 | options = qdict_new(); | ||
37 | - if (s->has_snapshot_node_name) { | ||
38 | + if (snapshot_node_name) { | ||
39 | qdict_put_str(options, "node-name", snapshot_node_name); | ||
40 | } | ||
41 | qdict_put_str(options, "driver", format); | ||
42 | -- | ||
43 | 2.19.1 | ||
44 | |||
45 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Li Qiang <liq3ea@gmail.com> | ||
2 | 1 | ||
3 | Currently, when hotplug/unhotplug nvme device, it will cause an | ||
4 | assert in object.c. Following is the backtrack: | ||
5 | |||
6 | ERROR:qom/object.c:981:object_unref: assertion failed: (obj->ref > 0) | ||
7 | |||
8 | Thread 2 "qemu-system-x86" received signal SIGABRT, Aborted. | ||
9 | [Switching to Thread 0x7fffcbd32700 (LWP 18844)] | ||
10 | 0x00007fffdb9e4fff in raise () from /lib/x86_64-linux-gnu/libc.so.6 | ||
11 | (gdb) bt | ||
12 | /lib/x86_64-linux-gnu/libglib-2.0.so.0 | ||
13 | /lib/x86_64-linux-gnu/libglib-2.0.so.0 | ||
14 | qom/object.c:981 | ||
15 | /home/liqiang02/qemu-upstream/qemu/memory.c:1732 | ||
16 | /home/liqiang02/qemu-upstream/qemu/memory.c:285 | ||
17 | util/qemu-thread-posix.c:504 | ||
18 | /lib/x86_64-linux-gnu/libpthread.so.0 | ||
19 | |||
20 | This is caused by memory_region_unref in nvme_exit. | ||
21 | |||
22 | Remove it to make the PCIdevice refcount correct. | ||
23 | |||
24 | Signed-off-by: Li Qiang <liq3ea@gmail.com> | ||
25 | Reviewed-by: Igor Mammedov <imammedo@redhat.com> | ||
26 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
27 | --- | ||
28 | hw/block/nvme.c | 3 --- | ||
29 | 1 file changed, 3 deletions(-) | ||
30 | |||
31 | diff --git a/hw/block/nvme.c b/hw/block/nvme.c | ||
32 | index XXXXXXX..XXXXXXX 100644 | ||
33 | --- a/hw/block/nvme.c | ||
34 | +++ b/hw/block/nvme.c | ||
35 | @@ -XXX,XX +XXX,XX @@ static void nvme_exit(PCIDevice *pci_dev) | ||
36 | g_free(n->namespaces); | ||
37 | g_free(n->cq); | ||
38 | g_free(n->sq); | ||
39 | - if (n->cmbsz) { | ||
40 | - memory_region_unref(&n->ctrl_mem); | ||
41 | - } | ||
42 | |||
43 | msix_uninit_exclusive_bar(pci_dev); | ||
44 | } | ||
45 | -- | ||
46 | 2.19.1 | ||
47 | |||
48 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Li Qiang <liq3ea@gmail.com> | ||
2 | 1 | ||
3 | This avoid a memory leak in unhotplug nvme device. | ||
4 | |||
5 | Signed-off-by: Li Qiang <liq3ea@gmail.com> | ||
6 | Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
7 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
8 | --- | ||
9 | hw/block/nvme.c | 3 +++ | ||
10 | 1 file changed, 3 insertions(+) | ||
11 | |||
12 | diff --git a/hw/block/nvme.c b/hw/block/nvme.c | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/hw/block/nvme.c | ||
15 | +++ b/hw/block/nvme.c | ||
16 | @@ -XXX,XX +XXX,XX @@ static void nvme_exit(PCIDevice *pci_dev) | ||
17 | g_free(n->cq); | ||
18 | g_free(n->sq); | ||
19 | |||
20 | + if (n->cmb_size_mb) { | ||
21 | + g_free(n->cmbuf); | ||
22 | + } | ||
23 | msix_uninit_exclusive_bar(pci_dev); | ||
24 | } | ||
25 | |||
26 | -- | ||
27 | 2.19.1 | ||
28 | |||
29 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Fam Zheng <famz@redhat.com> | ||
2 | 1 | ||
3 | If we know we've already locked the bytes, don't do it again; similarly | ||
4 | don't unlock a byte if we haven't locked it. This doesn't change the | ||
5 | behavior, but fixes a corner case explained below. | ||
6 | |||
7 | Libvirt had an error handling bug that an image can get its (ownership, | ||
8 | file mode, SELinux) permissions changed (RHBZ 1584982) by mistake behind | ||
9 | QEMU. Specifically, an image in use by Libvirt VM has: | ||
10 | |||
11 | $ ls -lhZ b.img | ||
12 | -rw-r--r--. qemu qemu system_u:object_r:svirt_image_t:s0:c600,c690 b.img | ||
13 | |||
14 | Trying to attach it a second time won't work because of image locking. | ||
15 | And after the error, it becomes: | ||
16 | |||
17 | $ ls -lhZ b.img | ||
18 | -rw-r--r--. root root system_u:object_r:virt_image_t:s0 b.img | ||
19 | |||
20 | Then, we won't be able to do OFD lock operations with the existing fd. | ||
21 | In other words, the code such as in blk_detach_dev: | ||
22 | |||
23 | blk_set_perm(blk, 0, BLK_PERM_ALL, &error_abort); | ||
24 | |||
25 | can abort() QEMU, out of environmental changes. | ||
26 | |||
27 | This patch is an easy fix to this and the change is regardlessly | ||
28 | reasonable, so do it. | ||
29 | |||
30 | Signed-off-by: Fam Zheng <famz@redhat.com> | ||
31 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
32 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
33 | --- | ||
34 | block/file-posix.c | 54 +++++++++++++++++++++++++++++++++++++--------- | ||
35 | 1 file changed, 44 insertions(+), 10 deletions(-) | ||
36 | |||
37 | diff --git a/block/file-posix.c b/block/file-posix.c | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/block/file-posix.c | ||
40 | +++ b/block/file-posix.c | ||
41 | @@ -XXX,XX +XXX,XX @@ typedef struct BDRVRawState { | ||
42 | uint64_t perm; | ||
43 | uint64_t shared_perm; | ||
44 | |||
45 | + /* The perms bits whose corresponding bytes are already locked in | ||
46 | + * s->lock_fd. */ | ||
47 | + uint64_t locked_perm; | ||
48 | + uint64_t locked_shared_perm; | ||
49 | + | ||
50 | #ifdef CONFIG_XFS | ||
51 | bool is_xfs:1; | ||
52 | #endif | ||
53 | @@ -XXX,XX +XXX,XX @@ typedef enum { | ||
54 | * file; if @unlock == true, also unlock the unneeded bytes. | ||
55 | * @shared_perm_lock_bits is the mask of all permissions that are NOT shared. | ||
56 | */ | ||
57 | -static int raw_apply_lock_bytes(int fd, | ||
58 | +static int raw_apply_lock_bytes(BDRVRawState *s, int fd, | ||
59 | uint64_t perm_lock_bits, | ||
60 | uint64_t shared_perm_lock_bits, | ||
61 | bool unlock, Error **errp) | ||
62 | { | ||
63 | int ret; | ||
64 | int i; | ||
65 | + uint64_t locked_perm, locked_shared_perm; | ||
66 | + | ||
67 | + if (s) { | ||
68 | + locked_perm = s->locked_perm; | ||
69 | + locked_shared_perm = s->locked_shared_perm; | ||
70 | + } else { | ||
71 | + /* | ||
72 | + * We don't have the previous bits, just lock/unlock for each of the | ||
73 | + * requested bits. | ||
74 | + */ | ||
75 | + if (unlock) { | ||
76 | + locked_perm = BLK_PERM_ALL; | ||
77 | + locked_shared_perm = BLK_PERM_ALL; | ||
78 | + } else { | ||
79 | + locked_perm = 0; | ||
80 | + locked_shared_perm = 0; | ||
81 | + } | ||
82 | + } | ||
83 | |||
84 | PERM_FOREACH(i) { | ||
85 | int off = RAW_LOCK_PERM_BASE + i; | ||
86 | - if (perm_lock_bits & (1ULL << i)) { | ||
87 | + uint64_t bit = (1ULL << i); | ||
88 | + if ((perm_lock_bits & bit) && !(locked_perm & bit)) { | ||
89 | ret = qemu_lock_fd(fd, off, 1, false); | ||
90 | if (ret) { | ||
91 | error_setg(errp, "Failed to lock byte %d", off); | ||
92 | return ret; | ||
93 | + } else if (s) { | ||
94 | + s->locked_perm |= bit; | ||
95 | } | ||
96 | - } else if (unlock) { | ||
97 | + } else if (unlock && (locked_perm & bit) && !(perm_lock_bits & bit)) { | ||
98 | ret = qemu_unlock_fd(fd, off, 1); | ||
99 | if (ret) { | ||
100 | error_setg(errp, "Failed to unlock byte %d", off); | ||
101 | return ret; | ||
102 | + } else if (s) { | ||
103 | + s->locked_perm &= ~bit; | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | PERM_FOREACH(i) { | ||
108 | int off = RAW_LOCK_SHARED_BASE + i; | ||
109 | - if (shared_perm_lock_bits & (1ULL << i)) { | ||
110 | + uint64_t bit = (1ULL << i); | ||
111 | + if ((shared_perm_lock_bits & bit) && !(locked_shared_perm & bit)) { | ||
112 | ret = qemu_lock_fd(fd, off, 1, false); | ||
113 | if (ret) { | ||
114 | error_setg(errp, "Failed to lock byte %d", off); | ||
115 | return ret; | ||
116 | + } else if (s) { | ||
117 | + s->locked_shared_perm |= bit; | ||
118 | } | ||
119 | - } else if (unlock) { | ||
120 | + } else if (unlock && (locked_shared_perm & bit) && | ||
121 | + !(shared_perm_lock_bits & bit)) { | ||
122 | ret = qemu_unlock_fd(fd, off, 1); | ||
123 | if (ret) { | ||
124 | error_setg(errp, "Failed to unlock byte %d", off); | ||
125 | return ret; | ||
126 | + } else if (s) { | ||
127 | + s->locked_shared_perm &= ~bit; | ||
128 | } | ||
129 | } | ||
130 | } | ||
131 | @@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs, | ||
132 | |||
133 | switch (op) { | ||
134 | case RAW_PL_PREPARE: | ||
135 | - ret = raw_apply_lock_bytes(s->lock_fd, s->perm | new_perm, | ||
136 | + ret = raw_apply_lock_bytes(s, s->lock_fd, s->perm | new_perm, | ||
137 | ~s->shared_perm | ~new_shared, | ||
138 | false, errp); | ||
139 | if (!ret) { | ||
140 | @@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs, | ||
141 | op = RAW_PL_ABORT; | ||
142 | /* fall through to unlock bytes. */ | ||
143 | case RAW_PL_ABORT: | ||
144 | - raw_apply_lock_bytes(s->lock_fd, s->perm, ~s->shared_perm, | ||
145 | + raw_apply_lock_bytes(s, s->lock_fd, s->perm, ~s->shared_perm, | ||
146 | true, &local_err); | ||
147 | if (local_err) { | ||
148 | /* Theoretically the above call only unlocks bytes and it cannot | ||
149 | @@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs, | ||
150 | } | ||
151 | break; | ||
152 | case RAW_PL_COMMIT: | ||
153 | - raw_apply_lock_bytes(s->lock_fd, new_perm, ~new_shared, | ||
154 | + raw_apply_lock_bytes(s, s->lock_fd, new_perm, ~new_shared, | ||
155 | true, &local_err); | ||
156 | if (local_err) { | ||
157 | /* Theoretically the above call only unlocks bytes and it cannot | ||
158 | @@ -XXX,XX +XXX,XX @@ raw_co_create(BlockdevCreateOptions *options, Error **errp) | ||
159 | shared = BLK_PERM_ALL & ~BLK_PERM_RESIZE; | ||
160 | |||
161 | /* Step one: Take locks */ | ||
162 | - result = raw_apply_lock_bytes(fd, perm, ~shared, false, errp); | ||
163 | + result = raw_apply_lock_bytes(NULL, fd, perm, ~shared, false, errp); | ||
164 | if (result < 0) { | ||
165 | goto out_close; | ||
166 | } | ||
167 | @@ -XXX,XX +XXX,XX @@ raw_co_create(BlockdevCreateOptions *options, Error **errp) | ||
168 | } | ||
169 | |||
170 | out_unlock: | ||
171 | - raw_apply_lock_bytes(fd, 0, 0, true, &local_err); | ||
172 | + raw_apply_lock_bytes(NULL, fd, 0, 0, true, &local_err); | ||
173 | if (local_err) { | ||
174 | /* The above call should not fail, and if it does, that does | ||
175 | * not mean the whole creation operation has failed. So | ||
176 | -- | ||
177 | 2.19.1 | ||
178 | |||
179 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Fam Zheng <famz@redhat.com> | ||
2 | 1 | ||
3 | The lock_fd field is not strictly necessary because transferring locked | ||
4 | bytes from old fd to the new one shouldn't fail anyway. This spares the | ||
5 | user one fd per image. | ||
6 | |||
7 | Signed-off-by: Fam Zheng <famz@redhat.com> | ||
8 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
9 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
10 | --- | ||
11 | block/file-posix.c | 37 +++++++++++++------------------------ | ||
12 | 1 file changed, 13 insertions(+), 24 deletions(-) | ||
13 | |||
14 | diff --git a/block/file-posix.c b/block/file-posix.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/block/file-posix.c | ||
17 | +++ b/block/file-posix.c | ||
18 | @@ -XXX,XX +XXX,XX @@ do { \ | ||
19 | |||
20 | typedef struct BDRVRawState { | ||
21 | int fd; | ||
22 | - int lock_fd; | ||
23 | bool use_lock; | ||
24 | int type; | ||
25 | int open_flags; | ||
26 | @@ -XXX,XX +XXX,XX @@ typedef struct BDRVRawState { | ||
27 | uint64_t shared_perm; | ||
28 | |||
29 | /* The perms bits whose corresponding bytes are already locked in | ||
30 | - * s->lock_fd. */ | ||
31 | + * s->fd. */ | ||
32 | uint64_t locked_perm; | ||
33 | uint64_t locked_shared_perm; | ||
34 | |||
35 | @@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options, | ||
36 | } | ||
37 | s->fd = fd; | ||
38 | |||
39 | - s->lock_fd = -1; | ||
40 | - if (s->use_lock) { | ||
41 | - fd = qemu_open(filename, s->open_flags); | ||
42 | - if (fd < 0) { | ||
43 | - ret = -errno; | ||
44 | - error_setg_errno(errp, errno, "Could not open '%s' for locking", | ||
45 | - filename); | ||
46 | - qemu_close(s->fd); | ||
47 | - goto fail; | ||
48 | - } | ||
49 | - s->lock_fd = fd; | ||
50 | - } | ||
51 | s->perm = 0; | ||
52 | s->shared_perm = BLK_PERM_ALL; | ||
53 | |||
54 | @@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs, | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | - assert(s->lock_fd > 0); | ||
59 | - | ||
60 | switch (op) { | ||
61 | case RAW_PL_PREPARE: | ||
62 | - ret = raw_apply_lock_bytes(s, s->lock_fd, s->perm | new_perm, | ||
63 | + ret = raw_apply_lock_bytes(s, s->fd, s->perm | new_perm, | ||
64 | ~s->shared_perm | ~new_shared, | ||
65 | false, errp); | ||
66 | if (!ret) { | ||
67 | - ret = raw_check_lock_bytes(s->lock_fd, new_perm, new_shared, errp); | ||
68 | + ret = raw_check_lock_bytes(s->fd, new_perm, new_shared, errp); | ||
69 | if (!ret) { | ||
70 | return 0; | ||
71 | } | ||
72 | @@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs, | ||
73 | op = RAW_PL_ABORT; | ||
74 | /* fall through to unlock bytes. */ | ||
75 | case RAW_PL_ABORT: | ||
76 | - raw_apply_lock_bytes(s, s->lock_fd, s->perm, ~s->shared_perm, | ||
77 | + raw_apply_lock_bytes(s, s->fd, s->perm, ~s->shared_perm, | ||
78 | true, &local_err); | ||
79 | if (local_err) { | ||
80 | /* Theoretically the above call only unlocks bytes and it cannot | ||
81 | @@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs, | ||
82 | } | ||
83 | break; | ||
84 | case RAW_PL_COMMIT: | ||
85 | - raw_apply_lock_bytes(s, s->lock_fd, new_perm, ~new_shared, | ||
86 | + raw_apply_lock_bytes(s, s->fd, new_perm, ~new_shared, | ||
87 | true, &local_err); | ||
88 | if (local_err) { | ||
89 | /* Theoretically the above call only unlocks bytes and it cannot | ||
90 | @@ -XXX,XX +XXX,XX @@ static void raw_reopen_commit(BDRVReopenState *state) | ||
91 | { | ||
92 | BDRVRawReopenState *rs = state->opaque; | ||
93 | BDRVRawState *s = state->bs->opaque; | ||
94 | + Error *local_err = NULL; | ||
95 | |||
96 | s->check_cache_dropped = rs->check_cache_dropped; | ||
97 | s->open_flags = rs->open_flags; | ||
98 | |||
99 | + /* Copy locks to the new fd before closing the old one. */ | ||
100 | + raw_apply_lock_bytes(NULL, rs->fd, s->locked_perm, | ||
101 | + ~s->locked_shared_perm, false, &local_err); | ||
102 | + if (local_err) { | ||
103 | + /* shouldn't fail in a sane host, but report it just in case. */ | ||
104 | + error_report_err(local_err); | ||
105 | + } | ||
106 | qemu_close(s->fd); | ||
107 | s->fd = rs->fd; | ||
108 | |||
109 | @@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs) | ||
110 | qemu_close(s->fd); | ||
111 | s->fd = -1; | ||
112 | } | ||
113 | - if (s->lock_fd >= 0) { | ||
114 | - qemu_close(s->lock_fd); | ||
115 | - s->lock_fd = -1; | ||
116 | - } | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | -- | ||
121 | 2.19.1 | ||
122 | |||
123 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Liam Merwick <Liam.Merwick@oracle.com> | ||
2 | 1 | ||
3 | In the assert checking the array dereference of JobVerbTable[verb] | ||
4 | in job_apply_verb() the check of the index, verb, allows an overrun | ||
5 | because an index equal to the array size is permitted. | ||
6 | |||
7 | Similarly, in the assert check of JobSTT[s0][s1] with index s1 | ||
8 | in job_state_transition(), an off-by-one overrun is not flagged | ||
9 | either. | ||
10 | |||
11 | This is not a run-time issue as there are no callers actually | ||
12 | passing in the max value. | ||
13 | |||
14 | Signed-off-by: Liam Merwick <Liam.Merwick@oracle.com> | ||
15 | Reviewed-by: Darren Kenny <Darren.Kenny@oracle.com> | ||
16 | Reviewed-by: Mark Kanda <Mark.Kanda@oracle.com> | ||
17 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
18 | Reviewed-by: John Snow <jsnow@redhat.com> | ||
19 | Message-id: 1541453919-25973-2-git-send-email-Liam.Merwick@oracle.com | ||
20 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
21 | --- | ||
22 | job.c | 4 ++-- | ||
23 | 1 file changed, 2 insertions(+), 2 deletions(-) | ||
24 | |||
25 | diff --git a/job.c b/job.c | ||
26 | index XXXXXXX..XXXXXXX 100644 | ||
27 | --- a/job.c | ||
28 | +++ b/job.c | ||
29 | @@ -XXX,XX +XXX,XX @@ bool job_is_internal(Job *job) | ||
30 | static void job_state_transition(Job *job, JobStatus s1) | ||
31 | { | ||
32 | JobStatus s0 = job->status; | ||
33 | - assert(s1 >= 0 && s1 <= JOB_STATUS__MAX); | ||
34 | + assert(s1 >= 0 && s1 < JOB_STATUS__MAX); | ||
35 | trace_job_state_transition(job, job->ret, | ||
36 | JobSTT[s0][s1] ? "allowed" : "disallowed", | ||
37 | JobStatus_str(s0), JobStatus_str(s1)); | ||
38 | @@ -XXX,XX +XXX,XX @@ static void job_state_transition(Job *job, JobStatus s1) | ||
39 | int job_apply_verb(Job *job, JobVerb verb, Error **errp) | ||
40 | { | ||
41 | JobStatus s0 = job->status; | ||
42 | - assert(verb >= 0 && verb <= JOB_VERB__MAX); | ||
43 | + assert(verb >= 0 && verb < JOB_VERB__MAX); | ||
44 | trace_job_apply_verb(job, JobStatus_str(s0), JobVerb_str(verb), | ||
45 | JobVerbTable[verb][s0] ? "allowed" : "prohibited"); | ||
46 | if (JobVerbTable[verb][s0]) { | ||
47 | -- | ||
48 | 2.19.1 | ||
49 | |||
50 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Liam Merwick <Liam.Merwick@oracle.com> | ||
2 | 1 | ||
3 | The dev_id returned by the call to blk_get_attached_dev_id() in | ||
4 | blk_root_get_parent_desc() can be NULL (an internal call to | ||
5 | object_get_canonical_path may have returned NULL). | ||
6 | |||
7 | Instead of just checking this case before before dereferencing, | ||
8 | adjust blk_get_attached_dev_id() to return the empty string if no | ||
9 | object path can be found (similar to the case when blk->dev is NULL | ||
10 | and an empty string is returned). | ||
11 | |||
12 | Signed-off-by: Liam Merwick <Liam.Merwick@oracle.com> | ||
13 | Message-id: 1541453919-25973-3-git-send-email-Liam.Merwick@oracle.com | ||
14 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
15 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
16 | --- | ||
17 | block/block-backend.c | 3 ++- | ||
18 | 1 file changed, 2 insertions(+), 1 deletion(-) | ||
19 | |||
20 | diff --git a/block/block-backend.c b/block/block-backend.c | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/block/block-backend.c | ||
23 | +++ b/block/block-backend.c | ||
24 | @@ -XXX,XX +XXX,XX @@ char *blk_get_attached_dev_id(BlockBackend *blk) | ||
25 | } else if (dev->id) { | ||
26 | return g_strdup(dev->id); | ||
27 | } | ||
28 | - return object_get_canonical_path(OBJECT(dev)); | ||
29 | + | ||
30 | + return object_get_canonical_path(OBJECT(dev)) ?: g_strdup(""); | ||
31 | } | ||
32 | |||
33 | /* | ||
34 | -- | ||
35 | 2.19.1 | ||
36 | |||
37 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Liam Merwick <Liam.Merwick@oracle.com> | ||
2 | 1 | ||
3 | Although the function block_job_get() can return NULL, it would be a | ||
4 | serious bug if it did so (because the job yields before executing anything | ||
5 | (if it started successfully); but otherwise, commit_active_start() would | ||
6 | have returned an error). However, as a precaution, before dereferencing | ||
7 | the 'job' pointer in img_commit() assert it is not NULL. | ||
8 | |||
9 | Signed-off-by: Liam Merwick <Liam.Merwick@oracle.com> | ||
10 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
11 | Message-id: 1541453919-25973-4-git-send-email-Liam.Merwick@oracle.com | ||
12 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
13 | --- | ||
14 | qemu-img.c | 1 + | ||
15 | 1 file changed, 1 insertion(+) | ||
16 | |||
17 | diff --git a/qemu-img.c b/qemu-img.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/qemu-img.c | ||
20 | +++ b/qemu-img.c | ||
21 | @@ -XXX,XX +XXX,XX @@ static int img_commit(int argc, char **argv) | ||
22 | } | ||
23 | |||
24 | job = block_job_get("commit"); | ||
25 | + assert(job); | ||
26 | run_block_job(job, &local_err); | ||
27 | if (local_err) { | ||
28 | goto unref_backing; | ||
29 | -- | ||
30 | 2.19.1 | ||
31 | |||
32 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Liam Merwick <Liam.Merwick@oracle.com> | ||
2 | 1 | ||
3 | The commit for 0e4e4318eaa5 increments QCOW2_OL_MAX_BITNR but does not | ||
4 | add an array entry for QCOW2_OL_BITMAP_DIRECTORY_BITNR to metadata_ol_names[]. | ||
5 | As a result, an array dereference of metadata_ol_names[8] in | ||
6 | qcow2_pre_write_overlap_check() could result in a read outside of the array bounds. | ||
7 | |||
8 | Fixes: 0e4e4318eaa5 ('qcow2: add overlap check for bitmap directory') | ||
9 | |||
10 | Cc: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> | ||
11 | Signed-off-by: Liam Merwick <Liam.Merwick@oracle.com> | ||
12 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
13 | Reviewed-by: Max Reitz <mreitz@redhat.com> | ||
14 | Message-id: 1541453919-25973-6-git-send-email-Liam.Merwick@oracle.com | ||
15 | Signed-off-by: Max Reitz <mreitz@redhat.com> | ||
16 | --- | ||
17 | block/qcow2-refcount.c | 18 ++++++++++-------- | ||
18 | 1 file changed, 10 insertions(+), 8 deletions(-) | ||
19 | |||
20 | diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/block/qcow2-refcount.c | ||
23 | +++ b/block/qcow2-refcount.c | ||
24 | @@ -XXX,XX +XXX,XX @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, | ||
25 | } | ||
26 | |||
27 | static const char *metadata_ol_names[] = { | ||
28 | - [QCOW2_OL_MAIN_HEADER_BITNR] = "qcow2_header", | ||
29 | - [QCOW2_OL_ACTIVE_L1_BITNR] = "active L1 table", | ||
30 | - [QCOW2_OL_ACTIVE_L2_BITNR] = "active L2 table", | ||
31 | - [QCOW2_OL_REFCOUNT_TABLE_BITNR] = "refcount table", | ||
32 | - [QCOW2_OL_REFCOUNT_BLOCK_BITNR] = "refcount block", | ||
33 | - [QCOW2_OL_SNAPSHOT_TABLE_BITNR] = "snapshot table", | ||
34 | - [QCOW2_OL_INACTIVE_L1_BITNR] = "inactive L1 table", | ||
35 | - [QCOW2_OL_INACTIVE_L2_BITNR] = "inactive L2 table", | ||
36 | + [QCOW2_OL_MAIN_HEADER_BITNR] = "qcow2_header", | ||
37 | + [QCOW2_OL_ACTIVE_L1_BITNR] = "active L1 table", | ||
38 | + [QCOW2_OL_ACTIVE_L2_BITNR] = "active L2 table", | ||
39 | + [QCOW2_OL_REFCOUNT_TABLE_BITNR] = "refcount table", | ||
40 | + [QCOW2_OL_REFCOUNT_BLOCK_BITNR] = "refcount block", | ||
41 | + [QCOW2_OL_SNAPSHOT_TABLE_BITNR] = "snapshot table", | ||
42 | + [QCOW2_OL_INACTIVE_L1_BITNR] = "inactive L1 table", | ||
43 | + [QCOW2_OL_INACTIVE_L2_BITNR] = "inactive L2 table", | ||
44 | + [QCOW2_OL_BITMAP_DIRECTORY_BITNR] = "bitmap directory", | ||
45 | }; | ||
46 | +QEMU_BUILD_BUG_ON(QCOW2_OL_MAX_BITNR != ARRAY_SIZE(metadata_ol_names)); | ||
47 | |||
48 | /* | ||
49 | * First performs a check for metadata overlaps (through | ||
50 | -- | ||
51 | 2.19.1 | ||
52 | |||
53 | diff view generated by jsdifflib |