aboutsummaryrefslogtreecommitdiff
path: root/block.c
diff options
context:
space:
mode:
authorMax Reitz <mreitz@redhat.com>2019-05-31 15:23:11 +0200
committerKevin Wolf <kwolf@redhat.com>2020-09-07 12:31:30 +0200
commit9a6fc88799cc9a68d2821e49665ca50de75f399c (patch)
treec3072a6da90340dfc703e5463265d06c06e66d43 /block.c
parentb111b3fcdecc7ce441fa6760e116c3c45b4b8133 (diff)
block: Add child access functions
There are BDS children that the general block layer code can access, namely bs->file and bs->backing. Since the introduction of filters and external data files, their meaning is not quite clear. bs->backing can be a COW source, or it can be a filtered child; bs->file can be a filtered child, it can be data and metadata storage, or it can be just metadata storage. This overloading really is not helpful. This patch adds functions that retrieve the correct child for each exact purpose. Later patches in this series will make use of them. Doing so will allow us to handle filter nodes in a meaningful way. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Diffstat (limited to 'block.c')
-rw-r--r--block.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/block.c b/block.c
index b204b93a2e..9f866e8676 100644
--- a/block.c
+++ b/block.c
@@ -6943,3 +6943,94 @@ int bdrv_make_empty(BdrvChild *c, Error **errp)
return 0;
}
+
+/*
+ * Return the child that @bs acts as an overlay for, and from which data may be
+ * copied in COW or COR operations. Usually this is the backing file.
+ */
+BdrvChild *bdrv_cow_child(BlockDriverState *bs)
+{
+ if (!bs || !bs->drv) {
+ return NULL;
+ }
+
+ if (bs->drv->is_filter) {
+ return NULL;
+ }
+
+ if (!bs->backing) {
+ return NULL;
+ }
+
+ assert(bs->backing->role & BDRV_CHILD_COW);
+ return bs->backing;
+}
+
+/*
+ * If @bs acts as a filter for exactly one of its children, return
+ * that child.
+ */
+BdrvChild *bdrv_filter_child(BlockDriverState *bs)
+{
+ BdrvChild *c;
+
+ if (!bs || !bs->drv) {
+ return NULL;
+ }
+
+ if (!bs->drv->is_filter) {
+ return NULL;
+ }
+
+ /* Only one of @backing or @file may be used */
+ assert(!(bs->backing && bs->file));
+
+ c = bs->backing ?: bs->file;
+ if (!c) {
+ return NULL;
+ }
+
+ assert(c->role & BDRV_CHILD_FILTERED);
+ return c;
+}
+
+/*
+ * Return either the result of bdrv_cow_child() or bdrv_filter_child(),
+ * whichever is non-NULL.
+ *
+ * Return NULL if both are NULL.
+ */
+BdrvChild *bdrv_filter_or_cow_child(BlockDriverState *bs)
+{
+ BdrvChild *cow_child = bdrv_cow_child(bs);
+ BdrvChild *filter_child = bdrv_filter_child(bs);
+
+ /* Filter nodes cannot have COW backing files */
+ assert(!(cow_child && filter_child));
+
+ return cow_child ?: filter_child;
+}
+
+/*
+ * Return the primary child of this node: For filters, that is the
+ * filtered child. For other nodes, that is usually the child storing
+ * metadata.
+ * (A generally more helpful description is that this is (usually) the
+ * child that has the same filename as @bs.)
+ *
+ * Drivers do not necessarily have a primary child; for example quorum
+ * does not.
+ */
+BdrvChild *bdrv_primary_child(BlockDriverState *bs)
+{
+ BdrvChild *c, *found = NULL;
+
+ QLIST_FOREACH(c, &bs->children, next) {
+ if (c->role & BDRV_CHILD_PRIMARY) {
+ assert(!found);
+ found = c;
+ }
+ }
+
+ return found;
+}