]> git.proxmox.com Git - mirror_qemu.git/blob - block/block-backend.c
fb91680f0365488ddcdfd66f6adc2d145e850eb2
[mirror_qemu.git] / block / block-backend.c
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 #include "sysemu/blockdev.h"
16
17 struct BlockBackend {
18 char *name;
19 int refcnt;
20 BlockDriverState *bs;
21 DriveInfo *legacy_dinfo;
22 QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
23 };
24
25 static void drive_info_del(DriveInfo *dinfo);
26
27 /* All the BlockBackends (except for hidden ones) */
28 static QTAILQ_HEAD(, BlockBackend) blk_backends =
29 QTAILQ_HEAD_INITIALIZER(blk_backends);
30
31 /*
32 * Create a new BlockBackend with @name, with a reference count of one.
33 * @name must not be null or empty.
34 * Fail if a BlockBackend with this name already exists.
35 * Store an error through @errp on failure, unless it's null.
36 * Return the new BlockBackend on success, null on failure.
37 */
38 BlockBackend *blk_new(const char *name, Error **errp)
39 {
40 BlockBackend *blk;
41
42 assert(name && name[0]);
43 if (!id_wellformed(name)) {
44 error_setg(errp, "Invalid device name");
45 return NULL;
46 }
47 if (blk_by_name(name)) {
48 error_setg(errp, "Device with id '%s' already exists", name);
49 return NULL;
50 }
51 if (bdrv_find_node(name)) {
52 error_setg(errp,
53 "Device name '%s' conflicts with an existing node name",
54 name);
55 return NULL;
56 }
57
58 blk = g_new0(BlockBackend, 1);
59 blk->name = g_strdup(name);
60 blk->refcnt = 1;
61 QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
62 return blk;
63 }
64
65 /*
66 * Create a new BlockBackend with a new BlockDriverState attached.
67 * Otherwise just like blk_new(), which see.
68 */
69 BlockBackend *blk_new_with_bs(const char *name, Error **errp)
70 {
71 BlockBackend *blk;
72 BlockDriverState *bs;
73
74 blk = blk_new(name, errp);
75 if (!blk) {
76 return NULL;
77 }
78
79 bs = bdrv_new_root();
80 blk->bs = bs;
81 bs->blk = blk;
82 return blk;
83 }
84
85 static void blk_delete(BlockBackend *blk)
86 {
87 assert(!blk->refcnt);
88 if (blk->bs) {
89 assert(blk->bs->blk == blk);
90 blk->bs->blk = NULL;
91 bdrv_unref(blk->bs);
92 blk->bs = NULL;
93 }
94 /* Avoid double-remove after blk_hide_on_behalf_of_do_drive_del() */
95 if (blk->name[0]) {
96 QTAILQ_REMOVE(&blk_backends, blk, link);
97 }
98 g_free(blk->name);
99 drive_info_del(blk->legacy_dinfo);
100 g_free(blk);
101 }
102
103 static void drive_info_del(DriveInfo *dinfo)
104 {
105 if (!dinfo) {
106 return;
107 }
108 qemu_opts_del(dinfo->opts);
109 g_free(dinfo->id);
110 g_free(dinfo->serial);
111 g_free(dinfo);
112 }
113
114 /*
115 * Increment @blk's reference count.
116 * @blk must not be null.
117 */
118 void blk_ref(BlockBackend *blk)
119 {
120 blk->refcnt++;
121 }
122
123 /*
124 * Decrement @blk's reference count.
125 * If this drops it to zero, destroy @blk.
126 * For convenience, do nothing if @blk is null.
127 */
128 void blk_unref(BlockBackend *blk)
129 {
130 if (blk) {
131 assert(blk->refcnt > 0);
132 if (!--blk->refcnt) {
133 blk_delete(blk);
134 }
135 }
136 }
137
138 /*
139 * Return the BlockBackend after @blk.
140 * If @blk is null, return the first one.
141 * Else, return @blk's next sibling, which may be null.
142 *
143 * To iterate over all BlockBackends, do
144 * for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
145 * ...
146 * }
147 */
148 BlockBackend *blk_next(BlockBackend *blk)
149 {
150 return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
151 }
152
153 /*
154 * Return @blk's name, a non-null string.
155 * Wart: the name is empty iff @blk has been hidden with
156 * blk_hide_on_behalf_of_do_drive_del().
157 */
158 const char *blk_name(BlockBackend *blk)
159 {
160 return blk->name;
161 }
162
163 /*
164 * Return the BlockBackend with name @name if it exists, else null.
165 * @name must not be null.
166 */
167 BlockBackend *blk_by_name(const char *name)
168 {
169 BlockBackend *blk;
170
171 assert(name);
172 QTAILQ_FOREACH(blk, &blk_backends, link) {
173 if (!strcmp(name, blk->name)) {
174 return blk;
175 }
176 }
177 return NULL;
178 }
179
180 /*
181 * Return the BlockDriverState attached to @blk if any, else null.
182 */
183 BlockDriverState *blk_bs(BlockBackend *blk)
184 {
185 return blk->bs;
186 }
187
188 /*
189 * Return @blk's DriveInfo if any, else null.
190 */
191 DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
192 {
193 return blk->legacy_dinfo;
194 }
195
196 /*
197 * Set @blk's DriveInfo to @dinfo, and return it.
198 * @blk must not have a DriveInfo set already.
199 * No other BlockBackend may have the same DriveInfo set.
200 */
201 DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
202 {
203 assert(!blk->legacy_dinfo);
204 return blk->legacy_dinfo = dinfo;
205 }
206
207 /*
208 * Return the BlockBackend with DriveInfo @dinfo.
209 * It must exist.
210 */
211 BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
212 {
213 BlockBackend *blk;
214
215 QTAILQ_FOREACH(blk, &blk_backends, link) {
216 if (blk->legacy_dinfo == dinfo) {
217 return blk;
218 }
219 }
220 abort();
221 }
222
223 /*
224 * Hide @blk.
225 * @blk must not have been hidden already.
226 * Make attached BlockDriverState, if any, anonymous.
227 * Once hidden, @blk is invisible to all functions that don't receive
228 * it as argument. For example, blk_by_name() won't return it.
229 * Strictly for use by do_drive_del().
230 * TODO get rid of it!
231 */
232 void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk)
233 {
234 QTAILQ_REMOVE(&blk_backends, blk, link);
235 blk->name[0] = 0;
236 if (blk->bs) {
237 bdrv_make_anon(blk->bs);
238 }
239 }