Add all upstream patches since 0.9.6 was released.

Package the ocaml bindings into a subpackage.
This commit is contained in:
Richard W.M. Jones 2019-08-03 15:35:41 +01:00
parent ec2e1367e3
commit f001a4af3f
12 changed files with 1888 additions and 5 deletions

View File

@ -0,0 +1,44 @@
From ed86327eef65c2be126cc8b1d1390a627dc89024 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Tue, 30 Jul 2019 15:41:55 -0500
Subject: [PATCH 01/11] TODO: Mark some items done
0.1.9 included an example of glib (bc3b4230); on the other hand, we
may still want examples of use of ppoll (I experimented with that on
nbdkit but decided that pipe-to-self was more efficient), or pollfd
(Linux-only).
0.1.9 added callback(FREE) (2d9b98e9) which let us fix language
bindings to release callbacks as soon as possible.
0.9.6 got rid of cookies in the completion callback (7091933f), which
in turn avoids the potential race of an early callback.
---
TODO | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/TODO b/TODO
index 6f3c7d8..87bcc1a 100644
--- a/TODO
+++ b/TODO
@@ -1,16 +1,9 @@
-Explore separation of nbd_aio_pread/nbd_aio_submit(callback) since
-current nbd_aio_pread_callback(callback) can race into the callback
-before cookie is known to the user.
-
Explore if nbd_aio_notify_error is needed for faster response if
server goes away.
-Improve python bindings to free persistent closure wrappers at time
-of command completion rather than nbd close.
-
Bindings in other languages.
-Example code integrating with glib2, APR pollset (and others?).
+Example code integrating with ppoll, pollfd, APR pollset (and others?).
Example command line utils to copy in/out (like qemu-img convert).
--
2.22.0

View File

