| Christoph Hellwig | 5792664 | 2011-07-13 13:43:48 +0200 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. | 
| Dave Chinner | f5f3d9b | 2013-04-03 16:11:20 +1100 | [diff] [blame^] | 3 |  * Copyright (c) 2013 Red Hat, Inc. | 
| Christoph Hellwig | 5792664 | 2011-07-13 13:43:48 +0200 | [diff] [blame] | 4 |  * All Rights Reserved. | 
 | 5 |  * | 
 | 6 |  * This program is free software; you can redistribute it and/or | 
 | 7 |  * modify it under the terms of the GNU General Public License as | 
 | 8 |  * published by the Free Software Foundation. | 
 | 9 |  * | 
 | 10 |  * This program is distributed in the hope that it would be useful, | 
 | 11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 | 13 |  * GNU General Public License for more details. | 
 | 14 |  * | 
 | 15 |  * You should have received a copy of the GNU General Public License | 
 | 16 |  * along with this program; if not, write the Free Software Foundation, | 
 | 17 |  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | 
 | 18 |  */ | 
 | 19 | #ifndef __XFS_DIR2_FORMAT_H__ | 
 | 20 | #define __XFS_DIR2_FORMAT_H__ | 
 | 21 |  | 
 | 22 | /* | 
 | 23 |  * Directory version 2. | 
 | 24 |  * | 
 | 25 |  * There are 4 possible formats: | 
 | 26 |  *  - shortform - embedded into the inode | 
 | 27 |  *  - single block - data with embedded leaf at the end | 
 | 28 |  *  - multiple data blocks, single leaf+freeindex block | 
 | 29 |  *  - data blocks, node and leaf blocks (btree), freeindex blocks | 
 | 30 |  * | 
 | 31 |  * Note: many node blocks structures and constants are shared with the attr | 
 | 32 |  * code and defined in xfs_da_btree.h. | 
 | 33 |  */ | 
 | 34 |  | 
 | 35 | #define	XFS_DIR2_BLOCK_MAGIC	0x58443242	/* XD2B: single block dirs */ | 
 | 36 | #define	XFS_DIR2_DATA_MAGIC	0x58443244	/* XD2D: multiblock dirs */ | 
 | 37 | #define	XFS_DIR2_FREE_MAGIC	0x58443246	/* XD2F: free index blocks */ | 
 | 38 |  | 
 | 39 | /* | 
| Dave Chinner | f5f3d9b | 2013-04-03 16:11:20 +1100 | [diff] [blame^] | 40 |  * Directory Version 3 With CRCs. | 
 | 41 |  * | 
 | 42 |  * The tree formats are the same as for version 2 directories.  The difference | 
 | 43 |  * is in the block header and dirent formats. In many cases the v3 structures | 
 | 44 |  * use v2 definitions as they are no different and this makes code sharing much | 
 | 45 |  * easier. | 
 | 46 |  * | 
 | 47 |  * Also, the xfs_dir3_*() functions handle both v2 and v3 formats - if the | 
 | 48 |  * format is v2 then they switch to the existing v2 code, or the format is v3 | 
 | 49 |  * they implement the v3 functionality. This means the existing dir2 is a mix of | 
 | 50 |  * xfs_dir2/xfs_dir3 calls and functions. The xfs_dir3 functions are called | 
 | 51 |  * where there is a difference in the formats, otherwise the code is unchanged. | 
 | 52 |  * | 
 | 53 |  * Where it is possible, the code decides what to do based on the magic numbers | 
 | 54 |  * in the blocks rather than feature bits in the superblock. This means the code | 
 | 55 |  * is as independent of the external XFS code as possible as doesn't require | 
 | 56 |  * passing struct xfs_mount pointers into places where it isn't really | 
 | 57 |  * necessary. | 
 | 58 |  * | 
 | 59 |  * Version 3 includes: | 
 | 60 |  * | 
 | 61 |  *	- a larger block header for CRC and identification purposes and so the | 
 | 62 |  *	offsets of all the structures inside the blocks are different. | 
 | 63 |  * | 
 | 64 |  *	- new magic numbers to be able to detect the v2/v3 types on the fly. | 
 | 65 |  */ | 
 | 66 |  | 
 | 67 | #define	XFS_DIR3_BLOCK_MAGIC	0x58444233	/* XDB3: single block dirs */ | 
 | 68 | #define	XFS_DIR3_DATA_MAGIC	0x58444433	/* XDD3: multiblock dirs */ | 
 | 69 |  | 
 | 70 | /* | 
| Christoph Hellwig | 5792664 | 2011-07-13 13:43:48 +0200 | [diff] [blame] | 71 |  * Byte offset in data block and shortform entry. | 
 | 72 |  */ | 
 | 73 | typedef	__uint16_t	xfs_dir2_data_off_t; | 
 | 74 | #define	NULLDATAOFF	0xffffU | 
 | 75 | typedef uint		xfs_dir2_data_aoff_t;	/* argument form */ | 
 | 76 |  | 
 | 77 | /* | 
 | 78 |  * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t. | 
 | 79 |  * Only need 16 bits, this is the byte offset into the single block form. | 
 | 80 |  */ | 
 | 81 | typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t; | 
 | 82 |  | 
 | 83 | /* | 
 | 84 |  * Offset in data space of a data entry. | 
 | 85 |  */ | 
 | 86 | typedef	__uint32_t	xfs_dir2_dataptr_t; | 
 | 87 | #define	XFS_DIR2_MAX_DATAPTR	((xfs_dir2_dataptr_t)0xffffffff) | 
 | 88 | #define	XFS_DIR2_NULL_DATAPTR	((xfs_dir2_dataptr_t)0) | 
 | 89 |  | 
 | 90 | /* | 
 | 91 |  * Byte offset in a directory. | 
 | 92 |  */ | 
 | 93 | typedef	xfs_off_t	xfs_dir2_off_t; | 
 | 94 |  | 
 | 95 | /* | 
 | 96 |  * Directory block number (logical dirblk in file) | 
 | 97 |  */ | 
 | 98 | typedef	__uint32_t	xfs_dir2_db_t; | 
 | 99 |  | 
 | 100 | /* | 
 | 101 |  * Inode number stored as 8 8-bit values. | 
 | 102 |  */ | 
 | 103 | typedef	struct { __uint8_t i[8]; } xfs_dir2_ino8_t; | 
 | 104 |  | 
 | 105 | /* | 
 | 106 |  * Inode number stored as 4 8-bit values. | 
 | 107 |  * Works a lot of the time, when all the inode numbers in a directory | 
 | 108 |  * fit in 32 bits. | 
 | 109 |  */ | 
 | 110 | typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t; | 
 | 111 |  | 
 | 112 | typedef union { | 
 | 113 | 	xfs_dir2_ino8_t	i8; | 
 | 114 | 	xfs_dir2_ino4_t	i4; | 
 | 115 | } xfs_dir2_inou_t; | 
 | 116 | #define	XFS_DIR2_MAX_SHORT_INUM	((xfs_ino_t)0xffffffffULL) | 
 | 117 |  | 
 | 118 | /* | 
 | 119 |  * Directory layout when stored internal to an inode. | 
 | 120 |  * | 
 | 121 |  * Small directories are packed as tightly as possible so as to fit into the | 
 | 122 |  * literal area of the inode.  These "shortform" directories consist of a | 
 | 123 |  * single xfs_dir2_sf_hdr header followed by zero or more xfs_dir2_sf_entry | 
 | 124 |  * structures.  Due the different inode number storage size and the variable | 
 | 125 |  * length name field in the xfs_dir2_sf_entry all these structure are | 
 | 126 |  * variable length, and the accessors in this file should be used to iterate | 
 | 127 |  * over them. | 
 | 128 |  */ | 
 | 129 | typedef struct xfs_dir2_sf_hdr { | 
 | 130 | 	__uint8_t		count;		/* count of entries */ | 
 | 131 | 	__uint8_t		i8count;	/* count of 8-byte inode #s */ | 
 | 132 | 	xfs_dir2_inou_t		parent;		/* parent dir inode number */ | 
 | 133 | } __arch_pack xfs_dir2_sf_hdr_t; | 
 | 134 |  | 
 | 135 | typedef struct xfs_dir2_sf_entry { | 
 | 136 | 	__u8			namelen;	/* actual name length */ | 
 | 137 | 	xfs_dir2_sf_off_t	offset;		/* saved offset */ | 
 | 138 | 	__u8			name[];		/* name, variable size */ | 
 | 139 | 	/* | 
 | 140 | 	 * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a | 
 | 141 | 	 * variable offset after the name. | 
 | 142 | 	 */ | 
 | 143 | } __arch_pack xfs_dir2_sf_entry_t; | 
 | 144 |  | 
 | 145 | static inline int xfs_dir2_sf_hdr_size(int i8count) | 
 | 146 | { | 
 | 147 | 	return sizeof(struct xfs_dir2_sf_hdr) - | 
 | 148 | 		(i8count == 0) * | 
 | 149 | 		(sizeof(xfs_dir2_ino8_t) - sizeof(xfs_dir2_ino4_t)); | 
 | 150 | } | 
 | 151 |  | 
 | 152 | static inline xfs_dir2_data_aoff_t | 
 | 153 | xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep) | 
 | 154 | { | 
 | 155 | 	return get_unaligned_be16(&sfep->offset.i); | 
 | 156 | } | 
 | 157 |  | 
 | 158 | static inline void | 
 | 159 | xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off) | 
 | 160 | { | 
 | 161 | 	put_unaligned_be16(off, &sfep->offset.i); | 
 | 162 | } | 
 | 163 |  | 
 | 164 | static inline int | 
 | 165 | xfs_dir2_sf_entsize(struct xfs_dir2_sf_hdr *hdr, int len) | 
 | 166 | { | 
 | 167 | 	return sizeof(struct xfs_dir2_sf_entry) +	/* namelen + offset */ | 
 | 168 | 		len +					/* name */ | 
 | 169 | 		(hdr->i8count ?				/* ino */ | 
 | 170 | 		 sizeof(xfs_dir2_ino8_t) : | 
 | 171 | 		 sizeof(xfs_dir2_ino4_t)); | 
 | 172 | } | 
 | 173 |  | 
 | 174 | static inline struct xfs_dir2_sf_entry * | 
 | 175 | xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr) | 
 | 176 | { | 
 | 177 | 	return (struct xfs_dir2_sf_entry *) | 
 | 178 | 		((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count)); | 
 | 179 | } | 
 | 180 |  | 
 | 181 | static inline struct xfs_dir2_sf_entry * | 
 | 182 | xfs_dir2_sf_nextentry(struct xfs_dir2_sf_hdr *hdr, | 
 | 183 | 		struct xfs_dir2_sf_entry *sfep) | 
 | 184 | { | 
 | 185 | 	return (struct xfs_dir2_sf_entry *) | 
 | 186 | 		((char *)sfep + xfs_dir2_sf_entsize(hdr, sfep->namelen)); | 
 | 187 | } | 
 | 188 |  | 
 | 189 |  | 
 | 190 | /* | 
 | 191 |  * Data block structures. | 
 | 192 |  * | 
 | 193 |  * A pure data block looks like the following drawing on disk: | 
 | 194 |  * | 
 | 195 |  *    +-------------------------------------------------+ | 
 | 196 |  *    | xfs_dir2_data_hdr_t                             | | 
 | 197 |  *    +-------------------------------------------------+ | 
 | 198 |  *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | | 
 | 199 |  *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | | 
 | 200 |  *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | | 
 | 201 |  *    | ...                                             | | 
 | 202 |  *    +-------------------------------------------------+ | 
 | 203 |  *    | unused space                                    | | 
 | 204 |  *    +-------------------------------------------------+ | 
 | 205 |  * | 
 | 206 |  * As all the entries are variable size structures the accessors below should | 
 | 207 |  * be used to iterate over them. | 
 | 208 |  * | 
 | 209 |  * In addition to the pure data blocks for the data and node formats, | 
 | 210 |  * most structures are also used for the combined data/freespace "block" | 
 | 211 |  * format below. | 
 | 212 |  */ | 
 | 213 |  | 
 | 214 | #define	XFS_DIR2_DATA_ALIGN_LOG	3		/* i.e., 8 bytes */ | 
 | 215 | #define	XFS_DIR2_DATA_ALIGN	(1 << XFS_DIR2_DATA_ALIGN_LOG) | 
 | 216 | #define	XFS_DIR2_DATA_FREE_TAG	0xffff | 
 | 217 | #define	XFS_DIR2_DATA_FD_COUNT	3 | 
 | 218 |  | 
 | 219 | /* | 
 | 220 |  * Directory address space divided into sections, | 
 | 221 |  * spaces separated by 32GB. | 
 | 222 |  */ | 
 | 223 | #define	XFS_DIR2_SPACE_SIZE	(1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG)) | 
 | 224 | #define	XFS_DIR2_DATA_SPACE	0 | 
 | 225 | #define	XFS_DIR2_DATA_OFFSET	(XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE) | 
 | 226 | #define	XFS_DIR2_DATA_FIRSTDB(mp)	\ | 
 | 227 | 	xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET) | 
 | 228 |  | 
 | 229 | /* | 
 | 230 |  * Offsets of . and .. in data space (always block 0) | 
 | 231 |  */ | 
 | 232 | #define	XFS_DIR2_DATA_DOT_OFFSET	\ | 
 | 233 | 	((xfs_dir2_data_aoff_t)sizeof(struct xfs_dir2_data_hdr)) | 
 | 234 | #define	XFS_DIR2_DATA_DOTDOT_OFFSET	\ | 
 | 235 | 	(XFS_DIR2_DATA_DOT_OFFSET + xfs_dir2_data_entsize(1)) | 
 | 236 | #define	XFS_DIR2_DATA_FIRST_OFFSET		\ | 
 | 237 | 	(XFS_DIR2_DATA_DOTDOT_OFFSET + xfs_dir2_data_entsize(2)) | 
 | 238 |  | 
 | 239 | /* | 
 | 240 |  * Describe a free area in the data block. | 
 | 241 |  * | 
 | 242 |  * The freespace will be formatted as a xfs_dir2_data_unused_t. | 
 | 243 |  */ | 
 | 244 | typedef struct xfs_dir2_data_free { | 
 | 245 | 	__be16			offset;		/* start of freespace */ | 
 | 246 | 	__be16			length;		/* length of freespace */ | 
 | 247 | } xfs_dir2_data_free_t; | 
 | 248 |  | 
 | 249 | /* | 
 | 250 |  * Header for the data blocks. | 
 | 251 |  * | 
 | 252 |  * The code knows that XFS_DIR2_DATA_FD_COUNT is 3. | 
 | 253 |  */ | 
 | 254 | typedef struct xfs_dir2_data_hdr { | 
 | 255 | 	__be32			magic;		/* XFS_DIR2_DATA_MAGIC or */ | 
 | 256 | 						/* XFS_DIR2_BLOCK_MAGIC */ | 
 | 257 | 	xfs_dir2_data_free_t	bestfree[XFS_DIR2_DATA_FD_COUNT]; | 
 | 258 | } xfs_dir2_data_hdr_t; | 
 | 259 |  | 
 | 260 | /* | 
| Dave Chinner | f5f3d9b | 2013-04-03 16:11:20 +1100 | [diff] [blame^] | 261 |  * define a structure for all the verification fields we are adding to the | 
 | 262 |  * directory block structures. This will be used in several structures. | 
 | 263 |  * The magic number must be the first entry to align with all the dir2 | 
 | 264 |  * structures so we determine how to decode them just by the magic number. | 
 | 265 |  */ | 
 | 266 | struct xfs_dir3_blk_hdr { | 
 | 267 | 	__be32			magic;	/* magic number */ | 
 | 268 | 	__be32			crc;	/* CRC of block */ | 
 | 269 | 	__be64			blkno;	/* first block of the buffer */ | 
 | 270 | 	__be64			lsn;	/* sequence number of last write */ | 
 | 271 | 	uuid_t			uuid;	/* filesystem we belong to */ | 
 | 272 | 	__be64			owner;	/* inode that owns the block */ | 
 | 273 | }; | 
 | 274 |  | 
 | 275 | struct xfs_dir3_data_hdr { | 
 | 276 | 	struct xfs_dir3_blk_hdr	hdr; | 
 | 277 | 	xfs_dir2_data_free_t	best_free[XFS_DIR2_DATA_FD_COUNT]; | 
 | 278 | }; | 
 | 279 |  | 
 | 280 | #define XFS_DIR3_DATA_CRC_OFF  offsetof(struct xfs_dir3_data_hdr, hdr.crc) | 
 | 281 |  | 
 | 282 | static inline struct xfs_dir2_data_free * | 
 | 283 | xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) | 
 | 284 | { | 
 | 285 | 	if (hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { | 
 | 286 | 		struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr; | 
 | 287 | 		return hdr3->best_free; | 
 | 288 | 	} | 
 | 289 | 	return hdr->bestfree; | 
 | 290 | } | 
 | 291 |  | 
 | 292 | /* | 
| Christoph Hellwig | 5792664 | 2011-07-13 13:43:48 +0200 | [diff] [blame] | 293 |  * Active entry in a data block. | 
 | 294 |  * | 
 | 295 |  * Aligned to 8 bytes.  After the variable length name field there is a | 
 | 296 |  * 2 byte tag field, which can be accessed using xfs_dir2_data_entry_tag_p. | 
 | 297 |  */ | 
 | 298 | typedef struct xfs_dir2_data_entry { | 
 | 299 | 	__be64			inumber;	/* inode number */ | 
 | 300 | 	__u8			namelen;	/* name length */ | 
 | 301 | 	__u8			name[];		/* name bytes, no null */ | 
 | 302 |      /*	__be16                  tag; */		/* starting offset of us */ | 
 | 303 | } xfs_dir2_data_entry_t; | 
 | 304 |  | 
 | 305 | /* | 
 | 306 |  * Unused entry in a data block. | 
 | 307 |  * | 
 | 308 |  * Aligned to 8 bytes.  Tag appears as the last 2 bytes and must be accessed | 
 | 309 |  * using xfs_dir2_data_unused_tag_p. | 
 | 310 |  */ | 
 | 311 | typedef struct xfs_dir2_data_unused { | 
 | 312 | 	__be16			freetag;	/* XFS_DIR2_DATA_FREE_TAG */ | 
 | 313 | 	__be16			length;		/* total free length */ | 
 | 314 | 						/* variable offset */ | 
 | 315 | 	__be16			tag;		/* starting offset of us */ | 
 | 316 | } xfs_dir2_data_unused_t; | 
 | 317 |  | 
 | 318 | /* | 
 | 319 |  * Size of a data entry. | 
 | 320 |  */ | 
 | 321 | static inline int xfs_dir2_data_entsize(int n) | 
 | 322 | { | 
 | 323 | 	return (int)roundup(offsetof(struct xfs_dir2_data_entry, name[0]) + n + | 
 | 324 | 		 (uint)sizeof(xfs_dir2_data_off_t), XFS_DIR2_DATA_ALIGN); | 
 | 325 | } | 
 | 326 |  | 
 | 327 | /* | 
 | 328 |  * Pointer to an entry's tag word. | 
 | 329 |  */ | 
 | 330 | static inline __be16 * | 
 | 331 | xfs_dir2_data_entry_tag_p(struct xfs_dir2_data_entry *dep) | 
 | 332 | { | 
 | 333 | 	return (__be16 *)((char *)dep + | 
 | 334 | 		xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16)); | 
 | 335 | } | 
 | 336 |  | 
 | 337 | /* | 
 | 338 |  * Pointer to a freespace's tag word. | 
 | 339 |  */ | 
 | 340 | static inline __be16 * | 
 | 341 | xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup) | 
 | 342 | { | 
 | 343 | 	return (__be16 *)((char *)dup + | 
 | 344 | 			be16_to_cpu(dup->length) - sizeof(__be16)); | 
 | 345 | } | 
 | 346 |  | 
