2 Commits

Author SHA1 Message Date
Patrick J Cherry
4ed8d49b2c Updated rules to skip ruby tests, and just use the normal make check 2016-08-31 10:06:07 +01:00
Patrick J Cherry
3af0e84f5f Updated Debian packaging to be in a separate branch.
This should allow us to use git-buildpackage to build our packages.
2016-08-30 21:57:00 +01:00
26 changed files with 3239 additions and 355 deletions

View File

@@ -1,10 +0,0 @@
image: "ruby:2.1"
before_script:
- apt-get update; apt-get install -y check libev-dev net-tools dpkg-dev
unit_test:
script:
- make clean
- make build
- make test

View File

@@ -50,11 +50,15 @@ CC?=gcc
LIBS=-lpthread LIBS=-lpthread
INC=-I/usr/include/libev -Isrc/common -Isrc/server -Isrc/proxy INC=-I/usr/include/libev -Isrc/common -Isrc/server -Isrc/proxy
COMPILE=$(CC) -MMD $(INC) -c $(CCFLAGS) COMPILE=$(CC) $(INC) -c $(CCFLAGS)
SAVEDEP=$(CC) $(INC) -MM $(CCFLAGS)
LINK=$(CC) $(LLDFLAGS) -Isrc $(LIBS) LINK=$(CC) $(LLDFLAGS) -Isrc $(LIBS)
LIB=build/ LIB=build/
EXISTING_OBJS := $(wildcard build/*.o)
-include $(EXISTING_OBJS:.o=.d)
COMMON_SRC := $(wildcard src/common/*.c) COMMON_SRC := $(wildcard src/common/*.c)
SERVER_SRC := $(wildcard src/server/*.c) SERVER_SRC := $(wildcard src/server/*.c)
PROXY_SRC := $(wildcard src/proxy/*.c) PROXY_SRC := $(wildcard src/proxy/*.c)
@@ -67,13 +71,12 @@ SRCS := $(COMMON_SRC) $(SERVER_SRC) $(PROXY_SRC)
OBJS := $(COMMON_OBJ) $(SERVER_OBJ) $(PROXY_OBJ) OBJS := $(COMMON_OBJ) $(SERVER_OBJ) $(PROXY_OBJ)
all: build doc all: build/flexnbd build/flexnbd-proxy doc
build: server proxy
build/%.o: %.c build/%.o: %.c
mkdir -p $(dir $@) mkdir -p $(dir $@)
$(COMPILE) $< -o $@ $(COMPILE) $< -o $@
$(SAVEDEP) $< > build/$*.d
objs: $(OBJS) objs: $(OBJS)
@@ -84,42 +87,41 @@ build/flexnbd-proxy: $(COMMON_OBJ) $(PROXY_OBJ) build/proxy-main.o
$(LINK) $^ -o $@ $(LINK) $^ -o $@
server: build/flexnbd server: build/flexnbd
proxy: build/flexnbd-proxy proxy: build/flexnbd-proxy
CHECK_SRC := $(wildcard tests/unit/*.c) CHECK_SRC := $(wildcard tests/unit/*.c)
CHECK_OBJ := $(CHECK_SRC:tests/unit/%.c=build/%.o) CHECK_OBJ := $(CHECK_SRC:tests/unit/%.c=build/tests/%.o)
# Why can't we reuse the build/%.o rule above? Not sure. # Why can't we reuse the build/%.o rule above? Not sure.
build/tests/%.o: tests/unit/%.c
mkdir -p $(dir $@)
$(COMPILE) $< -o $@
$(SAVEDEP) $< > build/tests/$*.d
CHECK_BINS := $(CHECK_SRC:tests/unit/%.c=build/%) CHECK_BINS := $(CHECK_OBJ:build/tests/%.o=build/tests/%)
build/tests/%: build/tests/%.o $(OBJS)
build/check_%: build/check_%.o $(LINK) $^ -o $@ -lcheck
$(LINK) $^ -o $@ $(COMMON_OBJ) $(SERVER_OBJ) -lcheck
check_objs: $(CHECK_OBJ) check_objs: $(CHECK_OBJ)
check_bins: $(CHECK_BINS) check_bins: $(CHECK_BINS)
check: $(CHECK_BINS)
check: $(OBJS) $(CHECK_BINS) for bin in $^; do $$bin; done
r=true ; for bin in $(CHECK_BINS); do $$bin || r=false; done ; $$r
acceptance: build
cd tests/acceptance && RUBYOPT='-I.' ruby nbd_scenarios -v
test: check acceptance
build/flexnbd.1: README.txt build/flexnbd.1: README.txt
txt2man -t flexnbd -s 1 $< > $@ a2x --destination-dir build --format manpage $<
build/flexnbd-proxy.1: README.proxy.txt build/flexnbd-proxy.1: README.proxy.txt
txt2man -t flexnbd-proxy -s 1 $< > $@ a2x --destination-dir build --format manpage $<
# If we don't pipe to file, gzip clobbers the original, causing make # If we don't pipe to file, gzip clobbers the original, causing make
# to rebuild each time # to rebuild each time
%.1.gz: %.1 %.1.gz: %.1
gzip -c -f $< > $@ gzip -c -f $< > $@
doc: build/flexnbd.1.gz build/flexnbd-proxy.1.gz
server-man: build/flexnbd.1.gz
proxy-man: build/flexnbd-proxy.1.gz
doc: server-man proxy-man
install: install:
mkdir -p $(INSTALLDIR) mkdir -p $(INSTALLDIR)
@@ -129,7 +131,4 @@ clean:
rm -rf build/* rm -rf build/*
.PHONY: clean objs check_objs all server proxy check_bins check doc build test acceptance .PHONY: clean objs check_objs all server proxy check_bins check server-man proxy-man doc
# Include extra dependencies at the end, NOT before 'all'
-include $(wildcard build/*.d)

View File

@@ -1,14 +1,19 @@
FLEXNBD-PROXY(1)
================
:doctype: manpage
NAME NAME
----
flexnbd-proxy - A simple NBD proxy flexnbd-proxy - A simple NBD proxy
SYNOPSIS SYNOPSIS
--------
flexnbd-proxy --addr ADDR [--port PORT] --conn-addr ADDR *flexnbd-proxy* ['OPTIONS']
--conn-port PORT [--bind ADDR] [--cache[=CACHE_BYTES]]
[--help] [--verbose] [--quiet]
DESCRIPTION DESCRIPTION
-----------
flexnbd-proxy is a simple NBD proxy server that implements resilient flexnbd-proxy is a simple NBD proxy server that implements resilient
connection logic for the client. It connects to an upstream NBD server connection logic for the client. It connects to an upstream NBD server
@@ -20,6 +25,11 @@ of view of the client) reconnects and retransmits the request, before
returning the response to the client. returning the response to the client.
USAGE USAGE
-----
$ flexnbd-proxy --addr <ADDR> [ --port <PORT> ]
--conn-addr <ADDR> --conn-port <PORT>
[--bind <ADDR>] [--cache[=<CACHE_BYTES>]] [option]*
Proxy requests from an NBD client to an NBD server, resiliently. Only one Proxy requests from an NBD client to an NBD server, resiliently. Only one
client can be connected at a time, and ACLs cannot be applied to the client, as they client can be connected at a time, and ACLs cannot be applied to the client, as they
@@ -48,39 +58,40 @@ Only one request may be in-flight at a time under the current architecture; that
doesn't seem to slow things down much relative to alternative options, but may doesn't seem to slow things down much relative to alternative options, but may
be changed in the future if it becomes an issue. be changed in the future if it becomes an issue.
OPTIONS Options
~~~~~~~
--addr, -l ADDR *--addr, -l ADDR*:
The address to listen on. If this begins with a '/', it is assumed to be The address to listen on. If this begins with a '/', it is assumed to be
a UNIX domain socket to create. Otherwise, it should be an IPv4 or IPv6 a UNIX domain socket to create. Otherwise, it should be an IPv4 or IPv6
address. address.
*--port, -p PORT*:
--port, -p PORT
The port to listen on, if --addr is not a UNIX socket. The port to listen on, if --addr is not a UNIX socket.
--conn-addr, -C ADDR *--conn-addr, -C ADDR*:
The address of the NBD server to connect to. Required. The address of the NBD server to connect to. Required.
--conn-port, -P PORT *--conn-port, -P PORT*:
The port of the NBD server to connect to. Required. The port of the NBD server to connect to. Required.
--cache, -c=CACHE_BYTES *--cache, -c=CACHE_BYTES*:
If given, the size in bytes of read cache to use. CACHE_BYTES If given, the size in bytes of read cache to use. CACHE_BYTES
defaults to 4096. defaults to 4096.
--help, -h *--help, -h* :
Show command or global help. Show command or global help.
--verbose, -v *--verbose, -v* :
Output all available log information to STDERR. Output all available log information to STDERR.
--quiet, -q *--quiet, -q* :
Output as little log information as possible to STDERR. Output as little log information as possible to STDERR.
LOGGING
Log output is sent to STDERR. If --quiet is set, no output will be LOGGING
seen unless the program termintes abnormally. If neither --quiet nor -------
Log output is sent to STDERR. If --quiet is set, no output will be seen
unless the program termintes abnormally. If neither --quiet nor
--verbose are set, no output will be seen unless something goes wrong --verbose are set, no output will be seen unless something goes wrong
with a specific request. If --verbose is given, every available log with a specific request. If --verbose is given, every available log
message will be seen (which, for a debug build, is many). It is not an message will be seen (which, for a debug build, is many). It is not an
@@ -90,31 +101,32 @@ The log line format is:
<TIMESTAMP>:<LEVEL>:<PID> <THREAD> <SOURCEFILE>:<SOURCELINE>: <MSG> <TIMESTAMP>:<LEVEL>:<PID> <THREAD> <SOURCEFILE>:<SOURCELINE>: <MSG>
<TIMESTAMP> *TIMESTAMP*:
Time the log entry was made. This is expressed in terms of monotonic ms Time the log entry was made. This is expressed in terms of monotonic ms
<LEVEL> *LEVEL*:
This will be one of 'D', 'I', 'W', 'E', 'F' in increasing order of This will be one of 'D', 'I', 'W', 'E', 'F' in increasing order of
severity. If flexnbd is started with the --quiet flag, only 'F' will severity. If flexnbd is started with the --quiet flag, only 'F' will be
be seen. If it is started with the --verbose flag, any from 'I' seen. If it is started with the --verbose flag, any from 'I' upwards
upwards will be seen. Only if you have a debug build and start it will be seen. Only if you have a debug build and start it with
with --verbose will you see 'D' entries. --verbose will you see 'D' entries.
<PID> *PID*:
This is the process ID. This is the process ID.
<THREAD> *THREAD*:
flexnbd-proxy is currently single-threaded, so this should be the flexnbd-proxy is currently single-threaded, so this should be the same
same for all lines. That may not be the case in the future. for all lines. That may not be the case in the future.
<SOURCEFILE:SOURCELINE> *SOURCEFILE:SOURCELINE*:
Identifies where in the source code this log line can be found. Identifies where in the source code this log line can be found.
<MSG> *MSG*:
A short message describing what's happening, how it's being done, or A short message describing what's happening, how it's being done, or
if you're very lucky why it's going on. if you're very lucky *why* it's going on.
EXAMPLES Proxying
~~~~~~~~
The main point of the proxy mode is to allow clients that would otherwise break The main point of the proxy mode is to allow clients that would otherwise break
when the NBD server goes away (during a migration, for instance) to see a when the NBD server goes away (during a migration, for instance) to see a
@@ -148,6 +160,7 @@ The data in myfile has been moved between physical servers without the nbd
client process having to be disturbed at all. client process having to be disturbed at all.
READ CACHE READ CACHE
----------
If the --cache option is given at the command line, either without an If the --cache option is given at the command line, either without an
argument or with an argument greater than 0, flexnbd-proxy will use a argument or with an argument greater than 0, flexnbd-proxy will use a
@@ -160,7 +173,7 @@ cache without making a request to the server.
This pattern is designed to match sequential reads, such as those This pattern is designed to match sequential reads, such as those
performed by a booting virtual machine. performed by a booting virtual machine.
Note: If specifying a cache size, you must use this form: Note: If specifying a cache size, you *must* use this form:
nbd-client$ flexnbd-proxy --cache=XXXX nbd-client$ flexnbd-proxy --cache=XXXX
@@ -170,37 +183,30 @@ If no cache size is given, a size of 4096 bytes is assumed. Caching can
be explicitly disabled by setting a size of 0. be explicitly disabled by setting a size of 0.
BUGS BUGS
----
Should be reported via GitHub. Should be reported to nick@bytemark.co.uk.
* https://github.com/BytemarkHosting/flexnbd-c/issues
Current issues include: Current issues include:
* only old-style NBD negotiation is supported; * Only old-style NBD negotiation is supported
* only one request may be in-flight at a time; * Only one request may be in-flight at a time
* all I/O is blocking, and signals terminate the process immediately; * All I/O is blocking, and signals terminate the process immediately
* UNIX socket support is limited to the listen address; * UNIX socket support is limited to the listen address
* FLUSH and TRIM commands, and the FUA flag, are not supported; * FLUSH and TRIM commands, and the FUA flag, are not supported
* DISCONNECT requests do not get passed through to the NBD server; * DISCONNECT requests do not get passed through to the NBD server
* no active timeout-retry of requests - we trust the kernel's idea of * No active timeout-retry of requests - we trust the kernel's idea of failure
failure.
AUTHOR AUTHOR
------
Originally written by Alex Young <alex@blackkettle.org>. Written by Alex Young <alex@bytemark.co.uk>.
Original concept and core code by Matthew Bloch <matthew@bytemark.co.uk>. Original concept and core code by Matthew Bloch <matthew@bytemark.co.uk>.
Proxy mode written by Nick Thomas <me@ur.gs>. Proxy mode written by Nick Thomas <nick@bytemark.co.uk>
The full commit history is available on GitHub. COPYING
-------
SEE ALSO Copyright (c) 2012 Bytemark Hosting Ltd. Free use of this software is
granted under the terms of the GNU General Public License version 3 or
flexnbd(1), nbd-client(8), xnbd-server(8), xnbd-client(8) later.
COPYRIGHT
Copyright (c) 2012-2016 Bytemark Hosting Ltd. Free use of this
software is granted under the terms of the GNU General Public License
version 3 or later.

View File

@@ -1,36 +1,17 @@
NAME FLEXNBD(1)
==========
:doctype: manpage
NAME
----
flexnbd - A fast NBD server flexnbd - A fast NBD server
SYNOPSIS SYNOPSIS
--------
flexnbd MODE [ ARGS ] *flexnbd* 'COMMAND' ['OPTIONS']
flexnbd serve --addr ADDR --port PORT --file FILE [--sock SOCK]
[--default-deny] [--killswitch] [global_option]* [acl_entry]*
flexnbd listen --addr ADDR --port PORT --file FILE [--sock SOCK]
[--default-deny] [global_option]* [acl_entry]*
flexnbd mirror --addr ADDR --port PORT --sock SOCK [--unlink]
[--bind BIND_ADDR] [global_option]*
flexnbd acl --sock SOCK [acl_entry]+ [global_option]*
flexnbd break --sock SOCK [global_option]*
flexnbd status --sock SOCK [global_option]*
flexnbd read --addr ADDR --port PORT --from OFFSET --size SIZE
[--bind BIND_ADDR] [global_option]*
flexnbd write --addr ADDR --port PORT --from OFFSET --size SIZE
[--bind BIND_ADDR] [global_option]*
flexnbd help [mode] [global_option]*
DESCRIPTION DESCRIPTION
-----------
Flexnbd is a fast NBD server which supports live migration. Live Flexnbd is a fast NBD server which supports live migration. Live
migration is performed by writing the data to a new server. A failed migration is performed by writing the data to a new server. A failed
migration will be invisible to any connected clients. migration will be invisible to any connected clients.
@@ -38,56 +19,57 @@ migration will be invisible to any connected clients.
Flexnbd tries quite hard to preserve sparsity of files it is serving, Flexnbd tries quite hard to preserve sparsity of files it is serving,
even across migrations. even across migrations.
SERVE MODE COMMANDS
--------
Serve a file.
serve
~~~~~
$ flexnbd serve --addr <ADDR> --port <PORT> --file <FILE> $ flexnbd serve --addr <ADDR> --port <PORT> --file <FILE>
[--sock <SOCK>] [--default-deny] [-k] [global_option]* [--sock <SOCK>] [--default-deny] [-k] [global option]* [acl entry]*
[acl_entry]*
If any ACL entries are given (which should be IP Serve a file. If any ACL entries are given (which should be IP
addresses), only those clients listed will be permitted to connect. addresses), only those clients listed will be permitted to connect.
flexnbd will continue to serve until a SIGINT, SIGQUIT, or a successful flexnbd will continue to serve until a SIGINT, SIGQUIT, or a successful
migration. migration.
OPTIONS Options
^^^^^^^
--addr, -l ADDR *--addr, -l ADDR*:
The address to listen on. Required. The address to listen on. Required.
--port, -p PORT *--port, -p PORT*:
The port to listen on. Required. The port to listen on. Required.
--file, -f FILE *--file, -f FILE*:
The file to serve. Must already exist. Required. The file to serve. Must already exist. Required.
--sock, -s SOCK *--sock, -s SOCK*:
Path to a control socket to open. You will need this if you want to Path to a control socket to open. You will need this if you want to
migrate, get the current status, or manipulate the access control migrate, get the current status, or manipulate the access control
list. list.
--default-deny, -d *--default-deny, -d*:
How to interpret an empty ACL. If --default-deny is given, an How to interpret an empty ACL. If --default-deny is given, an
empty ACL will let no clients connect. If it is not given, an empty ACL will let no clients connect. If it is not given, an
empty ACL will let any client connect. empty ACL will let any client connect.
--killswitch, -k *--killswitch, -k*:
If set, we implement a 2-minute timeout on NBD requests and If set, we implement a 2-minute timeout on NBD requests and
responses. If a request takes longer than that to complete, responses. If a request takes longer than that to complete,
the client is disconnected. This is useful to keep broken the client is disconnected. This is useful to keep broken
clients from breaking migrations, among other things. clients from breaking migrations, among other things.
LISTEN MODE listen
~~~~~~
$ flexnbd listen --addr <ADDR> --port <PORT> --file <FILE>
[--sock <SOCK>] [--default-deny] [global option]* [acl entry]*
Listen for an inbound migration, and quit with a status of 0 on Listen for an inbound migration, and quit with a status of 0 on
completion. completion.
$ flexnbd listen --addr ADDR --port PORT --file FILE
[--sock SOCK] [--default-deny] [global_option]*
[acl_entry]*
flexnbd will wait for a successful migration, and then quit. The file flexnbd will wait for a successful migration, and then quit. The file
to write the inbound migration data to must already exist before you to write the inbound migration data to must already exist before you
run 'flexnbd listen'. run 'flexnbd listen'.
@@ -99,24 +81,25 @@ to assume that a partial migration can be resumed because the
destination has no knowledge of whether a client has made a write to destination has no knowledge of whether a client has made a write to
the source in the interim. the source in the interim.
If the migration fails for a reason which the 'flexnbd listen' process If the migration fails for a reason which the `flexnbd listen` process
can't fix (say, a failed local write), it will exit with an error can't fix (say, a failed local write), it will exit with an error
status. In this case, the sender will continually retry the migration status. In this case, the sender will continually retry the migration
until it succeeds, and you will need to restart the 'flexnbd listen' until it succeeds, and you will need to restart the `flexnbd listen`
process to allow that to happen. process to allow that to happen.
OPTIONS Options
^^^^^^^
As for 'serve'.
As for serve. mirror
~~~~~~
MIRROR MODE $ flexnbd mirror --addr <ADDR> --port <PORT> --sock SOCK
[--unlink] [--bind <BIND-ADDR>] [global option]*
Start a migration from the server with control socket SOCK to the server Start a migration from the server with control socket SOCK to the server
listening at ADDR:PORT. listening at ADDR:PORT.
$ flexnbd mirror --addr ADDR --port PORT --sock SOCK [--unlink]
[--bind BIND_ADDR] [global_option]*
Migration can be a slow process. Rather than block the 'flexnbd mirror' Migration can be a slow process. Rather than block the 'flexnbd mirror'
process until it completes, it will exit with a message of "Migration process until it completes, it will exit with a message of "Migration
started" once it has confirmation that the local server was able to started" once it has confirmation that the local server was able to
@@ -129,7 +112,7 @@ again. It is not safe to resume the migration from where it left off
because the source can't see that the backing store behind the because the source can't see that the backing store behind the
destination is intact, or even on the same machine. destination is intact, or even on the same machine.
If the --unlink option is given, the local file will be deleted If the `--unlink` option is given, the local file will be deleted
immediately before the mirror connection is terminated. This allows immediately before the mirror connection is terminated. This allows
an otherwise-ambiguous situation to be resolved: if you don't unlink an otherwise-ambiguous situation to be resolved: if you don't unlink
the file and the flexnbd process at either end is terminated, it's not the file and the flexnbd process at either end is terminated, it's not
@@ -139,150 +122,161 @@ the data, there can be no ambiguity.
Note: files smaller than 4096 bytes cannot be mirrored. Note: files smaller than 4096 bytes cannot be mirrored.
OPTIONS Options
^^^^^^^
--addr, -l ADDR *--addr, -l ADDR*:
The address of the remote server to migrate to. Required. The address of the remote server to migrate to. Required.
--port, -p PORT *--port, -p PORT*:
The port of the remote server to migrate to. Required. The port of the remote server to migrate to. Required.
--sock, -s SOCK *--sock, -s SOCK*:
The control socket of the local server to migrate from. Required. The control socket of the local server to migrate from. Required.
--unlink, -u *--unlink, -u*:
Unlink the served file from the local filesystem after Unlink the served file from the local filesystem after successfully
successfully mirroring. mirroring.
--bind, -b BIND_ADDR *--bind, -b BIND-ADDR*:
The local address to bind to. You may need this if the remote The local address to bind to. You may need this if the remote server
server is using an access control list. is using an access control list.
BREAK MODE break
~~~~~
$ flexnbd mirror --sock SOCK [global option]*
Stop a running migration. Stop a running migration.
$ flexnbd break --sock SOCK [global_option]* Options
^^^^^^^
OPTIONS *--sock, -s SOCK*:
The control socket of the local server whose emigration to stop.
--sock, -s SOCK
The control socket of the local server whose migration to stop.
Required. Required.
ACL MODE
acl
~~~
$ flexnbd acl --sock <SOCK> [acl entry]+ [global option]*
Set the access control list of the server with the control socket SOCK Set the access control list of the server with the control socket SOCK
to the given access control list entries. to the given access control list entries.
$ flexnbd acl --sock SOCK [acl_entry]+ [global_option]*
ACL entries are given as IP addresses. ACL entries are given as IP addresses.
OPTIONS Options
^^^^^^^
--sock, -s SOCK *--sock, -s SOCK*:
The control socket of the server whose ACL to replace. Required The control socket of the server whose ACL to replace.
STATUS MODE status
~~~~~~
$ flexnbd status --sock <SOCK> [global option]*
Get the current status of the server with control socket SOCK. Get the current status of the server with control socket SOCK.
$ flexnbd status --sock SOCK [global_option]*
The status will be printed to STDOUT. It is a space-separated list of The status will be printed to STDOUT. It is a space-separated list of
key=value pairs. The space character will never appear in a key or key=value pairs. The space character will never appear in a key or
value. Currently reported values are: value. Currently reported values are:
pid *pid*:
The process id of the server listening on SOCK. The process id of the server listening on SOCK.
is_mirroring *is_mirroring*:
'true' if this server is sending migration data, 'false' otherwise. 'true' if this server is sending migration data, 'false' otherwise.
has_control *has_control*:
'false' if this server was started in 'listen' mode. 'true' otherwise. 'false' if this server was started in 'listen' mode. 'true' otherwise.
OPTIONS read
~~~~
--sock, -s SOCK $ flexnbd read --addr <ADDR> --port <PORT> --from <OFFSET>
The control socket of the server of interest. Required. --size <SIZE> [--bind BIND-ADDR] [global option]*
READ MODE
Connect to the server at ADDR:PORT, and read SIZE bytes starting at Connect to the server at ADDR:PORT, and read SIZE bytes starting at
OFFSET in a single NBD query. OFFSET in a single NBD query. The returned data will be echoed to
STDOUT. In case of a remote ACL, set the local source address to
BIND-ADDR.
$ flexnbd read --addr ADDR --port PORT --from OFFSET --size SIZE Options
[--bind BIND_ADDR] [global_option]* ^^^^^^^
The returned data will be echoed to STDOUT. In case of a remote ACL, *--addr, -l ADDR*:
set the local source address to BIND_ADDR.
OPTIONS
--addr, -l ADDR
The address of the remote server. Required. The address of the remote server. Required.
--port, -p PORT *--port, -p PORT*:
The port of the remote server. Required. The port of the remote server. Required.
--from, -F OFFSET *--from, -F OFFSET*:
The byte offset to start reading from. Required. Maximum 2^62. The byte offset to start reading from. Required. Maximum 2^62.
--size, -S SIZE *--size, -S SIZE*:
The number of bytes to read. Required. Maximum 2^30. The number of bytes to read. Required. Maximum 2^30.
--bind, -b BIND_ADDR *--bind, -b BIND-ADDR*:
The local address to bind to. You may need this if the remote The local address to bind to. You may need this if the remote server
server is using an access control list. is using an access control list.
WRITE MODE write
~~~~~
$ cat ... | flexnbd write --addr <ADDR> --port <PORT> --from <OFFSET>
--size <SIZE> [--bind BIND-ADDR] [global option]*
Connect to the server at ADDR:PORT, and write SIZE bytes from STDIN Connect to the server at ADDR:PORT, and write SIZE bytes from STDIN
starting at OFFSET in a single NBD query. starting at OFFSET in a single NBD query. In case of a remote ACL, set
the local source address to BIND-ADDR.
$ cat ... | flexnbd write --addr ADDR --port PORT --from OFFSET Options
--size SIZE [--bind BIND_ADDR] [global_option]* ^^^^^^^
In case of a remote ACL, set the local source address to BIND_ADDR. *--addr, -l ADDR*:
OPTIONS
--addr, -l ADDR
The address of the remote server. Required. The address of the remote server. Required.
--port, -p PORT *--port, -p PORT*:
The port of the remote server. Required. The port of the remote server. Required.
--from, -F OFFSET *--from, -F OFFSET*:
The byte offset to start writing from. Required. Maximum 2^62. The byte offset to start writing from. Required. Maximum 2^62.
--size, -S SIZE *--size, -S SIZE*:
The number of bytes to write. Required. Maximum 2^30. The number of bytes to write. Required. Maximum 2^30.
--bind, -b BIND_ADDR *--bind, -b BIND-ADDR*:
The local address to bind to. You may need this if the remote The local address to bind to. You may need this if the remote server
server is using an access control list. is using an access control list.
HELP MODE help
~~~~
$ flexnbd help [mode] [global_option]* $ flexnbd help [command] [global option]*
Without mode, show the list of available modes. With mode, show help for that mode. Without 'command', show the list of available commands. With 'command',
show help for that command.
GLOBAL OPTIONS GLOBAL OPTIONS
--------------
--help, -h Show mode or global help. *--help, -h* :
Show command or global help.
--verbose, -v Output all available log information to STDERR. *--verbose, -v* :
Output all available log information to STDERR.
*--quiet, -q* :
Output as little log information as possible to STDERR.
--quiet, -q Output as little log information as possible to STDERR.
LOGGING LOGGING
-------
Log output is sent to STDERR. If --quiet is set, no output will be Log output is sent to STDERR. If --quiet is set, no output will be seen
seen unless the program termintes abnormally. If neither --quiet nor unless the program termintes abnormally. If neither --quiet nor
--verbose are set, no output will be seen unless something goes wrong --verbose are set, no output will be seen unless something goes wrong
with a specific request. If --verbose is given, every available log with a specific request. If --verbose is given, every available log
message will be seen (which, for a debug build, is many). It is not an message will be seen (which, for a debug build, is many). It is not an
@@ -290,38 +284,39 @@ error to set both --verbose and --quiet. The last one wins.
The log line format is: The log line format is:
<TIMESTAMP>:<LEVEL>:<PID> <THREAD> <SOURCEFILE:SOURCELINE>: <MSG> <TIMESTAMP>:<LEVEL>:<PID> <THREAD> <SOURCEFILE>:<SOURCELINE>: <MSG>
<TIMESTAMP> *TIMESTAMP*:
Time the log entry was made. This is expressed in terms of monotonic Time the log entry was made. This is expressed in terms of monotonic ms.
ms.
<LEVEL> *LEVEL*:
This will be one of 'D', 'I', 'W', 'E', 'F' in increasing order of This will be one of 'D', 'I', 'W', 'E', 'F' in increasing order of
severity. If flexnbd is started with the --quiet flag, only 'F' severity. If flexnbd is started with the --quiet flag, only 'F' will be
will be seen. If it is started with the --verbose flag, any from 'I' seen. If it is started with the --verbose flag, any from 'I' upwards
upwards will be seen. Only if you have a debug build and start it will be seen. Only if you have a debug build and start it with
with --verbose will you see 'D' entries. --verbose will you see 'D' entries.
<PID> *PID*:
This is the process ID. This is the process ID.
<THREAD> *THREAD*:
There are several pthreads per flexnbd process: a main thread, a There are several pthreads per flexnbd process: a main thread, a serve
serve thread, a thread per client, and possibly a pair of mirror thread, a thread per client, and possibly a pair of mirror threads and a
threads and a control thread. This field identifies which thread was control thread. This field identifies which thread was responsible for
responsible for the log line. the log line.
<SOURCEFILE:SOURCELINE> *SOURCEFILE:SOURCELINE*:
Identifies where in the source code this log line can be found. Identifies where in the source code this log line can be found.
<MSG> *MSG*:
A short message describing what's happening, how it's being done, or A short message describing what's happening, how it's being done, or
if you're very lucky why it's going on. if you're very lucky *why* it's going on.
EXAMPLES EXAMPLES
--------
SERVING A FILE Serving a file
~~~~~~~~~~~~~~
The simplest case is serving a file on the default nbd port: The simplest case is serving a file on the default nbd port:
@@ -331,7 +326,8 @@ The simplest case is serving a file on the default nbd port:
root:x: root:x:
$ $
READING SERVER STATUS Reading server status
~~~~~~~~~~~~~~~~~~~~~
In order to read a server's status, we need it to open a control socket. In order to read a server's status, we need it to open a control socket.
@@ -344,7 +340,8 @@ In order to read a server's status, we need it to open a control socket.
Note that the status output is newline-terminated. Note that the status output is newline-terminated.
MIGRATING Migrating
~~~~~~~~~
To migrate, we need to provide a destination file of the right size. To migrate, we need to provide a destination file of the right size.
@@ -370,8 +367,8 @@ With this knowledge in hand, we can start the migration:
$ flexnbd mirror --addr 127.0.0.1 --port 4779 \ $ flexnbd mirror --addr 127.0.0.1 --port 4779 \
--sock /tmp/flex-source.sock --sock /tmp/flex-source.sock
Migration started Migration started
[1] + 9648 done flexnbd serve --addr 0.0.0.0 --port 4778 [1] + 9648 done build/flexnbd serve --addr 0.0.0.0 --port 4778
[2] + 9651 done flexnbd listen --addr 0.0.0.0 --port 4779 [2] + 9651 done build/flexnbd listen --addr 0.0.0.0 --port 4779
$ $
Note that because the file is so small in this case, we see the source Note that because the file is so small in this case, we see the source
@@ -379,25 +376,21 @@ server quit soon after we start the migration, and the destination
exited at roughly the same time. exited at roughly the same time.
BUGS BUGS
----
Should be reported on GitHub at Should be reported to alex@bytemark.co.uk.
* https://github.com/BytemarkHosting/flexnbd-c/issues
AUTHOR AUTHOR
------
Originally written by Alex Young <alex@blackkettle.org>. Written by Alex Young <alex@bytemark.co.uk>.
Original concept and core code by Matthew Bloch <matthew@bytemark.co.uk>. Original concept and core code by Matthew Bloch <matthew@bytemark.co.uk>.
Proxy mode written by Nick Thomas <me@ur.gs>. Some additions by Nick Thomas <nick@bytemark.co.uk>
The full commit history is available on GitHub. COPYING
-------
SEE ALSO Copyright (c) 2012 Bytemark Hosting Ltd. Free use of this software is
granted under the terms of the GNU General Public License version 3 or
later.
flexnbd-proxy(1), nbd-client(8), xnbd-server(8), xnbd-client(8)
COPYRIGHT
Copyright (c) 2012-2016 Bytemark Hosting Ltd. Free use of this
software is granted under the terms of the GNU General Public License
version 3 or later.

60
Rakefile Normal file
View File

@@ -0,0 +1,60 @@
# encoding: utf-8
def make(*targets)
sh "make #{targets.map{|t| t.to_s}.join(" ")}"
end
def maketask( opts )
case opts
when Symbol
maketask opts => opts
else
opts.each do |name, targets|
task( name ){make *[*targets]}
end
end
end
desc "Build the binary and man page"
maketask :build => [:all, :doc]
desc "Build just the flexnbd binary"
maketask :flexnbd => [:server]
file "build/flexnbd" => :flexnbd
desc "Build just the flexnbd-proxy binary"
maketask :flexnbd_proxy => [:proxy]
file "build/flexnbd-proxy" => :flexnbd_proxy
desc "Build just the man page"
maketask :man => :doc
namespace "test" do
desc "Run all tests"
task 'run' => ["unit", "scenarios"]
desc "Build C tests"
maketask :build => :check_bins
desc "Run C tests"
maketask :unit => :check
desc "Run NBD test scenarios"
task 'scenarios' => ["build/flexnbd", "build/flexnbd-proxy"] do
sh "cd tests/acceptance && RUBYOPT='-I.' ruby nbd_scenarios -v"
end
end
desc "Remove all build targets, binaries and temporary files"
maketask :clean
file "debian/changelog" do
FileUtils.mkdir_p "debian"
sh "hg log --style=changelog.template > debian/changelog"
end
desc "Generate the changelog"
task :changelog => "debian/changelog"

2743
debian/changelog vendored Normal file

File diff suppressed because it is too large Load Diff

1
debian/compat vendored Normal file
View File

@@ -0,0 +1 @@
7

26
debian/control vendored Normal file
View File

@@ -0,0 +1,26 @@
Source: flexnbd
Section: web
Priority: extra
Maintainer: Patrick J Cherry <patrick@bytemark.co.uk>
Build-Depends: debhelper (>= 7.0.50), ruby, rake, gcc, libev-dev,
asciidoc, libxml2-utils, xsltproc, xmlto, check
Standards-Version: 3.8.1
Homepage: https://github.com/BytemarkHosting/flexnbd-c
Package: flexnbd
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, libev4 | libev3
Description: FlexNBD server
An NBD server offering push-mirroring and intelligent sparse file handling
Package: flexnbd-dbg
Architecture: any
Section: debug
Priority: extra
Depends:
flexnbd (= ${binary:Version}),
${misc:Depends}
Description: debugging symbols for flexnbd
An NBD server offering push-mirroring and intelligent sparse file handling
.
This package contains the debugging symbols for flexnbd.

53
debian/copyright vendored Normal file
View File

@@ -0,0 +1,53 @@
This work was packaged for Debian by:
Alex Young <alex@bytemark.co.uk> on Wed, 30 May 2012 16:46:58 +0100
It was downloaded from:
<url://example.com>
Upstream Author(s):
<put author's name and email here>
<likewise for another author>
Copyright:
<Copyright (C) YYYY Firstname Lastname>
<likewise for another author>
License:
### SELECT: ###
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
### OR ###
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
##########
This package 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
The Debian packaging is:
Copyright (C) 2012 Alex Young <alex@bytemark.co.uk>
you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.

5
debian/flexnbd.install vendored Normal file
View File

@@ -0,0 +1,5 @@
build/flexnbd usr/bin
build/flexnbd-proxy usr/bin
build/flexnbd.1.gz usr/share/man/man1
build/flexnbd-proxy.1.gz usr/share/man/man1

19
debian/rules vendored Executable file
View File

@@ -0,0 +1,19 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
%:
dh $@
override_dh_strip:
dh_strip --dbg-package=flexnbd-dbg
#
# TODO: The ruby test suites don't work during buiding in a chroot, so leave
# them out for now.
#
#override_dh_auto_test:
# rake test:run

1
debian/source/format vendored Normal file
View File

@@ -0,0 +1 @@
3.0 (quilt)

View File

@@ -27,7 +27,7 @@ void nbd_r2h_request( struct nbd_request_raw *from, struct nbd_request * to )
{ {
to->magic = htobe32( from->magic ); to->magic = htobe32( from->magic );
to->type = htobe32( from->type ); to->type = htobe32( from->type );
to->handle.w = from->handle.w; memcpy( to->handle, from->handle, 8 );
to->from = htobe64( from->from ); to->from = htobe64( from->from );
to->len = htobe32( from->len ); to->len = htobe32( from->len );
} }
@@ -36,7 +36,7 @@ void nbd_h2r_request( struct nbd_request * from, struct nbd_request_raw * to )
{ {
to->magic = be32toh( from->magic ); to->magic = be32toh( from->magic );
to->type = be32toh( from->type ); to->type = be32toh( from->type );
to->handle.w = from->handle.w; memcpy( to->handle, from->handle, 8 );
to->from = be64toh( from->from ); to->from = be64toh( from->from );
to->len = be32toh( from->len ); to->len = be32toh( from->len );
} }
@@ -46,13 +46,13 @@ void nbd_r2h_reply( struct nbd_reply_raw * from, struct nbd_reply * to )
{ {
to->magic = htobe32( from->magic ); to->magic = htobe32( from->magic );
to->error = htobe32( from->error ); to->error = htobe32( from->error );
to->handle.w = from->handle.w; memcpy( to->handle, from->handle, 8 );
} }
void nbd_h2r_reply( struct nbd_reply * from, struct nbd_reply_raw * to ) void nbd_h2r_reply( struct nbd_reply * from, struct nbd_reply_raw * to )
{ {
to->magic = be32toh( from->magic ); to->magic = be32toh( from->magic );
to->error = be32toh( from->error ); to->error = be32toh( from->error );
to->handle.w = from->handle.w; memcpy( to->handle, from->handle, 8 );
} }

View File

@@ -24,11 +24,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <inttypes.h> #include <inttypes.h>
typedef union nbd_handle_t {
uint8_t b[8];
uint64_t w;
} nbd_handle_t;
/* The _raw types are the types as they appear on the wire. Non-_raw /* The _raw types are the types as they appear on the wire. Non-_raw
* types are in host-format. * types are in host-format.
* Conversion functions are _r2h_ for converting raw to host, and _h2r_ * Conversion functions are _r2h_ for converting raw to host, and _h2r_
@@ -44,7 +39,7 @@ struct nbd_init_raw {
struct nbd_request_raw { struct nbd_request_raw {
__be32 magic; __be32 magic;
__be32 type; /* == READ || == WRITE */ __be32 type; /* == READ || == WRITE */
nbd_handle_t handle; char handle[8];
__be64 from; __be64 from;
__be32 len; __be32 len;
} __attribute__((packed)); } __attribute__((packed));
@@ -52,7 +47,7 @@ struct nbd_request_raw {
struct nbd_reply_raw { struct nbd_reply_raw {
__be32 magic; __be32 magic;
__be32 error; /* 0 = ok, else error */ __be32 error; /* 0 = ok, else error */
nbd_handle_t handle; /* handle you got from request */ char handle[8]; /* handle you got from request */
}; };
@@ -67,7 +62,7 @@ struct nbd_init {
struct nbd_request { struct nbd_request {
uint32_t magic; uint32_t magic;
uint32_t type; /* == READ || == WRITE || == DISCONNECT */ uint32_t type; /* == READ || == WRITE || == DISCONNECT */
nbd_handle_t handle; char handle[8];
uint64_t from; uint64_t from;
uint32_t len; uint32_t len;
} __attribute__((packed)); } __attribute__((packed));
@@ -75,7 +70,7 @@ struct nbd_request {
struct nbd_reply { struct nbd_reply {
uint32_t magic; uint32_t magic;
uint32_t error; /* 0 = ok, else error */ uint32_t error; /* 0 = ok, else error */
nbd_handle_t handle; /* handle you got from request */ char handle[8]; /* handle you got from request */
}; };
void nbd_r2h_init( struct nbd_init_raw * from, struct nbd_init * to ); void nbd_r2h_init( struct nbd_init_raw * from, struct nbd_init * to );

View File

@@ -105,7 +105,9 @@ void fill_request(struct nbd_request *request, int type, uint64_t from, uint32_t
{ {
request->magic = htobe32(REQUEST_MAGIC); request->magic = htobe32(REQUEST_MAGIC);
request->type = htobe32(type); request->type = htobe32(type);
request->handle.w = (((uint64_t)rand()) << 32) | ((uint64_t)rand()); uint32_t * randa = (uint32_t*)request->handle;
randa[0] = rand();
randa[1] = rand();
request->from = htobe64(from); request->from = htobe64(from);
request->len = htobe32(len); request->len = htobe32(len);
} }
@@ -125,7 +127,7 @@ void read_reply(int fd, struct nbd_request *request, struct nbd_reply *reply)
if (reply->error != 0) { if (reply->error != 0) {
error("Server replied with error %d", reply->error); error("Server replied with error %d", reply->error);
} }
if (request->handle.w != reply->handle.w) { if (strncmp(request->handle, reply->handle, 8) != 0) {
error("Did not reply with correct handle"); error("Did not reply with correct handle");
} }
} }

View File

@@ -100,7 +100,7 @@ int sock_try_bind( int fd, const struct sockaddr* sa )
{ {
int bind_result; int bind_result;
char s_address[256]; char s_address[256];
int retry = 10; int retry = 1;
sockaddr_address_string( sa, &s_address[0], 256 ); sockaddr_address_string( sa, &s_address[0], 256 );
@@ -126,11 +126,8 @@ int sock_try_bind( int fd, const struct sockaddr* sa )
* will cope with it. * will cope with it.
*/ */
case EADDRNOTAVAIL: case EADDRNOTAVAIL:
retry--;
if (retry) {
debug( "retrying" ); debug( "retrying" );
sleep( 1 ); sleep( 1 );
}
continue; continue;
case EADDRINUSE: case EADDRINUSE:
warn( "%s in use, giving up.", s_address ); warn( "%s in use, giving up.", s_address );

View File

@@ -709,7 +709,7 @@ void proxy_session( struct proxier* proxy )
state_started = monotonic_time_ms(); state_started = monotonic_time_ms();
debug( debug(
"State transition from %s to %s", "State transitition from %s to %s",
proxy_session_state_names[old_state], proxy_session_state_names[old_state],
proxy_session_state_names[state] proxy_session_state_names[state]
); );

View File

@@ -252,14 +252,14 @@ int client_read_request( struct client * client , struct nbd_request *out_reques
return 1; return 1;
} }
int fd_write_reply( int fd, uint64_t handle, int error ) int fd_write_reply( int fd, char *handle, int error )
{ {
struct nbd_reply reply; struct nbd_reply reply;
struct nbd_reply_raw reply_raw; struct nbd_reply_raw reply_raw;
reply.magic = REPLY_MAGIC; reply.magic = REPLY_MAGIC;
reply.error = error; reply.error = error;
reply.handle.w = handle; memcpy( reply.handle, handle, 8 );
nbd_h2r_reply( &reply, &reply_raw ); nbd_h2r_reply( &reply, &reply_raw );
debug( "Replying with handle=0x%08X, error=%"PRIu32, handle, error ); debug( "Replying with handle=0x%08X, error=%"PRIu32, handle, error );
@@ -291,7 +291,7 @@ int fd_write_reply( int fd, uint64_t handle, int error )
*/ */
int client_write_reply( struct client * client, struct nbd_request *request, int error ) int client_write_reply( struct client * client, struct nbd_request *request, int error )
{ {
return fd_write_reply( client->socket, request->handle.w, error); return fd_write_reply( client->socket, request->handle, error);
} }

View File

@@ -412,7 +412,7 @@ int mirror_setup_next_xfer( struct mirror_ctrl *ctrl )
struct nbd_request req = { struct nbd_request req = {
.magic = REQUEST_MAGIC, .magic = REQUEST_MAGIC,
.type = REQUEST_WRITE, .type = REQUEST_WRITE,
.handle.b = ".MIRROR.", .handle = ".MIRROR.",
.from = current, .from = current,
.len = run .len = run
}; };
@@ -568,7 +568,7 @@ static void mirror_read_cb( struct ev_loop *loop, ev_io *w, int revents )
return; return;
} }
if ( memcmp( ".MIRROR.", rsp.handle.b, 8 ) != 0 ) { if ( memcmp( ".MIRROR.", &rsp.handle[0], 8 ) != 0 ) {
warn( "Bad handle returned from listener" ); warn( "Bad handle returned from listener" );
ev_break( loop, EVBREAK_ONE ); ev_break( loop, EVBREAK_ONE );
return; return;
@@ -922,7 +922,7 @@ void* mirror_runner(void* serve_params_uncast)
* for us ). But if we've failed and are going to retry on the next run, we * for us ). But if we've failed and are going to retry on the next run, we
* must close this socket here to have any chance of it succeeding. * must close this socket here to have any chance of it succeeding.
*/ */
if ( !(mirror->client < 0) ) { if ( !mirror->client < 0 ) {
sock_try_close( mirror->client ); sock_try_close( mirror->client );
mirror->client = -1; mirror->client = -1;
} }

View File

@@ -32,7 +32,7 @@ module FlexNBD
txt_lines.each do |line| txt_lines.each do |line|
if line =~ /^#\s*define\s+([A-Z0-9_]+)\s+(\d+)\s*$/ if line =~ /^#\s*define\s+([A-Z0-9_]+)\s+(\d+)\s*$/
# Bodge until I can figure out what to do with #ifdefs # Bodge until I can figure out what to do with #ifdefs
const_set($1, $2.to_i) unless const_defined?( $1 ) const_set($1, $2.to_i) unless constants.include?( $1 )
end end
end end
end end

View File

@@ -3,10 +3,6 @@ require 'flexnbd/fake_source'
require 'flexnbd/fake_dest' require 'flexnbd/fake_dest'
module ProxyTests module ProxyTests
def b
"\xFF".b
end
def with_proxied_client( override_size = nil ) def with_proxied_client( override_size = nil )
@env.serve1 unless @server_up @env.serve1 unless @server_up
@env.proxy2 unless @proxy_up @env.proxy2 unless @proxy_up
@@ -55,7 +51,7 @@ module ProxyTests
with_proxied_client do |client| with_proxied_client do |client|
(0..3).each do |n| (0..3).each do |n|
offset = n * 4096 offset = n * 4096
client.write(offset, b * 4096) client.write(offset, "\xFF" * 4096)
rsp = client.read_response rsp = client.read_response
assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic]
@@ -64,7 +60,7 @@ module ProxyTests
data = @env.file1.read(offset, 4096) data = @env.file1.read(offset, 4096)
assert_equal( ( b * 4096 ), data, "Data not written correctly (offset is #{n})" ) assert_equal( ( "\xFF" * 4096 ), data, "Data not written correctly (offset is #{n})" )
end end
end end
end end
@@ -111,7 +107,7 @@ module ProxyTests
# The reply should be proxied back to the client. # The reply should be proxied back to the client.
sc2.write_reply( req2[:handle] ) sc2.write_reply( req2[:handle] )
sc2.write_data( b * 4096 ) sc2.write_data( "\xFF" * 4096 )
# Check it to make sure it's correct # Check it to make sure it's correct
rsp = timeout(15) { client.read_response } rsp = timeout(15) { client.read_response }
@@ -120,7 +116,7 @@ module ProxyTests
assert_equal req1[:handle], rsp[:handle] assert_equal req1[:handle], rsp[:handle]
data = client.read_raw( 4096 ) data = client.read_raw( 4096 )
assert_equal( (b * 4096), data, "Wrong data returned" ) assert_equal( ("\xFF" * 4096), data, "Wrong data returned" )
sc2.close sc2.close
server.close server.close
@@ -135,7 +131,7 @@ module ProxyTests
server, sc1 = maker.value server, sc1 = maker.value
# Send the read request to the proxy # Send the read request to the proxy
client.write( 0, ( b * 4096 ) ) client.write( 0, ( "\xFF" * 4096 ) )
# ensure we're given the read request # ensure we're given the read request
req1 = sc1.read_request req1 = sc1.read_request
@@ -144,7 +140,7 @@ module ProxyTests
assert_equal 0, req1[:from] assert_equal 0, req1[:from]
assert_equal 4096, req1[:len] assert_equal 4096, req1[:len]
data1 = sc1.read_data( 4096 ) data1 = sc1.read_data( 4096 )
assert_equal( ( b * 4096 ), data1, "Data not proxied successfully" ) assert_equal( ( "\xFF" * 4096 ), data1, "Data not proxied successfully" )
# Kill the server again, now we're sure the read request has been sent once # Kill the server again, now we're sure the read request has been sent once
sc1.close sc1.close

View File

@@ -6,7 +6,6 @@ class TestServeMode < Test::Unit::TestCase
def setup def setup
super super
@b = "\xFF".b
@env = Environment.new @env = Environment.new
@env.writefile1( "0" ) @env.writefile1( "0" )
@env.serve1 @env.serve1
@@ -54,18 +53,18 @@ class TestServeMode < Test::Unit::TestCase
assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic]
assert_equal 0, rsp[:error] assert_equal 0, rsp[:error]
client.write( 0, @b ) client.write( 0, "\xFF" )
rsp = client.read_response rsp = client.read_response
assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic]
assert_equal 0, rsp[:error] assert_equal 0, rsp[:error]
client.write( 0, @b * 2 ) client.write( 0, "\xFF\xFF" )
rsp = client.read_response rsp = client.read_response
assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic] assert_equal FlexNBD::REPLY_MAGIC, rsp[:magic]
assert_equal 0, rsp[:error] assert_equal 0, rsp[:error]
end end
assert_equal @b * 2, @env.file1.read( 0, 2 ) assert_equal "\xFF\xFF", @env.file1.read( 0, 2 )
end end

