nbd: correctly propagate errors
Before:
    $ ./qemu-io-old
    qemu-io-old> open -r -o file.driver=nbd
    one of path and host must be specified.
    qemu-io-old: can't open device (null): Could not open image: Invalid argument
    $ ./qemu-io-old
    qemu-io-old> open -r -o file.driver=nbd,file.host=foo,file.path=bar
    path and host may not be used at the same time.
    qemu-io-old: can't open device (null): Could not open image: Invalid argument
After:
    $ ./qemu-io
    qemu-io> open -r -o file.driver=nbd
    qemu-io: can't open device (null): one of path and host must be specified.
    $ ./qemu-io
    qemu-io> open -r -o file.driver=nbd,file.host=foo,file.path=bar
    qemu-io: can't open device (null): path and host may not be used at the same time.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
			
			
This commit is contained in:
		
							parent
							
								
									a69d9af449
								
							
						
					
					
						commit
						77e8b9ca64
					
				
							
								
								
									
										34
									
								
								block/nbd.c
								
								
								
								
							
							
						
						
									
										34
									
								
								block/nbd.c
								
								
								
								
							| 
						 | 
					@ -188,19 +188,18 @@ out:
 | 
				
			||||||
    g_free(file);
 | 
					    g_free(file);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int nbd_config(BDRVNBDState *s, QDict *options, char **export)
 | 
					static void nbd_config(BDRVNBDState *s, QDict *options, char **export,
 | 
				
			||||||
 | 
					                       Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Error *local_err = NULL;
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (qdict_haskey(options, "path") == qdict_haskey(options, "host")) {
 | 
					    if (qdict_haskey(options, "path") == qdict_haskey(options, "host")) {
 | 
				
			||||||
        if (qdict_haskey(options, "path")) {
 | 
					        if (qdict_haskey(options, "path")) {
 | 
				
			||||||
            qerror_report(ERROR_CLASS_GENERIC_ERROR, "path and host may not "
 | 
					            error_setg(errp, "path and host may not be used at the same time.");
 | 
				
			||||||
                          "be used at the same time.");
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            qerror_report(ERROR_CLASS_GENERIC_ERROR, "one of path and host "
 | 
					            error_setg(errp, "one of path and host must be specified.");
 | 
				
			||||||
                          "must be specified.");
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return -EINVAL;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->client.is_unix = qdict_haskey(options, "path");
 | 
					    s->client.is_unix = qdict_haskey(options, "path");
 | 
				
			||||||
| 
						 | 
					@ -209,9 +208,8 @@ static int nbd_config(BDRVNBDState *s, QDict *options, char **export)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_opts_absorb_qdict(s->socket_opts, options, &local_err);
 | 
					    qemu_opts_absorb_qdict(s->socket_opts, options, &local_err);
 | 
				
			||||||
    if (local_err) {
 | 
					    if (local_err) {
 | 
				
			||||||
        qerror_report_err(local_err);
 | 
					        error_propagate(errp, local_err);
 | 
				
			||||||
        error_free(local_err);
 | 
					        return;
 | 
				
			||||||
        return -EINVAL;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!qemu_opt_get(s->socket_opts, "port")) {
 | 
					    if (!qemu_opt_get(s->socket_opts, "port")) {
 | 
				
			||||||
| 
						 | 
					@ -222,19 +220,17 @@ static int nbd_config(BDRVNBDState *s, QDict *options, char **export)
 | 
				
			||||||
    if (*export) {
 | 
					    if (*export) {
 | 
				
			||||||
        qdict_del(options, "export");
 | 
					        qdict_del(options, "export");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int nbd_establish_connection(BlockDriverState *bs)
 | 
					static int nbd_establish_connection(BlockDriverState *bs, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BDRVNBDState *s = bs->opaque;
 | 
					    BDRVNBDState *s = bs->opaque;
 | 
				
			||||||
    int sock;
 | 
					    int sock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->client.is_unix) {
 | 
					    if (s->client.is_unix) {
 | 
				
			||||||
        sock = unix_socket_outgoing(qemu_opt_get(s->socket_opts, "path"));
 | 
					        sock = unix_connect_opts(s->socket_opts, errp, NULL, NULL);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        sock = tcp_socket_outgoing_opts(s->socket_opts);
 | 
					        sock = inet_connect_opts(s->socket_opts, errp, NULL, NULL);
 | 
				
			||||||
        if (sock >= 0) {
 | 
					        if (sock >= 0) {
 | 
				
			||||||
            socket_set_nodelay(sock);
 | 
					            socket_set_nodelay(sock);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -255,17 +251,19 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags,
 | 
				
			||||||
    BDRVNBDState *s = bs->opaque;
 | 
					    BDRVNBDState *s = bs->opaque;
 | 
				
			||||||
    char *export = NULL;
 | 
					    char *export = NULL;
 | 
				
			||||||
    int result, sock;
 | 
					    int result, sock;
 | 
				
			||||||
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Pop the config into our state object. Exit if invalid. */
 | 
					    /* Pop the config into our state object. Exit if invalid. */
 | 
				
			||||||
    result = nbd_config(s, options, &export);
 | 
					    nbd_config(s, options, &export, &local_err);
 | 
				
			||||||
    if (result != 0) {
 | 
					    if (local_err) {
 | 
				
			||||||
        return result;
 | 
					        error_propagate(errp, local_err);
 | 
				
			||||||
 | 
					        return -EINVAL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* establish TCP connection, return error if it fails
 | 
					    /* establish TCP connection, return error if it fails
 | 
				
			||||||
     * TODO: Configurable retry-until-timeout behaviour.
 | 
					     * TODO: Configurable retry-until-timeout behaviour.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    sock = nbd_establish_connection(bs);
 | 
					    sock = nbd_establish_connection(bs, errp);
 | 
				
			||||||
    if (sock < 0) {
 | 
					    if (sock < 0) {
 | 
				
			||||||
        return sock;
 | 
					        return sock;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,6 @@ enum {
 | 
				
			||||||
ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read);
 | 
					ssize_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read);
 | 
				
			||||||
int tcp_socket_incoming(const char *address, uint16_t port);
 | 
					int tcp_socket_incoming(const char *address, uint16_t port);
 | 
				
			||||||
int tcp_socket_incoming_spec(const char *address_and_port);
 | 
					int tcp_socket_incoming_spec(const char *address_and_port);
 | 
				
			||||||
int tcp_socket_outgoing_opts(QemuOpts *opts);
 | 
					 | 
				
			||||||
int unix_socket_outgoing(const char *path);
 | 
					int unix_socket_outgoing(const char *path);
 | 
				
			||||||
int unix_socket_incoming(const char *path);
 | 
					int unix_socket_incoming(const char *path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								nbd.c
								
								
								
								
							
							
						
						
									
										12
									
								
								nbd.c
								
								
								
								
							| 
						 | 
					@ -199,18 +199,6 @@ static void combine_addr(char *buf, size_t len, const char* address,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int tcp_socket_outgoing_opts(QemuOpts *opts)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    Error *local_err = NULL;
 | 
					 | 
				
			||||||
    int fd = inet_connect_opts(opts, &local_err, NULL, NULL);
 | 
					 | 
				
			||||||
    if (local_err != NULL) {
 | 
					 | 
				
			||||||
        qerror_report_err(local_err);
 | 
					 | 
				
			||||||
        error_free(local_err);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return fd;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int tcp_socket_incoming(const char *address, uint16_t port)
 | 
					int tcp_socket_incoming(const char *address, uint16_t port)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    char address_and_port[128];
 | 
					    char address_and_port[128];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -231,8 +231,7 @@ Testing: -drive driver=file
 | 
				
			||||||
QEMU_PROG: -drive driver=file: could not open disk image ide0-hd0: The 'file' block driver requires a file name
 | 
					QEMU_PROG: -drive driver=file: could not open disk image ide0-hd0: The 'file' block driver requires a file name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Testing: -drive driver=nbd
 | 
					Testing: -drive driver=nbd
 | 
				
			||||||
QEMU_PROG: -drive driver=nbd: one of path and host must be specified.
 | 
					QEMU_PROG: -drive driver=nbd: could not open disk image ide0-hd0: one of path and host must be specified.
 | 
				
			||||||
QEMU_PROG: -drive driver=nbd: could not open disk image ide0-hd0: Could not open image: Invalid argument
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Testing: -drive driver=raw
 | 
					Testing: -drive driver=raw
 | 
				
			||||||
QEMU_PROG: -drive driver=raw: could not open disk image ide0-hd0: Can't use 'raw' as a block driver for the protocol level
 | 
					QEMU_PROG: -drive driver=raw: could not open disk image ide0-hd0: Can't use 'raw' as a block driver for the protocol level
 | 
				
			||||||
| 
						 | 
					@ -241,8 +240,7 @@ Testing: -drive file.driver=file
 | 
				
			||||||
QEMU_PROG: -drive file.driver=file: could not open disk image ide0-hd0: The 'file' block driver requires a file name
 | 
					QEMU_PROG: -drive file.driver=file: could not open disk image ide0-hd0: The 'file' block driver requires a file name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Testing: -drive file.driver=nbd
 | 
					Testing: -drive file.driver=nbd
 | 
				
			||||||
QEMU_PROG: -drive file.driver=nbd: one of path and host must be specified.
 | 
					QEMU_PROG: -drive file.driver=nbd: could not open disk image ide0-hd0: one of path and host must be specified.
 | 
				
			||||||
QEMU_PROG: -drive file.driver=nbd: could not open disk image ide0-hd0: Could not open image: Invalid argument
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Testing: -drive file.driver=raw
 | 
					Testing: -drive file.driver=raw
 | 
				
			||||||
QEMU_PROG: -drive file.driver=raw: could not open disk image ide0-hd0: Can't use 'raw' as a block driver for the protocol level
 | 
					QEMU_PROG: -drive file.driver=raw: could not open disk image ide0-hd0: Can't use 'raw' as a block driver for the protocol level
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue