[BTRFS]
[reactos.git] / reactos / drivers / filesystems / btrfs / btrfs_drv.h
index 80188dd..b658726 100644 (file)
@@ -1,17 +1,17 @@
-/* Copyright (c) Mark Harmstone 2016
- * 
+/* Copyright (c) Mark Harmstone 2016-17
+ *
  * This file is part of WinBtrfs.
- * 
+ *
  * WinBtrfs is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public Licence as published by
  * the Free Software Foundation, either version 3 of the Licence, or
  * (at your option) any later version.
- * 
+ *
  * WinBtrfs is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public Licence for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public Licence
  * along with WinBtrfs.  If not, see <http://www.gnu.org/licenses/>. */
 
 #undef _WIN32_WINNT
 #undef NTDDI_VERSION
 
-#define _WIN32_WINNT 0x0600
-#define NTDDI_VERSION 0x06010000 // Win 7
+#define _WIN32_WINNT 0x0601
+#define NTDDI_VERSION 0x06020000 // Win 8
 #define _CRT_SECURE_NO_WARNINGS
+#define _NO_CRT_STDIO_INLINE
 #endif /* __REACTOS__ */
 
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4163)
+#pragma warning(disable:4311)
+#pragma warning(disable:4312)
+#else
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#endif
+
 #include <ntifs.h>
 #include <ntddk.h>
 #ifdef __REACTOS__
 #include <iotypes.h>
 #include <pseh/pseh2.h>
 #endif /* __REACTOS__ */
-//#include <windows.h>
 #include <windef.h>
 #include <wdm.h>
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#else
+#pragma GCC diagnostic pop
+#endif
+
 #include <stdio.h>
 #include <stdarg.h>
 #include <stddef.h>
 #define DEBUG_PARANOID
 #endif
 
+#define UNUSED(x) (void)(x)
+
 #define BTRFS_NODE_TYPE_CCB 0x2295
 #define BTRFS_NODE_TYPE_FCB 0x2296
 
 #define ALLOC_TAG 0x7442484D //'MHBt'
 #define ALLOC_TAG_ZLIB 0x7A42484D //'MHBz'
 
-#define STDCALL __stdcall
-
 #define UID_NOBODY 65534
 #define GID_NOBODY 65534
 
 #define EA_DOSATTRIB "user.DOSATTRIB"
 #define EA_DOSATTRIB_HASH 0x914f9939
 
-#define EA_REPARSE "system.reparse"
-#define EA_REPARSE_HASH 0x786f6167
+#define EA_REPARSE "user.reparse"
+#define EA_REPARSE_HASH 0xfabad1fe
 
 #define EA_EA "user.EA"
 #define EA_EA_HASH 0x8270dd43
 
+#define EA_PROP_COMPRESSION "btrfs.compression"
+#define EA_PROP_COMPRESSION_HASH 0x20ccdf69
+
 #define MAX_EXTENT_SIZE 0x8000000 // 128 MB
 #define COMPRESSED_EXTENT_SIZE 0x20000 // 128 KB
 
 
 #define IO_REPARSE_TAG_LXSS_SYMLINK 0xa000001d // undocumented?
 
+#define BTRFS_VOLUME_PREFIX L"\\Device\\Btrfs{"
+
 #ifdef _MSC_VER
 #define try __try
 #define except __except
 #define finally if (1)
 #endif
 
-// #pragma pack(push, 1)
+#ifndef FILE_SUPPORTS_BLOCK_REFCOUNTING
+#define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000
+#endif
 
-struct _device_extension;
+#ifndef FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL
+#define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL 0x00020000
+#endif
 
-typedef struct {
-    BTRFS_UUID fsuuid;
-    BTRFS_UUID devuuid;
-    UINT64 devnum;
-    UNICODE_STRING devpath;
-    UINT64 length;
-    UINT64 gen1, gen2;
-    BOOL seeding;
-    BOOL processed;
-    DWORD disk_num;
-    DWORD part_num;
-    LIST_ENTRY list_entry;
-} volume;
+typedef struct _DUPLICATE_EXTENTS_DATA {
+    HANDLE FileHandle;
+    LARGE_INTEGER SourceFileOffset;
+    LARGE_INTEGER TargetFileOffset;
+    LARGE_INTEGER ByteCount;
+} DUPLICATE_EXTENTS_DATA, *PDUPLICATE_EXTENTS_DATA;
 
