[SETUP] Remove FSDs which have broken dismount implementation.
[reactos.git] / drivers / filesystems / btrfs / btrfs_drv.h
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