Skip to content

Conversation

rhn
Copy link
Contributor

@rhn rhn commented May 11, 2024

The way the CRC32C checksum used for btrfs-send differs from the way it's used elsewhere in btrfs. Without making the distinction, it's easy to make the flawed assumption that CRC32C always refers to the same, and end up with code that produces the wrong checksums.

This small note should guide the reader to the right function.


The best notes on the protocol I found are here:

https://archive.kernel.org/oldwiki/btrfs.wiki.kernel.org/index.php/Design_notes_on_Send/Receive.html

Reading "crc32", I thought it was easy to implement. Long story short I learned a lot more about CRC than I wanted. After bouncing around between different implementations claiming to be "the BTRFS one", I found that there are two ways to use CRC32C in btrfs.

Debugging a hash function is a trial-and-error affair, because you can hardly deduce which input was wrong, so you can never be sure if you actually made a subtle mistake or used the wrong algorithm whatsoever. So with the next person in mind, this commit reveals the mystery in the docs: yes, it's the same algorithm. Those two parameters are the ones which differ.

Rust code describing the algorithm for the crc crate that worked for me:

pub const CRC_32_BTRFS_SEND: crc::Algorithm<u32> = crc::Algorithm { width: 32, poly: 0x1edc6f41, init: 0, refin: true, refout: true, xorout: 0, check: 0xe3069283, residue: 0xb798b438 };

