nbd_opt_go - Man Page

end negotiation and move on to using an export

Synopsis

​ #include <libnbd.h>
​
​ int nbd_opt_go (
​       struct nbd_handle *h
​     );

Description

Request that the server finish negotiation and move on to serving the export previously specified by the most recent nbd_set_export_name(3) or nbd_connect_uri(3).  This can only be used if ​nbd_set_opt_mode(3) enabled option mode.

By default, libnbd will automatically request all meta contexts registered by nbd_add_meta_context(3) as part of this call; but this can be suppressed with nbd_set_request_meta_context(3), particularly if nbd_opt_set_meta_context(3) was used earlier in the negotiation sequence.

If this fails, the server may still be in negotiation, where it is possible to attempt another option such as a different export name; although older servers will instead have killed the connection.

Return Value

If the call is successful the function returns 0.

Errors

On error -1 is returned.

Refer to "ERROR HANDLING" in libnbd(3) for how to get further details of the error.

The following parameters must not be NULL: h. For more information see "Non-NULL parameters" in libnbd(3).

Handle State

nbd_opt_go can be called when the handle is in the following state:

​ ┌─────────────────────────────────────┬─────────────────────────┐
​ │ Handle created, before connecting   │ ❌ error                │
​ │ Connecting                          │ ❌ error                │
​ │ Connecting & handshaking (opt_mode) │ ✅ allowed              │
​ │ Connected to the server             │ ❌ error                │
​ │ Connection shut down                │ ❌ error                │
​ │ Handle dead                         │ ❌ error                │
​ └─────────────────────────────────────┴─────────────────────────┘

Version

This function first appeared in libnbd 1.4.

If you need to test if this function is available at compile time check if the following macro is defined:

​ #define LIBNBD_HAVE_NBD_OPT_GO 1

Example

This example is also available as examples/list-exports.c in the libnbd source code.

​ /* This example shows how to list NBD exports.
​  *
​  * To test this with qemu-nbd:
​  *   $ qemu-nbd -x "hello" -t -k /tmp/sock disk.img
​  *   $ ./run examples/list-exports /tmp/sock
​  *   [0] hello
​  *   Which export to connect to (-1 to quit)? 0
​  *   Connecting to hello ...
​  *   /tmp/sock: hello: size = 2048 bytes
​  *
​  * To test this with nbdkit (requires 1.22):
​  *   $ nbdkit -U /tmp/sock sh - <<\EOF
​  *   case $1 in
​  *     list_exports) echo NAMES; echo foo; echo foobar ;;
​  *     open) echo "$3" ;;
​  *     get_size) echo "$2" | wc -c ;;
​  *     pread) echo "$2" | dd bs=1 skip=$4 count=$3 ;;
​  *     *) exit 2 ;;
​  *   esac
​  *   EOF
​  *   $ ./run examples/list-exports /tmp/sock
​  *   [0] foo
​  *   [1] foobar
​  *   Which export to connect to (-1 to quit)? 1
​  *   Connecting to foobar ...
​  *   /tmp/sock: foobar: size = 7 bytes
​  */
​
​ #include <stdio.h>
​ #include <stdlib.h>
​ #include <stdbool.h>
​ #include <stdint.h>
​ #include <string.h>
​ #include <inttypes.h>
​ #include <errno.h>
​
​ #include <libnbd.h>
​
​ struct export_list {
​   int i;
​   char **names;
​ };
​
​ /* Callback function for nbd_opt_list */
​ static int
​ list_one (void *opaque, const char *name,
​           const char *description)
​ {
​   struct export_list *l = opaque;
​   char **names;
​
​   printf ("[%d] %s\n", l->i, name);
​   if (*description)
​     printf ("  (%s)\n", description);
​   names = realloc (l->names,
​                    (l->i + 1) * sizeof *names);
​   if (!names) {
​     perror ("realloc");
​     exit (EXIT_FAILURE);
​   }
​   names[l->i] = strdup (name);
​   if (!names[l->i]) {
​     perror ("strdup");
​     exit (EXIT_FAILURE);
​   }
​   l->names = names;
​   l->i++;
​   return 0;
​ }
​
​ int
​ main (int argc, char *argv[])
​ {
​   struct nbd_handle *nbd;
​   int i;
​   const char *name;
​   int64_t size;
​   struct export_list list = { 0 };
​
​   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);
​   }
​
​   /* Set opt mode. */
​   nbd_set_opt_mode (nbd, true);
​
​   /* Connect to the NBD server over a
​    * Unix domain socket.  If we did not
​    * end up in option mode, then a
​    * listing is not possible.
​    */
​   if (nbd_connect_unix (nbd, argv[1]) == -1) {
​     fprintf (stderr, "%s\n", nbd_get_error ());
​     exit (EXIT_FAILURE);
​   }
​   if (!nbd_aio_is_negotiating (nbd)) {
​     fprintf (stderr, "Server does not support "
​              "listing exports.\n");
​     exit (EXIT_FAILURE);
​   }
​
​   /* Print the export list. */
​   if (nbd_opt_list (nbd,
​                     (nbd_list_callback) {
​                       .callback = list_one,
​                       .user_data = &list, }) == -1) {
​     fprintf (stderr, "%s\n", nbd_get_error ());
​     exit (EXIT_FAILURE);
​   }
​
​   /* Display the list of exports. */
​   printf ("Which export to connect to? ");
​   if (scanf ("%d", &i) != 1) exit (EXIT_FAILURE);
​   if (i == -1) {
​     if (nbd_opt_abort (nbd) == -1) {
​       fprintf (stderr, "%s\n", nbd_get_error ());
​       exit (EXIT_FAILURE);
​     }
​     nbd_close (nbd);
​     exit (EXIT_SUCCESS);
​   }
​   if (i < 0 || i >= list.i) {
​     fprintf (stderr, "index %d out of range", i);
​     exit (EXIT_FAILURE);
​   }
​   name = list.names[i];
​   printf ("Connecting to %s ...\n", name);
​
​   /* Resume connecting to the chosen export. */
​   if (nbd_set_export_name (nbd, name) == -1 ||
​       nbd_opt_go (nbd) == -1) {
​     fprintf (stderr, "%s\n", nbd_get_error ());
​     exit (EXIT_FAILURE);
​   }
​   if (!nbd_aio_is_ready (nbd)) {
​     fprintf (stderr, "server closed early\n");
​     exit (EXIT_FAILURE);
​   }
​
​   /* Read the size in bytes and print it. */
​   size = nbd_get_size (nbd);
​   if (size == -1) {
​     fprintf (stderr, "%s\n", nbd_get_error ());
​     exit (EXIT_FAILURE);
​   }
​   printf ("%s: %s: size = %" PRIi64 " bytes\n",
​           argv[1], name, size);
​
​   /* Close the libnbd handle. */
​   nbd_close (nbd);
​
​   for (i = 0; i < list.i; i++)
​     free (list.names[i]);
​   free (list.names);
​
​   exit (EXIT_SUCCESS);
​ }

See Also

nbd_add_meta_context(3), ​nbd_aio_opt_go(3), ​nbd_connect_uri(3), ​nbd_create(3), ​nbd_opt_abort(3), ​nbd_opt_info(3), ​nbd_opt_set_meta_context(3), ​nbd_set_export_name(3), ​nbd_set_opt_mode(3), ​nbd_set_request_meta_context(3), ​libnbd(3).

Authors

Eric Blake

Richard W.M. Jones

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

Info

2026-10-03 libnbd-1.25.7