-typedef struct {
-    UNICODE_STRING devpath;
-    ULONG disk_num;
-    LIST_ENTRY list_entry;
-} pnp_disk;
+#define FSCTL_DUPLICATE_EXTENTS_TO_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 209, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+
+typedef struct _FSCTL_GET_INTEGRITY_INFORMATION_BUFFER {
+    WORD ChecksumAlgorithm;
+    WORD Reserved;
+    DWORD Flags;
+    DWORD ChecksumChunkSizeInBytes;
+    DWORD ClusterSizeInBytes;
+} FSCTL_GET_INTEGRITY_INFORMATION_BUFFER, *PFSCTL_GET_INTEGRITY_INFORMATION_BUFFER;
+
+typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER {
+    WORD ChecksumAlgorithm;
+    WORD Reserved;
+    DWORD Flags;
+} FSCTL_SET_INTEGRITY_INFORMATION_BUFFER, *PFSCTL_SET_INTEGRITY_INFORMATION_BUFFER;
+
+#define FSCTL_GET_INTEGRITY_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 159, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define FSCTL_SET_INTEGRITY_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 160, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
+
+#ifndef __REACTOS__
+#ifndef _MSC_VER
+#define __drv_aliasesMem
+#define _Requires_lock_held_(a)
+#define _Requires_exclusive_lock_held_(a)
+#define _Releases_lock_(a)
+#define _Out_writes_bytes_opt_(a)
+#define _Pre_satisfies_(a)
+#define _Post_satisfies_(a)
+#define _Releases_exclusive_lock_(a)
+#define _Dispatch_type_(a)
+#define _Create_lock_level_(a)
+#define _Lock_level_order_(a,b)
+#define _Has_lock_level_(a)
+#endif
+#endif
+
+_Create_lock_level_(tree_lock)
+_Create_lock_level_(fcb_lock)
+_Lock_level_order_(tree_lock, fcb_lock)
+
+struct _device_extension;
 
 typedef struct _fcb_nonpaged {
     FAST_MUTEX HeaderMutex;
@@ -135,14 +191,15 @@ struct _root;
 
 typedef struct {
     UINT64 offset;
-    EXTENT_DATA* data;
-    ULONG datalen;
+    UINT16 datalen;
     BOOL unique;
     BOOL ignore;
     BOOL inserted;
     UINT32* csum;
-    
+
     LIST_ENTRY list_entry;
+
+    EXTENT_DATA extent_data;
 } extent;
 
 typedef struct {
@@ -164,16 +221,32 @@ typedef struct {
     UNICODE_STRING name;
     UINT32 hash_uc;
     UNICODE_STRING name_uc;
+    ULONG size;
     struct _file_ref* fileref;
     LIST_ENTRY list_entry_index;
     LIST_ENTRY list_entry_hash;
     LIST_ENTRY list_entry_hash_uc;
 } dir_child;
 
+enum prop_compression_type {
+    PropCompression_None,
+    PropCompression_Zlib,
+    PropCompression_LZO
+};
+
+typedef struct {
+    LIST_ENTRY list_entry;
+    USHORT namelen;
+    USHORT valuelen;
+    BOOL dirty;
+    char data[1];
+} xattr;
+
 typedef struct _fcb {
     FSRTL_ADVANCED_FCB_HEADER Header;
     struct _fcb_nonpaged* nonpaged;
     LONG refcount;
+    POOL_TYPE pool_type;
     struct _device_extension* Vcb;
     struct _root* subvol;
     UINT64 inode;
@@ -186,55 +259,53 @@ typedef struct _fcb {
     ULONG atts;
     SHARE_ACCESS share_access;
     WCHAR* debug_desc;
+    BOOL csum_loaded;
     LIST_ENTRY extents;
-    UINT64 last_dir_index;
     ANSI_STRING reparse_xattr;
     ANSI_STRING ea_xattr;
     ULONG ealen;
     LIST_ENTRY hardlinks;
     struct _file_ref* fileref;
     BOOL inode_item_changed;
-    
+    enum prop_compression_type prop_compression;
+    LIST_ENTRY xattrs;
+
     LIST_ENTRY dir_children_index;
     LIST_ENTRY dir_children_hash;
     LIST_ENTRY dir_children_hash_uc;
     LIST_ENTRY** hash_ptrs;
     LIST_ENTRY** hash_ptrs_uc;
-    
+
     BOOL dirty;
-    BOOL sd_dirty;
+    BOOL sd_dirty, sd_deleted;
     BOOL atts_changed, atts_deleted;
     BOOL extents_changed;
     BOOL reparse_xattr_changed;
     BOOL ea_changed;
+    BOOL prop_compression_changed;
+    BOOL xattrs_changed;
     BOOL created;
-    
+
     BOOL ads;
     UINT32 adshash;
     ULONG adsmaxlen;
     ANSI_STRING adsxattr;
     ANSI_STRING adsdata;
-    
+
     LIST_ENTRY list_entry;
     LIST_ENTRY list_entry_all;
+    LIST_ENTRY list_entry_dirty;
 } fcb;
 
 typedef struct {
-    fcb* fcb;
-    LIST_ENTRY list_entry;
-} dirty_fcb;
-
-typedef struct {
+    ERESOURCE fileref_lock;
     ERESOURCE children_lock;
 } file_ref_nonpaged;
 
 typedef struct _file_ref {
     fcb* fcb;
-    UNICODE_STRING filepart;
-    UNICODE_STRING filepart_uc;
-    ANSI_STRING utf8;
     ANSI_STRING oldutf8;
-    UINT64 index;
+    UINT64 oldindex;
     BOOL delete_on_close;
     BOOL deleted;
     BOOL created;
@@ -245,16 +316,21 @@ typedef struct _file_ref {
     struct _file_ref* parent;
     WCHAR* debug_desc;
     dir_child* dc;
-    
+
     BOOL dirty;
-    
+
     LIST_ENTRY list_entry;
+    LIST_ENTRY list_entry_dirty;
 } file_ref;
 
 typedef struct {
-    file_ref* fileref;
+    HANDLE thread;
+    struct _ccb* ccb;
+    void* context;
+    KEVENT cleared_event;
+    BOOL cancelling;
     LIST_ENTRY list_entry;
-} dirty_fileref;
+} send_info;
 
 typedef struct _ccb {
     USHORT NodeType;
@@ -262,12 +338,12 @@ typedef struct _ccb {
     ULONG disposition;
     ULONG options;
     UINT64 query_dir_offset;
-//     char* query_string;
     UNICODE_STRING query_string;
     BOOL has_wildcard;
     BOOL specific_file;
     BOOL manage_volume_privilege;
     BOOL allow_extended_dasd_io;
+    BOOL reserving;
     ACCESS_MASK access;
     file_ref* fileref;
     UNICODE_STRING filename;
@@ -277,36 +353,17 @@ typedef struct _ccb {
     BOOL user_set_access_time;
     BOOL user_set_write_time;
     BOOL user_set_change_time;
+    BOOL lxss;
+    send_info* send;
+    NTSTATUS send_status;
 } ccb;
 
-// typedef struct _log_to_phys {
-//     UINT64 address;
-//     UINT64 size;
-//     UINT64 physaddr;
-//     UINT32 sector_size;
-//     struct _log_to_phys* next;
-// } log_to_phys;
-
 struct _device_extension;
 
-// enum tree_holder_status {
-//     tree_holder_unloaded,
-//     tree_holder_loading,
-//     tree_holder_loaded,
-//     tree_holder_unloading
-// };
-
-// typedef struct {
-//     enum tree_holder_status status;
-//     KSPIN_LOCK spin_lock;
-//     ERESOURCE lock;
-// } tree_holder_nonpaged;
-
 typedef struct {
     UINT64 address;
     UINT64 generation;
     struct _tree* tree;
-//     tree_holder_nonpaged* nonpaged;
 } tree_holder;
 
 typedef struct _tree_data {
@@ -314,24 +371,18 @@ typedef struct _tree_data {
     LIST_ENTRY list_entry;
     BOOL ignore;
     BOOL inserted;
-    
+
     union {
         tree_holder treeholder;
-        
+
         struct {
-            UINT32 size;
+            UINT16 size;
             UINT8* data;
         };
     };
 } tree_data;
 
-// typedef struct _tree_nonpaged {
-//     ERESOURCE load_tree_lock;
-// } tree_nonpaged;
-
 typedef struct _tree {
-//     UINT64 address;
-//     UINT8 level;
     tree_header header;
     UINT32 hash;
     BOOL has_address;
@@ -340,7 +391,6 @@ typedef struct _tree {
     struct _tree* parent;
     tree_data* paritem;
     struct _root* root;
-//     tree_nonpaged* nonpaged;
     LIST_ENTRY itemlist;
     LIST_ENTRY list_entry;
     LIST_ENTRY list_entry_hash;
@@ -348,10 +398,12 @@ typedef struct _tree {
     BOOL has_new_address;
     BOOL updated_extents;
     BOOL write;
+    BOOL is_unique;
+    BOOL uniqueness_determined;
+    UINT8* buf;
 } tree;
 
 typedef struct {
-//     KSPIN_LOCK load_tree_lock;
     ERESOURCE load_tree_lock;
 } root_nonpaged;
 
@@ -361,9 +413,14 @@ typedef struct _root {
     tree_holder treeholder;
     root_nonpaged* nonpaged;
     ROOT_ITEM root_item;
-    UNICODE_STRING path;
+    BOOL dirty;
+    BOOL received;
+    PEPROCESS reserved;
+    UINT64 parent;
+    LONG send_ops;
     LIST_ENTRY fcbs;
     LIST_ENTRY list_entry;
+    LIST_ENTRY list_entry_dirty;
 } root;
 
 enum batch_operation {
@@ -377,6 +434,9 @@ enum batch_operation {
     Batch_DeleteDirItem,
     Batch_DeleteInodeRef,
     Batch_DeleteInodeExtRef,
+    Batch_DeleteXattr,
+    Batch_DeleteExtentData,
+    Batch_DeleteFreeSpace,
 };
 
 typedef struct {
@@ -417,14 +477,17 @@ typedef struct {
     BOOL seeding;
     BOOL readonly;
     BOOL reloc;
-    BOOL ssd;
     BOOL trim;
+    BOOL can_flush;
     ULONG change_count;
-    UINT64 length;
     ULONG disk_num;
     ULONG part_num;
+    UINT64 stats[5];
+    BOOL stats_changed;
     LIST_ENTRY space;
     LIST_ENTRY list_entry;
+    ULONG num_trim_entries;
+    LIST_ENTRY trim_list;
 } device;
 
 typedef struct {
@@ -434,20 +497,29 @@ typedef struct {
     LIST_ENTRY list_entry;
 } range_lock;
 
+typedef struct {
+    UINT64 address;
+    ULONG* bmparr;
+    RTL_BITMAP bmp;
+    LIST_ENTRY list_entry;
+    UINT8 data[1];
+} partial_stripe;
+
 typedef struct {
     CHUNK_ITEM* chunk_item;
-    UINT32 size;
+    UINT16 size;
     UINT64 offset;
     UINT64 used;
-    UINT32 oldused;
+    UINT64 oldused;
     device** devices;
     fcb* cache;
+    fcb* old_cache;
     LIST_ENTRY space;
     LIST_ENTRY space_size;
     LIST_ENTRY deleting;
     LIST_ENTRY changed_extents;
     LIST_ENTRY range_locks;
-    KSPIN_LOCK range_locks_spinlock;
+    ERESOURCE range_locks_lock;
     KEVENT range_locks_event;
     ERESOURCE lock;
     ERESOURCE changed_extents_lock;
@@ -455,10 +527,16 @@ typedef struct {
     BOOL readonly;
     BOOL reloc;
     BOOL last_alloc_set;
+    BOOL cache_loaded;
+    BOOL changed;
+    BOOL space_changed;
     UINT64 last_alloc;
-    
+    UINT16 last_stripe;
+    LIST_ENTRY partial_stripes;
+    ERESOURCE partial_stripes_lock;
+    ULONG balance_num;
+
     LIST_ENTRY list_entry;
-    LIST_ENTRY list_entry_changed;
     LIST_ENTRY list_entry_balance;
 } chunk;
 
@@ -477,12 +555,12 @@ typedef struct {
 
 typedef struct {
     UINT8 type;
-    
+
     union {
         EXTENT_DATA_REF edr;
         SHARED_DATA_REF sdr;
     };
-    
+
     LIST_ENTRY list_entry;
 } changed_extent_ref;
 
@@ -528,14 +606,17 @@ typedef struct {
     UINT32 flush_interval;
     UINT32 max_inline;
     UINT64 subvol_id;
-    UINT32 raid5_recalculation;
-    UINT32 raid6_recalculation;
     BOOL skip_balance;
+    BOOL no_barrier;
+    BOOL no_trim;
+    BOOL clear_cache;
+    BOOL allow_degraded;
 } mount_options;
 
-#define VCB_TYPE_VOLUME     1
-#define VCB_TYPE_PARTITION0 2
-#define VCB_TYPE_CONTROL    3
+#define VCB_TYPE_FS         1
+#define VCB_TYPE_CONTROL    2
+#define VCB_TYPE_VOLUME     3
+#define VCB_TYPE_PDO        4
 
 #ifdef DEBUG_STATS
 typedef struct {
@@ -544,13 +625,15 @@ typedef struct {
     UINT64 read_total_time;
     UINT64 read_csum_time;
     UINT64 read_disk_time;
-    
+
     UINT64 num_opens;
     UINT64 open_total_time;
     UINT64 num_overwrites;
     UINT64 overwrite_total_time;
     UINT64 num_creates;
     UINT64 create_total_time;
+    UINT64 open_fcb_calls;
+    UINT64 open_fcb_time;
 } debug_stats;
 #endif
 
@@ -565,26 +648,71 @@ typedef struct {
     btrfs_balance_opts opts[3];
     BOOL paused;
     BOOL stopping;
-    BOOL cancelling;
     BOOL removing;
+    BOOL shrinking;
     BOOL dev_readonly;
+    ULONG balance_num;
     NTSTATUS status;
     KEVENT event;
     KEVENT finished;
 } balance_info;
 
+typedef struct {
+    UINT64 address;
+    UINT64 device;
+    BOOL recovered;
+    BOOL is_metadata;
+    BOOL parity;
+    LIST_ENTRY list_entry;
+
+    union {
+        struct {
+            UINT64 subvol;
+            UINT64 offset;
+            UINT16 filename_length;
+            WCHAR filename[1];
+        } data;
+
+        struct {
+            UINT64 root;
+            UINT8 level;
+            KEY firstitem;
+        } metadata;
+    };
+} scrub_error;
+
+typedef struct {
+    HANDLE thread;
+    ERESOURCE stats_lock;
+    KEVENT event;
+    KEVENT finished;
+    BOOL stopping;
+    BOOL paused;
+    LARGE_INTEGER start_time;
+    LARGE_INTEGER finish_time;
+    LARGE_INTEGER resume_time;
+    LARGE_INTEGER duration;
+    UINT64 total_chunks;
+    UINT64 chunks_left;
+    UINT64 data_scrubbed;
+    NTSTATUS error;
+    ULONG num_errors;
+    LIST_ENTRY errors;
+} scrub_info;
+
+struct _volume_device_extension;
+
 typedef struct _device_extension {
     UINT32 type;
     mount_options options;
     PVPB Vpb;
+    struct _volume_device_extension* vde;
     LIST_ENTRY devices;
 #ifdef DEBUG_STATS
     debug_stats stats;
 #endif
     UINT64 devices_loaded;
-//     DISK_GEOMETRY geometry;
     superblock superblock;
-//     WCHAR label[MAX_LABEL_SIZE];
     BOOL readonly;
     BOOL removing;
     BOOL locked;
@@ -593,21 +721,19 @@ typedef struct _device_extension {
     BOOL trim;
     PFILE_OBJECT locked_fileobj;
     fcb* volume_fcb;
+    fcb* dummy_fcb;
     file_ref* root_fileref;
     LONG open_files;
-    ERESOURCE fcb_lock;
+    _Has_lock_level_(fcb_lock) ERESOURCE fcb_lock;
     ERESOURCE load_lock;
-    ERESOURCE tree_lock;
+    _Has_lock_level_(tree_lock) ERESOURCE tree_lock;
     PNOTIFY_SYNC NotifySync;
     LIST_ENTRY DirNotifyList;
-    LONG open_trees;
     BOOL need_write;
-//     ERESOURCE LogToPhysLock;
-//     UINT64 chunk_root_phys_addr;
+    BOOL stats_changed;
     UINT64 data_flags;
     UINT64 metadata_flags;
     UINT64 system_flags;
-//     log_to_phys* log_to_phys;
     LIST_ENTRY roots;
     LIST_ENTRY drop_roots;
     root* chunk_root;
@@ -617,43 +743,96 @@ typedef struct _device_extension {
     root* dev_root;
     root* uuid_root;
     root* data_reloc_root;
+    root* space_root;
     BOOL log_to_phys_loaded;
+    BOOL chunk_usage_found;
     LIST_ENTRY sys_chunks;
     LIST_ENTRY chunks;
-    LIST_ENTRY chunks_changed;
     LIST_ENTRY trees;
     LIST_ENTRY trees_hash;
     LIST_ENTRY* trees_ptrs[256];
     LIST_ENTRY all_fcbs;
     LIST_ENTRY dirty_fcbs;
-    KSPIN_LOCK dirty_fcbs_lock;
+    ERESOURCE dirty_fcbs_lock;
     LIST_ENTRY dirty_filerefs;
-    KSPIN_LOCK dirty_filerefs_lock;
+    ERESOURCE dirty_filerefs_lock;
+    LIST_ENTRY dirty_subvols;
+    ERESOURCE dirty_subvols_lock;
     ERESOURCE chunk_lock;
     HANDLE flush_thread_handle;
     KTIMER flush_thread_timer;
     KEVENT flush_thread_finished;
     drv_calc_threads calcthreads;
     balance_info balance;
+    scrub_info scrub;
+    ERESOURCE send_load_lock;
+    LONG running_sends;
+    LIST_ENTRY send_ops;
     PFILE_OBJECT root_file;
     PAGED_LOOKASIDE_LIST tree_data_lookaside;
     PAGED_LOOKASIDE_LIST traverse_ptr_lookaside;
-    PAGED_LOOKASIDE_LIST rollback_item_lookaside;
     PAGED_LOOKASIDE_LIST batch_item_lookaside;
+    PAGED_LOOKASIDE_LIST fileref_lookaside;
+    PAGED_LOOKASIDE_LIST fcb_lookaside;
+    PAGED_LOOKASIDE_LIST name_bit_lookaside;
     NPAGED_LOOKASIDE_LIST range_lock_lookaside;
+    NPAGED_LOOKASIDE_LIST fileref_np_lookaside;
+    NPAGED_LOOKASIDE_LIST fcb_np_lookaside;
     LIST_ENTRY list_entry;
 } device_extension;
 
 typedef struct {
     UINT32 type;
-    PDEVICE_OBJECT devobj;
+    PDEVICE_OBJECT buspdo;
+    PDEVICE_OBJECT attached_device;
+    UNICODE_STRING bus_name;
+} control_device_extension;
+
+typedef struct {
     BTRFS_UUID uuid;
+    UINT64 devid;
+    UINT64 generation;
+    PDEVICE_OBJECT devobj;
+    PFILE_OBJECT fileobj;
+    UNICODE_STRING pnp_name;
+    UINT64 size;
+    BOOL seeding;
+    BOOL had_drive_letter;
+    void* notification_entry;
+    ULONG disk_num;
+    ULONG part_num;
+    LIST_ENTRY list_entry;
+} volume_child;
+
+struct pdo_device_extension;
+
+typedef struct _volume_device_extension {
+    UINT32 type;
     UNICODE_STRING name;
-} part0_device_extension;
+    PDEVICE_OBJECT device;
+    PDEVICE_OBJECT mounted_device;
+    PDEVICE_OBJECT pdo;
+    struct pdo_device_extension* pdode;
+    UNICODE_STRING bus_name;
+    PDEVICE_OBJECT attached_device;
+    BOOL removing;
+    LONG open_count;
+} volume_device_extension;
 
-typedef struct {
+typedef struct pdo_device_extension {
     UINT32 type;
-} control_device_extension;
+    BTRFS_UUID uuid;
+    volume_device_extension* vde;
+    PDEVICE_OBJECT pdo;
+    BOOL removable;
+
+    UINT64 num_children;
+    UINT64 children_loaded;
+    ERESOURCE child_lock;
+    LIST_ENTRY children;
+
+    LIST_ENTRY list_entry;
+} pdo_device_extension;
 
 typedef struct {
     LIST_ENTRY listentry;
@@ -661,6 +840,12 @@ typedef struct {
     UINT32 uid;
 } uid_map;
 
+typedef struct {
+    LIST_ENTRY listentry;
+    PSID sid;
+    UINT32 gid;
+} gid_map;
+
 enum write_data_status {
     WriteDataStatus_Pending,
     WriteDataStatus_Success,
@@ -675,7 +860,7 @@ struct _write_data_context;
 typedef struct {
     struct _write_data_context* context;
     UINT8* buf;
-    BOOL need_free;
+    PMDL mdl;
     device* device;
     PIRP Irp;
     IO_STATUS_BLOCK iosb;
@@ -687,24 +872,29 @@ typedef struct _write_data_context {
     KEVENT Event;
     LIST_ENTRY stripes;
     LONG stripes_left;
-    BOOL tree;
+    BOOL need_wait;
+    UINT8 *parity1, *parity2, *scratch;
+    PMDL mdl, parity1_mdl, parity2_mdl;
 } write_data_context;
 
 typedef struct {
     UINT64 address;
     UINT32 length;
-    BOOL overlap;
     UINT8* data;
+    chunk* c;
     LIST_ENTRY list_entry;
 } tree_write;
 
-// #pragma pack(pop)
+typedef struct {
+    UNICODE_STRING us;
+    LIST_ENTRY list_entry;
+} name_bit;
 
-static __inline void* map_user_buffer(PIRP Irp) {
+static __inline void* map_user_buffer(PIRP Irp, ULONG priority) {
     if (!Irp->MdlAddress) {
         return Irp->UserBuffer;
     } else {
-        return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+        return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, priority);
     }
 }
 
@@ -714,17 +904,18 @@ static __inline UINT64 unix_time_to_win(BTRFS_TIME* t) {
 
 static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME* out) {
     ULONGLONG l = t.QuadPart - 116444736000000000;
-    
+
     out->seconds = l / 10000000;
     out->nanoseconds = (l % 10000000) * 100;
 }
 
-static __inline void get_raid0_offset(UINT64 off, UINT64 stripe_length, UINT16 num_stripes, UINT64* stripeoff, UINT16* stripe) {
+_Post_satisfies_(*stripe>=0&&*stripe<num_stripes)
+static __inline void get_raid0_offset(_In_ UINT64 off, _In_ UINT64 stripe_length, _In_ UINT16 num_stripes, _Out_ UINT64* stripeoff, _Out_ UINT16* stripe) {
     UINT64 initoff, startoff;
-    
+
     startoff = off % (num_stripes * stripe_length);
     initoff = (off / (num_stripes * stripe_length)) * stripe_length;
-    
+
     *stripe = (UINT16)(startoff / stripe_length);
     *stripeoff = initoff + startoff - (*stripe * stripe_length);
 }
@@ -734,11 +925,7 @@ static __inline void get_raid0_offset(UINT64 off, UINT64 stripe_length, UINT16 n
  * five for the inode, which should be good enough.
  * Inodes are also 64 bits on Linux, but the Linux driver seems to get round
  * this by tricking it into thinking subvols are separate volumes. */
-#ifdef __REACTOS__
 static __inline UINT64 make_file_id(root* r, UINT64 inode) {
-#else
-static UINT64 __inline make_file_id(root* r, UINT64 inode) {
-#endif
     return (r->id << 40) | (inode & 0xffffffffff);
 }
 
@@ -751,38 +938,126 @@ static UINT64 __inline make_file_id(root* r, UINT64 inode) {
     ((key1.offset > key2.offset) ? 1 :\
     0))))))
 
+_Post_satisfies_(return>=n)
+__inline static UINT64 sector_align(_In_ UINT64 n, _In_ UINT64 a) {
+    if (n & (a - 1))
+        n = (n + a) & ~(a - 1);
+
+    return n;
+}
+
+__inline static BOOL is_subvol_readonly(root* r, PIRP Irp) {
+    if (!(r->root_item.flags & BTRFS_SUBVOL_READONLY))
+        return FALSE;
+
+    if (!r->reserved)
+        return TRUE;
+
+    return (!Irp || Irp->RequestorMode == UserMode) && PsGetCurrentProcess() != r->reserved ? TRUE : FALSE;
+}
+
+__inline static UINT16 get_extent_data_len(UINT8 type) {
+    switch (type) {
+        case TYPE_TREE_BLOCK_REF:
+            return sizeof(TREE_BLOCK_REF);
+
+        case TYPE_EXTENT_DATA_REF:
+            return sizeof(EXTENT_DATA_REF);
+
+        case TYPE_EXTENT_REF_V0:
+            return sizeof(EXTENT_REF_V0);
+
+        case TYPE_SHARED_BLOCK_REF:
+            return sizeof(SHARED_BLOCK_REF);
+
+        case TYPE_SHARED_DATA_REF:
+            return sizeof(SHARED_DATA_REF);
+
+        default:
+            return 0;
+    }
+}
+
+__inline static UINT32 get_extent_data_refcount(UINT8 type, void* data) {
+    switch (type) {
+        case TYPE_TREE_BLOCK_REF:
+            return 1;
+
+        case TYPE_EXTENT_DATA_REF:
+        {
+            EXTENT_DATA_REF* edr = (EXTENT_DATA_REF*)data;
+            return edr->count;
+        }
+
+        case TYPE_EXTENT_REF_V0:
+        {
+            EXTENT_REF_V0* erv0 = (EXTENT_REF_V0*)data;
+            return erv0->count;
+        }
+
+        case TYPE_SHARED_BLOCK_REF:
+            return 1;
+
+        case TYPE_SHARED_DATA_REF:
+        {
+            SHARED_DATA_REF* sdr = (SHARED_DATA_REF*)data;
+            return sdr->count;
+        }
+
+        default:
+            return 0;
+    }
+}
+
 // in btrfs.c
-device* find_device_from_uuid(device_extension* Vcb, BTRFS_UUID* uuid);
-UINT64 sector_align( UINT64 NumberToBeAligned, UINT64 Alignment );
-BOOL get_file_attributes_from_xattr(char* val, UINT16 len, ULONG* atts);
-ULONG STDCALL get_file_attributes(device_extension* Vcb, INODE_ITEM* ii, root* r, UINT64 inode, UINT8 type, BOOL dotfile, BOOL ignore_xa, PIRP Irp);
-BOOL extract_xattr(void* item, USHORT size, char* name, UINT8** data, UINT16* datalen);
-BOOL STDCALL get_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, UINT8** data, UINT16* datalen, PIRP Irp);
-void _free_fcb(fcb* fcb, const char* func, const char* file, unsigned int line);
-void _free_fileref(file_ref* fr, const char* func, const char* file, unsigned int line);
-fcb* create_fcb(POOL_TYPE pool_type);
-file_ref* create_fileref();
-void protect_superblocks(device_extension* Vcb, chunk* c);
-BOOL is_top_level(PIRP Irp);
-NTSTATUS create_root(device_extension* Vcb, UINT64 id, root** rootptr, BOOL no_tree, UINT64 offset, PIRP Irp, LIST_ENTRY* rollback);
-void STDCALL uninit(device_extension* Vcb, BOOL flush);
-NTSTATUS STDCALL dev_ioctl(PDEVICE_OBJECT DeviceObject, ULONG ControlCode, PVOID InputBuffer,
-                           ULONG InputBufferSize, PVOID OutputBuffer, ULONG OutputBufferSize, BOOLEAN Override, IO_STATUS_BLOCK* iosb);
-BOOL is_file_name_valid(PUNICODE_STRING us);
-void send_notification_fileref(file_ref* fileref, ULONG filter_match, ULONG action);
-void send_notification_fcb(file_ref* fileref, ULONG filter_match, ULONG action);
-WCHAR* file_desc(PFILE_OBJECT FileObject);
-WCHAR* file_desc_fileref(file_ref* fileref);
-BOOL add_thread_job(device_extension* Vcb, PIRP Irp);
-NTSTATUS part0_passthrough(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
-void mark_fcb_dirty(fcb* fcb);
-void mark_fileref_dirty(file_ref* fileref);
-NTSTATUS delete_fileref(file_ref* fileref, PFILE_OBJECT FileObject, PIRP Irp, LIST_ENTRY* rollback);
-void chunk_lock_range(device_extension* Vcb, chunk* c, UINT64 start, UINT64 length);
-void chunk_unlock_range(device_extension* Vcb, chunk* c, UINT64 start, UINT64 length);
-void init_device(device_extension* Vcb, device* dev, BOOL get_length, BOOL get_nums);
-void init_file_cache(PFILE_OBJECT FileObject, CC_FILE_SIZES* ccfs);
-NTSTATUS sync_read_phys(PDEVICE_OBJECT DeviceObject, LONGLONG StartingOffset, ULONG Length, PUCHAR Buffer, BOOL override);
+_Ret_maybenull_
+device* find_device_from_uuid(_In_ device_extension* Vcb, _In_ BTRFS_UUID* uuid);
+
+_Success_(return)
+BOOL get_file_attributes_from_xattr(_In_reads_bytes_(len) char* val, _In_ UINT16 len, _Out_ ULONG* atts);
+
+ULONG get_file_attributes(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ root* r, _In_ UINT64 inode,
+                          _In_ UINT8 type, _In_ BOOL dotfile, _In_ BOOL ignore_xa, _In_opt_ PIRP Irp);
+
+_Success_(return)
+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,
+               _Out_ UINT8** data, _Out_ UINT16* datalen, _In_opt_ PIRP Irp);
+
+#ifndef DEBUG_FCB_REFCOUNTS
+void free_fcb(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb, _Inout_ fcb* fcb);
+#endif
+void free_fileref(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb, _Inout_ file_ref* fr);
+void protect_superblocks(_Inout_ chunk* c);
+BOOL is_top_level(_In_ PIRP Irp);
+NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ UINT64 id,
+                     _Out_ root** rootptr, _In_ BOOL no_tree, _In_ UINT64 offset, _In_opt_ PIRP Irp);
+void uninit(_In_ device_extension* Vcb, _In_ BOOL flush);
+NTSTATUS dev_ioctl(_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG ControlCode, _In_reads_bytes_opt_(InputBufferSize) PVOID InputBuffer, _In_ ULONG InputBufferSize,
+                   _Out_writes_bytes_opt_(OutputBufferSize) PVOID OutputBuffer, _In_ ULONG OutputBufferSize, _In_ BOOLEAN Override, _Out_opt_ IO_STATUS_BLOCK* iosb);
+BOOL is_file_name_valid(_In_ PUNICODE_STRING us, _In_ BOOL posix);
+void send_notification_fileref(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream);
+void send_notification_fcb(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream);
+
+_Ret_z_
+WCHAR* file_desc(_In_ PFILE_OBJECT FileObject);
+WCHAR* file_desc_fileref(_In_ file_ref* fileref);
+void mark_fcb_dirty(_In_ fcb* fcb);
+void mark_fileref_dirty(_In_ file_ref* fileref);
+NTSTATUS delete_fileref(_In_ file_ref* fileref, _In_ PFILE_OBJECT FileObject, _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback);
+void chunk_lock_range(_In_ device_extension* Vcb, _In_ chunk* c, _In_ UINT64 start, _In_ UINT64 length);
+void chunk_unlock_range(_In_ device_extension* Vcb, _In_ chunk* c, _In_ UINT64 start, _In_ UINT64 length);
+void init_device(_In_ device_extension* Vcb, _Inout_ device* dev, _In_ BOOL get_nums);
+void init_file_cache(_In_ PFILE_OBJECT FileObject, _In_ CC_FILE_SIZES* ccfs);
+NTSTATUS sync_read_phys(_In_ PDEVICE_OBJECT DeviceObject, _In_ UINT64 StartingOffset, _In_ ULONG Length,
+                        _Out_writes_bytes_(Length) PUCHAR Buffer, _In_ BOOL override);
+NTSTATUS get_device_pnp_name(_In_ PDEVICE_OBJECT DeviceObject, _Out_ PUNICODE_STRING pnp_name, _Out_ const GUID** guid);
+void log_device_error(_In_ device_extension* Vcb, _Inout_ device* dev, _In_ int error);
+NTSTATUS find_chunk_usage(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_opt_ PIRP Irp);
+#ifdef __REACTOS__
+NTSTATUS NTAPI AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject);
+#else
+NTSTATUS AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject);
+#endif
 
 #ifdef _MSC_VER
 #define funcname __FUNCTION__
@@ -790,10 +1065,6 @@ NTSTATUS sync_read_phys(PDEVICE_OBJECT DeviceObject, LONGLONG StartingOffset, UL
 #define funcname __func__
 #endif
 
-// FIXME - we probably shouldn't be moving funcname etc. around if we're not printing debug messages
-#define free_fcb(fcb) _free_fcb(fcb, funcname, __FILE__, __LINE__)
-#define free_fileref(fileref) _free_fileref(fileref, funcname, __FILE__, __LINE__)
-
 extern BOOL have_sse2;
 
 extern UINT32 mount_compress;
@@ -802,9 +1073,13 @@ extern UINT32 mount_compress_type;
 extern UINT32 mount_zlib_level;
 extern UINT32 mount_flush_interval;
 extern UINT32 mount_max_inline;
-extern UINT32 mount_raid5_recalculation;
-extern UINT32 mount_raid6_recalculation;
 extern UINT32 mount_skip_balance;
+extern UINT32 mount_no_barrier;
+extern UINT32 mount_no_trim;
+extern UINT32 mount_clear_cache;
+extern UINT32 mount_allow_degraded;
+extern UINT32 mount_readonly;
+extern UINT32 no_pnp;
 
 #ifdef _DEBUG
 
@@ -820,7 +1095,7 @@ extern UINT32 debug_log_level;
 #define FIXME(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
 #define ERR(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
 
-void STDCALL _debug_message(const char* func, const char* file, unsigned int line, char* s, ...);
+void _debug_message(_In_ const char* func, _In_ const char* file, _In_ unsigned int line, _In_ char* s, ...);
 
 #else
 
@@ -831,7 +1106,7 @@ void STDCALL _debug_message(const char* func, const char* file, unsigned int lin
 #define FIXME(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
 #define ERR(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
 
-void STDCALL _debug_message(const char* func, char* s, ...);
+void _debug_message(_In_ const char* func, _In_ char* s, ...);
 
 #endif
 
@@ -839,27 +1114,21 @@ void STDCALL _debug_message(const char* func, char* s, ...);
 
 #define TRACE(s, ...)
 #define WARN(s, ...)
-#ifndef __REACTOS__
-#define FIXME(s, ...) DbgPrint("Btrfs FIXME : " funcname " : " s, ##__VA_ARGS__)
-#define ERR(s, ...) DbgPrint("Btrfs ERR : " funcname " : " s, ##__VA_ARGS__)
-#else
 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__)
 #define ERR(s, ...) DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__)
-#endif
 
 #endif
 
-static __inline void increase_chunk_usage(chunk* c, UINT64 delta) {
-    c->used += delta;
-    
-    TRACE("increasing size of chunk %llx by %llx\n", c->offset, delta);
-}
+#ifdef DEBUG_FCB_REFCOUNTS
+void _free_fcb(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb, _Inout_ fcb* fcb, _In_ const char* func);
+#define free_fcb(Vcb, fcb) _free_fcb(Vcb, fcb, funcname)
+#endif
 
 // in fastio.c
-void STDCALL init_fast_io_dispatch(FAST_IO_DISPATCH** fiod);
+void init_fast_io_dispatch(FAST_IO_DISPATCH** fiod);
 
 // in crc32c.c
-UINT32 STDCALL calc_crc32c(UINT32 seed, UINT8* msg, ULONG msglen);
+UINT32 calc_crc32c(_In_ UINT32 seed, _In_reads_bytes_(msglen) UINT8* msg, _In_ ULONG msglen);
 
 typedef struct {
     LIST_ENTRY* list;
@@ -875,8 +1144,6 @@ typedef struct {
 } rollback_extent;
 
 enum rollback_type {
-    ROLLBACK_INSERT_ITEM,
-    ROLLBACK_DELETE_ITEM,
     ROLLBACK_INSERT_EXTENT,
     ROLLBACK_DELETE_EXTENT,
     ROLLBACK_ADD_SPACE,
@@ -890,92 +1157,145 @@ typedef struct {
 } rollback_item;
 
 // in treefuncs.c
-NTSTATUS STDCALL _find_item(device_extension* Vcb, root* r, traverse_ptr* tp, const KEY* searchkey, BOOL ignore, PIRP Irp, const char* func, const char* file, unsigned int line);
-NTSTATUS STDCALL _find_item_to_level(device_extension* Vcb, root* r, traverse_ptr* tp, const KEY* searchkey, BOOL ignore, UINT8 level,
-                                     PIRP Irp, const char* func, const char* file, unsigned int line);
-BOOL STDCALL _find_next_item(device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* next_tp, BOOL ignore, PIRP Irp, const char* func, const char* file, unsigned int line);
-BOOL STDCALL _find_prev_item(device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* prev_tp, BOOL ignore, PIRP Irp, const char* func, const char* file, unsigned int line);
-void STDCALL free_trees(device_extension* Vcb);
-BOOL STDCALL insert_tree_item(device_extension* Vcb, root* r, UINT64 obj_id, UINT8 obj_type, UINT64 offset, void* data, UINT32 size, traverse_ptr* ptp, PIRP Irp, LIST_ENTRY* rollback);
-void STDCALL delete_tree_item(device_extension* Vcb, traverse_ptr* tp, LIST_ENTRY* rollback);
-tree* STDCALL _free_tree(tree* t, const char* func, const char* file, unsigned int line);
-NTSTATUS STDCALL _load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, tree* parent, PIRP Irp, const char* func, const char* file, unsigned int line);
-NTSTATUS STDCALL _do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, BOOL* loaded, PIRP Irp,
-                               const char* func, const char* file, unsigned int line);
-void clear_rollback(device_extension* Vcb, LIST_ENTRY* rollback);
+NTSTATUS find_item(_In_ _Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ root* r, _Out_ traverse_ptr* tp,
+                   _In_ const KEY* searchkey, _In_ BOOL ignore, _In_opt_ PIRP Irp);
+NTSTATUS find_item_to_level(device_extension* Vcb, root* r, traverse_ptr* tp, const KEY* searchkey, BOOL ignore, UINT8 level, PIRP Irp);
+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);
+BOOL find_prev_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* prev_tp, PIRP Irp);
+void free_trees(device_extension* Vcb);
+NTSTATUS insert_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _In_ root* r, _In_ UINT64 obj_id,
+                          _In_ UINT8 obj_type, _In_ UINT64 offset, _In_reads_bytes_opt_(size) _When_(return >= 0, __drv_aliasesMem) void* data,
+                          _In_ UINT16 size, _Out_opt_ traverse_ptr* ptp, _In_opt_ PIRP Irp);
+NTSTATUS delete_tree_item(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, _Inout_ traverse_ptr* tp);
+tree* free_tree(tree* t);
+NTSTATUS load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, UINT64 generation, PIRP Irp);
+NTSTATUS do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, BOOL* loaded, PIRP Irp);
+void clear_rollback(LIST_ENTRY* rollback);
 void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback);
 void free_trees_root(device_extension* Vcb, root* r);
-void add_rollback(device_extension* Vcb, LIST_ENTRY* rollback, enum rollback_type type, void* ptr);
-void commit_batch_list(device_extension* Vcb, LIST_ENTRY* batchlist, PIRP Irp, LIST_ENTRY* rollback);
+void add_rollback(_In_ LIST_ENTRY* rollback, _In_ enum rollback_type type, _In_ __drv_aliasesMem void* ptr);
+NTSTATUS commit_batch_list(_Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb, LIST_ENTRY* batchlist, PIRP Irp);
 void clear_batch_list(device_extension* Vcb, LIST_ENTRY* batchlist);
-
-#define find_item(Vcb, r, tp, searchkey, ignore, Irp) _find_item(Vcb, r, tp, searchkey, ignore, Irp, funcname, __FILE__, __LINE__)
-#define find_item_to_level(Vcb, r, tp, searchkey, ignore, level, Irp) _find_item_to_level(Vcb, r, tp, searchkey, ignore, level, Irp, funcname, __FILE__, __LINE__)
-#define find_next_item(Vcb, tp, next_tp, ignore, Irp) _find_next_item(Vcb, tp, next_tp, ignore, Irp, funcname, __FILE__, __LINE__)
-#define find_prev_item(Vcb, tp, prev_tp, ignore, Irp) _find_prev_item(Vcb, tp, prev_tp, ignore, Irp, funcname, __FILE__, __LINE__)
-#define free_tree(t) _free_tree(t, funcname, __FILE__, __LINE__)
-#define load_tree(t, addr, r, pt, parent, Irp) _load_tree(t, addr, r, pt, parent, Irp, funcname, __FILE__, __LINE__)
-#define do_load_tree(Vcb, th, r, t, td, loaded, Irp) _do_load_tree(Vcb, th, r, t, td, loaded, Irp, funcname, __FILE__, __LINE__)  
+NTSTATUS skip_to_difference(device_extension* Vcb, traverse_ptr* tp, traverse_ptr* tp2, BOOL* ended1, BOOL* ended2);
 
 // in search.c
-void remove_drive_letter(PDEVICE_OBJECT mountmgr, volume* v);
-void add_volume(PDEVICE_OBJECT mountmgr, PUNICODE_STRING us);
+NTSTATUS remove_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath);
+
+_Function_class_(KSTART_ROUTINE)
+#ifdef __REACTOS__
+void NTAPI mountmgr_thread(_In_ void* context);
+#else
+void mountmgr_thread(_In_ void* context);
+#endif
+
+_Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE)
 #ifdef __REACTOS__
 NTSTATUS NTAPI pnp_notification(PVOID NotificationStructure, PVOID Context);
 #else
 NTSTATUS pnp_notification(PVOID NotificationStructure, PVOID Context);
 #endif
 
+void disk_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath);
+void volume_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath);
+void volume_removal(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath);
+
+_Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE)
+#ifdef __REACTOS__
+NTSTATUS NTAPI volume_notification(PVOID NotificationStructure, PVOID Context);
+#else
+NTSTATUS volume_notification(PVOID NotificationStructure, PVOID Context);
+#endif
+
+void remove_volume_child(_Inout_ _Requires_exclusive_lock_held_(_Curr_->child_lock) _Releases_exclusive_lock_(_Curr_->child_lock) _In_ volume_device_extension* vde,
+                         _In_ volume_child* vc, _In_ BOOL skip_dev);
+
 // in cache.c
-NTSTATUS STDCALL init_cache();
-void STDCALL free_cache();
+NTSTATUS init_cache();
+void free_cache();
 extern CACHE_MANAGER_CALLBACKS* cache_callbacks;
 
 // in write.c
-NTSTATUS write_file(device_extension* Vcb, PIRP Irp, BOOL wait, BOOL deferred_write);
-NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void* buf, ULONG* length, BOOL paging_io, BOOL no_cache,
-                     BOOL wait, BOOL deferred_write, LIST_ENTRY* rollback);
+NTSTATUS write_file(device_extension* Vcb, PIRP Irp, BOOLEAN wait, BOOLEAN deferred_write);
+NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void* buf, ULONG* length, BOOLEAN paging_io, BOOLEAN no_cache,
+                     BOOLEAN wait, BOOLEAN deferred_write, BOOLEAN write_irp, LIST_ENTRY* rollback);
 NTSTATUS truncate_file(fcb* fcb, UINT64 end, PIRP Irp, LIST_ENTRY* rollback);
 NTSTATUS extend_file(fcb* fcb, file_ref* fileref, UINT64 end, BOOL prealloc, PIRP Irp, LIST_ENTRY* rollback);
 NTSTATUS excise_extents(device_extension* Vcb, fcb* fcb, UINT64 start_data, UINT64 end_data, PIRP Irp, LIST_ENTRY* rollback);
 chunk* get_chunk_from_address(device_extension* Vcb, UINT64 address);
-chunk* alloc_chunk(device_extension* Vcb, UINT64 flags);
-NTSTATUS STDCALL write_data(device_extension* Vcb, UINT64 address, void* data, BOOL need_free, UINT32 length, write_data_context* wtc, PIRP Irp, chunk* c);
-NTSTATUS STDCALL write_data_complete(device_extension* Vcb, UINT64 address, void* data, UINT32 length, PIRP Irp, chunk* c);
+NTSTATUS alloc_chunk(device_extension* Vcb, UINT64 flags, chunk** pc, BOOL full_size);
+NTSTATUS write_data(_In_ device_extension* Vcb, _In_ UINT64 address, _In_reads_bytes_(length) void* data, _In_ UINT32 length, _In_ write_data_context* wtc,
+                    _In_opt_ PIRP Irp, _In_opt_ chunk* c, _In_ BOOL file_write, _In_ UINT64 irp_offset, _In_ ULONG priority);
+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);
 void free_write_data_stripes(write_data_context* wtc);