| Dave Chinner | f5f3d9b | 2013-04-03 16:11:20 +1100 | [diff] [blame^] | 347 | static inline struct xfs_dir2_data_unused * | 
 | 348 | xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) | 
 | 349 | { | 
 | 350 | 	if (hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { | 
 | 351 | 		return (struct xfs_dir2_data_unused *) | 
 | 352 | 			((char *)hdr + sizeof(struct xfs_dir3_data_hdr)); | 
 | 353 | 	} | 
 | 354 | 	return (struct xfs_dir2_data_unused *) | 
 | 355 | 		((char *)hdr + sizeof(struct xfs_dir2_data_hdr)); | 
 | 356 | } | 
 | 357 |  | 
 | 358 | static inline size_t | 
 | 359 | xfs_dir3_data_hdr_size(bool dir3) | 
 | 360 | { | 
 | 361 | 	if (dir3) | 
 | 362 | 		return sizeof(struct xfs_dir3_data_hdr); | 
 | 363 | 	return sizeof(struct xfs_dir2_data_hdr); | 
 | 364 | } | 
 | 365 |  | 
 | 366 | static inline size_t | 
 | 367 | xfs_dir3_data_entry_offset(struct xfs_dir2_data_hdr *hdr) | 
 | 368 | { | 
 | 369 | 	bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || | 
 | 370 | 		    hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); | 
 | 371 | 	return xfs_dir3_data_hdr_size(dir3); | 
 | 372 | } | 
 | 373 |  | 
 | 374 | static inline struct xfs_dir2_data_entry * | 
 | 375 | xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr) | 
 | 376 | { | 
 | 377 | 	return (struct xfs_dir2_data_entry *) | 
 | 378 | 		((char *)hdr + xfs_dir3_data_entry_offset(hdr)); | 
 | 379 | } | 
 | 380 |  | 
 | 381 | /* | 
 | 382 |  * Offsets of . and .. in data space (always block 0) | 
 | 383 |  */ | 
 | 384 | static inline xfs_dir2_data_aoff_t | 
 | 385 | xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr) | 
 | 386 | { | 
 | 387 | 	return xfs_dir3_data_entry_offset(hdr); | 
 | 388 | } | 
 | 389 |  | 
 | 390 | static inline xfs_dir2_data_aoff_t | 
 | 391 | xfs_dir3_data_dotdot_offset(struct xfs_dir2_data_hdr *hdr) | 
 | 392 | { | 
 | 393 | 	return xfs_dir3_data_dot_offset(hdr) + xfs_dir2_data_entsize(1); | 
 | 394 | } | 
 | 395 |  | 
 | 396 | static inline xfs_dir2_data_aoff_t | 
 | 397 | xfs_dir3_data_first_offset(struct xfs_dir2_data_hdr *hdr) | 
 | 398 | { | 
 | 399 | 	return xfs_dir3_data_dotdot_offset(hdr) + xfs_dir2_data_entsize(2); | 
 | 400 | } | 
 | 401 |  | 
 | 402 | /* | 
 | 403 |  * location of . and .. in data space (always block 0) | 
 | 404 |  */ | 
 | 405 | static inline struct xfs_dir2_data_entry * | 
 | 406 | xfs_dir3_data_dot_entry_p(struct xfs_dir2_data_hdr *hdr) | 
 | 407 | { | 
 | 408 | 	return (struct xfs_dir2_data_entry *) | 
 | 409 | 		((char *)hdr + xfs_dir3_data_dot_offset(hdr)); | 
 | 410 | } | 
 | 411 |  | 
 | 412 | static inline struct xfs_dir2_data_entry * | 
 | 413 | xfs_dir3_data_dotdot_entry_p(struct xfs_dir2_data_hdr *hdr) | 
 | 414 | { | 
 | 415 | 	return (struct xfs_dir2_data_entry *) | 
 | 416 | 		((char *)hdr + xfs_dir3_data_dotdot_offset(hdr)); | 
 | 417 | } | 
 | 418 |  | 
 | 419 | static inline struct xfs_dir2_data_entry * | 
 | 420 | xfs_dir3_data_first_entry_p(struct xfs_dir2_data_hdr *hdr) | 
 | 421 | { | 
 | 422 | 	return (struct xfs_dir2_data_entry *) | 
 | 423 | 		((char *)hdr + xfs_dir3_data_first_offset(hdr)); | 
 | 424 | } | 
 | 425 |  | 
