public inbox for linux-btrfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Omar Sandoval <osandov@osandov.com>
To: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
Cc: linux-btrfs@vger.kernel.org, kernel-team@fb.com
Subject: Re: [PATCH v14 4/7] btrfs: send: write larger chunks when using stream v2
Date: Wed, 30 Mar 2022 10:05:57 -0700	[thread overview]
Message-ID: <YkSN9bKLA8m2/0Lh@relinquished.localdomain> (raw)
In-Reply-To: <757b48b9-db01-e8d0-ec64-02443828dd7a@dorminy.me>

On Thu, Mar 24, 2022 at 01:52:53PM -0400, Sweet Tea Dorminy wrote:
> 
> > diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
> > index 1f141de3a7d6..02053fff80ca 100644
> > --- a/fs/btrfs/send.c
> > +++ b/fs/btrfs/send.c
> > @@ -82,6 +82,7 @@ struct send_ctx {
> >   	char *send_buf;
> >   	u32 send_size;
> >   	u32 send_max_size;
> > +	bool put_data;
> put_data's use seems to be about making sure put_data_header() isn't called
> more than once, which is not super obvious to me from the name; perhaps one
> of 'data_header_{set,setup,initialized}' might make it clearer? Or if it's
> actually about put_file_data, maybe moving the assertion there would make
> that clearer?

The intention is to prevent adding another attribute after a data
attribute, since that's impossible with v2. Notice that it's also
checked in tlv_put(). So "put_data" means "was a data attribute already
added to this command?"; it's not specifically about the data header or
data itself. I'll add a comment to that effect.

> >   static int put_data_header(struct send_ctx *sctx, u32 len)
> >   {
> > -	struct btrfs_tlv_header *hdr;
> > +	if (WARN_ON_ONCE(sctx->put_data))
> > +		return -EINVAL;
> > +	sctx->put_data = true;
> > +	if (sctx->proto >= 2) {
> > +		/*
> > +		 * In v2, the data attribute header doesn't include a length; it
> > +		 * is implicitly to the end of the command.
> > +		 */
> > +		if (sctx->send_max_size - sctx->send_size < 2 + len)
> > +			return -EOVERFLOW;
> > +		put_unaligned_le16(BTRFS_SEND_A_DATA,
> > +				   sctx->send_buf + sctx->send_size);
> > +		sctx->send_size += 2;
> > +	} 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);
> > -	put_unaligned_le16(BTRFS_SEND_A_DATA, &hdr->tlv_type);
> > -	put_unaligned_le16(len, &hdr->tlv_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);
> > +		put_unaligned_le16(BTRFS_SEND_A_DATA, &hdr->tlv_type);
> > +		put_unaligned_le16(len, &hdr->tlv_len);
> > +		sctx->send_size += sizeof(*hdr);
> > +	}
> >   	return 0;
> >   }
> 
> I wish the 2s were named, and that there were more commonality between the
> two branches... Might I propose this alternative? It doesn't check the
> length's suitability until after adding the two fields, but I don't think
> anything bad happens from delaying the check.

We need to check that writing the header itself won't write past the end
of send_buf, so it'd have to look more like:

static int put_data_header(struct send_ctx *sctx, u32 len)
{
	struct btrfs_tlv_header *hdr =
		(struct btrfs_tlv_header *)(sctx->send_buf + sctx->send_size)

	if (WARN_ON_ONCE(sctx->put_data))
		return -EINVAL;
	sctx->put_data = true;

	if (sctx->send_max_size - sctx->send_size < sizeof(hdr->tlv_type))
		return -EOVERFLOW;
	put_unaligned_le16(BTRFS_SEND_A_DATA, &hdr->tlv_type);
	sctx->send_size += sizeof(hdr->tlv_type);

	/*
	 * In v2, the data attribute header doesn't include a length; it is
	 * implicitly to the end of the command.
	 */
	if (sctx->proto < 2) {
		if (sctx->send_max_size - sctx->send_size <
		    sizeof(hdr->tlv_len))
			return -EOVERFLOW;
		put_unaligned_le16(len, &hdr->tlv_len);
		sctx->send_size += sizeof(hdr->tlv_len);
	}

	if (sctx->send_max_size - sctx->send_size < len)
		return -EOVERFLOW;

	return 0;
}

Now we're checking for overflow in three places, shrug.

One thing that I like about the two separate cases is that it makes it
more clear that v2+ doesn't actually have a btrfs_tlv_header; it's just
a single __le16. If it's alright with you, I'll stick with my original
version, but I will replaced the hard-coded 2s with sizeof(__le16).

  reply	other threads:[~2022-03-30 17:06 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-17 17:25 [PATCH v14 0/7] btrfs: add send/receive support for reading/writing compressed data Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 1/7] btrfs: send: remove unused send_ctx::{total,cmd}_send_size Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 2/7] btrfs: send: explicitly number commands and attributes Omar Sandoval
2022-03-24 17:52   ` Sweet Tea Dorminy
2022-03-17 17:25 ` [PATCH v14 3/7] btrfs: add send stream v2 definitions Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 4/7] btrfs: send: write larger chunks when using stream v2 Omar Sandoval
2022-03-24 17:52   ` Sweet Tea Dorminy
2022-03-30 17:05     ` Omar Sandoval [this message]
2022-03-17 17:25 ` [PATCH v14 5/7] btrfs: send: allocate send buffer with alloc_page() and vmap() for v2 Omar Sandoval
2022-03-24 17:53   ` Sweet Tea Dorminy
2022-03-30 16:03     ` Omar Sandoval
2022-03-30 16:33       ` Sweet Tea Dorminy
2022-03-30 17:13         ` Omar Sandoval
2022-03-30 18:48           ` Sweet Tea Dorminy
2022-03-30 20:42             ` Omar Sandoval
2022-03-30 21:04               ` Sweet Tea Dorminy
2022-03-17 17:25 ` [PATCH v14 6/7] btrfs: send: send compressed extents with encoded writes Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 7/7] btrfs: send: enable support for stream v2 and compressed writes Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 01/10] btrfs-progs: receive: support v2 send stream larger tlv_len Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 02/10] btrfs-progs: receive: dynamically allocate sctx->read_buf Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 03/10] btrfs-progs: receive: support v2 send stream DATA tlv format Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 04/10] btrfs-progs: receive: add send stream v2 cmds and attrs to send.h Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 05/10] btrfs-progs: receive: process encoded_write commands Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 06/10] btrfs-progs: receive: encoded_write fallback to explicit decode and write Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 07/10] btrfs-progs: receive: process fallocate commands Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 08/10] btrfs-progs: receive: process setflags ioctl commands Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 09/10] btrfs-progs: send: stream v2 ioctl flags Omar Sandoval
2022-03-17 17:25 ` [PATCH v14 10/10] btrfs-progs: receive: add tests for basic encoded_write send/receive Omar Sandoval
2022-03-24 17:53 ` [PATCH v14 0/7] btrfs: add send/receive support for reading/writing compressed data Sweet Tea Dorminy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YkSN9bKLA8m2/0Lh@relinquished.localdomain \
    --to=osandov@osandov.com \
    --cc=kernel-team@fb.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=sweettea-kernel@dorminy.me \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox