Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0 */ 2 : #ifndef _XFS_CKSUM_H 3 : #define _XFS_CKSUM_H 1 4 : 5 : #define XFS_CRC_SEED (~(uint32_t)0) 6 : 7 : /* 8 : * Calculate the intermediate checksum for a buffer that has the CRC field 9 : * inside it. The offset of the 32bit crc fields is passed as the 10 : * cksum_offset parameter. We do not modify the buffer during verification, 11 : * hence we have to split the CRC calculation across the cksum_offset. 12 : */ 13 : static inline uint32_t 14 501384380 : xfs_start_cksum_safe(char *buffer, size_t length, unsigned long cksum_offset) 15 : { 16 501384380 : uint32_t zero = 0; 17 501384380 : uint32_t crc; 18 : 19 : /* Calculate CRC up to the checksum. */ 20 501384380 : crc = crc32c(XFS_CRC_SEED, buffer, cksum_offset); 21 : 22 : /* Skip checksum field */ 23 501393493 : crc = crc32c(crc, &zero, sizeof(__u32)); 24 : 25 : /* Calculate the rest of the CRC. */ 26 1002775656 : return crc32c(crc, &buffer[cksum_offset + sizeof(__be32)], 27 501392387 : length - (cksum_offset + sizeof(__be32))); 28 : } 29 : 30 : /* 31 : * Fast CRC method where the buffer is modified. Callers must have exclusive 32 : * access to the buffer while the calculation takes place. 33 : */ 34 : static inline uint32_t 35 : xfs_start_cksum_update(char *buffer, size_t length, unsigned long cksum_offset) 36 : { 37 : /* zero the CRC field */ 38 888713922 : *(__le32 *)(buffer + cksum_offset) = 0; 39 : 40 : /* single pass CRC calculation for the entire buffer */ 41 888713922 : return crc32c(XFS_CRC_SEED, buffer, length); 42 : } 43 : 44 : /* 45 : * Convert the intermediate checksum to the final ondisk format. 46 : * 47 : * The CRC32c calculation uses LE format even on BE machines, but returns the 48 : * result in host endian format. Hence we need to byte swap it back to LE format 49 : * so that it is consistent on disk. 50 : */ 51 : static inline __le32 52 : xfs_end_cksum(uint32_t crc) 53 : { 54 1013818830 : return ~cpu_to_le32(crc); 55 : } 56 : 57 : /* 58 : * Helper to generate the checksum for a buffer. 59 : * 60 : * This modifies the buffer temporarily - callers must have exclusive 61 : * access to the buffer while the calculation takes place. 62 : */ 63 : static inline void 64 335024095 : xfs_update_cksum(char *buffer, size_t length, unsigned long cksum_offset) 65 : { 66 335024095 : uint32_t crc = xfs_start_cksum_update(buffer, length, cksum_offset); 67 : 68 335035638 : *(__le32 *)(buffer + cksum_offset) = xfs_end_cksum(crc); 69 335035638 : } 70 : 71 : /* 72 : * Helper to verify the checksum for a buffer. 73 : */ 74 : static inline int 75 501385241 : xfs_verify_cksum(char *buffer, size_t length, unsigned long cksum_offset) 76 : { 77 501385241 : uint32_t crc = xfs_start_cksum_safe(buffer, length, cksum_offset); 78 : 79 501383824 : return *(__le32 *)(buffer + cksum_offset) == xfs_end_cksum(crc); 80 : } 81 : 82 : #endif /* _XFS_CKSUM_H */