-NTSTATUS STDCALL drv_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
-BOOL insert_extent_chunk(device_extension* Vcb, fcb* fcb, chunk* c, UINT64 start_data, UINT64 length, BOOL prealloc, void* data,
-                         PIRP Irp, LIST_ENTRY* rollback, UINT8 compression, UINT64 decoded_size);
-NTSTATUS insert_extent(device_extension* Vcb, fcb* fcb, UINT64 start_data, UINT64 length, void* data, PIRP Irp, LIST_ENTRY* rollback);
-NTSTATUS do_write_file(fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, PIRP Irp, LIST_ENTRY* rollback);
+
+_Dispatch_type_(IRP_MJ_WRITE)
+_Function_class_(DRIVER_DISPATCH)
+NTSTATUS drv_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+
+_Requires_lock_held_(c->lock)
+_When_(return != 0, _Releases_lock_(c->lock))
+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,
+                         _In_opt_ PIRP Irp, _In_ LIST_ENTRY* rollback, _In_ UINT8 compression, _In_ UINT64 decoded_size, _In_ BOOL file_write, _In_ UINT64 irp_offset);
+
+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);
 NTSTATUS write_compressed(fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, PIRP Irp, LIST_ENTRY* rollback);
 BOOL find_data_address_in_chunk(device_extension* Vcb, chunk* c, UINT64 length, UINT64* address);
 void get_raid56_lock_range(chunk* c, UINT64 address, UINT64 length, UINT64* lockaddr, UINT64* locklen);
