On Fri 07 Aug 2015 03:03:07 AM CEST, Wen Congyang wrote: >>> +void bdrv_add_child(BlockDriverState *bs, QDict *options, Error **errp) >>> +{ >>> + >>> + if (!bs->drv || !bs->drv->bdrv_add_child) { >>> + error_setg(errp, "The BDS %s doesn't support adding a child", >>> + bdrv_get_id_or_node_name(bs)); >>> + return; >>> + } >>> + >>> + bs->drv->bdrv_add_child(bs, options, errp); >>> +} >>> + >>> +void bdrv_del_child(BlockDriverState *bs, BlockDriverState *child_bs, >>> + Error **errp) >>> +{ >>> + BdrvChild *child; >>> + >>> + if (!bs->drv || !bs->drv->bdrv_del_child) { >>> + error_setg(errp, "The BDS %s doesn't support removing a child", >>> + bdrv_get_id_or_node_name(bs)); >>> + return; >>> + } >>> + >>> + QLIST_FOREACH(child, &bs->children, next) { >>> + if (child->bs == child_bs) { >>> + break; >>> + } >>> + } >>> + >>> + if (!child) { >>> + error_setg(errp, "The BDS %s is not the BDS %s's child", >>> + bdrv_get_id_or_node_name(child_bs), >>> + bdrv_get_id_or_node_name(bs)); >>> + return; >>> + } >>> + >>> + bs->drv->bdrv_del_child(bs, child_bs, errp); >>> +} >> >> I see that bdrv_del_child() checks that the child is in bs->children, >> but who takes care of putting it there in the first place? > > The child is opened by the function bdrv_open_image(). > bdrv_open_image() > bdrv_open_child() > bdrv_attach_child()
I see, it's drv->bdrv_add_child() who takes care of opening the image, this only provides the BlockdevOptions. Thanks! Reviewed-by: Alberto Garcia <be...@igalia.com> Berto