.\" -*- mode: troff; coding: utf-8 -*- .\" Automatically generated by Podwrapper::Man 1.20.0 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ . ds C` "" . ds C' "" 'br\} .el\{\ . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "libnbd 3" .TH libnbd 3 2024-05-31 libnbd-1.20.0 LIBNBD .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH NAME libnbd \- network block device (NBD) client library in userspace .SH SYNOPSIS .IX Header "SYNOPSIS" .Vb 1 \& #include \& \& struct nbd_handle *nbd; \& char buf[512]; \& \& if ((nbd = nbd_create ()) == NULL || \& nbd_connect_tcp (nbd, "server.example.com", "nbd") == \-1 || \& nbd_pread (nbd, buf, sizeof buf, 0, 0) == \-1) \& fprintf (stderr, "%s\en", nbd_get_error ()); \& nbd_close (nbd); \& exit (EXIT_FAILURE); \& } \& nbd_close (nbd); .Ve .PP .Vb 3 \& cc prog.c \-o prog \-lnbd \&or: \& cc prog.c \-o prog \`pkg\-config libnbd \-\-cflags \-\-libs\` .Ve .SH DESCRIPTION .IX Header "DESCRIPTION" Network Block Device (NBD) is a network protocol for accessing block devices over the network. Block devices are hard disks and things that behave like hard disks such as disk images and virtual machines. .PP Libnbd is a client library for the NBD protocol which can access most of the features of NBD while being simple to use and powerful. .PP This manual page gives an overview of libnbd, using C as an example, but the library is available from other programming languages. .IP "\fBnbd_create\fR\|(3), \fBnbd_pread\fR\|(3), etc." 4 .IX Item "nbd_create, nbd_pread, etc." Each manual page covers one function from the C API in detail. There is a full list in section "C API" below. .IP \fBlibnbd\-ocaml\fR\|(3) 4 .IX Item "libnbd-ocaml" Using the API from OCaml. .IP \fBlibnbd\-golang\fR\|(3) 4 .IX Item "libnbd-golang" Using the API from Go. .IP \fBlibnbd\-rust\fR\|(3) 4 .IX Item "libnbd-rust" Using the API from Rust. .IP \fBnbdsh\fR\|(1) 4 .IX Item "nbdsh" Using the NBD shell (nbdsh) for command line and Python scripting. .SH HANDLES .IX Header "HANDLES" To use the API at all you must first open a handle by calling \&\fBnbd_create\fR\|(3) (or its equivalent in other languages): .PP .Vb 1 \& struct nbd_handle *nbd; \& \& nbd = nbd_create (); .Ve .PP This creates and returns a handle, which is associated with one connection to an NBD server, initially not connected. .PP Each handle is a complex state machine which can be in states such as created, connected to a remote server, handshaking, idle and ready to issue commands, or busy sending or receiving commands. .PP Handles have a name used in debugging messages. The name is normally generated (\f(CW\*(C`nbd1\*(C'\fR, \f(CW\*(C`nbd2\*(C'\fR etc) but you can set a friendly name with \&\fBnbd_set_handle_name\fR\|(3). Also there is a private field in the handle for use by the application, see \fBnbd_set_private_data\fR\|(3). .PP When you have finished with the handle you must call \fBnbd_close\fR\|(3) which closes the underlying socket (if necessary) and frees up all associated resources. .SH "SYNCHRONOUS VS ASYNCHRONOUS API" .IX Header "SYNCHRONOUS VS ASYNCHRONOUS API" There are two levels of API available. A simple high level synchronous API lets you give the handle high level instructions like “connect to the server”, “read a block”, “write a block”, etc. Each of these functions will run to completion, blocking the current thread before returning. A more complicated low level non-blocking asynchronous API is also available where you can integrate with \&\fBpoll\fR\|(2) or another main loop. .PP You can freely mix the two APIs on the same handle. You can also call APIs on a single handle from multiple threads. Single API calls on the handle are atomic — they either take a lock on the handle while they run or are careful to access handle fields atomically. .PP Libnbd does \fBnot\fR create its own threads. .SH "USING THE SYNCHRONOUS (“HIGH LEVEL”) API" .IX Header "USING THE SYNCHRONOUS (“HIGH LEVEL”) API" This is the simplest way to use the API, with the possible drawback that each libnbd function blocks until it is finished. .PP Create a handle and connect to the server: .PP .Vb 1 \& struct nbd_handle *nbd; \& \& nbd = nbd_create (); \& if (!nbd) { \& fprintf (stderr, "%s\en", nbd_get_error ()); \& nbd_close (nbd); \& exit (EXIT_FAILURE); \& } \& if (nbd_connect_tcp (nbd, "server.example.com", "nbd") == \-1) { \& fprintf (stderr, "%s\en", nbd_get_error ()); \& nbd_close (nbd); \& exit (EXIT_FAILURE); \& } .Ve .PP Read the first sector (512 bytes) from the NBD export: .PP .Vb 1 \& char buf[512]; \& \& if (nbd_pread (nbd, buf, sizeof buf, 0, 0) == \-1) { \& fprintf (stderr, "%s\en", nbd_get_error ()); \& nbd_close (nbd); \& exit (EXIT_FAILURE); \& } .Ve .PP Close the handle: .PP .Vb 1 \& nbd_close (nbd); .Ve .PP You can call the high level API from multiple threads, but each libnbd API call takes a lock on the handle and so commands will not run in parallel. .SH "USING THE ASYNCHRONOUS (“LOW LEVEL”) API" .IX Header "USING THE ASYNCHRONOUS (“LOW LEVEL”) API" The low level API is useful if you want to use libnbd in non-blocking code; or if you want to issue commands in parallel from multiple threads; or if you need more control especially over having multiple commands in-flight on a single connection. .PP To use the low level API you will need to integrate with \fBpoll\fR\|(2) or another “main loop” such as the GLib main event loop. .SS "Issuing asynchronous commands" .IX Subsection "Issuing asynchronous commands" Use the \f(CW\*(C`nbd_aio_*\*(C'\fR variants to issue commands asynchronously (without waiting for the command to complete before returning). For example the asynchronous variant of \fBnbd_pread\fR\|(3) is: .PP .Vb 1 \& int64_t cookie; \& \& cookie = nbd_aio_pread (nbd, buf, sizeof buf, \& NBD_NULL_COMPLETION, 0); \& if (cookie == \-1) { \& fprintf (stderr, "%s\en", nbd_get_error ()); \& nbd_close (nbd); \& exit (EXIT_FAILURE); \& } .Ve .PP There are several things to note here: .IP \(bu 4 This only starts the command. The command is (usually) still in flight when the call returns success, where you must rely on subsequent API calls for learning the final command outcome and trigger any remaining callbacks. However, you must also be able to handle the case where system load allows the state machine to advance far enough to invoke callbacks before the asynchronous API returns. .IP \(bu 4 A buffer (\f(CW\*(C`buf\*(C'\fR) has been assigned to collect the result of the read, but it is not guaranteed to be filled with data until the command has completed (see examples below). The buffer must not be freed until the command has finished running. .IP \(bu 4 You can issue multiple commands on the same handle at the same time. .IP \(bu 4 A cookie is returned which identifies this command in subsequent calls. The cookie is unique (per libnbd handle) and ≥ 1. .IP \(bu 4 You may register a function which is called when the command completes, see "Completion callbacks" below. In this case we have specified a null completion callback. If a completion callback is specified, it will only be called if the asynchronous command was successfully submitted (if the asynchronous API itself returns an error, there is nothing further to be completed). .SS "Socket and direction" .IX Subsection "Socket and direction" Each libnbd handle has an associated socket (once it has started connecting). You can read the file descriptor of the socket using: .PP .Vb 1 \& int fd = nbd_aio_get_fd (nbd); .Ve .PP The socket is non-blocking. Between calls into libnbd it is in the "would block" condition. You can find out if libnbd is expecting to read or write from the socket next by calling: .PP .Vb 1 \& int dir = nbd_aio_get_direction (nbd); .Ve .PP which returns one of \f(CW\*(C`LIBNBD_AIO_DIRECTION_READ\*(C'\fR, \&\f(CW\*(C`LIBNBD_AIO_DIRECTION_WRITE\*(C'\fR or \f(CW\*(C`LIBNBD_AIO_DIRECTION_BOTH\*(C'\fR (= \&\f(CW\*(C`READ|WRITE\*(C'\fR). And so to set up the next call to \fBpoll\fR\|(2) or other main loop you must translate this to \f(CW\*(C`POLLIN\*(C'\fR, \f(CW\*(C`POLLOUT\*(C'\fR or \&\f(CW\*(C`POLLIN|POLLOUT\*(C'\fR (or whatever mechanism your main loop uses). .SS "Notifying libnbd when an event happens" .IX Subsection "Notifying libnbd when an event happens" When you detect (eg. using \fBpoll\fR\|(2)) that a read or write event has happened on the socket, you must then tell libnbd about it. You have to check the direction \fIagain\fR (since it may have been changed by another thread), and notify libnbd: .PP .Vb 1 \& int r = 0; \& \& dir = nbd_aio_get_direction (nbd); \& \& if ((dir & LIBNBD_AIO_DIRECTION_READ) && \& a_read_event_occurred ()) \& r = nbd_aio_notify_read (nbd); \& else if ((dir & LIBNBD_AIO_DIRECTION_WRITE) && \& a_write_event_occurred ()) \& r = nbd_aio_notify_write (nbd); \& \& if (r == \-1) { \& fprintf (stderr, "%s\en", nbd_get_error ()); \& // ... \& } .Ve .PP The notify calls move the state machine along, reading and writing from the socket possibly multiple times, until the socket would block again, at which point they return control to the caller. .SS "Simple implementation with \fBnbd_poll\fP\|(3)" .IX Subsection "Simple implementation with nbd_poll" In fact if you want to use \fBpoll\fR\|(2) on a single handle, a simple implementation has already been written called \fBnbd_poll\fR\|(3). It is also useful to examine how this is implemented (\fIlib/poll.c\fR in the libnbd source code) because that will tell you how to integrate libnbd with more complex main loops. .PP Some examples of using \fBnbd_poll\fR\|(3) follow. .PP As with the high level API, it all starts by creating a handle: .PP .Vb 1 \& struct nbd_handle *nbd; \& \& nbd = nbd_create (); \& if (nbd == NULL) { \& fprintf (stderr, "%s\en", nbd_get_error ()); \& nbd_close (nbd); \& exit (EXIT_FAILURE); \& } .Ve .PP To connect to the server asynchronously, we start the connection using \&\fBnbd_aio_connect\fR\|(3) and then enter our main loop to check for events until the connection becomes ready: .PP .Vb 3 \& int fd; \& struct sockaddr_un addr; \& socklen_t len; \& \& /* some code to set up addr, \& then ... */ \& if (nbd_aio_connect (nbd, &addr, len) == \-1) { \& fprintf (stderr, "%s\en", nbd_get_error ()); \& nbd_close (nbd); \& exit (EXIT_FAILURE); \& } \& while (! nbd_aio_is_ready (nbd)) { \& if (nbd_poll (nbd, \-1) == \-1) { \& fprintf (stderr, "%s\en", nbd_get_error ()); \& nbd_close (nbd); \& exit (EXIT_FAILURE); \& } \& } .Ve .PP To read data asynchronously, start an asynchronous read command, which returns a 64 bit command cookie, and enter the main loop until the command has completed: .PP .Vb 2 \& int64_t cookie; \& char buf[512]; \& \& cookie = nbd_aio_pread (nbd, buf, sizeof buf, offset, \& NBD_NULL_COMPLETION, 0); \& if (cookie == \-1) { \& fprintf (stderr, "%s\en", nbd_get_error ()); \& nbd_close (nbd); \& exit (EXIT_FAILURE); \& } \& while (! nbd_aio_command_completed (nbd, cookie)) { \& if (nbd_poll (nbd, \-1) == \-1) { \& fprintf (stderr, "%s\en", nbd_get_error ()); \& nbd_close (nbd); \& exit (EXIT_FAILURE); \& } \& } .Ve .PP For almost all high level synchronous calls (eg. \fBnbd_pread\fR\|(3)) there is a low level asynchronous equivalent (eg. \fBnbd_aio_pread\fR\|(3)) for starting a command. .SS "glib2 integration" .IX Subsection "glib2 integration" See https://gitlab.com/nbdkit/libnbd/blob/master/examples/glib\-main\-loop.c .SS "libev integration" .IX Subsection "libev integration" See https://gitlab.com/nbdkit/libnbd/blob/master/examples/copy\-libev.c .SH "ERROR HANDLING" .IX Header "ERROR HANDLING" When any API call returns an error (\f(CW\-1\fR or \f(CW\*(C`NULL\*(C'\fR depending on the API), an error message and sometimes an errno value are available. You can retrieve the error message and/or errno of the most recently failed call using \fBnbd_get_error\fR\|(3) and \fBnbd_get_errno\fR\|(3). For example: .PP .Vb 5 \& if (nbd_connect_tcp (nbd, "remote", "nbd") == \-1) { \& fprintf (stderr, \& "failed to connect to remote server: %s (errno = %d)\en", \& nbd_get_error (), nbd_get_errno ()); \& } .Ve .PP These functions use thread-local storage to return the most recent error in the current thread. This is why you don't need to pass the handle to these calls. They even work if \fBnbd_create\fR\|(3) returns \&\f(CW\*(C`NULL\*(C'\fR when there is no handle at all. .PP For this reason you cannot call them from a different thread. You should call them immediately after the failed API call, from the same thread. Furthermore the error string returned by \fBnbd_get_error\fR\|(3) is only valid until the next libnbd API call in the current thread, so if you need to keep the string you must copy it (eg. using \fBstrdup\fR\|(3)). .SS Errno .IX Subsection "Errno" For some errors, a system call error number (see \fBerrno\fR\|(3)) is available. You can find the error number by calling \&\fBnbd_get_errno\fR\|(3). It works the same way as \fBnbd_get_error\fR\|(3) with respect to threads. .PP Even when a call returns an error, \fBnbd_get_errno\fR\|(3) might return \&\f(CW0\fR. This does \fInot\fR mean there was no error. It means no additional errno information is available for this error. .PP The error number is often the raw error returned by a system call that failed. .PP It can also be used to indicate special conditions. The most common cases are: .ie n .IP """EINVAL""" 4 .el .IP \f(CWEINVAL\fR 4 .IX Item "EINVAL" Invalid parameters or state for the current libnbd call. (This can also indicate that requests are not aligned to "Block size constraints"). .ie n .IP """ENOTSUP""" 4 .el .IP \f(CWENOTSUP\fR 4 .IX Item "ENOTSUP" The libnbd call is not available in this build of libnbd (eg. when using a TLS API if the library was compiled without TLS support). .ie n .IP """ENOMEM""" 4 .el .IP \f(CWENOMEM\fR 4 .IX Item "ENOMEM" The library ran out of memory while performing some operation. .ie n .IP """ERANGE""" 4 .el .IP \f(CWERANGE\fR 4 .IX Item "ERANGE" A request is too large, for example if you try to read too many bytes in a single \fBnbd_pread\fR\|(3) call. .ie n .IP """EFAULT""" 4 .el .IP \f(CWEFAULT\fR 4 .IX Item "EFAULT" A pointer parameter was \f(CW\*(C`NULL\*(C'\fR when it should be non-NULL. See the section below. .SS "Non-NULL parameters" .IX Subsection "Non-NULL parameters" Almost all libnbd functions when called from C take one or more pointer parameters that must not be \f(CW\*(C`NULL\*(C'\fR. For example, the handle parameter, strings and buffers should usually not be \f(CW\*(C`NULL\*(C'\fR. .PP If a \f(CW\*(C`NULL\*(C'\fR is passed as one of these parameters, libnbd attempts to return an error with \fBnbd_get_errno\fR\|(3) returning \f(CW\*(C`EFAULT\*(C'\fR. .PP However it may cause other compiler-related warnings and even undefined behaviour, so you should try to avoid this programming mistake. .SH "DEBUGGING MESSAGES" .IX Header "DEBUGGING MESSAGES" Libnbd can print lots of debugging messages, useful if you have a problem with the library. Either enable debugging after creating the handle: .PP .Vb 2 \& nbd = nbd_create (); \& nbd_set_debug (nbd, true); .Ve .PP or set the \f(CW\*(C`LIBNBD_DEBUG=1\*(C'\fR environment variable which will enable debugging by default on all new handles. .PP Debugging messages are sent to stderr by default, but you can redirect them to a logging system using \fBnbd_set_debug_callback\fR\|(3). .SH "CONNECTING TO LOCAL OR REMOTE NBD SERVERS" .IX Header "CONNECTING TO LOCAL OR REMOTE NBD SERVERS" There are several ways to connect to NBD servers, and you can even run a server from libnbd. Normally you would connect to a server which is already running, over a local Unix domain socket or a remote TCP connection. The high level API calls are: .PP .Vb 2 \& nbd_connect_unix (nbd, "socket"); \& nbd_connect_tcp (nbd, "localhost", "nbd"); .Ve .PP For \fBnbd_connect_tcp\fR\|(3) the third parameter is the port name or number, which can either be a name from \fI/etc/services\fR or the port number as a string (eg. \f(CW"10809"\fR). .SS "Connecting to an NBD URI" .IX Subsection "Connecting to an NBD URI" libnbd supports the NBD URI specification. The format of URIs is documented in \fBnbd_connect_uri\fR\|(3). .PP You can connect to a URI as in these examples (using the high level API): .PP .Vb 1 \& nbd_connect_uri (nbd, "nbd://example.com/"); .Ve .PP .Vb 1 \& nbd_connect_uri (nbd, "nbds+unix:///export?socket=/tmp/nbd.sock"); .Ve .PP This feature is implemented by calling other libnbd APIs to set up the export name, TLS parameters, and finally connect over a Unix domain socket or TCP. .PP URI support is an optional feature of the library, requiring libxml2 at compile time. The \fBnbd_connect_uri\fR\|(3) and \&\fBnbd_aio_connect_uri\fR\|(3) calls will raise an error (with \&\fBnbd_get_errno\fR\|(3) returning \f(CW\*(C`ENOTSUP\*(C'\fR) if it was not built with this feature, and you can also test for it explicitly using \&\fBnbd_supports_uri\fR\|(3). .SS "Connecting to a subprocess" .IX Subsection "Connecting to a subprocess" Some NBD servers — notably \fBnbdkit\fR\|(1) with the \fI\-s\fR parameter, and \&\fBnbd\-server\fR\|(1) with the port parameter set to 0 — can also accept a single NBD connection on stdin/stdout. You can run these servers as a subprocess of your main program using \fBnbd_connect_command\fR\|(3). This example creates a 1G writable RAM disk: .PP .Vb 3 \& char *argv[] = { "nbdkit", "\-s", "\-\-exit\-with\-parent", \& "memory", "1G", NULL }; \& nbd_connect_command (nbd, argv); .Ve .PP When the handle is closed the nbdkit subprocess is killed, which in this case means the RAM disk is discarded, so this is useful for testing. .SS "Connecting to a subprocess using systemd socket activation" .IX Subsection "Connecting to a subprocess using systemd socket activation" Some NBD servers — notably \fBnbdkit\fR\|(1) and \fBqemu\-nbd\fR\|(1) — support systemd socket activation allowing libnbd to pass a socket to the subprocess. This works very similarly to \fBnbd_connect_command\fR\|(3) described above, but you must use \&\fBnbd_connect_systemd_socket_activation\fR\|(3) instead. .SS "Connecting to any socket" .IX Subsection "Connecting to any socket" If none of the other nbd_connect* methods are suitable you can create a connected socket yourself and pass it to \fBnbd_connect_socket\fR\|(3). .PP One use for this is in fuzzing where we use \fBsocketpair\fR\|(2) to create the socket, then fork, then have the test harness in the child process connected to libnbd over the socket pair (see: https://gitlab.com/nbdkit/libnbd/\-/blob/master/fuzzing/libnbd\-fuzz\-wrapper.c). .PP Another use is to connect libnbd to an address family that it does not support natively, such as XDP or IB. .SH "CONTROLLING NEGOTIATION" .IX Header "CONTROLLING NEGOTIATION" By default, when beginning a connection, libnbd will handle all negotiation with the server, using only the configuration (eg. \fBnbd_set_export_name\fR\|(3) or \fBnbd_add_meta_context\fR\|(3)) that was requested before the connection attempt; this phase continues until \&\fBnbd_aio_is_connecting\fR\|(3) no longer returns true, at which point, either data commands are ready to use or else the connection has failed with an error. .PP But there are scenarios in which it is useful to also control the handshaking commands sent during negotiation, such as asking the server for a list of available exports prior to selecting which one to use. This is done by calling \fBnbd_set_opt_mode\fR\|(3) before connecting; then after requesting a connection, the state machine will pause at \fBnbd_aio_is_negotiating\fR\|(3) at any point that the user can decide which handshake command to send next. Note that the negotiation state is only reachable from newstyle servers; older servers cannot negotiate and will progress all the way to the ready state. .PP When the negotiating state is reached, you can initiate option commands such as \fBnbd_opt_list\fR\|(3) or their asynchronous equivalents, as well as alter configuration such as export name that previously had to be set before connection. Since the NBD protocol does not allow parallel negotiating commands, no cookie is involved, and you can track completion of each command when the state is no longer \&\fBnbd_aio_is_connecting\fR\|(3). If \fBnbd_opt_go\fR\|(3) fails but the connection is still live, you will be back in negotiation state, where you can request a different export name and try again. Exiting the negotiation state is only possible with a successful \fBnbd_opt_go\fR\|(3) which moves to the data phase, or \fBnbd_opt_abort\fR\|(3) which performs a clean shutdown of the connection by skipping the data phase. .SH "EXPORTS AND FLAGS" .IX Header "EXPORTS AND FLAGS" It is possible for NBD servers to serve different content on different “exports”. For this you must pass the right export name to the server. Call this API before connecting: .PP .Vb 1 \& nbd_set_export_name (nbd, "export"); .Ve .PP Note that there are some servers (like \fBnbdkit\fR\|(1) ≤ 1.14) which ignore this, and other servers (like \fBqemu\-nbd\fR\|(8)) which require it to be set correctly but cannot serve different content. .PP These APIs are also available after a successful \fBnbd_opt_info\fR\|(3) during the negotiation phase, if you used \fBnbd_set_opt_mode\fR\|(3) prior to connecting. .SS "Flag calls" .IX Subsection "Flag calls" After connecting the server will send back a set of flags describing the export, such as whether it is writable and if it can support flush to permanent storage. These flags can be accessed from libnbd using APIs such as: .PP .Vb 2 \& int is_read_only = nbd_is_read_only (nbd); \& int can_flush = nbd_can_flush (nbd); .Ve .PP Flag calls are: \fBnbd_can_block_status_payload\fR\|(3), \&\fBnbd_can_cache\fR\|(3), \&\fBnbd_can_df\fR\|(3), \&\fBnbd_can_fast_zero\fR\|(3), \&\fBnbd_can_flush\fR\|(3), \&\fBnbd_can_fua\fR\|(3), \&\fBnbd_can_meta_context\fR\|(3), \&\fBnbd_can_multi_conn\fR\|(3), \&\fBnbd_can_trim\fR\|(3), \&\fBnbd_can_zero\fR\|(3), \&\fBnbd_is_read_only\fR\|(3), \&\fBnbd_is_rotational\fR\|(3). .SS "Size of the export" .IX Subsection "Size of the export" To get the size of the export in bytes, use \fBnbd_get_size\fR\|(3): .PP .Vb 1 \& int64_t size = nbd_get_size (nbd); .Ve .SS "Block size constraints" .IX Subsection "Block size constraints" Some NBD servers cannot handle requests at any byte boundary. They might, for example, require all requests to be aligned to 512 byte sectors. .PP Also some servers advertise a preferred block size. This is not a requirement, but is the minimum block size that can be accessed efficiently (usually without triggering expensive read-modify-write cycles inside the server). .PP These are referred to as block size constraints and can be queried by calling \fBnbd_get_block_size\fR\|(3). Pay attention in particular to the \&\f(CW\*(C`LIBNBD_SIZE_MINIMUM\*(C'\fR constraint as some servers will fail requests which are smaller or not aligned to this block size with \f(CW\*(C`EINVAL\*(C'\fR ("Invalid argument") errors. .PP For information on the server side, see ".block_size" in \fBnbdkit\-plugin\fR\|(3). .PP For definitive information about block size constraints, read the NBD protocol specification. .SH "DATA COMMANDS" .IX Header "DATA COMMANDS" You can read and write data from the NBD server using \fBnbd_pread\fR\|(3) and \fBnbd_pwrite\fR\|(3) or their asynchronous equivalents. .PP All data commands support a \f(CW\*(C`flags\*(C'\fR argument (mandatory in C, but optional in languages where it can default to 0). For convenience, the constant \f(CW\*(C`LIBNBD_CMD_FLAG_MASK\*(C'\fR is defined with the set of flags currently recognized by libnbd, where future NBD protocol extensions may result in additional flags being supported; but in general, specific data commands only accept a subset of known flags. .PP Libnbd defaults to performing some client-side sanity checking in each of its data commands; for example, attempts to write to a server that has advertised a read-only connection are rejected. It is possible to override aspects of this checking by using \fBnbd_set_strict_mode\fR\|(3). .PP Some servers also support: .IP trim/discard 4 .IX Item "trim/discard" If \fBnbd_can_trim\fR\|(3) returns true, \fBnbd_trim\fR\|(3) can be used to “punch holes” in the backing storage of the disk on the server. Normally (although not in every case) the holes read back as zeroes but take up no space. .IP zeroing 4 .IX Item "zeroing" If \fBnbd_can_zero\fR\|(3) returns true, \fBnbd_zero\fR\|(3) can be used to efficiently zero parts of the disk without having to send large amounts of zero bytes over the network (as would be necessary if using \&\fBnbd_pwrite\fR\|(3)). .Sp This is slightly different from trimming because the backing storage is still allocated. For some storage types this can make future writes more efficient and/or less likely to fail because of out of space errors. .IP flushing 4 .IX Item "flushing" Some servers can commit data to permanent storage and tell you that this has happened reliably. There are two export flags associated with this: \fBnbd_can_flush\fR\|(3) and \fBnbd_can_fua\fR\|(3). .Sp The \fBnbd_flush\fR\|(3) call (available if \fBnbd_can_flush\fR\|(3) returns true) flushes all pending writes to disk and does not complete until that operation has finished. It is similar to using \fBsync\fR\|(2) on POSIX systems. .Sp A more efficient way to achieve this is to set the flag \&\f(CW\*(C`LIBNBD_CMD_FLAG_FUA\*(C'\fR on write-like calls (like write, trim and zero). This flag means the call will not complete until committed to permanent storage, but it does not involve flushing the entire disk. .IP prefetching 4 .IX Item "prefetching" Some servers can prefetch data, making subsequent reads faster. The \&\fBnbd_cache\fR\|(3) call (available if \fBnbd_can_cache\fR\|(3) returns true) is used to prefetch. .IP "block status" 4 .IX Item "block status" Some servers are able to provide information about the various extents within the image, via the notion of one or more meta contexts. The most common meta context is "base:allocation" (available in libnbd.h as \f(CW\*(C`LIBNBD_CONTEXT_BASE_ALLOCATION\*(C'\fR), which can be used to learn which portions of a file are allocated or read as zero. Other contexts may be available; for example, \fBqemu\-nbd\fR\|(8) can expose a meta context "qemu:dirty\-bitmap:NAME" for tracking which portions of a file are tracked by a qcow2 dirty bitmap. .Sp In order to utilize block status, the client must call \&\fBnbd_add_meta_context\fR\|(3) prior to connecting, for each meta context in which it is interested, then check \fBnbd_can_meta_context\fR\|(3) after connection to see which contexts the server actually supports. If a context is supported, the client can then use \&\fBnbd_block_status_64\fR\|(3) with a callback function that will receive an array of structs describing consecutive extents within a context. Each struct gives the length of the extent, then a bitmask description of that extent (for the "base:allocation" context, the bitmask may include \f(CW\*(C`LIBNBD_STATE_HOLE\*(C'\fR for unallocated portions of the file, and/or \f(CW\*(C`LIBNBD_STATE_ZERO\*(C'\fR for portions of the file known to read as zero). .Sp There is a full example of requesting meta context and using block status available at https://gitlab.com/nbdkit/libnbd/blob/master/interop/dirty\-bitmap.c .SH PERFORMANCE .IX Header "PERFORMANCE" .SS "Issuing multiple in-flight requests" .IX Subsection "Issuing multiple in-flight requests" NBD servers which properly implement the specification can handle multiple data requests in flight over the same connection at the same time. Libnbd supports this when using the low level API. .PP To use it you simply issue more requests as needed (eg. using calls like \fBnbd_aio_pread\fR\|(3), \fBnbd_aio_pwrite\fR\|(3)) without waiting for previous commands to complete. You need to be careful that requests in flight do not overlap with disk offsets of other write-like commands in flight — an overlapping read may see indeterminate data, and an overlapping write may even cause disk corruption where the resulting disk contents do not match either of the two writes. .PP Each request is identified by a unique 64 bit cookie (assigned by libnbd), allowing libnbd and callers to match replies to requests. Replies may arrive out of order. A request that is rejected client-side for failing a sanity check (such as attempting to write to a read-only server, see \fBnbd_set_strict_mode\fR\|(3)) will fail rather than returning a cookie, although closure cleanup is still performed. .PP Although in theory you can have an indefinite number of requests in flight at the same time, in practice it's a good idea to limit them to some number. Libnbd will queue commands in the handle even if it cannot write them to the server, so this limit is largely to prevent a backlog of commands from consuming too much memory. It is suggested to start with a limit of 64 requests in flight (per NBD connection), and measure how adjusting the limit up and down affects performance for your local configuration. .PP There is a full example using multiple in-flight requests available at https://gitlab.com/nbdkit/libnbd/blob/master/examples/threaded\-reads\-and\-writes.c .SS Multi-conn .IX Subsection "Multi-conn" Some NBD servers advertise “multi\-conn” which means that it is safe to make multiple connections to the server and load-balance commands across all of the connections. .PP To do this you should open a single connection first and test for this feature using \fBnbd_can_multi_conn\fR\|(3). Without error handling it would look like this: .PP .Vb 3 \& struct nbd_handle *nbd[4]; \& size_t i; \& bool supports_multi_conn; \& \& nbd[0] = nbd_create (); \& nbd_connect_tcp (nbd[0], "server", "10809"); \& supports_multi_conn = nbd_can_multi_conn (nbd[0]) > 0; .Ve .PP If multi-conn is supported then you can open further connections: .PP .Vb 6 \& if (supports_multi_conn) { \& for (i = 1; i <= 3; ++i) { \& nbd[i] = nbd_create (); \& nbd_connect_tcp (nbd[i], "server", "10809"); \& } \& } .Ve .PP If you are issuing multiple in-flight requests (see above) and limiting the number, then the limit should be applied to each individual NBD connection. .SH "ENCRYPTION AND AUTHENTICATION" .IX Header "ENCRYPTION AND AUTHENTICATION" The NBD protocol and libnbd supports TLS (sometimes incorrectly called “SSL”) for encryption of the data stream and authentication of clients and servers. Libnbd defaults to TLS \fIdisabled\fR for maximum interoperability. To enable it on a handle you must call \&\fBnbd_set_tls\fR\|(3) before connecting. .PP To allow TLS, but fall back to unencrypted: .PP .Vb 1 \& nbd_set_tls (nbd, LIBNBD_TLS_ALLOW); .Ve .PP Use \fBnbd_get_tls_negotiated\fR\|(3) to find out if TLS negotiation was successful. Avoid \f(CW\*(C`LIBNBD_TLS_ALLOW\*(C'\fR if man-in-the-middle attacks are a concern. .PP The most secure mode is to require TLS and fail to connect if the server does not support it: .PP .Vb 1 \& nbd_set_tls (nbd, LIBNBD_TLS_REQUIRE); .Ve .PP It may also be necessary to verify that the server’s identity is correct. For some servers it may be necessary to verify to the server that the client is permitted to connect. This can be done using either X.509 certificates, or TLS Pre-Shared Keys (PSK). Certificates are more secure. PSK is far more convenient, but you must have an existing secure channel to distribute the keys. .SS "Setting up X.509 using system certificate authorities (CAs)" .IX Subsection "Setting up X.509 using system certificate authorities (CAs)" This is the default if you don’t call any other \f(CW\*(C`nbd_set_tls_*\*(C'\fR functions. In this case the server must have a public (eg. HTTPS) certificate which can be verified against the CAs registered on your system (eg. under \fI/etc/pki\fR). .PP To disable server name verification — which opens you up to a potential Man-In-The-Middle (MITM) attack — use: .PP .Vb 1 \& nbd_set_tls_verify_peer (nbd, false); .Ve .SS "Setting up an X.509 certificate authority (CA)" .IX Subsection "Setting up an X.509 certificate authority (CA)" You can set up your own CA and register clients and servers with it, issuing client and server certificates which will reliably authenticate your clients and servers to each other. .PP Doing this is described in detail in the \fBnbdkit\-tls\fR\|(1) manual. The only differences for libnbd are: .IP \(bu 4 Non-root certificates must be placed in \f(CW\*(C`$HOME/.pki/libnbd/\*(C'\fR or \&\f(CW\*(C`$HOME/.config/pki/libnbd/\*(C'\fR .IP \(bu 4 Libnbd reads \fIclient\-cert.pem\fR and \fIclient\-key.pem\fR (instead of \&\fIserver\-cert.pem\fR and \fIserver\-key.pem\fR). .PP Once you have set up the directory containing the certificates, call: .PP .Vb 1 \& nbd_set_tls_certificates (nbd, "/path/to/directory"); .Ve .SS "Setting up Pre-Shared Keys (PSK)" .IX Subsection "Setting up Pre-Shared Keys (PSK)" TLS Pre-Shared Keys are a much more convenient method of setting up TLS, and more appropriate for NBD, but you should have an existing secure method available to distribute the keys. They are therefore ideal if you want to set up an NBD service as an adjunct to an existing secure REST API. .PP Use \fBpsktool\fR\|(1) to create a file of \f(CW\*(C`username:key\*(C'\fR pairs: .PP .Vb 1 \& psktool \-u username \-p keys.psk .Ve .PP and pass this path to libnbd: .PP .Vb 1 \& nbd_set_tls_psk_file (nbd, "keys.psk"); .Ve .PP If necessary you may need to set the client username (otherwise libnbd will use your login name): .PP .Vb 1 \& nbd_set_tls_username (nbd, "username"); .Ve .SH CALLBACKS .IX Header "CALLBACKS" Some libnbd calls take callbacks (eg. \fBnbd_set_debug_callback\fR\|(3), \&\fBnbd_aio_pread\fR\|(3)). Libnbd can call these functions while processing. .PP In the C API these libnbd calls take a structure which contains the function pointer and an optional opaque \f(CW\*(C`void *user_data\*(C'\fR pointer: .PP .Vb 4 \& nbd_aio_pread (nbd, buf, sizeof buf, offset, \& (nbd_completion_callback) { .callback = my_fn, \& .user_data = my_data }, \& 0); .Ve .PP For optional callbacks, if you don't want the callback, either set \&\f(CW\*(C`.callback\*(C'\fR to \f(CW\*(C`NULL\*(C'\fR or use the equivalent macros (such as \&\f(CW\*(C`NBD_NULL_COMPLETION\*(C'\fR) defined in \f(CW\*(C`libnbd.h\*(C'\fR: .PP .Vb 2 \& nbd_aio_pread (nbd, buf, sizeof buf, offset, \& NBD_NULL_COMPLETION, 0); .Ve .PP From other languages the structure and opaque pointer are not needed because you can use closures to achieve the same effect. .SS "Callback lifetimes" .IX Subsection "Callback lifetimes" You can associate an optional free function with callbacks. Libnbd will call this function when the callback will not be called again by libnbd, including in the case where the API fails. .PP This can be used to free associated \f(CW\*(C`user_data\*(C'\fR. For example: .PP .Vb 1 \& void *my_data = malloc (...); \& \& nbd_aio_pread_structured (nbd, buf, sizeof buf, offset, \& (nbd_chunk_callback) { .callback = my_fn, \& .user_data = my_data, \& .free = free }, \& NBD_NULL_COMPLETION, \& 0); .Ve .PP will call \fBfree\fR\|(3) once on \f(CW\*(C`my_data\*(C'\fR after the point where it is known that the \f(CW\*(C`chunk.callback\ =\ my_fn\*(C'\fR function can no longer be called, regardless of how many times \f(CW\*(C`my_fn\*(C'\fR was actually called. If both a mid-command and completion callback are supplied, the functions will be reached in this order: mid-function callbacks, completion callback, mid-function free, and finally completion free. .PP The free function is only accessible in the C API as it is not needed in garbage collected programming languages. .ie n .SS "Callbacks with "".callback=NULL"" and "".free!=NULL""" .el .SS "Callbacks with \f(CW.callback=NULL\fP and \f(CW.free!=NULL\fP" .IX Subsection "Callbacks with .callback=NULL and .free!=NULL" It is possible to register a callback like this: .PP .Vb 5 \& ... \& (nbd_completion_callback) { .callback = NULL, \& .user_data = my_data, \& .free = free }, \& ... .Ve .PP The meaning of this is that the callback is never called, but the free function is still called after the last time the callback would have been called. This is useful for applying generic freeing actions when asynchronous commands are retired. .SS "Callbacks and locking" .IX Subsection "Callbacks and locking" The callbacks are invoked at a point where the libnbd lock is held, typically during a call to \f(CW\*(C`nbd_aio_notify_read\*(C'\fR, \&\f(CW\*(C`nbd_aio_notify_write\*(C'\fR, \f(CW\*(C`nbd_aio_poll\*(C'\fR, or other call that can advance libnbd's state machine. Depending on system load, it is even possible for a callback to be reached before completion of the \&\f(CW\*(C`nbd_aio_*\*(C'\fR call that specified the callback. As such, it is unsafe for the callback to call any \f(CW\*(C`nbd_*\*(C'\fR APIs on the same nbd object, as it would cause deadlock. .SS "Completion callbacks" .IX Subsection "Completion callbacks" All of the asychronous commands have an optional completion callback function that is used if the call to the asynchronous API reports success. The completion callback is invoked when the submitted command is eventually marked complete, after any mid-command callbacks have finished, and before any free functions. The completion callback is not reached if the asynchronous API itself fails, while free callbacks are reached regardless of the result of the initial asynchronous API. .PP When the completion callback returns \f(CW1\fR, the command is automatically retired (there is no need to call \&\fBnbd_aio_command_completed\fR\|(3)); for any other return value, the command still needs to be manually retired (otherwise, the command will tie up resources until \fBnbd_close\fR\|(3) is eventually reached). .ie n .SS "Callbacks with ""int *error"" parameter" .el .SS "Callbacks with \f(CWint *error\fP parameter" .IX Subsection "Callbacks with int *error parameter" Some of the high-level commands (\fBnbd_pread_structured\fR\|(3), \&\fBnbd_block_status_64\fR\|(3)) involve the use of a callback function invoked by the state machine at appropriate points in the server's reply before the overall command is complete. These callback functions, along with all of the completion callbacks, include a parameter \&\f(CW\*(C`error\*(C'\fR which is a pointer containing the value of any error detected so far. If a callback function fails and wants to change the resulting error of the overall command visible later in the API sequence, it should assign back into \f(CW\*(C`error\*(C'\fR and return \f(CW\-1\fR in the C API. Assignments into \f(CW\*(C`error\*(C'\fR are ignored for any other return value; similarly, assigning \f(CW0\fR into \f(CW\*(C`error\*(C'\fR does not have an effect. In other language bindings, reporting callback errors is generally done by raising an exception rather than by return value. .PP Note that a mid-command callback might never be reached, such as if libnbd detects that the command was invalid to send (see \&\fBnbd_set_strict_mode\fR\|(3)) or if the server reports a failure that concludes the command. It is safe for a mid-command callback to ignore non-zero \f(CW\*(C`error\*(C'\fR: all the other parameters to the mid-command callback will still be valid (corresponding to the current portion of the server's reply), and the overall command will still fail (at the completion callback or \fBnbd_aio_command_completed\fR\|(3) for an asynchronous command, or as the result of the overall synchronous command). Returing \f(CW\-1\fR from a mid-command callback does not prevent that callback from being reached again, if the server sends more mid-command replies that warrant another use of that callback. A mid-command callback may be reached more times than expected if the server is non-compliant. .PP On the other hand, if a completion callback is supplied (only possible with asynchronous commands), it will not be called if the initial API call fails (such as attempting an asynchronous command in the wrong state \- there is nothing to be completed since the command was not queued), but will otherwise be called exactly once, and the completion callback must not ignore the value pointed to by \f(CW\*(C`error\*(C'\fR. In particular, the content of a buffer passed to \fBnbd_aio_pread\fR\|(3) or \&\fBnbd_aio_pread_structured\fR\|(3) is undefined if \f(CW*error\fR is non-zero on entry to the completion callback. It is recommended that if you choose to use automatic command retirement (where the completion callback returns \f(CW1\fR to avoid needing to call \&\fBnbd_aio_command_completed\fR\|(3) later), your completion function should return \f(CW1\fR on all control paths, even when handling errors (note that with automatic retirement, assigning into \f(CW\*(C`error\*(C'\fR is pointless as there is no later API to see that value). .SH "STATISTICS COUNTERS" .IX Header "STATISTICS COUNTERS" Libnbd tracks several statistics counters, useful for tracking how much traffic was sent over the connection. The counters track the number of plaintext bytes sent and received by the NBD protocol (not necessarily the number of bytes sent over the socket, particularly when TLS is enabled), as well as the number of protocol chunks (a group of bytes delineated by a magic number, and not the same as the number of TCP packets). .PP .Vb 4 \& printf ("bytes: sent=%" PRIu64 " received=%" PRIu64, \& nbd_stats_bytes_sent (nbd), nbd_stats_bytes_received (nbd)); \& printf ("chunks: sent=%" PRIu64 " received=%" PRIu64, \& nbd_stats_chunks_sent (nbd), nbd_stats_chunks_received (nbd)); .Ve .SH SIGNALS .IX Header "SIGNALS" Libnbd does not install signal handlers. It attempts to disable \&\f(CW\*(C`SIGPIPE\*(C'\fR when writing to the NBD socket using the \f(CW\*(C`MSG_NOSIGNAL\*(C'\fR flag of \fBsend\fR\|(2), or the \f(CW\*(C`SO_NOSIGPIPE\*(C'\fR socket option, on platforms that support those. .PP On some old Linux or newer non-Linux platforms the main program may wish to register a signal handler to ignore SIGPIPE: .PP .Vb 1 \& signal (SIGPIPE, SIG_IGN); .Ve .SH "COMPILING YOUR PROGRAM" .IX Header "COMPILING YOUR PROGRAM" On most systems, C programs that use libnbd can be compiled like this: .PP .Vb 1 \& cc prog.c \-o prog \-lnbd .Ve .PP To detect if the libnbd library and header file is installed, the preferred method is to use \fBpkg\-config\fR\|(1) or \fBpkgconf\fR\|(1): .PP .Vb 1 \& pkg\-config libnbd \-\-exists || fail libnbd is required .Ve .PP In case the library or header file are not installed in the usual system locations, you can compile your program like this, using pkg-config to detect the proper location of libnbd: .PP .Vb 1 \& cc prog.c \-o prog \`pkg\-config libnbd \-\-cflags \-\-libs\` .Ve .PP To compile an external project against a built copy of the libnbd source tree which hasn't been installed, see the \fI./run\fR script. .SS "Autoconf projects" .IX Subsection "Autoconf projects" External projects which use autoconf and need to check if libnbd is installed should use the \f(CW\*(C`PKG_CHECK_MODULES\*(C'\fR macro in \fIconfigure.ac\fR like this: .PP .Vb 1 \& PKG_CHECK_MODULES([LIBNBD], [libnbd]) .Ve .PP This will define \f(CW\*(C`@LIBNBD_CFLAGS@\*(C'\fR and \f(CW\*(C`@LIBNBD_LIBS@\*(C'\fR which you will need to add to your \fIMakefile.am\fR. .SS "CMake projects" .IX Subsection "CMake projects" For CMake projects use: .PP .Vb 5 \& find_package(PkgConfig REQUIRED) \& pkg_check_modules(LIBNBD REQUIRED libnbd) \& target_link_libraries(prog ${LIBNBD_LIBRARIES}) \& target_include_directories(prog PUBLIC ${LIBNBD_INCLUDE_DIRS}) \& target_compile_options(prog PUBLIC ${LIBNBD_CFLAGS_OTHER}) .Ve .SS "Meson projects" .IX Subsection "Meson projects" For meson projects use: .PP .Vb 2 \& nbd_dep = dependency(\*(Aqlibnbd\*(Aq) \& executable(\*(Aqprog\*(Aq, \*(Aqprog.c\*(Aq, dependencies : [nbd_dep]) .Ve .SH "ENVIRONMENT VARIABLES" .IX Header "ENVIRONMENT VARIABLES" .ie n .IP """HOME""" 4 .el .IP \f(CWHOME\fR 4 .IX Item "HOME" Used in some situations to find TLS certificates. See \&\fBnbd_set_tls_certificates\fR\|(3). .ie n .IP """LIBNBD_DEBUG""" 4 .el .IP \f(CWLIBNBD_DEBUG\fR 4 .IX Item "LIBNBD_DEBUG" If this is set to the exact string \f(CW1\fR when the handle is created then debugging is enabled. See "DEBUGGING MESSAGES" above. .ie n .IP """LOGNAME""" 4 .el .IP \f(CWLOGNAME\fR 4 .IX Item "LOGNAME" The default TLS username. See \fBnbd_set_tls_username\fR\|(3). .SH "SEE ALSO" .IX Header "SEE ALSO" .SS "C API" .IX Subsection "C API" \&\fBnbd_add_meta_context\fR\|(3), \&\fBnbd_aio_block_status\fR\|(3), \&\fBnbd_aio_block_status_64\fR\|(3), \&\fBnbd_aio_block_status_filter\fR\|(3), \&\fBnbd_aio_cache\fR\|(3), \&\fBnbd_aio_command_completed\fR\|(3), \&\fBnbd_aio_connect\fR\|(3), \&\fBnbd_aio_connect_command\fR\|(3), \&\fBnbd_aio_connect_socket\fR\|(3), \&\fBnbd_aio_connect_systemd_socket_activation\fR\|(3), \&\fBnbd_aio_connect_tcp\fR\|(3), \&\fBnbd_aio_connect_unix\fR\|(3), \&\fBnbd_aio_connect_uri\fR\|(3), \&\fBnbd_aio_connect_vsock\fR\|(3), \&\fBnbd_aio_disconnect\fR\|(3), \&\fBnbd_aio_flush\fR\|(3), \&\fBnbd_aio_get_direction\fR\|(3), \&\fBnbd_aio_get_fd\fR\|(3), \&\fBnbd_aio_in_flight\fR\|(3), \&\fBnbd_aio_is_closed\fR\|(3), \&\fBnbd_aio_is_connecting\fR\|(3), \&\fBnbd_aio_is_created\fR\|(3), \&\fBnbd_aio_is_dead\fR\|(3), \&\fBnbd_aio_is_negotiating\fR\|(3), \&\fBnbd_aio_is_processing\fR\|(3), \&\fBnbd_aio_is_ready\fR\|(3), \&\fBnbd_aio_notify_read\fR\|(3), \&\fBnbd_aio_notify_write\fR\|(3), \&\fBnbd_aio_opt_abort\fR\|(3), \&\fBnbd_aio_opt_extended_headers\fR\|(3), \&\fBnbd_aio_opt_go\fR\|(3), \&\fBnbd_aio_opt_info\fR\|(3), \&\fBnbd_aio_opt_list\fR\|(3), \&\fBnbd_aio_opt_list_meta_context\fR\|(3), \&\fBnbd_aio_opt_list_meta_context_queries\fR\|(3), \&\fBnbd_aio_opt_set_meta_context\fR\|(3), \&\fBnbd_aio_opt_set_meta_context_queries\fR\|(3), \&\fBnbd_aio_opt_starttls\fR\|(3), \&\fBnbd_aio_opt_structured_reply\fR\|(3), \&\fBnbd_aio_peek_command_completed\fR\|(3), \&\fBnbd_aio_pread\fR\|(3), \&\fBnbd_aio_pread_structured\fR\|(3), \&\fBnbd_aio_pwrite\fR\|(3), \&\fBnbd_aio_trim\fR\|(3), \&\fBnbd_aio_zero\fR\|(3), \&\fBnbd_block_status\fR\|(3), \&\fBnbd_block_status_64\fR\|(3), \&\fBnbd_block_status_filter\fR\|(3), \&\fBnbd_cache\fR\|(3), \&\fBnbd_can_block_status_payload\fR\|(3), \&\fBnbd_can_cache\fR\|(3), \&\fBnbd_can_df\fR\|(3), \&\fBnbd_can_fast_zero\fR\|(3), \&\fBnbd_can_flush\fR\|(3), \&\fBnbd_can_fua\fR\|(3), \&\fBnbd_can_meta_context\fR\|(3), \&\fBnbd_can_multi_conn\fR\|(3), \&\fBnbd_can_trim\fR\|(3), \&\fBnbd_can_zero\fR\|(3), \&\fBnbd_clear_debug_callback\fR\|(3), \&\fBnbd_clear_meta_contexts\fR\|(3), \&\fBnbd_close\fR\|(3), \&\fBnbd_connect_command\fR\|(3), \&\fBnbd_connect_socket\fR\|(3), \&\fBnbd_connect_systemd_socket_activation\fR\|(3), \&\fBnbd_connect_tcp\fR\|(3), \&\fBnbd_connect_unix\fR\|(3), \&\fBnbd_connect_uri\fR\|(3), \&\fBnbd_connect_vsock\fR\|(3), \&\fBnbd_connection_state\fR\|(3), \&\fBnbd_create\fR\|(3), \&\fBnbd_flush\fR\|(3), \&\fBnbd_get_block_size\fR\|(3), \&\fBnbd_get_canonical_export_name\fR\|(3), \&\fBnbd_get_debug\fR\|(3), \&\fBnbd_get_errno\fR\|(3), \&\fBnbd_get_error\fR\|(3), \&\fBnbd_get_export_description\fR\|(3), \&\fBnbd_get_export_name\fR\|(3), \&\fBnbd_get_extended_headers_negotiated\fR\|(3), \&\fBnbd_get_full_info\fR\|(3), \&\fBnbd_get_handle_name\fR\|(3), \&\fBnbd_get_handshake_flags\fR\|(3), \&\fBnbd_get_meta_context\fR\|(3), \&\fBnbd_get_nr_meta_contexts\fR\|(3), \&\fBnbd_get_opt_mode\fR\|(3), \&\fBnbd_get_package_name\fR\|(3), \&\fBnbd_get_pread_initialize\fR\|(3), \&\fBnbd_get_private_data\fR\|(3), \&\fBnbd_get_protocol\fR\|(3), \&\fBnbd_get_request_block_size\fR\|(3), \&\fBnbd_get_request_extended_headers\fR\|(3), \&\fBnbd_get_request_meta_context\fR\|(3), \&\fBnbd_get_request_structured_replies\fR\|(3), \&\fBnbd_get_size\fR\|(3), \&\fBnbd_get_socket_activation_name\fR\|(3), \&\fBnbd_get_strict_mode\fR\|(3), \&\fBnbd_get_structured_replies_negotiated\fR\|(3), \&\fBnbd_get_tls\fR\|(3), \&\fBnbd_get_tls_negotiated\fR\|(3), \&\fBnbd_get_tls_username\fR\|(3), \&\fBnbd_get_tls_verify_peer\fR\|(3), \&\fBnbd_get_uri\fR\|(3), \&\fBnbd_get_version\fR\|(3), \&\fBnbd_is_read_only\fR\|(3), \&\fBnbd_is_rotational\fR\|(3), \&\fBnbd_kill_subprocess\fR\|(3), \&\fBnbd_opt_abort\fR\|(3), \&\fBnbd_opt_extended_headers\fR\|(3), \&\fBnbd_opt_go\fR\|(3), \&\fBnbd_opt_info\fR\|(3), \&\fBnbd_opt_list\fR\|(3), \&\fBnbd_opt_list_meta_context\fR\|(3), \&\fBnbd_opt_list_meta_context_queries\fR\|(3), \&\fBnbd_opt_set_meta_context\fR\|(3), \&\fBnbd_opt_set_meta_context_queries\fR\|(3), \&\fBnbd_opt_starttls\fR\|(3), \&\fBnbd_opt_structured_reply\fR\|(3), \&\fBnbd_poll\fR\|(3), \&\fBnbd_poll2\fR\|(3), \&\fBnbd_pread\fR\|(3), \&\fBnbd_pread_structured\fR\|(3), \&\fBnbd_pwrite\fR\|(3), \&\fBnbd_set_debug\fR\|(3), \&\fBnbd_set_debug_callback\fR\|(3), \&\fBnbd_set_export_name\fR\|(3), \&\fBnbd_set_full_info\fR\|(3), \&\fBnbd_set_handle_name\fR\|(3), \&\fBnbd_set_handshake_flags\fR\|(3), \&\fBnbd_set_opt_mode\fR\|(3), \&\fBnbd_set_pread_initialize\fR\|(3), \&\fBnbd_set_private_data\fR\|(3), \&\fBnbd_set_request_block_size\fR\|(3), \&\fBnbd_set_request_extended_headers\fR\|(3), \&\fBnbd_set_request_meta_context\fR\|(3), \&\fBnbd_set_request_structured_replies\fR\|(3), \&\fBnbd_set_socket_activation_name\fR\|(3), \&\fBnbd_set_strict_mode\fR\|(3), \&\fBnbd_set_tls\fR\|(3), \&\fBnbd_set_tls_certificates\fR\|(3), \&\fBnbd_set_tls_psk_file\fR\|(3), \&\fBnbd_set_tls_username\fR\|(3), \&\fBnbd_set_tls_verify_peer\fR\|(3), \&\fBnbd_set_uri_allow_local_file\fR\|(3), \&\fBnbd_set_uri_allow_tls\fR\|(3), \&\fBnbd_set_uri_allow_transports\fR\|(3), \&\fBnbd_shutdown\fR\|(3), \&\fBnbd_stats_bytes_received\fR\|(3), \&\fBnbd_stats_bytes_sent\fR\|(3), \&\fBnbd_stats_chunks_received\fR\|(3), \&\fBnbd_stats_chunks_sent\fR\|(3), \&\fBnbd_supports_tls\fR\|(3), \&\fBnbd_supports_uri\fR\|(3), \&\fBnbd_supports_vsock\fR\|(3), \&\fBnbd_trim\fR\|(3), \&\fBnbd_zero\fR\|(3). .SS Servers .IX Subsection "Servers" \&\fBnbdkit\fR\|(1), \&\fBnbd\-server\fR\|(1), \&\fBqemu\-nbd\fR\|(8). .SS "Encryption tools" .IX Subsection "Encryption tools" \&\fBcerttool\fR\|(1), \&\fBnbdkit\-tls\fR\|(1), \&\fBpsktool\fR\|(1). .SS Standards .IX Subsection "Standards" https://github.com/NetworkBlockDevice/nbd/blob/master/doc/proto.md, https://github.com/NetworkBlockDevice/nbd/blob/master/doc/uri.md. .SS "Release notes" .IX Subsection "Release notes" \&\fBlibnbd\-release\-notes\-1.20\fR\|(1), \&\fBlibnbd\-release\-notes\-1.18\fR\|(1), \&\fBlibnbd\-release\-notes\-1.16\fR\|(1), \&\fBlibnbd\-release\-notes\-1.14\fR\|(1), \&\fBlibnbd\-release\-notes\-1.12\fR\|(1), \&\fBlibnbd\-release\-notes\-1.10\fR\|(1), \&\fBlibnbd\-release\-notes\-1.8\fR\|(1), \&\fBlibnbd\-release\-notes\-1.6\fR\|(1), \&\fBlibnbd\-release\-notes\-1.4\fR\|(1), \&\fBlibnbd\-release\-notes\-1.2\fR\|(1). .SS Other .IX Subsection "Other" \&\fBlibnbd\-security\fR\|(3), \&\fBnbdcopy\fR\|(1), \&\fBnbddump\fR\|(1), \&\fBnbdfuse\fR\|(1), \&\fBnbdinfo\fR\|(1), \&\fBnbdsh\fR\|(1), \&\fBnbdublk\fR\|(1), \&\fBqemu\fR\|(1). .SH AUTHORS .IX Header "AUTHORS" Eric Blake .PP Richard W.M. Jones .SH COPYRIGHT .IX Header "COPYRIGHT" Copyright Red Hat .SH LICENSE .IX Header "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. .PP 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. .PP 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