block/export: Move blk to BlockExport
[qemu.git] / block / export / export.c
1 /*
2 * Common block export infrastructure
3 *
4 * Copyright (c) 2012, 2020 Red Hat, Inc.
5 *
6 * Authors:
7 * Paolo Bonzini <pbonzini@redhat.com>
8 * Kevin Wolf <kwolf@redhat.com>
9 *
10 * This work is licensed under the terms of the GNU GPL, version 2 or
11 * later. See the COPYING file in the top-level directory.
12 */
13
14 #include "qemu/osdep.h"
15
16 #include "block/block.h"
17 #include "sysemu/block-backend.h"
18 #include "block/export.h"
19 #include "block/nbd.h"
20 #include "qapi/error.h"
21 #include "qapi/qapi-commands-block-export.h"
22 #include "qapi/qapi-events-block-export.h"
23 #include "qemu/id.h"
24
25 static const BlockExportDriver *blk_exp_drivers[] = {
26 &blk_exp_nbd,
27 };
28
29 /* Only accessed from the main thread */
30 static QLIST_HEAD(, BlockExport) block_exports =
31 QLIST_HEAD_INITIALIZER(block_exports);
32
33 BlockExport *blk_exp_find(const char *id)
34 {
35 BlockExport *exp;
36
37 QLIST_FOREACH(exp, &block_exports, next) {
38 if (strcmp(id, exp->id) == 0) {
39 return exp;
40 }
41 }
42
43 return NULL;
44 }
45
46 static const BlockExportDriver *blk_exp_find_driver(BlockExportType type)
47 {
48 int i;
49
50 for (i = 0; i < ARRAY_SIZE(blk_exp_drivers); i++) {
51 if (blk_exp_drivers[i]->type == type) {
52 return blk_exp_drivers[i];
53 }
54 }
55 return NULL;
56 }
57
58 BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
59 {
60 const BlockExportDriver *drv;
61 BlockExport *exp;
62 int ret;
63
64 if (!id_wellformed(export->id)) {
65 error_setg(errp, "Invalid block export id");
66 return NULL;
67 }
68 if (blk_exp_find(export->id)) {
69 error_setg(errp, "Block export id '%s' is already in use", export->id);
70 return NULL;
71 }
72
73 drv = blk_exp_find_driver(export->type);
74 if (!drv) {
75 error_setg(errp, "No driver found for the requested export type");
76 return NULL;
77 }
78
79 assert(drv->instance_size >= sizeof(BlockExport));
80 exp = g_malloc0(drv->instance_size);
81 *exp = (BlockExport) {
82 .drv = drv,
83 .refcount = 1,
84 .user_owned = true,
85 .id = g_strdup(export->id),
86 };
87
88 ret = drv->create(exp, export, errp);
89 if (ret < 0) {
90 g_free(exp->id);
91 g_free(exp);
92 return NULL;
93 }
94
95 assert(exp->blk != NULL);
96
97 QLIST_INSERT_HEAD(&block_exports, exp, next);
98 return exp;
99 }
100
101 /* Callers must hold exp->ctx lock */
102 void blk_exp_ref(BlockExport *exp)
103 {
104 assert(exp->refcount > 0);
105 exp->refcount++;
106 }
107
108 /* Runs in the main thread */
109 static void blk_exp_delete_bh(void *opaque)
110 {
111 BlockExport *exp = opaque;
112 AioContext *aio_context = exp->ctx;
113
114 aio_context_acquire(aio_context);
115
116 assert(exp->refcount == 0);
117 QLIST_REMOVE(exp, next);
118 exp->drv->delete(exp);
119 blk_unref(exp->blk);
120 qapi_event_send_block_export_deleted(exp->id);
121 g_free(exp->id);
122 g_free(exp);
123
124 aio_context_release(aio_context);
125 }
126
127 /* Callers must hold exp->ctx lock */
128 void blk_exp_unref(BlockExport *exp)
129 {
130 assert(exp->refcount > 0);
131 if (--exp->refcount == 0) {
132 /* Touch the block_exports list only in the main thread */
133 aio_bh_schedule_oneshot(qemu_get_aio_context(), blk_exp_delete_bh,
134 exp);
135 }
136 }
137
138 /*
139 * Drops the user reference to the export and requests that all client
140 * connections and other internally held references start to shut down. When
141 * the function returns, there may still be active references while the export
142 * is in the process of shutting down.
143 *
144 * Acquires exp->ctx internally. Callers must *not* hold the lock.
145 */
146 void blk_exp_request_shutdown(BlockExport *exp)
147 {
148 AioContext *aio_context = exp->ctx;
149
150 aio_context_acquire(aio_context);
151
152 /*
153 * If the user doesn't own the export any more, it is already shutting
154 * down. We must not call .request_shutdown and decrease the refcount a
155 * second time.
156 */
157 if (!exp->user_owned) {
158 goto out;
159 }
160
161 exp->drv->request_shutdown(exp);
162
163 assert(exp->user_owned);
164 exp->user_owned = false;
165 blk_exp_unref(exp);
166
167 out:
168 aio_context_release(aio_context);
169 }
170
171 /*
172 * Returns whether a block export of the given type exists.
173 * type == BLOCK_EXPORT_TYPE__MAX checks for an export of any type.
174 */
175 static bool blk_exp_has_type(BlockExportType type)
176 {
177 BlockExport *exp;
178
179 if (type == BLOCK_EXPORT_TYPE__MAX) {
180 return !QLIST_EMPTY(&block_exports);
181 }
182
183 QLIST_FOREACH(exp, &block_exports, next) {
184 if (exp->drv->type == type) {
185 return true;
186 }
187 }
188
189 return false;
190 }
191
192 /* type == BLOCK_EXPORT_TYPE__MAX for all types */
193 void blk_exp_close_all_type(BlockExportType type)
194 {
195 BlockExport *exp, *next;
196
197 assert(in_aio_context_home_thread(qemu_get_aio_context()));
198
199 QLIST_FOREACH_SAFE(exp, &block_exports, next, next) {
200 if (type != BLOCK_EXPORT_TYPE__MAX && exp->drv->type != type) {
201 continue;
202 }
203 blk_exp_request_shutdown(exp);
204 }
205
206 AIO_WAIT_WHILE(NULL, blk_exp_has_type(type));
207 }
208
209 void blk_exp_close_all(void)
210 {
211 blk_exp_close_all_type(BLOCK_EXPORT_TYPE__MAX);
212 }
213
214 void qmp_block_export_add(BlockExportOptions *export, Error **errp)
215 {
216 blk_exp_add(export, errp);
217 }
218
219 void qmp_block_export_del(const char *id,
220 bool has_mode, BlockExportRemoveMode mode,
221 Error **errp)
222 {
223 ERRP_GUARD();
224 BlockExport *exp;
225
226 exp = blk_exp_find(id);
227 if (exp == NULL) {
228 error_setg(errp, "Export '%s' is not found", id);
229 return;
230 }
231 if (!exp->user_owned) {
232 error_setg(errp, "Export '%s' is already shutting down", id);
233 return;
234 }
235
236 if (!has_mode) {
237 mode = BLOCK_EXPORT_REMOVE_MODE_SAFE;
238 }
239 if (mode == BLOCK_EXPORT_REMOVE_MODE_SAFE && exp->refcount > 1) {
240 error_setg(errp, "export '%s' still in use", exp->id);
241 error_append_hint(errp, "Use mode='hard' to force client "
242 "disconnect\n");
243 return;
244 }
245
246 blk_exp_request_shutdown(exp);
247 }