]> git.proxmox.com Git - mirror_qemu.git/blame - block/block-backend.c
block: New BlockBackend
[mirror_qemu.git] / block / block-backend.c
CommitLineData
26f54e9a
MA
1/*
2 * QEMU Block backends
3 *
4 * Copyright (C) 2014 Red Hat, Inc.
5 *
6 * Authors:
7 * Markus Armbruster <armbru@redhat.com>,
8 *
9 * This work is licensed under the terms of the GNU LGPL, version 2.1
10 * or later. See the COPYING.LIB file in the top-level directory.
11 */
12
13#include "sysemu/block-backend.h"
14#include "block/block_int.h"
15
16struct BlockBackend {
17 char *name;
18 int refcnt;
19 QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
20};
21
22/* All the BlockBackends */
23static QTAILQ_HEAD(, BlockBackend) blk_backends =
24 QTAILQ_HEAD_INITIALIZER(blk_backends);
25
26/*
27 * Create a new BlockBackend with @name, with a reference count of one.
28 * @name must not be null or empty.
29 * Fail if a BlockBackend with this name already exists.
30 * Store an error through @errp on failure, unless it's null.
31 * Return the new BlockBackend on success, null on failure.
32 */
33BlockBackend *blk_new(const char *name, Error **errp)
34{
35 BlockBackend *blk;
36
37 assert(name && name[0]);
38 if (blk_by_name(name)) {
39 error_setg(errp, "Device with id '%s' already exists", name);
40 return NULL;
41 }
42
43 blk = g_new0(BlockBackend, 1);
44 blk->name = g_strdup(name);
45 blk->refcnt = 1;
46 QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
47 return blk;
48}
49
50static void blk_delete(BlockBackend *blk)
51{
52 assert(!blk->refcnt);
53 QTAILQ_REMOVE(&blk_backends, blk, link);
54 g_free(blk->name);
55 g_free(blk);
56}
57
58/*
59 * Increment @blk's reference count.
60 * @blk must not be null.
61 */
62void blk_ref(BlockBackend *blk)
63{
64 blk->refcnt++;
65}
66
67/*
68 * Decrement @blk's reference count.
69 * If this drops it to zero, destroy @blk.
70 * For convenience, do nothing if @blk is null.
71 */
72void blk_unref(BlockBackend *blk)
73{
74 if (blk) {
75 assert(blk->refcnt > 0);
76 if (!--blk->refcnt) {
77 blk_delete(blk);
78 }
79 }
80}
81
82/*
83 * Return the BlockBackend after @blk.
84 * If @blk is null, return the first one.
85 * Else, return @blk's next sibling, which may be null.
86 *
87 * To iterate over all BlockBackends, do
88 * for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
89 * ...
90 * }
91 */
92BlockBackend *blk_next(BlockBackend *blk)
93{
94 return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
95}
96
97/*
98 * Return @blk's name, a non-null, non-empty string.
99 */
100const char *blk_name(BlockBackend *blk)
101{
102 return blk->name;
103}
104
105/*
106 * Return the BlockBackend with name @name if it exists, else null.
107 * @name must not be null.
108 */
109BlockBackend *blk_by_name(const char *name)
110{
111 BlockBackend *blk;
112
113 assert(name);
114 QTAILQ_FOREACH(blk, &blk_backends, link) {
115 if (!strcmp(name, blk->name)) {
116 return blk;
117 }
118 }
119 return NULL;
120}