2217 |
2217 |
*/
|
2218 |
2218 |
static void tracked_request_begin(BdrvTrackedRequest *req,
|
2219 |
2219 |
BlockDriverState *bs,
|
2220 |
|
int64_t sector_num,
|
2221 |
|
int nb_sectors, bool is_write)
|
|
2220 |
int64_t offset,
|
|
2221 |
unsigned int bytes, bool is_write)
|
2222 |
2222 |
{
|
2223 |
2223 |
*req = (BdrvTrackedRequest){
|
2224 |
2224 |
.bs = bs,
|
2225 |
|
.sector_num = sector_num,
|
2226 |
|
.nb_sectors = nb_sectors,
|
|
2225 |
.offset = offset,
|
|
2226 |
.bytes = bytes,
|
2227 |
2227 |
.is_write = is_write,
|
2228 |
2228 |
.co = qemu_coroutine_self(),
|
2229 |
2229 |
};
|
... | ... | |
2254 |
2254 |
}
|
2255 |
2255 |
}
|
2256 |
2256 |
|
|
2257 |
static void round_bytes_to_clusters(BlockDriverState *bs,
|
|
2258 |
int64_t offset, unsigned int bytes,
|
|
2259 |
int64_t *cluster_offset,
|
|
2260 |
unsigned int *cluster_bytes)
|
|
2261 |
{
|
|
2262 |
BlockDriverInfo bdi;
|
|
2263 |
|
|
2264 |
if (bdrv_get_info(bs, &bdi) < 0 || bdi.cluster_size == 0) {
|
|
2265 |
*cluster_offset = offset;
|
|
2266 |
*cluster_bytes = bytes;
|
|
2267 |
} else {
|
|
2268 |
*cluster_offset = QEMU_ALIGN_DOWN(offset, bdi.cluster_size);
|
|
2269 |
*cluster_bytes = QEMU_ALIGN_UP(offset - *cluster_offset + bytes,
|
|
2270 |
bdi.cluster_size);
|
|
2271 |
}
|
|
2272 |
}
|
|
2273 |
|
2257 |
2274 |
static bool tracked_request_overlaps(BdrvTrackedRequest *req,
|
2258 |
|
int64_t sector_num, int nb_sectors) {
|
|
2275 |
int64_t offset, unsigned int bytes)
|
|
2276 |
{
|
2259 |
2277 |
/* aaaa bbbb */
|
2260 |
|
if (sector_num >= req->sector_num + req->nb_sectors) {
|
|
2278 |
if (offset >= req->offset + req->bytes) {
|
2261 |
2279 |
return false;
|
2262 |
2280 |
}
|
2263 |
2281 |
/* bbbb aaaa */
|
2264 |
|
if (req->sector_num >= sector_num + nb_sectors) {
|
|
2282 |
if (req->offset >= offset + bytes) {
|
2265 |
2283 |
return false;
|
2266 |
2284 |
}
|
2267 |
2285 |
return true;
|
2268 |
2286 |
}
|
2269 |
2287 |
|
2270 |
2288 |
static void coroutine_fn wait_for_overlapping_requests(BlockDriverState *bs,
|
2271 |
|
int64_t sector_num, int nb_sectors)
|
|
2289 |
int64_t offset, unsigned int bytes)
|
2272 |
2290 |
{
|
2273 |
2291 |
BdrvTrackedRequest *req;
|
2274 |
|
int64_t cluster_sector_num;
|
2275 |
|
int cluster_nb_sectors;
|
|
2292 |
int64_t cluster_offset;
|
|
2293 |
unsigned int cluster_bytes;
|
2276 |
2294 |
bool retry;
|
2277 |
2295 |
|
2278 |
2296 |
/* If we touch the same cluster it counts as an overlap. This guarantees
|
... | ... | |
2281 |
2299 |
* CoR read and write operations are atomic and guest writes cannot
|
2282 |
2300 |
* interleave between them.
|
2283 |
2301 |
*/
|
2284 |
|
bdrv_round_to_clusters(bs, sector_num, nb_sectors,
|
2285 |
|
&cluster_sector_num, &cluster_nb_sectors);
|
|
2302 |
round_bytes_to_clusters(bs, offset, bytes, &cluster_offset, &cluster_bytes);
|
2286 |
2303 |
|
2287 |
2304 |
do {
|
2288 |
2305 |
retry = false;
|
2289 |
2306 |
QLIST_FOREACH(req, &bs->tracked_requests, list) {
|
2290 |
|
if (tracked_request_overlaps(req, cluster_sector_num,
|
2291 |
|
cluster_nb_sectors)) {
|
|
2307 |
if (tracked_request_overlaps(req, cluster_offset, cluster_bytes)) {
|
2292 |
2308 |
/* Hitting this means there was a reentrant request, for
|
2293 |
2309 |
* example, a block driver issuing nested requests. This must
|
2294 |
2310 |
* never happen since it means deadlock.
|
... | ... | |
2908 |
2924 |
}
|
2909 |
2925 |
|
2910 |
2926 |
if (bs->copy_on_read_in_flight) {
|
2911 |
|
wait_for_overlapping_requests(bs, sector_num, nb_sectors);
|
|
2927 |
wait_for_overlapping_requests(bs, offset, bytes);
|
2912 |
2928 |
}
|
2913 |
2929 |
|
2914 |
|
tracked_request_begin(&req, bs, sector_num, nb_sectors, false);
|
|
2930 |
tracked_request_begin(&req, bs, offset, bytes, false);
|
2915 |
2931 |
|
2916 |
2932 |
if (flags & BDRV_REQ_COPY_ON_READ) {
|
2917 |
2933 |
int pnum;
|
... | ... | |
3160 |
3176 |
assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
|
3161 |
3177 |
|
3162 |
3178 |
if (bs->copy_on_read_in_flight) {
|
3163 |
|
wait_for_overlapping_requests(bs, sector_num, nb_sectors);
|
|
3179 |
wait_for_overlapping_requests(bs, offset, bytes);
|
3164 |
3180 |
}
|
3165 |
3181 |
|
3166 |
|
tracked_request_begin(&req, bs, sector_num, nb_sectors, true);
|
|
3182 |
tracked_request_begin(&req, bs, offset, bytes, true);
|
3167 |
3183 |
|
3168 |
3184 |
ret = notifier_with_return_list_notify(&bs->before_write_notifiers, &req);
|
3169 |
3185 |
|