156ee8626SKevin Wolf /* 256ee8626SKevin Wolf * Common block export infrastructure 356ee8626SKevin Wolf * 456ee8626SKevin Wolf * Copyright (c) 2012, 2020 Red Hat, Inc. 556ee8626SKevin Wolf * 656ee8626SKevin Wolf * Authors: 756ee8626SKevin Wolf * Paolo Bonzini <pbonzini@redhat.com> 856ee8626SKevin Wolf * Kevin Wolf <kwolf@redhat.com> 956ee8626SKevin Wolf * 1056ee8626SKevin Wolf * This work is licensed under the terms of the GNU GPL, version 2 or 1156ee8626SKevin Wolf * later. See the COPYING file in the top-level directory. 1256ee8626SKevin Wolf */ 1356ee8626SKevin Wolf 1456ee8626SKevin Wolf #include "qemu/osdep.h" 1556ee8626SKevin Wolf 169b562c64SKevin Wolf #include "block/block.h" 179b562c64SKevin Wolf #include "sysemu/block-backend.h" 1856ee8626SKevin Wolf #include "block/export.h" 1956ee8626SKevin Wolf #include "block/nbd.h" 2056ee8626SKevin Wolf #include "qapi/error.h" 2156ee8626SKevin Wolf #include "qapi/qapi-commands-block-export.h" 22d53be9ceSKevin Wolf #include "qemu/id.h" 2356ee8626SKevin Wolf 2456ee8626SKevin Wolf static const BlockExportDriver *blk_exp_drivers[] = { 2556ee8626SKevin Wolf &blk_exp_nbd, 2656ee8626SKevin Wolf }; 2756ee8626SKevin Wolf 28bc4ee65bSKevin Wolf /* Only accessed from the main thread */ 29bc4ee65bSKevin Wolf static QLIST_HEAD(, BlockExport) block_exports = 30bc4ee65bSKevin Wolf QLIST_HEAD_INITIALIZER(block_exports); 31bc4ee65bSKevin Wolf 32d53be9ceSKevin Wolf static BlockExport *blk_exp_find(const char *id) 33d53be9ceSKevin Wolf { 34d53be9ceSKevin Wolf BlockExport *exp; 35d53be9ceSKevin Wolf 36d53be9ceSKevin Wolf QLIST_FOREACH(exp, &block_exports, next) { 37d53be9ceSKevin Wolf if (strcmp(id, exp->id) == 0) { 38d53be9ceSKevin Wolf return exp; 39d53be9ceSKevin Wolf } 40d53be9ceSKevin Wolf } 41d53be9ceSKevin Wolf 42d53be9ceSKevin Wolf return NULL; 43d53be9ceSKevin Wolf } 44d53be9ceSKevin Wolf 4556ee8626SKevin Wolf static const BlockExportDriver *blk_exp_find_driver(BlockExportType type) 4656ee8626SKevin Wolf { 4756ee8626SKevin Wolf int i; 4856ee8626SKevin Wolf 4956ee8626SKevin Wolf for (i = 0; i < ARRAY_SIZE(blk_exp_drivers); i++) { 5056ee8626SKevin Wolf if (blk_exp_drivers[i]->type == type) { 5156ee8626SKevin Wolf return blk_exp_drivers[i]; 5256ee8626SKevin Wolf } 5356ee8626SKevin Wolf } 5456ee8626SKevin Wolf return NULL; 5556ee8626SKevin Wolf } 5656ee8626SKevin Wolf 579b562c64SKevin Wolf BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp) 5856ee8626SKevin Wolf { 5956ee8626SKevin Wolf const BlockExportDriver *drv; 60a6ff7989SKevin Wolf BlockExport *exp; 61a6ff7989SKevin Wolf int ret; 6256ee8626SKevin Wolf 63d53be9ceSKevin Wolf if (!id_wellformed(export->id)) { 64d53be9ceSKevin Wolf error_setg(errp, "Invalid block export id"); 65d53be9ceSKevin Wolf return NULL; 66d53be9ceSKevin Wolf } 67d53be9ceSKevin Wolf if (blk_exp_find(export->id)) { 68d53be9ceSKevin Wolf error_setg(errp, "Block export id '%s' is already in use", export->id); 69d53be9ceSKevin Wolf return NULL; 70d53be9ceSKevin Wolf } 71d53be9ceSKevin Wolf 7256ee8626SKevin Wolf drv = blk_exp_find_driver(export->type); 7356ee8626SKevin Wolf if (!drv) { 7456ee8626SKevin Wolf error_setg(errp, "No driver found for the requested export type"); 759b562c64SKevin Wolf return NULL; 7656ee8626SKevin Wolf } 7756ee8626SKevin Wolf 78a6ff7989SKevin Wolf assert(drv->instance_size >= sizeof(BlockExport)); 79a6ff7989SKevin Wolf exp = g_malloc0(drv->instance_size); 80a6ff7989SKevin Wolf *exp = (BlockExport) { 81a6ff7989SKevin Wolf .drv = drv, 82a6ff7989SKevin Wolf .refcount = 1, 83*3859ad36SKevin Wolf .user_owned = true, 84d53be9ceSKevin Wolf .id = g_strdup(export->id), 85a6ff7989SKevin Wolf }; 86a6ff7989SKevin Wolf 87a6ff7989SKevin Wolf ret = drv->create(exp, export, errp); 88a6ff7989SKevin Wolf if (ret < 0) { 89d53be9ceSKevin Wolf g_free(exp->id); 90a6ff7989SKevin Wolf g_free(exp); 91a6ff7989SKevin Wolf return NULL; 92a6ff7989SKevin Wolf } 93a6ff7989SKevin Wolf 94bc4ee65bSKevin Wolf QLIST_INSERT_HEAD(&block_exports, exp, next); 95a6ff7989SKevin Wolf return exp; 969b562c64SKevin Wolf } 979b562c64SKevin Wolf 988612c686SKevin Wolf /* Callers must hold exp->ctx lock */ 99c69de1beSKevin Wolf void blk_exp_ref(BlockExport *exp) 100c69de1beSKevin Wolf { 101c69de1beSKevin Wolf assert(exp->refcount > 0); 102c69de1beSKevin Wolf exp->refcount++; 103c69de1beSKevin Wolf } 104c69de1beSKevin Wolf 105bc4ee65bSKevin Wolf /* Runs in the main thread */ 106bc4ee65bSKevin Wolf static void blk_exp_delete_bh(void *opaque) 107bc4ee65bSKevin Wolf { 108bc4ee65bSKevin Wolf BlockExport *exp = opaque; 109bc4ee65bSKevin Wolf AioContext *aio_context = exp->ctx; 110bc4ee65bSKevin Wolf 111bc4ee65bSKevin Wolf aio_context_acquire(aio_context); 112bc4ee65bSKevin Wolf 113bc4ee65bSKevin Wolf assert(exp->refcount == 0); 114bc4ee65bSKevin Wolf QLIST_REMOVE(exp, next); 115bc4ee65bSKevin Wolf exp->drv->delete(exp); 116d53be9ceSKevin Wolf g_free(exp->id); 117bc4ee65bSKevin Wolf g_free(exp); 118bc4ee65bSKevin Wolf 119bc4ee65bSKevin Wolf aio_context_release(aio_context); 120bc4ee65bSKevin Wolf } 121bc4ee65bSKevin Wolf 1228612c686SKevin Wolf /* Callers must hold exp->ctx lock */ 123c69de1beSKevin Wolf void blk_exp_unref(BlockExport *exp) 124c69de1beSKevin Wolf { 125c69de1beSKevin Wolf assert(exp->refcount > 0); 126c69de1beSKevin Wolf if (--exp->refcount == 0) { 127bc4ee65bSKevin Wolf /* Touch the block_exports list only in the main thread */ 128bc4ee65bSKevin Wolf aio_bh_schedule_oneshot(qemu_get_aio_context(), blk_exp_delete_bh, 129bc4ee65bSKevin Wolf exp); 130c69de1beSKevin Wolf } 131c69de1beSKevin Wolf } 132c69de1beSKevin Wolf 133bc4ee65bSKevin Wolf /* 134bc4ee65bSKevin Wolf * Drops the user reference to the export and requests that all client 135bc4ee65bSKevin Wolf * connections and other internally held references start to shut down. When 136bc4ee65bSKevin Wolf * the function returns, there may still be active references while the export 137bc4ee65bSKevin Wolf * is in the process of shutting down. 138bc4ee65bSKevin Wolf * 139bc4ee65bSKevin Wolf * Acquires exp->ctx internally. Callers must *not* hold the lock. 140bc4ee65bSKevin Wolf */ 141bc4ee65bSKevin Wolf void blk_exp_request_shutdown(BlockExport *exp) 142bc4ee65bSKevin Wolf { 143bc4ee65bSKevin Wolf AioContext *aio_context = exp->ctx; 144bc4ee65bSKevin Wolf 145bc4ee65bSKevin Wolf aio_context_acquire(aio_context); 146bc4ee65bSKevin Wolf exp->drv->request_shutdown(exp); 147*3859ad36SKevin Wolf 148*3859ad36SKevin Wolf assert(exp->user_owned); 149*3859ad36SKevin Wolf exp->user_owned = false; 150*3859ad36SKevin Wolf blk_exp_unref(exp); 151*3859ad36SKevin Wolf 152bc4ee65bSKevin Wolf aio_context_release(aio_context); 153bc4ee65bSKevin Wolf } 154bc4ee65bSKevin Wolf 155bc4ee65bSKevin Wolf /* 156bc4ee65bSKevin Wolf * Returns whether a block export of the given type exists. 157bc4ee65bSKevin Wolf * type == BLOCK_EXPORT_TYPE__MAX checks for an export of any type. 158bc4ee65bSKevin Wolf */ 159bc4ee65bSKevin Wolf static bool blk_exp_has_type(BlockExportType type) 160bc4ee65bSKevin Wolf { 161bc4ee65bSKevin Wolf BlockExport *exp; 162bc4ee65bSKevin Wolf 163bc4ee65bSKevin Wolf if (type == BLOCK_EXPORT_TYPE__MAX) { 164bc4ee65bSKevin Wolf return !QLIST_EMPTY(&block_exports); 165bc4ee65bSKevin Wolf } 166bc4ee65bSKevin Wolf 167bc4ee65bSKevin Wolf QLIST_FOREACH(exp, &block_exports, next) { 168bc4ee65bSKevin Wolf if (exp->drv->type == type) { 169bc4ee65bSKevin Wolf return true; 170bc4ee65bSKevin Wolf } 171bc4ee65bSKevin Wolf } 172bc4ee65bSKevin Wolf 173bc4ee65bSKevin Wolf return false; 174bc4ee65bSKevin Wolf } 175bc4ee65bSKevin Wolf 176bc4ee65bSKevin Wolf /* type == BLOCK_EXPORT_TYPE__MAX for all types */ 177bc4ee65bSKevin Wolf void blk_exp_close_all_type(BlockExportType type) 178bc4ee65bSKevin Wolf { 179bc4ee65bSKevin Wolf BlockExport *exp, *next; 180bc4ee65bSKevin Wolf 181bc4ee65bSKevin Wolf assert(in_aio_context_home_thread(qemu_get_aio_context())); 182bc4ee65bSKevin Wolf 183bc4ee65bSKevin Wolf QLIST_FOREACH_SAFE(exp, &block_exports, next, next) { 184bc4ee65bSKevin Wolf if (type != BLOCK_EXPORT_TYPE__MAX && exp->drv->type != type) { 185bc4ee65bSKevin Wolf continue; 186bc4ee65bSKevin Wolf } 187bc4ee65bSKevin Wolf blk_exp_request_shutdown(exp); 188bc4ee65bSKevin Wolf } 189bc4ee65bSKevin Wolf 190bc4ee65bSKevin Wolf AIO_WAIT_WHILE(NULL, blk_exp_has_type(type)); 191bc4ee65bSKevin Wolf } 192bc4ee65bSKevin Wolf 193bc4ee65bSKevin Wolf void blk_exp_close_all(void) 194bc4ee65bSKevin Wolf { 195bc4ee65bSKevin Wolf blk_exp_close_all_type(BLOCK_EXPORT_TYPE__MAX); 196bc4ee65bSKevin Wolf } 197bc4ee65bSKevin Wolf 1989b562c64SKevin Wolf void qmp_block_export_add(BlockExportOptions *export, Error **errp) 1999b562c64SKevin Wolf { 2009b562c64SKevin Wolf blk_exp_add(export, errp); 20156ee8626SKevin Wolf } 202