4 Commits

Author SHA1 Message Date
Patrick J Cherry
4cd7e764bb Updated changelog 2016-10-04 21:22:07 +01:00
Patrick J Cherry
4f535fbb02 Merge branch 'master' of gitlab.bytemark.co.uk:open-source/flexnbd-c into debian 2016-10-04 21:14:26 +01:00
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
22 changed files with 3235 additions and 337 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
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)
LIB=build/
EXISTING_OBJS := $(wildcard build/*.o)
-include $(EXISTING_OBJS:.o=.d)
COMMON_SRC := $(wildcard src/common/*.c)
SERVER_SRC := $(wildcard src/server/*.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)
all: build doc
build: server proxy
all: build/flexnbd build/flexnbd-proxy doc
build/%.o: %.c
mkdir -p $(dir $@)
$(COMPILE) $< -o $@
$(SAVEDEP) $< > build/$*.d
objs: $(OBJS)
@@ -84,42 +87,41 @@ build/flexnbd-proxy: $(COMMON_OBJ) $(PROXY_OBJ) build/proxy-main.o
$(LINK) $^ -o $@
server: build/flexnbd
proxy: build/flexnbd-proxy
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.
build/tests/%.o: tests/unit/%.c
mkdir -p $(dir $@)
$(COMPILE) $< -o $@
$(SAVEDEP) $< > build/tests/$*.d
CHECK_BINS := $(CHECK_SRC:tests/unit/%.c=build/%)
build/check_%: build/check_%.o
$(LINK) $^ -o $@ $(COMMON_OBJ) $(SERVER_OBJ) -lcheck
CHECK_BINS := $(CHECK_OBJ:build/tests/%.o=build/tests/%)
build/tests/%: build/tests/%.o $(OBJS)
$(LINK) $^ -o $@ -lcheck
check_objs: $(CHECK_OBJ)
check_bins: $(CHECK_BINS)
check: $(OBJS) $(CHECK_BINS)
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
check: $(CHECK_BINS)
for bin in $^; do $$bin; done
build/flexnbd.1: README.txt
txt2man -t flexnbd -s 1 $< > $@
a2x --destination-dir build --format manpage $<
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
# to rebuild each time
%.1.gz: %.1
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:
mkdir -p $(INSTALLDIR)
@@ -129,7 +131,4 @@ clean:
rm -rf build/*
.PHONY: clean objs check_objs all server proxy check_bins check doc build test acceptance
# Include extra dependencies at the end, NOT before 'all'
-include $(wildcard build/*.d)
.PHONY: clean objs check_objs all server proxy check_bins check server-man proxy-man doc

View File

@@ -1,14 +1,19 @@
NAME
FLEXNBD-PROXY(1)
================
:doctype: manpage
flexnbd-proxy - A simple NBD proxy
NAME
----
flexnbd-proxy - A simple NBD proxy
SYNOPSIS
--------
flexnbd-proxy --addr ADDR [--port PORT] --conn-addr ADDR
--conn-port PORT [--bind ADDR] [--cache[=CACHE_BYTES]]
[--help] [--verbose] [--quiet]
*flexnbd-proxy* ['OPTIONS']
DESCRIPTION
-----------
flexnbd-proxy is a simple NBD proxy server that implements resilient
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.
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
client can be connected at a time, and ACLs cannot be applied to the client, as they
@@ -48,73 +58,75 @@ 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
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
a UNIX domain socket to create. Otherwise, it should be an IPv4 or IPv6
address.
--port, -p PORT
*--port, -p PORT*:
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.
--conn-port, -P PORT
*--conn-port, -P PORT*:
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
defaults to 4096.
--help, -h
*--help, -h* :
Show command or global help.
--verbose, -v
*--verbose, -v* :
Output all available log information to STDERR.
--quiet, -q
*--quiet, -q* :
Output as little log information as possible to STDERR.
LOGGING
Log output is sent to STDERR. If --quiet is set, no output will be
seen unless the program termintes abnormally. If neither --quiet nor
LOGGING
-------
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
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
error to set both --verbose and --quiet. The last one wins.
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
error to set both --verbose and --quiet. The last one wins.
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
<LEVEL>
*LEVEL*:
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
be seen. If it is started with the --verbose flag, any from 'I'
upwards will be seen. Only if you have a debug build and start it
with --verbose will you see 'D' entries.
severity. If flexnbd is started with the --quiet flag, only 'F' will be
seen. If it is started with the --verbose flag, any from 'I' upwards
will be seen. Only if you have a debug build and start it with
--verbose will you see 'D' entries.
<PID>
*PID*:
This is the process ID.
<THREAD>
flexnbd-proxy is currently single-threaded, so this should be the
same for all lines. That may not be the case in the future.
*THREAD*:
flexnbd-proxy is currently single-threaded, so this should be the same
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.
<MSG>
*MSG*:
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
when the NBD server goes away (during a migration, for instance) to see a
@@ -148,59 +160,53 @@ The data in myfile has been moved between physical servers without the nbd
client process having to be disturbed at all.
READ CACHE
----------
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
read-ahead cache. The cache as currently implemented doubles each read
read-ahead cache. The cache as currently implemented doubles each read
request size, up to a maximum of 2xCACHE_BYTES, and retains the latter
half in a buffer. If the next read request from the client exactly
half in a buffer. If the next read request from the client exactly
matches the region held in the buffer, flexnbd-proxy responds from the
cache without making a request to the server.
This pattern is designed to match sequential reads, such as those
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
That is, the '=' is required. This is a limitation of getopt-long.
That is, the '=' is required. This is a limitation of getopt-long.
If no cache size is given, a size of 4096 bytes is assumed. Caching can
be explicitly disabled by setting a size of 0.
BUGS
----
Should be reported via GitHub.
* https://github.com/BytemarkHosting/flexnbd-c/issues
Should be reported to nick@bytemark.co.uk.
Current issues include:
* only old-style NBD negotiation is supported;
* only one request may be in-flight at a time;
* all I/O is blocking, and signals terminate the process immediately;
* UNIX socket support is limited to the listen address;
* FLUSH and TRIM commands, and the FUA flag, are not supported;
* DISCONNECT requests do not get passed through to the NBD server;
* no active timeout-retry of requests - we trust the kernel's idea of
failure.
* Only old-style NBD negotiation is supported
* Only one request may be in-flight at a time
* All I/O is blocking, and signals terminate the process immediately
* UNIX socket support is limited to the listen address
* FLUSH and TRIM commands, and the FUA flag, are not supported
* DISCONNECT requests do not get passed through to the NBD server
* No active timeout-retry of requests - we trust the kernel's idea of failure
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>.
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
flexnbd(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.
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.

View File

@@ -1,36 +1,17 @@
NAME
FLEXNBD(1)
==========
:doctype: manpage
NAME
----
flexnbd - A fast NBD server
SYNOPSIS
flexnbd MODE [ ARGS ]
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]*
--------
*flexnbd* 'COMMAND' ['OPTIONS']
DESCRIPTION
-----------
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 will be invisible to any connected clients.
@@ -38,290 +19,304 @@ migration will be invisible to any connected clients.
Flexnbd tries quite hard to preserve sparsity of files it is serving,
even across migrations.
SERVE MODE
Serve a file.
COMMANDS
--------
serve
~~~~~
$ flexnbd serve --addr <ADDR> --port <PORT> --file <FILE>
[--sock <SOCK>] [--default-deny] [-k] [global_option]*
[acl_entry]*
[--sock <SOCK>] [--default-deny] [-k] [global option]* [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.
flexnbd will continue to serve until a SIGINT, SIGQUIT, or a successful
migration.
OPTIONS
Options
^^^^^^^
--addr, -l ADDR
*--addr, -l ADDR*:
The address to listen on. Required.
--port, -p PORT
*--port, -p PORT*:
The port to listen on. Required.
--file, -f FILE
*--file, -f FILE*:
The file to serve. Must already exist. Required.
--sock, -s SOCK
Path to a control socket to open. You will need this if you want to
*--sock, -s SOCK*:
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
list.
--default-deny, -d
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
*--default-deny, -d*:
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 any client connect.
--killswitch, -k
*--killswitch, -k*:
If set, we implement a 2-minute timeout on NBD requests and
responses. If a request takes longer than that to complete,
the client is disconnected. This is useful to keep broken
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
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
to write the inbound migration data to must already exist before you
run 'flexnbd listen'.
Only one sender may connect to send data, and if the sender
disconnects part-way through the migration, the destination will
expect it to reconnect and retry the whole migration. It isn't safe
expect it to reconnect and retry the whole migration. It isn't safe
to assume that a partial migration can be resumed because the
destination has no knowledge of whether a client has made a write to
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
status. In this case, the sender will continually retry the migration
until it succeeds, and you will need to restart the 'flexnbd listen'
status. In this case, the sender will continually retry the migration
until it succeeds, and you will need to restart the `flexnbd listen`
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
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'
process until it completes, it will exit with a message of "Migration
started" once it has confirmation that the local server was able to
connect to ADDR:PORT and got an NBD header back. To check on the
connect to ADDR:PORT and got an NBD header back. To check on the
progress of a running migration, use 'flexnbd status'.
If the destination unexpectedly disconnects part-way through the
migration, the source will attempt to reconnect and start the migration
again. It is not safe to resume the migration from where it left off
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
destination is intact, or even on the same machine.
If the --unlink option is given, the local file will be deleted
immediately before the mirror connection is terminated. This allows
If the `--unlink` option is given, the local file will be deleted
immediately before the mirror connection is terminated. This allows
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
possible to tell which copy of the data is canonical. Since the
possible to tell which copy of the data is canonical. Since the
unlink happens as soon as the sender knows that it has transmitted all
the data, there can be no ambiguity.
Note: files smaller than 4096 bytes cannot be mirrored.
OPTIONS
Options
^^^^^^^
--addr, -l ADDR
The address of the remote server to migrate to. Required.
*--addr, -l ADDR*:
The address of the remote server to migrate to. Required.
--port, -p PORT
The port of the remote server to migrate to. Required.
*--port, -p PORT*:
The port of the remote server to migrate to. Required.
--sock, -s SOCK
The control socket of the local server to migrate from. Required.
*--sock, -s SOCK*:
The control socket of the local server to migrate from. Required.
--unlink, -u
Unlink the served file from the local filesystem after
successfully mirroring.
*--unlink, -u*:
Unlink the served file from the local filesystem after successfully
mirroring.
--bind, -b BIND_ADDR
The local address to bind to. You may need this if the remote
server is using an access control list.
*--bind, -b BIND-ADDR*:
The local address to bind to. You may need this if the remote server
is using an access control list.
BREAK MODE
break
~~~~~
$ flexnbd mirror --sock SOCK [global option]*
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.
Required.
--sock, -s SOCK
The control socket of the local server whose migration to stop.
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
to the given access control list entries.
$ flexnbd acl --sock SOCK [acl_entry]+ [global_option]*
ACL entries are given as IP addresses.
OPTIONS
Options
^^^^^^^
--sock, -s SOCK
The control socket of the server whose ACL to replace. Required
*--sock, -s SOCK*:
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.
$ flexnbd status --sock SOCK [global_option]*
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
value. Currently reported values are:
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
value. Currently reported values are:
pid
*pid*:
The process id of the server listening on SOCK.
is_mirroring
*is_mirroring*:
'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.
OPTIONS
read
~~~~
--sock, -s SOCK
The control socket of the server of interest. Required.
READ MODE
$ flexnbd read --addr <ADDR> --port <PORT> --from <OFFSET>
--size <SIZE> [--bind BIND-ADDR] [global option]*
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
[--bind BIND_ADDR] [global_option]*
Options
^^^^^^^
The returned data will be echoed to STDOUT. In case of a remote ACL,
set the local source address to BIND_ADDR.
*--addr, -l ADDR*:
The address of the remote server. Required.
OPTIONS
*--port, -p PORT*:
The port of the remote server. Required.
--addr, -l ADDR
The address of the remote server. Required.
*--from, -F OFFSET*:
The byte offset to start reading from. Required. Maximum 2^62.
--port, -p PORT
The port of the remote server. Required.
*--size, -S SIZE*:
The number of bytes to read. Required. Maximum 2^30.
--from, -F OFFSET
The byte offset to start reading from. Required. Maximum 2^62.
*--bind, -b BIND-ADDR*:
The local address to bind to. You may need this if the remote server
is using an access control list.
--size, -S SIZE
The number of bytes to read. Required. Maximum 2^30.
write
~~~~~
--bind, -b BIND_ADDR
The local address to bind to. You may need this if the remote
server is using an access control list.
WRITE MODE
$ 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
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
--size SIZE [--bind BIND_ADDR] [global_option]*
Options
^^^^^^^
In case of a remote ACL, set the local source address to BIND_ADDR.
*--addr, -l ADDR*:
The address of the remote server. Required.
OPTIONS
*--port, -p PORT*:
The port of the remote server. Required.
--addr, -l ADDR
The address of the remote server. Required.
*--from, -F OFFSET*:
The byte offset to start writing from. Required. Maximum 2^62.
--port, -p PORT
The port of the remote server. Required.
*--size, -S SIZE*:
The number of bytes to write. Required. Maximum 2^30.
--from, -F OFFSET
The byte offset to start writing from. Required. Maximum 2^62.
*--bind, -b BIND-ADDR*:
The local address to bind to. You may need this if the remote server
is using an access control list.
--size, -S SIZE
The number of bytes to write. Required. Maximum 2^30.
help
~~~~
--bind, -b BIND_ADDR
The local address to bind to. You may need this if the remote
server is using an access control list.
$ flexnbd help [command] [global option]*
HELP MODE
$ flexnbd help [mode] [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
--------------
--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
Log output is sent to STDERR. If --quiet is set, no output will be
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
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
error to set both --verbose and --quiet. The last one wins.
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
error to set both --verbose and --quiet. The last one wins.
The log line format is:
<TIMESTAMP>:<LEVEL>:<PID> <THREAD> <SOURCEFILE:SOURCELINE>: <MSG>
<TIMESTAMP>:<LEVEL>:<PID> <THREAD> <SOURCEFILE>:<SOURCELINE>: <MSG>
<TIMESTAMP>
Time the log entry was made. This is expressed in terms of monotonic
ms.
*TIMESTAMP*:
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
severity. If flexnbd is started with the --quiet flag, only 'F'
will be seen. If it is started with the --verbose flag, any from 'I'
upwards will be seen. Only if you have a debug build and start it
with --verbose will you see 'D' entries.
severity. If flexnbd is started with the --quiet flag, only 'F' will be
seen. If it is started with the --verbose flag, any from 'I' upwards
will be seen. Only if you have a debug build and start it with
--verbose will you see 'D' entries.
<PID>
*PID*:
This is the process ID.
<THREAD>
There are several pthreads per flexnbd process: a main thread, a
serve thread, a thread per client, and possibly a pair of mirror
threads and a control thread. This field identifies which thread was
responsible for the log line.
*THREAD*:
There are several pthreads per flexnbd process: a main thread, a serve
thread, a thread per client, and possibly a pair of mirror threads and a
control thread. This field identifies which thread was responsible for
the log line.
<SOURCEFILE:SOURCELINE>
*SOURCEFILE:SOURCELINE*:
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
if you're very lucky why it's going on.
if you're very lucky *why* it's going on.
EXAMPLES
--------
SERVING A FILE
Serving a file
~~~~~~~~~~~~~~
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:
$
READING SERVER STATUS
Reading server status
~~~~~~~~~~~~~~~~~~~~~
In order to read a server's status, we need it to open a control socket.
@@ -339,12 +335,13 @@ In order to read a server's status, we need it to open a control socket.
--sock /tmp/flexnbd.sock
$ flexnbd status --sock /tmp/flexnbd.sock
pid=9635 is_mirroring=false has_control=true
$
Note that the status output is newline-terminated.
MIGRATING
Migrating
~~~~~~~~~
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 \
--sock /tmp/flex-source.sock
Migration started
[1] + 9648 done flexnbd serve --addr 0.0.0.0 --port 4778
[2] + 9651 done flexnbd listen --addr 0.0.0.0 --port 4779
[1] + 9648 done build/flexnbd serve --addr 0.0.0.0 --port 4778
[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
@@ -379,25 +376,21 @@ server quit soon after we start the migration, and the destination
exited at roughly the same time.
BUGS
----
Should be reported on GitHub at
* https://github.com/BytemarkHosting/flexnbd-c/issues
Should be reported to alex@bytemark.co.uk.
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>.
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"

2755
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

@@ -255,7 +255,7 @@ int tryjoin_client_thread( struct client_tbl_entry *entry, int (*joinfunc)(pthre
debug("nbd thread %016x exited (%s) with status %ld",
entry->thread,
s_client_address,
(uintptr_t)status);
(uint64_t)status);
client_destroy( entry->client );
entry->client = NULL;
entry->thread = 0;

View File

@@ -32,7 +32,7 @@ module FlexNBD
txt_lines.each do |line|
if line =~ /^#\s*define\s+([A-Z0-9_]+)\s+(\d+)\s*$/
# 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

View File

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

View File

@@ -115,11 +115,6 @@ class TestHappyPath < Test::Unit::TestCase
def test_write_to_high_block
#
# This test does not work on 32 bit platforms.
#
skip("Not relevant on 32-bit platforms") if ( ["a"].pack("p").size < 8 )
# Create a large file, then try to write to somewhere after the 2G boundary
@env.truncate1 "4G"
@env.serve1

View File

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

View File

@@ -59,7 +59,7 @@ END_TEST
START_TEST(test_bit_ranges)
{
bitfield_word_t buffer[BIT_WORDS_FOR_SIZE(4160)];
uint64_t *longs = (uint64_t *) buffer;
uint64_t *longs = (unsigned long*) buffer;
uint64_t i;
memset(buffer, 0, 4160);
@@ -67,9 +67,9 @@ START_TEST(test_bit_ranges)
for (i=0; i<64; i++) {
bit_set_range(buffer, i*64, i);
fail_unless(
longs[i] == (1ULL<<i)-1,
longs[i] == (1UL<<i)-1,
"longs[%ld] = %lx SHOULD BE %lx",
i, longs[i], (1ULL<<i)-1
i, longs[i], (1L<<i)-1
);
fail_unless(longs[i+1] == 0, "bit_set_range overshot at i=%d", i);

View File

@@ -66,9 +66,9 @@ START_TEST( test_receive_blocks_until_post )
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_post = tcase_create("post");
@@ -93,7 +93,7 @@ int main(void)
log_level = 2;
#endif
int number_failed;
Suite *s = mbox_suite();
Suite *s = acl_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
log_level = 0;

View File

@@ -88,14 +88,14 @@ START_TEST(test_request_handle)
struct nbd_request_raw request_raw;
struct nbd_request request;
memcpy( request_raw.handle.b, "MYHANDLE", 8 );
memcpy( request_raw.handle, "MYHANDLE", 8 );
nbd_r2h_request( &request_raw, &request );
request_raw.handle.w = 0;
memset( request_raw.handle, 0, 8 );
nbd_h2r_request( &request, &request_raw );
fail_unless( memcmp( request.handle.b, "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.handle, "MYHANDLE", 8 ) == 0, "The handle was not copied." );
fail_unless( memcmp( request_raw.handle, "MYHANDLE", 8 ) == 0, "The handle was not copied back." );
}
END_TEST
@@ -170,14 +170,14 @@ START_TEST(test_reply_handle)
struct nbd_reply_raw reply_raw;
struct nbd_reply reply;
memcpy( reply_raw.handle.b, "MYHANDLE", 8 );
memcpy( reply_raw.handle, "MYHANDLE", 8 );
nbd_r2h_reply( &reply_raw, &reply );
reply_raw.handle.w = 0;
memset( reply_raw.handle, 0, 8 );
nbd_h2r_reply( &reply, &reply_raw );
fail_unless( memcmp( reply.handle.b, "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.handle, "MYHANDLE", 8 ) == 0, "The handle was not copied." );
fail_unless( memcmp( reply_raw.handle, "MYHANDLE", 8 ) == 0, "The handle was not copied back." );
}
END_TEST
@@ -188,15 +188,14 @@ START_TEST( test_convert_from )
* nbd_request_raw */
struct nbd_request_raw request_raw;
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 );
uint64_t target = 1;
target <<= 63;
fail_unless( target == request.from, "from was wrong" );
}
END_TEST

