nbd_aio_pread(3)
π nbd_aio_pread β read from the NBD server (libnbd, bestie!!)
Okay so real talk: this whole page lives inside the libnbd manual, section 3, and it's about nbd_aio_pread β the async girlypop read function. She's the asynchronous version of nbd_pread(3), she's iconic, she's fire, and she's gonna let you fire off read requests without blocking. Let's get into it β¨
π¦ SYNOPSIS
First the include, obviously:
#include <libnbd.h>
Then this callback struct, which is basically the RSVP card for when your command finishes:
typedef struct {
int (*callback) (void *user_data, int *error);
void *user_data;
void (*free) (void *user_data);
} nbd_completion_callback;
And the function itself, the main character:
int64_t nbd_aio_pread (
struct nbd_handle *h, void *buf, size_t count,
uint64_t offset,
nbd_completion_callback completion_callback,
uint32_t flags
);
πΈ DESCRIPTION
So what she does: issues a read command to the NBD server. That's it. That's the vibe. Async, non-blocking, chef's kiss π
Wanna know if the command actually finished? Call nbd_aio_command_completed(3) and check. Or β and this is the fun option β hand in the optional completion_callback and she'll invoke it for you, exactly as described in "Completion callbacks" in libnbd(3). Cute, right? π
β οΈ Okay, big important thing, do NOT skip this: you must make sure buf stays valid until the command has completed. Like, do not free it, do not let it go out of scope, do not pass go. It has to still be there.
And here's the spicy part π«£ β if the error parameter to completion_callback is set, or if nbd_aio_command_completed(3) reports failure, and if nbd_get_pread_initialize(3) returns true, then libnbd sanitized buf for you β but it is unspecified whether the contents of buf will read as zero or as partial results from the server. Unspecified, bestie. Not a promise. If nbd_get_pread_initialize(3) returns false, then libnbd did not sanitize buf, and the contents are undefined on failure. Straight up undefined. π
Other parameters behave as documented in nbd_pread(3) β go read that one too, iykyk.
β RETURN VALUE
This call returns the 64 bit cookie of the command πͺ and the cookie is β₯ 1. Cookies are unique β but lowkey only per libnbd handle, not globally. So don't go comparing cookies across handles, that's not the move.
π ERRORS
On error, -1 is returned. Sad but true.
Need the actual deets on what went wrong? Refer to "ERROR HANDLING" in libnbd(3) for how to get further details of the error.
Also: the following parameters must not be NULL: h, buf. For more information see "Non-NULL parameters" in libnbd(3).
β¨ NOTES
π¨ Strict call
By default, libnbd will reject attempts to use this function with parameters that are likely to result in server failure β like, say, requesting an unknown command flag. Rude? No, protective. π«Ά
The nbd_set_strict_mode(3) function can be used to alter which scenarios should await a server reply rather than failing fast.
π¦ HANDLE STATE
nbd_aio_pread can be called when the handle is in the following state:
- Handle created, before connecting β β error
- Connecting β β error
- Connecting & handshaking (opt_mode) β β error
- Connected to the server β β allowed
- Connection shut down β β error
- Handle dead β β error
So yeah. She only works once you're actually connected to the server. The rest? Error, error, error, error. Periodt.
π VERSION
This function first appeared in libnbd 1.0. She's an OG, she's been here since day one π
If you need to test if this function is available at compile time, check if the following macro is defined:
#define LIBNBD_HAVE_NBD_AIO_PREAD 1
π§ EXAMPLE
This example is also available as examples/aio-connect-read.c in the libnbd source code. It's a whole moment, honestly β it shows the AIO (asynchronous) low level API connecting to a server and reading the disk. Also it fires off 32 reads at once and hexdumps each sector as it lands. Obsessed.
/* This example shows how to use the AIO (asynchronous) low
* level API to connect to a server and read the disk.
*
* Here are a few ways to try this example:
*
* nbdkit -U - linuxdisk . \
* --run './aio-connect-read $unixsocket'
*
* nbdkit -U - floppy . \
* --run './aio-connect-read $unixsocket'
*
* nbdkit -U - pattern size=1M \
* --run './aio-connect-read $unixsocket'
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <errno.h>
#include <assert.h>
#include <libnbd.h>
#define NR_SECTORS 32
#define SECTOR_SIZE 512
struct data {
uint64_t offset;
char sector[SECTOR_SIZE];
};
static int
hexdump (void *user_data, int *error)
{
struct data *data = user_data;
FILE *pp;
if (*error) {
errno = *error;
perror ("failed to read");
exit (EXIT_FAILURE);
}
printf ("sector at offset 0x%" PRIx64 ":\n",
data->offset);
pp = popen ("hexdump -C", "w");
if (pp == NULL) {
perror ("popen: hexdump");
exit (EXIT_FAILURE);
}
fwrite (data->sector, SECTOR_SIZE, 1, pp);
pclose (pp);
printf ("\n");
/* Returning 1 from the callback automatically retires
* the command.
*/
return 1;
}
static struct data data[NR_SECTORS];
int
main (int argc, char *argv[])
{
struct nbd_handle *nbd;
size_t i;
if (argc != 2) {
fprintf (stderr, "%s socket\n", argv[0]);
exit (EXIT_FAILURE);
}
/* Create the libnbd handle. */
nbd = nbd_create ();
if (nbd == NULL) {
fprintf (stderr, "%s\n", nbd_get_error ());
exit (EXIT_FAILURE);
}
/* Connect to the NBD server over a Unix domain socket.
* This only starts the connection.
*/
if (nbd_aio_connect_unix (nbd, argv[1]) == -1) {
fprintf (stderr, "%s\n", nbd_get_error ());
exit (EXIT_FAILURE);
}
/* Wait for the connection to complete. The use of
* nbd_poll here is only as an example. You could also
* integrate this with poll(2), glib or another main
* loop. Read libnbd(3) and the source file lib/poll.c.
*/
while (!nbd_aio_is_ready (nbd)) {
if (nbd_poll (nbd, -1) == -1) {
fprintf (stderr, "%s\n", nbd_get_error ());
exit (EXIT_FAILURE);
}
}
assert (nbd_get_size (nbd) >= NR_SECTORS * SECTOR_SIZE);
/* Issue read commands for the first NR sectors. */
for (i = 0; i < NR_SECTORS; ++i) {
data[i].offset = i * SECTOR_SIZE;
/* The callback (hexdump) is called when the command
* completes. The buffer must continue to exist while
* the command is running.
*/
if (nbd_aio_pread (nbd, data[i].sector, SECTOR_SIZE,
data[i].offset,
(nbd_completion_callback) {
.callback = hexdump,
.user_data = &data[i],
}, 0) == -1) {
fprintf (stderr, "%s\n", nbd_get_error ());
exit (EXIT_FAILURE);
}
}
/* Run the main loop until all the commands have
* completed and retired. Again the use of nbd_poll
* here is only as an example.
*/
while (nbd_aio_in_flight (nbd) > 0) {
if (nbd_poll (nbd, -1) == -1) {
fprintf (stderr, "%s\n", nbd_get_error ());
exit (EXIT_FAILURE);
}
}
/* Close the libnbd handle. */
nbd_close (nbd);
exit (EXIT_SUCCESS);
}
π SEE ALSO
Go read these, they're all linked and they all matter:
nbd_aio_command_completed(3)nbd_aio_pread_structured(3)nbd_create(3)nbd_get_pread_initialize(3)nbd_pread(3)nbd_set_pread_initialize(3)nbd_set_strict_mode(3)- "Issuing asynchronous commands" in
libnbd(3) libnbd(3)
π«Ά AUTHORS
Shoutout to the legends who wrote this:
- Eric Blake
- Richard W.M. Jones
π COPYRIGHT
Copyright Red Hat
πΈ LICENSE
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
And that's the whole page, bestie!! π This little beauty is from libnbd-1.25.8, dated 2026-10-13 β so yeah, freshly stamped, go read some sectors async and slay β¨π¦π
π¦ where this page comes from
- centos-stream 10: libnbd-devel 1.25.8-1.el10 Β· LGPL-2.0-or-later AND BSD-3-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms