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