View File

@@ -22,7 +22,7 @@
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;
@@ -46,7 +46,8 @@ void * responder( void *respond_uncast )
struct respond * resp = (struct respond *) respond_uncast;
int sock_fd = resp->sock_fds[1];
struct nbd_request_raw request_raw;
uint64_t wrong_handle = 0x80;
char wrong_handle[] = "WHOOPSIE";
if( fd_read_request( sock_fd, &request_raw ) == -1){
fprintf(stderr, "Problem with fd_read_request\n");
@@ -56,7 +57,7 @@ void * responder( void *respond_uncast )
fd_write_reply( sock_fd, wrong_handle, 0 );
}
else {
fd_write_reply( sock_fd, resp->received.handle.w, 0 );
fd_write_reply( sock_fd, (char*)resp->received.handle.b, 0 );
}
write( sock_fd, "12345678", 8 );
}
@@ -149,7 +150,7 @@ END_TEST
Suite* readwrite_suite(void)
{
Suite *s = suite_create("readwrite");
Suite *s = suite_create("acl");
TCase *tc_transfer = tcase_create("entrust");
TCase *tc_disconnect = tcase_create("disconnect");

View File

@@ -141,9 +141,9 @@ START_TEST( test_fatal_doesnt_call_handler )
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_handler = tcase_create("handler");
@@ -163,7 +163,7 @@ Suite* util_suite(void)
int main(void)
{
int number_failed;
Suite *s = util_suite();
Suite *s = error_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
number_failed = srunner_ntests_failed(sr);