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