diff --git a/block.c b/block.c index 30d64e6ca5aba6d4a91f33187f620460c897c304..101f8c628f06cdcf174785c913e0f3e1ae7dfedc 100644 --- a/block.c +++ b/block.c @@ -25,6 +25,7 @@ #include "trace.h" #include "block/block_int.h" #include "block/blockjob.h" +#include "block/nbd.h" #include "qemu/error-report.h" #include "qemu/module.h" #include "qapi/qmp/qerror.h" @@ -2206,6 +2207,7 @@ static void bdrv_close(BlockDriverState *bs) void bdrv_close_all(void) { block_job_cancel_sync_all(); + nbd_export_close_all(); /* Drop references from requests still in flight, such as canceled block * jobs whose AIO context has not been polled yet */ diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 12cae0ea720bd879f2abf92a78a55ccc3da2662d..c437d32573e5a0f1b35751df1bb574f559015cbe 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -176,8 +176,8 @@ void qmp_nbd_server_add(const char *device, bool has_writable, bool writable, writable = false; } - exp = nbd_export_new(blk, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, NULL, - errp); + exp = nbd_export_new(blk_bs(blk), 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY, + NULL, false, blk, errp); if (!exp) { return; } diff --git a/include/block/nbd.h b/include/block/nbd.h index 1897557a9bf3ba4fb0835287c893e5fe18d76018..80610ff31bfec3e8954670aed3a2414d5f289a47 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -103,8 +103,9 @@ int nbd_disconnect(int fd); typedef struct NBDExport NBDExport; typedef struct NBDClient NBDClient; -NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, +NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size, uint16_t nbdflags, void (*close)(NBDExport *), + bool writethrough, BlockBackend *on_eject_blk, Error **errp); void nbd_export_close(NBDExport *exp); void nbd_export_get(NBDExport *exp); diff --git a/nbd/server.c b/nbd/server.c index 80fbb4da1db520887fb0895fa4771ef93347fb1d..472f584c323ed28635ed34c101a4454fca505c79 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -69,6 +69,7 @@ struct NBDExport { AioContext *ctx; + BlockBackend *eject_notifier_blk; Notifier eject_notifier; }; @@ -807,11 +808,18 @@ static void nbd_eject_notifier(Notifier *n, void *data) nbd_export_close(exp); } -NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, +NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size, uint16_t nbdflags, void (*close)(NBDExport *), + bool writethrough, BlockBackend *on_eject_blk, Error **errp) { + BlockBackend *blk; NBDExport *exp = g_malloc0(sizeof(NBDExport)); + + blk = blk_new(); + blk_insert_bs(blk, bs); + blk_set_enable_write_cache(blk, !writethrough); + exp->refcount = 1; QTAILQ_INIT(&exp->clients); exp->blk = blk; @@ -827,11 +835,14 @@ NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, exp->close = close; exp->ctx = blk_get_aio_context(blk); - blk_ref(blk); blk_add_aio_context_notifier(blk, blk_aio_attached, blk_aio_detach, exp); - exp->eject_notifier.notify = nbd_eject_notifier; - blk_add_remove_bs_notifier(blk, &exp->eject_notifier); + if (on_eject_blk) { + blk_ref(on_eject_blk); + exp->eject_notifier_blk = on_eject_blk; + exp->eject_notifier.notify = nbd_eject_notifier; + blk_add_remove_bs_notifier(on_eject_blk, &exp->eject_notifier); + } /* * NBD exports are used for non-shared storage migration. Make sure @@ -844,6 +855,7 @@ NBDExport *nbd_export_new(BlockBackend *blk, off_t dev_offset, off_t size, return exp; fail: + blk_unref(blk); g_free(exp); return NULL; } @@ -914,7 +926,10 @@ void nbd_export_put(NBDExport *exp) } if (exp->blk) { - notifier_remove(&exp->eject_notifier); + if (exp->eject_notifier_blk) { + notifier_remove(&exp->eject_notifier); + blk_unref(exp->eject_notifier_blk); + } blk_remove_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach, exp); blk_unref(exp->blk); diff --git a/qemu-nbd.c b/qemu-nbd.c index e3571c202572c7d1b87c1ebe55b2d24b456b86b2..99297a556fc8b8848b7be2b38267857e522ed6ff 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -910,8 +910,8 @@ int main(int argc, char **argv) } } - exp = nbd_export_new(blk, dev_offset, fd_size, nbdflags, nbd_export_closed, - &local_err); + exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, nbd_export_closed, + writethrough, NULL, &local_err); if (!exp) { error_report_err(local_err); exit(EXIT_FAILURE);