All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, qemu-devel@nongnu.org, mreitz@redhat.com
Subject: [PATCH 17/29] block/export: Add blk_exp_close_all(_type)
Date: Mon,  7 Sep 2020 20:19:59 +0200	[thread overview]
Message-ID: <20200907182011.521007-18-kwolf@redhat.com> (raw)
In-Reply-To: <20200907182011.521007-1-kwolf@redhat.com>

This adds a function to shut down all block exports, and another one to
shut down the block exports of a single type. The latter is used for now
when stopping the NBD server. As soon as we implement support for
multiple NBD servers, we'll need a per-server list of exports and it
will be replaced by a function using that.

As a side effect, the BlockExport layer has a list tracking all existing
exports now. closed_exports loses its only user and can go away.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/block/export.h | 15 ++++++++
 include/block/nbd.h    |  2 --
 block.c                |  2 +-
 block/export/export.c  | 79 ++++++++++++++++++++++++++++++++++++++++--
 blockdev-nbd.c         |  2 +-
 nbd/server.c           | 34 +++---------------
 qemu-nbd.c             |  2 +-
 7 files changed, 100 insertions(+), 36 deletions(-)

diff --git a/include/block/export.h b/include/block/export.h
index cf9b1c9dad..6fffcb5651 100644
--- a/include/block/export.h
+++ b/include/block/export.h
@@ -15,6 +15,7 @@
 #define BLOCK_EXPORT_H
 
 #include "qapi/qapi-types-block-export.h"
+#include "qemu/queue.h"
 
 typedef struct BlockExport BlockExport;
 
@@ -36,6 +37,14 @@ typedef struct BlockExportDriver {
      * references have been dropped.
      */
     void (*delete)(BlockExport *);
+
+    /*
+     * Start to disconnect all clients and drop other references held
+     * internally by the export driver. When the function returns, there may
+     * still be active references while the export is in the process of
+     * shutting down.
+     */
+    void (*request_shutdown)(BlockExport *);
 } BlockExportDriver;
 
 struct BlockExport {
@@ -50,10 +59,16 @@ struct BlockExport {
 
     /* The AioContext whose lock protects this BlockExport object. */
     AioContext *ctx;
+
+    /* List entry for block_exports */
+    QLIST_ENTRY(BlockExport) next;
 };
 
 BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp);
 void blk_exp_ref(BlockExport *exp);
 void blk_exp_unref(BlockExport *exp);
+void blk_exp_request_shutdown(BlockExport *exp);
+void blk_exp_close_all(void);
+void blk_exp_close_all_type(BlockExportType type);
 
 #endif
diff --git a/include/block/nbd.h b/include/block/nbd.h
index fc2c153d5b..0b9f3e5d4e 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -337,12 +337,10 @@ int nbd_export_new(BlockExport *blk_exp, BlockDriverState *bs,
                    const char *bitmap, bool readonly, bool shared,
                    bool writethrough, Error **errp);
 void nbd_export_set_on_eject_blk(BlockExport *exp, BlockBackend *blk);
-void nbd_export_close(NBDExport *exp);
 void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error **errp);
 
 AioContext *nbd_export_aio_context(NBDExport *exp);
 NBDExport *nbd_export_find(const char *name);
-void nbd_export_close_all(void);
 
 void nbd_client_new(QIOChannelSocket *sioc,
                     QCryptoTLSCreds *tlscreds,
diff --git a/block.c b/block.c
index 9538af4884..acde53f92a 100644
--- a/block.c
+++ b/block.c
@@ -4462,7 +4462,7 @@ static void bdrv_close(BlockDriverState *bs)
 void bdrv_close_all(void)
 {
     assert(job_next(NULL) == NULL);
-    nbd_export_close_all();
+    blk_exp_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/block/export/export.c b/block/export/export.c
index 03ff155f97..1b36286010 100644
--- a/block/export/export.c
+++ b/block/export/export.c
@@ -24,6 +24,10 @@ static const BlockExportDriver *blk_exp_drivers[] = {
     &blk_exp_nbd,
 };
 
+/* Only accessed from the main thread */
+static QLIST_HEAD(, BlockExport) block_exports =
+    QLIST_HEAD_INITIALIZER(block_exports);
+
 static const BlockExportDriver *blk_exp_find_driver(BlockExportType type)
 {
     int i;
@@ -61,6 +65,7 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
         return NULL;
     }
 
+    QLIST_INSERT_HEAD(&block_exports, exp, next);
     return exp;
 }
 
@@ -71,16 +76,86 @@ void blk_exp_ref(BlockExport *exp)
     exp->refcount++;
 }
 
