req->overlap_bytes = MAX(req->overlap_bytes, overlap_bytes);
}
+static bool is_request_serialising_and_aligned(BdrvTrackedRequest *req)
+{
+ /*
+ * If the request is serialising, overlap_offset and overlap_bytes are set,
+ * so we can check if the request is aligned. Otherwise, don't care and
+ * return false.
+ */
+
+ return req->serialising && (req->offset == req->overlap_offset) &&
+ (req->bytes == req->overlap_bytes);
+}
+
/**
* Round a region to cluster boundaries
*/
mark_request_serialising(req, bdrv_get_cluster_size(bs));
}
+ /* BDRV_REQ_SERIALISING is only for write operation */
+ assert(!(flags & BDRV_REQ_SERIALISING));
+
if (!(flags & BDRV_REQ_NO_SERIALISING)) {
wait_serialising_requests(req);
}
/* BDRV_REQ_NO_SERIALISING is only for read operation */
assert(!(flags & BDRV_REQ_NO_SERIALISING));
+
+ if (flags & BDRV_REQ_SERIALISING) {
+ mark_request_serialising(req, bdrv_get_cluster_size(bs));
+ }
+
waited = wait_serialising_requests(req);
- assert(!waited || !req->serialising);
+ assert(!waited || !req->serialising ||
+ is_request_serialising_and_aligned(req));
assert(req->overlap_offset <= offset);
assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
if (flags & BDRV_REQ_WRITE_UNCHANGED) {
tracked_request_begin(&req, src->bs, src_offset, bytes,
BDRV_TRACKED_READ);
+ /* BDRV_REQ_SERIALISING is only for write operation */
+ assert(!(read_flags & BDRV_REQ_SERIALISING));
if (!(read_flags & BDRV_REQ_NO_SERIALISING)) {
wait_serialising_requests(&req);
}
/* BDRV_REQ_NO_SERIALISING is only for read operation */
assert(!(write_flags & BDRV_REQ_NO_SERIALISING));
+ if (write_flags & BDRV_REQ_SERIALISING) {
+ mark_request_serialising(&req, bdrv_get_cluster_size(dst->bs));
+ }
wait_serialising_requests(&req);
ret = dst->bs->drv->bdrv_co_copy_range_to(dst->bs,
* content. */
BDRV_REQ_WRITE_UNCHANGED = 0x40,
+ /*
+ * BDRV_REQ_SERIALISING forces request serialisation for writes.
+ * It is used to ensure that writes to the backing file of a backup process
+ * target cannot race with a read of the backup target that defers to the
+ * backing file.
+ *
+ * Note, that BDRV_REQ_SERIALISING is _not_ opposite in meaning to
+ * BDRV_REQ_NO_SERIALISING. A more descriptive name for the latter might be
+ * _DO_NOT_WAIT_FOR_SERIALISING, except that is too long.
+ */
+ BDRV_REQ_SERIALISING = 0x80,
+
/* Mask of valid flags */
- BDRV_REQ_MASK = 0x7f,
+ BDRV_REQ_MASK = 0xff,
} BdrvRequestFlags;
typedef struct BlockSizes {