block: Introduce bdrv_open_child()
It is the same as bdrv_open_image(), except that it doesn't only return success or failure, but the newly created BdrvChild object for the new child node. As the BdrvChild object already contains a BlockDriverState pointer (and this is supposed to become the only pointer so that bdrv_append() and friends can just change a single pointer in BdrvChild), the pbs parameter is removed for bdrv_open_child(). Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
		
							parent
							
								
									df58179267
								
							
						
					
					
						commit
						b4b059f628
					
				
							
								
								
									
										63
									
								
								block.c
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								block.c
									
									
									
									
									
								
							@ -1102,7 +1102,7 @@ static int bdrv_fill_options(QDict **options, const char **pfilename,
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void bdrv_attach_child(BlockDriverState *parent_bs,
 | 
					static BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
 | 
				
			||||||
                                    BlockDriverState *child_bs,
 | 
					                                    BlockDriverState *child_bs,
 | 
				
			||||||
                                    const BdrvChildRole *child_role)
 | 
					                                    const BdrvChildRole *child_role)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -1113,6 +1113,8 @@ static void bdrv_attach_child(BlockDriverState *parent_bs,
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    QLIST_INSERT_HEAD(&parent_bs->children, child, next);
 | 
					    QLIST_INSERT_HEAD(&parent_bs->children, child, next);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return child;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
 | 
					void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
 | 
				
			||||||
@ -1229,7 +1231,7 @@ free_exit:
 | 
				
			|||||||
 * device's options.
 | 
					 * device's options.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * If allow_none is true, no image will be opened if filename is false and no
 | 
					 * If allow_none is true, no image will be opened if filename is false and no
 | 
				
			||||||
 * BlockdevRef is given. *pbs will remain unchanged and 0 will be returned.
 | 
					 * BlockdevRef is given. NULL will be returned, but errp remains unset.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * bdrev_key specifies the key for the image's BlockdevRef in the options QDict.
 | 
					 * bdrev_key specifies the key for the image's BlockdevRef in the options QDict.
 | 
				
			||||||
 * That QDict has to be flattened; therefore, if the BlockdevRef is a QDict
 | 
					 * That QDict has to be flattened; therefore, if the BlockdevRef is a QDict
 | 
				
			||||||
@ -1237,21 +1239,20 @@ free_exit:
 | 
				
			|||||||
 * BlockdevRef.
 | 
					 * BlockdevRef.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * The BlockdevRef will be removed from the options QDict.
 | 
					 * The BlockdevRef will be removed from the options QDict.
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * To conform with the behavior of bdrv_open(), *pbs has to be NULL.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int bdrv_open_image(BlockDriverState **pbs, const char *filename,
 | 
					BdrvChild *bdrv_open_child(const char *filename,
 | 
				
			||||||
                           QDict *options, const char *bdref_key,
 | 
					                           QDict *options, const char *bdref_key,
 | 
				
			||||||
                    BlockDriverState* parent, const BdrvChildRole *child_role,
 | 
					                           BlockDriverState* parent,
 | 
				
			||||||
 | 
					                           const BdrvChildRole *child_role,
 | 
				
			||||||
                           bool allow_none, Error **errp)
 | 
					                           bool allow_none, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    BdrvChild *c = NULL;
 | 
				
			||||||
 | 
					    BlockDriverState *bs;
 | 
				
			||||||
    QDict *image_options;
 | 
					    QDict *image_options;
 | 
				
			||||||
    int ret;
 | 
					    int ret;
 | 
				
			||||||
    char *bdref_key_dot;
 | 
					    char *bdref_key_dot;
 | 
				
			||||||
    const char *reference;
 | 
					    const char *reference;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert(pbs);
 | 
					 | 
				
			||||||
    assert(*pbs == NULL);
 | 
					 | 
				
			||||||
    assert(child_role != NULL);
 | 
					    assert(child_role != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bdref_key_dot = g_strdup_printf("%s.", bdref_key);
 | 
					    bdref_key_dot = g_strdup_printf("%s.", bdref_key);
 | 
				
			||||||
@ -1260,28 +1261,60 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    reference = qdict_get_try_str(options, bdref_key);
 | 
					    reference = qdict_get_try_str(options, bdref_key);
 | 
				
			||||||
    if (!filename && !reference && !qdict_size(image_options)) {
 | 
					    if (!filename && !reference && !qdict_size(image_options)) {
 | 
				
			||||||
        if (allow_none) {
 | 
					        if (!allow_none) {
 | 
				
			||||||
            ret = 0;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            error_setg(errp, "A block device must be specified for \"%s\"",
 | 
					            error_setg(errp, "A block device must be specified for \"%s\"",
 | 
				
			||||||
                       bdref_key);
 | 
					                       bdref_key);
 | 
				
			||||||
            ret = -EINVAL;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        QDECREF(image_options);
 | 
					        QDECREF(image_options);
 | 
				
			||||||
        goto done;
 | 
					        goto done;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = bdrv_open_inherit(pbs, filename, reference, image_options, 0,
 | 
					    bs = NULL;
 | 
				
			||||||
 | 
					    ret = bdrv_open_inherit(&bs, filename, reference, image_options, 0,
 | 
				
			||||||
                            parent, child_role, NULL, errp);
 | 
					                            parent, child_role, NULL, errp);
 | 
				
			||||||
    if (ret < 0) {
 | 
					    if (ret < 0) {
 | 
				
			||||||
        goto done;
 | 
					        goto done;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bdrv_attach_child(parent, *pbs, child_role);
 | 
					    c = bdrv_attach_child(parent, bs, child_role);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
done:
 | 
					done:
 | 
				
			||||||
    qdict_del(options, bdref_key);
 | 
					    qdict_del(options, bdref_key);
 | 
				
			||||||
    return ret;
 | 
					    return c;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This is a version of bdrv_open_child() that returns 0/-EINVAL instead of
 | 
				
			||||||
 | 
					 * a BdrvChild object.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If allow_none is true, no image will be opened if filename is false and no
 | 
				
			||||||
 | 
					 * BlockdevRef is given. *pbs will remain unchanged and 0 will be returned.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * To conform with the behavior of bdrv_open(), *pbs has to be NULL.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int bdrv_open_image(BlockDriverState **pbs, const char *filename,
 | 
				
			||||||
 | 
					                    QDict *options, const char *bdref_key,
 | 
				
			||||||
 | 
					                    BlockDriverState* parent, const BdrvChildRole *child_role,
 | 
				
			||||||
 | 
					                    bool allow_none, Error **errp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
 | 
					    BdrvChild *c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert(pbs);
 | 
				
			||||||
 | 
					    assert(*pbs == NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    c = bdrv_open_child(filename, options, bdref_key, parent, child_role,
 | 
				
			||||||
 | 
					                        allow_none, &local_err);
 | 
				
			||||||
 | 
					    if (local_err) {
 | 
				
			||||||
 | 
					        error_propagate(errp, local_err);
 | 
				
			||||||
 | 
					        return -EINVAL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (c != NULL) {
 | 
				
			||||||
 | 
					        *pbs = c->bs;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
 | 
					int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,7 @@
 | 
				
			|||||||
/* block.c */
 | 
					/* block.c */
 | 
				
			||||||
typedef struct BlockDriver BlockDriver;
 | 
					typedef struct BlockDriver BlockDriver;
 | 
				
			||||||
typedef struct BlockJob BlockJob;
 | 
					typedef struct BlockJob BlockJob;
 | 
				
			||||||
 | 
					typedef struct BdrvChild BdrvChild;
 | 
				
			||||||
typedef struct BdrvChildRole BdrvChildRole;
 | 
					typedef struct BdrvChildRole BdrvChildRole;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct BlockDriverInfo {
 | 
					typedef struct BlockDriverInfo {
 | 
				
			||||||
@ -208,6 +209,11 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename,
 | 
				
			|||||||
                    QDict *options, const char *bdref_key,
 | 
					                    QDict *options, const char *bdref_key,
 | 
				
			||||||
                    BlockDriverState* parent, const BdrvChildRole *child_role,
 | 
					                    BlockDriverState* parent, const BdrvChildRole *child_role,
 | 
				
			||||||
                    bool allow_none, Error **errp);
 | 
					                    bool allow_none, Error **errp);
 | 
				
			||||||
 | 
					BdrvChild *bdrv_open_child(const char *filename,
 | 
				
			||||||
 | 
					                           QDict *options, const char *bdref_key,
 | 
				
			||||||
 | 
					                           BlockDriverState* parent,
 | 
				
			||||||
 | 
					                           const BdrvChildRole *child_role,
 | 
				
			||||||
 | 
					                           bool allow_none, Error **errp);
 | 
				
			||||||
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd);
 | 
					void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd);
 | 
				
			||||||
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp);
 | 
					int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp);
 | 
				
			||||||
int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp);
 | 
					int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp);
 | 
				
			||||||
 | 
				
			|||||||
@ -335,11 +335,11 @@ struct BdrvChildRole {
 | 
				
			|||||||
extern const BdrvChildRole child_file;
 | 
					extern const BdrvChildRole child_file;
 | 
				
			||||||
extern const BdrvChildRole child_format;
 | 
					extern const BdrvChildRole child_format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct BdrvChild {
 | 
					struct BdrvChild {
 | 
				
			||||||
    BlockDriverState *bs;
 | 
					    BlockDriverState *bs;
 | 
				
			||||||
    const BdrvChildRole *role;
 | 
					    const BdrvChildRole *role;
 | 
				
			||||||
    QLIST_ENTRY(BdrvChild) next;
 | 
					    QLIST_ENTRY(BdrvChild) next;
 | 
				
			||||||
} BdrvChild;
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Note: the function bdrv_append() copies and swaps contents of
 | 
					 * Note: the function bdrv_append() copies and swaps contents of
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user