Eric Blake
2019-May-25 18:10 UTC
[Libguestfs] [nbdkit PATCH] nbd: Rewrite thread passing to use semaphore rather than pipe
I ran some local testing on my Fedora 29 system via:
$ ./nbdkit memory 1m
$ for i in `seq 10`; do
./nbdkit -U - --filter=stats nbd \
statsappend=true statsfile=$file hostname=localhost port=10809 \
--run '~/libnbd/examples/threaded-reads-and-writes $unixsocket'
done
Pre-patch, the runs averaged 1.266s, 1.30E+08 bits/s
Post-patch, the runs averaged 1.154s, 1.42E+08 bits/s
This is roughly 9% performance gain, all because semaphores are
lighter weight than pipes for inter-thread locking. The refactoring
will also make it a bit easier to incorporate the use of libnbd.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
Sending this in case someone wants to review my work, but I was happy
enough with the benchmark numbers to go ahead and push this one.
plugins/nbd/nbd.c | 134 +++++++++++++++++++++++-----------------------
1 file changed, 67 insertions(+), 67 deletions(-)
diff --git a/plugins/nbd/nbd.c b/plugins/nbd/nbd.c
index 9039e1b..b2f3446 100644
--- a/plugins/nbd/nbd.c
+++ b/plugins/nbd/nbd.c
@@ -48,6 +48,7 @@
#include <sys/un.h>
#include <assert.h>
#include <pthread.h>
+#include <semaphore.h>
#define NBDKIT_API_VERSION 2
@@ -155,10 +156,8 @@ nbd_config_complete (void)
/* The per-transaction details */
struct transaction {
- union {
- uint64_t cookie;
- int fds[2];
- } u;
+ uint64_t cookie;
+ sem_t sem;
void *buf;
uint64_t offset;
uint32_t count;
@@ -182,6 +181,7 @@ struct handle {
pthread_mutex_t trans_lock; /* Covers access to all fields below */
struct transaction *trans;
+ uint64_t unique;
bool dead;
};
@@ -264,7 +264,7 @@ find_trans_by_cookie (struct handle *h, uint64_t cookie,
bool remove)
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&h->trans_lock);
ptr = &h->trans;
while ((trans = *ptr) != NULL) {
- if (cookie == trans->u.cookie)
+ if (cookie == trans->cookie)
break;
ptr = &trans->next;
}
@@ -300,28 +300,27 @@ nbd_request_raw (struct handle *h, uint16_t flags,
uint16_t type,
}
/* Perform the request half of a transaction. On success, return the
- non-negative fd for reading the reply; on error return -1. */
-static int
+ transaction; on error return NULL. */
+static struct transaction *
nbd_request_full (struct handle *h, uint16_t flags, uint16_t type,
uint64_t offset, uint32_t count, const void *req_buf,
void *rep_buf, struct nbdkit_extents *extents)
{
int err;
struct transaction *trans;
- int fd;
uint64_t cookie;
trans = calloc (1, sizeof *trans);
if (!trans) {
nbdkit_error ("unable to track transaction: %m");
/* Still in sync with server, so don't mark connection dead */
- return -1;
+ return NULL;
}
- if (pipe (trans->u.fds)) {
- nbdkit_error ("unable to create pipe: %m");
+ if (sem_init (&trans->sem, 0, 0)) {
+ nbdkit_error ("unable to create semaphore: %m");
/* Still in sync with server, so don't mark connection dead */
free (trans);
- return -1;
+ return NULL;
}
trans->buf = rep_buf;
trans->count = rep_buf ? count : 0;
@@ -331,43 +330,39 @@ nbd_request_full (struct handle *h, uint16_t flags,
uint16_t type,
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&h->trans_lock);
if (h->dead)
goto err;
+ cookie = trans->cookie = h->unique++;
trans->next = h->trans;
h->trans = trans;
- fd = trans->u.fds[0];
- cookie = trans->u.cookie;
}
if (nbd_request_raw (h, flags, type, offset, count, cookie, req_buf) == 0)
- return fd;
+ return trans;
trans = find_trans_by_cookie (h, cookie, true);
err:
err = errno;
- if (trans) {
- close (trans->u.fds[0]);
- close (trans->u.fds[1]);
- free (trans);
- }
- else
- close (fd);
+ if (sem_destroy (&trans->sem))
+ abort ();
+ free (trans);
+ nbd_mark_dead (h);
errno = err;
- return nbd_mark_dead (h);
+ return NULL;
}
/* Shorthand for nbd_request_full when no extra buffers are involved. */
-static int
+static struct transaction *
nbd_request (struct handle *h, uint16_t flags, uint16_t type, uint64_t offset,
uint32_t count)
{
return nbd_request_full (h, flags, type, offset, count, NULL, NULL, NULL);
}
-/* Read a reply, and look up the fd corresponding to the transaction.
+/* Read a reply, and look up the corresponding transaction.
Return the server's non-negative answer (converted to local errno
value) on success, or -1 on read failure. If structured replies
- were negotiated, fd is set to -1 if there are still more replies
+ were negotiated, trans_out is set to NULL if there are still more replies
expected. */
static int
-nbd_reply_raw (struct handle *h, int *fd)
+nbd_reply_raw (struct handle *h, struct transaction **trans_out)
{
union {
struct simple_reply simple;
@@ -387,7 +382,7 @@ nbd_reply_raw (struct handle *h, int *fd)
bool zero = false; /* if len, whether to read or memset */
uint16_t errlen;
- *fd = -1;
+ *trans_out = NULL;
/* magic and handle overlap between simple and structured replies */
if (read_full (h->fd, &rep, sizeof rep.simple))
return nbd_mark_dead (h);
@@ -573,10 +568,9 @@ nbd_reply_raw (struct handle *h, int *fd)
/* Thanks to structured replies, we must preserve an error in any
earlier chunk for replay during the final chunk. */
if (!more) {
- *fd = trans->u.fds[1];
+ *trans_out = trans;
if (!error)
error = trans->err;
- free (trans);
}
else if (error && !trans->err)
trans->err = error;
@@ -616,19 +610,20 @@ nbd_reader (void *handle)
int r;
while (!done) {
- int fd;
+ struct transaction *trans;
- r = nbd_reply_raw (h, &fd);
+ r = nbd_reply_raw (h, &trans);
if (r >= 0) {
- if (fd < 0)
+ if (!trans)
nbdkit_debug ("partial reply handled, waiting for final
reply");
- else if (write (fd, &r, sizeof r) != sizeof r) {
- nbdkit_error ("failed to write pipe: %m");
- abort ();
+ else {
+ trans->err = r;
+ if (sem_post (&trans->sem)) {
+ nbdkit_error ("failed to post semaphore: %m");
+ abort ();
+ }
}
}
- if (fd >= 0)
- close (fd);
ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&h->trans_lock);
done = h->dead;
}
@@ -645,27 +640,32 @@ nbd_reader (void *handle)
}
if (!trans)
break;
- if (write (trans->u.fds[1], &r, sizeof r) != sizeof r) {
- nbdkit_error ("failed to write pipe: %m");
+ trans->err = r;
+ if (sem_post (&trans->sem)) {
+ nbdkit_error ("failed to post semaphore: %m");
abort ();
}
- close (trans->u.fds[1]);
- free (trans);
}
return NULL;
}
/* Perform the reply half of a transaction. */
static int
-nbd_reply (struct handle *h, int fd)
+nbd_reply (struct handle *h, struct transaction *trans)
{
int err;
- if (read (fd, &err, sizeof err) != sizeof err) {
- nbdkit_debug ("failed to read pipe: %m");
+ while ((err = sem_wait (&trans->sem)) == -1 && errno == EINTR)
+ /* try again */;
+ if (err) {
+ nbdkit_debug ("failed to wait on semaphore: %m");
err = EIO;
}
- close (fd);
+ else
+ err = trans->err;
+ if (sem_destroy (&trans->sem))
+ abort ();
+ free (trans);
errno = err;
return err ? -1 : 0;
}
@@ -1175,11 +1175,11 @@ nbd_pread (void *handle, void *buf, uint32_t count,
uint64_t offset,
uint32_t flags)
{
struct handle *h = handle;
- int c;
+ struct transaction *s;
assert (!flags);
- c = nbd_request_full (h, 0, NBD_CMD_READ, offset, count, NULL, buf, NULL);
- return c < 0 ? c : nbd_reply (h, c);
+ s = nbd_request_full (h, 0, NBD_CMD_READ, offset, count, NULL, buf, NULL);
+ return s ? nbd_reply (h, s) : -1;
}
/* Write data to the file. */
@@ -1188,12 +1188,12 @@ nbd_pwrite (void *handle, const void *buf, uint32_t
count, uint64_t offset,
uint32_t flags)
{
struct handle *h = handle;
- int c;
+ struct transaction *s;
assert (!(flags & ~NBDKIT_FLAG_FUA));
- c = nbd_request_full (h, flags & NBDKIT_FLAG_FUA ? NBD_CMD_FLAG_FUA : 0,
+ s = nbd_request_full (h, flags & NBDKIT_FLAG_FUA ? NBD_CMD_FLAG_FUA : 0,
NBD_CMD_WRITE, offset, count, buf, NULL, NULL);
- return c < 0 ? c : nbd_reply (h, c);
+ return s ? nbd_reply (h, s) : -1;
}
/* Write zeroes to the file. */
@@ -1201,7 +1201,7 @@ static int
nbd_zero (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
{
struct handle *h = handle;
- int c;
+ struct transaction *s;
int f = 0;
assert (!(flags & ~(NBDKIT_FLAG_FUA | NBDKIT_FLAG_MAY_TRIM)));
@@ -1211,8 +1211,8 @@ nbd_zero (void *handle, uint32_t count, uint64_t offset,
uint32_t flags)
f |= NBD_CMD_FLAG_NO_HOLE;
if (flags & NBDKIT_FLAG_FUA)
f |= NBD_CMD_FLAG_FUA;
- c = nbd_request (h, f, NBD_CMD_WRITE_ZEROES, offset, count);
- return c < 0 ? c : nbd_reply (h, c);
+ s = nbd_request (h, f, NBD_CMD_WRITE_ZEROES, offset, count);
+ return s ? nbd_reply (h, s) : -1;
}
/* Trim a portion of the file. */
@@ -1220,12 +1220,12 @@ static int
nbd_trim (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
{
struct handle *h = handle;
- int c;
+ struct transaction *s;
assert (!(flags & ~NBDKIT_FLAG_FUA));
- c = nbd_request (h, flags & NBDKIT_FLAG_FUA ? NBD_CMD_FLAG_FUA : 0,
+ s = nbd_request (h, flags & NBDKIT_FLAG_FUA ? NBD_CMD_FLAG_FUA : 0,
NBD_CMD_TRIM, offset, count);
- return c < 0 ? c : nbd_reply (h, c);
+ return s ? nbd_reply (h, s) : -1;
}
/* Flush the file to disk. */
@@ -1233,11 +1233,11 @@ static int
nbd_flush (void *handle, uint32_t flags)
{
struct handle *h = handle;
- int c;
+ struct transaction *s;
assert (!flags);
- c = nbd_request (h, 0, NBD_CMD_FLUSH, 0, 0);
- return c < 0 ? c : nbd_reply (h, c);
+ s = nbd_request (h, 0, NBD_CMD_FLUSH, 0, 0);
+ return s ? nbd_reply (h, s) : -1;
}
/* Read extents of the file. */
@@ -1246,13 +1246,13 @@ nbd_extents (void *handle, uint32_t count, uint64_t
offset,
uint32_t flags, struct nbdkit_extents *extents)
{
struct handle *h = handle;
- int c;
+ struct transaction *s;
assert (!(flags & ~NBDKIT_FLAG_REQ_ONE) && h->extents);
- c = nbd_request_full (h, flags & NBDKIT_FLAG_REQ_ONE ?
NBD_CMD_FLAG_REQ_ONE : 0,
+ s = nbd_request_full (h, flags & NBDKIT_FLAG_REQ_ONE ?
NBD_CMD_FLAG_REQ_ONE : 0,
NBD_CMD_BLOCK_STATUS, offset, count, NULL, NULL,
extents);
- return c < 0 ? c : nbd_reply (h, c);
+ return s ? nbd_reply (h, s) : -1;
}
/* Cache a portion of the file. */
@@ -1260,11 +1260,11 @@ static int
nbd_cache (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
{
struct handle *h = handle;
- int c;
+ struct transaction *s;
assert (!flags);
- c = nbd_request (h, 0, NBD_CMD_CACHE, offset, count);
- return c < 0 ? c : nbd_reply (h, c);
+ s = nbd_request (h, 0, NBD_CMD_CACHE, offset, count);
+ return s ? nbd_reply (h, s) : -1;
}
static struct nbdkit_plugin plugin = {
--
2.20.1
Richard W.M. Jones
2019-May-25 18:15 UTC
Re: [Libguestfs] [nbdkit PATCH] nbd: Rewrite thread passing to use semaphore rather than pipe
On Sat, May 25, 2019 at 01:10:15PM -0500, Eric Blake wrote:> I ran some local testing on my Fedora 29 system via: > $ ./nbdkit memory 1m > $ for i in `seq 10`; do > ./nbdkit -U - --filter=stats nbd \ > statsappend=true statsfile=$file hostname=localhost port=10809 \ > --run '~/libnbd/examples/threaded-reads-and-writes $unixsocket' > done > > Pre-patch, the runs averaged 1.266s, 1.30E+08 bits/s > Post-patch, the runs averaged 1.154s, 1.42E+08 bits/s > > This is roughly 9% performance gain, all because semaphores are > lighter weight than pipes for inter-thread locking. The refactoring > will also make it a bit easier to incorporate the use of libnbd. > > Signed-off-by: Eric Blake <eblake@redhat.com> > --- > > Sending this in case someone wants to review my work, but I was happy > enough with the benchmark numbers to go ahead and push this one.Yup, seems fine. I was concerned this call might not have been available in FreeBSD, but it is so that's OK. Thanks, Rich.> plugins/nbd/nbd.c | 134 +++++++++++++++++++++++----------------------- > 1 file changed, 67 insertions(+), 67 deletions(-) > > diff --git a/plugins/nbd/nbd.c b/plugins/nbd/nbd.c > index 9039e1b..b2f3446 100644 > --- a/plugins/nbd/nbd.c > +++ b/plugins/nbd/nbd.c > @@ -48,6 +48,7 @@ > #include <sys/un.h> > #include <assert.h> > #include <pthread.h> > +#include <semaphore.h> > > #define NBDKIT_API_VERSION 2 > > @@ -155,10 +156,8 @@ nbd_config_complete (void) > > /* The per-transaction details */ > struct transaction { > - union { > - uint64_t cookie; > - int fds[2]; > - } u; > + uint64_t cookie; > + sem_t sem; > void *buf; > uint64_t offset; > uint32_t count; > @@ -182,6 +181,7 @@ struct handle { > > pthread_mutex_t trans_lock; /* Covers access to all fields below */ > struct transaction *trans; > + uint64_t unique; > bool dead; > }; > > @@ -264,7 +264,7 @@ find_trans_by_cookie (struct handle *h, uint64_t cookie, bool remove) > ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&h->trans_lock); > ptr = &h->trans; > while ((trans = *ptr) != NULL) { > - if (cookie == trans->u.cookie) > + if (cookie == trans->cookie) > break; > ptr = &trans->next; > } > @@ -300,28 +300,27 @@ nbd_request_raw (struct handle *h, uint16_t flags, uint16_t type, > } > > /* Perform the request half of a transaction. On success, return the > - non-negative fd for reading the reply; on error return -1. */ > -static int > + transaction; on error return NULL. */ > +static struct transaction * > nbd_request_full (struct handle *h, uint16_t flags, uint16_t type, > uint64_t offset, uint32_t count, const void *req_buf, > void *rep_buf, struct nbdkit_extents *extents) > { > int err; > struct transaction *trans; > - int fd; > uint64_t cookie; > > trans = calloc (1, sizeof *trans); > if (!trans) { > nbdkit_error ("unable to track transaction: %m"); > /* Still in sync with server, so don't mark connection dead */ > - return -1; > + return NULL; > } > - if (pipe (trans->u.fds)) { > - nbdkit_error ("unable to create pipe: %m"); > + if (sem_init (&trans->sem, 0, 0)) { > + nbdkit_error ("unable to create semaphore: %m"); > /* Still in sync with server, so don't mark connection dead */ > free (trans); > - return -1; > + return NULL; > } > trans->buf = rep_buf; > trans->count = rep_buf ? count : 0; > @@ -331,43 +330,39 @@ nbd_request_full (struct handle *h, uint16_t flags, uint16_t type, > ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&h->trans_lock); > if (h->dead) > goto err; > + cookie = trans->cookie = h->unique++; > trans->next = h->trans; > h->trans = trans; > - fd = trans->u.fds[0]; > - cookie = trans->u.cookie; > } > if (nbd_request_raw (h, flags, type, offset, count, cookie, req_buf) == 0) > - return fd; > + return trans; > trans = find_trans_by_cookie (h, cookie, true); > > err: > err = errno; > - if (trans) { > - close (trans->u.fds[0]); > - close (trans->u.fds[1]); > - free (trans); > - } > - else > - close (fd); > + if (sem_destroy (&trans->sem)) > + abort (); > + free (trans); > + nbd_mark_dead (h); > errno = err; > - return nbd_mark_dead (h); > + return NULL; > } > > /* Shorthand for nbd_request_full when no extra buffers are involved. */ > -static int > +static struct transaction * > nbd_request (struct handle *h, uint16_t flags, uint16_t type, uint64_t offset, > uint32_t count) > { > return nbd_request_full (h, flags, type, offset, count, NULL, NULL, NULL); > } > > -/* Read a reply, and look up the fd corresponding to the transaction. > +/* Read a reply, and look up the corresponding transaction. > Return the server's non-negative answer (converted to local errno > value) on success, or -1 on read failure. If structured replies > - were negotiated, fd is set to -1 if there are still more replies > + were negotiated, trans_out is set to NULL if there are still more replies > expected. */ > static int > -nbd_reply_raw (struct handle *h, int *fd) > +nbd_reply_raw (struct handle *h, struct transaction **trans_out) > { > union { > struct simple_reply simple; > @@ -387,7 +382,7 @@ nbd_reply_raw (struct handle *h, int *fd) > bool zero = false; /* if len, whether to read or memset */ > uint16_t errlen; > > - *fd = -1; > + *trans_out = NULL; > /* magic and handle overlap between simple and structured replies */ > if (read_full (h->fd, &rep, sizeof rep.simple)) > return nbd_mark_dead (h); > @@ -573,10 +568,9 @@ nbd_reply_raw (struct handle *h, int *fd) > /* Thanks to structured replies, we must preserve an error in any > earlier chunk for replay during the final chunk. */ > if (!more) { > - *fd = trans->u.fds[1]; > + *trans_out = trans; > if (!error) > error = trans->err; > - free (trans); > } > else if (error && !trans->err) > trans->err = error; > @@ -616,19 +610,20 @@ nbd_reader (void *handle) > int r; > > while (!done) { > - int fd; > + struct transaction *trans; > > - r = nbd_reply_raw (h, &fd); > + r = nbd_reply_raw (h, &trans); > if (r >= 0) { > - if (fd < 0) > + if (!trans) > nbdkit_debug ("partial reply handled, waiting for final reply"); > - else if (write (fd, &r, sizeof r) != sizeof r) { > - nbdkit_error ("failed to write pipe: %m"); > - abort (); > + else { > + trans->err = r; > + if (sem_post (&trans->sem)) { > + nbdkit_error ("failed to post semaphore: %m"); > + abort (); > + } > } > } > - if (fd >= 0) > - close (fd); > ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&h->trans_lock); > done = h->dead; > } > @@ -645,27 +640,32 @@ nbd_reader (void *handle) > } > if (!trans) > break; > - if (write (trans->u.fds[1], &r, sizeof r) != sizeof r) { > - nbdkit_error ("failed to write pipe: %m"); > + trans->err = r; > + if (sem_post (&trans->sem)) { > + nbdkit_error ("failed to post semaphore: %m"); > abort (); > } > - close (trans->u.fds[1]); > - free (trans); > } > return NULL; > } > > /* Perform the reply half of a transaction. */ > static int > -nbd_reply (struct handle *h, int fd) > +nbd_reply (struct handle *h, struct transaction *trans) > { > int err; > > - if (read (fd, &err, sizeof err) != sizeof err) { > - nbdkit_debug ("failed to read pipe: %m"); > + while ((err = sem_wait (&trans->sem)) == -1 && errno == EINTR) > + /* try again */; > + if (err) { > + nbdkit_debug ("failed to wait on semaphore: %m"); > err = EIO; > } > - close (fd); > + else > + err = trans->err; > + if (sem_destroy (&trans->sem)) > + abort (); > + free (trans); > errno = err; > return err ? -1 : 0; > } > @@ -1175,11 +1175,11 @@ nbd_pread (void *handle, void *buf, uint32_t count, uint64_t offset, > uint32_t flags) > { > struct handle *h = handle; > - int c; > + struct transaction *s; > > assert (!flags); > - c = nbd_request_full (h, 0, NBD_CMD_READ, offset, count, NULL, buf, NULL); > - return c < 0 ? c : nbd_reply (h, c); > + s = nbd_request_full (h, 0, NBD_CMD_READ, offset, count, NULL, buf, NULL); > + return s ? nbd_reply (h, s) : -1; > } > > /* Write data to the file. */ > @@ -1188,12 +1188,12 @@ nbd_pwrite (void *handle, const void *buf, uint32_t count, uint64_t offset, > uint32_t flags) > { > struct handle *h = handle; > - int c; > + struct transaction *s; > > assert (!(flags & ~NBDKIT_FLAG_FUA)); > - c = nbd_request_full (h, flags & NBDKIT_FLAG_FUA ? NBD_CMD_FLAG_FUA : 0, > + s = nbd_request_full (h, flags & NBDKIT_FLAG_FUA ? NBD_CMD_FLAG_FUA : 0, > NBD_CMD_WRITE, offset, count, buf, NULL, NULL); > - return c < 0 ? c : nbd_reply (h, c); > + return s ? nbd_reply (h, s) : -1; > } > > /* Write zeroes to the file. */ > @@ -1201,7 +1201,7 @@ static int > nbd_zero (void *handle, uint32_t count, uint64_t offset, uint32_t flags) > { > struct handle *h = handle; > - int c; > + struct transaction *s; > int f = 0; > > assert (!(flags & ~(NBDKIT_FLAG_FUA | NBDKIT_FLAG_MAY_TRIM))); > @@ -1211,8 +1211,8 @@ nbd_zero (void *handle, uint32_t count, uint64_t offset, uint32_t flags) > f |= NBD_CMD_FLAG_NO_HOLE; > if (flags & NBDKIT_FLAG_FUA) > f |= NBD_CMD_FLAG_FUA; > - c = nbd_request (h, f, NBD_CMD_WRITE_ZEROES, offset, count); > - return c < 0 ? c : nbd_reply (h, c); > + s = nbd_request (h, f, NBD_CMD_WRITE_ZEROES, offset, count); > + return s ? nbd_reply (h, s) : -1; > } > > /* Trim a portion of the file. */ > @@ -1220,12 +1220,12 @@ static int > nbd_trim (void *handle, uint32_t count, uint64_t offset, uint32_t flags) > { > struct handle *h = handle; > - int c; > + struct transaction *s; > > assert (!(flags & ~NBDKIT_FLAG_FUA)); > - c = nbd_request (h, flags & NBDKIT_FLAG_FUA ? NBD_CMD_FLAG_FUA : 0, > + s = nbd_request (h, flags & NBDKIT_FLAG_FUA ? NBD_CMD_FLAG_FUA : 0, > NBD_CMD_TRIM, offset, count); > - return c < 0 ? c : nbd_reply (h, c); > + return s ? nbd_reply (h, s) : -1; > } > > /* Flush the file to disk. */ > @@ -1233,11 +1233,11 @@ static int > nbd_flush (void *handle, uint32_t flags) > { > struct handle *h = handle; > - int c; > + struct transaction *s; > > assert (!flags); > - c = nbd_request (h, 0, NBD_CMD_FLUSH, 0, 0); > - return c < 0 ? c : nbd_reply (h, c); > + s = nbd_request (h, 0, NBD_CMD_FLUSH, 0, 0); > + return s ? nbd_reply (h, s) : -1; > } > > /* Read extents of the file. */ > @@ -1246,13 +1246,13 @@ nbd_extents (void *handle, uint32_t count, uint64_t offset, > uint32_t flags, struct nbdkit_extents *extents) > { > struct handle *h = handle; > - int c; > + struct transaction *s; > > assert (!(flags & ~NBDKIT_FLAG_REQ_ONE) && h->extents); > - c = nbd_request_full (h, flags & NBDKIT_FLAG_REQ_ONE ? NBD_CMD_FLAG_REQ_ONE : 0, > + s = nbd_request_full (h, flags & NBDKIT_FLAG_REQ_ONE ? NBD_CMD_FLAG_REQ_ONE : 0, > NBD_CMD_BLOCK_STATUS, offset, count, NULL, NULL, > extents); > - return c < 0 ? c : nbd_reply (h, c); > + return s ? nbd_reply (h, s) : -1; > } > > /* Cache a portion of the file. */ > @@ -1260,11 +1260,11 @@ static int > nbd_cache (void *handle, uint32_t count, uint64_t offset, uint32_t flags) > { > struct handle *h = handle; > - int c; > + struct transaction *s; > > assert (!flags); > - c = nbd_request (h, 0, NBD_CMD_CACHE, offset, count); > - return c < 0 ? c : nbd_reply (h, c); > + s = nbd_request (h, 0, NBD_CMD_CACHE, offset, count); > + return s ? nbd_reply (h, s) : -1; > } > > static struct nbdkit_plugin plugin = { > -- > 2.20.1 > > _______________________________________________ > Libguestfs mailing list > Libguestfs@redhat.com > https://www.redhat.com/mailman/listinfo/libguestfs-- 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
Maybe Matching Threads
- [nbdkit PATCH 0/4] Play with libnbd for nbdkit-add
- [nbdkit PATCH v2 0/5] Play with libnbd for nbdkit-nbd
- [nbdkit PATCH v3 0/5] Play with libnbd for nbdkit-nbd
- [nbdkit PATCH v2 0/5] structured replies/.extents for nbd plugin
- [nbdkit PATCH] nbd: Drop nbd-standalone fallback