[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC PATCH 13/13] nbd: add notifier to close exports when t
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [RFC PATCH 13/13] nbd: add notifier to close exports when the image is closed |
Date: |
Mon, 27 Aug 2012 17:00:26 +0200 |
Signed-off-by: Paolo Bonzini <address@hidden>
---
blockdev-nbd.c | 38 ++++++++++++++++++++++++++++++++++++++
qapi/opts-visitor.c | 48 ++++++++++++++++++++----------------------------
2 file modificati, 58 inserzioni(+), 28 rimozioni(-)
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 5a415be..c190caa 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -62,12 +62,39 @@ void qmp_nbd_server_start(IPSocketAddress *addr, Error
**errp)
qemu_opts_del(opts);
}
+/* Hook into the BlockDriverState notifiers to close the export when
+ * the file is closed.
+ */
+typedef struct NBDCloseNotifier {
+ Notifier n;
+ NBDExport *exp;
+ QTAILQ_ENTRY(NBDCloseNotifier) next;
+} NBDCloseNotifier;
+
+static QTAILQ_HEAD(, NBDCloseNotifier) close_notifiers =
+ QTAILQ_HEAD_INITIALIZER(close_notifiers);
+
+static void nbd_close_notifier_remove(NBDCloseNotifier *cn)
+{
+ notifier_remove(&cn->n);
+ QTAILQ_REMOVE(&close_notifiers, cn, next);
+ g_free(cn);
+}
+
+static void nbd_close_notifier(Notifier *n, void *data)
+{
+ NBDCloseNotifier *cn = DO_UPCAST(NBDCloseNotifier, n, n);
+
+ nbd_export_close(cn->exp);
+ nbd_close_notifier_remove(cn);
+}
void qmp_nbd_server_add(const char *device, bool has_writable, bool writable,
Error **errp)
{
BlockDriverState *bs;
NBDExport *exp;
+ NBDCloseNotifier *n;
bs = bdrv_find(device);
if (!bs) {
@@ -82,10 +109,21 @@ void qmp_nbd_server_add(const char *device, bool
has_writable, bool writable,
exp = nbd_export_new(bs, 0, -1, writable ? 0 : NBD_FLAG_READ_ONLY);
nbd_export_set_name(exp, device);
+
+ n = g_malloc0(sizeof(NBDCloseNotifier));
+ n->n.notify = nbd_close_notifier;
+ n->exp = exp;
+ bdrv_add_close_notifier(bs, &n->n);
+ QTAILQ_INSERT_TAIL(&close_notifiers, n, next);
}
void qmp_nbd_server_stop(Error **errp)
{
+ while (!QTAILQ_EMPTY(&close_notifiers)) {
+ NBDCloseNotifier *cn = QTAILQ_FIRST(&close_notifiers);
+ nbd_close_notifier_remove(cn);
+ }
+
nbd_export_close_all();
qemu_set_fd_handler2(server_fd, NULL, NULL, NULL, NULL);
close(server_fd);
diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
index a59d306..6893d62 100644
--- a/qapi/opts-visitor.c
+++ b/qapi/opts-visitor.c
@@ -20,9 +20,6 @@ struct OptsVisitor
{
Visitor visitor;
- /* Ownership remains with opts_visitor_new()'s caller. */
- const QemuOpts *opts_root;
-
unsigned depth;
/* Non-null iff depth is positive. Each key is a QemuOpt name. Each value
@@ -36,9 +33,9 @@ struct OptsVisitor
GQueue *repeated_opts;
bool repeated_opts_first;
- /* If "opts_root->id" is set, reinstantiate it as a fake QemuOpt for
- * uniformity. Only its "name" and "str" fields are set. "fake_id_opt" does
- * not survive or escape the OptsVisitor object.
+ /* If the "id" is set on the QemuOpts, reinstantiate it as a fake QemuOpt
+ * for uniformity. Only its "name" and "str" fields are set. "fake_id_opt"
+ * does not survive or escape the OptsVisitor object.
*/
QemuOpt *fake_id_opt;
};
@@ -77,29 +74,9 @@ opts_start_struct(Visitor *v, void **obj, const char *kind,
const char *name, size_t size, Error **errp)
{
OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
- const QemuOpt *opt;
*obj = g_malloc0(size > 0 ? size : 1);
- if (ov->depth++ > 0) {
- return;
- }
-
- ov->unprocessed_opts = g_hash_table_new_full(&g_str_hash, &g_str_equal,
- NULL, &destroy_list);
- QTAILQ_FOREACH(opt, &ov->opts_root->head, next) {
- /* ensured by qemu-option.c::opts_do_parse() */
- assert(strcmp(opt->name, "id") != 0);
-
- opts_visitor_insert(ov->unprocessed_opts, opt);
- }
-
- if (ov->opts_root->id != NULL) {
- ov->fake_id_opt = g_malloc0(sizeof *ov->fake_id_opt);
-
- ov->fake_id_opt->name = "id";
- ov->fake_id_opt->str = ov->opts_root->id;
- opts_visitor_insert(ov->unprocessed_opts, ov->fake_id_opt);
- }
+ ov->depth++;
}
@@ -372,6 +349,7 @@ OptsVisitor *
opts_visitor_new(const QemuOpts *opts)
{
OptsVisitor *ov;
+ const QemuOpt *opt;
ov = g_malloc0(sizeof *ov);
@@ -403,8 +381,22 @@ opts_visitor_new(const QemuOpts *opts)
ov->visitor.start_optional = &opts_start_optional;
- ov->opts_root = opts;
+ ov->unprocessed_opts = g_hash_table_new_full(&g_str_hash, &g_str_equal,
+ NULL, &destroy_list);
+ QTAILQ_FOREACH(opt, &opts->head, next) {
+ /* ensured by qemu-option.c::opts_do_parse() */
+ assert(strcmp(opt->name, "id") != 0);
+ opts_visitor_insert(ov->unprocessed_opts, opt);
+ }
+
+ if (opts->id != NULL) {
+ ov->fake_id_opt = g_malloc0(sizeof *ov->fake_id_opt);
+
+ ov->fake_id_opt->name = "id";
+ ov->fake_id_opt->str = opts->id;
+ opts_visitor_insert(ov->unprocessed_opts, ov->fake_id_opt);
+ }
return ov;
}
--
1.7.11.2
- [Qemu-devel] [RFC PATCH 03/13] nbd: do not leak nbd_trip coroutines when a connection is torn down, (continued)
- [Qemu-devel] [RFC PATCH 03/13] nbd: do not leak nbd_trip coroutines when a connection is torn down, Paolo Bonzini, 2012/08/27
- [Qemu-devel] [RFC PATCH 04/13] nbd: close all clients on deleting export, Paolo Bonzini, 2012/08/27
- [Qemu-devel] [RFC PATCH 02/13] nbd: pass NBDClient to nbd_send_negotiate, Paolo Bonzini, 2012/08/27
- [Qemu-devel] [RFC PATCH 05/13] nbd: register named exports, Paolo Bonzini, 2012/08/27
- [Qemu-devel] [RFC PATCH 08/13] qemu-sockets: publish dummy_opts, Paolo Bonzini, 2012/08/27
- [Qemu-devel] [RFC PATCH 07/13] nbd: do not close BlockDriverState in nbd_export_close, Paolo Bonzini, 2012/08/27
- [Qemu-devel] [RFC PATCH 06/13] nbd: negotiate with named exports, Paolo Bonzini, 2012/08/27
- [Qemu-devel] [RFC PATCH 10/13] qemu-sockets: make inet_parse public, Paolo Bonzini, 2012/08/27
- [Qemu-devel] [RFC PATCH 09/13] qmp: add NBD server commands, Paolo Bonzini, 2012/08/27
- [Qemu-devel] [RFC PATCH 11/13] hmp: add NBD server commands, Paolo Bonzini, 2012/08/27
- [Qemu-devel] [RFC PATCH 13/13] nbd: add notifier to close exports when the image is closed,
Paolo Bonzini <=
- [Qemu-devel] [RFC PATCH 12/13] block: add close notifiers, Paolo Bonzini, 2012/08/27