]>
Commit | Line | Data |
---|---|---|
56ee8626 KW |
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 | ||
9b562c64 KW |
16 | #include "block/block.h" |
17 | #include "sysemu/block-backend.h" | |
f51d23c8 | 18 | #include "sysemu/iothread.h" |
56ee8626 | 19 | #include "block/export.h" |
0c9b70d5 | 20 | #include "block/fuse.h" |
56ee8626 KW |
21 | #include "block/nbd.h" |
22 | #include "qapi/error.h" | |
23 | #include "qapi/qapi-commands-block-export.h" | |
1a9f7a80 | 24 | #include "qapi/qapi-events-block-export.h" |
d53be9ce | 25 | #include "qemu/id.h" |
bc15e44c | 26 | #ifdef CONFIG_VHOST_USER_BLK_SERVER |
3a213f83 SH |
27 | #include "vhost-user-blk-server.h" |
28 | #endif | |
2a2359b8 XY |
29 | #ifdef CONFIG_VDUSE_BLK_EXPORT |
30 | #include "vduse-blk.h" | |
31 | #endif | |
56ee8626 KW |
32 | |
33 | static const BlockExportDriver *blk_exp_drivers[] = { | |
34 | &blk_exp_nbd, | |
bc15e44c | 35 | #ifdef CONFIG_VHOST_USER_BLK_SERVER |
90fc91d5 SH |
36 | &blk_exp_vhost_user_blk, |
37 | #endif | |
0c9b70d5 HR |
38 | #ifdef CONFIG_FUSE |
39 | &blk_exp_fuse, | |
40 | #endif | |
2a2359b8 XY |
41 | #ifdef CONFIG_VDUSE_BLK_EXPORT |
42 | &blk_exp_vduse_blk, | |
43 | #endif | |
56ee8626 KW |
44 | }; |
45 | ||
bc4ee65b KW |
46 | /* Only accessed from the main thread */ |
47 | static QLIST_HEAD(, BlockExport) block_exports = | |
48 | QLIST_HEAD_INITIALIZER(block_exports); | |
49 | ||
3c3bc462 | 50 | BlockExport *blk_exp_find(const char *id) |
d53be9ce KW |
51 | { |
52 | BlockExport *exp; | |
53 | ||
54 | QLIST_FOREACH(exp, &block_exports, next) { | |
55 | if (strcmp(id, exp->id) == 0) { | |
56 | return exp; | |
57 | } | |
58 | } | |
59 | ||
60 | return NULL; | |
61 | } | |
62 | ||
56ee8626 KW |
63 | static const BlockExportDriver *blk_exp_find_driver(BlockExportType type) |
64 | { | |
65 | int i; | |
66 | ||
67 | for (i = 0; i < ARRAY_SIZE(blk_exp_drivers); i++) { | |
68 | if (blk_exp_drivers[i]->type == type) { | |
69 | return blk_exp_drivers[i]; | |
70 | } | |
71 | } | |
72 | return NULL; | |
73 | } | |
74 | ||
9b562c64 | 75 | BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp) |
56ee8626 | 76 | { |
f51d23c8 | 77 | bool fixed_iothread = export->has_fixed_iothread && export->fixed_iothread; |
56ee8626 | 78 | const BlockExportDriver *drv; |
331170e0 KW |
79 | BlockExport *exp = NULL; |
80 | BlockDriverState *bs; | |
f51d23c8 | 81 | BlockBackend *blk = NULL; |
331170e0 | 82 | AioContext *ctx; |
30dbc81d | 83 | uint64_t perm; |
a6ff7989 | 84 | int ret; |
56ee8626 | 85 | |
2b3912f1 KW |
86 | GLOBAL_STATE_CODE(); |
87 | ||
d53be9ce KW |
88 | if (!id_wellformed(export->id)) { |
89 | error_setg(errp, "Invalid block export id"); | |
90 | return NULL; | |
91 | } | |
92 | if (blk_exp_find(export->id)) { | |
93 | error_setg(errp, "Block export id '%s' is already in use", export->id); | |
94 | return NULL; | |
95 | } | |
96 | ||
56ee8626 KW |
97 | drv = blk_exp_find_driver(export->type); |
98 | if (!drv) { | |
99 | error_setg(errp, "No driver found for the requested export type"); | |
9b562c64 | 100 | return NULL; |
56ee8626 KW |
101 | } |
102 | ||
331170e0 KW |
103 | bs = bdrv_lookup_bs(NULL, export->node_name, errp); |
104 | if (!bs) { | |
105 | return NULL; | |
106 | } | |
107 | ||
30dbc81d KW |
108 | if (!export->has_writable) { |
109 | export->writable = false; | |
110 | } | |
111 | if (bdrv_is_read_only(bs) && export->writable) { | |
112 | error_setg(errp, "Cannot export read-only node as writable"); | |
113 | return NULL; | |
114 | } | |
115 | ||
331170e0 KW |
116 | ctx = bdrv_get_aio_context(bs); |
117 | aio_context_acquire(ctx); | |
118 | ||
54fde4ff | 119 | if (export->iothread) { |
f51d23c8 SH |
120 | IOThread *iothread; |
121 | AioContext *new_ctx; | |
8573823f | 122 | Error **set_context_errp; |
f51d23c8 SH |
123 | |
124 | iothread = iothread_by_id(export->iothread); | |
125 | if (!iothread) { | |
126 | error_setg(errp, "iothread \"%s\" not found", export->iothread); | |
127 | goto fail; | |
128 | } | |
129 | ||
130 | new_ctx = iothread_get_aio_context(iothread); | |
131 | ||
8573823f HR |
132 | /* Ignore errors with fixed-iothread=false */ |
133 | set_context_errp = fixed_iothread ? errp : NULL; | |
142e6907 | 134 | ret = bdrv_try_change_aio_context(bs, new_ctx, NULL, set_context_errp); |
f51d23c8 SH |
135 | if (ret == 0) { |
136 | aio_context_release(ctx); | |
137 | aio_context_acquire(new_ctx); | |
138 | ctx = new_ctx; | |
139 | } else if (fixed_iothread) { | |
140 | goto fail; | |
141 | } | |
142 | } | |
143 | ||
331170e0 KW |
144 | /* |
145 | * Block exports are used for non-shared storage migration. Make sure | |
146 | * that BDRV_O_INACTIVE is cleared and the image is ready for write | |
147 | * access since the export could be available before migration handover. | |
148 | * ctx was acquired in the caller. | |
149 | */ | |
2b3912f1 | 150 | bdrv_graph_rdlock_main_loop(); |
a94750d9 | 151 | bdrv_activate(bs, NULL); |
2b3912f1 | 152 | bdrv_graph_rdunlock_main_loop(); |
331170e0 | 153 | |
30dbc81d KW |
154 | perm = BLK_PERM_CONSISTENT_READ; |
155 | if (export->writable) { | |
156 | perm |= BLK_PERM_WRITE; | |
157 | } | |
158 | ||
159 | blk = blk_new(ctx, perm, BLK_PERM_ALL); | |
f51d23c8 SH |
160 | |
161 | if (!fixed_iothread) { | |
162 | blk_set_allow_aio_context_change(blk, true); | |
163 | } | |
164 | ||
331170e0 KW |
165 | ret = blk_insert_bs(blk, bs, errp); |
166 | if (ret < 0) { | |
167 | goto fail; | |
168 | } | |
169 | ||
170 | if (!export->has_writethrough) { | |
171 | export->writethrough = false; | |
172 | } | |
173 | blk_set_enable_write_cache(blk, !export->writethrough); | |
174 | ||
a6ff7989 KW |
175 | assert(drv->instance_size >= sizeof(BlockExport)); |
176 | exp = g_malloc0(drv->instance_size); | |
177 | *exp = (BlockExport) { | |
178 | .drv = drv, | |
179 | .refcount = 1, | |
3859ad36 | 180 | .user_owned = true, |
d53be9ce | 181 | .id = g_strdup(export->id), |
331170e0 KW |
182 | .ctx = ctx, |
183 | .blk = blk, | |
a6ff7989 KW |
184 | }; |
185 | ||
186 | ret = drv->create(exp, export, errp); | |
187 | if (ret < 0) { | |
331170e0 | 188 | goto fail; |
a6ff7989 KW |
189 | } |
190 | ||
37a4f70c KW |
191 | assert(exp->blk != NULL); |
192 | ||
bc4ee65b | 193 | QLIST_INSERT_HEAD(&block_exports, exp, next); |
331170e0 KW |
194 | |
195 | aio_context_release(ctx); | |
a6ff7989 | 196 | return exp; |
331170e0 KW |
197 | |
198 | fail: | |
a1845637 KW |
199 | if (blk) { |
200 | blk_set_dev_ops(blk, NULL, NULL); | |
201 | blk_unref(blk); | |
202 | } | |
331170e0 KW |
203 | aio_context_release(ctx); |
204 | if (exp) { | |
205 | g_free(exp->id); | |
206 | g_free(exp); | |
207 | } | |
208 | return NULL; | |
9b562c64 KW |
209 | } |
210 | ||
c69de1be KW |
211 | void blk_exp_ref(BlockExport *exp) |
212 | { | |
3d499a43 SH |
213 | assert(qatomic_read(&exp->refcount) > 0); |
214 | qatomic_inc(&exp->refcount); | |
c69de1be KW |
215 | } |
216 | ||
bc4ee65b KW |
217 | /* Runs in the main thread */ |
218 | static void blk_exp_delete_bh(void *opaque) | |
219 | { | |
220 | BlockExport *exp = opaque; | |
221 | AioContext *aio_context = exp->ctx; | |
222 | ||
223 | aio_context_acquire(aio_context); | |
224 | ||
225 | assert(exp->refcount == 0); | |
226 | QLIST_REMOVE(exp, next); | |
227 | exp->drv->delete(exp); | |
de79b526 | 228 | blk_set_dev_ops(exp->blk, NULL, NULL); |
37a4f70c | 229 | blk_unref(exp->blk); |
1a9f7a80 | 230 | qapi_event_send_block_export_deleted(exp->id); |
d53be9ce | 231 | g_free(exp->id); |
bc4ee65b KW |
232 | g_free(exp); |
233 | ||
234 | aio_context_release(aio_context); | |
235 | } | |
236 | ||
c69de1be KW |
237 | void blk_exp_unref(BlockExport *exp) |
238 | { | |
3d499a43 SH |
239 | assert(qatomic_read(&exp->refcount) > 0); |
240 | if (qatomic_fetch_dec(&exp->refcount) == 1) { | |
bc4ee65b KW |
241 | /* Touch the block_exports list only in the main thread */ |
242 | aio_bh_schedule_oneshot(qemu_get_aio_context(), blk_exp_delete_bh, | |
243 | exp); | |
244 | } | |
245 | } | |
246 | ||
247 | /* | |
248 | * Drops the user reference to the export and requests that all client | |
249 | * connections and other internally held references start to shut down. When | |
250 | * the function returns, there may still be active references while the export | |
251 | * is in the process of shutting down. | |
252 | * | |
253 | * Acquires exp->ctx internally. Callers must *not* hold the lock. | |
254 | */ | |
255 | void blk_exp_request_shutdown(BlockExport *exp) | |
256 | { | |
257 | AioContext *aio_context = exp->ctx; | |
258 | ||
259 | aio_context_acquire(aio_context); | |
3c3bc462 KW |
260 | |
261 | /* | |
262 | * If the user doesn't own the export any more, it is already shutting | |
263 | * down. We must not call .request_shutdown and decrease the refcount a | |
264 | * second time. | |
265 | */ | |
266 | if (!exp->user_owned) { | |
267 | goto out; | |
268 | } | |
269 | ||
bc4ee65b | 270 | exp->drv->request_shutdown(exp); |
3859ad36 KW |
271 | |
272 | assert(exp->user_owned); | |
273 | exp->user_owned = false; | |
274 | blk_exp_unref(exp); | |
275 | ||
3c3bc462 | 276 | out: |
bc4ee65b KW |
277 | aio_context_release(aio_context); |
278 | } | |
279 | ||
280 | /* | |
281 | * Returns whether a block export of the given type exists. | |
282 | * type == BLOCK_EXPORT_TYPE__MAX checks for an export of any type. | |
283 | */ | |
284 | static bool blk_exp_has_type(BlockExportType type) | |
285 | { | |
286 | BlockExport *exp; | |
287 | ||
288 | if (type == BLOCK_EXPORT_TYPE__MAX) { | |
289 | return !QLIST_EMPTY(&block_exports); | |
290 | } | |
291 | ||
292 | QLIST_FOREACH(exp, &block_exports, next) { | |
293 | if (exp->drv->type == type) { | |
294 | return true; | |
295 | } | |
c69de1be | 296 | } |
bc4ee65b KW |
297 | |
298 | return false; | |
299 | } | |
300 | ||
301 | /* type == BLOCK_EXPORT_TYPE__MAX for all types */ | |
302 | void blk_exp_close_all_type(BlockExportType type) | |
303 | { | |
304 | BlockExport *exp, *next; | |
305 | ||
306 | assert(in_aio_context_home_thread(qemu_get_aio_context())); | |
307 | ||
308 | QLIST_FOREACH_SAFE(exp, &block_exports, next, next) { | |
309 | if (type != BLOCK_EXPORT_TYPE__MAX && exp->drv->type != type) { | |
310 | continue; | |
311 | } | |
312 | blk_exp_request_shutdown(exp); | |
313 | } | |
314 | ||
e5568a66 | 315 | AIO_WAIT_WHILE_UNLOCKED(NULL, blk_exp_has_type(type)); |
bc4ee65b KW |
316 | } |
317 | ||
318 | void blk_exp_close_all(void) | |
319 | { | |
320 | blk_exp_close_all_type(BLOCK_EXPORT_TYPE__MAX); | |
c69de1be KW |
321 | } |
322 | ||
9b562c64 KW |
323 | void qmp_block_export_add(BlockExportOptions *export, Error **errp) |
324 | { | |
325 | blk_exp_add(export, errp); | |
56ee8626 | 326 | } |
3c3bc462 KW |
327 | |
328 | void qmp_block_export_del(const char *id, | |
329 | bool has_mode, BlockExportRemoveMode mode, | |
330 | Error **errp) | |
331 | { | |
332 | ERRP_GUARD(); | |
333 | BlockExport *exp; | |
334 | ||
335 | exp = blk_exp_find(id); | |
336 | if (exp == NULL) { | |
337 | error_setg(errp, "Export '%s' is not found", id); | |
338 | return; | |
339 | } | |
340 | if (!exp->user_owned) { | |
341 | error_setg(errp, "Export '%s' is already shutting down", id); | |
342 | return; | |
343 | } | |
344 | ||
345 | if (!has_mode) { | |
346 | mode = BLOCK_EXPORT_REMOVE_MODE_SAFE; | |
347 | } | |
3d499a43 SH |
348 | if (mode == BLOCK_EXPORT_REMOVE_MODE_SAFE && |
349 | qatomic_read(&exp->refcount) > 1) { | |
3c3bc462 KW |
350 | error_setg(errp, "export '%s' still in use", exp->id); |
351 | error_append_hint(errp, "Use mode='hard' to force client " | |
352 | "disconnect\n"); | |
353 | return; | |
354 | } | |
355 | ||
356 | blk_exp_request_shutdown(exp); | |
357 | } | |
8cade320 KW |
358 | |
359 | BlockExportInfoList *qmp_query_block_exports(Error **errp) | |
360 | { | |
c3033fd3 | 361 | BlockExportInfoList *head = NULL, **tail = &head; |
8cade320 KW |
362 | BlockExport *exp; |
363 | ||
364 | QLIST_FOREACH(exp, &block_exports, next) { | |
8cade320 KW |
365 | BlockExportInfo *info = g_new(BlockExportInfo, 1); |
366 | *info = (BlockExportInfo) { | |
367 | .id = g_strdup(exp->id), | |
368 | .type = exp->drv->type, | |
369 | .node_name = g_strdup(bdrv_get_node_name(blk_bs(exp->blk))), | |
370 | .shutting_down = !exp->user_owned, | |
371 | }; | |
372 | ||
c3033fd3 | 373 | QAPI_LIST_APPEND(tail, info); |
8cade320 KW |
374 | } |
375 | ||
376 | return head; | |
377 | } |