@ -0,0 +1,32 @@
From 8eac86f4a53e6523c5c1693cca1f20f4d8034125 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Thu, 1 Aug 2019 05:51:54 -0500
Subject: [PATCH 02/11] tests: Make sure errors test uses serialized nbdkit
An upcoming nbdkit release will be relaxing sh scripts to be fully
parallel unless the script requests otherwise; but our errors test
depends on the current serialized execution. Thankfully, older nbdkit
does not care if we provide the new hook for the sake of newer nbdkit.
An audit for other testsuite use of nbdkit sh turns up
eflags-plugin.sh and meta-base-allocation.sh, but those will continue
to work in a parallel model.
---
tests/errors.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/errors.c b/tests/errors.c
index 4043c78..8a916fe 100644
--- a/tests/errors.c
+++ b/tests/errors.c
@@ -104,6 +104,7 @@ main (int argc, char *argv[])
if (dprintf (script_fd, "case $1 in\n"
" get_size) echo 128m || exit 1 ;;\n"
+ " thread_model) echo serialize_all_requests; exit 0 ;;\n"
" pread) printf 'ENOMEM ' >&2; exit 1 ;;\n"
" can_write) exit 0 ;;\n"
" pwrite)\n"
--
2.22.0

View File

@ -0,0 +1,650 @@
From 80b922b6b6eaa504f98184ac816cc0ede15365bc Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 3 Aug 2019 10:30:39 +0100
Subject: [PATCH 03/11] tests: Add some basic compile tests, inspired by
nbdkit.
* Compile a program which only includes <libnbd.h>
* Compile a program which only opens and closes the handle.
* Compile a program using ANSI C settings.
* Test the debug flag can be set and cleared, and the effect of the
LIBNBD_DEBUG environment variable.
* Test that the export name can be set and read.
* Test the package name and version APIs.
---
.gitignore | 7 ++
tests/Makefile.am | 135 +++++++++++++++++++++++++++---------
tests/compile-ansi-c.c | 43 ++++++++++++
tests/compile-header-only.c | 27 ++++++++
tests/compile.c | 41 +++++++++++
tests/debug-environment.c | 68 ++++++++++++++++++
tests/debug.c | 70 +++++++++++++++++++
tests/export-name.c | 67 ++++++++++++++++++
tests/version.c | 58 ++++++++++++++++
9 files changed, 482 insertions(+), 34 deletions(-)
create mode 100644 tests/compile-ansi-c.c
create mode 100644 tests/compile-header-only.c
create mode 100644 tests/compile.c
create mode 100644 tests/debug-environment.c
create mode 100644 tests/debug.c
create mode 100644 tests/export-name.c
create mode 100644 tests/version.c
diff --git a/.gitignore b/.gitignore
index ed1e03e..e69d243 100644
--- a/.gitignore
+++ b/.gitignore
@@ -109,13 +109,19 @@ Makefile.in
/tests/can-not-trim-flag
/tests/can-zero-flag
/tests/closure-lifetimes
+/tests/compile
+/tests/compile-ansi-c
+/tests/compile-header-only
/tests/connect-tcp
/tests/connect-tls-certs
/tests/connect-tls-psk
/tests/connect-unix
/tests/connect-uri-tcp
/tests/connect-uri-unix
+/tests/debug
+/tests/debug-environment
/tests/errors
+/tests/export-name
/tests/functions.sh
/tests/get-size
/tests/is-rotational-flag
@@ -123,6 +129,7 @@ Makefile.in
/tests/keys.psk
/tests/meta-base-allocation
/tests/oldstyle
+/tests/version
/tests/pki/
/tests/read-only-flag
/tests/read-write-flag
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 3b8448e..59318b4 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -39,40 +39,9 @@ EXTRA_DIST = \
synch-parallel-tls.sh \
$(NULL)
-if HAVE_NBDKIT
-
check_DATA =
-
-check_PROGRAMS = \
- errors \
- server-death \
- get-size \
- read-only-flag \
- read-write-flag \
- can-flush-flag \
- can-not-flush-flag \
- can-fua-flag \
- can-not-fua-flag \
- is-rotational-flag \
- is-not-rotational-flag \
- can-trim-flag \
- can-not-trim-flag \
- can-zero-flag \
- can-multi-conn-flag \
- can-not-multi-conn-flag \
- oldstyle \
- connect-unix \
- connect-tcp \
- connect-uri-unix \
- connect-uri-tcp \
- aio-parallel \
- aio-parallel-load \
- synch-parallel \
- meta-base-allocation \
- closure-lifetimes \
- $(NULL)
-# can-cache-flag
-# can-not-cache-flag
+check_PROGRAMS =
+TESTS =
# Make sure that $srcdir is available to tests.
# Enable debug in all tests.
@@ -80,7 +49,103 @@ TESTS_ENVIRONMENT = srcdir=$(srcdir) LIBNBD_DEBUG=1
# Use the ./run script so we're always using the local library and tools.
LOG_COMPILER = $(top_builddir)/run
-TESTS = \
+#----------------------------------------------------------------------
+# The following tests do not need an NBD server.
+
+check_PROGRAMS += \
+ compile-header-only \
+ compile \
+ compile-ansi-c \
+ debug \
+ debug-environment \
+ version \
+ export-name \
+ $(NULL)
+
+TESTS += \
+ compile-header-only \
+ compile \
+ compile-ansi-c \
+ debug \
+ debug-environment \
+ version \
+ export-name \
+ $(NULL)
+
+compile_header_only_SOURCES = compile-header-only.c
+compile_header_only_CPPFLAGS = -I$(top_srcdir)/include
+compile_header_only_CFLAGS = $(WARNINGS_CFLAGS)
+compile_header_only_LDADD = $(top_builddir)/lib/libnbd.la
+
+compile_SOURCES = compile.c
+compile_CPPFLAGS = -I$(top_srcdir)/include
+compile_CFLAGS = $(WARNINGS_CFLAGS)
+compile_LDADD = $(top_builddir)/lib/libnbd.la
+
+compile_ansi_c_SOURCES = compile-ansi-c.c
+compile_ansi_c_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -std=c90 -pedantic
+compile_ansi_c_CFLAGS = $(WARNINGS_CFLAGS)
+compile_ansi_c_LDADD = $(top_builddir)/lib/libnbd.la
+
+debug_SOURCES = debug.c
+debug_CPPFLAGS = -I$(top_srcdir)/include
+debug_CFLAGS = $(WARNINGS_CFLAGS)
+debug_LDADD = $(top_builddir)/lib/libnbd.la
+
+debug_environment_SOURCES = debug-environment.c
+debug_environment_CPPFLAGS = -I$(top_srcdir)/include
+debug_environment_CFLAGS = $(WARNINGS_CFLAGS)
+debug_environment_LDADD = $(top_builddir)/lib/libnbd.la
+
+version_SOURCES = version.c
+version_CPPFLAGS = -I$(top_srcdir)/include
+version_CFLAGS = $(WARNINGS_CFLAGS)
+version_LDADD = $(top_builddir)/lib/libnbd.la
+
+export_name_SOURCES = export-name.c
+export_name_CPPFLAGS = -I$(top_srcdir)/include
+export_name_CFLAGS = $(WARNINGS_CFLAGS)
+export_name_LDADD = $(top_builddir)/lib/libnbd.la
+
+#----------------------------------------------------------------------
+# The following tests require nbdkit as an NBD server to test against.
+
+if HAVE_NBDKIT
+
+check_PROGRAMS += \
+ errors \
+ server-death \
+ get-size \
+ read-only-flag \
+ read-write-flag \
+ can-flush-flag \
+ can-not-flush-flag \
+ can-fua-flag \
+ can-not-fua-flag \
+ is-rotational-flag \
+ is-not-rotational-flag \
+ can-trim-flag \
+ can-not-trim-flag \
+ can-zero-flag \
+ can-multi-conn-flag \
+ can-not-multi-conn-flag \
+ oldstyle \
+ connect-unix \
+ connect-tcp \
+ connect-uri-unix \
+ connect-uri-tcp \
+ aio-parallel \
+ aio-parallel-load \
+ synch-parallel \
+ meta-base-allocation \
+ closure-lifetimes \
+ $(NULL)
+# can-cache-flag
+# can-not-cache-flag
+
+TESTS += \
errors \
server-death \
get-size \
@@ -286,7 +351,9 @@ closure_lifetimes_CPPFLAGS = -I$(top_srcdir)/include
closure_lifetimes_CFLAGS = $(WARNINGS_CFLAGS)
closure_lifetimes_LDADD = $(top_builddir)/lib/libnbd.la
+#----------------------------------------------------------------------
# Testing TLS support.
+
if HAVE_GNUTLS
if HAVE_CERTTOOL
diff --git a/tests/compile-ansi-c.c b/tests/compile-ansi-c.c
new file mode 100644
index 0000000..0d48618
--- /dev/null
+++ b/tests/compile-ansi-c.c
@@ -0,0 +1,43 @@
+/* NBD client library in userspace
+ * Copyright (C) 2013-2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Test that (only simple) programs can be compiled by an ANSI C
+ * compiler.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libnbd.h>
+
+int
+main (int argc, char *argv[])
+{
+ struct nbd_handle *nbd;
+
+ nbd = nbd_create ();
+ if (nbd == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ nbd_close (nbd);
+ exit (EXIT_SUCCESS);
+}
diff --git a/tests/compile-header-only.c b/tests/compile-header-only.c
new file mode 100644
index 0000000..52b93d7
--- /dev/null
+++ b/tests/compile-header-only.c
@@ -0,0 +1,27 @@
+/* NBD client library in userspace
+ * Copyright (C) 2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Check that <libnbd.h> does not require any other headers. */
+
+#include <libnbd.h>
+
+int
+main (int argc, char *argv[])
+{
+ return 0;
+}
diff --git a/tests/compile.c b/tests/compile.c
new file mode 100644
index 0000000..d7ef98c
--- /dev/null
+++ b/tests/compile.c
@@ -0,0 +1,41 @@
+/* NBD client library in userspace
+ * Copyright (C) 2013-2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Compile, open and close a handle. */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libnbd.h>
+
+int
+main (int argc, char *argv[])
+{
+ struct nbd_handle *nbd;
+
+ nbd = nbd_create ();
+ if (nbd == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ nbd_close (nbd);
+ exit (EXIT_SUCCESS);
+}
diff --git a/tests/debug-environment.c b/tests/debug-environment.c
new file mode 100644
index 0000000..e11708a
--- /dev/null
+++ b/tests/debug-environment.c
@@ -0,0 +1,68 @@
+/* NBD client library in userspace
+ * Copyright (C) 2013-2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Check that LIBNBD_DEBUG=0|1 affects the debug flag. */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <libnbd.h>
+
+static int
+get_debug_flag (void)
+{
+ struct nbd_handle *nbd;
+ int r;
+
+ nbd = nbd_create ();
+ if (nbd == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ r = nbd_get_debug (nbd);
+ if (r == -1) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ nbd_close (nbd);
+
+ return r;
+}
+
+int
+main (int argc, char *argv[])
+{
+ setenv ("LIBNBD_DEBUG", "1", 1);
+ assert (get_debug_flag () == 1);
+
+ setenv ("LIBNBD_DEBUG", "0", 1);
+ assert (get_debug_flag () == 0);
+
+ setenv ("LIBNBD_DEBUG", "", 1);
+ assert (get_debug_flag () == 0);
+
+ unsetenv ("LIBNBD_DEBUG");
+ assert (get_debug_flag () == 0);
+
+ exit (EXIT_SUCCESS);
+}
diff --git a/tests/debug.c b/tests/debug.c
new file mode 100644
index 0000000..af2e80f
--- /dev/null
+++ b/tests/debug.c
@@ -0,0 +1,70 @@
+/* NBD client library in userspace
+ * Copyright (C) 2013-2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Test setting and reading the debug flag. */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+
+#include <libnbd.h>
+
+int
+main (int argc, char *argv[])
+{
+ struct nbd_handle *nbd;
+ int r;
+
+ nbd = nbd_create ();
+ if (nbd == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ r = nbd_set_debug (nbd, true);
+ if (r == -1) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ r = nbd_get_debug (nbd);
+ if (r == -1) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+ assert (r == 1);
+
+ r = nbd_set_debug (nbd, false);
+ if (r == -1) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ r = nbd_get_debug (nbd);
+ if (r == -1) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+ assert (r == 0);
+
+ nbd_close (nbd);
+ exit (EXIT_SUCCESS);
+}
diff --git a/tests/export-name.c b/tests/export-name.c
new file mode 100644
index 0000000..7cbc3cd
--- /dev/null
+++ b/tests/export-name.c
@@ -0,0 +1,67 @@
+/* NBD client library in userspace
+ * Copyright (C) 2013-2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Test setting and reading the export name. */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libnbd.h>
+
+static void
+check_export_name (struct nbd_handle *nbd, const char *str)
+{
+ char *r;
+
+ if (nbd_set_export_name (nbd, str) == -1) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ r = nbd_get_export_name (nbd);
+ if (r == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ assert (strcmp (str, r) == 0);
+ free (r);
+}
+
+int
+main (int argc, char *argv[])
+{
+ struct nbd_handle *nbd;
+
+ nbd = nbd_create ();
+ if (nbd == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ check_export_name (nbd, "/");
+ check_export_name (nbd, "123");
+ check_export_name (nbd, "");
+
+ nbd_close (nbd);
+ exit (EXIT_SUCCESS);
+}
diff --git a/tests/version.c b/tests/version.c
new file mode 100644
index 0000000..1ba3f58
--- /dev/null
+++ b/tests/version.c
@@ -0,0 +1,58 @@
+/* NBD client library in userspace
+ * Copyright (C) 2013-2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Read the package and version from the handle. */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <libnbd.h>
+
+int
+main (int argc, char *argv[])
+{
+ struct nbd_handle *nbd;
+ const char *s;
+
+ nbd = nbd_create ();
+ if (nbd == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+
+ s = nbd_get_package_name (nbd);
+ if (s == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+ assert (strcmp (s, PACKAGE_NAME) == 0);
+
+ s = nbd_get_version (nbd);
+ if (s == NULL) {
+ fprintf (stderr, "%s\n", nbd_get_error ());
+ exit (EXIT_FAILURE);
+ }
+ assert (strcmp (s, PACKAGE_VERSION) == 0);
+
+ nbd_close (nbd);
+ exit (EXIT_SUCCESS);
+}
--
2.22.0

View File

@ -0,0 +1,162 @@
From e1efb1fd2efbadfa0a2b53662f2757c728e119ab Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 3 Aug 2019 11:00:40 +0100
Subject: [PATCH 04/11] Fix compilation with C++.
We lacked the appropriate extern "C" section in the header, so
compilation would fail if you were using C++.
This also adds a simple regression test.
---
.gitignore | 1 +
configure.ac | 11 +++++++++
generator/generator | 8 +++++++
tests/Makefile.am | 12 ++++++++++
tests/compile-cxx.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 84 insertions(+)
create mode 100644 tests/compile-cxx.cpp
diff --git a/.gitignore b/.gitignore
index e69d243..9558577 100644
--- a/.gitignore
+++ b/.gitignore
@@ -111,6 +111,7 @@ Makefile.in
/tests/closure-lifetimes
/tests/compile
/tests/compile-ansi-c
+/tests/compile-cxx
/tests/compile-header-only
/tests/connect-tcp
/tests/connect-tls-certs
diff --git a/configure.ac b/configure.ac
index 30d7f90..8c47e61 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,6 +44,17 @@ AM_PROG_CC_C_O
AX_PTHREAD
+dnl Check for C++ (optional, we just use this to test the header
+dnl can be included from C++ code).
+AC_PROG_CXX
+
+dnl The C++ compiler test is pretty useless because even if it fails
+dnl it sets CXX=g++. So test the compiler actually works.
+AC_MSG_CHECKING([if the C++ compiler really really works])
+AS_IF([$CXX --version >&AS_MESSAGE_LOG_FD 2>&1],[have_cxx=yes],[have_cxx=no])
+AC_MSG_RESULT([$have_cxx])
+AM_CONDITIONAL([HAVE_CXX], [test "$have_cxx" = "yes"])
+
AC_ARG_ENABLE([gcc-warnings],
[AS_HELP_STRING([--enable-gcc-warnings],
[turn on lots of GCC warnings (for developers)])],
diff --git a/generator/generator b/generator/generator
index 62ca99c..0d10214 100755
--- a/generator/generator
+++ b/generator/generator
@@ -3332,6 +3332,10 @@ let generate_include_libnbd_h () =
pr "#include <stdint.h>\n";
pr "#include <sys/socket.h>\n";
pr "\n";
+ pr "#ifdef __cplusplus\n";
+ pr "extern \"C\" {\n";
+ pr "#endif\n";
+ pr "\n";
pr "struct nbd_handle;\n";
pr "\n";
pr "typedef void (*nbd_close_callback) (void *user_data);\n";
@@ -3361,6 +3365,10 @@ let generate_include_libnbd_h () =
fun (ns, ctxts) -> print_ns ns ctxts
) metadata_namespaces;
pr "\n";
+ pr "#ifdef __cplusplus\n";
+ pr "}\n";
+ pr "#endif\n";
+ pr "\n";
pr "#endif /* LIBNBD_H */\n"
let generate_lib_unlocked_h () =
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 59318b4..3064301 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -109,6 +109,18 @@ export_name_CPPFLAGS = -I$(top_srcdir)/include
export_name_CFLAGS = $(WARNINGS_CFLAGS)
export_name_LDADD = $(top_builddir)/lib/libnbd.la
+if HAVE_CXX
+
+check_PROGRAMS += compile-cxx
+TESTS += compile-cxx
+
+compile_cxx_SOURCES = compile-cxx.cpp
+compile_cxx_CPPFLAGS = -I$(top_srcdir)/include
+compile_cxx_CXXFLAGS = $(WARNINGS_CFLAGS)
+compile_cxx_LDADD = $(top_builddir)/lib/libnbd.la
+
+endif HAVE_CXX
+
#----------------------------------------------------------------------
# The following tests require nbdkit as an NBD server to test against.
diff --git a/tests/compile-cxx.cpp b/tests/compile-cxx.cpp
new file mode 100644
index 0000000..4c8447c
--- /dev/null
+++ b/tests/compile-cxx.cpp
@@ -0,0 +1,52 @@
+/* NBD client library in userspace
+ * Copyright (C) 2013-2019 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Test compilation with C++. */
+
+#ifndef __cplusplus
+#error "this test should be compiled with a C++ compiler"
+#endif
+
+#include <config.h>
+
+#include <iostream>
+#include <cstdlib>
+
+#include <libnbd.h>
+
+using namespace std;
+
+int
+main ()
+{
+ struct nbd_handle *nbd;
+
+ nbd = nbd_create ();
+ if (nbd == NULL) {
+ cerr << nbd_get_error () << endl;
+ exit (EXIT_FAILURE);
+ }
+
+ cout << nbd_get_package_name (nbd)
+ << " "
+ << nbd_get_version (nbd)
+ << endl;
+
+ nbd_close (nbd);
+ exit (EXIT_SUCCESS);
+}
--
2.22.0

View File

@ -0,0 +1,25 @@
From a892453f1c04ea33cf8b98dff5a7e1c21e7bf0ce Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 3 Aug 2019 11:18:00 +0100
Subject: [PATCH 05/11] run: Set MALLOC_CHECK_=1 when using ./run or running
the tests.
---
run.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/run.in b/run.in
index 56ed703..83c92a7 100755
--- a/run.in
+++ b/run.in
@@ -73,6 +73,7 @@ export CAML_LD_LIBRARY_PATH
# This is a cheap way to find some use-after-free and uninitialized
# read problems when using glibc.
+export MALLOC_CHECK_=1
random_val="$(@AWK@ 'BEGIN{srand(); print 1+int(255*rand())}' < /dev/null)"
export MALLOC_PERTURB_=$random_val
--
2.22.0

View File

@ -0,0 +1,29 @@
From 9be99ad2ba0e81dc44f74b4dfc756b37a02de0fb Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 3 Aug 2019 12:40:01 +0100
Subject: [PATCH 06/11] include: Remove unused definition of
nbd_close_callback.
This feature was removed in
commit 7f191b150b52ed50098976309a6af883d245fc56 but the typedef was
left in the header file accidentally.
---
generator/generator | 2 --
1 file changed, 2 deletions(-)
diff --git a/generator/generator b/generator/generator
index 0d10214..2a952cc 100755
--- a/generator/generator
+++ b/generator/generator
@@ -3338,8 +3338,6 @@ let generate_include_libnbd_h () =
pr "\n";
pr "struct nbd_handle;\n";
pr "\n";
- pr "typedef void (*nbd_close_callback) (void *user_data);\n";
- pr "\n";
List.iter (fun (n, i) -> pr "#define LIBNBD_%-30s %d\n" n i) constants;
pr "\n";
pr "#define LIBNBD_CALLBACK_VALID 1\n";
--
2.22.0

View File

@ -0,0 +1,724 @@
From 3b35624499d01a4a37df26db5333a5218b7960f8 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 3 Aug 2019 13:10:30 +0100
Subject: [PATCH 07/11] generator: Generate typedefs automatically for Closure
arguments.
For example nbd_set_debug takes a callback function. Previously this
was defined explicitly inside the function parameters. This commit
defines a new public typedef:
typedef int (*nbd_debug_callback) (unsigned valid_flag, void *user_data,
const char *context, const char *msg);
and then uses the typedef like this:
extern int nbd_set_debug_callback (struct nbd_handle *h,
nbd_debug_callback debug_callback,
void *debug_callback_user_data);
(Previously typedefs were available, but they were written by hand and
only used internally to the library.)
This change necessitates that we uniquely name all of our closures
across methods (the same-named closure is required to have the same
cbargs).
I took this opportunity to rename some, so especially completion
callbacks now have the type nbd_completion_callback. The generator
also checks they are named uniquely.
This does not change the C API or ABI.
---
generator/generator | 93 +++++++++++++++++++++++------
generator/states-reply-simple.c | 12 ++--
generator/states-reply-structured.c | 40 ++++++-------
generator/states-reply.c | 8 +--
generator/states.c | 8 +--
lib/aio.c | 12 ++--
lib/debug.c | 12 ++--
lib/handle.c | 6 +-
lib/internal.h | 20 ++-----
lib/rw.c | 61 +++++++++++--------
10 files changed, 165 insertions(+), 107 deletions(-)
diff --git a/generator/generator b/generator/generator
index 2a952cc..6f89792 100755
--- a/generator/generator
+++ b/generator/generator
@@ -924,7 +924,7 @@ Return the state of the debug flag on this handle.";
"set_debug_callback", {
default_call with
- args = [ Closure { cbname="debug_fn";
+ args = [ Closure { cbname="debug";
cbargs=[String "context"; String "msg"] } ];
ret = RErr;
shortdesc = "set the debug callback";
@@ -1731,7 +1731,7 @@ C<nbd_pread>.";
"aio_pread_callback", {
default_call with
args = [ BytesPersistOut ("buf", "count"); UInt64 "offset";
- Closure { cbname="callback";
+ Closure { cbname="completion";
cbargs=[Mutable (Int "error")] };
Flags "flags" ];
ret = RInt64;
@@ -1778,7 +1778,7 @@ documented in C<nbd_pread_structured>.";
UInt64 "offset";
UInt "status";
Mutable (Int "error")] };
- Closure { cbname="callback";
+ Closure { cbname="completion";
cbargs=[Mutable (Int "error")] };
Flags "flags" ];
ret = RInt64;
@@ -1814,7 +1814,7 @@ C<nbd_pwrite>.";
"aio_pwrite_callback", {
default_call with
args = [ BytesPersistIn ("buf", "count"); UInt64 "offset";
- Closure { cbname="callback";
+ Closure { cbname="completion";
cbargs=[Mutable (Int "error")] };
Flags "flags" ];
ret = RInt64;
@@ -1870,7 +1870,7 @@ Parameters behave as documented in C<nbd_flush>.";
"aio_flush_callback", {
default_call with
- args = [ Closure { cbname="callback";
+ args = [ Closure { cbname="completion";
cbargs=[Mutable (Int "error")] };
Flags "flags" ];
ret = RInt64;
@@ -1904,7 +1904,7 @@ Parameters behave as documented in C<nbd_trim>.";
"aio_trim_callback", {
default_call with
args = [ UInt64 "count"; UInt64 "offset";
- Closure { cbname="callback";
+ Closure { cbname="completion";
cbargs=[Mutable (Int "error")] };
Flags "flags" ];
ret = RInt64;
@@ -1938,7 +1938,7 @@ Parameters behave as documented in C<nbd_cache>.";
"aio_cache_callback", {
default_call with
args = [ UInt64 "count"; UInt64 "offset";
- Closure { cbname="callback";
+ Closure { cbname="completion";
cbargs=[Mutable (Int "error")] };
Flags "flags" ];
ret = RInt64;
@@ -1972,7 +1972,7 @@ Parameters behave as documented in C<nbd_zero>.";
"aio_zero_callback", {
default_call with
args = [ UInt64 "count"; UInt64 "offset";
- Closure { cbname="callback";
+ Closure { cbname="completion";
cbargs=[Mutable (Int "error")] };
Flags "flags" ];
ret = RInt64;
@@ -2017,7 +2017,7 @@ Parameters behave as documented in C<nbd_block_status>.";
ArrayAndLen (UInt32 "entries",
"nr_entries");
Mutable (Int "error")] };
- Closure { cbname="callback";
+ Closure { cbname="completion";
cbargs=[Mutable (Int "error")] };
Flags "flags" ];
ret = RInt64;
@@ -2363,6 +2363,25 @@ let rec group_by = function
| (day, x) :: rest ->
(day, [x]) :: group_by rest
+let uniq ?(cmp = Pervasives.compare) xs =
+ let rec loop acc = function
+ | [] -> acc
+ | [x] -> x :: acc
+ | x :: (y :: _ as xs) when cmp x y = 0 ->
+ loop acc xs
+ | x :: (y :: _ as xs) ->
+ loop (x :: acc) xs
+ in
+ List.rev (loop [] xs)
+
+(* This is present in OCaml 4.04, so we can remove it when
+ * we depend on OCaml >= 4.04.
+ *)
+let sort_uniq ?(cmp = Pervasives.compare) xs =
+ let xs = List.sort cmp xs in
+ let xs = uniq ~cmp xs in
+ xs
+
let chan = ref Pervasives.stdout
let pr fs = ksprintf (fun str -> output_string !chan str) fs
@@ -3100,6 +3119,30 @@ let () =
name
) handle_calls;
+ (* Closures must be uniquely named across all calls. *)
+ let () =
+ let all_args =
+ List.flatten (List.map (fun (_, { args }) -> args) handle_calls) in
+ let h = Hashtbl.create 13 in
+ List.iter (
+ function
+ | Closure { cbname; cbargs } ->
+ (try
+ (* If we've already added this name to the hash, check
+ * closure args are identical.
+ *)
+ let other_cbargs = Hashtbl.find h cbname in
+ if cbargs <> other_cbargs then
+ failwithf "%s: Closure has different arguments across methods"
+ cbname
+ with Not_found ->
+ (* Otherwise add it to the hash. *)
+ Hashtbl.add h cbname cbargs
+ )
+ | _ -> ()
+ ) all_args
+ in
+
(* !may_set_error is incompatible with permitted_states != [] because
* an incorrect state will result in set_error being called by the
* generated wrapper. It is also incompatible with RUint.
@@ -3170,7 +3213,8 @@ let rec name_of_arg = function
| BytesOut (n, len) -> [n; len]
| BytesPersistIn (n, len) -> [n; len]
| BytesPersistOut (n, len) -> [n; len]
-| Closure { cbname } -> [cbname; sprintf "%s_user_data" cbname ]
+| Closure { cbname } ->
+ [ sprintf "%s_callback" cbname; sprintf "%s_user_data" cbname ]
| Flags n -> [n]
| Int n -> [n]
| Int64 n -> [n]
@@ -3232,12 +3276,8 @@ let rec print_arg_list ?(handle = false) ?(valid_flag = false)
if types then pr "size_t ";
pr "%s" len
| Closure { cbname; cbargs } ->
- if types then (
- pr "int (*%s) " cbname;
- print_arg_list ~valid_flag:true ~user_data:true cbargs;
- )
- else
- pr "%s" cbname;
+ if types then pr "nbd_%s_callback " cbname;
+ pr "%s_callback" cbname;
pr ", ";
if types then pr "void *";
pr "%s_user_data" cbname
@@ -3297,6 +3337,24 @@ let print_extern name args ret =
print_call name args ret;
pr ";\n"
+(* Callback typedefs in <libnbd.h> *)
+let print_closure_typedefs () =
+ let all_cls =
+ List.map (
+ fun (_, { args }) ->
+ filter_map (function Closure cl -> Some cl | _ -> None) args
+ ) handle_calls in
+ let all_cls = List.flatten all_cls in
+ let cmp { cbname = n1 } { cbname = n2 } = compare n1 n2 in
+ let unique_cls = sort_uniq ~cmp all_cls in
+ List.iter (
+ fun { cbname; cbargs } ->
+ pr "typedef int (*nbd_%s_callback) " cbname;
+ print_arg_list ~valid_flag:true ~user_data:true cbargs;
+ pr ";\n";
+ ) unique_cls;
+ pr "\n"
+
let print_extern_and_define name args ret =
let name_upper = String.uppercase_ascii name in
print_extern name args ret;
@@ -3355,6 +3413,7 @@ let generate_include_libnbd_h () =
pr "extern int nbd_get_errno (void);\n";
pr "#define LIBNBD_HAVE_NBD_GET_ERRNO 1\n";
pr "\n";
+ print_closure_typedefs ();
List.iter (
fun (name, { args; ret }) -> print_extern_and_define name args ret
) handle_calls;
@@ -4845,7 +4904,7 @@ let print_ocaml_binding (name, { args; ret }) =
pr " if (%s_user_data == NULL) caml_raise_out_of_memory ();\n" cbname;
pr " caml_register_generational_global_root (%s_user_data);\n" cbname;
pr " *%s_user_data = %sv;\n" cbname cbname;
- pr " const void *%s = %s_%s_wrapper;\n" cbname name cbname
+ pr " const void *%s_callback = %s_%s_wrapper;\n" cbname name cbname
| OCamlArg (Flags _) -> assert false (* see above *)
| OCamlArg (Int n) ->
pr " int %s = Int_val (%sv);\n" n n
diff --git a/generator/states-reply-simple.c b/generator/states-reply-simple.c
index e0fd71d..9b249ab 100644
--- a/generator/states-reply-simple.c
+++ b/generator/states-reply-simple.c
@@ -60,16 +60,16 @@
case 0:
/* guaranteed by START */
assert (cmd);
- if (cmd->cb.fn.read) {
+ if (cmd->cb.fn.chunk) {
int error = 0;
assert (cmd->error == 0);
- if (cmd->cb.fn.read (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE,
- cmd->cb.fn_user_data,
- cmd->data, cmd->count,
- cmd->offset, LIBNBD_READ_DATA, &error) == -1)
+ if (cmd->cb.fn.chunk (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE,
+ cmd->cb.fn_user_data,
+ cmd->data, cmd->count,
+ cmd->offset, LIBNBD_READ_DATA, &error) == -1)
cmd->error = error ? error : EPROTO;
- cmd->cb.fn.read = NULL; /* because we've freed it */
+ cmd->cb.fn.chunk = NULL; /* because we've freed it */
}
SET_NEXT_STATE (%^FINISH_COMMAND);
diff --git a/generator/states-reply-structured.c b/generator/states-reply-structured.c
index ff5b727..cdd9f10 100644
--- a/generator/states-reply-structured.c
+++ b/generator/states-reply-structured.c
@@ -304,7 +304,7 @@ valid_flags (struct nbd_handle *h)
offset, cmd->offset, cmd->count);
return 0;
}
- if (cmd->type == NBD_CMD_READ && cmd->cb.fn.read) {
+ if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk) {
int scratch = error;
unsigned valid = valid_flags (h);
@@ -312,13 +312,13 @@ valid_flags (struct nbd_handle *h)
* current error rather than any earlier one. If the callback fails
* without setting errno, then use the server's error below.
*/
- if (cmd->cb.fn.read (valid, cmd->cb.fn_user_data,
- cmd->data + (offset - cmd->offset),
- 0, offset, LIBNBD_READ_ERROR, &scratch) == -1)
+ if (cmd->cb.fn.chunk (valid, cmd->cb.fn_user_data,
+ cmd->data + (offset - cmd->offset),
+ 0, offset, LIBNBD_READ_ERROR, &scratch) == -1)
if (cmd->error == 0)
cmd->error = scratch;
if (valid & LIBNBD_CALLBACK_FREE)
- cmd->cb.fn.read = NULL; /* because we've freed it */
+ cmd->cb.fn.chunk = NULL; /* because we've freed it */
}
}
@@ -398,18 +398,18 @@ valid_flags (struct nbd_handle *h)
offset = be64toh (h->sbuf.sr.payload.offset_data.offset);
assert (cmd); /* guaranteed by CHECK */
- if (cmd->cb.fn.read) {
+ if (cmd->cb.fn.chunk) {
int error = cmd->error;
unsigned valid = valid_flags (h);
- if (cmd->cb.fn.read (valid, cmd->cb.fn_user_data,
- cmd->data + (offset - cmd->offset),
- length - sizeof offset, offset,
+ if (cmd->cb.fn.chunk (valid, cmd->cb.fn_user_data,
+ cmd->data + (offset - cmd->offset),
+ length - sizeof offset, offset,
LIBNBD_READ_DATA, &error) == -1)
if (cmd->error == 0)
cmd->error = error ? error : EPROTO;
if (valid & LIBNBD_CALLBACK_FREE)
- cmd->cb.fn.read = NULL; /* because we've freed it */
+ cmd->cb.fn.chunk = NULL; /* because we've freed it */
}
SET_NEXT_STATE (%FINISH);
@@ -463,18 +463,18 @@ valid_flags (struct nbd_handle *h)
* them as an extension, and this works even when length == 0.
*/
memset (cmd->data + offset, 0, length);
- if (cmd->cb.fn.read) {
+ if (cmd->cb.fn.chunk) {
int error = cmd->error;
unsigned valid = valid_flags (h);
- if (cmd->cb.fn.read (valid, cmd->cb.fn_user_data,
- cmd->data + offset, length,
- cmd->offset + offset,
- LIBNBD_READ_HOLE, &error) == -1)
+ if (cmd->cb.fn.chunk (valid, cmd->cb.fn_user_data,
+ cmd->data + offset, length,
+ cmd->offset + offset,
+ LIBNBD_READ_HOLE, &error) == -1)
if (cmd->error == 0)
cmd->error = error ? error : EPROTO;
if (valid & LIBNBD_CALLBACK_FREE)
- cmd->cb.fn.read = NULL; /* because we've freed it */
+ cmd->cb.fn.chunk = NULL; /* because we've freed it */
}
SET_NEXT_STATE(%FINISH);
@@ -548,10 +548,10 @@ valid_flags (struct nbd_handle *h)
if (cmd->type == NBD_CMD_BLOCK_STATUS && cmd->cb.fn.extent)
cmd->cb.fn.extent (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data,
NULL, 0, NULL, 0, NULL);
- if (cmd->type == NBD_CMD_READ && cmd->cb.fn.read)
- cmd->cb.fn.read (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data,
- NULL, 0, 0, 0, NULL);
- cmd->cb.fn.read = NULL;
+ if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk)
+ cmd->cb.fn.chunk (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data,
+ NULL, 0, 0, 0, NULL);
+ cmd->cb.fn.chunk = NULL;
SET_NEXT_STATE (%^FINISH_COMMAND);
}
else {
diff --git a/generator/states-reply.c b/generator/states-reply.c
index 078d67f..09adfed 100644
--- a/generator/states-reply.c
+++ b/generator/states-reply.c
@@ -168,14 +168,14 @@ save_reply_state (struct nbd_handle *h)
retire = cmd->type == NBD_CMD_DISC;
/* Notify the user */
- if (cmd->cb.callback) {
+ if (cmd->cb.completion) {
int error = cmd->error;
int r;
assert (cmd->type != NBD_CMD_DISC);
- r = cmd->cb.callback (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE,
- cmd->cb.user_data, &error);
- cmd->cb.callback = NULL; /* because we've freed it */
+ r = cmd->cb.completion (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE,
+ cmd->cb.user_data, &error);
+ cmd->cb.completion = NULL; /* because we've freed it */
switch (r) {
case -1:
if (error)
diff --git a/generator/states.c b/generator/states.c
index 654e4c8..9ed57ae 100644
--- a/generator/states.c
+++ b/generator/states.c
@@ -121,14 +121,14 @@ void abort_commands (struct nbd_handle *h,
bool retire = cmd->type == NBD_CMD_DISC;
next = cmd->next;
- if (cmd->cb.callback) {
+ if (cmd->cb.completion) {
int error = cmd->error ? cmd->error : ENOTCONN;
int r;
assert (cmd->type != NBD_CMD_DISC);
- r = cmd->cb.callback (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE,
- cmd->cb.user_data, &error);
- cmd->cb.callback = NULL; /* because we've freed it */
+ r = cmd->cb.completion (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE,
+ cmd->cb.user_data, &error);
+ cmd->cb.completion = NULL; /* because we've freed it */
switch (r) {
case -1:
if (error)
diff --git a/lib/aio.c b/lib/aio.c
index 1c11dbd..c141de6 100644
--- a/lib/aio.c
+++ b/lib/aio.c
@@ -35,12 +35,12 @@ nbd_internal_retire_and_free_command (struct command *cmd)
if (cmd->type == NBD_CMD_BLOCK_STATUS && cmd->cb.fn.extent)
cmd->cb.fn.extent (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data,
NULL, 0, NULL, 0, NULL);
- if (cmd->type == NBD_CMD_READ && cmd->cb.fn.read)
- cmd->cb.fn.read (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data,
- NULL, 0, 0, 0, NULL);
- if (cmd->cb.callback)
- cmd->cb.callback (LIBNBD_CALLBACK_FREE, cmd->cb.user_data,
- NULL);
+ if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk)
+ cmd->cb.fn.chunk (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data,
+ NULL, 0, 0, 0, NULL);
+ if (cmd->cb.completion)
+ cmd->cb.completion (LIBNBD_CALLBACK_FREE, cmd->cb.user_data,
+ NULL);
free (cmd);
}
diff --git a/lib/debug.c b/lib/debug.c
index 7784bd9..f4b374d 100644
--- a/lib/debug.c
+++ b/lib/debug.c
@@ -40,12 +40,12 @@ nbd_unlocked_get_debug (struct nbd_handle *h)
int
nbd_unlocked_set_debug_callback (struct nbd_handle *h,
- debug_fn debug_fn, void *data)
+ nbd_debug_callback debug_callback, void *data)
{
- if (h->debug_fn)
+ if (h->debug_callback)
/* ignore return value */
- h->debug_fn (LIBNBD_CALLBACK_FREE, h->debug_data, NULL, NULL);
- h->debug_fn = debug_fn;
+ h->debug_callback (LIBNBD_CALLBACK_FREE, h->debug_data, NULL, NULL);
+ h->debug_callback = debug_callback;
h->debug_data = data;
return 0;
}
@@ -76,9 +76,9 @@ nbd_internal_debug (struct nbd_handle *h, const char *fs, ...)
if (r == -1)
goto out;
- if (h->debug_fn)
+ if (h->debug_callback)
/* ignore return value */
- h->debug_fn (LIBNBD_CALLBACK_VALID, h->debug_data, context, msg);
+ h->debug_callback (LIBNBD_CALLBACK_VALID, h->debug_data, context, msg);
else
fprintf (stderr, "libnbd: debug: %s: %s\n", context ? : "unknown", msg);
out:
diff --git a/lib/handle.c b/lib/handle.c
index a9ade3d..1360079 100644
--- a/lib/handle.c
+++ b/lib/handle.c
@@ -105,9 +105,9 @@ nbd_close (struct nbd_handle *h)
return;
/* Free user callbacks first. */
- if (h->debug_fn)
- h->debug_fn (LIBNBD_CALLBACK_FREE, h->debug_data, NULL, NULL);
- h->debug_fn = NULL;
+ if (h->debug_callback)
+ h->debug_callback (LIBNBD_CALLBACK_FREE, h->debug_data, NULL, NULL);
+ h->debug_callback = NULL;
free (h->bs_entries);
for (m = h->meta_contexts; m != NULL; m = m_next) {
diff --git a/lib/internal.h b/lib/internal.h
index 90ce6aa..d85fb4b 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -47,7 +47,6 @@
struct meta_context;
struct socket;
struct command;
-typedef int (*debug_fn) (unsigned, void *, const char *, const char *);
struct nbd_handle {
/* Lock protecting concurrent access to the handle. */
@@ -80,7 +79,7 @@ struct nbd_handle {
/* For debugging. */
bool debug;
- debug_fn debug_fn;
+ nbd_debug_callback debug_callback;
void *debug_data;
/* State machine.
@@ -248,23 +247,14 @@ struct socket {
const struct socket_ops *ops;
};
-typedef int (*extent_fn) (unsigned valid_flag, void *user_data,
- const char *metacontext, uint64_t offset,
- uint32_t *entries, size_t nr_entries, int *error);
-typedef int (*read_fn) (unsigned valid_flag, void *user_data,
- const void *buf, size_t count,
- uint64_t offset, unsigned status, int *error);
-typedef int (*callback_fn) (unsigned valid_flag, void *user_data,
- int *error);
-
struct command_cb {
union {
- extent_fn extent;
- read_fn read;
+ nbd_extent_callback extent;
+ nbd_chunk_callback chunk;
} fn;
void *fn_user_data; /* associated with one of the fn callbacks above */
- callback_fn callback;
- void *user_data; /* associated with the callback function */
+ nbd_completion_callback completion;
+ void *user_data; /* associated with the completion callback */
};
struct command {
diff --git a/lib/rw.c b/lib/rw.c
index 382cfb9..51ee691 100644
--- a/lib/rw.c
+++ b/lib/rw.c
@@ -60,12 +60,13 @@ nbd_unlocked_pread (struct nbd_handle *h, void *buf,
int
nbd_unlocked_pread_structured (struct nbd_handle *h, void *buf,
size_t count, uint64_t offset,
- read_fn read, void *user_data, uint32_t flags)
+ nbd_chunk_callback chunk, void *user_data,
+ uint32_t flags)
{
int64_t cookie;
cookie = nbd_unlocked_aio_pread_structured (h, buf, count, offset,
- read, user_data, flags);
+ chunk, user_data, flags);
if (cookie == -1)
return -1;
@@ -145,7 +146,8 @@ nbd_unlocked_zero (struct nbd_handle *h,
int
nbd_unlocked_block_status (struct nbd_handle *h,
uint64_t count, uint64_t offset,
- extent_fn extent, void *user_data, uint32_t flags)
+ nbd_extent_callback extent, void *user_data,
+ uint32_t flags)
{
int64_t cookie;
@@ -255,10 +257,11 @@ nbd_unlocked_aio_pread (struct nbd_handle *h, void *buf,
int64_t
nbd_unlocked_aio_pread_callback (struct nbd_handle *h, void *buf,
size_t count, uint64_t offset,
- callback_fn callback, void *user_data,
+ nbd_completion_callback completion,
+ void *user_data,
uint32_t flags)
{
- struct command_cb cb = { .callback = callback, .user_data = user_data, };
+ struct command_cb cb = { .completion = completion, .user_data = user_data, };
/* We could silently accept flag DF, but it really only makes sense
* with callbacks, because otherwise there is no observable change
@@ -276,11 +279,11 @@ nbd_unlocked_aio_pread_callback (struct nbd_handle *h, void *buf,
int64_t
nbd_unlocked_aio_pread_structured (struct nbd_handle *h, void *buf,
size_t count, uint64_t offset,
- read_fn read, void *user_data,
+ nbd_chunk_callback chunk, void *user_data,
uint32_t flags)
{
return nbd_unlocked_aio_pread_structured_callback (h, buf, count, offset,
- read, user_data,
+ chunk, user_data,
NULL, NULL,
flags);
}
@@ -288,15 +291,15 @@ nbd_unlocked_aio_pread_structured (struct nbd_handle *h, void *buf,
int64_t
nbd_unlocked_aio_pread_structured_callback (struct nbd_handle *h, void *buf,
size_t count, uint64_t offset,
- read_fn read,
+ nbd_chunk_callback chunk,
void *read_user_data,
- callback_fn callback,
+ nbd_completion_callback completion,
void *callback_user_data,
uint32_t flags)
{
- struct command_cb cb = { .fn.read = read,
+ struct command_cb cb = { .fn.chunk = chunk,
.fn_user_data = read_user_data,
- .callback = callback,
+ .completion = completion,
.user_data = callback_user_data, };
if ((flags & ~LIBNBD_CMD_FLAG_DF) != 0) {
@@ -326,10 +329,11 @@ nbd_unlocked_aio_pwrite (struct nbd_handle *h, const void *buf,
int64_t
nbd_unlocked_aio_pwrite_callback (struct nbd_handle *h, const void *buf,
size_t count, uint64_t offset,
- callback_fn callback, void *user_data,
+ nbd_completion_callback completion,
+ void *user_data,
uint32_t flags)
{
- struct command_cb cb = { .callback = callback, .user_data = user_data, };
+ struct command_cb cb = { .completion = completion, .user_data = user_data, };
if (nbd_unlocked_read_only (h) == 1) {
set_error (EINVAL, "server does not support write operations");
@@ -358,10 +362,12 @@ nbd_unlocked_aio_flush (struct nbd_handle *h, uint32_t flags)
}
int64_t
-nbd_unlocked_aio_flush_callback (struct nbd_handle *h, callback_fn callback,
- void *user_data, uint32_t flags)
+nbd_unlocked_aio_flush_callback (struct nbd_handle *h,
+ nbd_completion_callback completion,
+ void *user_data,
+ uint32_t flags)
{
- struct command_cb cb = { .callback = callback, .user_data = user_data, };
+ struct command_cb cb = { .completion = completion, .user_data = user_data, };
if (nbd_unlocked_can_flush (h) != 1) {
set_error (EINVAL, "server does not support flush operations");
@@ -388,10 +394,11 @@ nbd_unlocked_aio_trim (struct nbd_handle *h,
int64_t
nbd_unlocked_aio_trim_callback (struct nbd_handle *h,
uint64_t count, uint64_t offset,
- callback_fn callback, void *user_data,
+ nbd_completion_callback completion,
+ void *user_data,
uint32_t flags)
{
- struct command_cb cb = { .callback = callback, .user_data = user_data, };
+ struct command_cb cb = { .completion = completion, .user_data = user_data, };
if (nbd_unlocked_read_only (h) == 1) {
set_error (EINVAL, "server does not support write operations");
@@ -428,10 +435,11 @@ nbd_unlocked_aio_cache (struct nbd_handle *h,
int64_t
nbd_unlocked_aio_cache_callback (struct nbd_handle *h,
uint64_t count, uint64_t offset,
- callback_fn callback, void *user_data,
+ nbd_completion_callback completion,
+ void *user_data,
uint32_t flags)
{
- struct command_cb cb = { .callback = callback, .user_data = user_data, };
+ struct command_cb cb = { .completion = completion, .user_data = user_data, };
/* Actually according to the NBD protocol document, servers do exist
* that support NBD_CMD_CACHE but don't advertise the
@@ -462,10 +470,11 @@ nbd_unlocked_aio_zero (struct nbd_handle *h,
int64_t
nbd_unlocked_aio_zero_callback (struct nbd_handle *h,
uint64_t count, uint64_t offset,
- callback_fn callback, void *user_data,
+ nbd_completion_callback completion,
+ void *user_data,
uint32_t flags)
{
- struct command_cb cb = { .callback = callback, .user_data = user_data, };
+ struct command_cb cb = { .completion = completion, .user_data = user_data, };
if (nbd_unlocked_read_only (h) == 1) {
set_error (EINVAL, "server does not support write operations");
@@ -495,7 +504,7 @@ nbd_unlocked_aio_zero_callback (struct nbd_handle *h,
int64_t
nbd_unlocked_aio_block_status (struct nbd_handle *h,
uint64_t count, uint64_t offset,
- extent_fn extent, void *user_data,
+ nbd_extent_callback extent, void *user_data,
uint32_t flags)
{
return nbd_unlocked_aio_block_status_callback (h, count, offset,
@@ -507,15 +516,15 @@ nbd_unlocked_aio_block_status (struct nbd_handle *h,
int64_t
nbd_unlocked_aio_block_status_callback (struct nbd_handle *h,
uint64_t count, uint64_t offset,
- extent_fn extent,
+ nbd_extent_callback extent,
void *extent_user_data,
- callback_fn callback,
+ nbd_completion_callback completion,
void *callback_user_data,
uint32_t flags)
{
struct command_cb cb = { .fn.extent = extent,
.fn_user_data = extent_user_data,
- .callback = callback,
+ .completion = completion,
.user_data = callback_user_data };
if (!h->structured_replies) {
--
2.22.0

View File

@ -0,0 +1,29 @@
From 6a4724eba9685ee56ba0509b033b83670edd5328 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 3 Aug 2019 15:07:07 +0100
Subject: [PATCH 08/11] generator: Remove some extraneous blank lines from
generated libnbd.h file.
---
generator/generator | 2 --
1 file changed, 2 deletions(-)
diff --git a/generator/generator b/generator/generator
index 6f89792..4de79ca 100755
--- a/generator/generator
+++ b/generator/generator
@@ -3417,11 +3417,9 @@ let generate_include_libnbd_h () =
List.iter (
fun (name, { args; ret }) -> print_extern_and_define name args ret
) handle_calls;
- pr "\n";
List.iter (
fun (ns, ctxts) -> print_ns ns ctxts
) metadata_namespaces;
- pr "\n";
pr "#ifdef __cplusplus\n";
pr "}\n";
pr "#endif\n";
--
2.22.0

View File

@ -0,0 +1,33 @@
From aa44163862c33cd261403ae2b875918582c872ce Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 3 Aug 2019 15:09:15 +0100
Subject: [PATCH 09/11] generator: Add link to documentation in <libnbd.h>
We do the same sort of thing in libguestfs. It helps people to find
the documentation if their first contact with the library is through
seeing the header file.
---
generator/generator | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/generator/generator b/generator/generator
index 4de79ca..25aeb00 100755
--- a/generator/generator
+++ b/generator/generator
@@ -3386,6 +3386,13 @@ let generate_include_libnbd_h () =
pr "#ifndef LIBNBD_H\n";
pr "#define LIBNBD_H\n";
pr "\n";
+ pr "/* This is the public interface to libnbd, a client library for\n";
+ pr " * accessing Network Block Device (NBD) servers.\n";
+ pr " *\n";
+ pr " * Please read the libnbd(3) and libnbd-api(3) manual pages to\n";
+ pr " * find out how to use this library.\n";
+ pr " */\n";
+ pr "\n";
pr "#include <stdbool.h>\n";
pr "#include <stdint.h>\n";
pr "#include <sys/socket.h>\n";
--
2.22.0

View File

@ -0,0 +1,50 @@
From c05f1005c2629237843db9c0830ba40d08b5516e Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 3 Aug 2019 15:17:53 +0100
Subject: [PATCH 10/11] build: Add ./configure --disable-ocaml to disable OCaml
bindings.
This can be used to disable the OCaml language bindings if you don't
want to build those. The OCaml toplevel is still needed to run the
generator, in particular in the case where you want to build from git.
---
configure.ac | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac
index 8c47e61..ade8ab0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -197,10 +197,6 @@ dnl bindings.
AC_PROG_OCAML
AC_PROG_FINDLIB
AM_CONDITIONAL([HAVE_OCAML_TOPLEVEL],[test "x$OCAML" != "xno"])
-AM_CONDITIONAL([HAVE_OCAML],
- [test "x$OCAMLC" != "xno" && test "x$OCAMLFIND" != "xno"])
-AM_CONDITIONAL([HAVE_OCAMLOPT],
- [test "x$OCAMLOPT" != "xno" && test "x$OCAMLFIND" != "xno"])
dnl Flags we want to pass to every OCaml compiler call.
OCAML_WARN_ERROR="-warn-error CDEFLMPSUVYZX+52-3"
@@ -208,6 +204,18 @@ AC_SUBST([OCAML_WARN_ERROR])
OCAML_FLAGS="-g -annot -safe-string"
AC_SUBST([OCAML_FLAGS])
+dnl Note this only disables the OCaml bindings.
+AC_ARG_ENABLE([ocaml],
+ AS_HELP_STRING([--disable-ocaml], [disable OCaml language bindings]),
+ [],
+ [enable_ocaml=yes])
+AM_CONDITIONAL([HAVE_OCAML],
+ [test "x$OCAMLC" != "xno" && test "x$OCAMLFIND" != "xno" && \
+ test "x$enable_ocaml" = "xyes"])
+AM_CONDITIONAL([HAVE_OCAMLOPT],
+ [test "x$OCAMLOPT" != "xno" && test "x$OCAMLFIND" != "xno" && \
+ test "x$enable_ocaml" = "xyes"])
+
dnl Python, optional for the Python bindings and shell.
PYTHON_PREFIX=
PYTHON_VERSION=
--
2.22.0

View File

@ -0,0 +1,42 @@
From aa54c46d5fdd9a68ae2237713d5086ecb91235f9 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 3 Aug 2019 15:20:50 +0100
Subject: [PATCH 11/11] ocaml: Add make install rule.
This installs the OCaml bindings into $(DESTDIR). If you don't want
this then use ./configure --disable-ocaml.
---
ocaml/Makefile.am | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/ocaml/Makefile.am b/ocaml/Makefile.am
index bae9e58..c69b5bd 100644
--- a/ocaml/Makefile.am
+++ b/ocaml/Makefile.am
@@ -103,4 +103,23 @@ endif
$(OCAMLFIND) ocamldep $^ > $@
-include .depend
+# Run ocamlfind to perform the install. ocamlfind refuses to install
+# the package if it is already installed, so remove the old package
+# first.
+data_hook_files = META *.so *.a *.cma *.cmi $(srcdir)/*.mli
+if HAVE_OCAMLOPT
+data_hook_files += *.cmx *.cmxa
+endif
+
+install-data-hook:
+ mkdir -p $(DESTDIR)$(OCAMLLIB)
+ mkdir -p $(DESTDIR)$(OCAMLLIB)/stublibs
+ rm -rf $(DESTDIR)$(OCAMLLIB)/nbd
+ rm -rf $(DESTDIR)$(OCAMLLIB)/stublibs/dllmlnbd.so*
+ $(OCAMLFIND) install \
+ -ldconf ignore -destdir $(DESTDIR)$(OCAMLLIB) \
+ nbd \
+ $(data_hook_files)
+ rm $(DESTDIR)$(OCAMLLIB)/nbd/libnbdocaml.a
+
endif HAVE_OCAML
--
2.22.0

View File

@ -2,14 +2,14 @@
%global verify_tarball_signature 1
# If there are patches which touch autotools files, set this to 1.
%global patches_touch_autotools %{nil}
%global patches_touch_autotools 1
# The source directory.
%global source_directory 0.x-unstable-api
Name: libnbd
Version: 0.9.6
Release: 1%{?dist}
Release: 2%{?dist}
Summary: NBD client library in userspace
License: LGPLv2+
@ -23,7 +23,17 @@ Source1: http://libguestfs.org/download/libnbd/%{source_directory}/%{name
Source2: libguestfs.keyring
# Patches.
# (none)
Patch0001: 0001-TODO-Mark-some-items-done.patch
Patch0002: 0002-tests-Make-sure-errors-test-uses-serialized-nbdkit.patch
Patch0003: 0003-tests-Add-some-basic-compile-tests-inspired-by-nbdki.patch
Patch0004: 0004-Fix-compilation-with-C.patch
Patch0005: 0005-run-Set-MALLOC_CHECK_-1-when-using-.-run-or-running-.patch
Patch0006: 0006-include-Remove-unused-definition-of-nbd_close_callba.patch
Patch0007: 0007-generator-Generate-typedefs-automatically-for-Closur.patch
Patch0008: 0008-generator-Remove-some-extraneous-blank-lines-from-ge.patch
Patch0009: 0009-generator-Add-link-to-documentation-in-libnbd.h.patch
Patch0010: 0010-build-Add-.-configure-disable-ocaml-to-disable-OCaml.patch
Patch0011: 0011-ocaml-Add-make-install-rule.patch
%if 0%{patches_touch_autotools}
BuildRequires: autoconf, automake, libtool
@ -33,17 +43,25 @@ BuildRequires: autoconf, automake, libtool
BuildRequires: gnupg2
%endif
# For the core library.
BuildRequires: gcc
BuildRequires: /usr/bin/pod2man
BuildRequires: gnutls-devel
BuildRequires: python3-devel
BuildRequires: libxml2-devel
# For the Python 3 bindings.
BuildRequires: python3-devel
# For the OCaml bindings.
BuildRequires: ocaml
BuildRequires: ocaml-findlib-devel
# Only for running the test suite.
BuildRequires: gnutls-utils
BuildRequires: nbdkit
BuildRequires: nbd
BuildRequires: qemu-img
BuildRequires: gcc-c++
%description
@ -77,6 +95,26 @@ Requires: %{name}%{?_isa} = %{version}-%{release}
This package contains development headers for %{name}.
%package -n ocaml-%{name}
Summary: OCaml language bindings for %{name}
Requires: %{name}%{?_isa} = %{version}-%{release}
%description -n ocaml-%{name}
This package contains OCaml language bindings for %{name}.
%package -n ocaml-%{name}-devel
Summary: OCaml language development package for %{name}
Requires: ocaml-%{name}%{?_isa} = %{version}-%{release}
%description -n ocaml-%{name}-devel
This package contains OCaml language development package for
%{name}. Install this if you want to compile OCaml software which
uses %{name}.
%package -n python3-%{name}
Summary: Python 3 bindings for %{name}
Requires: %{name}%{?_isa} = %{version}-%{release}
@ -107,7 +145,8 @@ autoreconf -i
--disable-static \
--with-tls-priority=@LIBNBD,SYSTEM \
PYTHON=%{__python3} \
--enable-python
--enable-python \
--enable-ocaml
make %{?_smp_mflags}
@ -154,6 +193,26 @@ make %{?_smp_mflags} check || {
%{_mandir}/man3/libnbd-api.3*
%files -n ocaml-%{name}
%{_libdir}/ocaml/nbd
%exclude %{_libdir}/ocaml/nbd/*.a
%exclude %{_libdir}/ocaml/nbd/*.cmxa
%exclude %{_libdir}/ocaml/nbd/*.cmx
%exclude %{_libdir}/ocaml/nbd/*.mli
%{_libdir}/ocaml/stublibs/dllmlnbd.so
%{_libdir}/ocaml/stublibs/dllmlnbd.so.owner
%files -n ocaml-%{name}-devel
%doc ocaml/examples/*.ml
%license ocaml/examples/LICENSE-FOR-EXAMPLES
%{_libdir}/ocaml/nbd/*.a
%{_libdir}/ocaml/nbd/*.cmxa
%{_libdir}/ocaml/nbd/*.cmx
%{_libdir}/ocaml/nbd/*.mli
#%{_mandir}/man3/libnbd-ocaml.3*
%files -n python3-%{name}
%{python3_sitearch}/libnbdmod*.so
%{python3_sitearch}/nbd.py
@ -164,6 +223,10 @@ make %{?_smp_mflags} check || {
%changelog
* Sat Aug 3 2019 Richard W.M. Jones <rjones@redhat.com> - 0.9.6-2
- Add all upstream patches since 0.9.6 was released.
- Package the ocaml bindings into a subpackage.
* Tue Jul 30 2019 Richard W.M. Jones <rjones@redhat.com> - 0.9.6-1
- New upstream verison 0.9.6.