Message ID | eebf24d3b42ef50a19ba9bc38ed5210d0cc87157.1597994106.git.osandov@osandov.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | btrfs: implement send/receive of compressed extents without decompressing | expand |
On 8/21/20 3:39 AM, Omar Sandoval wrote: > From: Omar Sandoval <osandov@fb.com> > > The length field of the send stream TLV header is 16 bits. This means > that the maximum amount of data that can be sent for one write is 64k > minus one. However, encoded writes must be able to send the maximum > compressed extent (128k) in one command. To support this, send stream > version 2 encodes the DATA attribute differently: it has no length > field, and the length is implicitly up to the end of containing command > (which has a 32-bit length field). Although this is necessary for > encoded writes, normal writes can benefit from it, too. > > For v2, let's bump up the send buffer to the maximum compressed extent > size plus 16k for the other metadata (144k total). Since this will most > likely be vmalloc'd (and always will be after the next commit), we round > it up to the next page since we might as well use the rest of the page > on systems with >16k pages. > > Signed-off-by: Omar Sandoval <osandov@fb.com> > --- > fs/btrfs/send.c | 34 ++++++++++++++++++++++++++-------- > 1 file changed, 26 insertions(+), 8 deletions(-) > > diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c > index e25c3391fc02..c0f81d302f49 100644 > --- a/fs/btrfs/send.c > +++ b/fs/btrfs/send.c > @@ -4799,14 +4799,27 @@ static u64 max_send_read_size(struct send_ctx *sctx) > > static int put_data_header(struct send_ctx *sctx, u32 len) > { > - struct btrfs_tlv_header *hdr; > + if (sctx->flags & BTRFS_SEND_FLAG_STREAM_V2) { > + __le16 tlv_type; > + > + if (sctx->send_max_size - sctx->send_size < > + sizeof(tlv_type) + len) > + return -EOVERFLOW; > + tlv_type = cpu_to_le16(BTRFS_SEND_A_DATA); > + memcpy(sctx->send_buf + sctx->send_size, &tlv_type, > + sizeof(tlv_type)); > + sctx->send_size += sizeof(tlv_type); Can we add a comment for implied length thing here? I was reviewing this in vimdiff without the commit message so missed the implied length detail. Thanks, Josef
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index e25c3391fc02..c0f81d302f49 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -4799,14 +4799,27 @@ static u64 max_send_read_size(struct send_ctx *sctx) static int put_data_header(struct send_ctx *sctx, u32 len) { - struct btrfs_tlv_header *hdr; + if (sctx->flags & BTRFS_SEND_FLAG_STREAM_V2) { + __le16 tlv_type; + + if (sctx->send_max_size - sctx->send_size < + sizeof(tlv_type) + len) + return -EOVERFLOW; + tlv_type = cpu_to_le16(BTRFS_SEND_A_DATA); + memcpy(sctx->send_buf + sctx->send_size, &tlv_type, + sizeof(tlv_type)); + sctx->send_size += sizeof(tlv_type); + } else { + struct btrfs_tlv_header *hdr; - if (sctx->send_max_size - sctx->send_size < sizeof(*hdr) + len) - return -EOVERFLOW; - hdr = (struct btrfs_tlv_header *)(sctx->send_buf + sctx->send_size); - hdr->tlv_type = cpu_to_le16(BTRFS_SEND_A_DATA); - hdr->tlv_len = cpu_to_le16(len); - sctx->send_size += sizeof(*hdr); + if (sctx->send_max_size - sctx->send_size < sizeof(*hdr) + len) + return -EOVERFLOW; + hdr = (struct btrfs_tlv_header *)(sctx->send_buf + + sctx->send_size); + hdr->tlv_type = cpu_to_le16(BTRFS_SEND_A_DATA); + hdr->tlv_len = cpu_to_le16(len); + sctx->send_size += sizeof(*hdr); + } return 0; } @@ -7136,7 +7149,12 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg) sctx->clone_roots_cnt = arg->clone_sources_count; - sctx->send_max_size = BTRFS_SEND_BUF_SIZE_V1; + if (sctx->flags & BTRFS_SEND_FLAG_STREAM_V2) { + sctx->send_max_size = ALIGN(SZ_16K + BTRFS_MAX_COMPRESSED, + PAGE_SIZE); + } else { + sctx->send_max_size = BTRFS_SEND_BUF_SIZE_V1; + } sctx->send_buf = kvmalloc(sctx->send_max_size, GFP_KERNEL); if (!sctx->send_buf) { ret = -ENOMEM;