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" 2256ee8626SKevin Wolf 2356ee8626SKevin Wolf static const BlockExportDriver *blk_exp_drivers[] = { 2456ee8626SKevin Wolf &blk_exp_nbd, 2556ee8626SKevin Wolf }; 2656ee8626SKevin Wolf 27*bc4ee65bSKevin Wolf /* Only accessed from the main thread */ 28*bc4ee65bSKevin Wolf static QLIST_HEAD(, BlockExport) block_exports = 29*bc4ee65bSKevin Wolf QLIST_HEAD_INITIALIZER(block_exports); 30*bc4ee65bSKevin Wolf 3156ee8626SKevin Wolf static const BlockExportDriver *blk_exp_find_driver(BlockExportType type) 3256ee8626SKevin Wolf { 3356ee8626SKevin Wolf int i; 3456ee8626SKevin Wolf 3556ee8626SKevin Wolf for (i = 0; i < ARRAY_SIZE(blk_exp_drivers); i++) { 3656ee8626SKevin Wolf if (blk_exp_drivers[i]->type == type) { 3756ee8626SKevin Wolf return blk_exp_drivers[i]; 3856ee8626SKevin Wolf } 3956ee8626SKevin Wolf } 4056ee8626SKevin Wolf return NULL; 4156ee8626SKevin Wolf } 4256ee8626SKevin Wolf 439b562c64SKevin Wolf BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp) 4456ee8626SKevin Wolf { 4556ee8626SKevin Wolf const BlockExportDriver *drv; 46a6ff7989SKevin Wolf BlockExport *exp; 47a6ff7989SKevin Wolf int ret; 4856ee8626SKevin Wolf 4956ee8626SKevin Wolf drv = blk_exp_find_driver(export->type); 5056ee8626SKevin Wolf if (!drv) { 5156ee8626SKevin Wolf error_setg(errp, "No driver found for the requested export type"); 529b562c64SKevin Wolf return NULL; 5356ee8626SKevin Wolf } 5456ee8626SKevin Wolf 55a6ff7989SKevin Wolf assert(drv->instance_size >= sizeof(BlockExport)); 56a6ff7989SKevin Wolf exp = g_malloc0(drv->instance_size); 57a6ff7989SKevin Wolf *exp = (BlockExport) { 58a6ff7989SKevin Wolf .drv = drv, 59a6ff7989SKevin Wolf .refcount = 1, 60a6ff7989SKevin Wolf }; 61a6ff7989SKevin Wolf 62a6ff7989SKevin Wolf ret = drv->create(exp, export, errp); 63a6ff7989SKevin Wolf if (ret < 0) { 64a6ff7989SKevin Wolf g_free(exp); 65a6ff7989SKevin Wolf return NULL; 66a6ff7989SKevin Wolf } 67a6ff7989SKevin Wolf 68*bc4ee65bSKevin Wolf QLIST_INSERT_HEAD(&block_exports, exp, next); 69a6ff7989SKevin Wolf return exp; 709b562c64SKevin Wolf } 719b562c64SKevin Wolf 728612c686SKevin Wolf /* Callers must hold exp->ctx lock */ 73c69de1beSKevin Wolf void blk_exp_ref(BlockExport *exp) 74c69de1beSKevin Wolf { 75c69de1beSKevin Wolf assert(exp->refcount > 0); 76c69de1beSKevin Wolf exp->refcount++; 77c69de1beSKevin Wolf } 78c69de1beSKevin Wolf 79*bc4ee65bSKevin Wolf /* Runs in the main thread */ 80*bc4ee65bSKevin Wolf static void blk_exp_delete_bh(void *opaque) 81*bc4ee65bSKevin Wolf { 82*bc4ee65bSKevin Wolf BlockExport *exp = opaque; 83*bc4ee65bSKevin Wolf AioContext *aio_context = exp->ctx; 84*bc4ee65bSKevin Wolf 85*bc4ee65bSKevin Wolf aio_context_acquire(aio_context); 86*bc4ee65bSKevin Wolf 87*bc4ee65bSKevin Wolf assert(exp->refcount == 0); 88*bc4ee65bSKevin Wolf QLIST_REMOVE(exp, next); 89*bc4ee65bSKevin Wolf exp->drv->delete(exp); 90*bc4ee65bSKevin Wolf g_free(exp); 91*bc4ee65bSKevin Wolf 92*bc4ee65bSKevin Wolf aio_context_release(aio_context); 93*bc4ee65bSKevin Wolf } 94*bc4ee65bSKevin Wolf 958612c686SKevin Wolf /* Callers must hold exp->ctx lock */ 96c69de1beSKevin Wolf void blk_exp_unref(BlockExport *exp) 97c69de1beSKevin Wolf { 98c69de1beSKevin Wolf assert(exp->refcount > 0); 99c69de1beSKevin Wolf if (--exp->refcount == 0) { 100*bc4ee65bSKevin Wolf /* Touch the block_exports list only in the main thread */ 101*bc4ee65bSKevin Wolf aio_bh_schedule_oneshot(qemu_get_aio_context(), blk_exp_delete_bh, 102*bc4ee65bSKevin Wolf exp); 103c69de1beSKevin Wolf } 104c69de1beSKevin Wolf } 105c69de1beSKevin Wolf 106*bc4ee65bSKevin Wolf /* 107*bc4ee65bSKevin Wolf * Drops the user reference to the export and requests that all client 108*bc4ee65bSKevin Wolf * connections and other internally held references start to shut down. When 109*bc4ee65bSKevin Wolf * the function returns, there may still be active references while the export 110*bc4ee65bSKevin Wolf * is in the process of shutting down. 111*bc4ee65bSKevin Wolf * 112*bc4ee65bSKevin Wolf * Acquires exp->ctx internally. Callers must *not* hold the lock. 113*bc4ee65bSKevin Wolf */ 114*bc4ee65bSKevin Wolf void blk_exp_request_shutdown(BlockExport *exp) 115*bc4ee65bSKevin Wolf { 116*bc4ee65bSKevin Wolf AioContext *aio_context = exp->ctx; 117*bc4ee65bSKevin Wolf 118*bc4ee65bSKevin Wolf aio_context_acquire(aio_context); 119*bc4ee65bSKevin Wolf exp->drv->request_shutdown(exp); 120*bc4ee65bSKevin Wolf aio_context_release(aio_context); 121*bc4ee65bSKevin Wolf } 122*bc4ee65bSKevin Wolf 123*bc4ee65bSKevin Wolf /* 124*bc4ee65bSKevin Wolf * Returns whether a block export of the given type exists. 125*bc4ee65bSKevin Wolf * type == BLOCK_EXPORT_TYPE__MAX checks for an export of any type. 126*bc4ee65bSKevin Wolf */ 127*bc4ee65bSKevin Wolf static bool blk_exp_has_type(BlockExportType type) 128*bc4ee65bSKevin Wolf { 129*bc4ee65bSKevin Wolf BlockExport *exp; 130*bc4ee65bSKevin Wolf 131*bc4ee65bSKevin Wolf if (type == BLOCK_EXPORT_TYPE__MAX) { 132*bc4ee65bSKevin Wolf return !QLIST_EMPTY(&block_exports); 133*bc4ee65bSKevin Wolf } 134*bc4ee65bSKevin Wolf 135*bc4ee65bSKevin Wolf QLIST_FOREACH(exp, &block_exports, next) { 136*bc4ee65bSKevin Wolf if (exp->drv->type == type) { 137*bc4ee65bSKevin Wolf return true; 138*bc4ee65bSKevin Wolf } 139*bc4ee65bSKevin Wolf } 140*bc4ee65bSKevin Wolf 141*bc4ee65bSKevin Wolf return false; 142*bc4ee65bSKevin Wolf } 143*bc4ee65bSKevin Wolf 144*bc4ee65bSKevin Wolf /* type == BLOCK_EXPORT_TYPE__MAX for all types */ 145*bc4ee65bSKevin Wolf void blk_exp_close_all_type(BlockExportType type) 146*bc4ee65bSKevin Wolf { 147*bc4ee65bSKevin Wolf BlockExport *exp, *next; 148*bc4ee65bSKevin Wolf 149*bc4ee65bSKevin Wolf assert(in_aio_context_home_thread(qemu_get_aio_context())); 150*bc4ee65bSKevin Wolf 151*bc4ee65bSKevin Wolf QLIST_FOREACH_SAFE(exp, &block_exports, next, next) { 152*bc4ee65bSKevin Wolf if (type != BLOCK_EXPORT_TYPE__MAX && exp->drv->type != type) { 153*bc4ee65bSKevin Wolf continue; 154*bc4ee65bSKevin Wolf } 155*bc4ee65bSKevin Wolf blk_exp_request_shutdown(exp); 156*bc4ee65bSKevin Wolf } 157*bc4ee65bSKevin Wolf 158*bc4ee65bSKevin Wolf AIO_WAIT_WHILE(NULL, blk_exp_has_type(type)); 159*bc4ee65bSKevin Wolf } 160*bc4ee65bSKevin Wolf 161*bc4ee65bSKevin Wolf void blk_exp_close_all(void) 162*bc4ee65bSKevin Wolf { 163*bc4ee65bSKevin Wolf blk_exp_close_all_type(BLOCK_EXPORT_TYPE__MAX); 164*bc4ee65bSKevin Wolf } 165*bc4ee65bSKevin Wolf 1669b562c64SKevin Wolf void qmp_block_export_add(BlockExportOptions *export, Error **errp) 1679b562c64SKevin Wolf { 1689b562c64SKevin Wolf blk_exp_add(export, errp); 16956ee8626SKevin Wolf } 170