-/* 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;
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 {
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;
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;
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;
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;
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 {
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;
struct _tree* parent;
tree_data* paritem;
struct _root* root;
-// tree_nonpaged* nonpaged;
LIST_ENTRY itemlist;
LIST_ENTRY list_entry;
LIST_ENTRY list_entry_hash;
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;
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 {
Batch_DeleteDirItem,
Batch_DeleteInodeRef,
Batch_DeleteInodeExtRef,
+ Batch_DeleteXattr,
+ Batch_DeleteExtentData,
+ Batch_DeleteFreeSpace,
};
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 {
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;
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;
typedef struct {
UINT8 type;
-
+
union {
EXTENT_DATA_REF edr;
SHARED_DATA_REF sdr;
};
-
+
LIST_ENTRY list_entry;
} changed_extent_ref;
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 {
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
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;
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;
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;
UINT32 uid;
} uid_map;
+typedef struct {
+ LIST_ENTRY listentry;
+ PSID sid;
+ UINT32 gid;
+} gid_map;
+
enum write_data_status {
WriteDataStatus_Pending,
WriteDataStatus_Success,
typedef struct {
struct _write_data_context* context;
UINT8* buf;
- BOOL need_free;
+ PMDL mdl;
device* device;
PIRP Irp;
IO_STATUS_BLOCK iosb;
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);
}
}
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);
}
* 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);
}
((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__
#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;
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
#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
#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
#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;
} rollback_extent;
enum rollback_type {
- ROLLBACK_INSERT_ITEM,
- ROLLBACK_DELETE_ITEM,
ROLLBACK_INSERT_EXTENT,
ROLLBACK_DELETE_EXTENT,
ROLLBACK_ADD_SPACE,
} 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);
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
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);
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) {
// 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;
}
#ifndef __REACTOS__
__m128i x1, x2;
#endif
-
+
#ifndef __REACTOS__
if (have_sse2 && ((uintptr_t)buf1 & 0xf) == 0 && ((uintptr_t)buf2 & 0xf) == 0) {
while (len >= 16) {
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++;
}
}
-#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) {\
#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
#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,
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)