---
plugins/python/nbdkit-python-plugin.pod | 18 +++++++-
plugins/python/python.c | 58 +++++++++++++++++++++++++
2 files changed, 74 insertions(+), 2 deletions(-)
diff --git a/plugins/python/nbdkit-python-plugin.pod
b/plugins/python/nbdkit-python-plugin.pod
index 4ba4ad4..b6255f3 100644
--- a/plugins/python/nbdkit-python-plugin.pod
+++ b/plugins/python/nbdkit-python-plugin.pod
@@ -228,6 +228,22 @@ contents will be garbage collected.
def can_fast_zero(h):
# return a boolean
+=item C<can_fua>
+
+(Optional)
+
+ def can_fua(h):
+ # return nbdkit.FUA_NONE or nbdkit.FUA_EMULATE
+ # or nbdkit.FUA_NATIVE
+
+=item C<can_cache>
+
+(Optional)
+
+ def can_cache(h):
+ # return nbdkit.CACHE_NONE or nbdkit.CACHE_EMULATE
+ # or nbdkit.CACHE_NATIVE
+
=item C<pread>
(Required)
@@ -344,8 +360,6 @@ C<longname>,
C<description>,
C<config_help>,
C<magic_config_key>,
-C<can_fua>,
-C<can_cache>,
C<can_extents>,
C<extents>.
diff --git a/plugins/python/python.c b/plugins/python/python.c
index 9c32aad..c27f147 100644
--- a/plugins/python/python.c
+++ b/plugins/python/python.c
@@ -808,6 +808,62 @@ py_can_fast_zero (void *handle)
return boolean_callback (handle, "can_fast_zero", NULL);
}
+static int
+py_can_fua (void *handle)
+{
+ PyObject *obj = handle;
+ PyObject *fn;
+ PyObject *r;
+ int ret;
+
+ if (callback_defined ("can_fua", &fn)) {
+ PyErr_Clear ();
+
+ r = PyObject_CallFunctionObjArgs (fn, obj, NULL);
+ Py_DECREF (fn);
+ if (check_python_failure ("can_fua") == -1)
+ return -1;
+ ret = PyLong_AsLong (r);
+ Py_DECREF (r);
+ return ret;
+ }
+ /* No Python ‘can_fua’, but check if there's a Python ‘flush’
+ * callback defined. (In C modules, nbdkit would do this).
+ */
+ else if (callback_defined ("flush", NULL))
+ return NBDKIT_FUA_EMULATE;
+ else
+ return NBDKIT_FUA_NONE;
+}
+
+static int
+py_can_cache (void *handle)
+{
+ PyObject *obj = handle;
+ PyObject *fn;
+ PyObject *r;
+ int ret;
+
+ if (callback_defined ("can_cache", &fn)) {
+ PyErr_Clear ();
+
+ r = PyObject_CallFunctionObjArgs (fn, obj, NULL);
+ Py_DECREF (fn);
+ if (check_python_failure ("can_cache") == -1)
+ return -1;
+ ret = PyLong_AsLong (r);
+ Py_DECREF (r);
+ return ret;
+ }
+ /* No Python ‘can_cache’, but check if there's a Python ‘cache’
+ * callback defined. (In C modules, nbdkit would do this).
+ */
+ else if (callback_defined ("cache", NULL))
+ return NBDKIT_CACHE_NATIVE;
+ else
+ return NBDKIT_CACHE_NONE;
+}
+
#define py_config_help \
"script=<FILENAME> (required) The Python plugin to run.\n" \
"[other arguments may be used by the plugin that you load]"
@@ -837,6 +893,8 @@ static struct nbdkit_plugin plugin = {
.can_trim = py_can_trim,
.can_zero = py_can_zero,
.can_fast_zero = py_can_fast_zero,
+ .can_fua = py_can_fua,
+ .can_cache = py_can_cache,
.pread = py_pread,
.pwrite = py_pwrite,
--
2.23.0