Commit e06018ad authored by Wen Congyang's avatar Wen Congyang Committed by Max Reitz
Browse files

Add new block driver interface to add/delete a BDS's child



In some cases, we want to take a quorum child offline, and take
another child online.

Signed-off-by: default avatarWen Congyang <wency@cn.fujitsu.com>
Signed-off-by: default avatarzhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: default avatarGonglei <arei.gonglei@huawei.com>
Signed-off-by: default avatarChanglong Xie <xiecl.fnst@cn.fujitsu.com>
Reviewed-by: default avatarMax Reitz <mreitz@redhat.com>
Reviewed-by: default avatarAlberto Garcia <berto@igalia.com>
Message-id: 1462865799-19402-2-git-send-email-xiecl.fnst@cn.fujitsu.com
Signed-off-by: default avatarMax Reitz <mreitz@redhat.com>
parent 263a6f4c
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -4011,3 +4011,52 @@ void bdrv_refresh_filename(BlockDriverState *bs)
        QDECREF(json);
    }
}

/*
 * Hot add/remove a BDS's child. So the user can take a child offline when
 * it is broken and take a new child online
 */
void bdrv_add_child(BlockDriverState *parent_bs, BlockDriverState *child_bs,
                    Error **errp)
{

    if (!parent_bs->drv || !parent_bs->drv->bdrv_add_child) {
        error_setg(errp, "The node %s does not support adding a child",
                   bdrv_get_device_or_node_name(parent_bs));
        return;
    }

    if (!QLIST_EMPTY(&child_bs->parents)) {
        error_setg(errp, "The node %s already has a parent",
                   child_bs->node_name);
        return;
    }

    parent_bs->drv->bdrv_add_child(parent_bs, child_bs, errp);
}

void bdrv_del_child(BlockDriverState *parent_bs, BdrvChild *child, Error **errp)
{
    BdrvChild *tmp;

    if (!parent_bs->drv || !parent_bs->drv->bdrv_del_child) {
        error_setg(errp, "The node %s does not support removing a child",
                   bdrv_get_device_or_node_name(parent_bs));
        return;
    }

    QLIST_FOREACH(tmp, &parent_bs->children, next) {
        if (tmp == child) {
            break;
        }
    }

    if (!tmp) {
        error_setg(errp, "The node %s does not have a child named %s",
                   bdrv_get_device_or_node_name(parent_bs),
                   bdrv_get_device_or_node_name(child->bs));
        return;
    }

    parent_bs->drv->bdrv_del_child(parent_bs, child, errp);
}
+4 −0
Original line number Diff line number Diff line
@@ -542,4 +542,8 @@ void bdrv_drained_begin(BlockDriverState *bs);
 */
void bdrv_drained_end(BlockDriverState *bs);

void bdrv_add_child(BlockDriverState *parent, BlockDriverState *child,
                    Error **errp);
void bdrv_del_child(BlockDriverState *parent, BdrvChild *child, Error **errp);

#endif
+5 −0
Original line number Diff line number Diff line
@@ -314,6 +314,11 @@ struct BlockDriver {
     */
    void (*bdrv_drain)(BlockDriverState *bs);

    void (*bdrv_add_child)(BlockDriverState *parent, BlockDriverState *child,
                           Error **errp);
    void (*bdrv_del_child)(BlockDriverState *parent, BdrvChild *child,
                           Error **errp);

    QLIST_ENTRY(BlockDriver) list;
};