+NTSTATUS calc_csum(_In_ device_extension* Vcb, _In_reads_bytes_(sectors*Vcb->superblock.sector_size) UINT8* data,
+                   _In_ UINT32 sectors, _Out_writes_bytes_(sectors*sizeof(UINT32)) UINT32* csum);
+void add_insert_extent_rollback(LIST_ENTRY* rollback, fcb* fcb, extent* ext);
+NTSTATUS add_extent_to_fcb(_In_ fcb* fcb, _In_ UINT64 offset, _In_reads_bytes_(edsize) EXTENT_DATA* ed, _In_ UINT16 edsize,
+                           _In_ BOOL unique, _In_opt_ _When_(return >= 0, __drv_aliasesMem) UINT32* csum, _In_ LIST_ENTRY* rollback);
+void add_extent(_In_ fcb* fcb, _In_ LIST_ENTRY* prevextle, _In_ __drv_aliasesMem extent* newext);
 
 // in dirctrl.c
-NTSTATUS STDCALL drv_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
-ULONG STDCALL get_reparse_tag(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 type, ULONG atts, PIRP Irp);
+
+_Dispatch_type_(IRP_MJ_DIRECTORY_CONTROL)
+_Function_class_(DRIVER_DISPATCH)
+NTSTATUS drv_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+
+ULONG get_reparse_tag(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 type, ULONG atts, BOOL lxss, PIRP Irp);
 
 // in security.c
