This is intended for use by the forthcoming retry filter to close and
reopen the backend chain. It is handled entirely by server/backend.c
as no cooperation is needed with the plugin.
Note the explicit readonly parameter: An alternative would be to store
the previous readonly setting in the b_conn_handle struct. However
passing it explicitly allows the retry filter to retry as readonly,
which might be useful. This design does however require any filter
which might call .reopen to save the original readonly parameter from
the .open call.
---
include/nbdkit-filter.h | 6 ++++++
server/backend.c | 12 ++++++++++++
server/filters.c | 8 ++++++++
server/internal.h | 4 ++++
4 files changed, 30 insertions(+)
diff --git a/include/nbdkit-filter.h b/include/nbdkit-filter.h
index babce0d..c1930c1 100644
--- a/include/nbdkit-filter.h
+++ b/include/nbdkit-filter.h
@@ -68,6 +68,12 @@ typedef int nbdkit_next_open (void *nxdata,
int readonly);
struct nbdkit_next_ops {
+ /* Performs close + open on the underlying chain.
+ * Used by the retry filter.
+ */
+ int (*reopen) (void *nxdata, int readonly);
+
+ /* The rest of the next ops are the same as normal plugin operations. */
int64_t (*get_size) (void *nxdata);
int (*can_write) (void *nxdata);
diff --git a/server/backend.c b/server/backend.c
index 6c102f9..52b1734 100644
--- a/server/backend.c
+++ b/server/backend.c
@@ -233,6 +233,18 @@ backend_valid_range (struct backend *b, struct connection *conn,
/* Wrappers for all callbacks in a filter's struct nbdkit_next_ops. */
+int
+backend_reopen (struct backend *b, struct connection *conn, int readonly)
+{
+ struct b_conn_handle *h = &conn->handles[b->i];
+
+ debug ("%s: reopen", b->name);
+
+ if (h->handle != NULL)
+ backend_close (b, conn);
+ return backend_open (b, conn, readonly);
+}
+
int64_t
backend_get_size (struct backend *b, struct connection *conn)
{
diff --git a/server/filters.c b/server/filters.c
index 1091c2d..78e32bc 100644
--- a/server/filters.c
+++ b/server/filters.c
@@ -237,6 +237,13 @@ filter_close (struct backend *b, struct connection *conn)
* single ‘void *nxdata’ struct pointer (‘b_conn’).
*/
+static int
+next_reopen (void *nxdata, int readonly)
+{
+ struct b_conn *b_conn = nxdata;
+ return backend_reopen (b_conn->b, b_conn->conn, readonly);
+}
+
static int64_t
next_get_size (void *nxdata)
{
@@ -373,6 +380,7 @@ next_cache (void *nxdata, uint32_t count, uint64_t offset,
}
static struct nbdkit_next_ops next_ops = {
+ .reopen = next_reopen,
.get_size = next_get_size,
.can_write = next_can_write,
.can_flush = next_can_flush,
diff --git a/server/internal.h b/server/internal.h
index a376d73..c58b020 100644
--- a/server/internal.h
+++ b/server/internal.h
@@ -307,6 +307,7 @@ struct backend {
int (*prepare) (struct backend *, struct connection *conn, int readonly);
int (*finalize) (struct backend *, struct connection *conn);
void (*close) (struct backend *, struct connection *conn);
+ int (*reopen) (struct backend *, struct connection *conn);
int64_t (*get_size) (struct backend *, struct connection *conn);
int (*can_write) (struct backend *, struct connection *conn);
@@ -360,6 +361,9 @@ extern bool backend_valid_range (struct backend *b, struct connection
*conn,
uint64_t offset, uint32_t count)
__attribute__((__nonnull__ (1, 2)));
+extern int backend_reopen (struct backend *b, struct connection *conn,
+ int readonly)
+ __attribute__((__nonnull__ (1, 2)));
extern int64_t backend_get_size (struct backend *b, struct connection *conn)
__attribute__((__nonnull__ (1, 2)));
extern int backend_can_write (struct backend *b, struct connection *conn)
--
2.23.0