The only hit is the following code:
tlv_len = le16_to_cpu(tlv_hdr->tlv_len);
if (tlv_type == 0 || tlv_type > BTRFS_SEND_A_MAX
|| tlv_len > BTRFS_SEND_BUF_SIZE) {
error("invalid tlv in cmd tlv_type = %hu, tlv_len = %hu",
tlv_type, tlv_len);
@tlv_len is u16, while BTRFS_SEND_BUF_SIZE is 64K.
u16 MAX is 64K - 1, so the final check is always false.
Just remove it.
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Similar to the changes where strerror(errno) was converted, continue
with the remaining cases where the argument was stored in another
variable.
The savings in object size are about 4500 bytes:
$ size btrfs.old btrfs.new
text data bss dec hex filename
805055 24248 19748 849051 cf49b btrfs.old
804527 24248 19748 848523 cf28b btrfs.new
Signed-off-by: David Sterba <dsterba@suse.com>
The old check here tried to ensure that empty streams are not considered valid.
The old check however, will always fail when only one run through the while(1)
loop is needed and honor_end_cmd is set. So this:
btrfs send /some/subvol | btrfs receive -e /some/
will consistently fail because -e causes honor_cmd_to be set and
btrfs_read_and_process_send_stream() to correctly return 1. So the command will
be successful but btrfs receive will error out because the send - receive
concluded in one run through the while(1) loop.
If we want to exclude empty streams we need a way to tell the difference between
btrfs_read_and_process_send_stream() returning 1 because read_buf() did not
detect any data and read_and_process_cmd() returning 1 because honor_end_cmd was
set. Without introducing too many changes the best way to me seems to have
btrfs_read_and_process_send_stream() return -ENODATA in the first case. The rest
stays the same. We can then check for -ENODATA in do_receive() and report a
proper error in this case. This should also be backwards compatible to previous
versions of btrfs receive. They will fail on empty streams because a negative
value is returned. The only thing that they will lack is a nice error message.
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Read buffer helper mistakenly reported end of data as an error. Next, we
have to check if the first stream exists as an empty file is not a valid
stream.
Reported-by: Tsutomu Itoh <t-itoh@jp.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
The read_buf does not verify that we've read the expected number of
bytes. A corrupted of malformated stream will not be detdcted.
Signed-off-by: David Sterba <dsterba@suse.com>
gcc 4.9.0 gives warnings about possibly uninitialized values when
compiling with function inlining and optimization level two enabled
(CFLAGS="-finline-functions -O2").
Initializing the values fixes the warning. Hope this is correct.
Signed-off-by: Christian Hesse <mail@eworm.de>
Signed-off-by: David Sterba <dsterba@suse.cz>
A user reported corruption after receiving subvolumes. Turning up the
logging during the receive showed that the commands and string
attributes were being received correctly but the u64 attrbutes were
sometimes corrupted by having variable number of low order bytes
introduced.
It turned out they were on a platform that corrupts unaligned userspace
loads. Loading the u64s from the unaligned pointers into the received
command stream with get_unaligned() fixed the problem.
Reported-By: Klaus Holler <kho@gmx.at>
Tested-By: Klaus Holler <kho@gmx.at>
Signed-off-by: Zach Brown <zab@zabbo.net>
Signed-off-by: David Sterba <dsterba@suse.cz>
Due to either bugs in send (kernel) that generate a command against
a wrong path for example, or transient errors on the receiving side,
we stopped processing the send stream immediately and exited with
an error.
It's often desirable to continue processing the send stream even if an
error happens while processing a single command from the send stream.
This change just adds a --max-errors <N> parameter, whose default value
is 1 (preserving current behaviour), that allows to tolerate N errors
before stopping. A value of 0 means to never stop no matter how many
errors we get into while processing the send stream. Regardless of its
value, errors are always printed to stderr when they happen, just like
before this change.
Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com>
Signed-off-by: David Sterba <dsterba@suse.cz>
A new option is added to btrfs-receive to change the behavior when
an <end cmd> is received in the Btrfs send stream.
The traditional behavior (which still is the default) is to continue
to read the stream until an EOF condition is encountered. If an
<end cmd> is received, afterwards either an EOF or a new
<stream header> is expected.
The new behavior (if the -e option is set on the command line) is
to terminate after an <end cmd> is read without the need for an EOF.
This allows the stream (e.g. a single TCP stream) to carry additional
data or even multiple Btrfs send streams.
Old btrfs-send tools used to encode multiple snapshots like this
(with 2 snapshots in this example):
<stream header> + <sequence of commands> + <end cmd> +
<stream header> + <sequence of commands> + <end cmd> + EOF
If the new -e option is set, the expected format is like this:
<stream header> + <sequence of commands> +
<sequence of commands> + <end cmd>
The btrfs-send tool is changed in a seperate commit to always use
the new format, i.e. to send an <end cmd> only at the end.
Note that the currently existing receivers treat <end cmd> only as
an indication that a new <stream header> is following. This means,
you can just skip the sequence <end cmd> <stream header> without
loosing compatibility. As long as an EOF is following, the currently
existing receivers handle the new format (if the two new flags are
used) exactly as the old one.
The goal of changing the semantic of <end cmd> is to be able to use
a single stream (one TCP connection) to multiplex a request/response
handshake plus Btrfs send streams, all in the same stream. In this
case you cannot evaluate an EOF condition as an end of the Btrfs send
stream. You need something else, and the <end cmd> is just perfect
for this purpose.
Signed-off-by: Stefan Behrens <sbehrens@giantdisaster.de>
The flag and command are synced from kernel to user. Also, this patch adds a
callback for the BTRFS_SEND_C_UPDATE_EXTENT in struct btrfs_send_ops.
read_and_process_cmd() is updated to decode BTRFS_SEND_C_UPDATE_EXTENT and
send the values through the right callback. I did not add a callback
definition to cmds-receive.c as that code never uses
BTRFS_SEND_FLAG_NO_FILE_DATA.
Signed-off-by: Mark Fasheh <mfasheh@suse.de>
Add user space commands for btrfs send/receive.
Signed-off-by: Alexander Block <ablock84@googlemail.com>
Reviewed-by: David Sterba <dave@jikos.cz>
Reviewed-by: Arne Jansen <sensille@gmx.net>
Reviewed-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Reviewed-by: Alex Lyakas <alex.bolshoy.btrfs@gmail.com>