block.c (d70d595429ecd9ac4917e53453dd8979db8e5ffd) | block.c (2f30b7c377fa9a7dfbaf6eed56a07be7953e509e) |
---|---|
1/* 2 * QEMU System Emulator block driver 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights --- 3528 unchanged lines hidden (view full) --- 3537 blk_remove_all_bs(); 3538 blockdev_close_all_bdrv_states(); 3539 3540 assert(QTAILQ_EMPTY(&all_bdrv_states)); 3541} 3542 3543static bool should_update_child(BdrvChild *c, BlockDriverState *to) 3544{ | 1/* 2 * QEMU System Emulator block driver 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights --- 3528 unchanged lines hidden (view full) --- 3537 blk_remove_all_bs(); 3538 blockdev_close_all_bdrv_states(); 3539 3540 assert(QTAILQ_EMPTY(&all_bdrv_states)); 3541} 3542 3543static bool should_update_child(BdrvChild *c, BlockDriverState *to) 3544{ |
3545 BdrvChild *to_c; | 3545 GQueue *queue; 3546 GHashTable *found; 3547 bool ret; |
3546 3547 if (c->role->stay_at_node) { 3548 return false; 3549 } 3550 3551 /* If the child @c belongs to the BDS @to, replacing the current 3552 * c->bs by @to would mean to create a loop. 3553 * --- 19 unchanged lines hidden (view full) --- 3573 * | 3574 * v 3575 * node A -> further backing chain... 3576 * 3577 * In general, when replacing a node A (c->bs) by a node B (@to), 3578 * if A is a child of B, that means we cannot replace A by B there 3579 * because that would create a loop. Silently detaching A from B 3580 * is also not really an option. So overall just leaving A in | 3548 3549 if (c->role->stay_at_node) { 3550 return false; 3551 } 3552 3553 /* If the child @c belongs to the BDS @to, replacing the current 3554 * c->bs by @to would mean to create a loop. 3555 * --- 19 unchanged lines hidden (view full) --- 3575 * | 3576 * v 3577 * node A -> further backing chain... 3578 * 3579 * In general, when replacing a node A (c->bs) by a node B (@to), 3580 * if A is a child of B, that means we cannot replace A by B there 3581 * because that would create a loop. Silently detaching A from B 3582 * is also not really an option. So overall just leaving A in |
3581 * place there is the most sensible choice. */ 3582 QLIST_FOREACH(to_c, &to->children, next) { 3583 if (to_c == c) { 3584 return false; | 3583 * place there is the most sensible choice. 3584 * 3585 * We would also create a loop in any cases where @c is only 3586 * indirectly referenced by @to. Prevent this by returning false 3587 * if @c is found (by breadth-first search) anywhere in the whole 3588 * subtree of @to. 3589 */ 3590 3591 ret = true; 3592 found = g_hash_table_new(NULL, NULL); 3593 g_hash_table_add(found, to); 3594 queue = g_queue_new(); 3595 g_queue_push_tail(queue, to); 3596 3597 while (!g_queue_is_empty(queue)) { 3598 BlockDriverState *v = g_queue_pop_head(queue); 3599 BdrvChild *c2; 3600 3601 QLIST_FOREACH(c2, &v->children, next) { 3602 if (c2 == c) { 3603 ret = false; 3604 break; 3605 } 3606 3607 if (g_hash_table_contains(found, c2->bs)) { 3608 continue; 3609 } 3610 3611 g_queue_push_tail(queue, c2->bs); 3612 g_hash_table_add(found, c2->bs); |
3585 } 3586 } 3587 | 3613 } 3614 } 3615 |
3588 return true; | 3616 g_queue_free(queue); 3617 g_hash_table_destroy(found); 3618 3619 return ret; |
3589} 3590 3591void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, 3592 Error **errp) 3593{ 3594 BdrvChild *c, *next; 3595 GSList *list = NULL, *p; 3596 uint64_t old_perm, old_shared; --- 2050 unchanged lines hidden --- | 3620} 3621 3622void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, 3623 Error **errp) 3624{ 3625 BdrvChild *c, *next; 3626 GSList *list = NULL, *p; 3627 uint64_t old_perm, old_shared; --- 2050 unchanged lines hidden --- |