-NTSTATUS STDCALL drv_query_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
-NTSTATUS STDCALL drv_set_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
-BOOL get_sd_from_xattr(fcb* fcb, ULONG buflen);
+
+_Dispatch_type_(IRP_MJ_QUERY_SECURITY)
+_Function_class_(DRIVER_DISPATCH)
+NTSTATUS drv_query_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+
+_Dispatch_type_(IRP_MJ_SET_SECURITY)
+_Function_class_(DRIVER_DISPATCH)
+NTSTATUS drv_set_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+
 void fcb_get_sd(fcb* fcb, struct _fcb* parent, BOOL look_for_xattr, PIRP Irp);
-// UINT32 STDCALL get_uid();
 void add_user_mapping(WCHAR* sidstring, ULONG sidstringlength, UINT32 uid);
+void add_group_mapping(WCHAR* sidstring, ULONG sidstringlength, UINT32 gid);
 UINT32 sid_to_uid(PSID sid);
-void uid_to_sid(UINT32 uid, PSID* sid);
+NTSTATUS uid_to_sid(UINT32 uid, PSID* sid);
 NTSTATUS fcb_get_new_sd(fcb* fcb, file_ref* parfileref, ACCESS_STATE* as);
+void find_gid(struct _fcb* fcb, struct _fcb* parfcb, PSECURITY_SUBJECT_CONTEXT subjcont);
 
 // in fileinfo.c
