2016-01-14 09:41:02 +01:00
|
|
|
/*
|
|
|
|
* NBD Internal Declarations
|
|
|
|
*
|
|
|
|
* Copyright (C) 2016 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
|
|
* See the COPYING file in the top-level directory.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef NBD_INTERNAL_H
|
|
|
|
#define NBD_INTERNAL_H
|
|
|
|
#include "block/nbd.h"
|
|
|
|
#include "sysemu/block-backend.h"
|
2016-02-10 19:41:11 +01:00
|
|
|
#include "io/channel-tls.h"
|
2016-01-14 09:41:02 +01:00
|
|
|
|
|
|
|
#include "qemu/coroutine.h"
|
2016-02-10 19:41:04 +01:00
|
|
|
#include "qemu/iov.h"
|
2016-01-14 09:41:02 +01:00
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#endif
|
|
|
|
#if defined(__sun__) || defined(__HAIKU__)
|
|
|
|
#include <sys/ioccom.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __linux__
|
|
|
|
#include <linux/fs.h>
|
|
|
|
#endif
|
|
|
|
|
2016-03-15 17:22:36 +01:00
|
|
|
#include "qemu/bswap.h"
|
2016-01-14 09:41:02 +01:00
|
|
|
#include "qemu/queue.h"
|
|
|
|
#include "qemu/main-loop.h"
|
|
|
|
|
|
|
|
/* This is all part of the "official" NBD API.
|
|
|
|
*
|
|
|
|
* The most up-to-date documentation is available at:
|
2016-10-14 20:33:04 +02:00
|
|
|
* https://github.com/yoe/nbd/blob/master/doc/proto.md
|
2016-01-14 09:41:02 +01:00
|
|
|
*/
|
|
|
|
|
nbd: Implement NBD_OPT_GO on client
NBD_OPT_EXPORT_NAME is lousy: per the NBD protocol, any failure
requires the server to close the connection rather than report an
error to us. Therefore, upstream NBD recently added NBD_OPT_GO as
the improved version of the option that does what we want [1]: it
reports sane errors on failures, and on success provides at least
as much info as NBD_OPT_EXPORT_NAME.
[1] https://github.com/NetworkBlockDevice/nbd/blob/extension-info/doc/proto.md
This is a first cut at use of the information types. Note that we
do not need to use NBD_OPT_INFO, and that use of NBD_OPT_GO means
we no longer have to use NBD_OPT_LIST to learn whether a server
requires TLS (this requires servers that gracefully handle unknown
NBD_OPT, many servers prior to qemu 2.5 were buggy, but I have patched
qemu, upstream nbd, and nbdkit in the meantime, in part because of
interoperability testing with this patch). We still fall back to
NBD_OPT_LIST when NBD_OPT_GO is not supported on the server, as it
is still one last chance for a nicer error message. Later patches
will use further info, like NBD_INFO_BLOCK_SIZE.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170707203049.534-8-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-07-07 22:30:47 +02:00
|
|
|
/* Size of all NBD_OPT_*, without payload */
|
2017-07-17 21:26:35 +02:00
|
|
|
#define NBD_REQUEST_SIZE (4 + 2 + 2 + 8 + 8 + 4)
|
nbd: Implement NBD_OPT_GO on client
NBD_OPT_EXPORT_NAME is lousy: per the NBD protocol, any failure
requires the server to close the connection rather than report an
error to us. Therefore, upstream NBD recently added NBD_OPT_GO as
the improved version of the option that does what we want [1]: it
reports sane errors on failures, and on success provides at least
as much info as NBD_OPT_EXPORT_NAME.
[1] https://github.com/NetworkBlockDevice/nbd/blob/extension-info/doc/proto.md
This is a first cut at use of the information types. Note that we
do not need to use NBD_OPT_INFO, and that use of NBD_OPT_GO means
we no longer have to use NBD_OPT_LIST to learn whether a server
requires TLS (this requires servers that gracefully handle unknown
NBD_OPT, many servers prior to qemu 2.5 were buggy, but I have patched
qemu, upstream nbd, and nbdkit in the meantime, in part because of
interoperability testing with this patch). We still fall back to
NBD_OPT_LIST when NBD_OPT_GO is not supported on the server, as it
is still one last chance for a nicer error message. Later patches
will use further info, like NBD_INFO_BLOCK_SIZE.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170707203049.534-8-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-07-07 22:30:47 +02:00
|
|
|
/* Size of all NBD_REP_* sent in answer to most NBD_OPT_*, without payload */
|
2017-07-17 21:26:35 +02:00
|
|
|
#define NBD_REPLY_SIZE (4 + 4 + 8)
|
|
|
|
/* Size of reply to NBD_OPT_EXPORT_NAME */
|
|
|
|
#define NBD_REPLY_EXPORT_NAME_SIZE (8 + 2 + 124)
|
|
|
|
/* Size of oldstyle negotiation */
|
|
|
|
#define NBD_OLDSTYLE_NEGOTIATE_SIZE (8 + 8 + 8 + 4 + 124)
|
nbd: Implement NBD_OPT_GO on client
NBD_OPT_EXPORT_NAME is lousy: per the NBD protocol, any failure
requires the server to close the connection rather than report an
error to us. Therefore, upstream NBD recently added NBD_OPT_GO as
the improved version of the option that does what we want [1]: it
reports sane errors on failures, and on success provides at least
as much info as NBD_OPT_EXPORT_NAME.
[1] https://github.com/NetworkBlockDevice/nbd/blob/extension-info/doc/proto.md
This is a first cut at use of the information types. Note that we
do not need to use NBD_OPT_INFO, and that use of NBD_OPT_GO means
we no longer have to use NBD_OPT_LIST to learn whether a server
requires TLS (this requires servers that gracefully handle unknown
NBD_OPT, many servers prior to qemu 2.5 were buggy, but I have patched
qemu, upstream nbd, and nbdkit in the meantime, in part because of
interoperability testing with this patch). We still fall back to
NBD_OPT_LIST when NBD_OPT_GO is not supported on the server, as it
is still one last chance for a nicer error message. Later patches
will use further info, like NBD_INFO_BLOCK_SIZE.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20170707203049.534-8-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-07-07 22:30:47 +02:00
|
|
|
|
2016-01-14 09:41:02 +01:00
|
|
|
#define NBD_REQUEST_MAGIC 0x25609513
|
|
|
|
#define NBD_REPLY_MAGIC 0x67446698
|
|
|
|
#define NBD_OPTS_MAGIC 0x49484156454F5054LL
|
|
|
|
#define NBD_CLIENT_MAGIC 0x0000420281861253LL
|
2016-10-14 20:33:10 +02:00
|
|
|
#define NBD_REP_MAGIC 0x0003e889045565a9LL
|
2016-01-14 09:41:02 +01:00
|
|
|
|
|
|
|
#define NBD_SET_SOCK _IO(0xab, 0)
|
|
|
|
#define NBD_SET_BLKSIZE _IO(0xab, 1)
|
|
|
|
#define NBD_SET_SIZE _IO(0xab, 2)
|
|
|
|
#define NBD_DO_IT _IO(0xab, 3)
|
|
|
|
#define NBD_CLEAR_SOCK _IO(0xab, 4)
|
|
|
|
#define NBD_CLEAR_QUE _IO(0xab, 5)
|
|
|
|
#define NBD_PRINT_DEBUG _IO(0xab, 6)
|
|
|
|
#define NBD_SET_SIZE_BLOCKS _IO(0xab, 7)
|
|
|
|
#define NBD_DISCONNECT _IO(0xab, 8)
|
|
|
|
#define NBD_SET_TIMEOUT _IO(0xab, 9)
|
|
|
|
#define NBD_SET_FLAGS _IO(0xab, 10)
|
|
|
|
|
|
|
|
/* NBD errors are based on errno numbers, so there is a 1:1 mapping,
|
|
|
|
* but only a limited set of errno values is specified in the protocol.
|
|
|
|
* Everything else is squashed to EINVAL.
|
|
|
|
*/
|
|
|
|
#define NBD_SUCCESS 0
|
|
|
|
#define NBD_EPERM 1
|
|
|
|
#define NBD_EIO 5
|
|
|
|
#define NBD_ENOMEM 12
|
|
|
|
#define NBD_EINVAL 22
|
|
|
|
#define NBD_ENOSPC 28
|
2016-10-14 20:33:16 +02:00
|
|
|
#define NBD_ESHUTDOWN 108
|
2016-01-14 09:41:02 +01:00
|
|
|
|
2017-06-02 17:01:39 +02:00
|
|
|
/* nbd_read_eof
|
2017-08-04 17:14:25 +02:00
|
|
|
* Tries to read @size bytes from @ioc.
|
|
|
|
* Returns 1 on success
|
|
|
|
* 0 on eof, when no data was read (errp is not set)
|
|
|
|
* negative errno on failure (errp is set)
|
nbd: read_sync and friends: return 0 on success
functions read_sync, drop_sync, write_sync, and also
nbd_negotiate_write, nbd_negotiate_read, nbd_negotiate_drop_sync
returns number of processed bytes. But what this number can be,
except requested number of bytes?
Actually, underlying nbd_wr_syncv function returns a value >= 0 and
!= requested_bytes only on eof on read operation. So, firstly, it is
impossible on write (let's add an assert) and on read it actually
means, that communication is broken (except nbd_receive_reply, see
below).
Most of callers operate like this:
if (func(..., size) != size) {
/* error path */
}
, i.e.:
1. They are not interested in partial success
2. Extra duplications in code (especially bad are duplications of
magic numbers)
3. User doesn't see actual error message, as return code is lost.
(this patch doesn't fix this point, but it makes fixing easier)
Several callers handles ret >= 0 and != requested-size separately, by
just returning EINVAL in this case. This patch makes read_sync and
friends return EINVAL in this case, so final behavior is the same.
And only one caller - nbd_receive_reply() does something not so
obvious. It returns EINVAL for ret > 0 and != requested-size, like
previous group, but for ret == 0 it returns 0. The only caller of
nbd_receive_reply() - nbd_read_reply_entry() handles ret == 0 in the
same way as ret < 0, so for now it doesn't matter. However, in
following commits error path handling will be improved and we'll need
to distinguish success from fail in this case too. So, this patch adds
separate helper for this case - read_sync_eof.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20170516094533.6160-3-vsementsov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-05-16 11:45:30 +02:00
|
|
|
*/
|
2017-08-04 17:14:25 +02:00
|
|
|
static inline int nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size,
|
|
|
|
Error **errp)
|
2016-01-14 09:41:02 +01:00
|
|
|
{
|
2017-09-05 21:11:14 +02:00
|
|
|
int ret;
|
2017-08-04 17:14:25 +02:00
|
|
|
|
|
|
|
assert(size);
|
2017-09-05 21:11:14 +02:00
|
|
|
ret = qio_channel_read_all_eof(ioc, buffer, size, errp);
|
|
|
|
if (ret < 0) {
|
|
|
|
ret = -EIO;
|
2017-08-04 17:14:25 +02:00
|
|
|
}
|
2017-09-05 21:11:14 +02:00
|
|
|
return ret;
|
2016-01-14 09:41:02 +01:00
|
|
|
}
|
|
|
|
|
2017-06-02 17:01:39 +02:00
|
|
|
/* nbd_read
|
nbd: read_sync and friends: return 0 on success
functions read_sync, drop_sync, write_sync, and also
nbd_negotiate_write, nbd_negotiate_read, nbd_negotiate_drop_sync
returns number of processed bytes. But what this number can be,
except requested number of bytes?
Actually, underlying nbd_wr_syncv function returns a value >= 0 and
!= requested_bytes only on eof on read operation. So, firstly, it is
impossible on write (let's add an assert) and on read it actually
means, that communication is broken (except nbd_receive_reply, see
below).
Most of callers operate like this:
if (func(..., size) != size) {
/* error path */
}
, i.e.:
1. They are not interested in partial success
2. Extra duplications in code (especially bad are duplications of
magic numbers)
3. User doesn't see actual error message, as return code is lost.
(this patch doesn't fix this point, but it makes fixing easier)
Several callers handles ret >= 0 and != requested-size separately, by
just returning EINVAL in this case. This patch makes read_sync and
friends return EINVAL in this case, so final behavior is the same.
And only one caller - nbd_receive_reply() does something not so
obvious. It returns EINVAL for ret > 0 and != requested-size, like
previous group, but for ret == 0 it returns 0. The only caller of
nbd_receive_reply() - nbd_read_reply_entry() handles ret == 0 in the
same way as ret < 0, so for now it doesn't matter. However, in
following commits error path handling will be improved and we'll need
to distinguish success from fail in this case too. So, this patch adds
separate helper for this case - read_sync_eof.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20170516094533.6160-3-vsementsov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-05-16 11:45:30 +02:00
|
|
|
* Reads @size bytes from @ioc. Returns 0 on success.
|
|
|
|
*/
|
2017-06-02 17:01:39 +02:00
|
|
|
static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size,
|
|
|
|
Error **errp)
|
nbd: read_sync and friends: return 0 on success
functions read_sync, drop_sync, write_sync, and also
nbd_negotiate_write, nbd_negotiate_read, nbd_negotiate_drop_sync
returns number of processed bytes. But what this number can be,
except requested number of bytes?
Actually, underlying nbd_wr_syncv function returns a value >= 0 and
!= requested_bytes only on eof on read operation. So, firstly, it is
impossible on write (let's add an assert) and on read it actually
means, that communication is broken (except nbd_receive_reply, see
below).
Most of callers operate like this:
if (func(..., size) != size) {
/* error path */
}
, i.e.:
1. They are not interested in partial success
2. Extra duplications in code (especially bad are duplications of
magic numbers)
3. User doesn't see actual error message, as return code is lost.
(this patch doesn't fix this point, but it makes fixing easier)
Several callers handles ret >= 0 and != requested-size separately, by
just returning EINVAL in this case. This patch makes read_sync and
friends return EINVAL in this case, so final behavior is the same.
And only one caller - nbd_receive_reply() does something not so
obvious. It returns EINVAL for ret > 0 and != requested-size, like
previous group, but for ret == 0 it returns 0. The only caller of
nbd_receive_reply() - nbd_read_reply_entry() handles ret == 0 in the
same way as ret < 0, so for now it doesn't matter. However, in
following commits error path handling will be improved and we'll need
to distinguish success from fail in this case too. So, this patch adds
separate helper for this case - read_sync_eof.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20170516094533.6160-3-vsementsov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-05-16 11:45:30 +02:00
|
|
|
{
|
2017-09-05 21:11:14 +02:00
|
|
|
return qio_channel_read_all(ioc, buffer, size, errp) < 0 ? -EIO : 0;
|
nbd: read_sync and friends: return 0 on success
functions read_sync, drop_sync, write_sync, and also
nbd_negotiate_write, nbd_negotiate_read, nbd_negotiate_drop_sync
returns number of processed bytes. But what this number can be,
except requested number of bytes?
Actually, underlying nbd_wr_syncv function returns a value >= 0 and
!= requested_bytes only on eof on read operation. So, firstly, it is
impossible on write (let's add an assert) and on read it actually
means, that communication is broken (except nbd_receive_reply, see
below).
Most of callers operate like this:
if (func(..., size) != size) {
/* error path */
}
, i.e.:
1. They are not interested in partial success
2. Extra duplications in code (especially bad are duplications of
magic numbers)
3. User doesn't see actual error message, as return code is lost.
(this patch doesn't fix this point, but it makes fixing easier)
Several callers handles ret >= 0 and != requested-size separately, by
just returning EINVAL in this case. This patch makes read_sync and
friends return EINVAL in this case, so final behavior is the same.
And only one caller - nbd_receive_reply() does something not so
obvious. It returns EINVAL for ret > 0 and != requested-size, like
previous group, but for ret == 0 it returns 0. The only caller of
nbd_receive_reply() - nbd_read_reply_entry() handles ret == 0 in the
same way as ret < 0, so for now it doesn't matter. However, in
following commits error path handling will be improved and we'll need
to distinguish success from fail in this case too. So, this patch adds
separate helper for this case - read_sync_eof.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20170516094533.6160-3-vsementsov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-05-16 11:45:30 +02:00
|
|
|
}
|
|
|
|
|
2017-06-02 17:01:39 +02:00
|
|
|
/* nbd_write
|
nbd: read_sync and friends: return 0 on success
functions read_sync, drop_sync, write_sync, and also
nbd_negotiate_write, nbd_negotiate_read, nbd_negotiate_drop_sync
returns number of processed bytes. But what this number can be,
except requested number of bytes?
Actually, underlying nbd_wr_syncv function returns a value >= 0 and
!= requested_bytes only on eof on read operation. So, firstly, it is
impossible on write (let's add an assert) and on read it actually
means, that communication is broken (except nbd_receive_reply, see
below).
Most of callers operate like this:
if (func(..., size) != size) {
/* error path */
}
, i.e.:
1. They are not interested in partial success
2. Extra duplications in code (especially bad are duplications of
magic numbers)
3. User doesn't see actual error message, as return code is lost.
(this patch doesn't fix this point, but it makes fixing easier)
Several callers handles ret >= 0 and != requested-size separately, by
just returning EINVAL in this case. This patch makes read_sync and
friends return EINVAL in this case, so final behavior is the same.
And only one caller - nbd_receive_reply() does something not so
obvious. It returns EINVAL for ret > 0 and != requested-size, like
previous group, but for ret == 0 it returns 0. The only caller of
nbd_receive_reply() - nbd_read_reply_entry() handles ret == 0 in the
same way as ret < 0, so for now it doesn't matter. However, in
following commits error path handling will be improved and we'll need
to distinguish success from fail in this case too. So, this patch adds
separate helper for this case - read_sync_eof.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20170516094533.6160-3-vsementsov@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2017-05-16 11:45:30 +02:00
|
|
|
* Writes @size bytes to @ioc. Returns 0 on success.
|
|
|
|
*/
|
2017-06-02 17:01:39 +02:00
|
|
|
static inline int nbd_write(QIOChannel *ioc, const void *buffer, size_t size,
|
|
|
|
Error **errp)
|
2016-01-14 09:41:02 +01:00
|
|
|
{
|
2017-09-05 21:11:14 +02:00
|
|
|
return qio_channel_write_all(ioc, buffer, size, errp) < 0 ? -EIO : 0;
|
2016-01-14 09:41:02 +01:00
|
|
|
}
|
|
|
|
|
2016-02-10 19:41:11 +01:00
|
|
|
struct NBDTLSHandshakeData {
|
|
|
|
GMainLoop *loop;
|
|
|
|
bool complete;
|
|
|
|
Error *error;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-08-11 16:20:58 +02:00
|
|
|
void nbd_tls_handshake(QIOTask *task,
|
2016-02-10 19:41:11 +01:00
|
|
|
void *opaque);
|
2017-07-07 22:30:43 +02:00
|
|
|
const char *nbd_opt_lookup(uint32_t opt);
|
|
|
|
const char *nbd_rep_lookup(uint32_t rep);
|
|
|
|
const char *nbd_info_lookup(uint16_t info);
|
|
|
|
const char *nbd_cmd_lookup(uint16_t info);
|
2016-02-10 19:41:11 +01:00
|
|
|
|
2017-06-02 17:01:40 +02:00
|
|
|
int nbd_drop(QIOChannel *ioc, size_t size, Error **errp);
|
|
|
|
|
2016-01-14 09:41:02 +01:00
|
|
|
#endif
|