+/* Runs in the main thread */
+static void blk_exp_delete_bh(void *opaque)
+{
+    BlockExport *exp = opaque;
+    AioContext *aio_context = exp->ctx;
+
+    aio_context_acquire(aio_context);
+
+    assert(exp->refcount == 0);
+    QLIST_REMOVE(exp, next);
+    exp->drv->delete(exp);
+    g_free(exp);
+
+    aio_context_release(aio_context);
+}
+
 /* Callers must hold exp->ctx lock */
 void blk_exp_unref(BlockExport *exp)
 {
     assert(exp->refcount > 0);
     if (--exp->refcount == 0) {
-        exp->drv->delete(exp);
-        g_free(exp);
+        /* Touch the block_exports list only in the main thread */
+        aio_bh_schedule_oneshot(qemu_get_aio_context(), blk_exp_delete_bh,
+                                exp);
     }
 }
 
+/* Acquires exp->ctx internally. Callers must *not* hold the lock. */
+void blk_exp_request_shutdown(BlockExport *exp)
+{
+    AioContext *aio_context = exp->ctx;
+
+    aio_context_acquire(aio_context);
+    exp->drv->request_shutdown(exp);
+    aio_context_release(aio_context);
+}
+
+/*
+ * Returns whether a block export of the given type exists.
+ * type == BLOCK_EXPORT_TYPE__MAX checks for an export of any type.
+ */
+static bool blk_exp_has_type(BlockExportType type)
+{
+    BlockExport *exp;
+
+    if (type == BLOCK_EXPORT_TYPE__MAX) {
+        return !QLIST_EMPTY(&block_exports);
+    }
+
+    QLIST_FOREACH(exp, &block_exports, next) {
+        if (exp->drv->type == type) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/* type == BLOCK_EXPORT_TYPE__MAX for all types */
+void blk_exp_close_all_type(BlockExportType type)
+{
+    BlockExport *exp, *next;
+
+    assert(in_aio_context_home_thread(qemu_get_aio_context()));
+
+    QLIST_FOREACH_SAFE(exp, &block_exports, next, next) {
+        if (type != BLOCK_EXPORT_TYPE__MAX && exp->drv->type != type) {
+            continue;
+        }
+        blk_exp_request_shutdown(exp);
+    }
+
+    AIO_WAIT_WHILE(NULL, blk_exp_has_type(type));
+}
+
+void blk_exp_close_all(void)
+{
+    blk_exp_close_all_type(BLOCK_EXPORT_TYPE__MAX);
+}
+
 void qmp_block_export_add(BlockExportOptions *export, Error **errp)
 {
     blk_exp_add(export, errp);
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index b34f159888..f927264777 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -345,7 +345,7 @@ void qmp_nbd_server_stop(Error **errp)
         return;
     }
 
-    nbd_export_close_all();
+    blk_exp_close_all_type(BLOCK_EXPORT_TYPE_NBD);
 
     nbd_server_free(nbd_server);
     nbd_server = NULL;
diff --git a/nbd/server.c b/nbd/server.c
index f31d8bbb60..32147e4871 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -100,8 +100,6 @@ struct NBDExport {
 };
 
 static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
-static QTAILQ_HEAD(, NBDExport) closed_exports =
-        QTAILQ_HEAD_INITIALIZER(closed_exports);
 
 /* NBDExportMetaContexts represents a list of contexts to be exported,
  * as selected by NBD_OPT_SET_META_CONTEXT. Also used for
@@ -1494,12 +1492,8 @@ static void blk_aio_detach(void *opaque)
 static void nbd_eject_notifier(Notifier *n, void *data)
 {
     NBDExport *exp = container_of(n, NBDExport, eject_notifier);
-    AioContext *aio_context;
 
-    aio_context = exp->common.ctx;
-    aio_context_acquire(aio_context);
-    nbd_export_close(exp);
-    aio_context_release(aio_context);
+    blk_exp_request_shutdown(&exp->common);
 }
 
 void nbd_export_set_on_eject_blk(BlockExport *exp, BlockBackend *blk)
@@ -1652,8 +1646,9 @@ nbd_export_aio_context(NBDExport *exp)
     return exp->common.ctx;
 }
 
-void nbd_export_close(NBDExport *exp)
+static void nbd_export_request_shutdown(BlockExport *blk_exp)
 {
+    NBDExport *exp = container_of(blk_exp, NBDExport, common);
     NBDClient *client, *next;
 
     blk_exp_ref(&exp->common);
@@ -1672,7 +1667,6 @@ void nbd_export_close(NBDExport *exp)
         g_free(exp->name);
         exp->name = NULL;
         QTAILQ_REMOVE(&exports, exp, next);
-        QTAILQ_INSERT_TAIL(&closed_exports, exp, next);
     }
     blk_exp_unref(&exp->common);
 }
@@ -1681,7 +1675,7 @@ void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error **errp)
 {
     ERRP_GUARD();
     if (mode == NBD_SERVER_REMOVE_MODE_HARD || QTAILQ_EMPTY(&exp->clients)) {
-        nbd_export_close(exp);
+        nbd_export_request_shutdown(&exp->common);
         return;
     }
 
@@ -1716,9 +1710,6 @@ static void nbd_export_delete(BlockExport *blk_exp)
         bdrv_dirty_bitmap_set_busy(exp->export_bitmap, false);
         g_free(exp->export_bitmap_context);
     }
-
-    QTAILQ_REMOVE(&closed_exports, exp, next);
-    aio_wait_kick();
 }
 
 const BlockExportDriver blk_exp_nbd = {
@@ -1726,24 +1717,9 @@ const BlockExportDriver blk_exp_nbd = {
     .instance_size      = sizeof(NBDExport),
     .create             = nbd_export_create,
     .delete             = nbd_export_delete,
+    .request_shutdown   = nbd_export_request_shutdown,
 };
 
-void nbd_export_close_all(void)
-{
-    NBDExport *exp, *next;
-    AioContext *aio_context;
-
-    QTAILQ_FOREACH_SAFE(exp, &exports, next, next) {
-        aio_context = exp->common.ctx;
-        aio_context_acquire(aio_context);
-        nbd_export_close(exp);
-        aio_context_release(aio_context);
-    }
-
-    AIO_WAIT_WHILE(NULL, !(QTAILQ_EMPTY(&exports) &&
-                           QTAILQ_EMPTY(&closed_exports)));
-}
-
 static int coroutine_fn nbd_co_send_iov(NBDClient *client, struct iovec *iov,
                                         unsigned niov, Error **errp)
 {
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 23c2b7da8e..c64f83618b 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -1119,7 +1119,7 @@ int main(int argc, char **argv)
     do {
         main_loop_wait(false);
         if (state == TERMINATE) {
-            nbd_export_close_all();
+            blk_exp_close_all();
             state = TERMINATED;
         }
     } while (state != TERMINATED);
-- 
2.25.4



  parent reply	other threads:[~2020-09-07 18:28 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-07 18:19 [PATCH 00/29] block/export: Add infrastructure and QAPI for block exports Kevin Wolf
2020-09-07 18:19 ` [PATCH 01/29] nbd: Remove unused nbd_export_get_blockdev() Kevin Wolf
2020-09-07 18:19 ` [PATCH 02/29] qapi: Create block-export module Kevin Wolf
2020-09-07 18:19 ` [PATCH 03/29] qapi: Rename BlockExport to BlockExportOptions Kevin Wolf
2020-09-07 18:19 ` [PATCH 04/29] block/export: Add BlockExport infrastructure and block-export-add Kevin Wolf
2020-09-10 10:16   ` Max Reitz
2020-09-07 18:19 ` [PATCH 05/29] qemu-storage-daemon: Use qmp_block_export_add() Kevin Wolf
2020-09-07 18:19 ` [PATCH 06/29] qemu-nbd: Use raw block driver for --offset Kevin Wolf
2020-09-07 18:19 ` [PATCH 07/29] block/export: Remove magic from block-export-add Kevin Wolf
2020-09-10 10:53   ` Max Reitz
2020-09-07 18:19 ` [PATCH 08/29] nbd: Add max-connections to nbd-server-start Kevin Wolf
2020-09-07 18:19 ` [PATCH 09/29] nbd: Add writethrough to block-export-add Kevin Wolf
2020-09-10 11:15   ` Max Reitz
2020-09-07 18:19 ` [PATCH 10/29] nbd: Remove NBDExport.close callback Kevin Wolf
2020-09-07 18:19 ` [PATCH 11/29] qemu-nbd: Use blk_exp_add() to create the export Kevin Wolf
2020-09-07 18:19 ` [PATCH 12/29] nbd/server: Simplify export shutdown Kevin Wolf
2020-09-07 18:19 ` [PATCH 13/29] block/export: Move refcount from NBDExport to BlockExport Kevin Wolf
2020-09-07 18:19 ` [PATCH 14/29] block/export: Move AioContext " Kevin Wolf
2020-09-10 11:52   ` Max Reitz
2020-09-07 18:19 ` [PATCH 15/29] block/export: Add node-name to BlockExportOptions Kevin Wolf
2020-09-10 12:35   ` Max Reitz
2020-09-07 18:19 ` [PATCH 16/29] block/export: Allocate BlockExport in blk_exp_add() Kevin Wolf
2020-09-16 10:56   ` Max Reitz
2020-09-07 18:19 ` Kevin Wolf [this message]
2020-09-10 13:22   ` [PATCH 17/29] block/export: Add blk_exp_close_all(_type) Max Reitz
2020-09-07 18:20 ` [PATCH 18/29] block/export: Add 'id' option to block-export-add Kevin Wolf
2020-09-10 13:26   ` Max Reitz
2020-09-07 18:20 ` [PATCH 19/29] block/export: Move strong user reference to block_exports Kevin Wolf
2020-09-10 13:33   ` Max Reitz
2020-09-10 13:36     ` Max Reitz
2020-09-07 18:20 ` [PATCH 20/29] block/export: Add block-export-del Kevin Wolf
2020-09-07 18:20 ` [PATCH 21/29] block/export: Add BLOCK_EXPORT_DELETED event Kevin Wolf
2020-09-10 14:04   ` Max Reitz
2020-09-10 15:12   ` Max Reitz
2020-09-16 14:57   ` Max Reitz
2020-09-07 18:20 ` [PATCH 22/29] block/export: Move blk to BlockExport Kevin Wolf
2020-09-07 18:20 ` [PATCH 23/29] block/export: Create BlockBackend in blk_exp_add() Kevin Wolf
2020-09-10 15:09   ` Max Reitz
2020-09-07 18:20 ` [PATCH 24/29] block/export: Add query-block-exports Kevin Wolf
2020-09-10 15:10   ` Max Reitz
2020-09-07 18:20 ` [PATCH 25/29] block/export: Move writable to BlockExportOptions Kevin Wolf
2020-09-10 15:15   ` Max Reitz
2020-09-07 18:20 ` [PATCH 26/29] nbd: Merge nbd_export_new() and nbd_export_create() Kevin Wolf
2020-09-10 15:30   ` Max Reitz
2020-09-07 18:20 ` [PATCH 27/29] nbd: Deprecate nbd-server-add/remove Kevin Wolf
2020-09-10 15:34   ` Max Reitz
2020-09-23 16:19     ` Kevin Wolf
2020-09-07 18:20 ` [PATCH 28/29] iotests: Factor out qemu_tool_pipe_and_status() Kevin Wolf
2020-09-10 15:45   ` Max Reitz
2020-09-07 18:20 ` [PATCH 29/29] iotests: Test block-export-* QMP interface Kevin Wolf
2020-09-10 16:11   ` Max Reitz
2020-09-08  8:38 ` [PATCH 00/29] block/export: Add infrastructure and QAPI for block exports Markus Armbruster
2020-09-08 12:29   ` Kevin Wolf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200907182011.521007-18-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.