-NTSTATUS STDCALL drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
-NTSTATUS STDCALL drv_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+
+_Dispatch_type_(IRP_MJ_SET_INFORMATION)
+_Function_class_(DRIVER_DISPATCH)
+NTSTATUS drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+
+_Dispatch_type_(IRP_MJ_QUERY_INFORMATION)
+_Function_class_(DRIVER_DISPATCH)
+NTSTATUS drv_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+
+_Dispatch_type_(IRP_MJ_QUERY_EA)
+_Function_class_(DRIVER_DISPATCH)
+NTSTATUS drv_query_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+
+_Dispatch_type_(IRP_MJ_SET_EA)
+_Function_class_(DRIVER_DISPATCH)
+NTSTATUS drv_set_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+
 BOOL has_open_children(file_ref* fileref);
-NTSTATUS STDCALL stream_set_end_of_file_information(device_extension* Vcb, UINT64 end, fcb* fcb, file_ref* fileref, PFILE_OBJECT FileObject, BOOL advance_only, LIST_ENTRY* rollback);
-NTSTATUS fileref_get_filename(file_ref* fileref, PUNICODE_STRING fn, USHORT* name_offset);
-NTSTATUS open_fileref_by_inode(device_extension* Vcb, root* subvol, UINT64 inode, file_ref** pfr, PIRP Irp);
-NTSTATUS STDCALL drv_query_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
-NTSTATUS STDCALL drv_set_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS stream_set_end_of_file_information(device_extension* Vcb, UINT16 end, fcb* fcb, file_ref* fileref, BOOL advance_only);
+NTSTATUS fileref_get_filename(file_ref* fileref, PUNICODE_STRING fn, USHORT* name_offset, ULONG* preqlen);
+NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension* Vcb, root* subvol, UINT64 inode, file_ref** pfr, PIRP Irp);
 void insert_dir_child_into_hash_lists(fcb* fcb, dir_child* dc);
 void remove_dir_child_from_hash_lists(fcb* fcb, dir_child* dc);
 
@@ -985,92 +1305,128 @@ NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 NTSTATUS delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 
 // in create.c
-NTSTATUS STDCALL drv_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
-NTSTATUS open_fileref(device_extension* Vcb, file_ref** pfr, PUNICODE_STRING fnus, file_ref* related, BOOL parent, USHORT* parsed, ULONG* fn_offset,
-                      POOL_TYPE pooltype, BOOL case_sensitive, PIRP Irp);
-NTSTATUS open_fcb(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 type, PANSI_STRING utf8, fcb* parent, fcb** pfcb, POOL_TYPE pooltype, PIRP Irp);
-NTSTATUS open_fcb_stream(device_extension* Vcb, root* subvol, UINT64 inode, ANSI_STRING* xattr, UINT32 streamhash, fcb* parent, fcb** pfcb, PIRP Irp);
-void insert_fileref_child(file_ref* parent, file_ref* child, BOOL do_lock);
-NTSTATUS fcb_get_last_dir_index(fcb* fcb, UINT64* index, PIRP Irp);
-NTSTATUS verify_vcb(device_extension* Vcb, PIRP Irp);
-NTSTATUS load_csum(device_extension* Vcb, UINT32* csum, UINT64 start, UINT64 length, PIRP Irp);
-NTSTATUS load_dir_children(fcb* fcb, BOOL ignore_size, PIRP Irp);
-NTSTATUS add_dir_child(fcb* fcb, UINT64 inode, BOOL subvol, UINT64 index, PANSI_STRING utf8, PUNICODE_STRING name, PUNICODE_STRING name_uc, UINT8 type, dir_child** pdc);
+
+_Dispatch_type_(IRP_MJ_CREATE)
+_Function_class_(DRIVER_DISPATCH)
+NTSTATUS drv_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+
+NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb, _Out_ file_ref** pfr,
+                      _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,
+                      _In_ BOOL case_sensitive, _In_opt_ PIRP Irp);
+NTSTATUS open_fcb(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) device_extension* Vcb,
+                  root* subvol, UINT64 inode, UINT8 type, PANSI_STRING utf8, fcb* parent, fcb** pfcb, POOL_TYPE pooltype, PIRP Irp);
+NTSTATUS load_csum(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, UINT32* csum, UINT64 start, UINT64 length, PIRP Irp);
+NTSTATUS load_dir_children(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb, fcb* fcb, BOOL ignore_size, PIRP Irp);
+NTSTATUS add_dir_child(fcb* fcb, UINT64 inode, BOOL subvol, PANSI_STRING utf8, PUNICODE_STRING name, UINT8 type, dir_child** pdc);
+NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusive_lock_held_(_Curr_->fcb_lock) _In_ device_extension* Vcb,
+                            _In_ file_ref* sf, _In_ PUNICODE_STRING name, _In_ BOOL case_sensitive, _In_ BOOL lastpart, _In_ BOOL streampart,
+                            _In_ POOL_TYPE pooltype, _Out_ file_ref** psf2, _In_opt_ PIRP Irp);
+fcb* create_fcb(device_extension* Vcb, POOL_TYPE pool_type);
+NTSTATUS find_file_in_dir(PUNICODE_STRING filename, fcb* fcb, root** subvol, UINT64* inode, dir_child** pdc, BOOL case_sensitive);
+UINT32 inherit_mode(fcb* parfcb, BOOL is_dir);
+file_ref* create_fileref(device_extension* Vcb);
 
 // in fsctl.c
-NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP Irp, UINT32 type, BOOL user);
+NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP* Pirp, UINT32 type);
 void do_unlock_volume(device_extension* Vcb);
+void trim_whole_device(device* dev);
+void flush_subvol_fcbs(root* subvol);
+BOOL fcb_is_inline(fcb* fcb);
 
 // in flushthread.c
-void STDCALL flush_thread(void* context);
-NTSTATUS STDCALL do_write(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback);
+
+_Function_class_(KSTART_ROUTINE)
+#ifdef __REACTOS__
+void NTAPI flush_thread(void* context);
+#else
+void flush_thread(void* context);
+#endif
+
+NTSTATUS do_write(device_extension* Vcb, PIRP Irp);
 NTSTATUS get_tree_new_address(device_extension* Vcb, tree* t, PIRP Irp, LIST_ENTRY* rollback);
-void flush_fcb(fcb* fcb, BOOL cache, LIST_ENTRY* batchlist, PIRP Irp, LIST_ENTRY* rollback);
-NTSTATUS STDCALL write_data_phys(PDEVICE_OBJECT device, UINT64 address, void* data, UINT32 length);
+NTSTATUS flush_fcb(fcb* fcb, BOOL cache, LIST_ENTRY* batchlist, PIRP Irp);
+NTSTATUS write_data_phys(_In_ PDEVICE_OBJECT device, _In_ UINT64 address, _In_reads_bytes_(length) void* data, _In_ UINT32 length);
 BOOL is_tree_unique(device_extension* Vcb, tree* t, PIRP Irp);
-NTSTATUS do_tree_writes(device_extension* Vcb, LIST_ENTRY* tree_writes, PIRP Irp);
-void add_checksum_entry(device_extension* Vcb, UINT64 address, ULONG length, UINT32* csum, PIRP Irp, LIST_ENTRY* rollback);
+NTSTATUS do_tree_writes(device_extension* Vcb, LIST_ENTRY* tree_writes, BOOL no_free);
+void add_checksum_entry(device_extension* Vcb, UINT64 address, ULONG length, UINT32* csum, PIRP Irp);
 BOOL find_metadata_address_in_chunk(device_extension* Vcb, chunk* c, UINT64* address);
