diff mbox series

[08/14] nbd/client: Refactor nbd_receive_list()

Message ID 20181130220344.3350618-9-eblake@redhat.com
State New
Headers show
Series nbd: add qemu-nbd --list | expand

Commit Message

Eric Blake Nov. 30, 2018, 10:03 p.m. UTC
Add some parameters to make this function reusable in upcoming
export listing, where we will want to capture the name and
description rather than compare against a user-supplied name.
No change in semantics to the existing caller.

Signed-off-by: Eric Blake <eblake@redhat.com>
---
 nbd/client.c | 66 +++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 47 insertions(+), 19 deletions(-)

Comments

Richard W.M. Jones Dec. 1, 2018, 10:37 a.m. UTC | #1
On Fri, Nov 30, 2018 at 04:03:37PM -0600, Eric Blake wrote:
> Add some parameters to make this function reusable in upcoming
> export listing, where we will want to capture the name and
> description rather than compare against a user-supplied name.
> No change in semantics to the existing caller.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
>  nbd/client.c | 66 +++++++++++++++++++++++++++++++++++++---------------
>  1 file changed, 47 insertions(+), 19 deletions(-)
> 
> diff --git a/nbd/client.c b/nbd/client.c
> index 1dc8f83e19a..27785c55d0a 100644
> --- a/nbd/client.c
> +++ b/nbd/client.c
> @@ -232,18 +232,21 @@ static int nbd_handle_reply_err(QIOChannel *ioc, NBDOptionReply *reply,
>      return result;
>  }
> 
> -/* Process another portion of the NBD_OPT_LIST reply.  Set *@match if
> - * the current reply matches @want or if the server does not support
> - * NBD_OPT_LIST, otherwise leave @match alone.  Return 0 if iteration
> - * is complete, positive if more replies are expected, or negative
> - * with @errp set if an unrecoverable error occurred. */
> +/* Process another portion of the NBD_OPT_LIST reply.  If @want, then
> + * set *@match if the current reply matches @want or if the server
> + * does not support NBD_OPT_LIST, otherwise leave @match alone.
> + * Otherwise, @nameout and @description are malloc'd to contain
> + * NUL-terminated copies of the reply.  Return 0 if iteration is
> + * complete, positive if more replies are expected, or negative with
> + * @errp set if an unrecoverable error occurred. */
>  static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
> -                            Error **errp)
> +                            char **nameout, char **description, Error **errp)
>  {
>      NBDOptionReply reply;
>      uint32_t len;
>      uint32_t namelen;
> -    char name[NBD_MAX_NAME_SIZE + 1];
> +    char array[NBD_MAX_NAME_SIZE + 1];
> +    char *name = array;
>      int error;
> 
>      if (nbd_receive_option_reply(ioc, NBD_OPT_LIST, &reply, errp) < 0) {
> @@ -253,7 +256,12 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
>      if (error <= 0) {
>          /* The server did not support NBD_OPT_LIST, so set *match on
>           * the assumption that any name will be accepted.  */
> -        *match = true;
> +        if (want) {
> +            *match = true;
> +        } else if (!error) {
> +            error_setg(errp, "Server does not support export lists");
> +            error = -1;
> +        }
>          return error;
>      }
>      len = reply.length;
> @@ -290,30 +298,49 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
>          nbd_send_opt_abort(ioc);
>          return -1;
>      }
> -    if (namelen != strlen(want)) {
> -        if (nbd_drop(ioc, len, errp) < 0) {
> -            error_prepend(errp,
> -                          "failed to skip export name with wrong length: ");
> -            nbd_send_opt_abort(ioc);
> -            return -1;
> +    if (want) {
> +        if (namelen != strlen(want)) {
> +            if (nbd_drop(ioc, len, errp) < 0) {
> +                error_prepend(errp,
> +                              "failed to skip export name with wrong length: ");
> +                nbd_send_opt_abort(ioc);
> +                return -1;
> +            }
> +            return 1;
>          }
> -        return 1;
> +        assert(namelen < sizeof(array));
> +    } else {
> +        assert(nameout);
> +        *nameout = name = g_new(char, namelen + 1);
>      }
> 
> -    assert(namelen < sizeof(name));
>      if (nbd_read(ioc, name, namelen, errp) < 0) {
>          error_prepend(errp, "failed to read export name: ");
>          nbd_send_opt_abort(ioc);
> +        if (!want) {
> +            free(name);
> +        }
>          return -1;
>      }
>      name[namelen] = '\0';
>      len -= namelen;
> -    if (nbd_drop(ioc, len, errp) < 0) {
> +    if (!want) {
> +        assert(description);
> +        *description = g_new(char, len + 1);
> +        if (nbd_read(ioc, *description, len, errp) < 0) {
> +            error_prepend(errp, "failed to read export description: ");
> +            nbd_send_opt_abort(ioc);
> +            free(name);
> +            free(*description);
> +            return -1;
> +        }
> +        (*description)[len] = '\0';
> +    } else if (nbd_drop(ioc, len, errp) < 0) {
>          error_prepend(errp, "failed to read export description: ");
>          nbd_send_opt_abort(ioc);
>          return -1;
>      }
> -    if (!strcmp(name, want)) {
> +    if (want && !strcmp(name, want)) {
>          *match = true;
>      }
>      return 1;
> @@ -498,7 +525,8 @@ static int nbd_receive_query_exports(QIOChannel *ioc,
>      }
> 
>      while (1) {
> -        int ret = nbd_receive_list(ioc, wantname, &foundExport, errp);
> +        int ret = nbd_receive_list(ioc, wantname, &foundExport,
> +                                   NULL, NULL, errp);
> 
>          if (ret < 0) {
>              /* Server gave unexpected reply */

I found this patch a lot easier to review once I started to use the
‘git show -w’ option.  The changes look like a reasonable adaptation
of the function, and the only consumer of the function (at this point)
is unaffected, so:

Reviewed-by: Richard W.M. Jones <rjones@redhat.com>

Rich.
Vladimir Sementsov-Ogievskiy Dec. 6, 2018, 2:18 p.m. UTC | #2
01.12.2018 1:03, Eric Blake wrote:
> Add some parameters to make this function reusable in upcoming
> export listing, where we will want to capture the name and
> description rather than compare against a user-supplied name.
> No change in semantics to the existing caller.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
>   nbd/client.c | 66 +++++++++++++++++++++++++++++++++++++---------------
>   1 file changed, 47 insertions(+), 19 deletions(-)
> 
> diff --git a/nbd/client.c b/nbd/client.c
> index 1dc8f83e19a..27785c55d0a 100644
> --- a/nbd/client.c
> +++ b/nbd/client.c
> @@ -232,18 +232,21 @@ static int nbd_handle_reply_err(QIOChannel *ioc, NBDOptionReply *reply,
>       return result;
>   }
> 
> -/* Process another portion of the NBD_OPT_LIST reply.  Set *@match if
> - * the current reply matches @want or if the server does not support
> - * NBD_OPT_LIST, otherwise leave @match alone.  Return 0 if iteration
> - * is complete, positive if more replies are expected, or negative
> - * with @errp set if an unrecoverable error occurred. */
> +/* Process another portion of the NBD_OPT_LIST reply.  If @want, then
> + * set *@match if the current reply matches @want or if the server
> + * does not support NBD_OPT_LIST, otherwise leave @match alone.
> + * Otherwise, @nameout and @description are malloc'd to contain

what this "otherwise" referred to?

upd: aha, after rereading, I understood that it relates to the very first
If, and the whole thing became clear. Hmm, I'm okay with this now, but it
may be still worth some simplifying.

> + * NUL-terminated copies of the reply.

You didn't say anything about @match in "Otherwise" branch

   Return 0 if iteration is

however, "iterations is complete" may differ for @want/!@want cases

> + * complete, positive if more replies are expected, or negative with
> + * @errp set if an unrecoverable error occurred. */
>   static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
> -                            Error **errp)
> +                            char **nameout, char **description, Error **errp)
>   {
>       NBDOptionReply reply;
>       uint32_t len;
>       uint32_t namelen;
> -    char name[NBD_MAX_NAME_SIZE + 1];
> +    char array[NBD_MAX_NAME_SIZE + 1];
> +    char *name = array;
>       int error;
> 
>       if (nbd_receive_option_reply(ioc, NBD_OPT_LIST, &reply, errp) < 0) {
> @@ -253,7 +256,12 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
>       if (error <= 0) {
>           /* The server did not support NBD_OPT_LIST, so set *match on
>            * the assumption that any name will be accepted.  */
> -        *match = true;
> +        if (want) {
> +            *match = true;
> +        } else if (!error) {
> +            error_setg(errp, "Server does not support export lists");
> +            error = -1;
> +        }
>           return error;
>       }
>       len = reply.length;
> @@ -290,30 +298,49 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
>           nbd_send_opt_abort(ioc);
>           return -1;
>       }
> -    if (namelen != strlen(want)) {
> -        if (nbd_drop(ioc, len, errp) < 0) {
> -            error_prepend(errp,
> -                          "failed to skip export name with wrong length: ");
> -            nbd_send_opt_abort(ioc);
> -            return -1;
> +    if (want) {
> +        if (namelen != strlen(want)) {
> +            if (nbd_drop(ioc, len, errp) < 0) {
> +                error_prepend(errp,
> +                              "failed to skip export name with wrong length: ");
> +                nbd_send_opt_abort(ioc);
> +                return -1;
> +            }
> +            return 1;
>           }
> -        return 1;
> +        assert(namelen < sizeof(array));
> +    } else {
> +        assert(nameout);

this assert looks a bit redundant, if nameout is 0, next line will abort not less clearly

> +        *nameout = name = g_new(char, namelen + 1);

We should check namelen <= NBD_MAX_NAME_SIZE before it, I think.

>       }
> 
> -    assert(namelen < sizeof(name));
>       if (nbd_read(ioc, name, namelen, errp) < 0) {
>           error_prepend(errp, "failed to read export name: ");
>           nbd_send_opt_abort(ioc);
> +        if (!want) {
> +            free(name);

g_free

> +        }
>           return -1;
>       }
>       name[namelen] = '\0';
>       len -= namelen;
> -    if (nbd_drop(ioc, len, errp) < 0) {
> +    if (!want) {
> +        assert(description);

NBD_MAX_NAME_SIZE

> +        *description = g_new(char, len + 1);
> +        if (nbd_read(ioc, *description, len, errp) < 0) {
> +            error_prepend(errp, "failed to read export description: ");
> +            nbd_send_opt_abort(ioc);
> +            free(name);
> +            free(*description);

g_free

> +            return -1;
> +        }
> +        (*description)[len] = '\0';
> +    } else if (nbd_drop(ioc, len, errp) < 0) {
>           error_prepend(errp, "failed to read export description: ");
>           nbd_send_opt_abort(ioc);
>           return -1;
>       }
> -    if (!strcmp(name, want)) {
> +    if (want && !strcmp(name, want)) {
>           *match = true;
>       }
>       return 1;

one more thing: on fail path, you finally fill output name and description
with freed pointers. I'd prefer to keep them unchanged in this case, however,
it's a matter of taste.


> @@ -498,7 +525,8 @@ static int nbd_receive_query_exports(QIOChannel *ioc,
>       }
> 
>       while (1) {
> -        int ret = nbd_receive_list(ioc, wantname, &foundExport, errp);
> +        int ret = nbd_receive_list(ioc, wantname, &foundExport,
> +                                   NULL, NULL, errp);
> 
>           if (ret < 0) {
>               /* Server gave unexpected reply */
>
Eric Blake Dec. 6, 2018, 4:31 p.m. UTC | #3
On 12/6/18 8:18 AM, Vladimir Sementsov-Ogievskiy wrote:
> 01.12.2018 1:03, Eric Blake wrote:
>> Add some parameters to make this function reusable in upcoming
>> export listing, where we will want to capture the name and
>> description rather than compare against a user-supplied name.
>> No change in semantics to the existing caller.
>>
>> Signed-off-by: Eric Blake <eblake@redhat.com>
>> ---
>>    nbd/client.c | 66 +++++++++++++++++++++++++++++++++++++---------------
>>    1 file changed, 47 insertions(+), 19 deletions(-)

>> @@ -290,30 +298,49 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
>>            nbd_send_opt_abort(ioc);
>>            return -1;
>>        }
>> -    if (namelen != strlen(want)) {
>> -        if (nbd_drop(ioc, len, errp) < 0) {
>> -            error_prepend(errp,
>> -                          "failed to skip export name with wrong length: ");
>> -            nbd_send_opt_abort(ioc);
>> -            return -1;
>> +    if (want) {
>> +        if (namelen != strlen(want)) {
>> +            if (nbd_drop(ioc, len, errp) < 0) {
>> +                error_prepend(errp,
>> +                              "failed to skip export name with wrong length: ");
>> +                nbd_send_opt_abort(ioc);
>> +                return -1;
>> +            }
>> +            return 1;
>>            }
>> -        return 1;
>> +        assert(namelen < sizeof(array));
>> +    } else {
>> +        assert(nameout);
> 
> this assert looks a bit redundant, if nameout is 0, next line will abort not less clearly
> 
>> +        *nameout = name = g_new(char, namelen + 1);
> 
> We should check namelen <= NBD_MAX_NAME_SIZE before it, I think.

Why? We already validated that the overall option is not too large, and 
even if the resulting name from the server is larger than 
NBD_MAX_NAME_SIZE, it's still nice to report that name to the client for 
'qemu-nbd --list'.  And these days, we only call nbd_receive_list if a 
server lacked NBD_OPT_GO, which is getting rarer and rarer, so 
micro-optimizing a rare case to avoid a large malloc isn't going to make 
a noticeable difference.

> 
>>        }
>>
>> -    assert(namelen < sizeof(name));
>>        if (nbd_read(ioc, name, namelen, errp) < 0) {
>>            error_prepend(errp, "failed to read export name: ");
>>            nbd_send_opt_abort(ioc);
>> +        if (!want) {
>> +            free(name);
> 
> g_free
> 
>> +        }
>>            return -1;
>>        }
>>        name[namelen] = '\0';
>>        len -= namelen;
>> -    if (nbd_drop(ioc, len, errp) < 0) {
>> +    if (!want) {
>> +        assert(description);
> 
> NBD_MAX_NAME_SIZE

The description is not bound by NBD_MAX_NAME_SIZE.  The NBD protocol 
DOES document a maximum string size (4k), but we are (so far) not 
actually honoring that limit (our choice for NBD_MAX_NAME_SIZE is 256, 
which is smaller than the NBD protocol limit).

> 
>> +        *description = g_new(char, len + 1);
>> +        if (nbd_read(ioc, *description, len, errp) < 0) {
>> +            error_prepend(errp, "failed to read export description: ");
>> +            nbd_send_opt_abort(ioc);
>> +            free(name);
>> +            free(*description);
> 
> g_free
> 
>> +            return -1;
>> +        }
>> +        (*description)[len] = '\0';
>> +    } else if (nbd_drop(ioc, len, errp) < 0) {
>>            error_prepend(errp, "failed to read export description: ");
>>            nbd_send_opt_abort(ioc);
>>            return -1;
>>        }
>> -    if (!strcmp(name, want)) {
>> +    if (want && !strcmp(name, want)) {
>>            *match = true;
>>        }
>>        return 1;
> 
> one more thing: on fail path, you finally fill output name and description
> with freed pointers. I'd prefer to keep them unchanged in this case, however,
> it's a matter of taste.

Okay, I'll try and be more careful in v2 about not altering the callers 
pointers on failure.
Vladimir Sementsov-Ogievskiy Dec. 6, 2018, 5:03 p.m. UTC | #4
06.12.2018 19:31, Eric Blake wrote:
> On 12/6/18 8:18 AM, Vladimir Sementsov-Ogievskiy wrote:
>> 01.12.2018 1:03, Eric Blake wrote:
>>> Add some parameters to make this function reusable in upcoming
>>> export listing, where we will want to capture the name and
>>> description rather than compare against a user-supplied name.
>>> No change in semantics to the existing caller.
>>>
>>> Signed-off-by: Eric Blake <eblake@redhat.com>
>>> ---
>>>    nbd/client.c | 66 +++++++++++++++++++++++++++++++++++++---------------
>>>    1 file changed, 47 insertions(+), 19 deletions(-)
> 
>>> @@ -290,30 +298,49 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
>>>            nbd_send_opt_abort(ioc);
>>>            return -1;
>>>        }
>>> -    if (namelen != strlen(want)) {
>>> -        if (nbd_drop(ioc, len, errp) < 0) {
>>> -            error_prepend(errp,
>>> -                          "failed to skip export name with wrong length: ");
>>> -            nbd_send_opt_abort(ioc);
>>> -            return -1;
>>> +    if (want) {
>>> +        if (namelen != strlen(want)) {
>>> +            if (nbd_drop(ioc, len, errp) < 0) {
>>> +                error_prepend(errp,
>>> +                              "failed to skip export name with wrong length: ");
>>> +                nbd_send_opt_abort(ioc);
>>> +                return -1;
>>> +            }
>>> +            return 1;
>>>            }
>>> -        return 1;
>>> +        assert(namelen < sizeof(array));
>>> +    } else {
>>> +        assert(nameout);
>>
>> this assert looks a bit redundant, if nameout is 0, next line will abort not less clearly
>>
>>> +        *nameout = name = g_new(char, namelen + 1);
>>
>> We should check namelen <= NBD_MAX_NAME_SIZE before it, I think.
> 
> Why? We already validated

Ah, than OK, the worst case is ~ NBD_MAX_BUFFER_SIZE (32M), not 4G. Missed that :(

  that the overall option is not too large, and even if the resulting name from the server is larger than NBD_MAX_NAME_SIZE, it's still nice to report that name to the client for 'qemu-nbd --list'.  And these days, we only call nbd_receive_list if a server lacked NBD_OPT_GO, which is getting rarer and rarer, so micro-optimizing a rare case to avoid a large malloc isn't going to make a noticeable difference.
> 
>>
>>>        }
>>>
>>> -    assert(namelen < sizeof(name));
>>>        if (nbd_read(ioc, name, namelen, errp) < 0) {
>>>            error_prepend(errp, "failed to read export name: ");
>>>            nbd_send_opt_abort(ioc);
>>> +        if (!want) {
>>> +            free(name);
>>
>> g_free
>>
>>> +        }
>>>            return -1;
>>>        }
>>>        name[namelen] = '\0';
>>>        len -= namelen;
>>> -    if (nbd_drop(ioc, len, errp) < 0) {
>>> +    if (!want) {
>>> +        assert(description);
>>
>> NBD_MAX_NAME_SIZE
> 
> The description is not bound by NBD_MAX_NAME_SIZE.  The NBD protocol DOES document a maximum string size (4k), but we are (so far) not actually honoring that limit (our choice for NBD_MAX_NAME_SIZE is 256, which is smaller than the NBD protocol limit).
> 

Ohm, yes, you are right :(. Too much reviewing, I should stop and make some patches :)

>>
>>> +        *description = g_new(char, len + 1);
>>> +        if (nbd_read(ioc, *description, len, errp) < 0) {
>>> +            error_prepend(errp, "failed to read export description: ");
>>> +            nbd_send_opt_abort(ioc);
>>> +            free(name);
>>> +            free(*description);
>>
>> g_free
>>
>>> +            return -1;
>>> +        }
>>> +        (*description)[len] = '\0';
>>> +    } else if (nbd_drop(ioc, len, errp) < 0) {
>>>            error_prepend(errp, "failed to read export description: ");
>>>            nbd_send_opt_abort(ioc);
>>>            return -1;
>>>        }
>>> -    if (!strcmp(name, want)) {
>>> +    if (want && !strcmp(name, want)) {
>>>            *match = true;
>>>        }
>>>        return 1;
>>
>> one more thing: on fail path, you finally fill output name and description
>> with freed pointers. I'd prefer to keep them unchanged in this case, however,
>> it's a matter of taste.
> 
> Okay, I'll try and be more careful in v2 about not altering the callers pointers on failure.
>
diff mbox series

Patch

diff --git a/nbd/client.c b/nbd/client.c
index 1dc8f83e19a..27785c55d0a 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -232,18 +232,21 @@  static int nbd_handle_reply_err(QIOChannel *ioc, NBDOptionReply *reply,
     return result;
 }

-/* Process another portion of the NBD_OPT_LIST reply.  Set *@match if
- * the current reply matches @want or if the server does not support
- * NBD_OPT_LIST, otherwise leave @match alone.  Return 0 if iteration
- * is complete, positive if more replies are expected, or negative
- * with @errp set if an unrecoverable error occurred. */
+/* Process another portion of the NBD_OPT_LIST reply.  If @want, then
+ * set *@match if the current reply matches @want or if the server
+ * does not support NBD_OPT_LIST, otherwise leave @match alone.
+ * Otherwise, @nameout and @description are malloc'd to contain
+ * NUL-terminated copies of the reply.  Return 0 if iteration is
+ * complete, positive if more replies are expected, or negative with
+ * @errp set if an unrecoverable error occurred. */
 static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
-                            Error **errp)
+                            char **nameout, char **description, Error **errp)
 {
     NBDOptionReply reply;
     uint32_t len;
     uint32_t namelen;
-    char name[NBD_MAX_NAME_SIZE + 1];
+    char array[NBD_MAX_NAME_SIZE + 1];
+    char *name = array;
     int error;

     if (nbd_receive_option_reply(ioc, NBD_OPT_LIST, &reply, errp) < 0) {
@@ -253,7 +256,12 @@  static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
     if (error <= 0) {
         /* The server did not support NBD_OPT_LIST, so set *match on
          * the assumption that any name will be accepted.  */
-        *match = true;
+        if (want) {
+            *match = true;
+        } else if (!error) {
+            error_setg(errp, "Server does not support export lists");
+            error = -1;
+        }
         return error;
     }
     len = reply.length;
@@ -290,30 +298,49 @@  static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
         nbd_send_opt_abort(ioc);
         return -1;
     }
-    if (namelen != strlen(want)) {
-        if (nbd_drop(ioc, len, errp) < 0) {
-            error_prepend(errp,
-                          "failed to skip export name with wrong length: ");
-            nbd_send_opt_abort(ioc);
-            return -1;
+    if (want) {
+        if (namelen != strlen(want)) {
+            if (nbd_drop(ioc, len, errp) < 0) {
+                error_prepend(errp,
+                              "failed to skip export name with wrong length: ");
+                nbd_send_opt_abort(ioc);
+                return -1;
+            }
+            return 1;
         }
-        return 1;
+        assert(namelen < sizeof(array));
+    } else {
+        assert(nameout);
+        *nameout = name = g_new(char, namelen + 1);
     }

-    assert(namelen < sizeof(name));
     if (nbd_read(ioc, name, namelen, errp) < 0) {
         error_prepend(errp, "failed to read export name: ");
         nbd_send_opt_abort(ioc);
+        if (!want) {
+            free(name);
+        }
         return -1;
     }
     name[namelen] = '\0';
     len -= namelen;
-    if (nbd_drop(ioc, len, errp) < 0) {
+    if (!want) {
+        assert(description);
+        *description = g_new(char, len + 1);
+        if (nbd_read(ioc, *description, len, errp) < 0) {
+            error_prepend(errp, "failed to read export description: ");
+            nbd_send_opt_abort(ioc);
+            free(name);
+            free(*description);
+            return -1;
+        }
+        (*description)[len] = '\0';
+    } else if (nbd_drop(ioc, len, errp) < 0) {
         error_prepend(errp, "failed to read export description: ");
         nbd_send_opt_abort(ioc);
         return -1;
     }
-    if (!strcmp(name, want)) {
+    if (want && !strcmp(name, want)) {
         *match = true;
     }
     return 1;
@@ -498,7 +525,8 @@  static int nbd_receive_query_exports(QIOChannel *ioc,
     }

     while (1) {
-        int ret = nbd_receive_list(ioc, wantname, &foundExport, errp);
+        int ret = nbd_receive_list(ioc, wantname, &foundExport,
+                                   NULL, NULL, errp);

         if (ret < 0) {
             /* Server gave unexpected reply */