Commit bc02e8693d875c2a9b0037cfd37fe0b726d26403

Authored by Christoph Hellwig
Committed by Ben Myers
1 parent 1813dd6405

xfs: add CRC infrastructure

- add a mount feature bit for CRC enabled filesystems
 - add some helpers for generating and verifying the CRCs
 - add a copy_uuid helper

The checksumming helpers are loosely based on similar ones in sctp,
all other bits come from Dave Chinner.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>

Showing 5 changed files with 78 additions and 0 deletions Side-by-side Diff

... ... @@ -2,6 +2,7 @@
2 2 tristate "XFS filesystem support"
3 3 depends on BLOCK
4 4 select EXPORTFS
  5 + select LIBCRC32C
5 6 help
6 7 XFS is a high performance journaling filesystem which originated
7 8 on the SGI IRIX platform. It is completely multi-threaded, can
... ... @@ -26,5 +26,11 @@
26 26 extern int uuid_equal(uuid_t *uuid1, uuid_t *uuid2);
27 27 extern void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]);
28 28  
  29 +static inline void
  30 +uuid_copy(uuid_t *dst, uuid_t *src)
  31 +{
  32 + memcpy(dst, src, sizeof(uuid_t));
  33 +}
  34 +
29 35 #endif /* __XFS_SUPPORT_UUID_H__ */
  1 +#ifndef _XFS_CKSUM_H
  2 +#define _XFS_CKSUM_H 1
  3 +
  4 +#define XFS_CRC_SEED (~(__uint32_t)0)
  5 +
  6 +/*
  7 + * Calculate the intermediate checksum for a buffer that has the CRC field
  8 + * inside it. The offset of the 32bit crc fields is passed as the
  9 + * cksum_offset parameter.
  10 + */
  11 +static inline __uint32_t
  12 +xfs_start_cksum(char *buffer, size_t length, unsigned long cksum_offset)
  13 +{
  14 + __uint32_t zero = 0;
  15 + __uint32_t crc;
  16 +
  17 + /* Calculate CRC up to the checksum. */
  18 + crc = crc32c(XFS_CRC_SEED, buffer, cksum_offset);
  19 +
  20 + /* Skip checksum field */
  21 + crc = crc32c(crc, &zero, sizeof(__u32));
  22 +
  23 + /* Calculate the rest of the CRC. */
  24 + return crc32c(crc, &buffer[cksum_offset + sizeof(__be32)],
  25 + length - (cksum_offset + sizeof(__be32)));
  26 +}
  27 +
  28 +/*
  29 + * Convert the intermediate checksum to the final ondisk format.
  30 + *
  31 + * The CRC32c calculation uses LE format even on BE machines, but returns the
  32 + * result in host endian format. Hence we need to byte swap it back to LE format
  33 + * so that it is consistent on disk.
  34 + */
  35 +static inline __le32
  36 +xfs_end_cksum(__uint32_t crc)
  37 +{
  38 + return ~cpu_to_le32(crc);
  39 +}
  40 +
  41 +/*
  42 + * Helper to generate the checksum for a buffer.
  43 + */
  44 +static inline void
  45 +xfs_update_cksum(char *buffer, size_t length, unsigned long cksum_offset)
  46 +{
  47 + __uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset);
  48 +
  49 + *(__le32 *)(buffer + cksum_offset) = xfs_end_cksum(crc);
  50 +}
  51 +
  52 +/*
  53 + * Helper to verify the checksum for a buffer.
  54 + */
  55 +static inline int
  56 +xfs_verify_cksum(char *buffer, size_t length, unsigned long cksum_offset)
  57 +{
  58 + __uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset);
  59 +
  60 + return *(__le32 *)(buffer + cksum_offset) == xfs_end_cksum(crc);
  61 +}
  62 +
  63 +#endif /* _XFS_CKSUM_H */
... ... @@ -44,6 +44,7 @@
44 44 #include <linux/kernel.h>
45 45 #include <linux/blkdev.h>
46 46 #include <linux/slab.h>
  47 +#include <linux/crc32c.h>
47 48 #include <linux/module.h>
48 49 #include <linux/mutex.h>
49 50 #include <linux/file.h>
... ... @@ -81,6 +81,7 @@
81 81 #define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */
82 82 #define XFS_SB_VERSION2_PARENTBIT 0x00000010 /* parent pointers */
83 83 #define XFS_SB_VERSION2_PROJID32BIT 0x00000080 /* 32 bit project id */
  84 +#define XFS_SB_VERSION2_CRCBIT 0x00000100 /* metadata CRCs */
84 85  
85 86 #define XFS_SB_VERSION2_OKREALFBITS \
86 87 (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \
... ... @@ -501,6 +502,12 @@
501 502 {
502 503 return xfs_sb_version_hasmorebits(sbp) &&
503 504 (sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT);
  505 +}
  506 +
  507 +static inline int xfs_sb_version_hascrc(xfs_sb_t *sbp)
  508 +{
  509 + return (xfs_sb_version_hasmorebits(sbp) &&
  510 + (sbp->sb_features2 & XFS_SB_VERSION2_CRCBIT));
504 511 }
505 512  
506 513 /*