+void add_trim_entry_avoid_sb(device_extension* Vcb, device* dev, UINT64 address, UINT64 size);
+NTSTATUS insert_tree_item_batch(LIST_ENTRY* batchlist, device_extension* Vcb, root* r, UINT64 objid, UINT8 objtype, UINT64 offset,
+                                _In_opt_ _When_(return >= 0, __drv_aliasesMem) void* data, UINT16 datalen, enum batch_operation operation);
+NTSTATUS flush_partial_stripe(device_extension* Vcb, chunk* c, partial_stripe* ps);
+NTSTATUS update_dev_item(device_extension* Vcb, device* device, PIRP Irp);
 
 // in read.c
-NTSTATUS STDCALL drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp);
-NTSTATUS STDCALL read_data(device_extension* Vcb, UINT64 addr, UINT32 length, UINT32* csum, BOOL is_tree, UINT8* buf, chunk* c, chunk** pc,
-                           PIRP Irp, BOOL check_nocsum_parity);
-NTSTATUS STDCALL read_file(fcb* fcb, UINT8* data, UINT64 start, UINT64 length, ULONG* pbr, PIRP Irp, BOOL check_nocsum_parity);
-NTSTATUS do_read(PIRP Irp, BOOL wait, ULONG* bytes_read);
+
+_Dispatch_type_(IRP_MJ_READ)
+_Function_class_(DRIVER_DISPATCH)
+NTSTATUS drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+
+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,
+                   _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,
+                   _In_ ULONG priority);
+NTSTATUS read_file(fcb* fcb, UINT8* data, UINT64 start, UINT64 length, ULONG* pbr, PIRP Irp);
+NTSTATUS read_stream(fcb* fcb, UINT8* data, UINT64 start, ULONG length, ULONG* pbr);
+NTSTATUS do_read(PIRP Irp, BOOLEAN wait, ULONG* bytes_read);
+NTSTATUS check_csum(device_extension* Vcb, UINT8* data, UINT32 sectors, UINT32* csum);
+void raid6_recover2(UINT8* sectors, UINT16 num_stripes, ULONG sector_size, UINT16 missing1, UINT16 missing2, UINT8* out);
 
 // in pnp.c
-NTSTATUS STDCALL drv_pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+
+_Dispatch_type_(IRP_MJ_PNP)
+_Function_class_(DRIVER_DISPATCH)
+NTSTATUS drv_pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+
+NTSTATUS pnp_surprise_removal(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+NTSTATUS pnp_query_remove_device(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 
 // in free-space.c
-NTSTATUS load_free_space_cache(device_extension* Vcb, chunk* c, PIRP Irp);
+NTSTATUS load_cache_chunk(device_extension* Vcb, chunk* c, PIRP Irp);
 NTSTATUS clear_free_space_cache(device_extension* Vcb, LIST_ENTRY* batchlist, PIRP Irp);
 NTSTATUS allocate_cache(device_extension* Vcb, BOOL* changed, PIRP Irp, LIST_ENTRY* rollback);
 NTSTATUS update_chunk_caches(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback);
+NTSTATUS update_chunk_caches_tree(device_extension* Vcb, PIRP Irp);
 NTSTATUS add_space_entry(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 offset, UINT64 size);
-void _space_list_add(device_extension* Vcb, chunk* c, BOOL deleting, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func);
-void _space_list_add2(device_extension* Vcb, LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, chunk* c, LIST_ENTRY* rollback, const char* func);
-void _space_list_subtract(device_extension* Vcb, chunk* c, BOOL deleting, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func);
-void _space_list_subtract2(device_extension* Vcb, LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, chunk* c, LIST_ENTRY* rollback, const char* func);
-
-#define space_list_add(Vcb, c, deleting, address, length, rollback) _space_list_add(Vcb, c, deleting, address, length, rollback, funcname)
-#define space_list_add2(Vcb, list, list_size, address, length, rollback) _space_list_add2(Vcb, list, list_size, address, length, NULL, rollback, funcname)
-#define space_list_subtract(Vcb, c, deleting, address, length, rollback) _space_list_subtract(Vcb, c, deleting, address, length, rollback, funcname)
-#define space_list_subtract2(Vcb, list, list_size, address, length, rollback) _space_list_subtract2(Vcb, list, list_size, address, length, NULL, rollback, funcname)
+void space_list_add(chunk* c, UINT64 address, UINT64 length, LIST_ENTRY* rollback);
+void space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, chunk* c, LIST_ENTRY* rollback);
+void space_list_subtract(chunk* c, BOOL deleting, UINT64 address, UINT64 length, LIST_ENTRY* rollback);
+void space_list_subtract2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, chunk* c, LIST_ENTRY* rollback);
+NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, BOOL load_only, PIRP Irp);
 
 // in extent-tree.c
-NTSTATUS increase_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode, UINT64 offset, UINT32 refcount, PIRP Irp, LIST_ENTRY* rollback);
+NTSTATUS increase_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode, UINT64 offset, UINT32 refcount, PIRP Irp);
 NTSTATUS decrease_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode, UINT64 offset,
-                                       UINT32 refcount, BOOL superseded, PIRP Irp, LIST_ENTRY* rollback);
-NTSTATUS decrease_extent_refcount_tree(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT8 level, PIRP Irp, LIST_ENTRY* rollback);
-void decrease_chunk_usage(chunk* c, UINT64 delta);
-// NTSTATUS convert_old_data_extent(device_extension* Vcb, UINT64 address, UINT64 size, PIRP Irp, LIST_ENTRY* rollback);
+                                       UINT32 refcount, BOOL superseded, PIRP Irp);
+NTSTATUS decrease_extent_refcount_tree(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT8 level, PIRP Irp);
 UINT64 get_extent_refcount(device_extension* Vcb, UINT64 address, UINT64 size, PIRP Irp);
 BOOL is_extent_unique(device_extension* Vcb, UINT64 address, UINT64 size, PIRP Irp);
-NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT8 type, void* data, KEY* firstitem, UINT8 level, PIRP Irp, LIST_ENTRY* rollback);
+NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT8 type, void* data, KEY* firstitem, UINT8 level, PIRP Irp);
 UINT64 get_extent_flags(device_extension* Vcb, UINT64 address, PIRP Irp);
 void update_extent_flags(device_extension* Vcb, UINT64 address, UINT64 flags, PIRP Irp);
 NTSTATUS update_changed_extent_ref(device_extension* Vcb, chunk* c, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset,
-                                   signed long long count, BOOL no_csum, BOOL superseded, PIRP Irp);
+                                   INT32 count, BOOL no_csum, BOOL superseded, PIRP Irp);
 void add_changed_extent_ref(chunk* c, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset, UINT32 count, BOOL no_csum);
 UINT64 find_extent_shared_tree_refcount(device_extension* Vcb, UINT64 address, UINT64 parent, PIRP Irp);
-UINT64 find_extent_shared_data_refcount(device_extension* Vcb, UINT64 address, UINT64 parent, PIRP Irp);
+UINT32 find_extent_shared_data_refcount(device_extension* Vcb, UINT64 address, UINT64 parent, PIRP Irp);
 NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT8 type, void* data, KEY* firstitem,
-                                  UINT8 level, UINT64 parent, BOOL superseded, PIRP Irp, LIST_ENTRY* rollback);
+                                  UINT8 level, UINT64 parent, BOOL superseded, PIRP Irp);
 UINT64 get_extent_data_ref_hash2(UINT64 root, UINT64 objid, UINT64 offset);
 
 // in worker-thread.c
 void do_read_job(PIRP Irp);
 void do_write_job(device_extension* Vcb, PIRP Irp);
+BOOL add_thread_job(device_extension* Vcb, PIRP Irp);
 
 // in registry.c
-void STDCALL read_registry(PUNICODE_STRING regpath);
+void read_registry(PUNICODE_STRING regpath, BOOL refresh);
 NTSTATUS registry_mark_volume_mounted(BTRFS_UUID* uuid);
 NTSTATUS registry_mark_volume_unmounted(BTRFS_UUID* uuid);
 NTSTATUS registry_load_volume_options(device_extension* Vcb);
+void watch_registry(HANDLE regh);
 
 // in compress.c
-NTSTATUS decompress(UINT8 type, UINT8* inbuf, UINT64 inlen, UINT8* outbuf, UINT64 outlen);
+NTSTATUS zlib_decompress(UINT8* inbuf, UINT32 inlen, UINT8* outbuf, UINT32 outlen);
+NTSTATUS lzo_decompress(UINT8* inbuf, UINT32 inlen, UINT8* outbuf, UINT32 outlen, UINT32 inpageoff);
 NTSTATUS write_compressed_bit(fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, BOOL* compressed, PIRP Irp, LIST_ENTRY* rollback);
 
 // in galois.c
@@ -1081,14 +1437,20 @@ UINT8 gmul(UINT8 a, UINT8 b);
 UINT8 gdiv(UINT8 a, UINT8 b);
 
 // in devctrl.c
-NTSTATUS STDCALL drv_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+
+_Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
+_Function_class_(DRIVER_DISPATCH)
+NTSTATUS drv_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
 
 // in calcthread.c
+
+_Function_class_(KSTART_ROUTINE)
 #ifdef __REACTOS__
 void NTAPI calc_thread(void* context);
 #else
 void calc_thread(void* context);
 #endif
+
 NTSTATUS add_calc_job(device_extension* Vcb, UINT8* data, UINT32 sectors, UINT32* csum, calc_job** pcj);
 void free_calc_job(calc_job* cj);
 
@@ -1098,9 +1460,61 @@ NTSTATUS query_balance(device_extension* Vcb, void* data, ULONG length);
 NTSTATUS pause_balance(device_extension* Vcb, KPROCESSOR_MODE processor_mode);
 NTSTATUS resume_balance(device_extension* Vcb, KPROCESSOR_MODE processor_mode);
 NTSTATUS stop_balance(device_extension* Vcb, KPROCESSOR_MODE processor_mode);
