On 03/08/2018 05:03 PM, Eric Blake wrote: > The NBD protocol supports Forced Unit Access (FUA) as a more efficient > way to wait for just one write to land in persistent storage, rather > than all outstanding writes at the time of a flush; modeled after > the kernel's block I/O flag of the same name. While we can emulate > the proper semantics with a full-blown flush, there are some plugins > that can properly pass the FUA flag on to the end storage and thereby > avoid some overhead. > > This patch introduces new callbacks, and updates the documentation > to the new API, while ensuring that plugins compiled to the old API > still work. The new API adds .can_fua, then adds a flags parameter > to all five data callbacks, even though only three of them will use > a flag at the moment. A plugin client has to opt in to both the > version 2 API and provide .can_fua with a return of NBDKIT_FUA_NATIVE > before nbdkit will pass the NBDKIT_FLAG_FUA to the plugin. >
> > +=head2 C<.can_fua> > + > + int can_fua (void *handle); > + > +This is called during the option negotiation phase to find out if the > +plugin supports the Forced Unit Access (FUA) flag on write, zero, and > +trim requests. If this returns C<NBDKIT_FUA_NONE>, FUA support is not > +advertised to the guest; if this returns C<NBDKIT_FUA_EMULATE>, the > +C<.flush> callback must work (even if C<.can_flush> returns false), > +and FUA support is emulated by calling C<.flush> after any write > +operation; if this returns C<NBDKIT_FUA_NATIVE>, then the C<.pwrite>, > +C<.zero>, and C<.trim> callbacks (if implemented) must handle the flag > +C<NBDKIT_FLAG_FUA>, by not returning until that action has landed in > +persistent storage. > + > +If there is an error, C<.can_fua> should call C<nbdkit_error> with an > +error message and return C<-1>. > + > +This callback is not required unless a plugin wants to specifically > +handle FUA requests. If omitted, nbdkit checks C<.can_flush>, and > +behaves as if this function returns C<NBDKIT_FUA_NONE> or > +C<NBDKIT_FUA_EMULATE> as appropriate. That documentation doesn't quite match the code, although I prefer the documentation... > +++ b/src/plugins.c > @@ -377,14 +383,20 @@ plugin_can_fua (struct backend *b, struct connection > *conn) > struct backend_plugin *p = container_of (b, struct backend_plugin, > backend); > int r; > > + assert (connection_get_handle (conn, 0)); > + > debug ("can_fua"); > > - /* TODO - wire FUA flag support into plugins. Until then, this copies > - * can_flush, since that's how we emulate FUA. */ > + if (p->plugin.can_fua) { > + r = p->plugin.can_fua (connection_get_handle (conn, 0)); > + if (r > NBDKIT_FUA_EMULATE && p->plugin._api_version == 1) > + r = NBDKIT_FUA_EMULATE; > + return r; > + } > r = plugin_can_flush (b, conn); > if (r == -1) > return -1; > - if (r == 0 || !p->plugin.flush) > + if (r == 0 || !(p->plugin.flush || p->plugin._flush_old)) > return NBDKIT_FUA_NONE; > return NBDKIT_FUA_EMULATE; According to the documentation, the result of .can_flush should have no impact on the return; we want to return NBDKIT_FUA_EMULATE if .flush exists, even when can_flush returns false. I'll be pushing this as followup: diff --git i/src/plugins.c w/src/plugins.c index ff4facf..8ee58fb 100644 --- i/src/plugins.c +++ w/src/plugins.c @@ -386,18 +386,18 @@ plugin_can_fua (struct backend *b, struct connection *conn) debug ("can_fua"); + /* The plugin MUST provide .can_fua with a return of NBDKIT_FUA_NATIVE + before we will pass FUA on to the plugin. */ if (p->plugin.can_fua) { r = p->plugin.can_fua (connection_get_handle (conn, 0)); if (r > NBDKIT_FUA_EMULATE && p->plugin._api_version == 1) r = NBDKIT_FUA_EMULATE; return r; } - r = plugin_can_flush (b, conn); - if (r == -1) - return -1; - if (r == 0 || !(p->plugin.flush || p->plugin._flush_old)) - return NBDKIT_FUA_NONE; - return NBDKIT_FUA_EMULATE; + /* We intend to call .flush even if .can_flush returns false */ + if (p->plugin.flush || p->plugin._flush_old) + return NBDKIT_FUA_EMULATE; + return NBDKIT_FUA_NONE; } /* Grab the appropriate error value. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://www.redhat.com/mailman/listinfo/libguestfs