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