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