| Christoph Hellwig | 5792664 | 2011-07-13 13:43:48 +0200 | [diff] [blame] | 426 | /* | 
 | 427 |  * Leaf block structures. | 
 | 428 |  * | 
 | 429 |  * A pure leaf block looks like the following drawing on disk: | 
 | 430 |  * | 
 | 431 |  *    +---------------------------+ | 
 | 432 |  *    | xfs_dir2_leaf_hdr_t       | | 
 | 433 |  *    +---------------------------+ | 
 | 434 |  *    | xfs_dir2_leaf_entry_t     | | 
 | 435 |  *    | xfs_dir2_leaf_entry_t     | | 
 | 436 |  *    | xfs_dir2_leaf_entry_t     | | 
 | 437 |  *    | xfs_dir2_leaf_entry_t     | | 
 | 438 |  *    | ...                       | | 
 | 439 |  *    +---------------------------+ | 
 | 440 |  *    | xfs_dir2_data_off_t       | | 
 | 441 |  *    | xfs_dir2_data_off_t       | | 
 | 442 |  *    | xfs_dir2_data_off_t       | | 
 | 443 |  *    | ...                       | | 
 | 444 |  *    +---------------------------+ | 
 | 445 |  *    | xfs_dir2_leaf_tail_t      | | 
 | 446 |  *    +---------------------------+ | 
 | 447 |  * | 
 | 448 |  * The xfs_dir2_data_off_t members (bests) and tail are at the end of the block | 
 | 449 |  * for single-leaf (magic = XFS_DIR2_LEAF1_MAGIC) blocks only, but not present | 
 | 450 |  * for directories with separate leaf nodes and free space blocks | 
 | 451 |  * (magic = XFS_DIR2_LEAFN_MAGIC). | 
 | 452 |  * | 
 | 453 |  * As all the entries are variable size structures the accessors below should | 
 | 454 |  * be used to iterate over them. | 
 | 455 |  */ | 
 | 456 |  | 
 | 457 | /* | 
 | 458 |  * Offset of the leaf/node space.  First block in this space | 
 | 459 |  * is the btree root. | 
 | 460 |  */ | 
 | 461 | #define	XFS_DIR2_LEAF_SPACE	1 | 
 | 462 | #define	XFS_DIR2_LEAF_OFFSET	(XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE) | 
 | 463 | #define	XFS_DIR2_LEAF_FIRSTDB(mp)	\ | 
 | 464 | 	xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET) | 
 | 465 |  | 
 | 466 | /* | 
 | 467 |  * Leaf block header. | 
 | 468 |  */ | 
 | 469 | typedef struct xfs_dir2_leaf_hdr { | 
 | 470 | 	xfs_da_blkinfo_t	info;		/* header for da routines */ | 
 | 471 | 	__be16			count;		/* count of entries */ | 
 | 472 | 	__be16			stale;		/* count of stale entries */ | 
 | 473 | } xfs_dir2_leaf_hdr_t; | 
 | 474 |  | 
 | 475 | /* | 
 | 476 |  * Leaf block entry. | 
 | 477 |  */ | 
 | 478 | typedef struct xfs_dir2_leaf_entry { | 
 | 479 | 	__be32			hashval;	/* hash value of name */ | 
 | 480 | 	__be32			address;	/* address of data entry */ | 
 | 481 | } xfs_dir2_leaf_entry_t; | 
 | 482 |  | 
 | 483 | /* | 
 | 484 |  * Leaf block tail. | 
 | 485 |  */ | 
 | 486 | typedef struct xfs_dir2_leaf_tail { | 
 | 487 | 	__be32			bestcount; | 
 | 488 | } xfs_dir2_leaf_tail_t; | 
 | 489 |  | 
 | 490 | /* | 
 | 491 |  * Leaf block. | 
 | 492 |  */ | 
 | 493 | typedef struct xfs_dir2_leaf { | 
 | 494 | 	xfs_dir2_leaf_hdr_t	hdr;		/* leaf header */ | 
 | 495 | 	xfs_dir2_leaf_entry_t	ents[];		/* entries */ | 
 | 496 | } xfs_dir2_leaf_t; | 
 | 497 |  | 
 | 498 | /* | 
 | 499 |  * DB blocks here are logical directory block numbers, not filesystem blocks. | 
 | 500 |  */ | 
 | 501 |  | 
 | 502 | static inline int xfs_dir2_max_leaf_ents(struct xfs_mount *mp) | 
 | 503 | { | 
 | 504 | 	return (mp->m_dirblksize - (uint)sizeof(struct xfs_dir2_leaf_hdr)) / | 
 | 505 | 		(uint)sizeof(struct xfs_dir2_leaf_entry); | 
 | 506 | } | 
 | 507 |  | 
 | 508 | /* | 
 | 509 |  * Get address of the bestcount field in the single-leaf block. | 
 | 510 |  */ | 
 | 511 | static inline struct xfs_dir2_leaf_tail * | 
 | 512 | xfs_dir2_leaf_tail_p(struct xfs_mount *mp, struct xfs_dir2_leaf *lp) | 
 | 513 | { | 
 | 514 | 	return (struct xfs_dir2_leaf_tail *) | 
 | 515 | 		((char *)lp + mp->m_dirblksize - | 
 | 516 | 		  sizeof(struct xfs_dir2_leaf_tail)); | 
 | 517 | } | 
 | 518 |  | 
 | 519 | /* | 
 | 520 |  * Get address of the bests array in the single-leaf block. | 
 | 521 |  */ | 
 | 522 | static inline __be16 * | 
 | 523 | xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp) | 
 | 524 | { | 
 | 525 | 	return (__be16 *)ltp - be32_to_cpu(ltp->bestcount); | 
 | 526 | } | 
 | 527 |  | 
 | 528 | /* | 
 | 529 |  * Convert dataptr to byte in file space | 
 | 530 |  */ | 
 | 531 | static inline xfs_dir2_off_t | 
 | 532 | xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) | 
 | 533 | { | 
 | 534 | 	return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG; | 
 | 535 | } | 
 | 536 |  | 
 | 537 | /* | 
 | 538 |  * Convert byte in file space to dataptr.  It had better be aligned. | 
 | 539 |  */ | 
 | 540 | static inline xfs_dir2_dataptr_t | 
 | 541 | xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by) | 
 | 542 | { | 
 | 543 | 	return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG); | 
 | 544 | } | 
 | 545 |  | 
 | 546 | /* | 
 | 547 |  * Convert byte in space to (DB) block | 
 | 548 |  */ | 
 | 549 | static inline xfs_dir2_db_t | 
 | 550 | xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by) | 
 | 551 | { | 
 | 552 | 	return (xfs_dir2_db_t) | 
 | 553 | 		(by >> (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)); | 
 | 554 | } | 
 | 555 |  | 
 | 556 | /* | 
 | 557 |  * Convert dataptr to a block number | 
 | 558 |  */ | 
 | 559 | static inline xfs_dir2_db_t | 
 | 560 | xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) | 
 | 561 | { | 
 | 562 | 	return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp)); | 
 | 563 | } | 
 | 564 |  | 
 | 565 | /* | 
 | 566 |  * Convert byte in space to offset in a block | 
 | 567 |  */ | 
 | 568 | static inline xfs_dir2_data_aoff_t | 
 | 569 | xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by) | 
 | 570 | { | 
 | 571 | 	return (xfs_dir2_data_aoff_t)(by & | 
 | 572 | 		((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) - 1)); | 
 | 573 | } | 
 | 574 |  | 
 | 575 | /* | 
 | 576 |  * Convert dataptr to a byte offset in a block | 
 | 577 |  */ | 
 | 578 | static inline xfs_dir2_data_aoff_t | 
 | 579 | xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) | 
 | 580 | { | 
 | 581 | 	return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp)); | 
 | 582 | } | 
 | 583 |  | 
 | 584 | /* | 
 | 585 |  * Convert block and offset to byte in space | 
 | 586 |  */ | 
 | 587 | static inline xfs_dir2_off_t | 
 | 588 | xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db, | 
 | 589 | 			xfs_dir2_data_aoff_t o) | 
 | 590 | { | 
 | 591 | 	return ((xfs_dir2_off_t)db << | 
 | 592 | 		(mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) + o; | 
 | 593 | } | 
 | 594 |  | 
 | 595 | /* | 
 | 596 |  * Convert block (DB) to block (dablk) | 
 | 597 |  */ | 
 | 598 | static inline xfs_dablk_t | 
 | 599 | xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db) | 
 | 600 | { | 
 | 601 | 	return (xfs_dablk_t)(db << mp->m_sb.sb_dirblklog); | 
 | 602 | } | 
 | 603 |  | 
 | 604 | /* | 
 | 605 |  * Convert byte in space to (DA) block | 
 | 606 |  */ | 
 | 607 | static inline xfs_dablk_t | 
 | 608 | xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by) | 
 | 609 | { | 
 | 610 | 	return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by)); | 
 | 611 | } | 
 | 612 |  | 
 | 613 | /* | 
 | 614 |  * Convert block and offset to dataptr | 
 | 615 |  */ | 
 | 616 | static inline xfs_dir2_dataptr_t | 
 | 617 | xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db, | 
 | 618 | 			   xfs_dir2_data_aoff_t o) | 
 | 619 | { | 
 | 620 | 	return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o)); | 
 | 621 | } | 
 | 622 |  | 
 | 623 | /* | 
 | 624 |  * Convert block (dablk) to block (DB) | 
 | 625 |  */ | 
 | 626 | static inline xfs_dir2_db_t | 
 | 627 | xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da) | 
 | 628 | { | 
 | 629 | 	return (xfs_dir2_db_t)(da >> mp->m_sb.sb_dirblklog); | 
 | 630 | } | 
 | 631 |  | 
 | 632 | /* | 
 | 633 |  * Convert block (dablk) to byte offset in space | 
 | 634 |  */ | 
 | 635 | static inline xfs_dir2_off_t | 
 | 636 | xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da) | 
 | 637 | { | 
 | 638 | 	return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0); | 
 | 639 | } | 
 | 640 |  | 
 | 641 | /* | 
 | 642 |  * Free space block defintions for the node format. | 
 | 643 |  */ | 
 | 644 |  | 
 | 645 | /* | 
 | 646 |  * Offset of the freespace index. | 
 | 647 |  */ | 
 | 648 | #define	XFS_DIR2_FREE_SPACE	2 | 
 | 649 | #define	XFS_DIR2_FREE_OFFSET	(XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE) | 
 | 650 | #define	XFS_DIR2_FREE_FIRSTDB(mp)	\ | 
 | 651 | 	xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET) | 
 | 652 |  | 
 | 653 | typedef	struct xfs_dir2_free_hdr { | 
 | 654 | 	__be32			magic;		/* XFS_DIR2_FREE_MAGIC */ | 
 | 655 | 	__be32			firstdb;	/* db of first entry */ | 
 | 656 | 	__be32			nvalid;		/* count of valid entries */ | 
 | 657 | 	__be32			nused;		/* count of used entries */ | 
 | 658 | } xfs_dir2_free_hdr_t; | 
 | 659 |  | 
 | 660 | typedef struct xfs_dir2_free { | 
 | 661 | 	xfs_dir2_free_hdr_t	hdr;		/* block header */ | 
| Christoph Hellwig | a00b774 | 2011-07-13 13:43:48 +0200 | [diff] [blame] | 662 | 	__be16			bests[];	/* best free counts */ | 
| Christoph Hellwig | 5792664 | 2011-07-13 13:43:48 +0200 | [diff] [blame] | 663 | 						/* unused entries are -1 */ | 
 | 664 | } xfs_dir2_free_t; | 
 | 665 |  | 
