xref: /qemu/block/block-backend.c (revision 7f06d47e)
126f54e9aSMarkus Armbruster /*
226f54e9aSMarkus Armbruster  * QEMU Block backends
326f54e9aSMarkus Armbruster  *
426f54e9aSMarkus Armbruster  * Copyright (C) 2014 Red Hat, Inc.
526f54e9aSMarkus Armbruster  *
626f54e9aSMarkus Armbruster  * Authors:
726f54e9aSMarkus Armbruster  *  Markus Armbruster <armbru@redhat.com>,
826f54e9aSMarkus Armbruster  *
926f54e9aSMarkus Armbruster  * This work is licensed under the terms of the GNU LGPL, version 2.1
1026f54e9aSMarkus Armbruster  * or later.  See the COPYING.LIB file in the top-level directory.
1126f54e9aSMarkus Armbruster  */
1226f54e9aSMarkus Armbruster 
1326f54e9aSMarkus Armbruster #include "sysemu/block-backend.h"
1426f54e9aSMarkus Armbruster #include "block/block_int.h"
1518e46a03SMarkus Armbruster #include "sysemu/blockdev.h"
1626f54e9aSMarkus Armbruster 
1726f54e9aSMarkus Armbruster struct BlockBackend {
1826f54e9aSMarkus Armbruster     char *name;
1926f54e9aSMarkus Armbruster     int refcnt;
207e7d56d9SMarkus Armbruster     BlockDriverState *bs;
2118e46a03SMarkus Armbruster     DriveInfo *legacy_dinfo;
2226f54e9aSMarkus Armbruster     QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
2326f54e9aSMarkus Armbruster };
2426f54e9aSMarkus Armbruster 
258fb3c76cSMarkus Armbruster static void drive_info_del(DriveInfo *dinfo);
268fb3c76cSMarkus Armbruster 
277e7d56d9SMarkus Armbruster /* All the BlockBackends (except for hidden ones) */
2826f54e9aSMarkus Armbruster static QTAILQ_HEAD(, BlockBackend) blk_backends =
2926f54e9aSMarkus Armbruster     QTAILQ_HEAD_INITIALIZER(blk_backends);
3026f54e9aSMarkus Armbruster 
3126f54e9aSMarkus Armbruster /*
3226f54e9aSMarkus Armbruster  * Create a new BlockBackend with @name, with a reference count of one.
3326f54e9aSMarkus Armbruster  * @name must not be null or empty.
3426f54e9aSMarkus Armbruster  * Fail if a BlockBackend with this name already exists.
3526f54e9aSMarkus Armbruster  * Store an error through @errp on failure, unless it's null.
3626f54e9aSMarkus Armbruster  * Return the new BlockBackend on success, null on failure.
3726f54e9aSMarkus Armbruster  */
3826f54e9aSMarkus Armbruster BlockBackend *blk_new(const char *name, Error **errp)
3926f54e9aSMarkus Armbruster {
4026f54e9aSMarkus Armbruster     BlockBackend *blk;
4126f54e9aSMarkus Armbruster 
4226f54e9aSMarkus Armbruster     assert(name && name[0]);
43*7f06d47eSMarkus Armbruster     if (!id_wellformed(name)) {
44*7f06d47eSMarkus Armbruster         error_setg(errp, "Invalid device name");
45*7f06d47eSMarkus Armbruster         return NULL;
46*7f06d47eSMarkus Armbruster     }
4726f54e9aSMarkus Armbruster     if (blk_by_name(name)) {
4826f54e9aSMarkus Armbruster         error_setg(errp, "Device with id '%s' already exists", name);
4926f54e9aSMarkus Armbruster         return NULL;
5026f54e9aSMarkus Armbruster     }
51*7f06d47eSMarkus Armbruster     if (bdrv_find_node(name)) {
52*7f06d47eSMarkus Armbruster         error_setg(errp,
53*7f06d47eSMarkus Armbruster                    "Device name '%s' conflicts with an existing node name",
54*7f06d47eSMarkus Armbruster                    name);
55*7f06d47eSMarkus Armbruster         return NULL;
56*7f06d47eSMarkus Armbruster     }
5726f54e9aSMarkus Armbruster 
5826f54e9aSMarkus Armbruster     blk = g_new0(BlockBackend, 1);
5926f54e9aSMarkus Armbruster     blk->name = g_strdup(name);
6026f54e9aSMarkus Armbruster     blk->refcnt = 1;
6126f54e9aSMarkus Armbruster     QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
6226f54e9aSMarkus Armbruster     return blk;
6326f54e9aSMarkus Armbruster }
6426f54e9aSMarkus Armbruster 
657e7d56d9SMarkus Armbruster /*
667e7d56d9SMarkus Armbruster  * Create a new BlockBackend with a new BlockDriverState attached.
677e7d56d9SMarkus Armbruster  * Otherwise just like blk_new(), which see.
687e7d56d9SMarkus Armbruster  */
697e7d56d9SMarkus Armbruster BlockBackend *blk_new_with_bs(const char *name, Error **errp)
707e7d56d9SMarkus Armbruster {
717e7d56d9SMarkus Armbruster     BlockBackend *blk;
727e7d56d9SMarkus Armbruster     BlockDriverState *bs;
737e7d56d9SMarkus Armbruster 
747e7d56d9SMarkus Armbruster     blk = blk_new(name, errp);
757e7d56d9SMarkus Armbruster     if (!blk) {
767e7d56d9SMarkus Armbruster         return NULL;
777e7d56d9SMarkus Armbruster     }
787e7d56d9SMarkus Armbruster 
79*7f06d47eSMarkus Armbruster     bs = bdrv_new_root();
807e7d56d9SMarkus Armbruster     blk->bs = bs;
817e7d56d9SMarkus Armbruster     bs->blk = blk;
827e7d56d9SMarkus Armbruster     return blk;
837e7d56d9SMarkus Armbruster }
847e7d56d9SMarkus Armbruster 
8526f54e9aSMarkus Armbruster static void blk_delete(BlockBackend *blk)
8626f54e9aSMarkus Armbruster {
8726f54e9aSMarkus Armbruster     assert(!blk->refcnt);
887e7d56d9SMarkus Armbruster     if (blk->bs) {
899ba10c95SMarkus Armbruster         assert(blk->bs->blk == blk);
907e7d56d9SMarkus Armbruster         blk->bs->blk = NULL;
919ba10c95SMarkus Armbruster         bdrv_unref(blk->bs);
927e7d56d9SMarkus Armbruster         blk->bs = NULL;
937e7d56d9SMarkus Armbruster     }
947e7d56d9SMarkus Armbruster     /* Avoid double-remove after blk_hide_on_behalf_of_do_drive_del() */
957e7d56d9SMarkus Armbruster     if (blk->name[0]) {
9626f54e9aSMarkus Armbruster         QTAILQ_REMOVE(&blk_backends, blk, link);
977e7d56d9SMarkus Armbruster     }
9826f54e9aSMarkus Armbruster     g_free(blk->name);
9918e46a03SMarkus Armbruster     drive_info_del(blk->legacy_dinfo);
10026f54e9aSMarkus Armbruster     g_free(blk);
10126f54e9aSMarkus Armbruster }
10226f54e9aSMarkus Armbruster 
1038fb3c76cSMarkus Armbruster static void drive_info_del(DriveInfo *dinfo)
1048fb3c76cSMarkus Armbruster {
1058fb3c76cSMarkus Armbruster     if (!dinfo) {
1068fb3c76cSMarkus Armbruster         return;
1078fb3c76cSMarkus Armbruster     }
1088fb3c76cSMarkus Armbruster     qemu_opts_del(dinfo->opts);
1098fb3c76cSMarkus Armbruster     g_free(dinfo->id);
1108fb3c76cSMarkus Armbruster     g_free(dinfo->serial);
1118fb3c76cSMarkus Armbruster     g_free(dinfo);
1128fb3c76cSMarkus Armbruster }
1138fb3c76cSMarkus Armbruster 
11426f54e9aSMarkus Armbruster /*
11526f54e9aSMarkus Armbruster  * Increment @blk's reference count.
11626f54e9aSMarkus Armbruster  * @blk must not be null.
11726f54e9aSMarkus Armbruster  */
11826f54e9aSMarkus Armbruster void blk_ref(BlockBackend *blk)
11926f54e9aSMarkus Armbruster {
12026f54e9aSMarkus Armbruster     blk->refcnt++;
12126f54e9aSMarkus Armbruster }
12226f54e9aSMarkus Armbruster 
12326f54e9aSMarkus Armbruster /*
12426f54e9aSMarkus Armbruster  * Decrement @blk's reference count.
12526f54e9aSMarkus Armbruster  * If this drops it to zero, destroy @blk.
12626f54e9aSMarkus Armbruster  * For convenience, do nothing if @blk is null.
12726f54e9aSMarkus Armbruster  */
12826f54e9aSMarkus Armbruster void blk_unref(BlockBackend *blk)
12926f54e9aSMarkus Armbruster {
13026f54e9aSMarkus Armbruster     if (blk) {
13126f54e9aSMarkus Armbruster         assert(blk->refcnt > 0);
13226f54e9aSMarkus Armbruster         if (!--blk->refcnt) {
13326f54e9aSMarkus Armbruster             blk_delete(blk);
13426f54e9aSMarkus Armbruster         }
13526f54e9aSMarkus Armbruster     }
13626f54e9aSMarkus Armbruster }
13726f54e9aSMarkus Armbruster 
13826f54e9aSMarkus Armbruster /*
13926f54e9aSMarkus Armbruster  * Return the BlockBackend after @blk.
14026f54e9aSMarkus Armbruster  * If @blk is null, return the first one.
14126f54e9aSMarkus Armbruster  * Else, return @blk's next sibling, which may be null.
14226f54e9aSMarkus Armbruster  *
14326f54e9aSMarkus Armbruster  * To iterate over all BlockBackends, do
14426f54e9aSMarkus Armbruster  * for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
14526f54e9aSMarkus Armbruster  *     ...
14626f54e9aSMarkus Armbruster  * }
14726f54e9aSMarkus Armbruster  */
14826f54e9aSMarkus Armbruster BlockBackend *blk_next(BlockBackend *blk)
14926f54e9aSMarkus Armbruster {
15026f54e9aSMarkus Armbruster     return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
15126f54e9aSMarkus Armbruster }
15226f54e9aSMarkus Armbruster 
15326f54e9aSMarkus Armbruster /*
1547e7d56d9SMarkus Armbruster  * Return @blk's name, a non-null string.
1557e7d56d9SMarkus Armbruster  * Wart: the name is empty iff @blk has been hidden with
1567e7d56d9SMarkus Armbruster  * blk_hide_on_behalf_of_do_drive_del().
15726f54e9aSMarkus Armbruster  */
15826f54e9aSMarkus Armbruster const char *blk_name(BlockBackend *blk)
15926f54e9aSMarkus Armbruster {
16026f54e9aSMarkus Armbruster     return blk->name;
16126f54e9aSMarkus Armbruster }
16226f54e9aSMarkus Armbruster 
16326f54e9aSMarkus Armbruster /*
16426f54e9aSMarkus Armbruster  * Return the BlockBackend with name @name if it exists, else null.
16526f54e9aSMarkus Armbruster  * @name must not be null.
16626f54e9aSMarkus Armbruster  */
16726f54e9aSMarkus Armbruster BlockBackend *blk_by_name(const char *name)
16826f54e9aSMarkus Armbruster {
16926f54e9aSMarkus Armbruster     BlockBackend *blk;
17026f54e9aSMarkus Armbruster 
17126f54e9aSMarkus Armbruster     assert(name);
17226f54e9aSMarkus Armbruster     QTAILQ_FOREACH(blk, &blk_backends, link) {
17326f54e9aSMarkus Armbruster         if (!strcmp(name, blk->name)) {
17426f54e9aSMarkus Armbruster             return blk;
17526f54e9aSMarkus Armbruster         }
17626f54e9aSMarkus Armbruster     }
17726f54e9aSMarkus Armbruster     return NULL;
17826f54e9aSMarkus Armbruster }
1797e7d56d9SMarkus Armbruster 
1807e7d56d9SMarkus Armbruster /*
1817e7d56d9SMarkus Armbruster  * Return the BlockDriverState attached to @blk if any, else null.
1827e7d56d9SMarkus Armbruster  */
1837e7d56d9SMarkus Armbruster BlockDriverState *blk_bs(BlockBackend *blk)
1847e7d56d9SMarkus Armbruster {
1857e7d56d9SMarkus Armbruster     return blk->bs;
1867e7d56d9SMarkus Armbruster }
1877e7d56d9SMarkus Armbruster 
1887e7d56d9SMarkus Armbruster /*
18918e46a03SMarkus Armbruster  * Return @blk's DriveInfo if any, else null.
19018e46a03SMarkus Armbruster  */
19118e46a03SMarkus Armbruster DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
19218e46a03SMarkus Armbruster {
19318e46a03SMarkus Armbruster     return blk->legacy_dinfo;
19418e46a03SMarkus Armbruster }
19518e46a03SMarkus Armbruster 
19618e46a03SMarkus Armbruster /*
19718e46a03SMarkus Armbruster  * Set @blk's DriveInfo to @dinfo, and return it.
19818e46a03SMarkus Armbruster  * @blk must not have a DriveInfo set already.
19918e46a03SMarkus Armbruster  * No other BlockBackend may have the same DriveInfo set.
20018e46a03SMarkus Armbruster  */
20118e46a03SMarkus Armbruster DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
20218e46a03SMarkus Armbruster {
20318e46a03SMarkus Armbruster     assert(!blk->legacy_dinfo);
20418e46a03SMarkus Armbruster     return blk->legacy_dinfo = dinfo;
20518e46a03SMarkus Armbruster }
20618e46a03SMarkus Armbruster 
20718e46a03SMarkus Armbruster /*
20818e46a03SMarkus Armbruster  * Return the BlockBackend with DriveInfo @dinfo.
20918e46a03SMarkus Armbruster  * It must exist.
21018e46a03SMarkus Armbruster  */
21118e46a03SMarkus Armbruster BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
21218e46a03SMarkus Armbruster {
21318e46a03SMarkus Armbruster     BlockBackend *blk;
21418e46a03SMarkus Armbruster 
21518e46a03SMarkus Armbruster     QTAILQ_FOREACH(blk, &blk_backends, link) {
21618e46a03SMarkus Armbruster         if (blk->legacy_dinfo == dinfo) {
21718e46a03SMarkus Armbruster             return blk;
21818e46a03SMarkus Armbruster         }
21918e46a03SMarkus Armbruster     }
22018e46a03SMarkus Armbruster     abort();
22118e46a03SMarkus Armbruster }
22218e46a03SMarkus Armbruster 
22318e46a03SMarkus Armbruster /*
2247e7d56d9SMarkus Armbruster  * Hide @blk.
2257e7d56d9SMarkus Armbruster  * @blk must not have been hidden already.
2267e7d56d9SMarkus Armbruster  * Make attached BlockDriverState, if any, anonymous.
2277e7d56d9SMarkus Armbruster  * Once hidden, @blk is invisible to all functions that don't receive
2287e7d56d9SMarkus Armbruster  * it as argument.  For example, blk_by_name() won't return it.
2297e7d56d9SMarkus Armbruster  * Strictly for use by do_drive_del().
2307e7d56d9SMarkus Armbruster  * TODO get rid of it!
2317e7d56d9SMarkus Armbruster  */
2327e7d56d9SMarkus Armbruster void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk)
2337e7d56d9SMarkus Armbruster {
2347e7d56d9SMarkus Armbruster     QTAILQ_REMOVE(&blk_backends, blk, link);
2357e7d56d9SMarkus Armbruster     blk->name[0] = 0;
2367e7d56d9SMarkus Armbruster     if (blk->bs) {
2377e7d56d9SMarkus Armbruster         bdrv_make_anon(blk->bs);
2387e7d56d9SMarkus Armbruster     }
2397e7d56d9SMarkus Armbruster }
240