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