| Christoph Hellwig | a00b774 | 2011-07-13 13:43:48 +0200 | [diff] [blame] | 666 | static inline int xfs_dir2_free_max_bests(struct xfs_mount *mp) | 
 | 667 | { | 
 | 668 | 	return (mp->m_dirblksize - sizeof(struct xfs_dir2_free_hdr)) / | 
 | 669 | 		sizeof(xfs_dir2_data_off_t); | 
 | 670 | } | 
| Christoph Hellwig | 5792664 | 2011-07-13 13:43:48 +0200 | [diff] [blame] | 671 |  | 
 | 672 | /* | 
 | 673 |  * Convert data space db to the corresponding free db. | 
 | 674 |  */ | 
 | 675 | static inline xfs_dir2_db_t | 
 | 676 | xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db) | 
 | 677 | { | 
| Christoph Hellwig | a00b774 | 2011-07-13 13:43:48 +0200 | [diff] [blame] | 678 | 	return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir2_free_max_bests(mp); | 
| Christoph Hellwig | 5792664 | 2011-07-13 13:43:48 +0200 | [diff] [blame] | 679 | } | 
 | 680 |  | 
 | 681 | /* | 
 | 682 |  * Convert data space db to the corresponding index in a free db. | 
 | 683 |  */ | 
 | 684 | static inline int | 
 | 685 | xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db) | 
 | 686 | { | 
| Christoph Hellwig | a00b774 | 2011-07-13 13:43:48 +0200 | [diff] [blame] | 687 | 	return db % xfs_dir2_free_max_bests(mp); | 
| Christoph Hellwig | 5792664 | 2011-07-13 13:43:48 +0200 | [diff] [blame] | 688 | } | 
 | 689 |  | 
 | 690 | /* | 
 | 691 |  * Single block format. | 
 | 692 |  * | 
 | 693 |  * The single block format looks like the following drawing on disk: | 
 | 694 |  * | 
 | 695 |  *    +-------------------------------------------------+ | 
 | 696 |  *    | xfs_dir2_data_hdr_t                             | | 
 | 697 |  *    +-------------------------------------------------+ | 
 | 698 |  *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | | 
 | 699 |  *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | | 
 | 700 |  *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t : | 
 | 701 |  *    | ...                                             | | 
 | 702 |  *    +-------------------------------------------------+ | 
 | 703 |  *    | unused space                                    | | 
 | 704 |  *    +-------------------------------------------------+ | 
 | 705 |  *    | ...                                             | | 
 | 706 |  *    | xfs_dir2_leaf_entry_t                           | | 
 | 707 |  *    | xfs_dir2_leaf_entry_t                           | | 
 | 708 |  *    +-------------------------------------------------+ | 
 | 709 |  *    | xfs_dir2_block_tail_t                           | | 
 | 710 |  *    +-------------------------------------------------+ | 
 | 711 |  * | 
 | 712 |  * As all the entries are variable size structures the accessors below should | 
 | 713 |  * be used to iterate over them. | 
 | 714 |  */ | 
 | 715 |  | 
 | 716 | typedef struct xfs_dir2_block_tail { | 
 | 717 | 	__be32		count;			/* count of leaf entries */ | 
 | 718 | 	__be32		stale;			/* count of stale lf entries */ | 
 | 719 | } xfs_dir2_block_tail_t; | 
 | 720 |  | 
 | 721 | /* | 
 | 722 |  * Pointer to the leaf header embedded in a data block (1-block format) | 
 | 723 |  */ | 
 | 724 | static inline struct xfs_dir2_block_tail * | 
 | 725 | xfs_dir2_block_tail_p(struct xfs_mount *mp, struct xfs_dir2_data_hdr *hdr) | 
 | 726 | { | 
 | 727 | 	return ((struct xfs_dir2_block_tail *) | 
 | 728 | 		((char *)hdr + mp->m_dirblksize)) - 1; | 
 | 729 | } | 
 | 730 |  | 
 | 731 | /* | 
 | 732 |  * Pointer to the leaf entries embedded in a data block (1-block format) | 
 | 733 |  */ | 
 | 734 | static inline struct xfs_dir2_leaf_entry * | 
 | 735 | xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp) | 
 | 736 | { | 
 | 737 | 	return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count); | 
 | 738 | } | 
 | 739 |  | 
 | 740 | #endif /* __XFS_DIR2_FORMAT_H__ */ |