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