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