/fs/xfs/xfs_dir2_format.h
C Header | 597 lines | 266 code | 64 blank | 267 comment | 1 complexity | 8141ea2dcc1101b8b363b01619521bf6 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
1/* 2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. 3 * All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18#ifndef __XFS_DIR2_FORMAT_H__ 19#define __XFS_DIR2_FORMAT_H__ 20 21/* 22 * Directory version 2. 23 * 24 * There are 4 possible formats: 25 * - shortform - embedded into the inode 26 * - single block - data with embedded leaf at the end 27 * - multiple data blocks, single leaf+freeindex block 28 * - data blocks, node and leaf blocks (btree), freeindex blocks 29 * 30 * Note: many node blocks structures and constants are shared with the attr 31 * code and defined in xfs_da_btree.h. 32 */ 33 34#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: single block dirs */ 35#define XFS_DIR2_DATA_MAGIC 0x58443244 /* XD2D: multiblock dirs */ 36#define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F: free index blocks */ 37 38/* 39 * Byte offset in data block and shortform entry. 40 */ 41typedef __uint16_t xfs_dir2_data_off_t; 42#define NULLDATAOFF 0xffffU 43typedef uint xfs_dir2_data_aoff_t; /* argument form */ 44 45/* 46 * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t. 47 * Only need 16 bits, this is the byte offset into the single block form. 48 */ 49typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t; 50 51/* 52 * Offset in data space of a data entry. 53 */ 54typedef __uint32_t xfs_dir2_dataptr_t; 55#define XFS_DIR2_MAX_DATAPTR ((xfs_dir2_dataptr_t)0xffffffff) 56#define XFS_DIR2_NULL_DATAPTR ((xfs_dir2_dataptr_t)0) 57 58/* 59 * Byte offset in a directory. 60 */ 61typedef xfs_off_t xfs_dir2_off_t; 62 63/* 64 * Directory block number (logical dirblk in file) 65 */ 66typedef __uint32_t xfs_dir2_db_t; 67 68/* 69 * Inode number stored as 8 8-bit values. 70 */ 71typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t; 72 73/* 74 * Inode number stored as 4 8-bit values. 75 * Works a lot of the time, when all the inode numbers in a directory 76 * fit in 32 bits. 77 */ 78typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t; 79 80typedef union { 81 xfs_dir2_ino8_t i8; 82 xfs_dir2_ino4_t i4; 83} xfs_dir2_inou_t; 84#define XFS_DIR2_MAX_SHORT_INUM ((xfs_ino_t)0xffffffffULL) 85 86/* 87 * Directory layout when stored internal to an inode. 88 * 89 * Small directories are packed as tightly as possible so as to fit into the 90 * literal area of the inode. These "shortform" directories consist of a 91 * single xfs_dir2_sf_hdr header followed by zero or more xfs_dir2_sf_entry 92 * structures. Due the different inode number storage size and the variable 93 * length name field in the xfs_dir2_sf_entry all these structure are 94 * variable length, and the accessors in this file should be used to iterate 95 * over them. 96 */ 97typedef struct xfs_dir2_sf_hdr { 98 __uint8_t count; /* count of entries */ 99 __uint8_t i8count; /* count of 8-byte inode #s */ 100 xfs_dir2_inou_t parent; /* parent dir inode number */ 101} __arch_pack xfs_dir2_sf_hdr_t; 102 103typedef struct xfs_dir2_sf_entry { 104 __u8 namelen; /* actual name length */ 105 xfs_dir2_sf_off_t offset; /* saved offset */ 106 __u8 name[]; /* name, variable size */ 107 /* 108 * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a 109 * variable offset after the name. 110 */ 111} __arch_pack xfs_dir2_sf_entry_t; 112 113static inline int xfs_dir2_sf_hdr_size(int i8count) 114{ 115 return sizeof(struct xfs_dir2_sf_hdr) - 116 (i8count == 0) * 117 (sizeof(xfs_dir2_ino8_t) - sizeof(xfs_dir2_ino4_t)); 118} 119 120static inline xfs_dir2_data_aoff_t 121xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep) 122{ 123 return get_unaligned_be16(&sfep->offset.i); 124} 125 126static inline void 127xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off) 128{ 129 put_unaligned_be16(off, &sfep->offset.i); 130} 131 132static inline int 133xfs_dir2_sf_entsize(struct xfs_dir2_sf_hdr *hdr, int len) 134{ 135 return sizeof(struct xfs_dir2_sf_entry) + /* namelen + offset */ 136 len + /* name */ 137 (hdr->i8count ? /* ino */ 138 sizeof(xfs_dir2_ino8_t) : 139 sizeof(xfs_dir2_ino4_t)); 140} 141 142static inline struct xfs_dir2_sf_entry * 143xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr) 144{ 145 return (struct xfs_dir2_sf_entry *) 146 ((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count)); 147} 148 149static inline struct xfs_dir2_sf_entry * 150xfs_dir2_sf_nextentry(struct xfs_dir2_sf_hdr *hdr, 151 struct xfs_dir2_sf_entry *sfep) 152{ 153 return (struct xfs_dir2_sf_entry *) 154 ((char *)sfep + xfs_dir2_sf_entsize(hdr, sfep->namelen)); 155} 156 157 158/* 159 * Data block structures. 160 * 161 * A pure data block looks like the following drawing on disk: 162 * 163 * +-------------------------------------------------+ 164 * | xfs_dir2_data_hdr_t | 165 * +-------------------------------------------------+ 166 * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | 167 * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | 168 * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | 169 * | ... | 170 * +-------------------------------------------------+ 171 * | unused space | 172 * +-------------------------------------------------+ 173 * 174 * As all the entries are variable size structures the accessors below should 175 * be used to iterate over them. 176 * 177 * In addition to the pure data blocks for the data and node formats, 178 * most structures are also used for the combined data/freespace "block" 179 * format below. 180 */ 181 182#define XFS_DIR2_DATA_ALIGN_LOG 3 /* i.e., 8 bytes */ 183#define XFS_DIR2_DATA_ALIGN (1 << XFS_DIR2_DATA_ALIGN_LOG) 184#define XFS_DIR2_DATA_FREE_TAG 0xffff 185#define XFS_DIR2_DATA_FD_COUNT 3 186 187/* 188 * Directory address space divided into sections, 189 * spaces separated by 32GB. 190 */ 191#define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG)) 192#define XFS_DIR2_DATA_SPACE 0 193#define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE) 194#define XFS_DIR2_DATA_FIRSTDB(mp) \ 195 xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET) 196 197/* 198 * Offsets of . and .. in data space (always block 0) 199 */ 200#define XFS_DIR2_DATA_DOT_OFFSET \ 201 ((xfs_dir2_data_aoff_t)sizeof(struct xfs_dir2_data_hdr)) 202#define XFS_DIR2_DATA_DOTDOT_OFFSET \ 203 (XFS_DIR2_DATA_DOT_OFFSET + xfs_dir2_data_entsize(1)) 204#define XFS_DIR2_DATA_FIRST_OFFSET \ 205 (XFS_DIR2_DATA_DOTDOT_OFFSET + xfs_dir2_data_entsize(2)) 206 207/* 208 * Describe a free area in the data block. 209 * 210 * The freespace will be formatted as a xfs_dir2_data_unused_t. 211 */ 212typedef struct xfs_dir2_data_free { 213 __be16 offset; /* start of freespace */ 214 __be16 length; /* length of freespace */ 215} xfs_dir2_data_free_t; 216 217/* 218 * Header for the data blocks. 219 * 220 * The code knows that XFS_DIR2_DATA_FD_COUNT is 3. 221 */ 222typedef struct xfs_dir2_data_hdr { 223 __be32 magic; /* XFS_DIR2_DATA_MAGIC or */ 224 /* XFS_DIR2_BLOCK_MAGIC */ 225 xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT]; 226} xfs_dir2_data_hdr_t; 227 228/* 229 * Active entry in a data block. 230 * 231 * Aligned to 8 bytes. After the variable length name field there is a 232 * 2 byte tag field, which can be accessed using xfs_dir2_data_entry_tag_p. 233 */ 234typedef struct xfs_dir2_data_entry { 235 __be64 inumber; /* inode number */ 236 __u8 namelen; /* name length */ 237 __u8 name[]; /* name bytes, no null */ 238 /* __be16 tag; */ /* starting offset of us */ 239} xfs_dir2_data_entry_t; 240 241/* 242 * Unused entry in a data block. 243 * 244 * Aligned to 8 bytes. Tag appears as the last 2 bytes and must be accessed 245 * using xfs_dir2_data_unused_tag_p. 246 */ 247typedef struct xfs_dir2_data_unused { 248 __be16 freetag; /* XFS_DIR2_DATA_FREE_TAG */ 249 __be16 length; /* total free length */ 250 /* variable offset */ 251 __be16 tag; /* starting offset of us */ 252} xfs_dir2_data_unused_t; 253 254/* 255 * Size of a data entry. 256 */ 257static inline int xfs_dir2_data_entsize(int n) 258{ 259 return (int)roundup(offsetof(struct xfs_dir2_data_entry, name[0]) + n + 260 (uint)sizeof(xfs_dir2_data_off_t), XFS_DIR2_DATA_ALIGN); 261} 262 263/* 264 * Pointer to an entry's tag word. 265 */ 266static inline __be16 * 267xfs_dir2_data_entry_tag_p(struct xfs_dir2_data_entry *dep) 268{ 269 return (__be16 *)((char *)dep + 270 xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16)); 271} 272 273/* 274 * Pointer to a freespace's tag word. 275 */ 276static inline __be16 * 277xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup) 278{ 279 return (__be16 *)((char *)dup + 280 be16_to_cpu(dup->length) - sizeof(__be16)); 281} 282 283/* 284 * Leaf block structures. 285 * 286 * A pure leaf block looks like the following drawing on disk: 287 * 288 * +---------------------------+ 289 * | xfs_dir2_leaf_hdr_t | 290 * +---------------------------+ 291 * | xfs_dir2_leaf_entry_t | 292 * | xfs_dir2_leaf_entry_t | 293 * | xfs_dir2_leaf_entry_t | 294 * | xfs_dir2_leaf_entry_t | 295 * | ... | 296 * +---------------------------+ 297 * | xfs_dir2_data_off_t | 298 * | xfs_dir2_data_off_t | 299 * | xfs_dir2_data_off_t | 300 * | ... | 301 * +---------------------------+ 302 * | xfs_dir2_leaf_tail_t | 303 * +---------------------------+ 304 * 305 * The xfs_dir2_data_off_t members (bests) and tail are at the end of the block 306 * for single-leaf (magic = XFS_DIR2_LEAF1_MAGIC) blocks only, but not present 307 * for directories with separate leaf nodes and free space blocks 308 * (magic = XFS_DIR2_LEAFN_MAGIC). 309 * 310 * As all the entries are variable size structures the accessors below should 311 * be used to iterate over them. 312 */ 313 314/* 315 * Offset of the leaf/node space. First block in this space 316 * is the btree root. 317 */ 318#define XFS_DIR2_LEAF_SPACE 1 319#define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE) 320#define XFS_DIR2_LEAF_FIRSTDB(mp) \ 321 xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET) 322 323/* 324 * Leaf block header. 325 */ 326typedef struct xfs_dir2_leaf_hdr { 327 xfs_da_blkinfo_t info; /* header for da routines */ 328 __be16 count; /* count of entries */ 329 __be16 stale; /* count of stale entries */ 330} xfs_dir2_leaf_hdr_t; 331 332/* 333 * Leaf block entry. 334 */ 335typedef struct xfs_dir2_leaf_entry { 336 __be32 hashval; /* hash value of name */ 337 __be32 address; /* address of data entry */ 338} xfs_dir2_leaf_entry_t; 339 340/* 341 * Leaf block tail. 342 */ 343typedef struct xfs_dir2_leaf_tail { 344 __be32 bestcount; 345} xfs_dir2_leaf_tail_t; 346 347/* 348 * Leaf block. 349 */ 350typedef struct xfs_dir2_leaf { 351 xfs_dir2_leaf_hdr_t hdr; /* leaf header */ 352 xfs_dir2_leaf_entry_t ents[]; /* entries */ 353} xfs_dir2_leaf_t; 354 355/* 356 * DB blocks here are logical directory block numbers, not filesystem blocks. 357 */ 358 359static inline int xfs_dir2_max_leaf_ents(struct xfs_mount *mp) 360{ 361 return (mp->m_dirblksize - (uint)sizeof(struct xfs_dir2_leaf_hdr)) / 362 (uint)sizeof(struct xfs_dir2_leaf_entry); 363} 364 365/* 366 * Get address of the bestcount field in the single-leaf block. 367 */ 368static inline struct xfs_dir2_leaf_tail * 369xfs_dir2_leaf_tail_p(struct xfs_mount *mp, struct xfs_dir2_leaf *lp) 370{ 371 return (struct xfs_dir2_leaf_tail *) 372 ((char *)lp + mp->m_dirblksize - 373 sizeof(struct xfs_dir2_leaf_tail)); 374} 375 376/* 377 * Get address of the bests array in the single-leaf block. 378 */ 379static inline __be16 * 380xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp) 381{ 382 return (__be16 *)ltp - be32_to_cpu(ltp->bestcount); 383} 384 385/* 386 * Convert dataptr to byte in file space 387 */ 388static inline xfs_dir2_off_t 389xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) 390{ 391 return (xfs_dir2_off_t)dp << XFS_DIR2_DATA_ALIGN_LOG; 392} 393 394/* 395 * Convert byte in file space to dataptr. It had better be aligned. 396 */ 397static inline xfs_dir2_dataptr_t 398xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by) 399{ 400 return (xfs_dir2_dataptr_t)(by >> XFS_DIR2_DATA_ALIGN_LOG); 401} 402 403/* 404 * Convert byte in space to (DB) block 405 */ 406static inline xfs_dir2_db_t 407xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by) 408{ 409 return (xfs_dir2_db_t) 410 (by >> (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)); 411} 412 413/* 414 * Convert dataptr to a block number 415 */ 416static inline xfs_dir2_db_t 417xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) 418{ 419 return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp)); 420} 421 422/* 423 * Convert byte in space to offset in a block 424 */ 425static inline xfs_dir2_data_aoff_t 426xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by) 427{ 428 return (xfs_dir2_data_aoff_t)(by & 429 ((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) - 1)); 430} 431 432/* 433 * Convert dataptr to a byte offset in a block 434 */ 435static inline xfs_dir2_data_aoff_t 436xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp) 437{ 438 return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp)); 439} 440 441/* 442 * Convert block and offset to byte in space 443 */ 444static inline xfs_dir2_off_t 445xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db, 446 xfs_dir2_data_aoff_t o) 447{ 448 return ((xfs_dir2_off_t)db << 449 (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) + o; 450} 451 452/* 453 * Convert block (DB) to block (dablk) 454 */ 455static inline xfs_dablk_t 456xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db) 457{ 458 return (xfs_dablk_t)(db << mp->m_sb.sb_dirblklog); 459} 460 461/* 462 * Convert byte in space to (DA) block 463 */ 464static inline xfs_dablk_t 465xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by) 466{ 467 return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by)); 468} 469 470/* 471 * Convert block and offset to dataptr 472 */ 473static inline xfs_dir2_dataptr_t 474xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db, 475 xfs_dir2_data_aoff_t o) 476{ 477 return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o)); 478} 479 480/* 481 * Convert block (dablk) to block (DB) 482 */ 483static inline xfs_dir2_db_t 484xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da) 485{ 486 return (xfs_dir2_db_t)(da >> mp->m_sb.sb_dirblklog); 487} 488 489/* 490 * Convert block (dablk) to byte offset in space 491 */ 492static inline xfs_dir2_off_t 493xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da) 494{ 495 return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0); 496} 497 498/* 499 * Free space block defintions for the node format. 500 */ 501 502/* 503 * Offset of the freespace index. 504 */ 505#define XFS_DIR2_FREE_SPACE 2 506#define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE) 507#define XFS_DIR2_FREE_FIRSTDB(mp) \ 508 xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET) 509 510typedef struct xfs_dir2_free_hdr { 511 __be32 magic; /* XFS_DIR2_FREE_MAGIC */ 512 __be32 firstdb; /* db of first entry */ 513 __be32 nvalid; /* count of valid entries */ 514 __be32 nused; /* count of used entries */ 515} xfs_dir2_free_hdr_t; 516 517typedef struct xfs_dir2_free { 518 xfs_dir2_free_hdr_t hdr; /* block header */ 519 __be16 bests[]; /* best free counts */ 520 /* unused entries are -1 */ 521} xfs_dir2_free_t; 522 523static inline int xfs_dir2_free_max_bests(struct xfs_mount *mp) 524{ 525 return (mp->m_dirblksize - sizeof(struct xfs_dir2_free_hdr)) / 526 sizeof(xfs_dir2_data_off_t); 527} 528 529/* 530 * Convert data space db to the corresponding free db. 531 */ 532static inline xfs_dir2_db_t 533xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db) 534{ 535 return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir2_free_max_bests(mp); 536} 537 538/* 539 * Convert data space db to the corresponding index in a free db. 540 */ 541static inline int 542xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db) 543{ 544 return db % xfs_dir2_free_max_bests(mp); 545} 546 547/* 548 * Single block format. 549 * 550 * The single block format looks like the following drawing on disk: 551 * 552 * +-------------------------------------------------+ 553 * | xfs_dir2_data_hdr_t | 554 * +-------------------------------------------------+ 555 * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | 556 * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | 557 * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t : 558 * | ... | 559 * +-------------------------------------------------+ 560 * | unused space | 561 * +-------------------------------------------------+ 562 * | ... | 563 * | xfs_dir2_leaf_entry_t | 564 * | xfs_dir2_leaf_entry_t | 565 * +-------------------------------------------------+ 566 * | xfs_dir2_block_tail_t | 567 * +-------------------------------------------------+ 568 * 569 * As all the entries are variable size structures the accessors below should 570 * be used to iterate over them. 571 */ 572 573typedef struct xfs_dir2_block_tail { 574 __be32 count; /* count of leaf entries */ 575 __be32 stale; /* count of stale lf entries */ 576} xfs_dir2_block_tail_t; 577 578/* 579 * Pointer to the leaf header embedded in a data block (1-block format) 580 */ 581static inline struct xfs_dir2_block_tail * 582xfs_dir2_block_tail_p(struct xfs_mount *mp, struct xfs_dir2_data_hdr *hdr) 583{ 584 return ((struct xfs_dir2_block_tail *) 585 ((char *)hdr + mp->m_dirblksize)) - 1; 586} 587 588/* 589 * Pointer to the leaf entries embedded in a data block (1-block format) 590 */ 591static inline struct xfs_dir2_leaf_entry * 592xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp) 593{ 594 return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count); 595} 596 597#endif /* __XFS_DIR2_FORMAT_H__ */