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