diff options
| author | Dave Chinner <dchinner@redhat.com> | 2013-04-03 16:11:20 +1100 | 
|---|---|---|
| committer | Ben Myers <bpm@sgi.com> | 2013-04-27 11:51:56 -0500 | 
| commit | f5f3d9b0161633e8943520e83df634ad540b3b7f (patch) | |
| tree | bd1a014fd6472904e53d7680e5692b49431ca6ab /fs/xfs/xfs_dir2_format.h | |
| parent | f948dd76dde021c050c7c35720dc066a8b9a5e35 (diff) | |
| download | olio-linux-3.10-f5f3d9b0161633e8943520e83df634ad540b3b7f.tar.xz olio-linux-3.10-f5f3d9b0161633e8943520e83df634ad540b3b7f.zip  | |
xfs: add CRC checks to block format directory blocks
Now that directory buffers are made from a single struct xfs_buf, we
can add CRC calculation and checking callbacks. While there, add all
the fields to the on disk structures for future functionality such
as d_type support, uuids, block numbers, owner inode, etc.
To distinguish between the different on disk formats, change the
magic numbers for the new format directory blocks.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_dir2_format.h')
| -rw-r--r-- | fs/xfs/xfs_dir2_format.h | 143 | 
1 files changed, 143 insertions, 0 deletions
diff --git a/fs/xfs/xfs_dir2_format.h b/fs/xfs/xfs_dir2_format.h index 07270981f48..845979a4ee9 100644 --- a/fs/xfs/xfs_dir2_format.h +++ b/fs/xfs/xfs_dir2_format.h @@ -1,5 +1,6 @@  /*   * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. + * Copyright (c) 2013 Red Hat, Inc.   * All Rights Reserved.   *   * This program is free software; you can redistribute it and/or @@ -36,6 +37,37 @@  #define	XFS_DIR2_FREE_MAGIC	0x58443246	/* XD2F: free index blocks */  /* + * Directory Version 3 With CRCs. + * + * The tree formats are the same as for version 2 directories.  The difference + * is in the block header and dirent formats. In many cases the v3 structures + * use v2 definitions as they are no different and this makes code sharing much + * easier. + * + * Also, the xfs_dir3_*() functions handle both v2 and v3 formats - if the + * format is v2 then they switch to the existing v2 code, or the format is v3 + * they implement the v3 functionality. This means the existing dir2 is a mix of + * xfs_dir2/xfs_dir3 calls and functions. The xfs_dir3 functions are called + * where there is a difference in the formats, otherwise the code is unchanged. + * + * Where it is possible, the code decides what to do based on the magic numbers + * in the blocks rather than feature bits in the superblock. This means the code + * is as independent of the external XFS code as possible as doesn't require + * passing struct xfs_mount pointers into places where it isn't really + * necessary. + * + * Version 3 includes: + * + *	- a larger block header for CRC and identification purposes and so the + *	offsets of all the structures inside the blocks are different. + * + *	- new magic numbers to be able to detect the v2/v3 types on the fly. + */ + +#define	XFS_DIR3_BLOCK_MAGIC	0x58444233	/* XDB3: single block dirs */ +#define	XFS_DIR3_DATA_MAGIC	0x58444433	/* XDD3: multiblock dirs */ + +/*   * Byte offset in data block and shortform entry.   */  typedef	__uint16_t	xfs_dir2_data_off_t; @@ -226,6 +258,38 @@ typedef struct xfs_dir2_data_hdr {  } xfs_dir2_data_hdr_t;  /* + * define a structure for all the verification fields we are adding to the + * directory block structures. This will be used in several structures. + * The magic number must be the first entry to align with all the dir2 + * structures so we determine how to decode them just by the magic number. + */ +struct xfs_dir3_blk_hdr { +	__be32			magic;	/* magic number */ +	__be32			crc;	/* CRC of block */ +	__be64			blkno;	/* first block of the buffer */ +	__be64			lsn;	/* sequence number of last write */ +	uuid_t			uuid;	/* filesystem we belong to */ +	__be64			owner;	/* inode that owns the block */ +}; + +struct xfs_dir3_data_hdr { +	struct xfs_dir3_blk_hdr	hdr; +	xfs_dir2_data_free_t	best_free[XFS_DIR2_DATA_FD_COUNT]; +}; + +#define XFS_DIR3_DATA_CRC_OFF  offsetof(struct xfs_dir3_data_hdr, hdr.crc) + +static inline struct xfs_dir2_data_free * +xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) +{ +	if (hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { +		struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr; +		return hdr3->best_free; +	} +	return hdr->bestfree; +} + +/*   * Active entry in a data block.   *   * Aligned to 8 bytes.  After the variable length name field there is a @@ -280,6 +344,85 @@ xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup)  			be16_to_cpu(dup->length) - sizeof(__be16));  } +static inline struct xfs_dir2_data_unused * +xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) +{ +	if (hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { +		return (struct xfs_dir2_data_unused *) +			((char *)hdr + sizeof(struct xfs_dir3_data_hdr)); +	} +	return (struct xfs_dir2_data_unused *) +		((char *)hdr + sizeof(struct xfs_dir2_data_hdr)); +} + +static inline size_t +xfs_dir3_data_hdr_size(bool dir3) +{ +	if (dir3) +		return sizeof(struct xfs_dir3_data_hdr); +	return sizeof(struct xfs_dir2_data_hdr); +} + +static inline size_t +xfs_dir3_data_entry_offset(struct xfs_dir2_data_hdr *hdr) +{ +	bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || +		    hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); +	return xfs_dir3_data_hdr_size(dir3); +} + +static inline struct xfs_dir2_data_entry * +xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr) +{ +	return (struct xfs_dir2_data_entry *) +		((char *)hdr + xfs_dir3_data_entry_offset(hdr)); +} + +/* + * Offsets of . and .. in data space (always block 0) + */ +static inline xfs_dir2_data_aoff_t +xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr) +{ +	return xfs_dir3_data_entry_offset(hdr); +} + +static inline xfs_dir2_data_aoff_t +xfs_dir3_data_dotdot_offset(struct xfs_dir2_data_hdr *hdr) +{ +	return xfs_dir3_data_dot_offset(hdr) + xfs_dir2_data_entsize(1); +} + +static inline xfs_dir2_data_aoff_t +xfs_dir3_data_first_offset(struct xfs_dir2_data_hdr *hdr) +{ +	return xfs_dir3_data_dotdot_offset(hdr) + xfs_dir2_data_entsize(2); +} + +/* + * location of . and .. in data space (always block 0) + */ +static inline struct xfs_dir2_data_entry * +xfs_dir3_data_dot_entry_p(struct xfs_dir2_data_hdr *hdr) +{ +	return (struct xfs_dir2_data_entry *) +		((char *)hdr + xfs_dir3_data_dot_offset(hdr)); +} + +static inline struct xfs_dir2_data_entry * +xfs_dir3_data_dotdot_entry_p(struct xfs_dir2_data_hdr *hdr) +{ +	return (struct xfs_dir2_data_entry *) +		((char *)hdr + xfs_dir3_data_dotdot_offset(hdr)); +} + +static inline struct xfs_dir2_data_entry * +xfs_dir3_data_first_entry_p(struct xfs_dir2_data_hdr *hdr) +{ +	return (struct xfs_dir2_data_entry *) +		((char *)hdr + xfs_dir3_data_first_offset(hdr)); +} +  /*   * Leaf block structures.   *  |