(it's a slight variation on the one used in ISCSI)

The way the CRC32C checksum used for btrfs-send differs from the way it's used elsewhere in btrfs. Without making the distinction, it's easy to make the flawed assumption that CRC32C always refers to the same, and end up with code that produces the wrong checksums.

This small note should guide the reader to the right function.
kdave pushed a commit that referenced this pull request May 17, 2024
The way the CRC32C checksum used for btrfs-send differs from the way
it's used elsewhere in btrfs. Without making the distinction, it's easy
to make the flawed assumption that CRC32C always refers to the same, and
end up with code that produces the wrong checksums.

This small note should guide the reader to the right function.

The best notes on the protocol I found are here:
https://archive.kernel.org/oldwiki/btrfs.wiki.kernel.org/index.php/Design_notes_on_Send/Receive.html

The crc32c might be used in two meanings and this could be confusing
when implementing the send stream protocol.

Rust code describing the algorithm for the crc crate that worked for me:

pub const CRC_32_BTRFS_SEND: crc::Algorithm<u32> = crc::Algorithm {
	width: 32, poly: 0x1edc6f41, init: 0, refin: true, refout: true,
	xorout: 0, check: 0xe3069283, residue: 0xb798b438
};

(it's a slight variation on the one used in ISCSI)

Note: Documentation/dev/dev-send-stream.rst briefly mentions that

Pull-request: #794
Author: rhn <gihu.rhn@porcupinefactory.org>
[ rephrase changelog and copy text from pull request and add link to
  developer documentation of the send stream ]
Signed-off-by: David Sterba <dsterba@suse.com>
@kdave
Copy link
Owner

kdave commented May 17, 2024

Also mentioned in https://btrfs.readthedocs.io/en/latest/dev/dev-send-stream.html#command-structure "Note: the checksum initial seed is not 0xFFFFFFFF but 0x0. That is a slight mistake and not the recommended way, overlooked when the protocol was implemented. This does not have a big impact though."

I've updated the changelog a bit so it's more descriptive and added link to the stream docs. Patch added to devel, thanks.

@kdave kdave closed this May 17, 2024
@kdave kdave added this to the v6.9 milestone May 17, 2024
kdave pushed a commit that referenced this pull request May 17, 2024
The way the CRC32C checksum used for btrfs-send differs from the way
it's used elsewhere in btrfs. Without making the distinction, it's easy
to make the flawed assumption that CRC32C always refers to the same, and
end up with code that produces the wrong checksums.

This small note should guide the reader to the right function.

The best notes on the protocol I found are here:
https://archive.kernel.org/oldwiki/btrfs.wiki.kernel.org/index.php/Design_notes_on_Send/Receive.html

The crc32c might be used in two meanings and this could be confusing
when implementing the send stream protocol.

Rust code describing the algorithm for the crc crate that worked for me:

pub const CRC_32_BTRFS_SEND: crc::Algorithm<u32> = crc::Algorithm {
	width: 32, poly: 0x1edc6f41, init: 0, refin: true, refout: true,
	xorout: 0, check: 0xe3069283, residue: 0xb798b438
};

(it's a slight variation on the one used in ISCSI)

Note: Documentation/dev/dev-send-stream.rst briefly mentions that

Pull-request: #794
Author: rhn <gihu.rhn@porcupinefactory.org>
[ rephrase changelog and copy text from pull request and add link to
  developer documentation of the send stream ]
Signed-off-by: David Sterba <dsterba@suse.com>
kdave pushed a commit that referenced this pull request Aug 7, 2024
The way the CRC32C checksum used for btrfs-send differs from the way
it's used elsewhere in btrfs. Without making the distinction, it's easy
to make the flawed assumption that CRC32C always refers to the same, and
end up with code that produces the wrong checksums.

This small note should guide the reader to the right function.

The best notes on the protocol I found are here:
https://archive.kernel.org/oldwiki/btrfs.wiki.kernel.org/index.php/Design_notes_on_Send/Receive.html

The crc32c might be used in two meanings and this could be confusing
when implementing the send stream protocol.

Rust code describing the algorithm for the crc crate that worked for me:

pub const CRC_32_BTRFS_SEND: crc::Algorithm<u32> = crc::Algorithm {
	width: 32, poly: 0x1edc6f41, init: 0, refin: true, refout: true,
	xorout: 0, check: 0xe3069283, residue: 0xb798b438
};

(it's a slight variation on the one used in ISCSI)

Note: Documentation/dev/dev-send-stream.rst briefly mentions that

Pull-request: #794
Author: rhn <gihu.rhn@porcupinefactory.org>
[ rephrase changelog and copy text from pull request and add link to
  developer documentation of the send stream ]
Signed-off-by: David Sterba <dsterba@suse.com>
@kdave
Copy link
Owner

kdave commented Aug 7, 2024

Due to mistake on my side this was not in v6.9, will be released in v6.10.1.

@kdave kdave modified the milestones: v6.9, v6.10.1 Aug 7, 2024
kdave pushed a commit that referenced this pull request Aug 9, 2024
The way the CRC32C checksum used for btrfs-send differs from the way
it's used elsewhere in btrfs. Without making the distinction, it's easy
to make the flawed assumption that CRC32C always refers to the same, and
end up with code that produces the wrong checksums.

This small note should guide the reader to the right function.

The best notes on the protocol I found are here:
https://archive.kernel.org/oldwiki/btrfs.wiki.kernel.org/index.php/Design_notes_on_Send/Receive.html

The crc32c might be used in two meanings and this could be confusing
when implementing the send stream protocol.

Rust code describing the algorithm for the crc crate that worked for me:

pub const CRC_32_BTRFS_SEND: crc::Algorithm<u32> = crc::Algorithm {
	width: 32, poly: 0x1edc6f41, init: 0, refin: true, refout: true,
	xorout: 0, check: 0xe3069283, residue: 0xb798b438
};

(it's a slight variation on the one used in ISCSI)

Note: Documentation/dev/dev-send-stream.rst briefly mentions that

Pull-request: #794
Author: rhn <gihu.rhn@porcupinefactory.org>
[ rephrase changelog and copy text from pull request and add link to
  developer documentation of the send stream ]
Signed-off-by: David Sterba <dsterba@suse.com>
kdave pushed a commit that referenced this pull request Aug 14, 2024
The way the CRC32C checksum used for btrfs-send differs from the way
it's used elsewhere in btrfs. Without making the distinction, it's easy
to make the flawed assumption that CRC32C always refers to the same, and
end up with code that produces the wrong checksums.

This small note should guide the reader to the right function.

The best notes on the protocol I found are here:
https://archive.kernel.org/oldwiki/btrfs.wiki.kernel.org/index.php/Design_notes_on_Send/Receive.html

The crc32c might be used in two meanings and this could be confusing
when implementing the send stream protocol.

Rust code describing the algorithm for the crc crate that worked for me:

pub const CRC_32_BTRFS_SEND: crc::Algorithm<u32> = crc::Algorithm {
	width: 32, poly: 0x1edc6f41, init: 0, refin: true, refout: true,
	xorout: 0, check: 0xe3069283, residue: 0xb798b438
};

(it's a slight variation on the one used in ISCSI)

Note: Documentation/dev/dev-send-stream.rst briefly mentions that

Pull-request: #794
Author: rhn <gihu.rhn@porcupinefactory.org>
[ rephrase changelog and copy text from pull request and add link to
  developer documentation of the send stream ]
Signed-off-by: David Sterba <dsterba@suse.com>
kdave pushed a commit that referenced this pull request Aug 14, 2024
The way the CRC32C checksum used for btrfs-send differs from the way
it's used elsewhere in btrfs. Without making the distinction, it's easy
to make the flawed assumption that CRC32C always refers to the same, and
end up with code that produces the wrong checksums.

This small note should guide the reader to the right function.

The best notes on the protocol I found are here:
https://archive.kernel.org/oldwiki/btrfs.wiki.kernel.org/index.php/Design_notes_on_Send/Receive.html

The crc32c might be used in two meanings and this could be confusing
when implementing the send stream protocol.

Rust code describing the algorithm for the crc crate that worked for me:

pub const CRC_32_BTRFS_SEND: crc::Algorithm<u32> = crc::Algorithm {
	width: 32, poly: 0x1edc6f41, init: 0, refin: true, refout: true,
	xorout: 0, check: 0xe3069283, residue: 0xb798b438
};

(it's a slight variation on the one used in ISCSI)

Note: Documentation/dev/dev-send-stream.rst briefly mentions that

Pull-request: #794
Author: rhn <gihu.rhn@porcupinefactory.org>
[ rephrase changelog and copy text from pull request and add link to
  developer documentation of the send stream ]
Signed-off-by: David Sterba <dsterba@suse.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants