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