xref: /openbmc/linux/fs/xfs/libxfs/xfs_cksum.h (revision 84be0ffc9043f7c56044294eb775a2200452c76d)
1*84be0ffcSDave Chinner #ifndef _XFS_CKSUM_H
2*84be0ffcSDave Chinner #define _XFS_CKSUM_H 1
3*84be0ffcSDave Chinner 
4*84be0ffcSDave Chinner #define XFS_CRC_SEED	(~(__uint32_t)0)
5*84be0ffcSDave Chinner 
6*84be0ffcSDave Chinner /*
7*84be0ffcSDave Chinner  * Calculate the intermediate checksum for a buffer that has the CRC field
8*84be0ffcSDave Chinner  * inside it.  The offset of the 32bit crc fields is passed as the
9*84be0ffcSDave Chinner  * cksum_offset parameter.
10*84be0ffcSDave Chinner  */
11*84be0ffcSDave Chinner static inline __uint32_t
12*84be0ffcSDave Chinner xfs_start_cksum(char *buffer, size_t length, unsigned long cksum_offset)
13*84be0ffcSDave Chinner {
14*84be0ffcSDave Chinner 	__uint32_t zero = 0;
15*84be0ffcSDave Chinner 	__uint32_t crc;
16*84be0ffcSDave Chinner 
17*84be0ffcSDave Chinner 	/* Calculate CRC up to the checksum. */
18*84be0ffcSDave Chinner 	crc = crc32c(XFS_CRC_SEED, buffer, cksum_offset);
19*84be0ffcSDave Chinner 
20*84be0ffcSDave Chinner 	/* Skip checksum field */
21*84be0ffcSDave Chinner 	crc = crc32c(crc, &zero, sizeof(__u32));
22*84be0ffcSDave Chinner 
23*84be0ffcSDave Chinner 	/* Calculate the rest of the CRC. */
24*84be0ffcSDave Chinner 	return crc32c(crc, &buffer[cksum_offset + sizeof(__be32)],
25*84be0ffcSDave Chinner 		      length - (cksum_offset + sizeof(__be32)));
26*84be0ffcSDave Chinner }
27*84be0ffcSDave Chinner 
28*84be0ffcSDave Chinner /*
29*84be0ffcSDave Chinner  * Convert the intermediate checksum to the final ondisk format.
30*84be0ffcSDave Chinner  *
31*84be0ffcSDave Chinner  * The CRC32c calculation uses LE format even on BE machines, but returns the
32*84be0ffcSDave Chinner  * result in host endian format. Hence we need to byte swap it back to LE format
33*84be0ffcSDave Chinner  * so that it is consistent on disk.
34*84be0ffcSDave Chinner  */
35*84be0ffcSDave Chinner static inline __le32
36*84be0ffcSDave Chinner xfs_end_cksum(__uint32_t crc)
37*84be0ffcSDave Chinner {
38*84be0ffcSDave Chinner 	return ~cpu_to_le32(crc);
39*84be0ffcSDave Chinner }
40*84be0ffcSDave Chinner 
41*84be0ffcSDave Chinner /*
42*84be0ffcSDave Chinner  * Helper to generate the checksum for a buffer.
43*84be0ffcSDave Chinner  */
44*84be0ffcSDave Chinner static inline void
45*84be0ffcSDave Chinner xfs_update_cksum(char *buffer, size_t length, unsigned long cksum_offset)
46*84be0ffcSDave Chinner {
47*84be0ffcSDave Chinner 	__uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset);
48*84be0ffcSDave Chinner 
49*84be0ffcSDave Chinner 	*(__le32 *)(buffer + cksum_offset) = xfs_end_cksum(crc);
50*84be0ffcSDave Chinner }
51*84be0ffcSDave Chinner 
52*84be0ffcSDave Chinner /*
53*84be0ffcSDave Chinner  * Helper to verify the checksum for a buffer.
54*84be0ffcSDave Chinner  */
55*84be0ffcSDave Chinner static inline int
56*84be0ffcSDave Chinner xfs_verify_cksum(char *buffer, size_t length, unsigned long cksum_offset)
57*84be0ffcSDave Chinner {
58*84be0ffcSDave Chinner 	__uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset);
59*84be0ffcSDave Chinner 
60*84be0ffcSDave Chinner 	return *(__le32 *)(buffer + cksum_offset) == xfs_end_cksum(crc);
61*84be0ffcSDave Chinner }
62*84be0ffcSDave Chinner 
63*84be0ffcSDave Chinner #endif /* _XFS_CKSUM_H */
64