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