1 /* 2 * Copyright 2017, Chế Vũ Gia Hy, cvghy116@gmail.com. 3 * Copyright 2011, Jérôme Duval, korli@users.berlios.de. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef BTRFS_H 7 #define BTRFS_H 8 9 10 #include "system_dependencies.h" 11 12 13 typedef uint64 fileblock_t; // file block number 14 typedef uint64 fsblock_t; // filesystem block number 15 16 #define BTRFS_LABEL_SIZE 256 17 18 #define BTRFS_SUPER_BLOCK_OFFSET 0x10000 // 64KiB 19 #define BTRFS_RESERVED_SPACE_OFFSET 0x100000 // 1MiB 20 21 #define BTRFS_NUM_ROOT_BACKUPS 4 22 23 24 struct btrfs_backup_roots { 25 uint64 root; 26 uint64 root_generation; 27 uint64 chunk_root; 28 uint64 chunk_root_generation; 29 uint64 extent_root; 30 uint64 extent_root_generation; 31 uint64 fs_root; 32 uint64 fs_root_generation; 33 uint64 device_root; 34 uint64 device_root_generation; 35 uint64 csum_root; 36 uint64 csum_root_generation; 37 uint64 total_size; 38 uint64 used_size; 39 uint64 num_devices; 40 uint8 unused_1[32]; 41 uint8 root_level; 42 uint8 chunk_root_level; 43 uint8 extent_root_level; 44 uint8 fs_root_level; 45 uint8 device_root_level; 46 uint8 csum_root_level; 47 uint8 unused_2[10]; 48 49 uint64 Root() const { return B_LENDIAN_TO_HOST_INT64(root); } 50 uint64 RootGen() const 51 { return B_LENDIAN_TO_HOST_INT64(root_generation); } 52 uint64 ChunkRoot() const { return B_LENDIAN_TO_HOST_INT64(chunk_root); } 53 uint64 ChunkRootGen() const 54 { return B_LENDIAN_TO_HOST_INT64(chunk_root_generation); } 55 uint64 ExtentRoot() const { return B_LENDIAN_TO_HOST_INT64(extent_root); } 56 uint64 ExtentRootGen() const 57 { return B_LENDIAN_TO_HOST_INT64(extent_root_generation); } 58 uint64 FSRoot() const { return B_LENDIAN_TO_HOST_INT64(fs_root); } 59 uint64 FSRootGen() const 60 { return B_LENDIAN_TO_HOST_INT64(fs_root_generation); } 61 uint64 DeviceRoot() const { return B_LENDIAN_TO_HOST_INT64(device_root); } 62 uint64 DeviceRootGen() const 63 { return B_LENDIAN_TO_HOST_INT64(device_root_generation); } 64 uint64 CSumRoot() const { return B_LENDIAN_TO_HOST_INT64(csum_root); } 65 uint64 CSumRootGen() const 66 { return B_LENDIAN_TO_HOST_INT64(csum_root_generation); } 67 uint8 RootLevel() const { return root_level; } 68 uint8 ChunkRootLevel() const { return chunk_root_level; } 69 uint8 ExtentRootLevel() const { return extent_root_level; } 70 uint8 FSRootLevel() const { return fs_root_level; } 71 uint8 DeviceRootLevel() const { return device_root_level; } 72 uint8 CSumRootLevel() const { return csum_root_level; } 73 } _PACKED; 74 75 76 struct btrfs_key { 77 uint64 object_id; 78 uint8 type; 79 uint64 offset; 80 81 uint64 ObjectID() const { return B_LENDIAN_TO_HOST_INT64(object_id); } 82 uint8 Type() const { return type; } 83 uint64 Offset() const { return B_LENDIAN_TO_HOST_INT64(offset); } 84 void SetObjectID(uint64 id) { object_id = B_HOST_TO_LENDIAN_INT64(id); } 85 void SetType(uint8 key_type) { type = key_type; } 86 void SetOffset(uint64 off) { offset = B_HOST_TO_LENDIAN_INT64(off); } 87 int32 Compare(const btrfs_key& key) const; 88 // implemented in BTree.cpp 89 } _PACKED; 90 91 92 struct btrfs_timespec { 93 uint64 seconds; 94 uint32 nanoseconds; 95 } _PACKED; 96 97 98 struct btrfs_header { 99 uint8 checksum[32]; 100 uuid_t fsid; 101 uint64 logical_address; 102 uint64 flags; 103 uuid_t chunk_tree_uuid; 104 uint64 generation; 105 uint64 owner; 106 uint32 item_count; 107 uint8 level; 108 uint64 LogicalAddress() const 109 { return B_LENDIAN_TO_HOST_INT64(logical_address); } 110 uint64 Flags() const { return B_LENDIAN_TO_HOST_INT64(flags); } 111 uint64 Generation() const 112 { return B_LENDIAN_TO_HOST_INT64(generation); } 113 uint64 Owner() const 114 { return B_LENDIAN_TO_HOST_INT64(owner); } 115 uint32 ItemCount() const 116 { return B_LENDIAN_TO_HOST_INT32(item_count); } 117 uint8 Level() const { return level; } 118 119 void SetLogicalAddress(uint64 logical) 120 { logical_address = B_HOST_TO_LENDIAN_INT64(logical); } 121 void SetGeneration(uint64 gen) 122 { generation = B_HOST_TO_LENDIAN_INT64(gen); } 123 void SetItemCount(uint32 itemCount) 124 { item_count = B_HOST_TO_LENDIAN_INT32(itemCount); } 125 } _PACKED; 126 127 128 struct btrfs_index { 129 btrfs_key key; 130 uint64 logical_address; 131 uint64 generation; 132 uint64 LogicalAddress() const 133 { return B_LENDIAN_TO_HOST_INT64(logical_address); } 134 uint64 Generation() const 135 { return B_LENDIAN_TO_HOST_INT64(generation); } 136 137 void SetLogicalAddress(uint64 address) 138 { logical_address = B_HOST_TO_LENDIAN_INT64(address); } 139 void SetGeneration(uint64 gen) 140 { generation = B_HOST_TO_LENDIAN_INT64(gen); } 141 } _PACKED; 142 143 144 struct btrfs_entry { 145 btrfs_key key; 146 uint32 offset; 147 uint32 size; 148 uint32 Offset() const 149 { return B_LENDIAN_TO_HOST_INT32(offset); } 150 uint32 Size() const 151 { return B_LENDIAN_TO_HOST_INT32(size); } 152 void SetOffset(uint32 off) { offset = B_HOST_TO_LENDIAN_INT32(off); } 153 void SetSize(uint32 itemSize) { size = B_HOST_TO_LENDIAN_INT32(itemSize); } 154 } _PACKED; 155 156 157 struct btrfs_stream { 158 btrfs_header header; 159 union { 160 btrfs_entry entries[0]; 161 btrfs_index index[0]; 162 }; 163 } _PACKED; 164 165 166 struct btrfs_stripe { 167 uint64 device_id; 168 uint64 offset; 169 uuid_t device_uuid; 170 uint64 DeviceID() const { return B_LENDIAN_TO_HOST_INT64(device_id); } 171 uint64 Offset() const { return B_LENDIAN_TO_HOST_INT64(offset); } 172 } _PACKED; 173 174 175 struct btrfs_chunk { 176 uint64 length; 177 uint64 owner; 178 uint64 stripe_length; 179 uint64 type; 180 uint32 io_align; 181 uint32 io_width; 182 uint32 sector_size; 183 uint16 stripe_count; 184 uint16 sub_stripes; 185 btrfs_stripe stripes[0]; 186 uint64 Length() const { return B_LENDIAN_TO_HOST_INT64(length); } 187 uint64 Owner() const { return B_LENDIAN_TO_HOST_INT64(owner); } 188 uint64 StripeLength() const 189 { return B_LENDIAN_TO_HOST_INT64(stripe_length); } 190 uint64 Type() const { return B_LENDIAN_TO_HOST_INT64(type); } 191 uint32 IOAlign() const { return B_LENDIAN_TO_HOST_INT32(io_align); } 192 uint32 IOWidth() const { return B_LENDIAN_TO_HOST_INT32(io_width); } 193 uint32 SectorSize() const 194 { return B_LENDIAN_TO_HOST_INT32(sector_size); } 195 uint16 StripeCount() const 196 { return B_LENDIAN_TO_HOST_INT16(stripe_count); } 197 uint16 SubStripes() const 198 { return B_LENDIAN_TO_HOST_INT16(sub_stripes); } 199 } _PACKED; 200 201 202 struct btrfs_device { 203 uint64 id; 204 uint64 total_size; 205 uint64 used_size; 206 uint32 io_align; 207 uint32 io_width; 208 uint32 sector_size; 209 uint64 type; 210 uint64 generation; 211 uint64 start_offset; 212 uint32 group; 213 uint8 seek_speed; 214 uint8 bandwidth; 215 uuid_t uuid; 216 uuid_t fsid; 217 } _PACKED; 218 219 220 struct btrfs_super_block { 221 uint8 checksum[32]; 222 uuid_t fsid; 223 uint64 blocknum; 224 uint64 flags; 225 char magic[8]; 226 uint64 generation; 227 uint64 root; 228 uint64 chunk_root; 229 uint64 log_root; 230 uint64 log_root_transaction_id; 231 uint64 total_size; 232 uint64 used_size; 233 uint64 root_dir_object_id; 234 uint64 num_devices; 235 uint32 sector_size; 236 uint32 node_size; 237 uint32 leaf_size; 238 uint32 stripe_size; 239 uint32 system_chunk_array_size; 240 uint64 chunk_root_generation; 241 uint64 compat_flags; 242 uint64 readonly_flags; 243 uint64 incompat_flags; 244 uint16 checksum_type; 245 uint8 root_level; 246 uint8 chunk_root_level; 247 uint8 log_root_level; 248 btrfs_device device; 249 char label[BTRFS_LABEL_SIZE]; 250 uint64 reserved[32]; 251 uint8 system_chunk_array[2048]; 252 btrfs_backup_roots backup_roots[BTRFS_NUM_ROOT_BACKUPS]; 253 254 // implemented in Volume.cpp: 255 bool IsValid() const; 256 void Initialize(const char* name, off_t numBlocks, 257 uint32 blockSize, uint32 sectorSize); 258 uint64 TotalSize() const { return B_LENDIAN_TO_HOST_INT64(total_size); } 259 uint32 BlockSize() const { return B_LENDIAN_TO_HOST_INT32(node_size); } 260 uint32 SectorSize() const { return B_LENDIAN_TO_HOST_INT32(sector_size); } 261 uint64 RootDirObjectID() const 262 { return B_LENDIAN_TO_HOST_INT64(root_dir_object_id); } 263 uint64 Generation() const 264 { return B_LENDIAN_TO_HOST_INT64(generation); } 265 uint64 Root() const 266 { return B_LENDIAN_TO_HOST_INT64(root); } 267 uint64 ChunkRoot() const 268 { return B_LENDIAN_TO_HOST_INT64(chunk_root); } 269 uint64 LogRoot() const 270 { return B_LENDIAN_TO_HOST_INT64(log_root); } 271 uint8 ChunkRootLevel() const { return chunk_root_level; } 272 } _PACKED; 273 274 275 struct btrfs_inode { 276 uint64 generation; 277 uint64 transaction_id; 278 uint64 size; 279 uint64 nbytes; 280 uint64 blockgroup; 281 uint32 num_links; 282 uint32 uid; 283 uint32 gid; 284 uint32 mode; 285 uint64 rdev; 286 uint64 flags; 287 uint64 sequence; 288 uint64 reserved[4]; 289 btrfs_timespec access_time; 290 btrfs_timespec change_time; 291 btrfs_timespec modification_time; 292 btrfs_timespec creation_time; 293 uint64 Generation() const { return B_LENDIAN_TO_HOST_INT64(generation); } 294 uint64 Size() const { return B_LENDIAN_TO_HOST_INT64(size); } 295 uint32 UserID() const { return B_LENDIAN_TO_HOST_INT32(uid); } 296 uint32 GroupID() const { return B_LENDIAN_TO_HOST_INT32(gid); } 297 uint32 Mode() const { return B_LENDIAN_TO_HOST_INT32(mode); } 298 uint64 Flags() const { return B_LENDIAN_TO_HOST_INT64(flags); } 299 uint64 Sequence() const { return B_LENDIAN_TO_HOST_INT64(sequence); } 300 static void _DecodeTime(struct timespec& timespec, 301 const btrfs_timespec& time) 302 { 303 timespec.tv_sec = B_LENDIAN_TO_HOST_INT64(time.seconds); 304 timespec.tv_nsec = B_LENDIAN_TO_HOST_INT32(time.nanoseconds); 305 } 306 void GetAccessTime(struct timespec& timespec) const 307 { _DecodeTime(timespec, access_time); } 308 void GetChangeTime(struct timespec& timespec) const 309 { _DecodeTime(timespec, change_time); } 310 void GetModificationTime(struct timespec& timespec) const 311 { _DecodeTime(timespec, modification_time); } 312 void GetCreationTime(struct timespec& timespec) const 313 { _DecodeTime(timespec, creation_time); } 314 static void SetTime(btrfs_timespec& time, const struct timespec& timespec) 315 { 316 time.seconds = B_HOST_TO_LENDIAN_INT64(timespec.tv_sec); 317 time.nanoseconds = B_HOST_TO_LENDIAN_INT64(timespec.tv_nsec); 318 } 319 } _PACKED; 320 321 322 struct btrfs_inode_ref { 323 uint64 index; 324 uint16 name_length; 325 uint8 name[]; 326 327 uint64 Index() const { return index; } 328 uint16 NameLength() const { return B_LENDIAN_TO_HOST_INT16(name_length); } 329 uint16 Length() const 330 { return sizeof(btrfs_inode_ref) + NameLength(); } 331 void SetName(const char* name, uint16 nameLength) 332 { 333 name_length = B_HOST_TO_LENDIAN_INT16(nameLength); 334 memcpy(this->name, name, nameLength); 335 } 336 } _PACKED; 337 338 339 struct btrfs_root { 340 btrfs_inode inode; 341 uint64 generation; 342 uint64 root_dirid; 343 uint64 logical_address; 344 uint64 limit_bytes; 345 uint64 used_bytes; 346 uint64 last_snapshot; 347 uint64 flags; 348 uint32 refs; 349 btrfs_key drop_progress; 350 uint8 drop_level; 351 uint8 level; 352 uint64 Generation() const 353 { return B_LENDIAN_TO_HOST_INT64(generation); } 354 uint64 LogicalAddress() const 355 { return B_LENDIAN_TO_HOST_INT64(logical_address); } 356 } _PACKED; 357 358 359 struct btrfs_dir_entry { 360 btrfs_key location; 361 uint64 transaction_id; 362 uint16 data_length; 363 uint16 name_length; 364 uint8 type; 365 uint8 name[]; 366 // if attribute data exists, it goes here 367 uint16 DataLength() const { return B_LENDIAN_TO_HOST_INT16(data_length); } 368 uint16 NameLength() const { return B_LENDIAN_TO_HOST_INT16(name_length); } 369 ino_t InodeID() const { return location.ObjectID(); } 370 uint16 Length() const 371 { return sizeof(*this) + NameLength() + DataLength(); } 372 void SetTransactionID(uint64 id) 373 { transaction_id = B_HOST_TO_LENDIAN_INT64(id); } 374 void SetAttributeData(void* data, uint16 dataLength) 375 { 376 data_length = B_HOST_TO_LENDIAN_INT16(dataLength); 377 if (data != NULL) 378 memcpy(&name[name_length], data, dataLength); 379 } 380 void SetName(const char* name, uint16 nameLength) 381 { 382 name_length = B_HOST_TO_LENDIAN_INT16(nameLength); 383 memcpy(this->name, name, nameLength); 384 } 385 } _PACKED; 386 387 388 struct btrfs_extent_data { 389 uint64 generation; 390 uint64 memory_size; 391 uint8 compression; 392 uint8 encryption; 393 uint16 reserved; 394 uint8 type; 395 union { 396 struct { 397 uint64 disk_offset; 398 uint64 disk_size; 399 uint64 extent_offset; 400 uint64 size; 401 }; 402 uint8 inline_data[0]; 403 }; 404 uint64 Generation() const 405 { return B_LENDIAN_TO_HOST_INT64(generation); } 406 uint64 MemoryBytes() const 407 { return B_LENDIAN_TO_HOST_INT64(memory_size); } 408 uint8 Compression() const { return compression; } 409 uint8 Type() const { return type; } 410 uint64 DiskOffset() const 411 { return B_LENDIAN_TO_HOST_INT64(disk_offset); } 412 uint64 DiskSize() const 413 { return B_LENDIAN_TO_HOST_INT64(disk_size); } 414 uint64 ExtentOffset() const 415 { return B_LENDIAN_TO_HOST_INT64(extent_offset); } 416 uint64 Size() const 417 { return B_LENDIAN_TO_HOST_INT64(size); } 418 } _PACKED; 419 420 421 struct btrfs_block_group { 422 uint64 used_space; 423 uint64 chunk_object_id; 424 uint64 flags; 425 426 uint64 UsedSpace() const { return B_LENDIAN_TO_HOST_INT64(used_space); } 427 uint64 ChunkObjectID() const 428 { return B_LENDIAN_TO_HOST_INT64(chunk_object_id); } 429 uint64 Flags() const { return B_LENDIAN_TO_HOST_INT64(flags); } 430 } _PACKED; 431 432 433 struct btrfs_extent { 434 uint64 refs; 435 uint64 generation; 436 uint64 flags; 437 438 uint64 RefCount() const { return B_LENDIAN_TO_HOST_INT64(refs); } 439 uint64 Generation() const { return B_LENDIAN_TO_HOST_INT64(generation); } 440 uint64 Flags() const { return B_LENDIAN_TO_HOST_INT64(flags); } 441 } _PACKED; 442 443 444 struct btrfs_extent_inline_ref { 445 uint8 type; 446 uint64 offset; 447 448 uint8 Type() const { return type; } 449 uint64 Offset() const { return B_LENDIAN_TO_HOST_INT64(offset); } 450 } _PACKED; 451 452 453 struct btrfs_extent_data_ref { 454 uint64 root_id; 455 uint64 inode_id; 456 uint64 offset; 457 uint32 ref_count; 458 459 uint64 RootID() const { return B_LENDIAN_TO_HOST_INT64(root_id); } 460 uint64 InodeID() const { return B_LENDIAN_TO_HOST_INT64(inode_id); } 461 uint64 Offset() const { return B_LENDIAN_TO_HOST_INT64(offset);} 462 uint32 RefCount() const { return B_LENDIAN_TO_HOST_INT32(ref_count); } 463 } _PACKED; 464 465 #define BTRFS_SUPER_BLOCK_MAGIC "_BHRfS_M" 466 #define BTRFS_SUPER_BLOCK_MAGIC_TEMPORARY "!BHRfS_M" 467 468 #define BTRFS_FIRST_SUBVOLUME 256 469 470 #define BTRFS_CSUM_TYPE_CRC32 0 471 472 #define BTRFS_OBJECT_ID_ROOT_TREE 1 473 #define BTRFS_OBJECT_ID_EXTENT_TREE 2 474 #define BTRFS_OBJECT_ID_CHUNK_TREE 3 475 #define BTRFS_OBJECT_ID_DEV_TREE 4 476 #define BTRFS_OBJECT_ID_FS_TREE 5 477 #define BTRFS_OBJECT_ID_ROOT_TREE_DIR 6 478 #define BTRFS_OBJECT_ID_CHECKSUM_TREE 7 479 #define BTRFS_OBJECT_ID_FIRST_CHUNK_TREE 256 480 481 #define BTRFS_KEY_TYPE_ANY 0 482 #define BTRFS_KEY_TYPE_INODE_ITEM 1 483 #define BTRFS_KEY_TYPE_INODE_REF 12 484 #define BTRFS_KEY_TYPE_XATTR_ITEM 24 485 #define BTRFS_KEY_TYPE_DIR_ITEM 84 486 #define BTRFS_KEY_TYPE_DIR_INDEX 96 487 #define BTRFS_KEY_TYPE_EXTENT_DATA 108 488 #define BTRFS_KEY_TYPE_ROOT_ITEM 132 489 #define BTRFS_KEY_TYPE_EXTENT_ITEM 168 490 #define BTRFS_KEY_TYPE_METADATA_ITEM 169 491 #define BTRFS_KEY_TYPE_EXTENT_DATA_REF 178 492 #define BTRFS_KEY_TYPE_BLOCKGROUP_ITEM 192 493 #define BTRFS_KEY_TYPE_CHUNK_ITEM 228 494 495 #define BTRFS_EXTENT_COMPRESS_NONE 0 496 #define BTRFS_EXTENT_COMPRESS_ZLIB 1 497 #define BTRFS_EXTENT_COMPRESS_LZO 2 498 #define BTRFS_EXTENT_DATA_INLINE 0 499 #define BTRFS_EXTENT_DATA_REGULAR 1 500 #define BTRFS_EXTENT_DATA_PRE 2 501 #define BTRFS_EXTENT_FLAG_DATA 1 502 #define BTRFS_EXTENT_FLAG_TREE_BLOCK 2 503 #define BTRFS_EXTENT_FLAG_ALLOCATED 4 504 505 #define BTRFS_BLOCKGROUP_FLAG_DATA 1 506 #define BTRFS_BLOCKGROUP_FLAG_SYSTEM 2 507 #define BTRFS_BLOCKGROUP_FLAG_METADATA 4 508 #define BTRFS_BLOCKGROUP_FLAG_RAID0 8 509 #define BTRFS_BLOCKGROUP_FLAG_RAID1 16 510 #define BTRFS_BLOCKGROUP_FLAG_DUP 32 511 #define BTRFS_BLOCKGROUP_FLAG_RAID10 64 512 #define BTRFS_BLOCKGROUP_FLAG_RAID5 128 513 #define BTRFS_BLOCKGROUP_FLAG_RAID6 256 514 #define BTRFS_BLOCKGROUP_FLAG_MASK 511 515 516 // d_type in struct dirent 517 #define BTRFS_FILETYPE_UNKNOWN 0 518 #define BTRFS_FILETYPE_REGULAR 1 519 #define BTRFS_FILETYPE_DIRECTORY 2 520 #define BTRFS_FILETYPE_CHRDEV 3 // character device 521 #define BTRFS_FILETYPE_BLKDEV 4 // block device 522 #define BTRFS_FILETYPE_FIFO 5 // fifo device 523 #define BTRFS_FILETYPE_SOCKET 6 524 #define BTRFS_FILETYPE_SYMLINK 7 525 #define BTRFS_FILETYPE_XATTR 8 // ondisk but not user-visible 526 527 528 struct file_cookie { 529 bigtime_t last_notification; 530 off_t last_size; 531 int open_mode; 532 }; 533 534 535 #define BTRFS_OPEN_MODE_USER_MASK 0x7fffffff 536 537 extern fs_volume_ops gBtrfsVolumeOps; 538 extern fs_vnode_ops gBtrfsVnodeOps; 539 540 541 #endif // BTRFS_H 542