View File

@@ -66,9 +66,9 @@ START_TEST( test_receive_blocks_until_post )
END_TEST END_TEST
Suite* mbox_suite(void) Suite* acl_suite(void)
{ {
Suite *s = suite_create("mbox"); Suite *s = suite_create("acl");
TCase *tc_create = tcase_create("create"); TCase *tc_create = tcase_create("create");
TCase *tc_post = tcase_create("post"); TCase *tc_post = tcase_create("post");
@@ -93,7 +93,7 @@ int main(void)
log_level = 2; log_level = 2;
#endif #endif
int number_failed; int number_failed;
Suite *s = mbox_suite(); Suite *s = acl_suite();
SRunner *sr = srunner_create(s); SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL); srunner_run_all(sr, CK_NORMAL);
log_level = 0; log_level = 0;

View File

@@ -88,14 +88,14 @@ START_TEST(test_request_handle)
struct nbd_request_raw request_raw; struct nbd_request_raw request_raw;
struct nbd_request request; struct nbd_request request;
memcpy( request_raw.handle.b, "MYHANDLE", 8 ); memcpy( request_raw.handle, "MYHANDLE", 8 );
nbd_r2h_request( &request_raw, &request ); nbd_r2h_request( &request_raw, &request );
request_raw.handle.w = 0; memset( request_raw.handle, 0, 8 );
nbd_h2r_request( &request, &request_raw ); nbd_h2r_request( &request, &request_raw );
fail_unless( memcmp( request.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied." ); fail_unless( memcmp( request.handle, "MYHANDLE", 8 ) == 0, "The handle was not copied." );
fail_unless( memcmp( request_raw.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied back." ); fail_unless( memcmp( request_raw.handle, "MYHANDLE", 8 ) == 0, "The handle was not copied back." );
} }
END_TEST END_TEST
@@ -170,14 +170,14 @@ START_TEST(test_reply_handle)
struct nbd_reply_raw reply_raw; struct nbd_reply_raw reply_raw;
struct nbd_reply reply; struct nbd_reply reply;
memcpy( reply_raw.handle.b, "MYHANDLE", 8 ); memcpy( reply_raw.handle, "MYHANDLE", 8 );
nbd_r2h_reply( &reply_raw, &reply ); nbd_r2h_reply( &reply_raw, &reply );
reply_raw.handle.w = 0; memset( reply_raw.handle, 0, 8 );
nbd_h2r_reply( &reply, &reply_raw ); nbd_h2r_reply( &reply, &reply_raw );
fail_unless( memcmp( reply.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied." ); fail_unless( memcmp( reply.handle, "MYHANDLE", 8 ) == 0, "The handle was not copied." );
fail_unless( memcmp( reply_raw.handle.b, "MYHANDLE", 8 ) == 0, "The handle was not copied back." ); fail_unless( memcmp( reply_raw.handle, "MYHANDLE", 8 ) == 0, "The handle was not copied back." );
} }
END_TEST END_TEST
@@ -188,15 +188,14 @@ START_TEST( test_convert_from )
* nbd_request_raw */ * nbd_request_raw */
struct nbd_request_raw request_raw; struct nbd_request_raw request_raw;
struct nbd_request request; struct nbd_request request;
char readbuf[] = {0x80, 0, 0, 0, 0, 0, 0, 0};
uint64_t target = 0x8000000000000000; memcpy( &request_raw.from, readbuf, 8 );
/* this is stored big-endian */
request_raw.from = htobe64(target);
/* We expect this to convert big-endian to the host format */
nbd_r2h_request( &request_raw, &request ); nbd_r2h_request( &request_raw, &request );
uint64_t target = 1;
target <<= 63;
fail_unless( target == request.from, "from was wrong" ); fail_unless( target == request.from, "from was wrong" );
} }
END_TEST END_TEST

View File

@@ -22,7 +22,7 @@
int fd_read_request( int, struct nbd_request_raw *); int fd_read_request( int, struct nbd_request_raw *);
int fd_write_reply( int, uint64_t, int ); int fd_write_reply( int, char *, int );
int marker; int marker;
@@ -57,7 +57,7 @@ void * responder( void *respond_uncast )
fd_write_reply( sock_fd, wrong_handle, 0 ); fd_write_reply( sock_fd, wrong_handle, 0 );
} }
else { else {
fd_write_reply( sock_fd, resp->received.handle.w, 0 ); fd_write_reply( sock_fd, resp->received.handle, 0 );
} }
write( sock_fd, "12345678", 8 ); write( sock_fd, "12345678", 8 );
} }
@@ -150,7 +150,7 @@ END_TEST
Suite* readwrite_suite(void) Suite* readwrite_suite(void)
{ {
Suite *s = suite_create("readwrite"); Suite *s = suite_create("acl");
TCase *tc_transfer = tcase_create("entrust"); TCase *tc_transfer = tcase_create("entrust");
TCase *tc_disconnect = tcase_create("disconnect"); TCase *tc_disconnect = tcase_create("disconnect");

View File

@@ -141,9 +141,9 @@ START_TEST( test_fatal_doesnt_call_handler )
END_TEST END_TEST
Suite* util_suite(void) Suite* error_suite(void)
{ {
Suite *s = suite_create("util"); Suite *s = suite_create("error");
TCase *tc_process = tcase_create("process"); TCase *tc_process = tcase_create("process");
TCase *tc_handler = tcase_create("handler"); TCase *tc_handler = tcase_create("handler");
@@ -163,7 +163,7 @@ Suite* util_suite(void)
int main(void) int main(void)
{ {
int number_failed; int number_failed;
Suite *s = util_suite(); Suite *s = error_suite();
SRunner *sr = srunner_create(s); SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL); srunner_run_all(sr, CK_NORMAL);
number_failed = srunner_ntests_failed(sr); number_failed = srunner_ntests_failed(sr);