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