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 ---