|
|
dbfe2d |
From 7e5cd32fbb38103b11a8a87ca5af943d0fb2804a Mon Sep 17 00:00:00 2001
|
|
|
dbfe2d |
From: Boris Burkov <borisb@fb.com>
|
|
|
dbfe2d |
Date: Fri, 21 Aug 2020 00:40:00 -0700
|
|
|
dbfe2d |
Subject: [PATCH] btrfs-progs: receive: support v2 send stream larger tlv_len
|
|
|
dbfe2d |
|
|
|
dbfe2d |
An encoded extent can be up to 128K in length, which exceeds the largest
|
|
|
dbfe2d |
value expressible by the current send stream format's 16 bit tlv_len
|
|
|
dbfe2d |
field. Since encoded writes cannot be split into multiple writes by
|
|
|
dbfe2d |
btrfs send, the send stream format must change to accommodate encoded
|
|
|
dbfe2d |
writes.
|
|
|
dbfe2d |
|
|
|
dbfe2d |
Supporting this changed format requires retooling how we store the
|
|
|
dbfe2d |
commands we have processed. We currently store pointers to the struct
|
|
|
dbfe2d |
btrfs_tlv_headers in the command buffer. This is not sufficient to
|
|
|
dbfe2d |
represent the new BTRFS_SEND_A_DATA format. Instead, parse the attribute
|
|
|
dbfe2d |
headers and store them in a new struct btrfs_send_attribute which has a
|
|
|
dbfe2d |
32-bit length field. This is transparent to users of the various TLV_GET
|
|
|
dbfe2d |
macros.
|
|
|
dbfe2d |
|
|
|
dbfe2d |
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
|
|
|
dbfe2d |
Signed-off-by: Boris Burkov <boris@bur.io>
|
|
|
dbfe2d |
---
|
|
|
dbfe2d |
common/send-stream.c | 34 +++++++++++++++++++++++++---------
|
|
|
dbfe2d |
1 file changed, 25 insertions(+), 9 deletions(-)
|
|
|
dbfe2d |
|
|
|
dbfe2d |
diff --git a/common/send-stream.c b/common/send-stream.c
|
|
|
dbfe2d |
index e9be922b..7d182238 100644
|
|
|
dbfe2d |
--- a/common/send-stream.c
|
|
|
dbfe2d |
+++ b/common/send-stream.c
|
|
|
dbfe2d |
@@ -24,13 +24,23 @@
|
|
|
dbfe2d |
#include "crypto/crc32c.h"
|
|
|
dbfe2d |
#include "common/utils.h"
|
|
|
dbfe2d |
|
|
|
dbfe2d |
+struct btrfs_send_attribute {
|
|
|
dbfe2d |
+ u16 tlv_type;
|
|
|
dbfe2d |
+ /*
|
|
|
dbfe2d |
+ * Note: in btrfs_tlv_header, this is __le16, but we need 32 bits for
|
|
|
dbfe2d |
+ * attributes with file data as of version 2 of the send stream format
|
|
|
dbfe2d |
+ */
|
|
|
dbfe2d |
+ u32 tlv_len;
|
|
|
dbfe2d |
+ char *data;
|
|
|
dbfe2d |
+};
|
|
|
dbfe2d |
+
|
|
|
dbfe2d |
struct btrfs_send_stream {
|
|
|
dbfe2d |
char read_buf[BTRFS_SEND_BUF_SIZE];
|
|
|
dbfe2d |
int fd;
|
|
|
dbfe2d |
|
|
|
dbfe2d |
int cmd;
|
|
|
dbfe2d |
struct btrfs_cmd_header *cmd_hdr;
|
|
|
dbfe2d |
- struct btrfs_tlv_header *cmd_attrs[BTRFS_SEND_A_MAX + 1];
|
|
|
dbfe2d |
+ struct btrfs_send_attribute cmd_attrs[BTRFS_SEND_A_MAX + 1];
|
|
|
dbfe2d |
u32 version;
|
|
|
dbfe2d |
|
|
|
dbfe2d |
/*
|
|
|
dbfe2d |
@@ -152,6 +162,7 @@ static int read_cmd(struct btrfs_send_stream *sctx)
|
|
|
dbfe2d |
struct btrfs_tlv_header *tlv_hdr;
|
|
|
dbfe2d |
u16 tlv_type;
|
|
|
dbfe2d |
u16 tlv_len;
|
|
|
dbfe2d |
+ struct btrfs_send_attribute *send_attr;
|
|
|
dbfe2d |
|
|
|
dbfe2d |
tlv_hdr = (struct btrfs_tlv_header *)data;
|
|
|
dbfe2d |
tlv_type = le16_to_cpu(tlv_hdr->tlv_type);
|
|
|
dbfe2d |
@@ -164,10 +175,15 @@ static int read_cmd(struct btrfs_send_stream *sctx)
|
|
|
dbfe2d |
goto out;
|
|
|
dbfe2d |
}
|
|
|
dbfe2d |
|
|
|
dbfe2d |
- sctx->cmd_attrs[tlv_type] = tlv_hdr;
|
|
|
dbfe2d |
+ send_attr = &sctx->cmd_attrs[tlv_type];
|
|
|
dbfe2d |
+ send_attr->tlv_type = tlv_type;
|
|
|
dbfe2d |
+ send_attr->tlv_len = tlv_len;
|
|
|
dbfe2d |
+ pos += sizeof(*tlv_hdr);
|
|
|
dbfe2d |
+ data += sizeof(*tlv_hdr);
|
|
|
dbfe2d |
|
|
|
dbfe2d |
- data += sizeof(*tlv_hdr) + tlv_len;
|
|
|
dbfe2d |
- pos += sizeof(*tlv_hdr) + tlv_len;
|
|
|
dbfe2d |
+ send_attr->data = data;
|
|
|
dbfe2d |
+ pos += send_attr->tlv_len;
|
|
|
dbfe2d |
+ data += send_attr->tlv_len;
|
|
|
dbfe2d |
}
|
|
|
dbfe2d |
|
|
|
dbfe2d |
sctx->cmd = cmd;
|
|
|
dbfe2d |
@@ -180,7 +196,7 @@ out:
|
|
|
dbfe2d |
static int tlv_get(struct btrfs_send_stream *sctx, int attr, void **data, int *len)
|
|
|
dbfe2d |
{
|
|
|
dbfe2d |
int ret;
|
|
|
dbfe2d |
- struct btrfs_tlv_header *hdr;
|
|
|
dbfe2d |
+ struct btrfs_send_attribute *send_attr;
|
|
|
dbfe2d |
|
|
|
dbfe2d |
if (attr <= 0 || attr > BTRFS_SEND_A_MAX) {
|
|
|
dbfe2d |
error("invalid attribute requested, attr = %d", attr);
|
|
|
dbfe2d |
@@ -188,15 +204,15 @@ static int tlv_get(struct btrfs_send_stream *sctx, int attr, void **data, int *l
|
|
|
dbfe2d |
goto out;
|
|
|
dbfe2d |
}
|
|
|
dbfe2d |
|
|
|
dbfe2d |
- hdr = sctx->cmd_attrs[attr];
|
|
|
dbfe2d |
- if (!hdr) {
|
|
|
dbfe2d |
+ send_attr = &sctx->cmd_attrs[attr];
|
|
|
dbfe2d |
+ if (!send_attr->data) {
|
|
|
dbfe2d |
error("attribute %d requested but not present", attr);
|
|
|
dbfe2d |
ret = -ENOENT;
|
|
|
dbfe2d |
goto out;
|
|
|
dbfe2d |
}
|
|
|
dbfe2d |
|
|
|
dbfe2d |
- *len = le16_to_cpu(hdr->tlv_len);
|
|
|
dbfe2d |
- *data = hdr + 1;
|
|
|
dbfe2d |
+ *len = send_attr->tlv_len;
|
|
|
dbfe2d |
+ *data = send_attr->data;
|
|
|
dbfe2d |
|
|
|
dbfe2d |
ret = 0;
|
|
|
dbfe2d |
|
|
|
dbfe2d |
--
|
|
|
dbfe2d |
2.35.1
|
|
|
dbfe2d |
|