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 2756ee8626SKevin Wolf static const BlockExportDriver *blk_exp_find_driver(BlockExportType type) 2856ee8626SKevin Wolf { 2956ee8626SKevin Wolf int i; 3056ee8626SKevin Wolf 3156ee8626SKevin Wolf for (i = 0; i < ARRAY_SIZE(blk_exp_drivers); i++) { 3256ee8626SKevin Wolf if (blk_exp_drivers[i]->type == type) { 3356ee8626SKevin Wolf return blk_exp_drivers[i]; 3456ee8626SKevin Wolf } 3556ee8626SKevin Wolf } 3656ee8626SKevin Wolf return NULL; 3756ee8626SKevin Wolf } 3856ee8626SKevin Wolf 399b562c64SKevin Wolf BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp) 4056ee8626SKevin Wolf { 4156ee8626SKevin Wolf const BlockExportDriver *drv; 42*a6ff7989SKevin Wolf BlockExport *exp; 43*a6ff7989SKevin Wolf int ret; 4456ee8626SKevin Wolf 4556ee8626SKevin Wolf drv = blk_exp_find_driver(export->type); 4656ee8626SKevin Wolf if (!drv) { 4756ee8626SKevin Wolf error_setg(errp, "No driver found for the requested export type"); 489b562c64SKevin Wolf return NULL; 4956ee8626SKevin Wolf } 5056ee8626SKevin Wolf 51*a6ff7989SKevin Wolf assert(drv->instance_size >= sizeof(BlockExport)); 52*a6ff7989SKevin Wolf exp = g_malloc0(drv->instance_size); 53*a6ff7989SKevin Wolf *exp = (BlockExport) { 54*a6ff7989SKevin Wolf .drv = drv, 55*a6ff7989SKevin Wolf .refcount = 1, 56*a6ff7989SKevin Wolf }; 57*a6ff7989SKevin Wolf 58*a6ff7989SKevin Wolf ret = drv->create(exp, export, errp); 59*a6ff7989SKevin Wolf if (ret < 0) { 60*a6ff7989SKevin Wolf g_free(exp); 61*a6ff7989SKevin Wolf return NULL; 62*a6ff7989SKevin Wolf } 63*a6ff7989SKevin Wolf 64*a6ff7989SKevin Wolf return exp; 659b562c64SKevin Wolf } 669b562c64SKevin Wolf 678612c686SKevin Wolf /* Callers must hold exp->ctx lock */ 68c69de1beSKevin Wolf void blk_exp_ref(BlockExport *exp) 69c69de1beSKevin Wolf { 70c69de1beSKevin Wolf assert(exp->refcount > 0); 71c69de1beSKevin Wolf exp->refcount++; 72c69de1beSKevin Wolf } 73c69de1beSKevin Wolf 748612c686SKevin Wolf /* Callers must hold exp->ctx lock */ 75c69de1beSKevin Wolf void blk_exp_unref(BlockExport *exp) 76c69de1beSKevin Wolf { 77c69de1beSKevin Wolf assert(exp->refcount > 0); 78c69de1beSKevin Wolf if (--exp->refcount == 0) { 79c69de1beSKevin Wolf exp->drv->delete(exp); 80*a6ff7989SKevin Wolf g_free(exp); 81c69de1beSKevin Wolf } 82c69de1beSKevin Wolf } 83c69de1beSKevin Wolf 849b562c64SKevin Wolf void qmp_block_export_add(BlockExportOptions *export, Error **errp) 859b562c64SKevin Wolf { 869b562c64SKevin Wolf blk_exp_add(export, errp); 8756ee8626SKevin Wolf } 88