static void coroutine_fn wait_for_overlapping_requests(BlockDriverState *bs, BdrvTrackedRequest *self, int64_t offset, unsigned int bytes) { BdrvTrackedRequest *req; int64_t cluster_offset; unsigned int cluster_bytes; bool retry; /* If we touch the same cluster it counts as an overlap. This guarantees * that allocating writes will be serialized and not race with each other * for the same cluster. For example, in copy-on-read it ensures that the * CoR read and write operations are atomic and guest writes cannot * interleave between them. */ round_bytes_to_clusters(bs, offset, bytes, &cluster_offset, &cluster_bytes); do { retry = false; QLIST_FOREACH(req, &bs->tracked_requests, list) { if (req == self) { continue; } if (tracked_request_overlaps(req, cluster_offset, cluster_bytes)) { /* Hitting this means there was a reentrant request, for * example, a block driver issuing nested requests. This must * never happen since it means deadlock. */ assert(qemu_coroutine_self() != req->co); qemu_co_queue_wait(&req->wait_queue); retry = true; break; } } } while (retry); }