1*4882a593Smuzhiyun.. SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun 3*4882a593SmuzhiyunDirectory Entries 4*4882a593Smuzhiyun----------------- 5*4882a593Smuzhiyun 6*4882a593SmuzhiyunIn an ext4 filesystem, a directory is more or less a flat file that maps 7*4882a593Smuzhiyunan arbitrary byte string (usually ASCII) to an inode number on the 8*4882a593Smuzhiyunfilesystem. There can be many directory entries across the filesystem 9*4882a593Smuzhiyunthat reference the same inode number--these are known as hard links, and 10*4882a593Smuzhiyunthat is why hard links cannot reference files on other filesystems. As 11*4882a593Smuzhiyunsuch, directory entries are found by reading the data block(s) 12*4882a593Smuzhiyunassociated with a directory file for the particular directory entry that 13*4882a593Smuzhiyunis desired. 14*4882a593Smuzhiyun 15*4882a593SmuzhiyunLinear (Classic) Directories 16*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17*4882a593Smuzhiyun 18*4882a593SmuzhiyunBy default, each directory lists its entries in an “almost-linear” 19*4882a593Smuzhiyunarray. I write “almost” because it's not a linear array in the memory 20*4882a593Smuzhiyunsense because directory entries are not split across filesystem blocks. 21*4882a593SmuzhiyunTherefore, it is more accurate to say that a directory is a series of 22*4882a593Smuzhiyundata blocks and that each block contains a linear array of directory 23*4882a593Smuzhiyunentries. The end of each per-block array is signified by reaching the 24*4882a593Smuzhiyunend of the block; the last entry in the block has a record length that 25*4882a593Smuzhiyuntakes it all the way to the end of the block. The end of the entire 26*4882a593Smuzhiyundirectory is of course signified by reaching the end of the file. Unused 27*4882a593Smuzhiyundirectory entries are signified by inode = 0. By default the filesystem 28*4882a593Smuzhiyunuses ``struct ext4_dir_entry_2`` for directory entries unless the 29*4882a593Smuzhiyun“filetype” feature flag is not set, in which case it uses 30*4882a593Smuzhiyun``struct ext4_dir_entry``. 31*4882a593Smuzhiyun 32*4882a593SmuzhiyunThe original directory entry format is ``struct ext4_dir_entry``, which 33*4882a593Smuzhiyunis at most 263 bytes long, though on disk you'll need to reference 34*4882a593Smuzhiyun``dirent.rec_len`` to know for sure. 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun.. list-table:: 37*4882a593Smuzhiyun :widths: 8 8 24 40 38*4882a593Smuzhiyun :header-rows: 1 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun * - Offset 41*4882a593Smuzhiyun - Size 42*4882a593Smuzhiyun - Name 43*4882a593Smuzhiyun - Description 44*4882a593Smuzhiyun * - 0x0 45*4882a593Smuzhiyun - \_\_le32 46*4882a593Smuzhiyun - inode 47*4882a593Smuzhiyun - Number of the inode that this directory entry points to. 48*4882a593Smuzhiyun * - 0x4 49*4882a593Smuzhiyun - \_\_le16 50*4882a593Smuzhiyun - rec\_len 51*4882a593Smuzhiyun - Length of this directory entry. Must be a multiple of 4. 52*4882a593Smuzhiyun * - 0x6 53*4882a593Smuzhiyun - \_\_le16 54*4882a593Smuzhiyun - name\_len 55*4882a593Smuzhiyun - Length of the file name. 56*4882a593Smuzhiyun * - 0x8 57*4882a593Smuzhiyun - char 58*4882a593Smuzhiyun - name[EXT4\_NAME\_LEN] 59*4882a593Smuzhiyun - File name. 60*4882a593Smuzhiyun 61*4882a593SmuzhiyunSince file names cannot be longer than 255 bytes, the new directory 62*4882a593Smuzhiyunentry format shortens the name\_len field and uses the space for a file 63*4882a593Smuzhiyuntype flag, probably to avoid having to load every inode during directory 64*4882a593Smuzhiyuntree traversal. This format is ``ext4_dir_entry_2``, which is at most 65*4882a593Smuzhiyun263 bytes long, though on disk you'll need to reference 66*4882a593Smuzhiyun``dirent.rec_len`` to know for sure. 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun.. list-table:: 69*4882a593Smuzhiyun :widths: 8 8 24 40 70*4882a593Smuzhiyun :header-rows: 1 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun * - Offset 73*4882a593Smuzhiyun - Size 74*4882a593Smuzhiyun - Name 75*4882a593Smuzhiyun - Description 76*4882a593Smuzhiyun * - 0x0 77*4882a593Smuzhiyun - \_\_le32 78*4882a593Smuzhiyun - inode 79*4882a593Smuzhiyun - Number of the inode that this directory entry points to. 80*4882a593Smuzhiyun * - 0x4 81*4882a593Smuzhiyun - \_\_le16 82*4882a593Smuzhiyun - rec\_len 83*4882a593Smuzhiyun - Length of this directory entry. 84*4882a593Smuzhiyun * - 0x6 85*4882a593Smuzhiyun - \_\_u8 86*4882a593Smuzhiyun - name\_len 87*4882a593Smuzhiyun - Length of the file name. 88*4882a593Smuzhiyun * - 0x7 89*4882a593Smuzhiyun - \_\_u8 90*4882a593Smuzhiyun - file\_type 91*4882a593Smuzhiyun - File type code, see ftype_ table below. 92*4882a593Smuzhiyun * - 0x8 93*4882a593Smuzhiyun - char 94*4882a593Smuzhiyun - name[EXT4\_NAME\_LEN] 95*4882a593Smuzhiyun - File name. 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun.. _ftype: 98*4882a593Smuzhiyun 99*4882a593SmuzhiyunThe directory file type is one of the following values: 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun.. list-table:: 102*4882a593Smuzhiyun :widths: 16 64 103*4882a593Smuzhiyun :header-rows: 1 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun * - Value 106*4882a593Smuzhiyun - Description 107*4882a593Smuzhiyun * - 0x0 108*4882a593Smuzhiyun - Unknown. 109*4882a593Smuzhiyun * - 0x1 110*4882a593Smuzhiyun - Regular file. 111*4882a593Smuzhiyun * - 0x2 112*4882a593Smuzhiyun - Directory. 113*4882a593Smuzhiyun * - 0x3 114*4882a593Smuzhiyun - Character device file. 115*4882a593Smuzhiyun * - 0x4 116*4882a593Smuzhiyun - Block device file. 117*4882a593Smuzhiyun * - 0x5 118*4882a593Smuzhiyun - FIFO. 119*4882a593Smuzhiyun * - 0x6 120*4882a593Smuzhiyun - Socket. 121*4882a593Smuzhiyun * - 0x7 122*4882a593Smuzhiyun - Symbolic link. 123*4882a593Smuzhiyun 124*4882a593SmuzhiyunTo support directories that are both encrypted and casefolded directories, we 125*4882a593Smuzhiyunmust also include hash information in the directory entry. We append 126*4882a593Smuzhiyun``ext4_extended_dir_entry_2`` to ``ext4_dir_entry_2`` except for the entries 127*4882a593Smuzhiyunfor dot and dotdot, which are kept the same. The structure follows immediately 128*4882a593Smuzhiyunafter ``name`` and is included in the size listed by ``rec_len`` If a directory 129*4882a593Smuzhiyunentry uses this extension, it may be up to 271 bytes. 130*4882a593Smuzhiyun 131*4882a593Smuzhiyun.. list-table:: 132*4882a593Smuzhiyun :widths: 8 8 24 40 133*4882a593Smuzhiyun :header-rows: 1 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun * - Offset 136*4882a593Smuzhiyun - Size 137*4882a593Smuzhiyun - Name 138*4882a593Smuzhiyun - Description 139*4882a593Smuzhiyun * - 0x0 140*4882a593Smuzhiyun - \_\_le32 141*4882a593Smuzhiyun - hash 142*4882a593Smuzhiyun - The hash of the directory name 143*4882a593Smuzhiyun * - 0x4 144*4882a593Smuzhiyun - \_\_le32 145*4882a593Smuzhiyun - minor\_hash 146*4882a593Smuzhiyun - The minor hash of the directory name 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun 149*4882a593SmuzhiyunIn order to add checksums to these classic directory blocks, a phony 150*4882a593Smuzhiyun``struct ext4_dir_entry`` is placed at the end of each leaf block to 151*4882a593Smuzhiyunhold the checksum. The directory entry is 12 bytes long. The inode 152*4882a593Smuzhiyunnumber and name\_len fields are set to zero to fool old software into 153*4882a593Smuzhiyunignoring an apparently empty directory entry, and the checksum is stored 154*4882a593Smuzhiyunin the place where the name normally goes. The structure is 155*4882a593Smuzhiyun``struct ext4_dir_entry_tail``: 156*4882a593Smuzhiyun 157*4882a593Smuzhiyun.. list-table:: 158*4882a593Smuzhiyun :widths: 8 8 24 40 159*4882a593Smuzhiyun :header-rows: 1 160*4882a593Smuzhiyun 161*4882a593Smuzhiyun * - Offset 162*4882a593Smuzhiyun - Size 163*4882a593Smuzhiyun - Name 164*4882a593Smuzhiyun - Description 165*4882a593Smuzhiyun * - 0x0 166*4882a593Smuzhiyun - \_\_le32 167*4882a593Smuzhiyun - det\_reserved\_zero1 168*4882a593Smuzhiyun - Inode number, which must be zero. 169*4882a593Smuzhiyun * - 0x4 170*4882a593Smuzhiyun - \_\_le16 171*4882a593Smuzhiyun - det\_rec\_len 172*4882a593Smuzhiyun - Length of this directory entry, which must be 12. 173*4882a593Smuzhiyun * - 0x6 174*4882a593Smuzhiyun - \_\_u8 175*4882a593Smuzhiyun - det\_reserved\_zero2 176*4882a593Smuzhiyun - Length of the file name, which must be zero. 177*4882a593Smuzhiyun * - 0x7 178*4882a593Smuzhiyun - \_\_u8 179*4882a593Smuzhiyun - det\_reserved\_ft 180*4882a593Smuzhiyun - File type, which must be 0xDE. 181*4882a593Smuzhiyun * - 0x8 182*4882a593Smuzhiyun - \_\_le32 183*4882a593Smuzhiyun - det\_checksum 184*4882a593Smuzhiyun - Directory leaf block checksum. 185*4882a593Smuzhiyun 186*4882a593SmuzhiyunThe leaf directory block checksum is calculated against the FS UUID, the 187*4882a593Smuzhiyundirectory's inode number, the directory's inode generation number, and 188*4882a593Smuzhiyunthe entire directory entry block up to (but not including) the fake 189*4882a593Smuzhiyundirectory entry. 190*4882a593Smuzhiyun 191*4882a593SmuzhiyunHash Tree Directories 192*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~ 193*4882a593Smuzhiyun 194*4882a593SmuzhiyunA linear array of directory entries isn't great for performance, so a 195*4882a593Smuzhiyunnew feature was added to ext3 to provide a faster (but peculiar) 196*4882a593Smuzhiyunbalanced tree keyed off a hash of the directory entry name. If the 197*4882a593SmuzhiyunEXT4\_INDEX\_FL (0x1000) flag is set in the inode, this directory uses a 198*4882a593Smuzhiyunhashed btree (htree) to organize and find directory entries. For 199*4882a593Smuzhiyunbackwards read-only compatibility with ext2, this tree is actually 200*4882a593Smuzhiyunhidden inside the directory file, masquerading as “empty” directory data 201*4882a593Smuzhiyunblocks! It was stated previously that the end of the linear directory 202*4882a593Smuzhiyunentry table was signified with an entry pointing to inode 0; this is 203*4882a593Smuzhiyun(ab)used to fool the old linear-scan algorithm into thinking that the 204*4882a593Smuzhiyunrest of the directory block is empty so that it moves on. 205*4882a593Smuzhiyun 206*4882a593SmuzhiyunThe root of the tree always lives in the first data block of the 207*4882a593Smuzhiyundirectory. By ext2 custom, the '.' and '..' entries must appear at the 208*4882a593Smuzhiyunbeginning of this first block, so they are put here as two 209*4882a593Smuzhiyun``struct ext4_dir_entry_2``\ s and not stored in the tree. The rest of 210*4882a593Smuzhiyunthe root node contains metadata about the tree and finally a hash->block 211*4882a593Smuzhiyunmap to find nodes that are lower in the htree. If 212*4882a593Smuzhiyun``dx_root.info.indirect_levels`` is non-zero then the htree has two 213*4882a593Smuzhiyunlevels; the data block pointed to by the root node's map is an interior 214*4882a593Smuzhiyunnode, which is indexed by a minor hash. Interior nodes in this tree 215*4882a593Smuzhiyuncontains a zeroed out ``struct ext4_dir_entry_2`` followed by a 216*4882a593Smuzhiyunminor\_hash->block map to find leafe nodes. Leaf nodes contain a linear 217*4882a593Smuzhiyunarray of all ``struct ext4_dir_entry_2``; all of these entries 218*4882a593Smuzhiyun(presumably) hash to the same value. If there is an overflow, the 219*4882a593Smuzhiyunentries simply overflow into the next leaf node, and the 220*4882a593Smuzhiyunleast-significant bit of the hash (in the interior node map) that gets 221*4882a593Smuzhiyunus to this next leaf node is set. 222*4882a593Smuzhiyun 223*4882a593SmuzhiyunTo traverse the directory as a htree, the code calculates the hash of 224*4882a593Smuzhiyunthe desired file name and uses it to find the corresponding block 225*4882a593Smuzhiyunnumber. If the tree is flat, the block is a linear array of directory 226*4882a593Smuzhiyunentries that can be searched; otherwise, the minor hash of the file name 227*4882a593Smuzhiyunis computed and used against this second block to find the corresponding 228*4882a593Smuzhiyunthird block number. That third block number will be a linear array of 229*4882a593Smuzhiyundirectory entries. 230*4882a593Smuzhiyun 231*4882a593SmuzhiyunTo traverse the directory as a linear array (such as the old code does), 232*4882a593Smuzhiyunthe code simply reads every data block in the directory. The blocks used 233*4882a593Smuzhiyunfor the htree will appear to have no entries (aside from '.' and '..') 234*4882a593Smuzhiyunand so only the leaf nodes will appear to have any interesting content. 235*4882a593Smuzhiyun 236*4882a593SmuzhiyunThe root of the htree is in ``struct dx_root``, which is the full length 237*4882a593Smuzhiyunof a data block: 238*4882a593Smuzhiyun 239*4882a593Smuzhiyun.. list-table:: 240*4882a593Smuzhiyun :widths: 8 8 24 40 241*4882a593Smuzhiyun :header-rows: 1 242*4882a593Smuzhiyun 243*4882a593Smuzhiyun * - Offset 244*4882a593Smuzhiyun - Type 245*4882a593Smuzhiyun - Name 246*4882a593Smuzhiyun - Description 247*4882a593Smuzhiyun * - 0x0 248*4882a593Smuzhiyun - \_\_le32 249*4882a593Smuzhiyun - dot.inode 250*4882a593Smuzhiyun - inode number of this directory. 251*4882a593Smuzhiyun * - 0x4 252*4882a593Smuzhiyun - \_\_le16 253*4882a593Smuzhiyun - dot.rec\_len 254*4882a593Smuzhiyun - Length of this record, 12. 255*4882a593Smuzhiyun * - 0x6 256*4882a593Smuzhiyun - u8 257*4882a593Smuzhiyun - dot.name\_len 258*4882a593Smuzhiyun - Length of the name, 1. 259*4882a593Smuzhiyun * - 0x7 260*4882a593Smuzhiyun - u8 261*4882a593Smuzhiyun - dot.file\_type 262*4882a593Smuzhiyun - File type of this entry, 0x2 (directory) (if the feature flag is set). 263*4882a593Smuzhiyun * - 0x8 264*4882a593Smuzhiyun - char 265*4882a593Smuzhiyun - dot.name[4] 266*4882a593Smuzhiyun - “.\\0\\0\\0” 267*4882a593Smuzhiyun * - 0xC 268*4882a593Smuzhiyun - \_\_le32 269*4882a593Smuzhiyun - dotdot.inode 270*4882a593Smuzhiyun - inode number of parent directory. 271*4882a593Smuzhiyun * - 0x10 272*4882a593Smuzhiyun - \_\_le16 273*4882a593Smuzhiyun - dotdot.rec\_len 274*4882a593Smuzhiyun - block\_size - 12. The record length is long enough to cover all htree 275*4882a593Smuzhiyun data. 276*4882a593Smuzhiyun * - 0x12 277*4882a593Smuzhiyun - u8 278*4882a593Smuzhiyun - dotdot.name\_len 279*4882a593Smuzhiyun - Length of the name, 2. 280*4882a593Smuzhiyun * - 0x13 281*4882a593Smuzhiyun - u8 282*4882a593Smuzhiyun - dotdot.file\_type 283*4882a593Smuzhiyun - File type of this entry, 0x2 (directory) (if the feature flag is set). 284*4882a593Smuzhiyun * - 0x14 285*4882a593Smuzhiyun - char 286*4882a593Smuzhiyun - dotdot\_name[4] 287*4882a593Smuzhiyun - “..\\0\\0” 288*4882a593Smuzhiyun * - 0x18 289*4882a593Smuzhiyun - \_\_le32 290*4882a593Smuzhiyun - struct dx\_root\_info.reserved\_zero 291*4882a593Smuzhiyun - Zero. 292*4882a593Smuzhiyun * - 0x1C 293*4882a593Smuzhiyun - u8 294*4882a593Smuzhiyun - struct dx\_root\_info.hash\_version 295*4882a593Smuzhiyun - Hash type, see dirhash_ table below. 296*4882a593Smuzhiyun * - 0x1D 297*4882a593Smuzhiyun - u8 298*4882a593Smuzhiyun - struct dx\_root\_info.info\_length 299*4882a593Smuzhiyun - Length of the tree information, 0x8. 300*4882a593Smuzhiyun * - 0x1E 301*4882a593Smuzhiyun - u8 302*4882a593Smuzhiyun - struct dx\_root\_info.indirect\_levels 303*4882a593Smuzhiyun - Depth of the htree. Cannot be larger than 3 if the INCOMPAT\_LARGEDIR 304*4882a593Smuzhiyun feature is set; cannot be larger than 2 otherwise. 305*4882a593Smuzhiyun * - 0x1F 306*4882a593Smuzhiyun - u8 307*4882a593Smuzhiyun - struct dx\_root\_info.unused\_flags 308*4882a593Smuzhiyun - 309*4882a593Smuzhiyun * - 0x20 310*4882a593Smuzhiyun - \_\_le16 311*4882a593Smuzhiyun - limit 312*4882a593Smuzhiyun - Maximum number of dx\_entries that can follow this header, plus 1 for 313*4882a593Smuzhiyun the header itself. 314*4882a593Smuzhiyun * - 0x22 315*4882a593Smuzhiyun - \_\_le16 316*4882a593Smuzhiyun - count 317*4882a593Smuzhiyun - Actual number of dx\_entries that follow this header, plus 1 for the 318*4882a593Smuzhiyun header itself. 319*4882a593Smuzhiyun * - 0x24 320*4882a593Smuzhiyun - \_\_le32 321*4882a593Smuzhiyun - block 322*4882a593Smuzhiyun - The block number (within the directory file) that goes with hash=0. 323*4882a593Smuzhiyun * - 0x28 324*4882a593Smuzhiyun - struct dx\_entry 325*4882a593Smuzhiyun - entries[0] 326*4882a593Smuzhiyun - As many 8-byte ``struct dx_entry`` as fits in the rest of the data block. 327*4882a593Smuzhiyun 328*4882a593Smuzhiyun.. _dirhash: 329*4882a593Smuzhiyun 330*4882a593SmuzhiyunThe directory hash is one of the following values: 331*4882a593Smuzhiyun 332*4882a593Smuzhiyun.. list-table:: 333*4882a593Smuzhiyun :widths: 16 64 334*4882a593Smuzhiyun :header-rows: 1 335*4882a593Smuzhiyun 336*4882a593Smuzhiyun * - Value 337*4882a593Smuzhiyun - Description 338*4882a593Smuzhiyun * - 0x0 339*4882a593Smuzhiyun - Legacy. 340*4882a593Smuzhiyun * - 0x1 341*4882a593Smuzhiyun - Half MD4. 342*4882a593Smuzhiyun * - 0x2 343*4882a593Smuzhiyun - Tea. 344*4882a593Smuzhiyun * - 0x3 345*4882a593Smuzhiyun - Legacy, unsigned. 346*4882a593Smuzhiyun * - 0x4 347*4882a593Smuzhiyun - Half MD4, unsigned. 348*4882a593Smuzhiyun * - 0x5 349*4882a593Smuzhiyun - Tea, unsigned. 350*4882a593Smuzhiyun * - 0x6 351*4882a593Smuzhiyun - Siphash. 352*4882a593Smuzhiyun 353*4882a593SmuzhiyunInterior nodes of an htree are recorded as ``struct dx_node``, which is 354*4882a593Smuzhiyunalso the full length of a data block: 355*4882a593Smuzhiyun 356*4882a593Smuzhiyun.. list-table:: 357*4882a593Smuzhiyun :widths: 8 8 24 40 358*4882a593Smuzhiyun :header-rows: 1 359*4882a593Smuzhiyun 360*4882a593Smuzhiyun * - Offset 361*4882a593Smuzhiyun - Type 362*4882a593Smuzhiyun - Name 363*4882a593Smuzhiyun - Description 364*4882a593Smuzhiyun * - 0x0 365*4882a593Smuzhiyun - \_\_le32 366*4882a593Smuzhiyun - fake.inode 367*4882a593Smuzhiyun - Zero, to make it look like this entry is not in use. 368*4882a593Smuzhiyun * - 0x4 369*4882a593Smuzhiyun - \_\_le16 370*4882a593Smuzhiyun - fake.rec\_len 371*4882a593Smuzhiyun - The size of the block, in order to hide all of the dx\_node data. 372*4882a593Smuzhiyun * - 0x6 373*4882a593Smuzhiyun - u8 374*4882a593Smuzhiyun - name\_len 375*4882a593Smuzhiyun - Zero. There is no name for this “unused” directory entry. 376*4882a593Smuzhiyun * - 0x7 377*4882a593Smuzhiyun - u8 378*4882a593Smuzhiyun - file\_type 379*4882a593Smuzhiyun - Zero. There is no file type for this “unused” directory entry. 380*4882a593Smuzhiyun * - 0x8 381*4882a593Smuzhiyun - \_\_le16 382*4882a593Smuzhiyun - limit 383*4882a593Smuzhiyun - Maximum number of dx\_entries that can follow this header, plus 1 for 384*4882a593Smuzhiyun the header itself. 385*4882a593Smuzhiyun * - 0xA 386*4882a593Smuzhiyun - \_\_le16 387*4882a593Smuzhiyun - count 388*4882a593Smuzhiyun - Actual number of dx\_entries that follow this header, plus 1 for the 389*4882a593Smuzhiyun header itself. 390*4882a593Smuzhiyun * - 0xE 391*4882a593Smuzhiyun - \_\_le32 392*4882a593Smuzhiyun - block 393*4882a593Smuzhiyun - The block number (within the directory file) that goes with the lowest 394*4882a593Smuzhiyun hash value of this block. This value is stored in the parent block. 395*4882a593Smuzhiyun * - 0x12 396*4882a593Smuzhiyun - struct dx\_entry 397*4882a593Smuzhiyun - entries[0] 398*4882a593Smuzhiyun - As many 8-byte ``struct dx_entry`` as fits in the rest of the data block. 399*4882a593Smuzhiyun 400*4882a593SmuzhiyunThe hash maps that exist in both ``struct dx_root`` and 401*4882a593Smuzhiyun``struct dx_node`` are recorded as ``struct dx_entry``, which is 8 bytes 402*4882a593Smuzhiyunlong: 403*4882a593Smuzhiyun 404*4882a593Smuzhiyun.. list-table:: 405*4882a593Smuzhiyun :widths: 8 8 24 40 406*4882a593Smuzhiyun :header-rows: 1 407*4882a593Smuzhiyun 408*4882a593Smuzhiyun * - Offset 409*4882a593Smuzhiyun - Type 410*4882a593Smuzhiyun - Name 411*4882a593Smuzhiyun - Description 412*4882a593Smuzhiyun * - 0x0 413*4882a593Smuzhiyun - \_\_le32 414*4882a593Smuzhiyun - hash 415*4882a593Smuzhiyun - Hash code. 416*4882a593Smuzhiyun * - 0x4 417*4882a593Smuzhiyun - \_\_le32 418*4882a593Smuzhiyun - block 419*4882a593Smuzhiyun - Block number (within the directory file, not filesystem blocks) of the 420*4882a593Smuzhiyun next node in the htree. 421*4882a593Smuzhiyun 422*4882a593Smuzhiyun(If you think this is all quite clever and peculiar, so does the 423*4882a593Smuzhiyunauthor.) 424*4882a593Smuzhiyun 425*4882a593SmuzhiyunIf metadata checksums are enabled, the last 8 bytes of the directory 426*4882a593Smuzhiyunblock (precisely the length of one dx\_entry) are used to store a 427*4882a593Smuzhiyun``struct dx_tail``, which contains the checksum. The ``limit`` and 428*4882a593Smuzhiyun``count`` entries in the dx\_root/dx\_node structures are adjusted as 429*4882a593Smuzhiyunnecessary to fit the dx\_tail into the block. If there is no space for 430*4882a593Smuzhiyunthe dx\_tail, the user is notified to run e2fsck -D to rebuild the 431*4882a593Smuzhiyundirectory index (which will ensure that there's space for the checksum. 432*4882a593SmuzhiyunThe dx\_tail structure is 8 bytes long and looks like this: 433*4882a593Smuzhiyun 434*4882a593Smuzhiyun.. list-table:: 435*4882a593Smuzhiyun :widths: 8 8 24 40 436*4882a593Smuzhiyun :header-rows: 1 437*4882a593Smuzhiyun 438*4882a593Smuzhiyun * - Offset 439*4882a593Smuzhiyun - Type 440*4882a593Smuzhiyun - Name 441*4882a593Smuzhiyun - Description 442*4882a593Smuzhiyun * - 0x0 443*4882a593Smuzhiyun - u32 444*4882a593Smuzhiyun - dt\_reserved 445*4882a593Smuzhiyun - Zero. 446*4882a593Smuzhiyun * - 0x4 447*4882a593Smuzhiyun - \_\_le32 448*4882a593Smuzhiyun - dt\_checksum 449*4882a593Smuzhiyun - Checksum of the htree directory block. 450*4882a593Smuzhiyun 451*4882a593SmuzhiyunThe checksum is calculated against the FS UUID, the htree index header 452*4882a593Smuzhiyun(dx\_root or dx\_node), all of the htree indices (dx\_entry) that are in 453*4882a593Smuzhiyunuse, and the tail block (dx\_tail). 454