| Commit | Line | Data |
|---|---|---|
| 703720e4 MD |
1 | /* |
| 2 | * Copyright (c) 2011-2012 The DragonFly Project. All rights reserved. | |
| 3 | * | |
| 4 | * This code is derived from software contributed to The DragonFly Project | |
| 5 | * by Matthew Dillon <dillon@dragonflybsd.org> | |
| 6 | * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org> | |
| 7 | * | |
| 8 | * Redistribution and use in source and binary forms, with or without | |
| 9 | * modification, are permitted provided that the following conditions | |
| 10 | * are met: | |
| 11 | * | |
| 12 | * 1. Redistributions of source code must retain the above copyright | |
| 13 | * notice, this list of conditions and the following disclaimer. | |
| 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 15 | * notice, this list of conditions and the following disclaimer in | |
| 16 | * the documentation and/or other materials provided with the | |
| 17 | * distribution. | |
| 18 | * 3. Neither the name of The DragonFly Project nor the names of its | |
| 19 | * contributors may be used to endorse or promote products derived | |
| 20 | * from this software without specific, prior written permission. | |
| 21 | * | |
| 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 23 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
| 25 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
| 26 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| 27 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
| 28 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
| 30 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| 31 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
| 32 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 33 | * SUCH DAMAGE. | |
| 34 | */ | |
| 35 | #ifndef VFS_HAMMER2_DISK_H_ | |
| 36 | #define VFS_HAMMER2_DISK_H_ | |
| 37 | ||
| 2910a90c MD |
38 | #ifndef _SYS_UUID_H_ |
| 39 | #include <sys/uuid.h> | |
| 40 | #endif | |
| 41 | ||
| 703720e4 MD |
42 | /* |
| 43 | * The structures below represent the on-disk media structures for the HAMMER2 | |
| 44 | * filesystem. Note that all fields for on-disk structures are naturally | |
| 45 | * aligned. The host endian format is typically used - compatibility is | |
| 46 | * possible if the implementation detects reversed endian and adjusts accesses | |
| 47 | * accordingly. | |
| 48 | * | |
| 49 | * HAMMER2 primarily revolves around the directory topology: inodes, | |
| 50 | * directory entries, and block tables. Block device buffer cache buffers | |
| 51 | * are always 64KB. Logical file buffers are typically 16KB. All data | |
| 52 | * references utilize 64-bit byte offsets. | |
| 53 | * | |
| 54 | * Free block management is handled independently using blocks reserved by | |
| 55 | * the media topology. | |
| 56 | */ | |
| 57 | ||
| 58 | /* | |
| 59 | * The data at the end of a file or directory may be a fragment in order | |
| 60 | * to optimize storage efficiency. The minimum fragment size is 64 bytes. | |
| 61 | * Since allocations are in powers of 2 fragments must also be sized in | |
| 62 | * powers of 2 (64, 128, 256, ... 65536). | |
| 63 | * | |
| 64 | * For the moment the maximum allocation size is HAMMER2_PBUFSIZE (64K), | |
| 65 | * which is 2^16. Larger extents may be supported in the future. | |
| 66 | * | |
| 67 | * A full indirect block uses supports 1024 x 64-byte blockrefs. | |
| 68 | * | |
| 69 | * A maximally sized file (2^64-1 bytes) requires 5 indirect block levels. | |
| 70 | * The hammer2_blockset in the volume header or file inode has another 8 | |
| 71 | * entries, giving us 66+3 = 69 bits of address space. However, some bits | |
| 72 | * are taken up by (potentially) requests for redundant copies. HAMMER2 | |
| 73 | * currently supports up to 8 copies, which brings the address space down | |
| 74 | * to 66 bits and gives us 2 bits of leeway. | |
| 75 | */ | |
| 76 | #define HAMMER2_MIN_ALLOC 64 /* minimum allocation size */ | |
| 77 | #define HAMMER2_MIN_RADIX 6 /* minimum allocation size 2^N */ | |
| 78 | #define HAMMER2_MAX_RADIX 16 /* maximum allocation size 2^N */ | |
| 995e78dc | 79 | #define HAMMER2_KEY_RADIX 64 /* number of bits in key */ |
| 703720e4 MD |
80 | |
| 81 | /* | |
| 01eabad4 MD |
82 | * MINALLOCSIZE - The minimum allocation size. This can be smaller |
| 83 | * or larger than the minimum physical IO size. | |
| 84 | * | |
| 85 | * NOTE: Should not be larger than 1K since inodes | |
| 86 | * are 1K. | |
| 87 | * | |
| 88 | * MINIOSIZE - The minimum IO size. This must be less than | |
| 89 | * or equal to HAMMER2_PBUFSIZE. | |
| 90 | * | |
| 91 | * XXX currently must be set to MINALLOCSIZE until/if | |
| 92 | * we deal with recursive buffer cache locks. | |
| 93 | * | |
| 94 | * HAMMER2_PBUFSIZE - Topological block size used by files for all | |
| 95 | * blocks except the block straddling EOF. | |
| 96 | * | |
| 97 | * HAMMER2_SEGSIZE - Allocation map segment size, typically 2MB | |
| 703720e4 | 98 | */ |
| 01eabad4 MD |
99 | |
| 100 | #define HAMMER2_SEGSIZE (65536 * 8) | |
| 101 | ||
| 703720e4 | 102 | #define HAMMER2_PBUFRADIX 16 /* physical buf (1<<16) bytes */ |
| 866d5273 | 103 | #define HAMMER2_PBUFSIZE 65536 |
| 73e441b9 | 104 | #define HAMMER2_LBUFRADIX 14 /* logical buf (1<<14) bytes */ |
| 866d5273 | 105 | #define HAMMER2_LBUFSIZE 16384 |
| 01eabad4 MD |
106 | |
| 107 | #if 0 | |
| 108 | #define HAMMER2_MINIORADIX 16 /* minimum phsical IO size */ | |
| 109 | #define HAMMER2_MINIOSIZE 65536 | |
| 110 | #endif | |
| 111 | #define HAMMER2_MINIORADIX HAMMER2_MINALLOCRADIX | |
| 112 | #define HAMMER2_MINIOSIZE HAMMER2_MINALLOCSIZE | |
| 113 | ||
| 114 | #define HAMMER2_MINALLOCRADIX 10 /* minimum block allocation size */ | |
| 115 | #define HAMMER2_MINALLOCSIZE 1024 | |
| 6ba3b984 MD |
116 | #define HAMMER2_IND_BYTES_MIN 4096 /* first indirect layer only */ |
| 117 | #define HAMMER2_IND_BYTES_MAX HAMMER2_PBUFSIZE | |
| 118 | #define HAMMER2_IND_COUNT_MIN (HAMMER2_IND_BYTES_MIN / \ | |
| 119 | sizeof(hammer2_blockref_t)) | |
| 120 | #define HAMMER2_IND_COUNT_MAX (HAMMER2_IND_BYTES_MAX / \ | |
| 121 | sizeof(hammer2_blockref_t)) | |
| 703720e4 MD |
122 | |
| 123 | /* | |
| 124 | * HAMMER2 processes blockrefs in sets of 8. The set is fully associative, | |
| 125 | * is not sorted, and may contain holes. | |
| 126 | * | |
| 127 | * A full indirect block supports 1024 blockrefs. | |
| 128 | * | |
| 129 | * An inode embeds one set of blockrefs but may also use the data area for | |
| 130 | * up to 512 bytes of direct data. | |
| 131 | */ | |
| 132 | #define HAMMER2_SET_COUNT 8 /* direct entries & associativity */ | |
| 133 | #define HAMMER2_SET_RADIX 3 | |
| 703720e4 MD |
134 | #define HAMMER2_EMBEDDED_BYTES 512 |
| 135 | #define HAMMER2_EMBEDDED_RADIX 9 | |
| 136 | ||
| 137 | #define HAMMER2_PBUFMASK (HAMMER2_PBUFSIZE - 1) | |
| 138 | #define HAMMER2_LBUFMASK (HAMMER2_LBUFSIZE - 1) | |
| 01eabad4 | 139 | #define HAMMER2_SEGMASK (HAMMER2_SEGSIZE - 1) |
| 703720e4 | 140 | |
| 01eabad4 | 141 | #define HAMMER2_LBUFMASK64 ((hammer2_off_t)HAMMER2_LBUFMASK) |
| 703720e4 MD |
142 | #define HAMMER2_PBUFSIZE64 ((hammer2_off_t)HAMMER2_PBUFSIZE) |
| 143 | #define HAMMER2_PBUFMASK64 ((hammer2_off_t)HAMMER2_PBUFMASK) | |
| 01eabad4 MD |
144 | #define HAMMER2_SEGSIZE64 ((hammer2_off_t)HAMMER2_SEGSIZE) |
| 145 | #define HAMMER2_SEGMASK64 ((hammer2_off_t)HAMMER2_SEGMASK) | |
| 703720e4 MD |
146 | |
| 147 | #define HAMMER2_UUID_STRING "5cbb9ad1-862d-11dc-a94d-01301bb8a9f5" | |
| 148 | ||
| 149 | /* | |
| 150 | * A HAMMER2 filesystem is always sized in multiples of 8MB. | |
| 151 | * | |
| 4894e7c9 MD |
152 | * A 4MB segment is reserved at the beginning of each 2GB zone. This segment |
| 153 | * contains the volume header, the free block table, and possibly other | |
| 154 | * information in the future. 4MB = 64 x 64K blocks. | |
| 703720e4 MD |
155 | */ |
| 156 | #define HAMMER2_VOLUME_ALIGN (8 * 1024 * 1024) | |
| 157 | #define HAMMER2_VOLUME_ALIGN64 ((hammer2_off_t)HAMMER2_VOLUME_ALIGN) | |
| 158 | #define HAMMER2_VOLUME_ALIGNMASK (HAMMER2_VOLUME_ALIGN - 1) | |
| 159 | #define HAMMER2_VOLUME_ALIGNMASK64 ((hammer2_off_t)HAMMER2_VOLUME_ALIGNMASK) | |
| 160 | ||
| 161 | #define HAMMER2_NEWFS_ALIGN (HAMMER2_VOLUME_ALIGN) | |
| 162 | #define HAMMER2_NEWFS_ALIGN64 ((hammer2_off_t)HAMMER2_VOLUME_ALIGN) | |
| 163 | #define HAMMER2_NEWFS_ALIGNMASK (HAMMER2_VOLUME_ALIGN - 1) | |
| 164 | #define HAMMER2_NEWFS_ALIGNMASK64 ((hammer2_off_t)HAMMER2_NEWFS_ALIGNMASK) | |
| 165 | ||
| 62efe6ec MD |
166 | #define HAMMER2_ZONE_BYTES64 (2LLU * 1024 * 1024 * 1024) |
| 167 | #define HAMMER2_ZONE_MASK64 (HAMMER2_ZONE_BYTES64 - 1) | |
| 168 | #define HAMMER2_ZONE_SEG (4 * 1024 * 1024) | |
| 169 | #define HAMMER2_ZONE_SEG64 ((hammer2_off_t)HAMMER2_ZONE_SEG) | |
| 170 | #define HAMMER2_ZONE_BLOCKS_SEG (HAMMER2_ZONE_SEG / HAMMER2_PBUFSIZE) | |
| 703720e4 MD |
171 | |
| 172 | /* | |
| 173 | * Two linear areas can be reserved after the initial 2MB segment in the base | |
| 174 | * zone (the one starting at offset 0). These areas are NOT managed by the | |
| 175 | * block allocator and do not fall under HAMMER2 crc checking rules based | |
| 176 | * at the volume header (but can be self-CRCd internally, depending). | |
| 177 | */ | |
| 178 | #define HAMMER2_BOOT_MIN_BYTES HAMMER2_VOLUME_ALIGN | |
| 179 | #define HAMMER2_BOOT_NOM_BYTES (64*1024*1024) | |
| 180 | #define HAMMER2_BOOT_MAX_BYTES (256*1024*1024) | |
| 181 | ||
| 182 | #define HAMMER2_REDO_MIN_BYTES HAMMER2_VOLUME_ALIGN | |
| 183 | #define HAMMER2_REDO_NOM_BYTES (256*1024*1024) | |
| 184 | #define HAMMER2_REDO_MAX_BYTES (1024*1024*1024) | |
| 185 | ||
| 186 | /* | |
| 187 | * Most HAMMER2 types are implemented as unsigned 64-bit integers. | |
| 188 | * Transaction ids are monotonic. | |
| 189 | * | |
| 190 | * We utilize 32-bit iSCSI CRCs. | |
| 191 | */ | |
| 192 | typedef uint64_t hammer2_tid_t; | |
| 193 | typedef uint64_t hammer2_off_t; | |
| 194 | typedef uint64_t hammer2_key_t; | |
| 195 | typedef uint32_t hammer2_crc32_t; | |
| 196 | ||
| 197 | /* | |
| 198 | * Miscellanious ranges (all are unsigned). | |
| 199 | */ | |
| 200 | #define HAMMER2_MIN_TID 1ULL | |
| 201 | #define HAMMER2_MAX_TID 0xFFFFFFFFFFFFFFFFULL | |
| 202 | #define HAMMER2_MIN_KEY 0ULL | |
| 203 | #define HAMMER2_MAX_KEY 0xFFFFFFFFFFFFFFFFULL | |
| 204 | #define HAMMER2_MIN_OFFSET 0ULL | |
| 205 | #define HAMMER2_MAX_OFFSET 0xFFFFFFFFFFFFFFFFULL | |
| 206 | ||
| 207 | /* | |
| 208 | * HAMMER2 data offset special cases and masking. | |
| 209 | * | |
| 210 | * All HAMMER2 data offsets have to be broken down into a 64K buffer base | |
| 211 | * offset (HAMMER2_OFF_MASK_HI) and a 64K buffer index (HAMMER2_OFF_MASK_LO). | |
| 212 | * | |
| 213 | * Indexes into physical buffers are always 64-byte aligned. The low 6 bits | |
| 214 | * of the data offset field specifies how large the data chunk being pointed | |
| 215 | * to as a power of 2. This value typically ranges from HAMMER2_MIN_RADIX | |
| 216 | * to HAMMER2_MAX_RADIX (6-16). Larger values may be supported in the future | |
| 217 | * to support file extents. | |
| 218 | */ | |
| 219 | #define HAMMER2_OFF_BAD ((hammer2_off_t)-1) | |
| 220 | #define HAMMER2_OFF_MASK 0xFFFFFFFFFFFFFFC0ULL | |
| 221 | #define HAMMER2_OFF_MASK_LO (HAMMER2_OFF_MASK & HAMMER2_PBUFMASK64) | |
| 222 | #define HAMMER2_OFF_MASK_HI (~HAMMER2_PBUFMASK64) | |
| 223 | #define HAMMER2_OFF_MASK_RADIX 0x000000000000003FULL | |
| 224 | #define HAMMER2_MAX_COPIES 6 | |
| 225 | ||
| 226 | /* | |
| 7cfa8da5 MD |
227 | * HAMMER2 directory support and pre-defined keys |
| 228 | */ | |
| 229 | #define HAMMER2_DIRHASH_VISIBLE 0x8000000000000000ULL | |
| e028fa74 MD |
230 | #define HAMMER2_DIRHASH_USERMSK 0x7FFFFFFFFFFFFFFFULL |
| 231 | #define HAMMER2_DIRHASH_LOMASK 0x0000000000007FFFULL | |
| 5c23d7f1 | 232 | #define HAMMER2_DIRHASH_HIMASK 0xFFFFFFFFFFFF0000ULL |
| e028fa74 | 233 | #define HAMMER2_DIRHASH_FORCED 0x0000000000008000ULL /* bit forced on */ |
| 7cfa8da5 MD |
234 | |
| 235 | #define HAMMER2_SROOT_KEY 0x0000000000000000ULL /* volume to sroot */ | |
| 236 | ||
| 237 | /* | |
| 703720e4 MD |
238 | * The media block reference structure. This forms the core of the HAMMER2 |
| 239 | * media topology recursion. This 64-byte data structure is embedded in the | |
| 240 | * volume header, in inodes (which are also directory entries), and in | |
| 241 | * indirect blocks. | |
| 242 | * | |
| 243 | * A blockref references a single media item, which typically can be a | |
| 244 | * directory entry (aka inode), indirect block, or data block. | |
| 245 | * | |
| 246 | * The primary feature a blockref represents is the ability to validate | |
| 247 | * the entire tree underneath it via its check code. Any modification to | |
| 248 | * anything propagates up the blockref tree all the way to the root, replacing | |
| 249 | * the related blocks. Propagations can shortcut to the volume root to | |
| 250 | * implement the 'fast syncing' feature but this only delays the eventual | |
| 251 | * propagation. | |
| 252 | * | |
| 253 | * The check code can be a simple 32-bit iscsi code, a 64-bit crc, | |
| 254 | * or as complex as a 192 bit cryptographic hash. 192 bits is the maximum | |
| 255 | * supported check code size, which is not sufficient for unverified dedup | |
| 256 | * UNLESS one doesn't mind once-in-a-blue-moon data corruption (such as when | |
| 257 | * farming web data). HAMMER2 has an unverified dedup feature for just this | |
| 258 | * purpose. | |
| 259 | */ | |
| 260 | struct hammer2_blockref { /* MUST BE EXACTLY 64 BYTES */ | |
| 261 | uint8_t type; /* type of underlying item */ | |
| 262 | uint8_t methods; /* check method & compression method */ | |
| 263 | uint8_t copyid; /* specify which copy this is */ | |
| 232a50f9 | 264 | uint8_t keybits; /* #of keybits masked off 0=leaf */ |
| 5a9a531c MD |
265 | uint8_t vradix; /* virtual data/meta-data size */ |
| 266 | uint8_t flags; /* blockref flags */ | |
| 703720e4 MD |
267 | uint8_t reserved06; |
| 268 | uint8_t reserved07; | |
| 269 | hammer2_key_t key; /* key specification */ | |
| 270 | hammer2_tid_t mirror_tid; /* propagate for mirror scan */ | |
| 271 | hammer2_tid_t modify_tid; /* modifications sans propagation */ | |
| 272 | hammer2_off_t data_off; /* low 6 bits is phys size (radix)*/ | |
| 273 | union { /* check info */ | |
| 274 | char buf[24]; | |
| 275 | struct { | |
| 276 | uint32_t value; | |
| 277 | uint32_t unused[5]; | |
| 278 | } iscsi32; | |
| 279 | struct { | |
| 280 | uint64_t value; | |
| 281 | uint64_t unused[2]; | |
| 282 | } crc64; | |
| 283 | struct { | |
| 284 | char data[24]; | |
| 285 | } sha192; | |
| 286 | } check; | |
| 287 | }; | |
| 288 | ||
| 289 | typedef struct hammer2_blockref hammer2_blockref_t; | |
| 290 | ||
| 4894e7c9 MD |
291 | #define HAMMER2_BREF_SYNC1 0x01 /* modification synchronized */ |
| 292 | #define HAMMER2_BREF_SYNC2 0x02 /* modification committed */ | |
| 293 | #define HAMMER2_BREF_DESYNCCHLD 0x04 /* desynchronize children */ | |
| 294 | #define HAMMER2_BREF_DELETED 0x80 /* indicates a deletion */ | |
| 5a9a531c | 295 | |
| 703720e4 | 296 | #define HAMMER2_BLOCKREF_BYTES 64 /* blockref struct in bytes */ |
| 4894e7c9 MD |
297 | |
| 298 | #define HAMMER2_BREF_TYPE_EMPTY 0 | |
| 299 | #define HAMMER2_BREF_TYPE_INODE 1 | |
| 232a50f9 | 300 | #define HAMMER2_BREF_TYPE_INDIRECT 2 |
| 4894e7c9 | 301 | #define HAMMER2_BREF_TYPE_DATA 3 |
| 232a50f9 | 302 | #define HAMMER2_BREF_TYPE_VOLUME 255 /* pseudo-type */ |
| 4894e7c9 | 303 | |
| 703720e4 MD |
304 | #define HAMMER2_ENC_COMPMETHOD(n) (n) |
| 305 | #define HAMMER2_ENC_CHECKMETHOD(n) ((n) << 4) | |
| 306 | #define HAMMER2_DEC_COMPMETHOD(n) ((n) & 15) | |
| 307 | #define HAMMER2_DEC_CHECKMETHOD(n) (((n) >> 4) & 15) | |
| 308 | ||
| 309 | /* | |
| 310 | * HAMMER2 block references are collected into sets of 8 blockrefs. These | |
| 311 | * sets are fully associative, meaning the elements making up a set are | |
| 312 | * not sorted in any way and may contain duplicate entries, holes, or | |
| 313 | * entries which shortcut multiple levels of indirection. Sets are used | |
| 314 | * in various ways: | |
| 315 | * | |
| 316 | * (1) When redundancy is desired a set may contain several duplicate | |
| 317 | * entries pointing to different copies of the same data. Up to 8 copies | |
| 318 | * are supported but the set structure becomes a bit inefficient once | |
| 319 | * you go over 4. | |
| 320 | * | |
| 321 | * (2) The blockrefs in a set can shortcut multiple levels of indirections | |
| 322 | * within the bounds imposed by the parent of set. | |
| 323 | * | |
| 324 | * When a set fills up another level of indirection is inserted, moving | |
| 325 | * some or all of the set's contents into indirect blocks placed under the | |
| 326 | * set. This is a top-down approach in that indirect blocks are not created | |
| 327 | * until the set actually becomes full (that is, the entries in the set can | |
| 328 | * shortcut the indirect blocks when the set is not full). Depending on how | |
| 329 | * things are filled multiple indirect blocks will eventually be created. | |
| 330 | */ | |
| 331 | struct hammer2_blockset { | |
| 4894e7c9 | 332 | hammer2_blockref_t blockref[HAMMER2_SET_COUNT]; |
| 703720e4 MD |
333 | }; |
| 334 | ||
| 4894e7c9 MD |
335 | typedef struct hammer2_blockset hammer2_blockset_t; |
| 336 | ||
| 703720e4 MD |
337 | /* |
| 338 | * Catch programmer snafus | |
| 339 | */ | |
| 703720e4 MD |
340 | #if (1 << HAMMER2_SET_RADIX) != HAMMER2_SET_COUNT |
| 341 | #error "hammer2 direct radix is incorrect" | |
| 342 | #endif | |
| 343 | #if (1 << HAMMER2_PBUFRADIX) != HAMMER2_PBUFSIZE | |
| 344 | #error "HAMMER2_PBUFRADIX and HAMMER2_PBUFSIZE are inconsistent" | |
| 345 | #endif | |
| 346 | #if (1 << HAMMER2_MIN_RADIX) != HAMMER2_MIN_ALLOC | |
| 347 | #error "HAMMER2_MIN_RADIX and HAMMER2_MIN_ALLOC are inconsistent" | |
| 348 | #endif | |
| 349 | ||
| 350 | /* | |
| 351 | * The media indirect block structure. | |
| 352 | */ | |
| 7cfa8da5 | 353 | struct hammer2_indblock_data { |
| 6ba3b984 | 354 | hammer2_blockref_t blockref[HAMMER2_IND_COUNT_MAX]; |
| 703720e4 MD |
355 | }; |
| 356 | ||
| 7cfa8da5 | 357 | typedef struct hammer2_indblock_data hammer2_indblock_data_t; |
| 703720e4 MD |
358 | |
| 359 | /* | |
| 360 | * In HAMMER2 inodes ARE directory entries, with a special exception for | |
| 361 | * hardlinks. The inode number is stored in the inode rather than being | |
| 362 | * based on the location of the inode (since the location moves every time | |
| 363 | * the inode or anything underneath the inode is modified). | |
| 364 | * | |
| 365 | * The inode is 1024 bytes, made up of 256 bytes of meta-data, 256 bytes | |
| 366 | * for the filename, and 512 bytes worth of direct file data OR an embedded | |
| 367 | * blockset. | |
| 368 | * | |
| 369 | * Directories represent one inode per blockref. Inodes are not laid out | |
| 370 | * as a file but instead are represented by the related blockrefs. The | |
| 371 | * blockrefs, in turn, are indexed by the 64-bit directory hash key. Remember | |
| 372 | * that blocksets are fully associative, so a certain degree efficiency is | |
| 373 | * achieved just from that. | |
| 374 | * | |
| 375 | * Up to 512 bytes of direct data can be embedded in an inode, and since | |
| 376 | * inodes are essentially directory entries this also means that small data | |
| 377 | * files end up simply being laid out linearly in the directory, resulting | |
| 378 | * in fewer seeks and highly optimal access. | |
| 379 | * | |
| 380 | * The compression mode can be changed at any time in the inode and is | |
| 381 | * recorded on a blockref-by-blockref basis. | |
| 382 | * | |
| 383 | * Hardlinks are supported via the inode map. Essentially the way a hardlink | |
| 384 | * works is that all individual directory entries representing the same file | |
| 385 | * are special cased and specify the same inode number. The actual file | |
| 386 | * is placed in the nearest parent directory that is parent to all instances | |
| 387 | * of the hardlink. If all hardlinks to a file are in the same directory | |
| 388 | * the actual file will also be placed in that directory. This file uses | |
| 389 | * the inode number as the directory entry key and is invisible to normal | |
| 390 | * directory scans. Real directory entry keys are differentiated from the | |
| 391 | * inode number key via bit 63. Access to the hardlink silently looks up | |
| 392 | * the real file and forwards all operations to that file. Removal of the | |
| 393 | * last hardlink also removes the real file. | |
| 2910a90c MD |
394 | * |
| 395 | * (attr_tid) is only updated when the inode's specific attributes or regular | |
| 396 | * file size has changed, and affects path lookups and stat. (attr_tid) | |
| 397 | * represents a special cache coherency lock under the inode. The inode | |
| 398 | * blockref's modify_tid will always cover it. | |
| 399 | * | |
| 400 | * (dirent_tid) is only updated when an entry under a directory inode has | |
| 401 | * been created, deleted, renamed, or had its attributes change, and affects | |
| 402 | * directory lookups and scans. (dirent_tid) represents another special cache | |
| 403 | * coherency lock under the inode. The inode blockref's modify_tid will | |
| 404 | * always cover it. | |
| 703720e4 MD |
405 | */ |
| 406 | #define HAMMER2_INODE_BYTES 1024 /* (asserted by code) */ | |
| 407 | #define HAMMER2_INODE_MAXNAME 256 /* maximum name in bytes */ | |
| 408 | #define HAMMER2_INODE_VERSION_ONE 1 | |
| 409 | ||
| 410 | struct hammer2_inode_data { | |
| 411 | uint16_t version; /* 0000 inode data version */ | |
| 412 | uint16_t reserved02; /* 0002 */ | |
| ae183399 MD |
413 | |
| 414 | /* | |
| 415 | * core inode attributes, inode type, misc flags | |
| 416 | */ | |
| 703720e4 MD |
417 | uint32_t uflags; /* 0004 chflags */ |
| 418 | uint32_t rmajor; /* 0008 available for device nodes */ | |
| 419 | uint32_t rminor; /* 000C available for device nodes */ | |
| 420 | uint64_t ctime; /* 0010 inode change time */ | |
| 421 | uint64_t mtime; /* 0018 modified time */ | |
| 422 | uint64_t atime; /* 0020 access time (unsupported) */ | |
| 423 | uint64_t btime; /* 0028 birth time */ | |
| 424 | uuid_t uid; /* 0030 uid / degenerate unix uid */ | |
| 425 | uuid_t gid; /* 0040 gid / degenerate unix gid */ | |
| 426 | ||
| 427 | uint8_t type; /* 0050 object type */ | |
| 428 | uint8_t op_flags; /* 0051 operational flags */ | |
| 429 | uint16_t cap_flags; /* 0052 capability flags */ | |
| 430 | uint32_t mode; /* 0054 unix modes (typ low 16 bits) */ | |
| 431 | ||
| ae183399 MD |
432 | /* |
| 433 | * inode size, identification, localized recursive configuration | |
| 434 | * for compression and backup copies. | |
| 435 | */ | |
| 703720e4 MD |
436 | hammer2_tid_t inum; /* 0058 inode number */ |
| 437 | hammer2_off_t size; /* 0060 size of file */ | |
| 438 | uint64_t nlinks; /* 0068 hard links (typ only dirs) */ | |
| 439 | hammer2_tid_t iparent; /* 0070 parent inum (recovery only) */ | |
| ae183399 MD |
440 | hammer2_key_t name_key; /* 0078 full filename key */ |
| 441 | uint16_t name_len; /* 0080 filename length */ | |
| 442 | uint8_t ncopies; /* 0082 ncopies to local media */ | |
| 443 | uint8_t comp_algo; /* 0083 compression request & algo */ | |
| 444 | ||
| 445 | /* | |
| 446 | * These fields are currently only applicable to PFSROOTs. | |
| 447 | * | |
| 8c280d5d | 448 | * NOTE: We can't use {volume_data->fsid, pfs_clid} to uniquely |
| ae183399 MD |
449 | * identify an instance of a PFS in the cluster because |
| 450 | * a mount may contain more than one copy of the PFS as | |
| 8c280d5d | 451 | * a separate node. {pfs_clid, pfs_fsid} must be used for |
| ae183399 MD |
452 | * registration in the cluster. |
| 453 | */ | |
| 99535653 | 454 | uint8_t target_type; /* 0084 hardlink target type */ |
| ae183399 MD |
455 | uint8_t reserved85; /* 0085 */ |
| 456 | uint8_t reserved86; /* 0086 */ | |
| 457 | uint8_t pfs_type; /* 0087 (if PFSROOT) node type */ | |
| 458 | uint64_t pfs_inum; /* 0088 (if PFSROOT) inum allocator */ | |
| 8c280d5d MD |
459 | uuid_t pfs_clid; /* 0090 (if PFSROOT) cluster uuid */ |
| 460 | uuid_t pfs_fsid; /* 00A0 (if PFSROOT) unique uuid */ | |
| ae183399 MD |
461 | |
| 462 | /* | |
| 463 | * Quotas and cumulative sub-tree counters. | |
| 464 | */ | |
| 465 | hammer2_off_t data_quota; /* 00B0 subtree quota in bytes */ | |
| 466 | hammer2_off_t data_count; /* 00B8 subtree byte count */ | |
| 467 | hammer2_off_t inode_quota; /* 00C0 subtree quota inode count */ | |
| 468 | hammer2_off_t inode_count; /* 00C8 subtree inode count */ | |
| 2910a90c MD |
469 | hammer2_tid_t attr_tid; /* 00D0 attributes changed */ |
| 470 | hammer2_tid_t dirent_tid; /* 00D8 directory/attr changed */ | |
| 703720e4 MD |
471 | uint64_t reservedE0; /* 00E0 */ |
| 472 | uint64_t reservedE8; /* 00E8 */ | |
| 473 | uint64_t reservedF0; /* 00F0 */ | |
| 474 | uint64_t reservedF8; /* 00F8 */ | |
| 475 | ||
| 4894e7c9 | 476 | unsigned char filename[HAMMER2_INODE_MAXNAME]; |
| 703720e4 MD |
477 | /* 0100-01FF (256 char, unterminated) */ |
| 478 | union { /* 0200-03FF (64x8 = 512 bytes) */ | |
| 479 | struct hammer2_blockset blockset; | |
| 480 | char data[HAMMER2_EMBEDDED_BYTES]; | |
| 481 | } u; | |
| 482 | }; | |
| 483 | ||
| 4894e7c9 MD |
484 | typedef struct hammer2_inode_data hammer2_inode_data_t; |
| 485 | ||
| 703720e4 | 486 | #define HAMMER2_OPFLAG_DIRECTDATA 0x01 |
| 4894e7c9 | 487 | #define HAMMER2_OPFLAG_PFSROOT 0x02 |
| 2910a90c | 488 | #define HAMMER2_OPFLAG_COPYIDS 0x04 /* copyids override parent */ |
| 703720e4 MD |
489 | |
| 490 | #define HAMMER2_OBJTYPE_UNKNOWN 0 | |
| 491 | #define HAMMER2_OBJTYPE_DIRECTORY 1 | |
| 492 | #define HAMMER2_OBJTYPE_REGFILE 2 | |
| 493 | #define HAMMER2_OBJTYPE_FIFO 4 | |
| 494 | #define HAMMER2_OBJTYPE_CDEV 5 | |
| 495 | #define HAMMER2_OBJTYPE_BDEV 6 | |
| 496 | #define HAMMER2_OBJTYPE_SOFTLINK 7 | |
| db0c2eb3 | 497 | #define HAMMER2_OBJTYPE_HARDLINK 8 /* dummy entry for hardlink */ |
| 703720e4 MD |
498 | #define HAMMER2_OBJTYPE_SOCKET 9 |
| 499 | #define HAMMER2_OBJTYPE_WHITEOUT 10 | |
| 500 | ||
| 4894e7c9 MD |
501 | #define HAMMER2_COPYID_NONE 0 |
| 502 | #define HAMMER2_COPYID_LOCAL ((uint8_t)-1) | |
| 503 | ||
| 504 | #define HAMMER2_COMP_NONE 0 | |
| 505 | #define HAMMER2_COMP_AUTOZERO 1 | |
| 506 | ||
| 507 | #define HAMMER2_CHECK_NONE 0 | |
| 508 | #define HAMMER2_CHECK_ICRC 1 | |
| 509 | ||
| 2063f4d7 MD |
510 | /* |
| 511 | * PEER types identify connections and help cluster controller filter | |
| 512 | * out unwanted SPANs. | |
| 513 | */ | |
| 514 | #define HAMMER2_PEER_NONE 0 | |
| 515 | #define HAMMER2_PEER_CLUSTER 1 /* a cluster controller */ | |
| 516 | #define HAMMER2_PEER_BLOCK 2 /* block devices */ | |
| 517 | #define HAMMER2_PEER_HAMMER2 3 /* hammer2-mounted volumes */ | |
| 518 | ||
| 519 | /* | |
| 520 | * PFS types identify a PFS on media and in LNK_SPAN messages. | |
| 521 | */ | |
| 2910a90c MD |
522 | #define HAMMER2_PFSTYPE_NONE 0 |
| 523 | #define HAMMER2_PFSTYPE_ADMIN 1 | |
| 9b8b748f MD |
524 | #define HAMMER2_PFSTYPE_CLIENT 2 |
| 525 | #define HAMMER2_PFSTYPE_CACHE 3 | |
| 526 | #define HAMMER2_PFSTYPE_COPY 4 | |
| 527 | #define HAMMER2_PFSTYPE_SLAVE 5 | |
| 528 | #define HAMMER2_PFSTYPE_SOFT_SLAVE 6 | |
| 529 | #define HAMMER2_PFSTYPE_SOFT_MASTER 7 | |
| 530 | #define HAMMER2_PFSTYPE_MASTER 8 | |
| 8c280d5d | 531 | #define HAMMER2_PFSTYPE_MAX 9 /* 0-8 */ |
| 2910a90c | 532 | |
| 703720e4 MD |
533 | /* |
| 534 | * The allocref structure represents the allocation table. One 64K block | |
| 535 | * is broken down into 4096 x 16 byte entries. Each indirect block chops | |
| 536 | * 11 bits off the 64-bit storage space, with leaf entries representing | |
| 537 | * 64KB blocks. So: (12, 12, 12, 12, 16) = 64 bit storage space. | |
| 538 | * | |
| 5a9a531c | 539 | * Each 64K freemap block breaks the 4096 entries into a 64x64 tree with |
| 703720e4 MD |
540 | * big_hint1 representing the top level every 64th entry and big_hint2 |
| 541 | * representing the lower level in each entry. These fields specify the | |
| 542 | * largest contiguous radix (1-63) available for allocation in the related | |
| 543 | * sub-tree. The largest contiguous radix available for the entire block | |
| 544 | * is saved in the parent (for the root this will be alloc_blockref in the | |
| 545 | * volume header). The hints may be larger than actual and will be corrected | |
| 546 | * on the fly but must not be smaller. The allocator uses the hints to | |
| 547 | * very quickly locate nearby blocks of the desired size. | |
| 548 | * | |
| 549 | * In indirect blocks the 64-bit free[_or_mask] field stores the total free | |
| 550 | * space for each of the 4096 sub-nodes in bytes. The total free space | |
| 551 | * represented by the indirect block is stored in its parent. | |
| 552 | * | |
| 553 | * Each leaf element represents a 64K block. A bitmap replaces the free space | |
| 554 | * count, giving us a 1KB allocation resolution. A micro-allocation append | |
| 555 | * offset replaces the icrc field. The micro-allocation feature is not | |
| 556 | * currently implemented and the field will be set to 65536. | |
| 557 | * | |
| 558 | * The allocation map uses reserved blocks so no data block reference is | |
| 559 | * required, only a bit in the flags field to specify which of two possible | |
| 560 | * reserved blocks to use. This allows the allocation map to be flushed to | |
| 561 | * disk with minimal synchronization. | |
| 562 | */ | |
| 563 | struct hammer2_allocref { | |
| 564 | uint32_t icrc_or_app; /* node: icrc, leaf: append offset */ | |
| 565 | uint16_t flags; | |
| 566 | uint8_t big_hint1; /* upper level hint */ | |
| 567 | uint8_t big_hint2; /* lower level hint */ | |
| 568 | uint64_t free_or_mask; /* node: free bytes, leaf: bitmask */ | |
| 569 | }; | |
| 570 | ||
| 571 | typedef struct hammer2_allocref hammer2_allocref_t; | |
| 572 | ||
| 573 | /* | |
| 574 | * WARNING - allocref size x entries must equate to the hammer buffer size, | |
| 575 | * and 12 bits per recursion is assumed by the allocator. | |
| 576 | * | |
| 577 | * ALTA-D Since no data_offset is specified flags are needed to select | |
| 578 | * which sub-block to recurse down into for root & internal nodes. | |
| 579 | * (only ALTA and ALTB is currently supported). | |
| 580 | * | |
| 581 | * LEAF Terminal entry, always set for leafs. May be used to support | |
| 582 | * 4MB extent allocations and early termination in the future. | |
| 583 | * (not required to shortcut allocation scans as the big_hint1/2 | |
| 584 | * fields are used for this). | |
| 585 | */ | |
| 586 | #define HAMMER2_ALLOCREF_BYTES 16 /* structure size */ | |
| 587 | #define HAMMER2_ALLOCREF_ENTRIES 4096 /* entries */ | |
| 588 | #define HAMMER2_ALLOCREF_RADIX 12 /* log2(entries) */ | |
| 589 | ||
| 4894e7c9 | 590 | #if (HAMMER2_ALLOCREF_BYTES * HAMMER2_ALLOCREF_ENTRIES) != HAMMER2_PBUFSIZE |
| 703720e4 MD |
591 | #error "allocref parameters do not fit in hammer buffer" |
| 592 | #endif | |
| 593 | #if (1 << HAMMER2_ALLOCREF_RADIX) != HAMMER2_ALLOCREF_ENTRIES | |
| 594 | #error "allocref parameters are inconsistent" | |
| 595 | #endif | |
| 596 | ||
| 597 | #define HAMMER2_ALLOCREF_ALTMASK 0x0003 /* select block for recurse */ | |
| 598 | #define HAMMER2_ALLOCREF_ALTA 0x0000 | |
| 599 | #define HAMMER2_ALLOCREF_ALTB 0x0001 | |
| 600 | #define HAMMER2_ALLOCREF_ALTC 0x0002 /* unsupported */ | |
| 601 | #define HAMMER2_ALLOCREF_ALTD 0x0003 /* unsupported */ | |
| 602 | #define HAMMER2_ALLOCREF_LEAF 0x0004 | |
| 603 | ||
| 703720e4 | 604 | /* |
| 2910a90c MD |
605 | * All HAMMER2 directories directly under the super-root on your local |
| 606 | * media can be mounted separately, even if they share the same physical | |
| 607 | * device. | |
| 608 | * | |
| 609 | * When you do a HAMMER2 mount you are effectively tying into a HAMMER2 | |
| 610 | * cluster via local media. The local media does not have to participate | |
| 611 | * in the cluster, other than to provide the hammer2_copy_data[] array and | |
| 612 | * root inode for the mount. | |
| 613 | * | |
| 614 | * This is important: The mount device path you specify serves to bootstrap | |
| 615 | * your entry into the cluster, but your mount will make active connections | |
| 616 | * to ALL copy elements in the hammer2_copy_data[] array which match the | |
| 617 | * PFSID of the directory in the super-root that you specified. The local | |
| 618 | * media path does not have to be mentioned in this array but becomes part | |
| 619 | * of the cluster based on its type and access rights. ALL ELEMENTS ARE | |
| 620 | * TREATED ACCORDING TO TYPE NO MATTER WHICH ONE YOU MOUNT FROM. | |
| 621 | * | |
| 622 | * The actual cluster may be far larger than the elements you list in the | |
| 623 | * hammer2_copy_data[] array. You list only the elements you wish to | |
| 624 | * directly connect to and you are able to access the rest of the cluster | |
| 625 | * indirectly through those connections. | |
| 626 | * | |
| 627 | * This structure must be exactly 128 bytes long. | |
| 703720e4 MD |
628 | */ |
| 629 | struct hammer2_copy_data { | |
| 2910a90c MD |
630 | uint8_t copyid; /* 00 copyid 0-255 (must match slot) */ |
| 631 | uint8_t inprog; /* 01 operation in progress, or 0 */ | |
| 632 | uint8_t chain_to; /* 02 operation chaining to, or 0 */ | |
| 633 | uint8_t chain_from; /* 03 operation chaining from, or 0 */ | |
| 634 | uint16_t flags; /* 04-05 flags field */ | |
| 635 | uint8_t error; /* 06 last operational error */ | |
| 636 | uint8_t priority; /* 07 priority and round-robin flag */ | |
| 62efe6ec | 637 | uint8_t remote_pfs_type;/* 08 probed direct remote PFS type */ |
| 2910a90c | 638 | uint8_t reserved08[23]; /* 09-1F */ |
| 8c280d5d | 639 | uuid_t pfs_clid; /* 20-2F copy target must match this uuid */ |
| 2910a90c MD |
640 | uint8_t label[16]; /* 30-3F import/export label */ |
| 641 | uint8_t path[64]; /* 40-7F target specification string or key */ | |
| 703720e4 MD |
642 | }; |
| 643 | ||
| 644 | typedef struct hammer2_copy_data hammer2_copy_data_t; | |
| 645 | ||
| 2910a90c MD |
646 | #define COPYDATAF_ENABLED 0x0001 |
| 647 | #define COPYDATAF_INPROG 0x0002 | |
| 648 | #define COPYDATAF_CONN_RR 0x80 /* round-robin at same priority */ | |
| 649 | #define COPYDATAF_CONN_EF 0x40 /* media errors flagged */ | |
| 650 | #define COPYDATAF_CONN_PRI 0x0F /* select priority 0-15 (15=best) */ | |
| 703720e4 MD |
651 | |
| 652 | /* | |
| 653 | * The volume header eats a 64K block. There is currently an issue where | |
| 654 | * we want to try to fit all nominal filesystem updates in a 512-byte section | |
| 655 | * but it may be a lost cause due to the need for a blockset. | |
| 656 | * | |
| 657 | * All information is stored in host byte order. The volume header's magic | |
| 658 | * number may be checked to determine the byte order. If you wish to mount | |
| 659 | * between machines w/ different endian modes you'll need filesystem code | |
| 660 | * which acts on the media data consistently (either all one way or all the | |
| 661 | * other). Our code currently does not do that. | |
| 662 | * | |
| 663 | * A read-write mount may have to recover missing allocations by doing an | |
| 664 | * incremental mirror scan looking for modifications made after alloc_tid. | |
| 665 | * If alloc_tid == last_tid then no recovery operation is needed. Recovery | |
| 666 | * operations are usually very, very fast. | |
| 667 | * | |
| 668 | * Read-only mounts do not need to do any recovery, access to the filesystem | |
| 669 | * topology is always consistent after a crash (is always consistent, period). | |
| 670 | * However, there may be shortcutted blockref updates present from deep in | |
| 671 | * the tree which are stored in the volumeh eader and must be tracked on | |
| 672 | * the fly. | |
| 673 | * | |
| 62efe6ec MD |
674 | * NOTE: The copyinfo[] array contains the configuration for both the |
| 675 | * cluster connections and any local media copies. The volume | |
| 676 | * header will be replicated for each local media copy. | |
| 677 | * | |
| 678 | * The mount command may specify multiple medias or just one and | |
| 679 | * allow HAMMER2 to pick up the others when it checks the copyinfo[] | |
| 680 | * array on mount. | |
| 703720e4 MD |
681 | * |
| 682 | * NOTE: root_blockref points to the super-root directory, not the root | |
| 683 | * directory. The root directory will be a subdirectory under the | |
| 684 | * super-root. | |
| 685 | * | |
| 686 | * The super-root directory contains all root directories and all | |
| 687 | * snapshots (readonly or writable). It is possible to do a | |
| 688 | * null-mount of the super-root using special path constructions | |
| 689 | * relative to your mounted root. | |
| 690 | * | |
| 691 | * NOTE: HAMMER2 allows any subdirectory tree to be managed as if it were | |
| 692 | * a PFS, including mirroring and storage quota operations, and this is | |
| 693 | * prefered over creating discrete PFSs in the super-root. Instead | |
| 694 | * the super-root is most typically used to create writable snapshots, | |
| 695 | * alternative roots, and so forth. The super-root is also used by | |
| 696 | * the automatic snapshotting mechanism. | |
| 697 | */ | |
| 698 | #define HAMMER2_VOLUME_ID_HBO 0x48414d3205172011LLU | |
| 699 | #define HAMMER2_VOLUME_ID_ABO 0x11201705324d4148LLU | |
| 700 | ||
| 2910a90c MD |
701 | #define HAMMER2_COPYID_COUNT 256 |
| 702 | ||
| 703720e4 MD |
703 | struct hammer2_volume_data { |
| 704 | /* | |
| 2910a90c | 705 | * sector #0 - 512 bytes |
| 703720e4 MD |
706 | */ |
| 707 | uint64_t magic; /* 0000 Signature */ | |
| 708 | hammer2_off_t boot_beg; /* 0008 Boot area (future) */ | |
| 709 | hammer2_off_t boot_end; /* 0010 (size = end - beg) */ | |
| 866d5273 MD |
710 | hammer2_off_t aux_beg; /* 0018 Aux area (future) */ |
| 711 | hammer2_off_t aux_end; /* 0020 (size = end - beg) */ | |
| 703720e4 MD |
712 | hammer2_off_t volu_size; /* 0028 Volume size, bytes */ |
| 713 | ||
| 714 | uint32_t version; /* 0030 */ | |
| 715 | uint32_t flags; /* 0034 */ | |
| 716 | uint8_t copyid; /* 0038 copyid of phys vol */ | |
| 5a9a531c | 717 | uint8_t freemap_version; /* 0039 freemap algorithm */ |
| 2063f4d7 | 718 | uint8_t peer_type; /* 003A HAMMER2_PEER_xxx */ |
| 703720e4 MD |
719 | uint8_t reserved003B; /* 003B */ |
| 720 | uint32_t reserved003C; /* 003C */ | |
| 721 | ||
| 722 | uuid_t fsid; /* 0040 */ | |
| 723 | uuid_t fstype; /* 0050 */ | |
| 724 | ||
| 725 | /* | |
| 726 | * allocator_size is precalculated at newfs time and does not include | |
| 727 | * reserved blocks, boot, or redo areas. | |
| 728 | * | |
| 729 | * Initial non-reserved-area allocations do not use the allocation | |
| 730 | * map but instead adjust alloc_iterator. Dynamic allocations take | |
| 731 | * over starting at (allocator_beg). This makes newfs_hammer2's | |
| 732 | * job a lot easier and can also serve as a testing jig. | |
| 733 | */ | |
| 734 | hammer2_off_t allocator_size; /* 0060 Total data space */ | |
| 735 | hammer2_off_t allocator_free; /* 0068 Free space */ | |
| 4d5318eb MD |
736 | hammer2_off_t allocator_beg; /* 0070 Initial allocations */ |
| 737 | hammer2_tid_t mirror_tid; /* 0078 best committed tid */ | |
| 703720e4 MD |
738 | hammer2_tid_t alloc_tid; /* 0080 Alloctable modify tid */ |
| 739 | hammer2_blockref_t alloc_blockref; /* 0088-00C7 */ | |
| 740 | ||
| 741 | /* | |
| 742 | * Copyids are allocated dynamically from the copyexists bitmap. | |
| 743 | * An id from the active copies set (up to 8, see copyinfo later on) | |
| 744 | * may still exist after the copy set has been removed from the | |
| 745 | * volume header and its bit will remain active in the bitmap and | |
| 746 | * cannot be reused until it is 100% removed from the hierarchy. | |
| 747 | */ | |
| 748 | uint32_t copyexists[8]; /* 00C8-00E7 copy exists bmap */ | |
| 749 | char reserved0140[248]; /* 00E8-01DF */ | |
| 750 | ||
| 751 | /* | |
| 752 | * 32 bit CRC array at the end of the first 512 byte sector. | |
| 753 | * | |
| 754 | * icrc_sects[7] - First 512-4 bytes of volume header (including all | |
| 755 | * the other icrc's except the last one). | |
| 756 | * | |
| 757 | * icrc_sects[6] - Second 512-4 bytes of volume header, which is | |
| 758 | * the blockset for the root. | |
| 759 | */ | |
| 760 | hammer2_crc32_t icrc_sects[8]; /* 01E0-01FF */ | |
| 761 | ||
| 762 | /* | |
| 2910a90c | 763 | * sector #1 - 512 bytes |
| 703720e4 MD |
764 | * |
| 765 | * The entire sector is used by a blockset. | |
| 766 | */ | |
| 2910a90c | 767 | hammer2_blockset_t sroot_blockset; /* 0200-03FF Superroot dir */ |
| 703720e4 MD |
768 | |
| 769 | /* | |
| 2910a90c MD |
770 | * sector #2-7 |
| 771 | */ | |
| 772 | char sector2[512]; /* 0400-05FF reserved */ | |
| 773 | char sector3[512]; /* 0600-07FF reserved */ | |
| 774 | char sector4[512]; /* 0800-09FF reserved */ | |
| 775 | char sector5[512]; /* 0A00-0BFF reserved */ | |
| 776 | char sector6[512]; /* 0C00-0DFF reserved */ | |
| 777 | char sector7[512]; /* 0E00-0FFF reserved */ | |
| 778 | ||
| 779 | /* | |
| 780 | * sector #8-71 - 32768 bytes | |
| 781 | * | |
| 782 | * Contains the configuration for up to 256 copyinfo targets. These | |
| 783 | * specify local and remote copies operating as masters or slaves. | |
| 784 | * copyid's 0 and 255 are reserved (0 indicates an empty slot and 255 | |
| 785 | * indicates the local media). | |
| 5a9a531c | 786 | * |
| 2910a90c MD |
787 | * Each inode contains a set of up to 8 copyids, either inherited |
| 788 | * from its parent or explicitly specified in the inode, which | |
| 789 | * indexes into this array. | |
| 790 | */ | |
| 791 | /* 1000-8FFF copyinfo config */ | |
| 792 | struct hammer2_copy_data copyinfo[HAMMER2_COPYID_COUNT]; | |
| 793 | ||
| 794 | /* | |
| 703720e4 | 795 | * |
| 703720e4 | 796 | */ |
| 703720e4 MD |
797 | |
| 798 | /* | |
| 799 | * Remaining sections are reserved for future use. | |
| 800 | */ | |
| 2910a90c | 801 | char reserved0400[0x6FFC]; /* 9000-FFFB reserved */ |
| 703720e4 MD |
802 | |
| 803 | /* | |
| 804 | * icrc on entire volume header | |
| 805 | */ | |
| 806 | hammer2_crc32_t icrc_volheader; /* FFFC-FFFF full volume icrc*/ | |
| 807 | }; | |
| 808 | ||
| 4894e7c9 MD |
809 | typedef struct hammer2_volume_data hammer2_volume_data_t; |
| 810 | ||
| 703720e4 | 811 | /* |
| 4894e7c9 MD |
812 | * Various parts of the volume header have their own iCRCs. |
| 813 | * | |
| 814 | * The first 512 bytes has its own iCRC stored at the end of the 512 bytes | |
| 815 | * and not included the icrc calculation. | |
| 816 | * | |
| 817 | * The second 512 bytes also has its own iCRC but it is stored in the first | |
| 818 | * 512 bytes so it covers the entire second 512 bytes. | |
| 703720e4 | 819 | * |
| 4894e7c9 MD |
820 | * The whole volume block (64KB) has an iCRC covering all but the last 4 bytes, |
| 821 | * which is where the iCRC for the whole volume is stored. This is currently | |
| 822 | * a catch-all for anything not individually iCRCd. | |
| 703720e4 MD |
823 | */ |
| 824 | #define HAMMER2_VOL_ICRC_SECT0 7 | |
| 825 | #define HAMMER2_VOL_ICRC_SECT1 6 | |
| 826 | ||
| 703720e4 | 827 | #define HAMMER2_VOLUME_BYTES 65536 |
| 4894e7c9 MD |
828 | |
| 829 | #define HAMMER2_VOLUME_ICRC0_OFF 0 | |
| 830 | #define HAMMER2_VOLUME_ICRC1_OFF 512 | |
| 831 | #define HAMMER2_VOLUME_ICRCVH_OFF 0 | |
| 832 | ||
| 833 | #define HAMMER2_VOLUME_ICRC0_SIZE (512 - 4) | |
| 834 | #define HAMMER2_VOLUME_ICRC1_SIZE (512) | |
| 835 | #define HAMMER2_VOLUME_ICRCVH_SIZE (65536 - 4) | |
| 703720e4 MD |
836 | |
| 837 | #define HAMMER2_VOL_VERSION_MIN 1 | |
| 838 | #define HAMMER2_VOL_VERSION_DEFAULT 1 | |
| 839 | #define HAMMER2_VOL_VERSION_WIP 2 | |
| 840 | ||
| 841 | #define HAMMER2_NUM_VOLHDRS 4 | |
| 842 | ||
| 5c23d7f1 | 843 | union hammer2_media_data { |
| 4d5318eb | 844 | hammer2_volume_data_t voldata; |
| 5c23d7f1 MD |
845 | hammer2_inode_data_t ipdata; |
| 846 | hammer2_indblock_data_t npdata; | |
| 847 | char buf[HAMMER2_PBUFSIZE]; | |
| 848 | }; | |
| 849 | ||
| 850 | typedef union hammer2_media_data hammer2_media_data_t; | |
| 851 | ||
| 703720e4 MD |
852 | /* |
| 853 | * Prototypes for user & kernel functions. Kernel-only prototypes are | |
| 854 | * elsewhere. | |
| 855 | */ | |
| 856 | uint32_t hammer2_icrc32(const void *buf, size_t size); | |
| 857 | uint32_t hammer2_icrc32c(const void *buf, size_t size, uint32_t crc); | |
| 858 | ||
| 859 | #endif |