1 /* Copyright (c) Mark Harmstone 2016-17 2 * 3 * This file is part of WinBtrfs. 4 * 5 * WinBtrfs is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public Licence as published by 7 * the Free Software Foundation, either version 3 of the Licence, or 8 * (at your option) any later version. 9 * 10 * WinBtrfs is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public Licence for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public Licence 16 * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */ 17 18 #pragma once 19 20 #ifndef __REACTOS__ 21 #undef _WIN32_WINNT 22 #undef NTDDI_VERSION 23 24 #define _WIN32_WINNT 0x0601 25 #define NTDDI_VERSION 0x06020000 // Win 8 26 #define _CRT_SECURE_NO_WARNINGS 27 #define _NO_CRT_STDIO_INLINE 28 #endif /* __REACTOS__ */ 29 30 #ifdef _MSC_VER 31 #pragma warning(push) 32 #pragma warning(disable:4163) 33 #pragma warning(disable:4311) 34 #pragma warning(disable:4312) 35 #else 36 #pragma GCC diagnostic push 37 #pragma GCC diagnostic ignored "-Wsign-compare" 38 #pragma GCC diagnostic ignored "-Wsign-conversion" 39 #endif 40 41 #include <ntifs.h> 42 #include <ntddk.h> 43 #ifdef __REACTOS__ 44 #include <ntdddisk.h> 45 #endif /* __REACTOS__ */ 46 #include <mountmgr.h> 47 #ifdef __REACTOS__ 48 #include <rtlfuncs.h> 49 #include <iotypes.h> 50 #include <pseh/pseh2.h> 51 #endif /* __REACTOS__ */ 52 #include <windef.h> 53 #include <wdm.h> 54 55 #ifdef _MSC_VER 56 #pragma warning(pop) 57 #else 58 #pragma GCC diagnostic pop 59 #endif 60 61 #include <stdio.h> 62 #include <stdarg.h> 63 #include <stddef.h> 64 #include <stdint.h> 65 #include <stdbool.h> 66 #include "btrfs.h" 67 #include "btrfsioctl.h" 68 69 #ifdef __REACTOS__ 70 C_ASSERT(sizeof(bool) == 1); 71 #endif 72 73 #ifdef _DEBUG 74 // #define DEBUG_FCB_REFCOUNTS 75 // #define DEBUG_LONG_MESSAGES 76 // #define DEBUG_FLUSH_TIMES 77 // #define DEBUG_CHUNK_LOCKS 78 // #define DEBUG_TRIM_EMULATION 79 #define DEBUG_PARANOID 80 #endif 81 82 #define UNUSED(x) (void)(x) 83 84 #define BTRFS_NODE_TYPE_CCB 0x2295 85 #define BTRFS_NODE_TYPE_FCB 0x2296 86 87 #define ALLOC_TAG 0x7442484D //'MHBt' 88 #define ALLOC_TAG_ZLIB 0x7A42484D //'MHBz' 89 90 #define UID_NOBODY 65534 91 #define GID_NOBODY 65534 92 93 #define EA_NTACL "security.NTACL" 94 #define EA_NTACL_HASH 0x45922146 95 96 #define EA_DOSATTRIB "user.DOSATTRIB" 97 #define EA_DOSATTRIB_HASH 0x914f9939 98 99 #define EA_REPARSE "user.reparse" 100 #define EA_REPARSE_HASH 0xfabad1fe 101 102 #define EA_EA "user.EA" 103 #define EA_EA_HASH 0x8270dd43 104 105 #define EA_CASE_SENSITIVE "user.casesensitive" 106 #define EA_CASE_SENSITIVE_HASH 0x1a9d97d4 107 108 #define EA_PROP_COMPRESSION "btrfs.compression" 109 #define EA_PROP_COMPRESSION_HASH 0x20ccdf69 110 111 #define MAX_EXTENT_SIZE 0x8000000 // 128 MB 112 #define COMPRESSED_EXTENT_SIZE 0x20000 // 128 KB 113 114 #define READ_AHEAD_GRANULARITY COMPRESSED_EXTENT_SIZE // really ought to be a multiple of COMPRESSED_EXTENT_SIZE 115 116 #ifndef IO_REPARSE_TAG_LX_SYMLINK 117 118 #define IO_REPARSE_TAG_LX_SYMLINK 0xa000001d 119 120 #define IO_REPARSE_TAG_AF_UNIX 0x80000023 121 #define IO_REPARSE_TAG_LX_FIFO 0x80000024 122 #define IO_REPARSE_TAG_LX_CHR 0x80000025 123 #define IO_REPARSE_TAG_LX_BLK 0x80000026 124 125 #endif 126 127 #define BTRFS_VOLUME_PREFIX L"\\Device\\Btrfs{" 128 129 #if defined(_MSC_VER) || defined(__clang__) 130 #define try __try 131 #define except __except 132 #define finally __finally 133 #define leave __leave 134 #else 135 #define try if (1) 136 #define except(x) if (0 && (x)) 137 #define finally if (1) 138 #define leave 139 #endif 140 141 #ifndef __REACTOS__ 142 #ifndef InterlockedIncrement64 143 #define InterlockedIncrement64(a) __sync_add_and_fetch(a, 1) 144 #endif 145 #endif // __REACTOS__ 146 147 #ifndef FILE_SUPPORTS_BLOCK_REFCOUNTING 148 #define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000 149 #endif 150 151 #ifndef FILE_SUPPORTS_POSIX_UNLINK_RENAME 152 #define FILE_SUPPORTS_POSIX_UNLINK_RENAME 0x00000400 153 #endif 154 155 #ifndef FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL 156 #define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL 0x00020000 157 #endif 158 159 #ifndef __REACTOS__ 160 #ifndef _MSC_VER 161 typedef struct _FILE_ID_128 { 162 UCHAR Identifier[16]; 163 } FILE_ID_128, *PFILE_ID_128; 164 165 #define FILE_CS_FLAG_CASE_SENSITIVE_DIR 1 166 #endif 167 #else 168 typedef struct _FILE_ID_128 { 169 UCHAR Identifier[16]; 170 } FILE_ID_128, *PFILE_ID_128; 171 172 #define FILE_CS_FLAG_CASE_SENSITIVE_DIR 1 173 #endif // __REACTOS__ 174 175 typedef struct _DUPLICATE_EXTENTS_DATA { 176 HANDLE FileHandle; 177 LARGE_INTEGER SourceFileOffset; 178 LARGE_INTEGER TargetFileOffset; 179 LARGE_INTEGER ByteCount; 180 } DUPLICATE_EXTENTS_DATA, *PDUPLICATE_EXTENTS_DATA; 181 182 #define FSCTL_DUPLICATE_EXTENTS_TO_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 209, METHOD_BUFFERED, FILE_WRITE_ACCESS) 183 184 typedef struct _FSCTL_GET_INTEGRITY_INFORMATION_BUFFER { 185 WORD ChecksumAlgorithm; 186 WORD Reserved; 187 DWORD Flags; 188 DWORD ChecksumChunkSizeInBytes; 189 DWORD ClusterSizeInBytes; 190 } FSCTL_GET_INTEGRITY_INFORMATION_BUFFER, *PFSCTL_GET_INTEGRITY_INFORMATION_BUFFER; 191 192 typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER { 193 WORD ChecksumAlgorithm; 194 WORD Reserved; 195 DWORD Flags; 196 } FSCTL_SET_INTEGRITY_INFORMATION_BUFFER, *PFSCTL_SET_INTEGRITY_INFORMATION_BUFFER; 197 198 #define FSCTL_GET_INTEGRITY_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 159, METHOD_BUFFERED, FILE_ANY_ACCESS) 199 #define FSCTL_SET_INTEGRITY_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 160, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) 200 201 #ifndef __REACTOS__ 202 #ifndef _MSC_VER 203 #define __drv_aliasesMem 204 #define _Dispatch_type_(a) 205 #define _Lock_level_order_(a,b) 206 #endif 207 #endif // __REACTOS__ 208 209 _Create_lock_level_(tree_lock) 210 _Create_lock_level_(fcb_lock) 211 _Lock_level_order_(tree_lock, fcb_lock) 212 213 #define MAX_HASH_SIZE 32 214 215 struct _device_extension; 216 217 typedef struct _fcb_nonpaged { 218 FAST_MUTEX HeaderMutex; 219 SECTION_OBJECT_POINTERS segment_object; 220 ERESOURCE resource; 221 ERESOURCE paging_resource; 222 ERESOURCE dir_children_lock; 223 } fcb_nonpaged; 224 225 struct _root; 226 227 typedef struct { 228 uint64_t offset; 229 uint16_t datalen; 230 bool unique; 231 bool ignore; 232 bool inserted; 233 void* csum; 234 235 LIST_ENTRY list_entry; 236 237 EXTENT_DATA extent_data; 238 } extent; 239 240 typedef struct { 241 uint64_t parent; 242 uint64_t index; 243 UNICODE_STRING name; 244 ANSI_STRING utf8; 245 LIST_ENTRY list_entry; 246 } hardlink; 247 248 struct _file_ref; 249 250 typedef struct { 251 KEY key; 252 uint64_t index; 253 uint8_t type; 254 ANSI_STRING utf8; 255 uint32_t hash; 256 UNICODE_STRING name; 257 uint32_t hash_uc; 258 UNICODE_STRING name_uc; 259 ULONG size; 260 struct _file_ref* fileref; 261 bool root_dir; 262 LIST_ENTRY list_entry_index; 263 LIST_ENTRY list_entry_hash; 264 LIST_ENTRY list_entry_hash_uc; 265 } dir_child; 266 267 enum prop_compression_type { 268 PropCompression_None, 269 PropCompression_Zlib, 270 PropCompression_LZO, 271 PropCompression_ZSTD 272 }; 273 274 typedef struct { 275 LIST_ENTRY list_entry; 276 USHORT namelen; 277 USHORT valuelen; 278 bool dirty; 279 char data[1]; 280 } xattr; 281 282 typedef struct _fcb { 283 FSRTL_ADVANCED_FCB_HEADER Header; 284 struct _fcb_nonpaged* nonpaged; 285 LONG refcount; 286 POOL_TYPE pool_type; 287 struct _device_extension* Vcb; 288 struct _root* subvol; 289 uint64_t inode; 290 uint32_t hash; 291 uint8_t type; 292 INODE_ITEM inode_item; 293 SECURITY_DESCRIPTOR* sd; 294 FILE_LOCK lock; 295 bool deleted; 296 PKTHREAD lazy_writer_thread; 297 ULONG atts; 298 SHARE_ACCESS share_access; 299 bool csum_loaded; 300 LIST_ENTRY extents; 301 ANSI_STRING reparse_xattr; 302 ANSI_STRING ea_xattr; 303 ULONG ealen; 304 LIST_ENTRY hardlinks; 305 struct _file_ref* fileref; 306 bool inode_item_changed; 307 enum prop_compression_type prop_compression; 308 LIST_ENTRY xattrs; 309 bool marked_as_orphan; 310 bool case_sensitive; 311 bool case_sensitive_set; 312 OPLOCK oplock; 313 314 LIST_ENTRY dir_children_index; 315 LIST_ENTRY dir_children_hash; 316 LIST_ENTRY dir_children_hash_uc; 317 LIST_ENTRY** hash_ptrs; 318 LIST_ENTRY** hash_ptrs_uc; 319 320 bool dirty; 321 bool sd_dirty, sd_deleted; 322 bool atts_changed, atts_deleted; 323 bool extents_changed; 324 bool reparse_xattr_changed; 325 bool ea_changed; 326 bool prop_compression_changed; 327 bool xattrs_changed; 328 bool created; 329 330 bool ads; 331 uint32_t adshash; 332 ULONG adsmaxlen; 333 ANSI_STRING adsxattr; 334 ANSI_STRING adsdata; 335 336 LIST_ENTRY list_entry; 337 LIST_ENTRY list_entry_all; 338 LIST_ENTRY list_entry_dirty; 339 } fcb; 340 341 typedef struct _file_ref { 342 fcb* fcb; 343 ANSI_STRING oldutf8; 344 uint64_t oldindex; 345 bool delete_on_close; 346 bool posix_delete; 347 bool deleted; 348 bool created; 349 LIST_ENTRY children; 350 LONG refcount; 351 LONG open_count; 352 struct _file_ref* parent; 353 dir_child* dc; 354 355 bool dirty; 356 357 LIST_ENTRY list_entry; 358 LIST_ENTRY list_entry_dirty; 359 } file_ref; 360 361 typedef struct { 362 HANDLE thread; 363 struct _ccb* ccb; 364 void* context; 365 KEVENT cleared_event; 366 bool cancelling; 367 LIST_ENTRY list_entry; 368 } send_info; 369 370 typedef struct _ccb { 371 USHORT NodeType; 372 CSHORT NodeSize; 373 ULONG disposition; 374 ULONG options; 375 uint64_t query_dir_offset; 376 UNICODE_STRING query_string; 377 bool has_wildcard; 378 bool specific_file; 379 bool manage_volume_privilege; 380 bool allow_extended_dasd_io; 381 bool reserving; 382 ACCESS_MASK access; 383 file_ref* fileref; 384 UNICODE_STRING filename; 385 ULONG ea_index; 386 bool case_sensitive; 387 bool user_set_creation_time; 388 bool user_set_access_time; 389 bool user_set_write_time; 390 bool user_set_change_time; 391 bool lxss; 392 send_info* send; 393 NTSTATUS send_status; 394 } ccb; 395 396 struct _device_extension; 397 398 typedef struct { 399 uint64_t address; 400 uint64_t generation; 401 struct _tree* tree; 402 } tree_holder; 403 404 typedef struct _tree_data { 405 KEY key; 406 LIST_ENTRY list_entry; 407 bool ignore; 408 bool inserted; 409 410 union { 411 tree_holder treeholder; 412 413 struct { 414 uint16_t size; 415 uint8_t* data; 416 }; 417 }; 418 } tree_data; 419 420 typedef struct { 421 FAST_MUTEX mutex; 422 } tree_nonpaged; 423 424 typedef struct _tree { 425 tree_nonpaged* nonpaged; 426 tree_header header; 427 uint32_t hash; 428 bool has_address; 429 uint32_t size; 430 struct _device_extension* Vcb; 431 struct _tree* parent; 432 tree_data* paritem; 433 struct _root* root; 434 LIST_ENTRY itemlist; 435 LIST_ENTRY list_entry; 436 LIST_ENTRY list_entry_hash; 437 uint64_t new_address; 438 bool has_new_address; 439 bool updated_extents; 440 bool write; 441 bool is_unique; 442 bool uniqueness_determined; 443 uint8_t* buf; 444 } tree; 445 446 typedef struct { 447 ERESOURCE load_tree_lock; 448 } root_nonpaged; 449 450 typedef struct _root { 451 uint64_t id; 452 LONGLONG lastinode; // signed so we can use InterlockedIncrement64 453 tree_holder treeholder; 454 root_nonpaged* nonpaged; 455 ROOT_ITEM root_item; 456 bool dirty; 457 bool received; 458 PEPROCESS reserved; 459 uint64_t parent; 460 LONG send_ops; 461 uint64_t fcbs_version; 462 bool checked_for_orphans; 463 bool dropped; 464 LIST_ENTRY fcbs; 465 LIST_ENTRY* fcbs_ptrs[256]; 466 LIST_ENTRY list_entry; 467 LIST_ENTRY list_entry_dirty; 468 } root; 469 470 enum batch_operation { 471 Batch_Delete, 472 Batch_DeleteInode, 473 Batch_DeleteDirItem, 474 Batch_DeleteInodeRef, 475 Batch_DeleteInodeExtRef, 476 Batch_DeleteXattr, 477 Batch_DeleteExtentData, 478 Batch_DeleteFreeSpace, 479 Batch_Insert, 480 Batch_SetXattr, 481 Batch_DirItem, 482 Batch_InodeRef, 483 Batch_InodeExtRef, 484 }; 485 486 typedef struct { 487 KEY key; 488 void* data; 489 uint16_t datalen; 490 enum batch_operation operation; 491 LIST_ENTRY list_entry; 492 } batch_item; 493 494 typedef struct { 495 KEY key; 496 LIST_ENTRY items; 497 unsigned int num_items; 498 LIST_ENTRY list_entry; 499 } batch_item_ind; 500 501 typedef struct { 502 root* r; 503 LIST_ENTRY items_ind; 504 LIST_ENTRY list_entry; 505 } batch_root; 506 507 typedef struct { 508 tree* tree; 509 tree_data* item; 510 } traverse_ptr; 511 512 typedef struct _root_cache { 513 root* root; 514 struct _root_cache* next; 515 } root_cache; 516 517 typedef struct { 518 uint64_t address; 519 uint64_t size; 520 LIST_ENTRY list_entry; 521 LIST_ENTRY list_entry_size; 522 } space; 523 524 typedef struct { 525 PDEVICE_OBJECT devobj; 526 PFILE_OBJECT fileobj; 527 DEV_ITEM devitem; 528 bool removable; 529 bool seeding; 530 bool readonly; 531 bool reloc; 532 bool trim; 533 bool can_flush; 534 ULONG change_count; 535 ULONG disk_num; 536 ULONG part_num; 537 uint64_t stats[5]; 538 bool stats_changed; 539 LIST_ENTRY space; 540 LIST_ENTRY list_entry; 541 ULONG num_trim_entries; 542 LIST_ENTRY trim_list; 543 } device; 544 545 typedef struct { 546 uint64_t start; 547 uint64_t length; 548 PETHREAD thread; 549 LIST_ENTRY list_entry; 550 } range_lock; 551 552 typedef struct { 553 uint64_t address; 554 ULONG* bmparr; 555 ULONG bmplen; 556 RTL_BITMAP bmp; 557 LIST_ENTRY list_entry; 558 uint8_t data[1]; 559 } partial_stripe; 560 561 typedef struct { 562 CHUNK_ITEM* chunk_item; 563 uint16_t size; 564 uint64_t offset; 565 uint64_t used; 566 uint64_t oldused; 567 device** devices; 568 fcb* cache; 569 fcb* old_cache; 570 LIST_ENTRY space; 571 LIST_ENTRY space_size; 572 LIST_ENTRY deleting; 573 LIST_ENTRY changed_extents; 574 LIST_ENTRY range_locks; 575 ERESOURCE range_locks_lock; 576 KEVENT range_locks_event; 577 ERESOURCE lock; 578 ERESOURCE changed_extents_lock; 579 bool created; 580 bool readonly; 581 bool reloc; 582 bool last_alloc_set; 583 bool cache_loaded; 584 bool changed; 585 bool space_changed; 586 uint64_t last_alloc; 587 uint16_t last_stripe; 588 LIST_ENTRY partial_stripes; 589 ERESOURCE partial_stripes_lock; 590 ULONG balance_num; 591 592 LIST_ENTRY list_entry; 593 LIST_ENTRY list_entry_balance; 594 } chunk; 595 596 typedef struct { 597 uint64_t address; 598 uint64_t size; 599 uint64_t old_size; 600 uint64_t count; 601 uint64_t old_count; 602 bool no_csum; 603 bool superseded; 604 LIST_ENTRY refs; 605 LIST_ENTRY old_refs; 606 LIST_ENTRY list_entry; 607 } changed_extent; 608 609 typedef struct { 610 uint8_t type; 611 612 union { 613 EXTENT_DATA_REF edr; 614 SHARED_DATA_REF sdr; 615 }; 616 617 LIST_ENTRY list_entry; 618 } changed_extent_ref; 619 620 typedef struct { 621 KEY key; 622 void* data; 623 USHORT size; 624 LIST_ENTRY list_entry; 625 } sys_chunk; 626 627 enum calc_thread_type { 628 calc_thread_crc32c, 629 calc_thread_xxhash, 630 calc_thread_sha256, 631 calc_thread_blake2, 632 calc_thread_decomp_zlib, 633 calc_thread_decomp_lzo, 634 calc_thread_decomp_zstd, 635 calc_thread_comp_zlib, 636 calc_thread_comp_lzo, 637 calc_thread_comp_zstd, 638 }; 639 640 typedef struct { 641 LIST_ENTRY list_entry; 642 void* in; 643 void* out; 644 unsigned int inlen, outlen, off, space_left; 645 LONG left, not_started; 646 KEVENT event; 647 enum calc_thread_type type; 648 NTSTATUS Status; 649 } calc_job; 650 651 typedef struct { 652 PDEVICE_OBJECT DeviceObject; 653 HANDLE handle; 654 KEVENT finished; 655 unsigned int number; 656 bool quit; 657 } drv_calc_thread; 658 659 typedef struct { 660 ULONG num_threads; 661 LIST_ENTRY job_list; 662 KSPIN_LOCK spinlock; 663 drv_calc_thread* threads; 664 KEVENT event; 665 } drv_calc_threads; 666 667 typedef struct { 668 bool ignore; 669 bool compress; 670 bool compress_force; 671 uint8_t compress_type; 672 bool readonly; 673 uint32_t zlib_level; 674 uint32_t zstd_level; 675 uint32_t flush_interval; 676 uint32_t max_inline; 677 uint64_t subvol_id; 678 bool skip_balance; 679 bool no_barrier; 680 bool no_trim; 681 bool clear_cache; 682 bool allow_degraded; 683 bool no_root_dir; 684 bool nodatacow; 685 } mount_options; 686 687 #define VCB_TYPE_FS 1 688 #define VCB_TYPE_CONTROL 2 689 #define VCB_TYPE_VOLUME 3 690 #define VCB_TYPE_PDO 4 691 #define VCB_TYPE_BUS 5 692 693 #define BALANCE_OPTS_DATA 0 694 #define BALANCE_OPTS_METADATA 1 695 #define BALANCE_OPTS_SYSTEM 2 696 697 typedef struct { 698 HANDLE thread; 699 uint64_t total_chunks; 700 uint64_t chunks_left; 701 btrfs_balance_opts opts[3]; 702 bool paused; 703 bool stopping; 704 bool removing; 705 bool shrinking; 706 bool dev_readonly; 707 ULONG balance_num; 708 NTSTATUS status; 709 KEVENT event; 710 KEVENT finished; 711 } balance_info; 712 713 typedef struct { 714 uint64_t address; 715 uint64_t device; 716 bool recovered; 717 bool is_metadata; 718 bool parity; 719 LIST_ENTRY list_entry; 720 721 union { 722 struct { 723 uint64_t subvol; 724 uint64_t offset; 725 uint16_t filename_length; 726 WCHAR filename[1]; 727 } data; 728 729 struct { 730 uint64_t root; 731 uint8_t level; 732 KEY firstitem; 733 } metadata; 734 }; 735 } scrub_error; 736 737 typedef struct { 738 HANDLE thread; 739 ERESOURCE stats_lock; 740 KEVENT event; 741 KEVENT finished; 742 bool stopping; 743 bool paused; 744 LARGE_INTEGER start_time; 745 LARGE_INTEGER finish_time; 746 LARGE_INTEGER resume_time; 747 LARGE_INTEGER duration; 748 uint64_t total_chunks; 749 uint64_t chunks_left; 750 uint64_t data_scrubbed; 751 NTSTATUS error; 752 ULONG num_errors; 753 LIST_ENTRY errors; 754 } scrub_info; 755 756 struct _volume_device_extension; 757 758 typedef struct _device_extension { 759 uint32_t type; 760 mount_options options; 761 PVPB Vpb; 762 PDEVICE_OBJECT devobj; 763 struct _volume_device_extension* vde; 764 LIST_ENTRY devices; 765 #ifdef DEBUG_CHUNK_LOCKS 766 LONG chunk_locks_held; 767 #endif 768 uint64_t devices_loaded; 769 superblock superblock; 770 unsigned int sector_shift; 771 unsigned int csum_size; 772 bool readonly; 773 bool removing; 774 bool locked; 775 bool lock_paused_balance; 776 bool disallow_dismount; 777 LONG page_file_count; 778 bool trim; 779 PFILE_OBJECT locked_fileobj; 780 fcb* volume_fcb; 781 fcb* dummy_fcb; 782 file_ref* root_fileref; 783 LONG open_files; 784 _Has_lock_level_(fcb_lock) ERESOURCE fcb_lock; 785 ERESOURCE fileref_lock; 786 ERESOURCE load_lock; 787 _Has_lock_level_(tree_lock) ERESOURCE tree_lock; 788 PNOTIFY_SYNC NotifySync; 789 LIST_ENTRY DirNotifyList; 790 bool need_write; 791 bool stats_changed; 792 uint64_t data_flags; 793 uint64_t metadata_flags; 794 uint64_t system_flags; 795 LIST_ENTRY roots; 796 LIST_ENTRY drop_roots; 797 root* chunk_root; 798 root* root_root; 799 root* extent_root; 800 root* checksum_root; 801 root* dev_root; 802 root* uuid_root; 803 root* data_reloc_root; 804 root* space_root; 805 bool log_to_phys_loaded; 806 bool chunk_usage_found; 807 LIST_ENTRY sys_chunks; 808 LIST_ENTRY chunks; 809 LIST_ENTRY trees; 810 LIST_ENTRY trees_hash; 811 LIST_ENTRY* trees_ptrs[256]; 812 FAST_MUTEX trees_list_mutex; 813 LIST_ENTRY all_fcbs; 814 LIST_ENTRY dirty_fcbs; 815 ERESOURCE dirty_fcbs_lock; 816 LIST_ENTRY dirty_filerefs; 817 ERESOURCE dirty_filerefs_lock; 818 LIST_ENTRY dirty_subvols; 819 ERESOURCE dirty_subvols_lock; 820 ERESOURCE chunk_lock; 821 HANDLE flush_thread_handle; 822 KTIMER flush_thread_timer; 823 KEVENT flush_thread_finished; 824 drv_calc_threads calcthreads; 825 balance_info balance; 826 scrub_info scrub; 827 ERESOURCE send_load_lock; 828 LONG running_sends; 829 LIST_ENTRY send_ops; 830 PFILE_OBJECT root_file; 831 PAGED_LOOKASIDE_LIST tree_data_lookaside; 832 PAGED_LOOKASIDE_LIST traverse_ptr_lookaside; 833 PAGED_LOOKASIDE_LIST batch_item_lookaside; 834 PAGED_LOOKASIDE_LIST fileref_lookaside; 835 PAGED_LOOKASIDE_LIST fcb_lookaside; 836 PAGED_LOOKASIDE_LIST name_bit_lookaside; 837 NPAGED_LOOKASIDE_LIST range_lock_lookaside; 838 NPAGED_LOOKASIDE_LIST fcb_np_lookaside; 839 LIST_ENTRY list_entry; 840 } device_extension; 841 842 typedef struct { 843 uint32_t type; 844 } control_device_extension; 845 846 typedef struct { 847 uint32_t type; 848 PDEVICE_OBJECT buspdo; 849 PDEVICE_OBJECT attached_device; 850 UNICODE_STRING bus_name; 851 } bus_device_extension; 852 853 typedef struct { 854 BTRFS_UUID uuid; 855 uint64_t devid; 856 uint64_t generation; 857 PDEVICE_OBJECT devobj; 858 PFILE_OBJECT fileobj; 859 UNICODE_STRING pnp_name; 860 uint64_t size; 861 bool seeding; 862 bool had_drive_letter; 863 void* notification_entry; 864 ULONG disk_num; 865 ULONG part_num; 866 bool boot_volume; 867 LIST_ENTRY list_entry; 868 } volume_child; 869 870 struct pdo_device_extension; 871 872 typedef struct _volume_device_extension { 873 uint32_t type; 874 UNICODE_STRING name; 875 PDEVICE_OBJECT device; 876 PDEVICE_OBJECT mounted_device; 877 PDEVICE_OBJECT pdo; 878 struct pdo_device_extension* pdode; 879 UNICODE_STRING bus_name; 880 PDEVICE_OBJECT attached_device; 881 bool removing; 882 bool dead; 883 LONG open_count; 884 } volume_device_extension; 885 886 typedef struct pdo_device_extension { 887 uint32_t type; 888 BTRFS_UUID uuid; 889 volume_device_extension* vde; 890 PDEVICE_OBJECT pdo; 891 bool removable; 892 bool dont_report; 893 894 uint64_t num_children; 895 uint64_t children_loaded; 896 ERESOURCE child_lock; 897 LIST_ENTRY children; 898 899 LIST_ENTRY list_entry; 900 } pdo_device_extension; 901 902 typedef struct { 903 LIST_ENTRY listentry; 904 PSID sid; 905 uint32_t uid; 906 } uid_map; 907 908 typedef struct { 909 LIST_ENTRY listentry; 910 PSID sid; 911 uint32_t gid; 912 } gid_map; 913 914 enum write_data_status { 915 WriteDataStatus_Pending, 916 WriteDataStatus_Success, 917 WriteDataStatus_Error, 918 WriteDataStatus_Cancelling, 919 WriteDataStatus_Cancelled, 920 WriteDataStatus_Ignore 921 }; 922 923 struct _write_data_context; 924 925 typedef struct { 926 struct _write_data_context* context; 927 uint8_t* buf; 928 PMDL mdl; 929 device* device; 930 PIRP Irp; 931 IO_STATUS_BLOCK iosb; 932 enum write_data_status status; 933 LIST_ENTRY list_entry; 934 } write_data_stripe; 935 936 typedef struct _write_data_context { 937 KEVENT Event; 938 LIST_ENTRY stripes; 939 LONG stripes_left; 940 bool need_wait; 941 uint8_t *parity1, *parity2, *scratch; 942 PMDL mdl, parity1_mdl, parity2_mdl; 943 } write_data_context; 944 945 typedef struct { 946 uint64_t address; 947 uint32_t length; 948 uint8_t* data; 949 chunk* c; 950 bool allocated; 951 LIST_ENTRY list_entry; 952 } tree_write; 953 954 typedef struct { 955 UNICODE_STRING us; 956 LIST_ENTRY list_entry; 957 } name_bit; 958 959 _Requires_lock_not_held_(Vcb->fcb_lock) 960 _Acquires_shared_lock_(Vcb->fcb_lock) 961 static __inline void acquire_fcb_lock_shared(device_extension* Vcb) { 962 ExAcquireResourceSharedLite(&Vcb->fcb_lock, true); 963 } 964 965 _Requires_lock_not_held_(Vcb->fcb_lock) 966 _Acquires_exclusive_lock_(Vcb->fcb_lock) 967 static __inline void acquire_fcb_lock_exclusive(device_extension* Vcb) { 968 ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, true); 969 } 970 971 _Requires_lock_held_(Vcb->fcb_lock) 972 _Releases_lock_(Vcb->fcb_lock) 973 static __inline void release_fcb_lock(device_extension* Vcb) { 974 ExReleaseResourceLite(&Vcb->fcb_lock); 975 } 976 977 static __inline void* map_user_buffer(PIRP Irp, ULONG priority) { 978 if (!Irp->MdlAddress) { 979 return Irp->UserBuffer; 980 } else { 981 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, priority); 982 } 983 } 984 985 static __inline uint64_t unix_time_to_win(BTRFS_TIME* t) { 986 return (t->seconds * 10000000) + (t->nanoseconds / 100) + 116444736000000000; 987 } 988 989 static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME* out) { 990 ULONGLONG l = (ULONGLONG)t.QuadPart - 116444736000000000; 991 992 out->seconds = l / 10000000; 993 out->nanoseconds = (uint32_t)((l % 10000000) * 100); 994 } 995 996 _Post_satisfies_(*stripe>=0&&*stripe<num_stripes) 997 static __inline void get_raid0_offset(_In_ uint64_t off, _In_ uint64_t stripe_length, _In_ uint16_t num_stripes, _Out_ uint64_t* stripeoff, _Out_ uint16_t* stripe) { 998 uint64_t initoff, startoff; 999 1000 startoff = off % (num_stripes * stripe_length); 1001 initoff = (off / (num_stripes * stripe_length)) * stripe_length; 1002 1003 *stripe = (uint16_t)(startoff / stripe_length); 1004 *stripeoff = initoff + startoff - (*stripe * stripe_length); 1005 } 1006 1007 /* We only have 64 bits for a file ID, which isn't technically enough to be 1008 * unique on Btrfs. We fudge it by having three bytes for the subvol and 1009 * five for the inode, which should be good enough. 1010 * Inodes are also 64 bits on Linux, but the Linux driver seems to get round 1011 * this by tricking it into thinking subvols are separate volumes. */ 1012 static __inline uint64_t make_file_id(root* r, uint64_t inode) { 1013 return (r->id << 40) | (inode & 0xffffffffff); 1014 } 1015 1016 #define keycmp(key1, key2)\ 1017 ((key1.obj_id < key2.obj_id) ? -1 :\ 1018 ((key1.obj_id > key2.obj_id) ? 1 :\ 1019 ((key1.obj_type < key2.obj_type) ? -1 :\ 1020 ((key1.obj_type > key2.obj_type) ? 1 :\ 1021 ((key1.offset < key2.offset) ? -1 :\ 1022 ((key1.offset > key2.offset) ? 1 :\ 1023 0)))))) 1024 1025 _Post_satisfies_(return>=n) 1026 __inline static uint64_t sector_align(_In_ uint64_t n, _In_ uint64_t a) { 1027 if (n & (a - 1)) 1028 n = (n + a) & ~(a - 1); 1029 1030 return n; 1031 } 1032 1033 __inline static bool is_subvol_readonly(root* r, PIRP Irp) { 1034 if (!(r->root_item.flags & BTRFS_SUBVOL_READONLY)) 1035 return false; 1036 1037 if (!r->reserved) 1038 return true; 1039 1040 return (!Irp || Irp->RequestorMode == UserMode) && PsGetCurrentProcess() != r->reserved ? true : false; 1041 } 1042 1043 __inline static uint16_t get_extent_data_len(uint8_t type) { 1044 switch (type) { 1045 case TYPE_TREE_BLOCK_REF: 1046 return sizeof(TREE_BLOCK_REF); 1047 1048 case TYPE_EXTENT_DATA_REF: 1049 return sizeof(EXTENT_DATA_REF); 1050 1051 case TYPE_EXTENT_REF_V0: 1052 return sizeof(EXTENT_REF_V0); 1053 1054 case TYPE_SHARED_BLOCK_REF: 1055 return sizeof(SHARED_BLOCK_REF); 1056 1057 case TYPE_SHARED_DATA_REF: 1058 return sizeof(SHARED_DATA_REF); 1059 1060 default: 1061 return 0; 1062 } 1063 } 1064 1065 __inline static uint32_t get_extent_data_refcount(uint8_t type, void* data) { 1066 switch (type) { 1067 case TYPE_TREE_BLOCK_REF: 1068 return 1; 1069 1070 case TYPE_EXTENT_DATA_REF: 1071 { 1072 EXTENT_DATA_REF* edr = (EXTENT_DATA_REF*)data; 1073 return edr->count; 1074 } 1075 1076 case TYPE_EXTENT_REF_V0: 1077 { 1078 EXTENT_REF_V0* erv0 = (EXTENT_REF_V0*)data; 1079 return erv0->count; 1080 } 1081 1082 case TYPE_SHARED_BLOCK_REF: 1083 return 1; 1084 1085 case TYPE_SHARED_DATA_REF: 1086 { 1087 SHARED_DATA_REF* sdr = (SHARED_DATA_REF*)data; 1088 return sdr->count; 1089 } 1090 1091 default: 1092 return 0; 1093 } 1094 } 1095 1096 // in xor-gas.S 1097 #if defined(_X86_) || defined(_AMD64_) 1098 void __stdcall do_xor_sse2(uint8_t* buf1, uint8_t* buf2, uint32_t len); 1099 void __stdcall do_xor_avx2(uint8_t* buf1, uint8_t* buf2, uint32_t len); 1100 #endif 1101 1102 // in btrfs.c 1103 _Ret_maybenull_ 1104 device* find_device_from_uuid(_In_ device_extension* Vcb, _In_ BTRFS_UUID* uuid); 1105 1106 _Success_(return) 1107 bool get_file_attributes_from_xattr(_In_reads_bytes_(len) char* val, _In_ uint16_t len, _Out_ ULONG* atts); 1108 1109 ULONG get_file_attributes(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ root* r, _In_ uint64_t inode, 1110 _In_ uint8_t type, _In_ bool dotfile, _In_ bool ignore_xa, _In_opt_ PIRP Irp); 1111 1112 _Success_(return) 1113 bool get_xattr(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ root* subvol, _In_ uint64_t inode, _In_z_ char* name, _In_ uint32_t crc32, 1114 _Out_ uint8_t** data, _Out_ uint16_t* datalen, _In_opt_ PIRP Irp); 1115 1116 #ifndef DEBUG_FCB_REFCOUNTS 1117 void free_fcb(_Inout_ fcb* fcb); 1118 #endif 1119 void free_fileref(_Inout_ file_ref* fr); 1120 void protect_superblocks(_Inout_ chunk* c); 1121 bool is_top_level(_In_ PIRP Irp); 1122 NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ uint64_t id, 1123 _Out_ root** rootptr, _In_ bool no_tree, _In_ uint64_t offset, _In_opt_ PIRP Irp); 1124 void uninit(_In_ device_extension* Vcb); 1125 NTSTATUS dev_ioctl(_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG ControlCode, _In_reads_bytes_opt_(InputBufferSize) PVOID InputBuffer, _In_ ULONG InputBufferSize, 1126 _Out_writes_bytes_opt_(OutputBufferSize) PVOID OutputBuffer, _In_ ULONG OutputBufferSize, _In_ bool Override, _Out_opt_ IO_STATUS_BLOCK* iosb); 1127 NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream); 1128 void send_notification_fileref(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream); 1129 void queue_notification_fcb(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream); 1130 1131 typedef void (__stdcall *xor_func)(uint8_t* buf1, uint8_t* buf2, uint32_t len); 1132 1133 extern xor_func do_xor; 1134 1135 #ifdef DEBUG_CHUNK_LOCKS 1136 #define acquire_chunk_lock(c, Vcb) { ExAcquireResourceExclusiveLite(&c->lock, true); InterlockedIncrement(&Vcb->chunk_locks_held); } 1137 #define release_chunk_lock(c, Vcb) { InterlockedDecrement(&Vcb->chunk_locks_held); ExReleaseResourceLite(&c->lock); } 1138 #else 1139 #define acquire_chunk_lock(c, Vcb) ExAcquireResourceExclusiveLite(&(c)->lock, true) 1140 #define release_chunk_lock(c, Vcb) ExReleaseResourceLite(&(c)->lock) 1141 #endif 1142 1143 void mark_fcb_dirty(_In_ fcb* fcb); 1144 void mark_fileref_dirty(_In_ file_ref* fileref); 1145 NTSTATUS delete_fileref(_In_ file_ref* fileref, _In_opt_ PFILE_OBJECT FileObject, _In_ bool make_orphan, _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback); 1146 void chunk_lock_range(_In_ device_extension* Vcb, _In_ chunk* c, _In_ uint64_t start, _In_ uint64_t length); 1147 void chunk_unlock_range(_In_ device_extension* Vcb, _In_ chunk* c, _In_ uint64_t start, _In_ uint64_t length); 1148 void init_device(_In_ device_extension* Vcb, _Inout_ device* dev, _In_ bool get_nums); 1149 void init_file_cache(_In_ PFILE_OBJECT FileObject, _In_ CC_FILE_SIZES* ccfs); 1150 NTSTATUS sync_read_phys(_In_ PDEVICE_OBJECT DeviceObject, _In_ PFILE_OBJECT FileObject, _In_ uint64_t StartingOffset, _In_ ULONG Length, 1151 _Out_writes_bytes_(Length) PUCHAR Buffer, _In_ bool override); 1152 NTSTATUS get_device_pnp_name(_In_ PDEVICE_OBJECT DeviceObject, _Out_ PUNICODE_STRING pnp_name, _Out_ const GUID** guid); 1153 void log_device_error(_In_ device_extension* Vcb, _Inout_ device* dev, _In_ int error); 1154 NTSTATUS find_chunk_usage(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_opt_ PIRP Irp); 1155 1156 _Function_class_(DRIVER_ADD_DEVICE) 1157 NTSTATUS __stdcall AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject); 1158 1159 void reap_fcb(fcb* fcb); 1160 void reap_fcbs(device_extension* Vcb); 1161 void reap_fileref(device_extension* Vcb, file_ref* fr); 1162 void reap_filerefs(device_extension* Vcb, file_ref* fr); 1163 NTSTATUS utf8_to_utf16(WCHAR* dest, ULONG dest_max, ULONG* dest_len, char* src, ULONG src_len); 1164 NTSTATUS utf16_to_utf8(char* dest, ULONG dest_max, ULONG* dest_len, WCHAR* src, ULONG src_len); 1165 uint32_t get_num_of_processors(); 1166 1167 _Ret_maybenull_ 1168 root* find_default_subvol(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_opt_ PIRP Irp); 1169 1170 void do_shutdown(PIRP Irp); 1171 bool check_superblock_checksum(superblock* sb); 1172 1173 #ifdef _MSC_VER 1174 #define funcname __FUNCTION__ 1175 #else 1176 #define funcname __func__ 1177 #endif 1178 1179 extern uint32_t mount_compress; 1180 extern uint32_t mount_compress_force; 1181 extern uint32_t mount_compress_type; 1182 extern uint32_t mount_zlib_level; 1183 extern uint32_t mount_zstd_level; 1184 extern uint32_t mount_flush_interval; 1185 extern uint32_t mount_max_inline; 1186 extern uint32_t mount_skip_balance; 1187 extern uint32_t mount_no_barrier; 1188 extern uint32_t mount_no_trim; 1189 extern uint32_t mount_clear_cache; 1190 extern uint32_t mount_allow_degraded; 1191 extern uint32_t mount_readonly; 1192 extern uint32_t mount_no_root_dir; 1193 extern uint32_t mount_nodatacow; 1194 extern uint32_t no_pnp; 1195 1196 #ifndef __GNUC__ 1197 #define __attribute__(x) 1198 #endif 1199 1200 #ifdef _DEBUG 1201 1202 extern bool log_started; 1203 extern uint32_t debug_log_level; 1204 1205 #ifdef DEBUG_LONG_MESSAGES 1206 1207 #define MSG(fn, file, line, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, file, line, s, ##__VA_ARGS__) : (void)0 1208 1209 #define TRACE(s, ...) MSG(funcname, __FILE__, __LINE__, s, 3, ##__VA_ARGS__) 1210 #define WARN(s, ...) MSG(funcname, __FILE__, __LINE__, s, 2, ##__VA_ARGS__) 1211 #define FIXME(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__) 1212 #define ERR(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__) 1213 1214 void _debug_message(_In_ const char* func, _In_ const char* file, _In_ unsigned int line, _In_ char* s, ...) __attribute__((format(printf, 4, 5))); 1215 1216 #else 1217 1218 #define MSG(fn, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, s, ##__VA_ARGS__) : (void)0 1219 1220 #define TRACE(s, ...) MSG(funcname, s, 3, ##__VA_ARGS__) 1221 #define WARN(s, ...) MSG(funcname, s, 2, ##__VA_ARGS__) 1222 #define FIXME(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__) 1223 #define ERR(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__) 1224 1225 void _debug_message(_In_ const char* func, _In_ char* s, ...) __attribute__((format(printf, 2, 3))); 1226 1227 #endif 1228 1229 #else 1230 1231 #define TRACE(s, ...) do { } while(0) 1232 #define WARN(s, ...) do { } while(0) 1233 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__) 1234 #define ERR(s, ...) DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__) 1235 1236 #endif 1237 1238 #ifdef DEBUG_FCB_REFCOUNTS 1239 void _free_fcb(_Inout_ fcb* fcb, _In_ const char* func); 1240 #define free_fcb(fcb) _free_fcb(fcb, funcname) 1241 #endif 1242 1243 // in fastio.c 1244 void init_fast_io_dispatch(FAST_IO_DISPATCH** fiod); 1245 1246 // in sha256.c 1247 void calc_sha256(uint8_t* hash, const void* input, size_t len); 1248 #define SHA256_HASH_SIZE 32 1249 1250 // in blake2b-ref.c 1251 void blake2b(void *out, size_t outlen, const void* in, size_t inlen); 1252 #define BLAKE2_HASH_SIZE 32 1253 1254 typedef struct { 1255 LIST_ENTRY* list; 1256 LIST_ENTRY* list_size; 1257 uint64_t address; 1258 uint64_t length; 1259 chunk* chunk; 1260 } rollback_space; 1261 1262 typedef struct { 1263 fcb* fcb; 1264 extent* ext; 1265 } rollback_extent; 1266 1267 enum rollback_type { 1268 ROLLBACK_INSERT_EXTENT, 1269 ROLLBACK_DELETE_EXTENT, 1270 ROLLBACK_ADD_SPACE, 1271 ROLLBACK_SUBTRACT_SPACE 1272 }; 1273 1274 typedef struct { 1275 enum rollback_type type; 1276 void* ptr; 1277 LIST_ENTRY list_entry; 1278 } rollback_item; 1279 1280 typedef struct { 1281 ANSI_STRING name; 1282 ANSI_STRING value; 1283 UCHAR flags; 1284 LIST_ENTRY list_entry; 1285 } ea_item; 1286 1287 static const char lxuid[] = "$LXUID"; 1288 static const char lxgid[] = "$LXGID"; 1289 static const char lxmod[] = "$LXMOD"; 1290 static const char lxdev[] = "$LXDEV"; 1291 1292 // in treefuncs.c 1293 NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ root* r, _Out_ traverse_ptr* tp, 1294 _In_ const KEY* searchkey, _In_ bool ignore, _In_opt_ PIRP Irp) __attribute__((nonnull(1,2,3,4))); 1295 NTSTATUS find_item_to_level(device_extension* Vcb, root* r, traverse_ptr* tp, const KEY* searchkey, bool ignore, 1296 uint8_t level, PIRP Irp) __attribute__((nonnull(1,2,3,4))); 1297 bool find_next_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, const traverse_ptr* tp, 1298 traverse_ptr* next_tp, bool ignore, PIRP Irp) __attribute__((nonnull(1,2,3))); 1299 bool find_prev_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, const traverse_ptr* tp, 1300 traverse_ptr* prev_tp, PIRP Irp) __attribute__((nonnull(1,2,3))); 1301 void free_trees(device_extension* Vcb) __attribute__((nonnull(1))); 1302 NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ root* r, _In_ uint64_t obj_id, 1303 _In_ uint8_t obj_type, _In_ uint64_t offset, _In_reads_bytes_opt_(size) _When_(return >= 0, __drv_aliasesMem) void* data, 1304 _In_ uint16_t size, _Out_opt_ traverse_ptr* ptp, _In_opt_ PIRP Irp) __attribute__((nonnull(1,2))); 1305 NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, 1306 _Inout_ traverse_ptr* tp) __attribute__((nonnull(1,2))); 1307 void free_tree(tree* t) __attribute__((nonnull(1))); 1308 NTSTATUS load_tree(device_extension* Vcb, uint64_t addr, uint8_t* buf, root* r, tree** pt) __attribute__((nonnull(1,3,4,5))); 1309 NTSTATUS do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, PIRP Irp) __attribute__((nonnull(1,2,3))); 1310 void clear_rollback(LIST_ENTRY* rollback) __attribute__((nonnull(1))); 1311 void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback) __attribute__((nonnull(1,2))); 1312 void free_trees_root(device_extension* Vcb, root* r) __attribute__((nonnull(1,2))); 1313 void add_rollback(_In_ LIST_ENTRY* rollback, _In_ enum rollback_type type, _In_ __drv_aliasesMem void* ptr) __attribute__((nonnull(1,3))); 1314 NTSTATUS commit_batch_list(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, 1315 LIST_ENTRY* batchlist, PIRP Irp) __attribute__((nonnull(1,2))); 1316 void clear_batch_list(device_extension* Vcb, LIST_ENTRY* batchlist) __attribute__((nonnull(1,2))); 1317 NTSTATUS skip_to_difference(device_extension* Vcb, traverse_ptr* tp, traverse_ptr* tp2, bool* ended1, bool* ended2) __attribute__((nonnull(1,2,3,4,5))); 1318 1319 // in search.c 1320 NTSTATUS remove_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath); 1321 1322 _Function_class_(KSTART_ROUTINE) 1323 void __stdcall mountmgr_thread(_In_ void* context); 1324 1325 _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE) 1326 NTSTATUS __stdcall pnp_notification(PVOID NotificationStructure, PVOID Context); 1327 1328 void disk_arrival(PUNICODE_STRING devpath); 1329 bool volume_arrival(PUNICODE_STRING devpath, bool fve_callback); 1330 void volume_removal(PUNICODE_STRING devpath); 1331 1332 _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE) 1333 NTSTATUS __stdcall volume_notification(PVOID NotificationStructure, PVOID Context); 1334 1335 void remove_volume_child(_Inout_ _Requires_exclusive_lock_held_(_Curr_->child_lock) _Releases_exclusive_lock_(_Curr_->child_lock) _In_ volume_device_extension* vde, 1336 _In_ volume_child* vc, _In_ bool skip_dev); 1337 extern KSPIN_LOCK fve_data_lock; 1338 1339 // in cache.c 1340 void init_cache(); 1341 extern CACHE_MANAGER_CALLBACKS cache_callbacks; 1342 1343 // in write.c 1344 NTSTATUS write_file(device_extension* Vcb, PIRP Irp, bool wait, bool deferred_write) __attribute__((nonnull(1,2))); 1345 NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void* buf, ULONG* length, bool paging_io, bool no_cache, 1346 bool wait, bool deferred_write, bool write_irp, LIST_ENTRY* rollback) __attribute__((nonnull(1,2,4,5,11))); 1347 NTSTATUS truncate_file(fcb* fcb, uint64_t end, PIRP Irp, LIST_ENTRY* rollback) __attribute__((nonnull(1,4))); 1348 NTSTATUS extend_file(fcb* fcb, file_ref* fileref, uint64_t end, bool prealloc, PIRP Irp, LIST_ENTRY* rollback) __attribute__((nonnull(1,6))); 1349 NTSTATUS excise_extents(device_extension* Vcb, fcb* fcb, uint64_t start_data, uint64_t end_data, PIRP Irp, LIST_ENTRY* rollback) __attribute__((nonnull(1,2,6))); 1350 chunk* get_chunk_from_address(device_extension* Vcb, uint64_t address) __attribute__((nonnull(1))); 1351 NTSTATUS alloc_chunk(device_extension* Vcb, uint64_t flags, chunk** pc, bool full_size) __attribute__((nonnull(1,3))); 1352 NTSTATUS write_data(_In_ device_extension* Vcb, _In_ uint64_t address, _In_reads_bytes_(length) void* data, _In_ uint32_t length, _In_ write_data_context* wtc, 1353 _In_opt_ PIRP Irp, _In_opt_ chunk* c, _In_ bool file_write, _In_ uint64_t irp_offset, _In_ ULONG priority) __attribute__((nonnull(1,3,5))); 1354 NTSTATUS write_data_complete(device_extension* Vcb, uint64_t address, void* data, uint32_t length, PIRP Irp, chunk* c, bool file_write, 1355 uint64_t irp_offset, ULONG priority) __attribute__((nonnull(1,3))); 1356 void free_write_data_stripes(write_data_context* wtc) __attribute__((nonnull(1))); 1357 1358 _Dispatch_type_(IRP_MJ_WRITE) 1359 _Function_class_(DRIVER_DISPATCH) 1360 NTSTATUS __stdcall drv_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) __attribute__((nonnull(1,2))); 1361 1362 _Requires_lock_held_(c->lock) 1363 _When_(return != 0, _Releases_lock_(c->lock)) 1364 bool insert_extent_chunk(_In_ device_extension* Vcb, _In_ fcb* fcb, _In_ chunk* c, _In_ uint64_t start_data, _In_ uint64_t length, _In_ bool prealloc, 1365 _In_opt_ void* data, _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback, _In_ uint8_t compression, _In_ uint64_t decoded_size, 1366 _In_ bool file_write, _In_ uint64_t irp_offset) __attribute__((nonnull(1,2,3,9))); 1367 1368 NTSTATUS do_write_file(fcb* fcb, uint64_t start_data, uint64_t end_data, void* data, PIRP Irp, bool file_write, uint32_t irp_offset, LIST_ENTRY* rollback) __attribute__((nonnull(1, 4))); 1369 bool find_data_address_in_chunk(device_extension* Vcb, chunk* c, uint64_t length, uint64_t* address) __attribute__((nonnull(1, 2, 4))); 1370 void get_raid56_lock_range(chunk* c, uint64_t address, uint64_t length, uint64_t* lockaddr, uint64_t* locklen) __attribute__((nonnull(1,4,5))); 1371 NTSTATUS add_extent_to_fcb(_In_ fcb* fcb, _In_ uint64_t offset, _In_reads_bytes_(edsize) EXTENT_DATA* ed, _In_ uint16_t edsize, 1372 _In_ bool unique, _In_opt_ _When_(return >= 0, __drv_aliasesMem) void* csum, _In_ LIST_ENTRY* rollback) __attribute__((nonnull(1,3,7))); 1373 void add_extent(_In_ fcb* fcb, _In_ LIST_ENTRY* prevextle, _In_ __drv_aliasesMem extent* newext) __attribute__((nonnull(1,2,3))); 1374 1375 // in dirctrl.c 1376 1377 _Dispatch_type_(IRP_MJ_DIRECTORY_CONTROL) 1378 _Function_class_(DRIVER_DISPATCH) 1379 NTSTATUS __stdcall drv_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1380 1381 ULONG get_reparse_tag(device_extension* Vcb, root* subvol, uint64_t inode, uint8_t type, ULONG atts, bool lxss, PIRP Irp); 1382 ULONG get_reparse_tag_fcb(fcb* fcb); 1383 1384 // in security.c 1385 1386 _Dispatch_type_(IRP_MJ_QUERY_SECURITY) 1387 _Function_class_(DRIVER_DISPATCH) 1388 NTSTATUS __stdcall drv_query_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1389 1390 _Dispatch_type_(IRP_MJ_SET_SECURITY) 1391 _Function_class_(DRIVER_DISPATCH) 1392 NTSTATUS __stdcall drv_set_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1393 1394 void fcb_get_sd(fcb* fcb, struct _fcb* parent, bool look_for_xattr, PIRP Irp); 1395 void add_user_mapping(WCHAR* sidstring, ULONG sidstringlength, uint32_t uid); 1396 void add_group_mapping(WCHAR* sidstring, ULONG sidstringlength, uint32_t gid); 1397 uint32_t sid_to_uid(PSID sid); 1398 NTSTATUS uid_to_sid(uint32_t uid, PSID* sid); 1399 NTSTATUS fcb_get_new_sd(fcb* fcb, file_ref* parfileref, ACCESS_STATE* as); 1400 void find_gid(struct _fcb* fcb, struct _fcb* parfcb, PSECURITY_SUBJECT_CONTEXT subjcont); 1401 1402 // in fileinfo.c 1403 1404 _Dispatch_type_(IRP_MJ_SET_INFORMATION) 1405 _Function_class_(DRIVER_DISPATCH) 1406 NTSTATUS __stdcall drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1407 1408 _Dispatch_type_(IRP_MJ_QUERY_INFORMATION) 1409 _Function_class_(DRIVER_DISPATCH) 1410 NTSTATUS __stdcall drv_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1411 1412 _Dispatch_type_(IRP_MJ_QUERY_EA) 1413 _Function_class_(DRIVER_DISPATCH) 1414 NTSTATUS __stdcall drv_query_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1415 1416 _Dispatch_type_(IRP_MJ_SET_EA) 1417 _Function_class_(DRIVER_DISPATCH) 1418 NTSTATUS __stdcall drv_set_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1419 1420 bool has_open_children(file_ref* fileref); 1421 NTSTATUS stream_set_end_of_file_information(device_extension* Vcb, uint16_t end, fcb* fcb, file_ref* fileref, bool advance_only); 1422 NTSTATUS fileref_get_filename(file_ref* fileref, PUNICODE_STRING fn, USHORT* name_offset, ULONG* preqlen); 1423 void insert_dir_child_into_hash_lists(fcb* fcb, dir_child* dc); 1424 void remove_dir_child_from_hash_lists(fcb* fcb, dir_child* dc); 1425 void add_fcb_to_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb* fcb); 1426 void remove_fcb_from_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb* fcb); 1427 1428 // in reparse.c 1429 NTSTATUS get_reparse_point(PFILE_OBJECT FileObject, void* buffer, DWORD buflen, ULONG_PTR* retlen); 1430 NTSTATUS set_reparse_point2(fcb* fcb, REPARSE_DATA_BUFFER* rdb, ULONG buflen, ccb* ccb, file_ref* fileref, PIRP Irp, LIST_ENTRY* rollback); 1431 NTSTATUS set_reparse_point(PIRP Irp); 1432 NTSTATUS delete_reparse_point(PIRP Irp); 1433 1434 // in create.c 1435 1436 _Dispatch_type_(IRP_MJ_CREATE) 1437 _Function_class_(DRIVER_DISPATCH) 1438 NTSTATUS __stdcall drv_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1439 1440 NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb, _Out_ file_ref** pfr, 1441 _In_ PUNICODE_STRING fnus, _In_opt_ file_ref* related, _In_ bool parent, _Out_opt_ USHORT* parsed, _Out_opt_ ULONG* fn_offset, _In_ POOL_TYPE pooltype, 1442 _In_ bool case_sensitive, _In_opt_ PIRP Irp); 1443 NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension* Vcb, 1444 root* subvol, uint64_t inode, uint8_t type, PANSI_STRING utf8, bool always_add_hl, fcb* parent, fcb** pfcb, POOL_TYPE pooltype, PIRP Irp); 1445 NTSTATUS load_csum(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, void* csum, uint64_t start, uint64_t length, PIRP Irp); 1446 NTSTATUS load_dir_children(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, fcb* fcb, bool ignore_size, PIRP Irp); 1447 NTSTATUS add_dir_child(fcb* fcb, uint64_t inode, bool subvol, PANSI_STRING utf8, PUNICODE_STRING name, uint8_t type, dir_child** pdc); 1448 NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb, 1449 _In_ file_ref* sf, _In_ PUNICODE_STRING name, _In_ bool case_sensitive, _In_ bool lastpart, _In_ bool streampart, 1450 _In_ POOL_TYPE pooltype, _Out_ file_ref** psf2, _In_opt_ PIRP Irp); 1451 fcb* create_fcb(device_extension* Vcb, POOL_TYPE pool_type); 1452 NTSTATUS find_file_in_dir(PUNICODE_STRING filename, fcb* fcb, root** subvol, uint64_t* inode, dir_child** pdc, bool case_sensitive); 1453 uint32_t inherit_mode(fcb* parfcb, bool is_dir); 1454 file_ref* create_fileref(device_extension* Vcb); 1455 NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension* Vcb, root* subvol, uint64_t inode, file_ref** pfr, PIRP Irp); 1456 1457 // in fsctl.c 1458 NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP* Pirp, uint32_t type); 1459 void do_unlock_volume(device_extension* Vcb); 1460 void trim_whole_device(device* dev); 1461 void flush_subvol_fcbs(root* subvol); 1462 bool fcb_is_inline(fcb* fcb); 1463 NTSTATUS dismount_volume(device_extension* Vcb, bool shutdown, PIRP Irp); 1464 1465 // in flushthread.c 1466 1467 _Function_class_(KSTART_ROUTINE) 1468 void __stdcall flush_thread(void* context); 1469 1470 NTSTATUS do_write(device_extension* Vcb, PIRP Irp); 1471 NTSTATUS get_tree_new_address(device_extension* Vcb, tree* t, PIRP Irp, LIST_ENTRY* rollback); 1472 NTSTATUS flush_fcb(fcb* fcb, bool cache, LIST_ENTRY* batchlist, PIRP Irp); 1473 NTSTATUS write_data_phys(_In_ PDEVICE_OBJECT device, _In_ PFILE_OBJECT fileobj, _In_ uint64_t address, 1474 _In_reads_bytes_(length) void* data, _In_ uint32_t length); 1475 bool is_tree_unique(device_extension* Vcb, tree* t, PIRP Irp); 1476 NTSTATUS do_tree_writes(device_extension* Vcb, LIST_ENTRY* tree_writes, bool no_free); 1477 void add_checksum_entry(device_extension* Vcb, uint64_t address, ULONG length, void* csum, PIRP Irp); 1478 bool find_metadata_address_in_chunk(device_extension* Vcb, chunk* c, uint64_t* address); 1479 void add_trim_entry_avoid_sb(device_extension* Vcb, device* dev, uint64_t address, uint64_t size); 1480 NTSTATUS flush_partial_stripe(device_extension* Vcb, chunk* c, partial_stripe* ps); 1481 NTSTATUS update_dev_item(device_extension* Vcb, device* device, PIRP Irp); 1482 void calc_tree_checksum(device_extension* Vcb, tree_header* th); 1483 1484 // in read.c 1485 1486 _Dispatch_type_(IRP_MJ_READ) 1487 _Function_class_(DRIVER_DISPATCH) 1488 NTSTATUS __stdcall drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp); 1489 1490 NTSTATUS read_data(_In_ device_extension* Vcb, _In_ uint64_t addr, _In_ uint32_t length, _In_reads_bytes_opt_(length*sizeof(uint32_t)/Vcb->superblock.sector_size) void* csum, 1491 _In_ bool is_tree, _Out_writes_bytes_(length) uint8_t* buf, _In_opt_ chunk* c, _Out_opt_ chunk** pc, _In_opt_ PIRP Irp, _In_ uint64_t generation, _In_ bool file_read, 1492 _In_ ULONG priority); 1493 NTSTATUS read_file(fcb* fcb, uint8_t* data, uint64_t start, uint64_t length, ULONG* pbr, PIRP Irp) __attribute__((nonnull(1, 2))); 1494 NTSTATUS read_stream(fcb* fcb, uint8_t* data, uint64_t start, ULONG length, ULONG* pbr) __attribute__((nonnull(1, 2))); 1495 NTSTATUS do_read(PIRP Irp, bool wait, ULONG* bytes_read); 1496 NTSTATUS check_csum(device_extension* Vcb, uint8_t* data, uint32_t sectors, void* csum); 1497 void raid6_recover2(uint8_t* sectors, uint16_t num_stripes, ULONG sector_size, uint16_t missing1, uint16_t missing2, uint8_t* out); 1498 void get_tree_checksum(device_extension* Vcb, tree_header* th, void* csum); 1499 bool check_tree_checksum(device_extension* Vcb, tree_header* th); 1500 void get_sector_csum(device_extension* Vcb, void* buf, void* csum); 1501 bool check_sector_csum(device_extension* Vcb, void* buf, void* csum); 1502 1503 // in pnp.c 1504 1505 _Dispatch_type_(IRP_MJ_PNP) 1506 _Function_class_(DRIVER_DISPATCH) 1507 NTSTATUS __stdcall drv_pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp); 1508 1509 NTSTATUS pnp_surprise_removal(PDEVICE_OBJECT DeviceObject, PIRP Irp); 1510 NTSTATUS pnp_query_remove_device(PDEVICE_OBJECT DeviceObject, PIRP Irp); 1511 1512 // in free-space.c 1513 NTSTATUS load_cache_chunk(device_extension* Vcb, chunk* c, PIRP Irp); 1514 NTSTATUS clear_free_space_cache(device_extension* Vcb, LIST_ENTRY* batchlist, PIRP Irp); 1515 NTSTATUS allocate_cache(device_extension* Vcb, bool* changed, PIRP Irp, LIST_ENTRY* rollback); 1516 NTSTATUS update_chunk_caches(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback); 1517 NTSTATUS update_chunk_caches_tree(device_extension* Vcb, PIRP Irp); 1518 NTSTATUS add_space_entry(LIST_ENTRY* list, LIST_ENTRY* list_size, uint64_t offset, uint64_t size); 1519 void space_list_add(chunk* c, uint64_t address, uint64_t length, LIST_ENTRY* rollback); 1520 void space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, uint64_t address, uint64_t length, chunk* c, LIST_ENTRY* rollback); 1521 void space_list_subtract(chunk* c, uint64_t address, uint64_t length, LIST_ENTRY* rollback); 1522 void space_list_subtract2(LIST_ENTRY* list, LIST_ENTRY* list_size, uint64_t address, uint64_t length, chunk* c, LIST_ENTRY* rollback); 1523 void space_list_merge(LIST_ENTRY* spacelist, LIST_ENTRY* spacelist_size, LIST_ENTRY* deleting); 1524 NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, bool load_only, PIRP Irp); 1525 1526 // in extent-tree.c 1527 NTSTATUS increase_extent_refcount_data(device_extension* Vcb, uint64_t address, uint64_t size, uint64_t root, uint64_t inode, uint64_t offset, uint32_t refcount, PIRP Irp); 1528 NTSTATUS decrease_extent_refcount_data(device_extension* Vcb, uint64_t address, uint64_t size, uint64_t root, uint64_t inode, uint64_t offset, 1529 uint32_t refcount, bool superseded, PIRP Irp); 1530 NTSTATUS decrease_extent_refcount_tree(device_extension* Vcb, uint64_t address, uint64_t size, uint64_t root, uint8_t level, PIRP Irp); 1531 uint64_t get_extent_refcount(device_extension* Vcb, uint64_t address, uint64_t size, PIRP Irp); 1532 bool is_extent_unique(device_extension* Vcb, uint64_t address, uint64_t size, PIRP Irp); 1533 NTSTATUS increase_extent_refcount(device_extension* Vcb, uint64_t address, uint64_t size, uint8_t type, void* data, KEY* firstitem, uint8_t level, PIRP Irp); 1534 uint64_t get_extent_flags(device_extension* Vcb, uint64_t address, PIRP Irp); 1535 void update_extent_flags(device_extension* Vcb, uint64_t address, uint64_t flags, PIRP Irp); 1536 NTSTATUS update_changed_extent_ref(device_extension* Vcb, chunk* c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, 1537 int32_t count, bool no_csum, bool superseded, PIRP Irp); 1538 void add_changed_extent_ref(chunk* c, uint64_t address, uint64_t size, uint64_t root, uint64_t objid, uint64_t offset, uint32_t count, bool no_csum); 1539 uint64_t find_extent_shared_tree_refcount(device_extension* Vcb, uint64_t address, uint64_t parent, PIRP Irp); 1540 uint32_t find_extent_shared_data_refcount(device_extension* Vcb, uint64_t address, uint64_t parent, PIRP Irp); 1541 NTSTATUS decrease_extent_refcount(device_extension* Vcb, uint64_t address, uint64_t size, uint8_t type, void* data, KEY* firstitem, 1542 uint8_t level, uint64_t parent, bool superseded, PIRP Irp); 1543 uint64_t get_extent_data_ref_hash2(uint64_t root, uint64_t objid, uint64_t offset); 1544 1545 // in worker-thread.c 1546 NTSTATUS do_read_job(PIRP Irp); 1547 NTSTATUS do_write_job(device_extension* Vcb, PIRP Irp); 1548 bool add_thread_job(device_extension* Vcb, PIRP Irp); 1549 1550 // in registry.c 1551 void read_registry(PUNICODE_STRING regpath, bool refresh); 1552 NTSTATUS registry_mark_volume_mounted(BTRFS_UUID* uuid); 1553 NTSTATUS registry_mark_volume_unmounted(BTRFS_UUID* uuid); 1554 NTSTATUS registry_load_volume_options(device_extension* Vcb); 1555 void watch_registry(HANDLE regh); 1556 1557 // in compress.c 1558 NTSTATUS zlib_decompress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen); 1559 NTSTATUS lzo_decompress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, uint32_t inpageoff); 1560 NTSTATUS zstd_decompress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen); 1561 NTSTATUS write_compressed(fcb* fcb, uint64_t start_data, uint64_t end_data, void* data, PIRP Irp, LIST_ENTRY* rollback); 1562 NTSTATUS zlib_compress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, unsigned int level, unsigned int* space_left); 1563 NTSTATUS lzo_compress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, unsigned int* space_left); 1564 NTSTATUS zstd_compress(uint8_t* inbuf, uint32_t inlen, uint8_t* outbuf, uint32_t outlen, uint32_t level, unsigned int* space_left); 1565 1566 // in galois.c 1567 void galois_double(uint8_t* data, uint32_t len); 1568 void galois_divpower(uint8_t* data, uint8_t div, uint32_t readlen); 1569 uint8_t gpow2(uint8_t e); 1570 uint8_t gmul(uint8_t a, uint8_t b); 1571 uint8_t gdiv(uint8_t a, uint8_t b); 1572 1573 // in devctrl.c 1574 1575 _Dispatch_type_(IRP_MJ_DEVICE_CONTROL) 1576 _Function_class_(DRIVER_DISPATCH) 1577 NTSTATUS __stdcall drv_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1578 1579 // in calcthread.c 1580 1581 _Function_class_(KSTART_ROUTINE) 1582 void __stdcall calc_thread(void* context); 1583 1584 void do_calc_job(device_extension* Vcb, uint8_t* data, uint32_t sectors, void* csum); 1585 NTSTATUS add_calc_job_decomp(device_extension* Vcb, uint8_t compression, void* in, unsigned int inlen, 1586 void* out, unsigned int outlen, unsigned int off, calc_job** pcj); 1587 NTSTATUS add_calc_job_comp(device_extension* Vcb, uint8_t compression, void* in, unsigned int inlen, 1588 void* out, unsigned int outlen, calc_job** pcj); 1589 void calc_thread_main(device_extension* Vcb, calc_job* cj); 1590 1591 // in balance.c 1592 NTSTATUS start_balance(device_extension* Vcb, void* data, ULONG length, KPROCESSOR_MODE processor_mode); 1593 NTSTATUS query_balance(device_extension* Vcb, void* data, ULONG length); 1594 NTSTATUS pause_balance(device_extension* Vcb, KPROCESSOR_MODE processor_mode); 1595 NTSTATUS resume_balance(device_extension* Vcb, KPROCESSOR_MODE processor_mode); 1596 NTSTATUS stop_balance(device_extension* Vcb, KPROCESSOR_MODE processor_mode); 1597 NTSTATUS look_for_balance_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb); 1598 NTSTATUS remove_device(device_extension* Vcb, void* data, ULONG length, KPROCESSOR_MODE processor_mode); 1599 1600 _Function_class_(KSTART_ROUTINE) 1601 void __stdcall balance_thread(void* context); 1602 1603 // in volume.c 1604 NTSTATUS vol_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1605 NTSTATUS vol_close(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1606 NTSTATUS vol_read(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1607 NTSTATUS vol_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1608 NTSTATUS vol_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 1609 void add_volume_device(superblock* sb, PUNICODE_STRING devpath, uint64_t length, ULONG disk_num, ULONG part_num); 1610 NTSTATUS mountmgr_add_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath); 1611 1612 _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE) 1613 NTSTATUS __stdcall pnp_removal(PVOID NotificationStructure, PVOID Context); 1614 1615 void free_vol(volume_device_extension* vde); 1616 1617 // in scrub.c 1618 NTSTATUS start_scrub(device_extension* Vcb, KPROCESSOR_MODE processor_mode); 1619 NTSTATUS query_scrub(device_extension* Vcb, KPROCESSOR_MODE processor_mode, void* data, ULONG length); 1620 NTSTATUS pause_scrub(device_extension* Vcb, KPROCESSOR_MODE processor_mode); 1621 NTSTATUS resume_scrub(device_extension* Vcb, KPROCESSOR_MODE processor_mode); 1622 NTSTATUS stop_scrub(device_extension* Vcb, KPROCESSOR_MODE processor_mode); 1623 1624 // in send.c 1625 NTSTATUS send_subvol(device_extension* Vcb, void* data, ULONG datalen, PFILE_OBJECT FileObject, PIRP Irp); 1626 NTSTATUS read_send_buffer(device_extension* Vcb, PFILE_OBJECT FileObject, void* data, ULONG datalen, ULONG_PTR* retlen, KPROCESSOR_MODE processor_mode); 1627 1628 // in fsrtl.c 1629 NTSTATUS __stdcall compat_FsRtlValidateReparsePointBuffer(IN ULONG BufferLength, IN PREPARSE_DATA_BUFFER ReparseBuffer); 1630 1631 // in boot.c 1632 void check_system_root(); 1633 void boot_add_device(DEVICE_OBJECT* pdo); 1634 extern BTRFS_UUID boot_uuid; 1635 1636 // based on function in sys/sysmacros.h 1637 #define makedev(major, minor) (((minor) & 0xFF) | (((major) & 0xFFF) << 8) | (((uint64_t)((minor) & ~0xFF)) << 12) | (((uint64_t)((major) & ~0xFFF)) << 32)) 1638 1639 #ifndef __REACTOS__ 1640 // not in mingw yet 1641 #ifndef _MSC_VER 1642 typedef struct { 1643 FSRTL_COMMON_FCB_HEADER Header; 1644 PFAST_MUTEX FastMutex; 1645 LIST_ENTRY FilterContexts; 1646 EX_PUSH_LOCK PushLock; 1647 PVOID* FileContextSupportPointer; 1648 union { 1649 OPLOCK Oplock; 1650 PVOID ReservedForRemote; 1651 }; 1652 PVOID ReservedContext; 1653 } FSRTL_ADVANCED_FCB_HEADER_NEW; 1654 1655 #define FSRTL_FCB_HEADER_V2 2 1656 1657 #else 1658 #define FSRTL_ADVANCED_FCB_HEADER_NEW FSRTL_ADVANCED_FCB_HEADER 1659 #endif 1660 #else 1661 typedef struct { 1662 FSRTL_COMMON_FCB_HEADER Header; 1663 PFAST_MUTEX FastMutex; 1664 LIST_ENTRY FilterContexts; 1665 EX_PUSH_LOCK PushLock; 1666 PVOID* FileContextSupportPointer; 1667 union { 1668 OPLOCK Oplock; 1669 PVOID ReservedForRemote; 1670 }; 1671 PVOID ReservedContext; 1672 } FSRTL_ADVANCED_FCB_HEADER_NEW; 1673 1674 #define FSRTL_FCB_HEADER_V2 2 1675 #endif // __REACTOS__ 1676 1677 static __inline POPLOCK fcb_oplock(fcb* fcb) { 1678 if (fcb->Header.Version >= FSRTL_FCB_HEADER_V2) 1679 return &((FSRTL_ADVANCED_FCB_HEADER_NEW*)&fcb->Header)->Oplock; 1680 else 1681 return &fcb->oplock; 1682 } 1683 1684 static __inline FAST_IO_POSSIBLE fast_io_possible(fcb* fcb) { 1685 if (!FsRtlOplockIsFastIoPossible(fcb_oplock(fcb))) 1686 return FastIoIsNotPossible; 1687 1688 if (!FsRtlAreThereCurrentFileLocks(&fcb->lock) && !fcb->Vcb->readonly) 1689 return FastIoIsPossible; 1690 1691 return FastIoIsQuestionable; 1692 } 1693 1694 static __inline void print_open_trees(device_extension* Vcb) { 1695 LIST_ENTRY* le = Vcb->trees.Flink; 1696 while (le != &Vcb->trees) { 1697 tree* t = CONTAINING_RECORD(le, tree, list_entry); 1698 tree_data* td = CONTAINING_RECORD(t->itemlist.Flink, tree_data, list_entry); 1699 ERR("tree %p: root %I64x, level %u, first key (%I64x,%x,%I64x)\n", 1700 t, t->root->id, t->header.level, td->key.obj_id, td->key.obj_type, td->key.offset); 1701 1702 le = le->Flink; 1703 } 1704 } 1705 1706 static __inline bool write_fcb_compressed(fcb* fcb) { 1707 if (fcb->inode_item.flags & BTRFS_INODE_NODATACOW) 1708 return false; 1709 1710 // make sure we don't accidentally write the cache inodes or pagefile compressed 1711 if (fcb->subvol->id == BTRFS_ROOT_ROOT || fcb->Header.Flags2 & FSRTL_FLAG2_IS_PAGING_FILE) 1712 return false; 1713 1714 if (fcb->Vcb->options.compress_force) 1715 return true; 1716 1717 if (fcb->inode_item.flags & BTRFS_INODE_NOCOMPRESS) 1718 return false; 1719 1720 if (fcb->inode_item.flags & BTRFS_INODE_COMPRESS || fcb->Vcb->options.compress) 1721 return true; 1722 1723 return false; 1724 } 1725 1726 #ifdef DEBUG_FCB_REFCOUNTS 1727 #ifdef DEBUG_LONG_MESSAGES 1728 #define increase_fileref_refcount(fileref) {\ 1729 LONG rc = InterlockedIncrement(&fileref->refcount);\ 1730 MSG(funcname, __FILE__, __LINE__, "fileref %p: refcount now %i\n", 1, fileref, rc);\ 1731 } 1732 #else 1733 #define increase_fileref_refcount(fileref) {\ 1734 LONG rc = InterlockedIncrement(&fileref->refcount);\ 1735 MSG(funcname, "fileref %p: refcount now %i\n", 1, fileref, rc);\ 1736 } 1737 #endif 1738 #else 1739 #define increase_fileref_refcount(fileref) InterlockedIncrement(&fileref->refcount) 1740 #endif 1741 1742 #ifdef _MSC_VER 1743 #define int3 __debugbreak() 1744 #else 1745 #define int3 asm("int3;") 1746 #endif 1747 1748 #define hex_digit(c) ((c) <= 9) ? ((c) + '0') : ((c) - 10 + 'a') 1749 1750 // FIXME - find a way to catch unfreed trees again 1751 1752 // from sys/stat.h 1753 #define __S_IFMT 0170000 /* These bits determine file type. */ 1754 #define __S_IFDIR 0040000 /* Directory. */ 1755 #define __S_IFCHR 0020000 /* Character device. */ 1756 #define __S_IFBLK 0060000 /* Block device. */ 1757 #define __S_IFREG 0100000 /* Regular file. */ 1758 #define __S_IFIFO 0010000 /* FIFO. */ 1759 #define __S_IFLNK 0120000 /* Symbolic link. */ 1760 #define __S_IFSOCK 0140000 /* Socket. */ 1761 #define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask)) 1762 1763 #ifndef S_ISDIR 1764 #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR) 1765 #endif 1766 1767 #ifndef S_IRUSR 1768 #define S_IRUSR 0000400 1769 #endif 1770 1771 #ifndef S_IWUSR 1772 #define S_IWUSR 0000200 1773 #endif 1774 1775 #ifndef S_IXUSR 1776 #define S_IXUSR 0000100 1777 #endif 1778 1779 #ifdef __REACTOS__ 1780 #define S_IFDIR __S_IFDIR 1781 #define S_IFREG __S_IFREG 1782 #endif /* __REACTOS__ */ 1783 1784 #ifndef S_IRGRP 1785 #define S_IRGRP (S_IRUSR >> 3) 1786 #endif 1787 1788 #ifndef S_IWGRP 1789 #define S_IWGRP (S_IWUSR >> 3) 1790 #endif 1791 1792 #ifndef S_IXGRP 1793 #define S_IXGRP (S_IXUSR >> 3) 1794 #endif 1795 1796 #ifndef S_IROTH 1797 #define S_IROTH (S_IRGRP >> 3) 1798 #endif 1799 1800 #ifndef S_IWOTH 1801 #define S_IWOTH (S_IWGRP >> 3) 1802 #endif 1803 1804 #ifndef S_IXOTH 1805 #define S_IXOTH (S_IXGRP >> 3) 1806 #endif 1807 1808 #ifndef S_ISUID 1809 #define S_ISUID 0004000 1810 #endif 1811 1812 #ifndef S_ISGID 1813 #define S_ISGID 0002000 1814 #endif 1815 1816 #ifndef S_ISVTX 1817 #define S_ISVTX 0001000 1818 #endif 1819 1820 // based on functions in sys/sysmacros.h 1821 #define major(rdev) ((((rdev) >> 8) & 0xFFF) | ((uint32_t)((rdev) >> 32) & ~0xFFF)) 1822 #define minor(rdev) (((rdev) & 0xFF) | ((uint32_t)((rdev) >> 12) & ~0xFF)) 1823 1824 static __inline uint64_t fcb_alloc_size(fcb* fcb) { 1825 if (S_ISDIR(fcb->inode_item.st_mode)) 1826 return 0; 1827 else if (fcb->atts & FILE_ATTRIBUTE_SPARSE_FILE) 1828 return fcb->inode_item.st_blocks; 1829 else 1830 return sector_align(fcb->inode_item.st_size, fcb->Vcb->superblock.sector_size); 1831 } 1832 1833 typedef BOOLEAN (__stdcall *tPsIsDiskCountersEnabled)(); 1834 1835 typedef VOID (__stdcall *tPsUpdateDiskCounters)(PEPROCESS Process, ULONG64 BytesRead, ULONG64 BytesWritten, 1836 ULONG ReadOperationCount, ULONG WriteOperationCount, ULONG FlushOperationCount); 1837 1838 typedef BOOLEAN (__stdcall *tCcCopyWriteEx)(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, 1839 PVOID Buffer, PETHREAD IoIssuerThread); 1840 1841 typedef BOOLEAN (__stdcall *tCcCopyReadEx)(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, 1842 PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PETHREAD IoIssuerThread); 1843 1844 #ifndef CC_ENABLE_DISK_IO_ACCOUNTING 1845 #define CC_ENABLE_DISK_IO_ACCOUNTING 0x00000010 1846 #endif 1847 1848 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_VISTA) 1849 typedef struct _ECP_LIST ECP_LIST; 1850 typedef struct _ECP_LIST *PECP_LIST; 1851 #endif 1852 1853 typedef VOID (__stdcall *tCcSetAdditionalCacheAttributesEx)(PFILE_OBJECT FileObject, ULONG Flags); 1854 1855 typedef VOID (__stdcall *tFsRtlUpdateDiskCounters)(ULONG64 BytesRead, ULONG64 BytesWritten); 1856 1857 typedef NTSTATUS (__stdcall *tIoUnregisterPlugPlayNotificationEx)(PVOID NotificationEntry); 1858 1859 typedef NTSTATUS (__stdcall *tFsRtlGetEcpListFromIrp)(PIRP Irp, PECP_LIST* EcpList); 1860 1861 typedef NTSTATUS (__stdcall *tFsRtlGetNextExtraCreateParameter)(PECP_LIST EcpList, PVOID CurrentEcpContext, LPGUID NextEcpType, 1862 PVOID* NextEcpContext, ULONG* NextEcpContextSize); 1863 1864 typedef NTSTATUS (__stdcall *tFsRtlValidateReparsePointBuffer)(ULONG BufferLength, PREPARSE_DATA_BUFFER ReparseBuffer); 1865 1866 typedef BOOLEAN (__stdcall *tFsRtlCheckLockForOplockRequest)(PFILE_LOCK FileLock, PLARGE_INTEGER AllocationSize); 1867 1868 typedef BOOLEAN (__stdcall *tFsRtlAreThereCurrentOrInProgressFileLocks)(PFILE_LOCK FileLock); 1869 1870 #ifndef __REACTOS__ 1871 #ifndef _MSC_VER 1872 PEPROCESS __stdcall PsGetThreadProcess(_In_ PETHREAD Thread); // not in mingw 1873 #endif 1874 1875 // not in DDK headers - taken from winternl.h 1876 typedef struct _LDR_DATA_TABLE_ENTRY { 1877 PVOID Reserved1[2]; 1878 LIST_ENTRY InMemoryOrderLinks; 1879 PVOID Reserved2[2]; 1880 PVOID DllBase; 1881 PVOID Reserved3[2]; 1882 UNICODE_STRING FullDllName; 1883 BYTE Reserved4[8]; 1884 PVOID Reserved5[3]; 1885 union { 1886 ULONG CheckSum; 1887 PVOID Reserved6; 1888 }; 1889 ULONG TimeDateStamp; 1890 } LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY; 1891 1892 typedef struct _PEB_LDR_DATA { 1893 BYTE Reserved1[8]; 1894 PVOID Reserved2[3]; 1895 LIST_ENTRY InMemoryOrderModuleList; 1896 } PEB_LDR_DATA,*PPEB_LDR_DATA; 1897 1898 typedef struct _RTL_USER_PROCESS_PARAMETERS { 1899 BYTE Reserved1[16]; 1900 PVOID Reserved2[10]; 1901 UNICODE_STRING ImagePathName; 1902 UNICODE_STRING CommandLine; 1903 } RTL_USER_PROCESS_PARAMETERS,*PRTL_USER_PROCESS_PARAMETERS; 1904 1905 typedef VOID (NTAPI *PPS_POST_PROCESS_INIT_ROUTINE)(VOID); 1906 1907 typedef struct _PEB { 1908 BYTE Reserved1[2]; 1909 BYTE BeingDebugged; 1910 BYTE Reserved2[1]; 1911 PVOID Reserved3[2]; 1912 PPEB_LDR_DATA Ldr; 1913 PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 1914 BYTE Reserved4[104]; 1915 PVOID Reserved5[52]; 1916 PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; 1917 BYTE Reserved6[128]; 1918 PVOID Reserved7[1]; 1919 ULONG SessionId; 1920 } PEB,*PPEB; 1921 #endif /* __REACTOS__ */ 1922 1923 #ifdef _MSC_VER 1924 __kernel_entry 1925 NTSTATUS NTAPI ZwQueryInformationProcess( 1926 IN HANDLE ProcessHandle, 1927 IN PROCESSINFOCLASS ProcessInformationClass, 1928 OUT PVOID ProcessInformation, 1929 IN ULONG ProcessInformationLength, 1930 OUT PULONG ReturnLength OPTIONAL 1931 ); 1932 #endif 1933