-NTSTATUS look_for_balance_item(device_extension* Vcb);
+NTSTATUS look_for_balance_item(_Requires_lock_held_(_Curr_->tree_lock) device_extension* Vcb);
 NTSTATUS remove_device(device_extension* Vcb, void* data, ULONG length, KPROCESSOR_MODE processor_mode);
 
+_Function_class_(KSTART_ROUTINE)
+#ifdef __REACTOS__
+void NTAPI balance_thread(void* context);
+#else
+void balance_thread(void* context);
+#endif
+
+// in volume.c
+NTSTATUS vol_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_close(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_read(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_query_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_set_ea(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_flush_buffers(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_query_volume_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_set_volume_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_cleanup(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_file_system_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_lock_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_shutdown(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_query_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_set_security(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+NTSTATUS vol_power(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+void add_volume_device(superblock* sb, PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath, UINT64 length, ULONG disk_num, ULONG part_num);
+NTSTATUS mountmgr_add_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath);
+
+_Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE)
+#ifdef __REACTOS__
+NTSTATUS NTAPI pnp_removal(PVOID NotificationStructure, PVOID Context);
+#else
+NTSTATUS pnp_removal(PVOID NotificationStructure, PVOID Context);
+#endif
+
+// in scrub.c
+NTSTATUS start_scrub(device_extension* Vcb, KPROCESSOR_MODE processor_mode);
+NTSTATUS query_scrub(device_extension* Vcb, KPROCESSOR_MODE processor_mode, void* data, ULONG length);
+NTSTATUS pause_scrub(device_extension* Vcb, KPROCESSOR_MODE processor_mode);
+NTSTATUS resume_scrub(device_extension* Vcb, KPROCESSOR_MODE processor_mode);
+NTSTATUS stop_scrub(device_extension* Vcb, KPROCESSOR_MODE processor_mode);
+
+// in send.c
+NTSTATUS send_subvol(device_extension* Vcb, void* data, ULONG datalen, PFILE_OBJECT FileObject, PIRP Irp);
+NTSTATUS read_send_buffer(device_extension* Vcb, PFILE_OBJECT FileObject, void* data, ULONG datalen, ULONG_PTR* retlen, KPROCESSOR_MODE processor_mode);
+
+// based on function in sys/sysmacros.h
+#define makedev(major, minor) (((minor) & 0xFF) | (((major) & 0xFFF) << 8) | (((UINT64)((minor) & ~0xFF)) << 12) | (((UINT64)((major) & ~0xFFF)) << 32))
+
 #define fast_io_possible(fcb) (!FsRtlAreThereCurrentFileLocks(&fcb->lock) && !fcb->Vcb->readonly ? FastIoIsPossible : FastIoIsQuestionable)
 
 static __inline void print_open_trees(device_extension* Vcb) {
@@ -1119,16 +1533,16 @@ static __inline BOOL write_fcb_compressed(fcb* fcb) {
     // make sure we don't accidentally write the cache inodes or pagefile compressed
     if (fcb->subvol->id == BTRFS_ROOT_ROOT || fcb->Header.Flags2 & FSRTL_FLAG2_IS_PAGING_FILE)
         return FALSE;
-    
+
     if (fcb->Vcb->options.compress_force)
         return TRUE;
-    
+
     if (fcb->inode_item.flags & BTRFS_INODE_NOCOMPRESS)
         return FALSE;
-    
+
     if (fcb->inode_item.flags & BTRFS_INODE_COMPRESS || fcb->Vcb->options.compress)
         return TRUE;
-    
+
     return FALSE;
 }
 
@@ -1137,7 +1551,7 @@ static __inline void do_xor(UINT8* buf1, UINT8* buf2, UINT32 len) {
 #ifndef __REACTOS__
     __m128i x1, x2;
 #endif
-    
+
 #ifndef __REACTOS__
     if (have_sse2 && ((uintptr_t)buf1 & 0xf) == 0 && ((uintptr_t)buf2 & 0xf) == 0) {
         while (len >= 16) {
@@ -1145,14 +1559,14 @@ static __inline void do_xor(UINT8* buf1, UINT8* buf2, UINT32 len) {
             x2 = _mm_load_si128((__m128i*)buf2);
             x1 = _mm_xor_si128(x1, x2);
             _mm_store_si128((__m128i*)buf1, x1);
-            
+
             buf1 += 16;
             buf2 += 16;
             len -= 16;
         }
     }
 #endif
-    
+
     for (j = 0; j < len; j++) {
         *buf1 ^= *buf2;
         buf1++;
@@ -1160,8 +1574,6 @@ static __inline void do_xor(UINT8* buf1, UINT8* buf2, UINT32 len) {
     }
 }
 
-#define first_device(Vcb) CONTAINING_RECORD(Vcb->devices.Flink, device, list_entry)
-
 #ifdef DEBUG_FCB_REFCOUNTS
 #ifdef DEBUG_LONG_MESSAGES
 #define increase_fileref_refcount(fileref) {\
@@ -1179,14 +1591,12 @@ static __inline void do_xor(UINT8* buf1, UINT8* buf2, UINT32 len) {
 #endif
 
 #ifdef _MSC_VER
-// #define int3 __asm { int 3 }
 #define int3 __debugbreak()
 #else
 #define int3 asm("int3;")
 #endif
 
-// if (Vcb->open_trees > 0) { ERR("open tree count = %i\n", Vcb->open_trees); print_open_trees(Vcb); int3; }
-// else TRACE("open tree count = %i\n", Vcb->open_trees);
+#define hex_digit(c) ((c) <= 9) ? ((c) + '0') : ((c) - 10 + 'a')
 
 // FIXME - find a way to catch unfreed trees again
 
@@ -1246,18 +1656,27 @@ static __inline void do_xor(UINT8* buf1, UINT8* buf2, UINT32 len) {
 #define S_IXOTH (S_IXGRP >> 3)
 #endif
 
-// LXSS programs can be distinguished by the fact they have a NULL PEB.
-#ifdef _AMD64_
-    static __inline BOOL called_from_lxss() {
-        UINT8* proc = (UINT8*)PsGetCurrentProcess();
-        ULONG_PTR* peb = (ULONG_PTR*)&proc[0x3f8];
-        
-        return !*peb;
-    }
-#else
-#define called_from_lxss() FALSE
+#ifndef S_ISUID
+#define S_ISUID 0004000
 #endif
 
+#ifndef S_ISGID
+#define S_ISGID 0002000
+#endif
+
+#ifndef S_ISVTX
+#define S_ISVTX 0001000
+#endif
+
+static __inline UINT64 fcb_alloc_size(fcb* fcb) {
+    if (S_ISDIR(fcb->inode_item.st_mode))
+        return 0;
+    else if (fcb->atts & FILE_ATTRIBUTE_SPARSE_FILE)
+        return fcb->inode_item.st_blocks;
+    else
+        return sector_align(fcb->inode_item.st_size, fcb->Vcb->superblock.sector_size);
+}
+
 typedef BOOLEAN (*tPsIsDiskCountersEnabled)();
 
 typedef VOID (*tPsUpdateDiskCounters)(PEPROCESS Process, ULONG64 BytesRead, ULONG64 BytesWritten,
@@ -1269,16 +1688,81 @@ typedef BOOLEAN (*tCcCopyWriteEx)(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOf
 typedef BOOLEAN (*tCcCopyReadEx)(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait,
                                  PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PETHREAD IoIssuerThread);
 
+#ifndef CC_ENABLE_DISK_IO_ACCOUNTING
 #define CC_ENABLE_DISK_IO_ACCOUNTING 0x00000010
+#endif
 
 typedef VOID (*tCcSetAdditionalCacheAttributesEx)(PFILE_OBJECT FileObject, ULONG Flags);
 
+typedef VOID (*tFsRtlUpdateDiskCounters)(ULONG64 BytesRead, ULONG64 BytesWritten);
+
 #ifndef __REACTOS__
+#ifndef _MSC_VER
+
 #undef RtlIsNtDdiVersionAvailable
 
 BOOLEAN RtlIsNtDdiVersionAvailable(ULONG Version);
 
-PEPROCESS PsGetThreadProcess(PETHREAD Thread); // not in mingw
+PEPROCESS PsGetThreadProcess(_In_ PETHREAD Thread); // not in mingw
+#endif
+
+// not in DDK headers - taken from winternl.h
+typedef struct _LDR_DATA_TABLE_ENTRY {
+    PVOID Reserved1[2];
+    LIST_ENTRY InMemoryOrderLinks;
+    PVOID Reserved2[2];
+    PVOID DllBase;
+    PVOID Reserved3[2];
+    UNICODE_STRING FullDllName;
+    BYTE Reserved4[8];
+    PVOID Reserved5[3];
+    union {
+        ULONG CheckSum;
+        PVOID Reserved6;
+    };
+    ULONG TimeDateStamp;
+} LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;
+
+typedef struct _PEB_LDR_DATA {
+    BYTE Reserved1[8];
+    PVOID Reserved2[3];
+    LIST_ENTRY InMemoryOrderModuleList;
+} PEB_LDR_DATA,*PPEB_LDR_DATA;
+
+typedef struct _RTL_USER_PROCESS_PARAMETERS {
+    BYTE Reserved1[16];
+    PVOID Reserved2[10];
+    UNICODE_STRING ImagePathName;
+    UNICODE_STRING CommandLine;
+} RTL_USER_PROCESS_PARAMETERS,*PRTL_USER_PROCESS_PARAMETERS;
+
+typedef VOID (NTAPI *PPS_POST_PROCESS_INIT_ROUTINE)(VOID);
+
+typedef struct _PEB {
+    BYTE Reserved1[2];
+    BYTE BeingDebugged;
+    BYTE Reserved2[1];
+    PVOID Reserved3[2];
+    PPEB_LDR_DATA Ldr;
+    PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
+    BYTE Reserved4[104];
+    PVOID Reserved5[52];
+    PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine;
+    BYTE Reserved6[128];
+    PVOID Reserved7[1];
+    ULONG SessionId;
+} PEB,*PPEB;
+
+#ifdef _MSC_VER
+__kernel_entry
+NTSTATUS NTAPI ZwQueryInformationProcess(
+    IN HANDLE ProcessHandle,
+    IN PROCESSINFOCLASS ProcessInformationClass,
+    OUT PVOID ProcessInformation,
+    IN ULONG ProcessInformationLength,
+    OUT PULONG ReturnLength OPTIONAL
+);
+#endif
 #endif
 
 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7)