I had an idea about how we might do this and still keep a single
.pwrite method for plugins. Maybe it's too complicated but here goes:
(1) Rename the pwrite method as pwrite_old1, and add new pwrite method
with either the FUA flag or general flags:
int (*pread) (void *handle, void *buf, uint32_t count, uint64_t offset);
- int (*pwrite) (void *handle, const void *buf, uint32_t count, uint64_t offset);
+ int (*pwrite_old1) (void *handle, const void *buf, uint32_t count, uint64_t offset);
int (*flush) (void *handle);
int (*trim) (void *handle, uint32_t count, uint64_t offset);
int (*zero) (void *handle, uint32_t count, uint64_t offset, int may_trim);
int errno_is_preserved;
void (*dump_plugin) (void);
+ int (*pwrite) (void *handle, const void *buf, uint32_t count, uint64_t offset, unsigned
flags);
This is binary-compatible with old plugins, but not source compatible, so:
(2) Plugsin may optionally define NBDKIT_PLUGIN_LEVEL before including
<nbdkit-plugin.h>. Code wishing to use the flags variant of pwrite
can do:
#define NBDKIT_PLUGIN_LEVEL 2
#include <nbdkit-plugin.h>
which would modify the definition of the struct (again), something
like:
#ifndef NBDKIT_PLUGIN_LEVEL
#define NBDKIT_PLUGIN_LEVEL 1
#endif
...
int (*pread) (void *handle, void *buf, uint32_t count, uint64_t offset);
#if NBDKIT_PLUGIN_LEVEL <= 1
int (*pwrite) (void *handle, const void *buf, uint32_t count, uint64_t offset);
#else
int (*pwrite_old1) (void *handle, const void *buf, uint32_t count, uint64_t offset);
#endif
int (*flush) (void *handle);
int (*trim) (void *handle, uint32_t count, uint64_t offset);
int (*zero) (void *handle, uint32_t count, uint64_t offset, int may_trim);
int errno_is_preserved;
void (*dump_plugin) (void);
#if NBDKIT_PLUGIN_LEVEL <= 1
int (*never_used1) (void *handle, const void *buf, uint32_t count, uint64_t offset,
unsigned flags);
#else
int (*pwrite) (void *handle, const void *buf, uint32_t count, uint64_t offset, unsigned
flags);
#endif
(3) Core nbdkit code always defines NBDKIT_PLUGIN_LEVEL == 2 so that
it always sees the new function, but it may need to call the old
function:
int
plugin_pwrite (...)
{
if (plugin.pwrite != NULL)
plugin.pwrite (handle, buf, count, offset, flags);
else if (plugin.pwrite_old1 != NULL)
plugin.pwrite_old1 (handle, buf, count, offset);
}
(4) Internal plugins which don't need the FUA flag can continue to use
the level 1 API, which means that we keep checking that the old API
still works.
What do you think?
Rich.
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
Read my programming and virtualization blog:
http://rwmj.wordpress.com
virt-p2v converts physical machines to virtual machines. Boot with a
live CD or over the network (PXE) and turn machines into KVM guests.
http://libguestfs.org/virt-v2v