41
41
static int coroutine_fn bdrv_co_do_pwrite_zeroes (BlockDriverState * bs ,
42
42
int64_t offset , int bytes , BdrvRequestFlags flags );
43
43
44
- void bdrv_parent_drained_begin (BlockDriverState * bs , BdrvChild * ignore )
44
+ void bdrv_parent_drained_begin (BlockDriverState * bs , BdrvChild * ignore ,
45
+ bool ignore_bds_parents )
45
46
{
46
47
BdrvChild * c , * next ;
47
48
48
49
QLIST_FOREACH_SAFE (c , & bs -> parents , next_parent , next ) {
49
- if (c == ignore ) {
50
+ if (c == ignore || ( ignore_bds_parents && c -> role -> parent_is_bds ) ) {
50
51
continue ;
51
52
}
52
53
if (c -> role -> drained_begin ) {
@@ -55,12 +56,13 @@ void bdrv_parent_drained_begin(BlockDriverState *bs, BdrvChild *ignore)
55
56
}
56
57
}
57
58
58
- void bdrv_parent_drained_end (BlockDriverState * bs , BdrvChild * ignore )
59
+ void bdrv_parent_drained_end (BlockDriverState * bs , BdrvChild * ignore ,
60
+ bool ignore_bds_parents )
59
61
{
60
62
BdrvChild * c , * next ;
61
63
62
64
QLIST_FOREACH_SAFE (c , & bs -> parents , next_parent , next ) {
63
- if (c == ignore ) {
65
+ if (c == ignore || ( ignore_bds_parents && c -> role -> parent_is_bds ) ) {
64
66
continue ;
65
67
}
66
68
if (c -> role -> drained_end ) {
@@ -69,13 +71,14 @@ void bdrv_parent_drained_end(BlockDriverState *bs, BdrvChild *ignore)
69
71
}
70
72
}
71
73
72
- static bool bdrv_parent_drained_poll (BlockDriverState * bs , BdrvChild * ignore )
74
+ static bool bdrv_parent_drained_poll (BlockDriverState * bs , BdrvChild * ignore ,
75
+ bool ignore_bds_parents )
73
76
{
74
77
BdrvChild * c , * next ;
75
78
bool busy = false;
76
79
77
80
QLIST_FOREACH_SAFE (c , & bs -> parents , next_parent , next ) {
78
- if (c == ignore ) {
81
+ if (c == ignore || ( ignore_bds_parents && c -> role -> parent_is_bds ) ) {
79
82
continue ;
80
83
}
81
84
if (c -> role -> drained_poll ) {
@@ -167,6 +170,7 @@ typedef struct {
167
170
bool recursive ;
168
171
bool poll ;
169
172
BdrvChild * parent ;
173
+ bool ignore_bds_parents ;
170
174
} BdrvCoDrainData ;
171
175
172
176
static void coroutine_fn bdrv_drain_invoke_entry (void * opaque )
@@ -220,11 +224,11 @@ static void bdrv_drain_invoke(BlockDriverState *bs, bool begin)
220
224
221
225
/* Returns true if BDRV_POLL_WHILE() should go into a blocking aio_poll() */
222
226
bool bdrv_drain_poll (BlockDriverState * bs , bool recursive ,
223
- BdrvChild * ignore_parent )
227
+ BdrvChild * ignore_parent , bool ignore_bds_parents )
224
228
{
225
229
BdrvChild * child , * next ;
226
230
227
- if (bdrv_parent_drained_poll (bs , ignore_parent )) {
231
+ if (bdrv_parent_drained_poll (bs , ignore_parent , ignore_bds_parents )) {
228
232
return true;
229
233
}
230
234
@@ -233,8 +237,9 @@ bool bdrv_drain_poll(BlockDriverState *bs, bool recursive,
233
237
}
234
238
235
239
if (recursive ) {
240
+ assert (!ignore_bds_parents );
236
241
QLIST_FOREACH_SAFE (child , & bs -> children , next , next ) {
237
- if (bdrv_drain_poll (child -> bs , recursive , child )) {
242
+ if (bdrv_drain_poll (child -> bs , recursive , child , false )) {
238
243
return true;
239
244
}
240
245
}
@@ -250,13 +255,14 @@ static bool bdrv_drain_poll_top_level(BlockDriverState *bs, bool recursive,
250
255
* have executed. */
251
256
while (aio_poll (bs -> aio_context , false));
252
257
253
- return bdrv_drain_poll (bs , recursive , ignore_parent );
258
+ return bdrv_drain_poll (bs , recursive , ignore_parent , false );
254
259
}
255
260
256
261
static void bdrv_do_drained_begin (BlockDriverState * bs , bool recursive ,
257
- BdrvChild * parent , bool poll );
262
+ BdrvChild * parent , bool ignore_bds_parents ,
263
+ bool poll );
258
264
static void bdrv_do_drained_end (BlockDriverState * bs , bool recursive ,
259
- BdrvChild * parent );
265
+ BdrvChild * parent , bool ignore_bds_parents );
260
266
261
267
static void bdrv_co_drain_bh_cb (void * opaque )
262
268
{
@@ -267,9 +273,11 @@ static void bdrv_co_drain_bh_cb(void *opaque)
267
273
if (bs ) {
268
274
bdrv_dec_in_flight (bs );
269
275
if (data -> begin ) {
270
- bdrv_do_drained_begin (bs , data -> recursive , data -> parent , data -> poll );
276
+ bdrv_do_drained_begin (bs , data -> recursive , data -> parent ,
277
+ data -> ignore_bds_parents , data -> poll );
271
278
} else {
272
- bdrv_do_drained_end (bs , data -> recursive , data -> parent );
279
+ bdrv_do_drained_end (bs , data -> recursive , data -> parent ,
280
+ data -> ignore_bds_parents );
273
281
}
274
282
} else {
275
283
assert (data -> begin );
@@ -282,7 +290,9 @@ static void bdrv_co_drain_bh_cb(void *opaque)
282
290
283
291
static void coroutine_fn bdrv_co_yield_to_drain (BlockDriverState * bs ,
284
292
bool begin , bool recursive ,
285
- BdrvChild * parent , bool poll )
293
+ BdrvChild * parent ,
294
+ bool ignore_bds_parents ,
295
+ bool poll )
286
296
{
287
297
BdrvCoDrainData data ;
288
298
@@ -297,6 +307,7 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
297
307
.begin = begin ,
298
308
.recursive = recursive ,
299
309
.parent = parent ,
310
+ .ignore_bds_parents = ignore_bds_parents ,
300
311
.poll = poll ,
301
312
};
302
313
if (bs ) {
@@ -312,7 +323,7 @@ static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs,
312
323
}
313
324
314
325
void bdrv_do_drained_begin_quiesce (BlockDriverState * bs ,
315
- BdrvChild * parent )
326
+ BdrvChild * parent , bool ignore_bds_parents )
316
327
{
317
328
assert (!qemu_in_coroutine ());
318
329
@@ -321,26 +332,30 @@ void bdrv_do_drained_begin_quiesce(BlockDriverState *bs,
321
332
aio_disable_external (bdrv_get_aio_context (bs ));
322
333
}
323
334
324
- bdrv_parent_drained_begin (bs , parent );
335
+ bdrv_parent_drained_begin (bs , parent , ignore_bds_parents );
325
336
bdrv_drain_invoke (bs , true);
326
337
}
327
338
328
339
static void bdrv_do_drained_begin (BlockDriverState * bs , bool recursive ,
329
- BdrvChild * parent , bool poll )
340
+ BdrvChild * parent , bool ignore_bds_parents ,
341
+ bool poll )
330
342
{
331
343
BdrvChild * child , * next ;
332
344
333
345
if (qemu_in_coroutine ()) {
334
- bdrv_co_yield_to_drain (bs , true, recursive , parent , poll );
346
+ bdrv_co_yield_to_drain (bs , true, recursive , parent , ignore_bds_parents ,
347
+ poll );
335
348
return ;
336
349
}
337
350
338
- bdrv_do_drained_begin_quiesce (bs , parent );
351
+ bdrv_do_drained_begin_quiesce (bs , parent , ignore_bds_parents );
339
352
340
353
if (recursive ) {
354
+ assert (!ignore_bds_parents );
341
355
bs -> recursive_quiesce_counter ++ ;
342
356
QLIST_FOREACH_SAFE (child , & bs -> children , next , next ) {
343
- bdrv_do_drained_begin (child -> bs , true, child , false);
357
+ bdrv_do_drained_begin (child -> bs , true, child , ignore_bds_parents ,
358
+ false);
344
359
}
345
360
}
346
361
@@ -354,64 +369,67 @@ static void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive,
354
369
* nodes.
355
370
*/
356
371
if (poll ) {
372
+ assert (!ignore_bds_parents );
357
373
BDRV_POLL_WHILE (bs , bdrv_drain_poll_top_level (bs , recursive , parent ));
358
374
}
359
375
}
360
376
361
377
void bdrv_drained_begin (BlockDriverState * bs )
362
378
{
363
- bdrv_do_drained_begin (bs , false, NULL , true);
379
+ bdrv_do_drained_begin (bs , false, NULL , false, true);
364
380
}
365
381
366
382
void bdrv_subtree_drained_begin (BlockDriverState * bs )
367
383
{
368
- bdrv_do_drained_begin (bs , true, NULL , true);
384
+ bdrv_do_drained_begin (bs , true, NULL , false, true);
369
385
}
370
386
371
- void bdrv_do_drained_end (BlockDriverState * bs , bool recursive ,
372
- BdrvChild * parent )
387
+ static void bdrv_do_drained_end (BlockDriverState * bs , bool recursive ,
388
+ BdrvChild * parent , bool ignore_bds_parents )
373
389
{
374
390
BdrvChild * child , * next ;
375
391
int old_quiesce_counter ;
376
392
377
393
if (qemu_in_coroutine ()) {
378
- bdrv_co_yield_to_drain (bs , false, recursive , parent , false);
394
+ bdrv_co_yield_to_drain (bs , false, recursive , parent , ignore_bds_parents ,
395
+ false);
379
396
return ;
380
397
}
381
398
assert (bs -> quiesce_counter > 0 );
382
399
old_quiesce_counter = atomic_fetch_dec (& bs -> quiesce_counter );
383
400
384
401
/* Re-enable things in child-to-parent order */
385
402
bdrv_drain_invoke (bs , false);
386
- bdrv_parent_drained_end (bs , parent );
403
+ bdrv_parent_drained_end (bs , parent , ignore_bds_parents );
387
404
if (old_quiesce_counter == 1 ) {
388
405
aio_enable_external (bdrv_get_aio_context (bs ));
389
406
}
390
407
391
408
if (recursive ) {
409
+ assert (!ignore_bds_parents );
392
410
bs -> recursive_quiesce_counter -- ;
393
411
QLIST_FOREACH_SAFE (child , & bs -> children , next , next ) {
394
- bdrv_do_drained_end (child -> bs , true, child );
412
+ bdrv_do_drained_end (child -> bs , true, child , ignore_bds_parents );
395
413
}
396
414
}
397
415
}
398
416
399
417
void bdrv_drained_end (BlockDriverState * bs )
400
418
{
401
- bdrv_do_drained_end (bs , false, NULL );
419
+ bdrv_do_drained_end (bs , false, NULL , false );
402
420
}
403
421
404
422
void bdrv_subtree_drained_end (BlockDriverState * bs )
405
423
{
406
- bdrv_do_drained_end (bs , true, NULL );
424
+ bdrv_do_drained_end (bs , true, NULL , false );
407
425
}
408
426
409
427
void bdrv_apply_subtree_drain (BdrvChild * child , BlockDriverState * new_parent )
410
428
{
411
429
int i ;
412
430
413
431
for (i = 0 ; i < new_parent -> recursive_quiesce_counter ; i ++ ) {
414
- bdrv_do_drained_begin (child -> bs , true, child , true);
432
+ bdrv_do_drained_begin (child -> bs , true, child , false, true);
415
433
}
416
434
}
417
435
@@ -420,7 +438,7 @@ void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent)
420
438
int i ;
421
439
422
440
for (i = 0 ; i < old_parent -> recursive_quiesce_counter ; i ++ ) {
423
- bdrv_do_drained_end (child -> bs , true, child );
441
+ bdrv_do_drained_end (child -> bs , true, child , false );
424
442
}
425
443
}
426
444
@@ -472,7 +490,7 @@ void bdrv_drain_all_begin(void)
472
490
BdrvNextIterator it ;
473
491
474
492
if (qemu_in_coroutine ()) {
475
- bdrv_co_yield_to_drain (NULL , true, false, NULL , true);
493
+ bdrv_co_yield_to_drain (NULL , true, false, NULL , false, true);
476
494
return ;
477
495
}
478
496
@@ -486,7 +504,7 @@ void bdrv_drain_all_begin(void)
486
504
AioContext * aio_context = bdrv_get_aio_context (bs );
487
505
488
506
aio_context_acquire (aio_context );
489
- bdrv_do_drained_begin (bs , true, NULL , true);
507
+ bdrv_do_drained_begin (bs , true, NULL , false, true);
490
508
aio_context_release (aio_context );
491
509
}
492
510
@@ -504,7 +522,7 @@ void bdrv_drain_all_end(void)
504
522
AioContext * aio_context = bdrv_get_aio_context (bs );
505
523
506
524
aio_context_acquire (aio_context );
507
- bdrv_do_drained_end (bs , true, NULL );
525
+ bdrv_do_drained_end (bs , true, NULL , false );
508
526
aio_context_release (aio_context );
509
527
}
510
528
}
0 commit comments