diff --git a/MAINTAINERS b/MAINTAINERS index bcd88668bcdb..00626941f1a0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2210,6 +2210,7 @@ F: scsi/* Block Jobs M: John Snow +M: Vladimir Sementsov-Ogievskiy L: qemu-block@nongnu.org S: Supported F: blockjob.c @@ -2222,7 +2223,16 @@ F: block/commit.c F: block/stream.c F: block/mirror.c F: qapi/job.json +F: block/block-copy.c +F: include/block/block-copy.c +F: block/backup-top.h +F: block/backup-top.c +F: include/block/aio_task.h +F: block/aio_task.c +F: util/qemu-co-shared-resource.c +F: include/qemu/co-shared-resource.h T: git https://gitlab.com/jsnow/qemu.git jobs +T: git https://src.openvz.org/scm/~vsementsov/qemu.git jobs Block QAPI, monitor, command line M: Markus Armbruster diff --git a/block.c b/block.c index 91a66d4f3e16..4e52b1c588cd 100644 --- a/block.c +++ b/block.c @@ -4435,7 +4435,6 @@ static void bdrv_close(BlockDriverState *bs) void bdrv_close_all(void) { assert(job_next(NULL) == NULL); - blk_exp_close_all(); /* Drop references from requests still in flight, such as canceled block * jobs whose AIO context has not been polled yet */ @@ -6439,7 +6438,10 @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs, AioContext *new_context, GSList **ignore) { AioContext *old_context = bdrv_get_aio_context(bs); - BdrvChild *child; + GSList *children_to_process = NULL; + GSList *parents_to_process = NULL; + GSList *entry; + BdrvChild *child, *parent; g_assert(qemu_get_current_aio_context() == qemu_get_aio_context()); @@ -6454,16 +6456,33 @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs, continue; } *ignore = g_slist_prepend(*ignore, child); - bdrv_set_aio_context_ignore(child->bs, new_context, ignore); + children_to_process = g_slist_prepend(children_to_process, child); } - QLIST_FOREACH(child, &bs->parents, next_parent) { - if (g_slist_find(*ignore, child)) { + + QLIST_FOREACH(parent, &bs->parents, next_parent) { + if (g_slist_find(*ignore, parent)) { continue; } - assert(child->klass->set_aio_ctx); - *ignore = g_slist_prepend(*ignore, child); - child->klass->set_aio_ctx(child, new_context, ignore); + *ignore = g_slist_prepend(*ignore, parent); + parents_to_process = g_slist_prepend(parents_to_process, parent); + } + + for (entry = children_to_process; + entry != NULL; + entry = g_slist_next(entry)) { + child = entry->data; + bdrv_set_aio_context_ignore(child->bs, new_context, ignore); + } + g_slist_free(children_to_process); + + for (entry = parents_to_process; + entry != NULL; + entry = g_slist_next(entry)) { + parent = entry->data; + assert(parent->klass->set_aio_ctx); + parent->klass->set_aio_ctx(parent, new_context, ignore); } + g_slist_free(parents_to_process); bdrv_detach_aio_context(bs); diff --git a/block/nvme.c b/block/nvme.c index 5a6fbacf4a5f..2b5421e7aa6e 100644 --- a/block/nvme.c +++ b/block/nvme.c @@ -708,6 +708,7 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, AioContext *aio_context = bdrv_get_aio_context(bs); int ret; uint64_t cap; + uint32_t ver; uint64_t timeout_ms; uint64_t deadline, now; volatile NvmeBar *regs = NULL; @@ -745,7 +746,7 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, trace_nvme_controller_capability("Contiguous Queues Required", NVME_CAP_CQR(cap)); trace_nvme_controller_capability("Doorbell Stride", - 2 << (2 + NVME_CAP_DSTRD(cap))); + 1 << (2 + NVME_CAP_DSTRD(cap))); trace_nvme_controller_capability("Subsystem Reset Supported", NVME_CAP_NSSRS(cap)); trace_nvme_controller_capability("Memory Page Size Minimum", @@ -764,6 +765,11 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, bs->bl.request_alignment = s->page_size; timeout_ms = MIN(500 * NVME_CAP_TO(cap), 30000); + ver = le32_to_cpu(regs->vs); + trace_nvme_controller_spec_version(extract32(ver, 16, 16), + extract32(ver, 8, 8), + extract32(ver, 0, 8)); + /* Reset device to get a clean state. */ regs->cc = cpu_to_le32(le32_to_cpu(regs->cc) & 0xFE); /* Wait for CSTS.RDY = 0. */ diff --git a/block/qapi.c b/block/qapi.c index 0a96099e36e2..84a0aadc0950 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -677,7 +677,7 @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn) char *sizing = NULL; if (!sn) { - qemu_printf("%-10s%-18s%7s%20s%13s%11s", + qemu_printf("%-10s%-17s%8s%20s%13s%11s", "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK", "ICOUNT"); } else { ti = sn->date_sec; @@ -696,7 +696,7 @@ void bdrv_snapshot_dump(QEMUSnapshotInfo *sn) snprintf(icount_buf, sizeof(icount_buf), "%"PRId64, sn->icount); } - qemu_printf("%-9s %-17s %7s%20s%13s%11s", + qemu_printf("%-9s %-16s %8s%20s%13s%11s", sn->id_str, sn->name, sizing, date_buf, diff --git a/block/trace-events b/block/trace-events index 8368f4acb0bb..ecbc32a80a91 100644 --- a/block/trace-events +++ b/block/trace-events @@ -136,6 +136,7 @@ qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s # nvme.c nvme_controller_capability_raw(uint64_t value) "0x%08"PRIx64 nvme_controller_capability(const char *desc, uint64_t value) "%s: %"PRIu64 +nvme_controller_spec_version(uint32_t mjr, uint32_t mnr, uint32_t ter) "Specification supported: %u.%u.%u" nvme_kick(void *s, unsigned q_index) "s %p q #%u" nvme_dma_flush_queue_wait(void *s) "s %p" nvme_error(int cmd_specific, int sq_head, int sqid, int cid, int status) "cmd_specific %d sq_head %d sqid %d cid %d status 0x%x" diff --git a/qemu-nbd.c b/qemu-nbd.c index 0d513cb38c88..608c63e82a25 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -503,6 +503,7 @@ static const char *socket_activation_validate_opts(const char *device, static void qemu_nbd_shutdown(void) { job_cancel_sync_all(); + blk_exp_close_all(); bdrv_close_all(); } diff --git a/softmmu/runstate.c b/softmmu/runstate.c index beee050815db..a7fcb603f711 100644 --- a/softmmu/runstate.c +++ b/softmmu/runstate.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "audio/audio.h" #include "block/block.h" +#include "block/export.h" #include "chardev/char.h" #include "crypto/cipher.h" #include "crypto/init.h" @@ -784,6 +785,14 @@ void qemu_cleanup(void) */ migration_shutdown(); + /* + * Close the exports before draining the block layer. The export + * drivers may have coroutines yielding on it, so we need to clean + * them up before the drain, as otherwise they may be get stuck in + * blk_wait_while_drained(). + */ + blk_exp_close_all(); + /* * We must cancel all block jobs while the block layer is drained, * or cancelling will be affected by throttling and thus may block diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c index e0c87edbdd48..d8d172cc60a6 100644 --- a/storage-daemon/qemu-storage-daemon.c +++ b/storage-daemon/qemu-storage-daemon.c @@ -314,6 +314,7 @@ int main(int argc, char *argv[]) main_loop_wait(false); } + blk_exp_close_all(); bdrv_drain_all_begin(); bdrv_close_all(); diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check index 5190dee82e89..d1c87ceaf17f 100755 --- a/tests/qemu-iotests/check +++ b/tests/qemu-iotests/check @@ -140,4 +140,7 @@ if __name__ == '__main__': else: with TestRunner(env, makecheck=args.makecheck, color=args.color) as tr: - tr.run_tests([os.path.join(env.source_iotests, t) for t in tests]) + paths = [os.path.join(env.source_iotests, t) for t in tests] + ok = tr.run_tests(paths) + if not ok: + sys.exit(1) diff --git a/tests/qemu-iotests/pylintrc b/tests/qemu-iotests/pylintrc index cd3702e23c39..7a6c0a947400 100644 --- a/tests/qemu-iotests/pylintrc +++ b/tests/qemu-iotests/pylintrc @@ -21,6 +21,8 @@ disable=invalid-name, unsubscriptable-object, # These are temporary, and should be removed: missing-docstring, + too-many-return-statements, + too-many-statements [FORMAT] diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py index b31275f518b1..1fbec854c1f7 100644 --- a/tests/qemu-iotests/testenv.py +++ b/tests/qemu-iotests/testenv.py @@ -135,7 +135,7 @@ def root(*names: str) -> str: if not os.path.exists(self.qemu_prog): pattern = root('qemu-system-*') try: - progs = glob.iglob(pattern) + progs = sorted(glob.iglob(pattern)) self.qemu_prog = next(p for p in progs if isxfile(p)) except StopIteration: sys.exit("Not found any Qemu executable binary by pattern " diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py index 24b3fba1154f..1fc61fcaa344 100644 --- a/tests/qemu-iotests/testrunner.py +++ b/tests/qemu-iotests/testrunner.py @@ -301,8 +301,10 @@ def run_test(self, test: str, last_el = self.last_elapsed.get(test) start = datetime.datetime.now().strftime('%H:%M:%S') - self.test_print_one_line(test=test, starttime=start, lasttime=last_el, - end='\r', test_field_width=test_field_width) + if not self.makecheck: + self.test_print_one_line(test=test, starttime=start, + lasttime=last_el, end='\r', + test_field_width=test_field_width) res = self.do_run_test(test) @@ -318,7 +320,7 @@ def run_test(self, test: str, return res - def run_tests(self, tests: List[str]) -> None: + def run_tests(self, tests: List[str]) -> bool: n_run = 0 failed = [] notrun = [] @@ -363,5 +365,7 @@ def run_tests(self, tests: List[str]) -> None: if failed: print('Failures:', ' '.join(failed)) print(f'Failed {len(failed)} of {n_run} iotests') + return False else: print(f'Passed all {n_run} iotests') + return True