1 /* Copyright (c) Mark Harmstone 2016-17
3 * This file is part of WinBtrfs.
5 * WinBtrfs is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public Licence as published by
7 * the Free Software Foundation, either version 3 of the Licence, or
8 * (at your option) any later version.
10 * WinBtrfs is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public Licence for more details.
15 * You should have received a copy of the GNU Lesser General Public Licence
16 * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
18 #ifndef BTRFS_DRV_H_DEFINED
19 #define BTRFS_DRV_H_DEFINED
25 #define _WIN32_WINNT 0x0601
26 #define NTDDI_VERSION 0x06020000 // Win 8
27 #define _CRT_SECURE_NO_WARNINGS
28 #define _NO_CRT_STDIO_INLINE
29 #endif /* __REACTOS__ */
33 #pragma warning(disable:4163)
34 #pragma warning(disable:4311)
35 #pragma warning(disable:4312)
37 #pragma GCC diagnostic push
38 #pragma GCC diagnostic ignored "-Wsign-compare"
39 #pragma GCC diagnostic ignored "-Wsign-conversion"
46 #endif /* __REACTOS__ */
51 #include <pseh/pseh2.h>
52 #endif /* __REACTOS__ */
59 #pragma GCC diagnostic pop
67 #include <emmintrin.h>
68 #endif /* __REACTOS__ */
70 #include "btrfsioctl.h"
73 // #define DEBUG_FCB_REFCOUNTS
74 // #define DEBUG_LONG_MESSAGES
75 // #define DEBUG_FLUSH_TIMES
76 // #define DEBUG_STATS
77 #define DEBUG_PARANOID
80 #define UNUSED(x) (void)(x)
82 #define BTRFS_NODE_TYPE_CCB 0x2295
83 #define BTRFS_NODE_TYPE_FCB 0x2296
85 #define ALLOC_TAG 0x7442484D //'MHBt'
86 #define ALLOC_TAG_ZLIB 0x7A42484D //'MHBz'
88 #define UID_NOBODY 65534
89 #define GID_NOBODY 65534
91 #define EA_NTACL "security.NTACL"
92 #define EA_NTACL_HASH 0x45922146
94 #define EA_DOSATTRIB "user.DOSATTRIB"
95 #define EA_DOSATTRIB_HASH 0x914f9939
97 #define EA_REPARSE "user.reparse"
98 #define EA_REPARSE_HASH 0xfabad1fe
100 #define EA_EA "user.EA"
101 #define EA_EA_HASH 0x8270dd43
103 #define EA_PROP_COMPRESSION "btrfs.compression"
104 #define EA_PROP_COMPRESSION_HASH 0x20ccdf69
106 #define MAX_EXTENT_SIZE 0x8000000 // 128 MB
107 #define COMPRESSED_EXTENT_SIZE 0x20000 // 128 KB
109 #define READ_AHEAD_GRANULARITY COMPRESSED_EXTENT_SIZE // really ought to be a multiple of COMPRESSED_EXTENT_SIZE
111 #define IO_REPARSE_TAG_LXSS_SYMLINK 0xa000001d // undocumented?
113 #define BTRFS_VOLUME_PREFIX L"\\Device\\Btrfs{"
117 #define except __except
118 #define finally __finally
121 #define except(x) if (0 && (x))
122 #define finally if (1)
125 #ifndef FILE_SUPPORTS_BLOCK_REFCOUNTING
126 #define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000
129 #ifndef FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL
130 #define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL 0x00020000
133 typedef struct _DUPLICATE_EXTENTS_DATA
{
135 LARGE_INTEGER SourceFileOffset
;
136 LARGE_INTEGER TargetFileOffset
;
137 LARGE_INTEGER ByteCount
;
138 } DUPLICATE_EXTENTS_DATA
, *PDUPLICATE_EXTENTS_DATA
;
140 #define FSCTL_DUPLICATE_EXTENTS_TO_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 209, METHOD_BUFFERED, FILE_WRITE_ACCESS)
142 typedef struct _FSCTL_GET_INTEGRITY_INFORMATION_BUFFER
{
143 WORD ChecksumAlgorithm
;
146 DWORD ChecksumChunkSizeInBytes
;
147 DWORD ClusterSizeInBytes
;
148 } FSCTL_GET_INTEGRITY_INFORMATION_BUFFER
, *PFSCTL_GET_INTEGRITY_INFORMATION_BUFFER
;
150 typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER
{
151 WORD ChecksumAlgorithm
;
154 } FSCTL_SET_INTEGRITY_INFORMATION_BUFFER
, *PFSCTL_SET_INTEGRITY_INFORMATION_BUFFER
;
156 #define FSCTL_GET_INTEGRITY_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 159, METHOD_BUFFERED, FILE_ANY_ACCESS)
157 #define FSCTL_SET_INTEGRITY_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 160, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
161 #define __drv_aliasesMem
162 #define _Requires_lock_held_(a)
163 #define _Requires_exclusive_lock_held_(a)
164 #define _Releases_lock_(a)
165 #define _Out_writes_bytes_opt_(a)
166 #define _Pre_satisfies_(a)
167 #define _Post_satisfies_(a)
168 #define _Releases_exclusive_lock_(a)
169 #define _Dispatch_type_(a)
170 #define _Create_lock_level_(a)
171 #define _Lock_level_order_(a,b)
172 #define _Has_lock_level_(a)
176 _Create_lock_level_(tree_lock
)
177 _Create_lock_level_(fcb_lock
)
178 _Lock_level_order_(tree_lock
, fcb_lock
)
180 struct _device_extension
;
182 typedef struct _fcb_nonpaged
{
183 FAST_MUTEX HeaderMutex
;
184 SECTION_OBJECT_POINTERS segment_object
;
186 ERESOURCE paging_resource
;
187 ERESOURCE dir_children_lock
;
200 LIST_ENTRY list_entry
;
202 EXTENT_DATA extent_data
;
210 LIST_ENTRY list_entry
;
223 UNICODE_STRING name_uc
;
225 struct _file_ref
* fileref
;
226 LIST_ENTRY list_entry_index
;
227 LIST_ENTRY list_entry_hash
;
228 LIST_ENTRY list_entry_hash_uc
;
231 enum prop_compression_type
{
232 PropCompression_None
,
233 PropCompression_Zlib
,
238 LIST_ENTRY list_entry
;
245 typedef struct _fcb
{
246 FSRTL_ADVANCED_FCB_HEADER Header
;
247 struct _fcb_nonpaged
* nonpaged
;
250 struct _device_extension
* Vcb
;
251 struct _root
* subvol
;
254 INODE_ITEM inode_item
;
255 SECURITY_DESCRIPTOR
* sd
;
258 PKTHREAD lazy_writer_thread
;
260 SHARE_ACCESS share_access
;
264 ANSI_STRING reparse_xattr
;
265 ANSI_STRING ea_xattr
;
267 LIST_ENTRY hardlinks
;
268 struct _file_ref
* fileref
;
269 BOOL inode_item_changed
;
270 enum prop_compression_type prop_compression
;
273 LIST_ENTRY dir_children_index
;
274 LIST_ENTRY dir_children_hash
;
275 LIST_ENTRY dir_children_hash_uc
;
276 LIST_ENTRY
** hash_ptrs
;
277 LIST_ENTRY
** hash_ptrs_uc
;
280 BOOL sd_dirty
, sd_deleted
;
281 BOOL atts_changed
, atts_deleted
;
282 BOOL extents_changed
;
283 BOOL reparse_xattr_changed
;
285 BOOL prop_compression_changed
;
292 ANSI_STRING adsxattr
;
295 LIST_ENTRY list_entry
;
296 LIST_ENTRY list_entry_all
;
297 LIST_ENTRY list_entry_dirty
;
301 ERESOURCE fileref_lock
;
302 ERESOURCE children_lock
;
305 typedef struct _file_ref
{
309 BOOL delete_on_close
;
312 file_ref_nonpaged
* nonpaged
;
316 struct _file_ref
* parent
;
322 LIST_ENTRY list_entry
;
323 LIST_ENTRY list_entry_dirty
;
330 KEVENT cleared_event
;
332 LIST_ENTRY list_entry
;
335 typedef struct _ccb
{
340 UINT64 query_dir_offset
;
341 UNICODE_STRING query_string
;
344 BOOL manage_volume_privilege
;
345 BOOL allow_extended_dasd_io
;
349 UNICODE_STRING filename
;
352 BOOL user_set_creation_time
;
353 BOOL user_set_access_time
;
354 BOOL user_set_write_time
;
355 BOOL user_set_change_time
;
358 NTSTATUS send_status
;
361 struct _device_extension
;
369 typedef struct _tree_data
{
371 LIST_ENTRY list_entry
;
376 tree_holder treeholder
;
385 typedef struct _tree
{
390 struct _device_extension
* Vcb
;
391 struct _tree
* parent
;
395 LIST_ENTRY list_entry
;
396 LIST_ENTRY list_entry_hash
;
398 BOOL has_new_address
;
399 BOOL updated_extents
;
402 BOOL uniqueness_determined
;
407 ERESOURCE load_tree_lock
;
410 typedef struct _root
{
412 LONGLONG lastinode
; // signed so we can use InterlockedIncrement64
413 tree_holder treeholder
;
414 root_nonpaged
* nonpaged
;
422 LIST_ENTRY list_entry
;
423 LIST_ENTRY list_entry_dirty
;
426 enum batch_operation
{
435 Batch_DeleteInodeRef
,
436 Batch_DeleteInodeExtRef
,
438 Batch_DeleteExtentData
,
439 Batch_DeleteFreeSpace
,
446 enum batch_operation operation
;
447 LIST_ENTRY list_entry
;
453 LIST_ENTRY list_entry
;
461 typedef struct _root_cache
{
463 struct _root_cache
* next
;
469 LIST_ENTRY list_entry
;
470 LIST_ENTRY list_entry_size
;
474 PDEVICE_OBJECT devobj
;
488 LIST_ENTRY list_entry
;
489 ULONG num_trim_entries
;
490 LIST_ENTRY trim_list
;
497 LIST_ENTRY list_entry
;
504 LIST_ENTRY list_entry
;
509 CHUNK_ITEM
* chunk_item
;
518 LIST_ENTRY space_size
;
520 LIST_ENTRY changed_extents
;
521 LIST_ENTRY range_locks
;
522 ERESOURCE range_locks_lock
;
523 KEVENT range_locks_event
;
525 ERESOURCE changed_extents_lock
;
535 LIST_ENTRY partial_stripes
;
536 ERESOURCE partial_stripes_lock
;
539 LIST_ENTRY list_entry
;
540 LIST_ENTRY list_entry_balance
;
553 LIST_ENTRY list_entry
;
564 LIST_ENTRY list_entry
;
565 } changed_extent_ref
;
571 LIST_ENTRY list_entry
;
581 LIST_ENTRY list_entry
;
585 PDEVICE_OBJECT DeviceObject
;
595 drv_calc_thread
* threads
;
606 UINT32 flush_interval
;
616 #define VCB_TYPE_FS 1
617 #define VCB_TYPE_CONTROL 2
618 #define VCB_TYPE_VOLUME 3
619 #define VCB_TYPE_PDO 4
625 UINT64 read_total_time
;
626 UINT64 read_csum_time
;
627 UINT64 read_disk_time
;
630 UINT64 open_total_time
;
631 UINT64 num_overwrites
;
632 UINT64 overwrite_total_time
;
634 UINT64 create_total_time
;
635 UINT64 open_fcb_calls
;
636 UINT64 open_fcb_time
;
640 #define BALANCE_OPTS_DATA 0
641 #define BALANCE_OPTS_METADATA 1
642 #define BALANCE_OPTS_SYSTEM 2
648 btrfs_balance_opts opts
[3];
666 LIST_ENTRY list_entry
;
672 UINT16 filename_length
;
686 ERESOURCE stats_lock
;
691 LARGE_INTEGER start_time
;
692 LARGE_INTEGER finish_time
;
693 LARGE_INTEGER resume_time
;
694 LARGE_INTEGER duration
;
697 UINT64 data_scrubbed
;
703 struct _volume_device_extension
;
705 typedef struct _device_extension
{
707 mount_options options
;
709 struct _volume_device_extension
* vde
;
714 UINT64 devices_loaded
;
715 superblock superblock
;
719 BOOL lock_paused_balance
;
720 BOOL disallow_dismount
;
722 PFILE_OBJECT locked_fileobj
;
725 file_ref
* root_fileref
;
727 _Has_lock_level_(fcb_lock
) ERESOURCE fcb_lock
;
729 _Has_lock_level_(tree_lock
) ERESOURCE tree_lock
;
730 PNOTIFY_SYNC NotifySync
;
731 LIST_ENTRY DirNotifyList
;
735 UINT64 metadata_flags
;
738 LIST_ENTRY drop_roots
;
745 root
* data_reloc_root
;
747 BOOL log_to_phys_loaded
;
748 BOOL chunk_usage_found
;
749 LIST_ENTRY sys_chunks
;
752 LIST_ENTRY trees_hash
;
753 LIST_ENTRY
* trees_ptrs
[256];
755 LIST_ENTRY dirty_fcbs
;
756 ERESOURCE dirty_fcbs_lock
;
757 LIST_ENTRY dirty_filerefs
;
758 ERESOURCE dirty_filerefs_lock
;
759 LIST_ENTRY dirty_subvols
;
760 ERESOURCE dirty_subvols_lock
;
761 ERESOURCE chunk_lock
;
762 HANDLE flush_thread_handle
;
763 KTIMER flush_thread_timer
;
764 KEVENT flush_thread_finished
;
765 drv_calc_threads calcthreads
;
766 balance_info balance
;
768 ERESOURCE send_load_lock
;
771 PFILE_OBJECT root_file
;
772 PAGED_LOOKASIDE_LIST tree_data_lookaside
;
773 PAGED_LOOKASIDE_LIST traverse_ptr_lookaside
;
774 PAGED_LOOKASIDE_LIST batch_item_lookaside
;
775 PAGED_LOOKASIDE_LIST fileref_lookaside
;
776 PAGED_LOOKASIDE_LIST fcb_lookaside
;
777 PAGED_LOOKASIDE_LIST name_bit_lookaside
;
778 NPAGED_LOOKASIDE_LIST range_lock_lookaside
;
779 NPAGED_LOOKASIDE_LIST fileref_np_lookaside
;
780 NPAGED_LOOKASIDE_LIST fcb_np_lookaside
;
781 LIST_ENTRY list_entry
;
786 PDEVICE_OBJECT buspdo
;
787 PDEVICE_OBJECT attached_device
;
788 UNICODE_STRING bus_name
;
789 } control_device_extension
;
795 PDEVICE_OBJECT devobj
;
796 PFILE_OBJECT fileobj
;
797 UNICODE_STRING pnp_name
;
800 BOOL had_drive_letter
;
801 void* notification_entry
;
804 LIST_ENTRY list_entry
;
807 struct pdo_device_extension
;
809 typedef struct _volume_device_extension
{
812 PDEVICE_OBJECT device
;
813 PDEVICE_OBJECT mounted_device
;
815 struct pdo_device_extension
* pdode
;
816 UNICODE_STRING bus_name
;
817 PDEVICE_OBJECT attached_device
;
820 } volume_device_extension
;
822 typedef struct pdo_device_extension
{
825 volume_device_extension
* vde
;
830 UINT64 children_loaded
;
831 ERESOURCE child_lock
;
834 LIST_ENTRY list_entry
;
835 } pdo_device_extension
;
838 LIST_ENTRY listentry
;
844 LIST_ENTRY listentry
;
849 enum write_data_status
{
850 WriteDataStatus_Pending
,
851 WriteDataStatus_Success
,
852 WriteDataStatus_Error
,
853 WriteDataStatus_Cancelling
,
854 WriteDataStatus_Cancelled
,
855 WriteDataStatus_Ignore
858 struct _write_data_context
;
861 struct _write_data_context
* context
;
866 IO_STATUS_BLOCK iosb
;
867 enum write_data_status status
;
868 LIST_ENTRY list_entry
;
871 typedef struct _write_data_context
{
876 UINT8
*parity1
, *parity2
, *scratch
;
877 PMDL mdl
, parity1_mdl
, parity2_mdl
;
878 } write_data_context
;
885 LIST_ENTRY list_entry
;
890 LIST_ENTRY list_entry
;
893 static __inline
void* map_user_buffer(PIRP Irp
, ULONG priority
) {
894 if (!Irp
->MdlAddress
) {
895 return Irp
->UserBuffer
;
897 return MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, priority
);
901 static __inline UINT64
unix_time_to_win(BTRFS_TIME
* t
) {
902 return (t
->seconds
* 10000000) + (t
->nanoseconds
/ 100) + 116444736000000000;
905 static __inline
void win_time_to_unix(LARGE_INTEGER t
, BTRFS_TIME
* out
) {
906 ULONGLONG l
= t
.QuadPart
- 116444736000000000;
908 out
->seconds
= l
/ 10000000;
909 out
->nanoseconds
= (l
% 10000000) * 100;
912 _Post_satisfies_(*stripe
>=0&&*stripe
<num_stripes
)
913 static __inline
void get_raid0_offset(_In_ UINT64 off
, _In_ UINT64 stripe_length
, _In_ UINT16 num_stripes
, _Out_ UINT64
* stripeoff
, _Out_ UINT16
* stripe
) {
914 UINT64 initoff
, startoff
;
916 startoff
= off
% (num_stripes
* stripe_length
);
917 initoff
= (off
/ (num_stripes
* stripe_length
)) * stripe_length
;
919 *stripe
= (UINT16
)(startoff
/ stripe_length
);
920 *stripeoff
= initoff
+ startoff
- (*stripe
* stripe_length
);
923 /* We only have 64 bits for a file ID, which isn't technically enough to be
924 * unique on Btrfs. We fudge it by having three bytes for the subvol and
925 * five for the inode, which should be good enough.
926 * Inodes are also 64 bits on Linux, but the Linux driver seems to get round
927 * this by tricking it into thinking subvols are separate volumes. */
928 static __inline UINT64
make_file_id(root
* r
, UINT64 inode
) {
929 return (r
->id
<< 40) | (inode
& 0xffffffffff);
932 #define keycmp(key1, key2)\
933 ((key1.obj_id < key2.obj_id) ? -1 :\
934 ((key1.obj_id > key2.obj_id) ? 1 :\
935 ((key1.obj_type < key2.obj_type) ? -1 :\
936 ((key1.obj_type > key2.obj_type) ? 1 :\
937 ((key1.offset < key2.offset) ? -1 :\
938 ((key1.offset > key2.offset) ? 1 :\
941 _Post_satisfies_(return>=n
)
942 __inline
static UINT64
sector_align(_In_ UINT64 n
, _In_ UINT64 a
) {
944 n
= (n
+ a
) & ~(a
- 1);
949 __inline
static BOOL
is_subvol_readonly(root
* r
, PIRP Irp
) {
950 if (!(r
->root_item
.flags
& BTRFS_SUBVOL_READONLY
))
956 return (!Irp
|| Irp
->RequestorMode
== UserMode
) && PsGetCurrentProcess() != r
->reserved
? TRUE
: FALSE
;
959 __inline
static UINT16
get_extent_data_len(UINT8 type
) {
961 case TYPE_TREE_BLOCK_REF
:
962 return sizeof(TREE_BLOCK_REF
);
964 case TYPE_EXTENT_DATA_REF
:
965 return sizeof(EXTENT_DATA_REF
);
967 case TYPE_EXTENT_REF_V0
:
968 return sizeof(EXTENT_REF_V0
);
970 case TYPE_SHARED_BLOCK_REF
:
971 return sizeof(SHARED_BLOCK_REF
);
973 case TYPE_SHARED_DATA_REF
:
974 return sizeof(SHARED_DATA_REF
);
981 __inline
static UINT32
get_extent_data_refcount(UINT8 type
, void* data
) {
983 case TYPE_TREE_BLOCK_REF
:
986 case TYPE_EXTENT_DATA_REF
:
988 EXTENT_DATA_REF
* edr
= (EXTENT_DATA_REF
*)data
;
992 case TYPE_EXTENT_REF_V0
:
994 EXTENT_REF_V0
* erv0
= (EXTENT_REF_V0
*)data
;
998 case TYPE_SHARED_BLOCK_REF
:
1001 case TYPE_SHARED_DATA_REF
:
1003 SHARED_DATA_REF
* sdr
= (SHARED_DATA_REF
*)data
;
1014 device
* find_device_from_uuid(_In_ device_extension
* Vcb
, _In_ BTRFS_UUID
* uuid
);
1017 BOOL
get_file_attributes_from_xattr(_In_reads_bytes_(len
) char* val
, _In_ UINT16 len
, _Out_ ULONG
* atts
);
1019 ULONG
get_file_attributes(_In_
_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _In_ root
* r
, _In_ UINT64 inode
,
1020 _In_ UINT8 type
, _In_ BOOL dotfile
, _In_ BOOL ignore_xa
, _In_opt_ PIRP Irp
);
1023 BOOL
get_xattr(_In_
_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _In_ root
* subvol
, _In_ UINT64 inode
, _In_z_
char* name
, _In_ UINT32 crc32
,
1024 _Out_ UINT8
** data
, _Out_ UINT16
* datalen
, _In_opt_ PIRP Irp
);
1026 #ifndef DEBUG_FCB_REFCOUNTS
1027 void free_fcb(_Requires_exclusive_lock_held_(_Curr_
->fcb_lock
) _In_ device_extension
* Vcb
, _Inout_ fcb
* fcb
);
1029 void free_fileref(_Requires_exclusive_lock_held_(_Curr_
->fcb_lock
) _In_ device_extension
* Vcb
, _Inout_ file_ref
* fr
);
1030 void protect_superblocks(_Inout_ chunk
* c
);
1031 BOOL
is_top_level(_In_ PIRP Irp
);
1032 NTSTATUS
create_root(_In_
_Requires_exclusive_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _In_ UINT64 id
,
1033 _Out_ root
** rootptr
, _In_ BOOL no_tree
, _In_ UINT64 offset
, _In_opt_ PIRP Irp
);
1034 void uninit(_In_ device_extension
* Vcb
, _In_ BOOL flush
);
1035 NTSTATUS
dev_ioctl(_In_ PDEVICE_OBJECT DeviceObject
, _In_ ULONG ControlCode
, _In_reads_bytes_opt_(InputBufferSize
) PVOID InputBuffer
, _In_ ULONG InputBufferSize
,
1036 _Out_writes_bytes_opt_(OutputBufferSize
) PVOID OutputBuffer
, _In_ ULONG OutputBufferSize
, _In_ BOOLEAN Override
, _Out_opt_ IO_STATUS_BLOCK
* iosb
);
1037 BOOL
is_file_name_valid(_In_ PUNICODE_STRING us
, _In_ BOOL posix
);
1038 void send_notification_fileref(_In_ file_ref
* fileref
, _In_ ULONG filter_match
, _In_ ULONG action
, _In_opt_ PUNICODE_STRING stream
);
1039 void send_notification_fcb(_In_ file_ref
* fileref
, _In_ ULONG filter_match
, _In_ ULONG action
, _In_opt_ PUNICODE_STRING stream
);
1042 WCHAR
* file_desc(_In_ PFILE_OBJECT FileObject
);
1043 WCHAR
* file_desc_fileref(_In_ file_ref
* fileref
);
1044 void mark_fcb_dirty(_In_ fcb
* fcb
);
1045 void mark_fileref_dirty(_In_ file_ref
* fileref
);
1046 NTSTATUS
delete_fileref(_In_ file_ref
* fileref
, _In_ PFILE_OBJECT FileObject
, _In_opt_ PIRP Irp
, _In_ LIST_ENTRY
* rollback
);
1047 void chunk_lock_range(_In_ device_extension
* Vcb
, _In_ chunk
* c
, _In_ UINT64 start
, _In_ UINT64 length
);
1048 void chunk_unlock_range(_In_ device_extension
* Vcb
, _In_ chunk
* c
, _In_ UINT64 start
, _In_ UINT64 length
);
1049 void init_device(_In_ device_extension
* Vcb
, _Inout_ device
* dev
, _In_ BOOL get_nums
);
1050 void init_file_cache(_In_ PFILE_OBJECT FileObject
, _In_ CC_FILE_SIZES
* ccfs
);
1051 NTSTATUS
sync_read_phys(_In_ PDEVICE_OBJECT DeviceObject
, _In_ UINT64 StartingOffset
, _In_ ULONG Length
,
1052 _Out_writes_bytes_(Length
) PUCHAR Buffer
, _In_ BOOL override
);
1053 NTSTATUS
get_device_pnp_name(_In_ PDEVICE_OBJECT DeviceObject
, _Out_ PUNICODE_STRING pnp_name
, _Out_
const GUID
** guid
);
1054 void log_device_error(_In_ device_extension
* Vcb
, _Inout_ device
* dev
, _In_
int error
);
1055 NTSTATUS
find_chunk_usage(_In_
_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _In_opt_ PIRP Irp
);
1057 NTSTATUS NTAPI
AddDevice(PDRIVER_OBJECT DriverObject
, PDEVICE_OBJECT PhysicalDeviceObject
);
1059 NTSTATUS
AddDevice(PDRIVER_OBJECT DriverObject
, PDEVICE_OBJECT PhysicalDeviceObject
);
1063 #define funcname __FUNCTION__
1065 #define funcname __func__
1068 extern BOOL have_sse2
;
1070 extern UINT32 mount_compress
;
1071 extern UINT32 mount_compress_force
;
1072 extern UINT32 mount_compress_type
;
1073 extern UINT32 mount_zlib_level
;
1074 extern UINT32 mount_flush_interval
;
1075 extern UINT32 mount_max_inline
;
1076 extern UINT32 mount_skip_balance
;
1077 extern UINT32 mount_no_barrier
;
1078 extern UINT32 mount_no_trim
;
1079 extern UINT32 mount_clear_cache
;
1080 extern UINT32 mount_allow_degraded
;
1081 extern UINT32 mount_readonly
;
1082 extern UINT32 no_pnp
;
1086 extern BOOL log_started
;
1087 extern UINT32 debug_log_level
;
1089 #ifdef DEBUG_LONG_MESSAGES
1091 #define MSG(fn, file, line, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, file, line, s, ##__VA_ARGS__) : 0
1093 #define TRACE(s, ...) MSG(funcname, __FILE__, __LINE__, s, 3, ##__VA_ARGS__)
1094 #define WARN(s, ...) MSG(funcname, __FILE__, __LINE__, s, 2, ##__VA_ARGS__)
1095 #define FIXME(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
1096 #define ERR(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
1098 void _debug_message(_In_
const char* func
, _In_
const char* file
, _In_
unsigned int line
, _In_
char* s
, ...);
1102 #define MSG(fn, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, s, ##__VA_ARGS__) : 0
1104 #define TRACE(s, ...) MSG(funcname, s, 3, ##__VA_ARGS__)
1105 #define WARN(s, ...) MSG(funcname, s, 2, ##__VA_ARGS__)
1106 #define FIXME(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
1107 #define ERR(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
1109 void _debug_message(_In_
const char* func
, _In_
char* s
, ...);
1115 #define TRACE(s, ...)
1116 #define WARN(s, ...)
1117 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__)
1118 #define ERR(s, ...) DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__)
1122 #ifdef DEBUG_FCB_REFCOUNTS
1123 void _free_fcb(_Requires_exclusive_lock_held_(_Curr_
->fcb_lock
) _In_ device_extension
* Vcb
, _Inout_ fcb
* fcb
, _In_
const char* func
);
1124 #define free_fcb(Vcb, fcb) _free_fcb(Vcb, fcb, funcname)
1128 void init_fast_io_dispatch(FAST_IO_DISPATCH
** fiod
);
1131 UINT32
calc_crc32c(_In_ UINT32 seed
, _In_reads_bytes_(msglen
) UINT8
* msg
, _In_ ULONG msglen
);
1135 LIST_ENTRY
* list_size
;
1146 enum rollback_type
{
1147 ROLLBACK_INSERT_EXTENT
,
1148 ROLLBACK_DELETE_EXTENT
,
1150 ROLLBACK_SUBTRACT_SPACE
1154 enum rollback_type type
;
1156 LIST_ENTRY list_entry
;
1160 NTSTATUS
find_item(_In_
_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _In_ root
* r
, _Out_ traverse_ptr
* tp
,
1161 _In_
const KEY
* searchkey
, _In_ BOOL ignore
, _In_opt_ PIRP Irp
);
1162 NTSTATUS
find_item_to_level(device_extension
* Vcb
, root
* r
, traverse_ptr
* tp
, const KEY
* searchkey
, BOOL ignore
, UINT8 level
, PIRP Irp
);
1163 BOOL
find_next_item(_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, const traverse_ptr
* tp
, traverse_ptr
* next_tp
, BOOL ignore
, PIRP Irp
);
1164 BOOL
find_prev_item(_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, const traverse_ptr
* tp
, traverse_ptr
* prev_tp
, PIRP Irp
);
1165 void free_trees(device_extension
* Vcb
);
1166 NTSTATUS
insert_tree_item(_In_
_Requires_exclusive_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _In_ root
* r
, _In_ UINT64 obj_id
,
1167 _In_ UINT8 obj_type
, _In_ UINT64 offset
, _In_reads_bytes_opt_(size
) _When_(return >= 0, __drv_aliasesMem
) void* data
,
1168 _In_ UINT16 size
, _Out_opt_ traverse_ptr
* ptp
, _In_opt_ PIRP Irp
);
1169 NTSTATUS
delete_tree_item(_In_
_Requires_exclusive_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, _Inout_ traverse_ptr
* tp
);
1170 tree
* free_tree(tree
* t
);
1171 NTSTATUS
load_tree(device_extension
* Vcb
, UINT64 addr
, root
* r
, tree
** pt
, UINT64 generation
, PIRP Irp
);
1172 NTSTATUS
do_load_tree(device_extension
* Vcb
, tree_holder
* th
, root
* r
, tree
* t
, tree_data
* td
, BOOL
* loaded
, PIRP Irp
);
1173 void clear_rollback(LIST_ENTRY
* rollback
);
1174 void do_rollback(device_extension
* Vcb
, LIST_ENTRY
* rollback
);
1175 void free_trees_root(device_extension
* Vcb
, root
* r
);
1176 void add_rollback(_In_ LIST_ENTRY
* rollback
, _In_
enum rollback_type type
, _In_ __drv_aliasesMem
void* ptr
);
1177 NTSTATUS
commit_batch_list(_Requires_exclusive_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, LIST_ENTRY
* batchlist
, PIRP Irp
);
1178 void clear_batch_list(device_extension
* Vcb
, LIST_ENTRY
* batchlist
);
1179 NTSTATUS
skip_to_difference(device_extension
* Vcb
, traverse_ptr
* tp
, traverse_ptr
* tp2
, BOOL
* ended1
, BOOL
* ended2
);
1182 NTSTATUS
remove_drive_letter(PDEVICE_OBJECT mountmgr
, PUNICODE_STRING devpath
);
1184 _Function_class_(KSTART_ROUTINE
)
1186 void NTAPI
mountmgr_thread(_In_
void* context
);
1188 void mountmgr_thread(_In_
void* context
);
1191 _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE
)
1193 NTSTATUS NTAPI
pnp_notification(PVOID NotificationStructure
, PVOID Context
);
1195 NTSTATUS
pnp_notification(PVOID NotificationStructure
, PVOID Context
);
1198 void disk_arrival(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING devpath
);
1199 void volume_arrival(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING devpath
);
1200 void volume_removal(PDRIVER_OBJECT DriverObject
, PUNICODE_STRING devpath
);
1202 _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE
)
1204 NTSTATUS NTAPI
volume_notification(PVOID NotificationStructure
, PVOID Context
);
1206 NTSTATUS
volume_notification(PVOID NotificationStructure
, PVOID Context
);
1209 void remove_volume_child(_Inout_
_Requires_exclusive_lock_held_(_Curr_
->child_lock
) _Releases_exclusive_lock_(_Curr_
->child_lock
) _In_ volume_device_extension
* vde
,
1210 _In_ volume_child
* vc
, _In_ BOOL skip_dev
);
1213 NTSTATUS
init_cache();
1215 extern CACHE_MANAGER_CALLBACKS
* cache_callbacks
;
1218 NTSTATUS
write_file(device_extension
* Vcb
, PIRP Irp
, BOOLEAN wait
, BOOLEAN deferred_write
);
1219 NTSTATUS
write_file2(device_extension
* Vcb
, PIRP Irp
, LARGE_INTEGER offset
, void* buf
, ULONG
* length
, BOOLEAN paging_io
, BOOLEAN no_cache
,
1220 BOOLEAN wait
, BOOLEAN deferred_write
, BOOLEAN write_irp
, LIST_ENTRY
* rollback
);
1221 NTSTATUS
truncate_file(fcb
* fcb
, UINT64 end
, PIRP Irp
, LIST_ENTRY
* rollback
);
1222 NTSTATUS
extend_file(fcb
* fcb
, file_ref
* fileref
, UINT64 end
, BOOL prealloc
, PIRP Irp
, LIST_ENTRY
* rollback
);
1223 NTSTATUS
excise_extents(device_extension
* Vcb
, fcb
* fcb
, UINT64 start_data
, UINT64 end_data
, PIRP Irp
, LIST_ENTRY
* rollback
);
1224 chunk
* get_chunk_from_address(device_extension
* Vcb
, UINT64 address
);
1225 NTSTATUS
alloc_chunk(device_extension
* Vcb
, UINT64 flags
, chunk
** pc
, BOOL full_size
);
1226 NTSTATUS
write_data(_In_ device_extension
* Vcb
, _In_ UINT64 address
, _In_reads_bytes_(length
) void* data
, _In_ UINT32 length
, _In_ write_data_context
* wtc
,
1227 _In_opt_ PIRP Irp
, _In_opt_ chunk
* c
, _In_ BOOL file_write
, _In_ UINT64 irp_offset
, _In_ ULONG priority
);
1228 NTSTATUS
write_data_complete(device_extension
* Vcb
, UINT64 address
, void* data
, UINT32 length
, PIRP Irp
, chunk
* c
, BOOL file_write
, UINT64 irp_offset
, ULONG priority
);
1229 void free_write_data_stripes(write_data_context
* wtc
);
1231 _Dispatch_type_(IRP_MJ_WRITE
)
1232 _Function_class_(DRIVER_DISPATCH
)
1233 NTSTATUS
drv_write(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1235 _Requires_lock_held_(c
->lock
)
1236 _When_(return != 0, _Releases_lock_(c
->lock
))
1237 BOOL
insert_extent_chunk(_In_ device_extension
* Vcb
, _In_ fcb
* fcb
, _In_ chunk
* c
, _In_ UINT64 start_data
, _In_ UINT64 length
, _In_ BOOL prealloc
, _In_opt_
void* data
,
1238 _In_opt_ PIRP Irp
, _In_ LIST_ENTRY
* rollback
, _In_ UINT8 compression
, _In_ UINT64 decoded_size
, _In_ BOOL file_write
, _In_ UINT64 irp_offset
);
1240 NTSTATUS
do_write_file(fcb
* fcb
, UINT64 start_data
, UINT64 end_data
, void* data
, PIRP Irp
, BOOL file_write
, UINT32 irp_offset
, LIST_ENTRY
* rollback
);
1241 NTSTATUS
write_compressed(fcb
* fcb
, UINT64 start_data
, UINT64 end_data
, void* data
, PIRP Irp
, LIST_ENTRY
* rollback
);
1242 BOOL
find_data_address_in_chunk(device_extension
* Vcb
, chunk
* c
, UINT64 length
, UINT64
* address
);
1243 void get_raid56_lock_range(chunk
* c
, UINT64 address
, UINT64 length
, UINT64
* lockaddr
, UINT64
* locklen
);
1244 NTSTATUS
calc_csum(_In_ device_extension
* Vcb
, _In_reads_bytes_(sectors
*Vcb
->superblock
.sector_size
) UINT8
* data
,
1245 _In_ UINT32 sectors
, _Out_writes_bytes_(sectors
*sizeof(UINT32
)) UINT32
* csum
);
1246 void add_insert_extent_rollback(LIST_ENTRY
* rollback
, fcb
* fcb
, extent
* ext
);
1247 NTSTATUS
add_extent_to_fcb(_In_ fcb
* fcb
, _In_ UINT64 offset
, _In_reads_bytes_(edsize
) EXTENT_DATA
* ed
, _In_ UINT16 edsize
,
1248 _In_ BOOL unique
, _In_opt_
_When_(return >= 0, __drv_aliasesMem
) UINT32
* csum
, _In_ LIST_ENTRY
* rollback
);
1249 void add_extent(_In_ fcb
* fcb
, _In_ LIST_ENTRY
* prevextle
, _In_ __drv_aliasesMem extent
* newext
);
1253 _Dispatch_type_(IRP_MJ_DIRECTORY_CONTROL
)
1254 _Function_class_(DRIVER_DISPATCH
)
1255 NTSTATUS
drv_directory_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1257 ULONG
get_reparse_tag(device_extension
* Vcb
, root
* subvol
, UINT64 inode
, UINT8 type
, ULONG atts
, BOOL lxss
, PIRP Irp
);
1261 _Dispatch_type_(IRP_MJ_QUERY_SECURITY
)
1262 _Function_class_(DRIVER_DISPATCH
)
1263 NTSTATUS
drv_query_security(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1265 _Dispatch_type_(IRP_MJ_SET_SECURITY
)
1266 _Function_class_(DRIVER_DISPATCH
)
1267 NTSTATUS
drv_set_security(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1269 void fcb_get_sd(fcb
* fcb
, struct _fcb
* parent
, BOOL look_for_xattr
, PIRP Irp
);
1270 void add_user_mapping(WCHAR
* sidstring
, ULONG sidstringlength
, UINT32 uid
);
1271 void add_group_mapping(WCHAR
* sidstring
, ULONG sidstringlength
, UINT32 gid
);
1272 UINT32
sid_to_uid(PSID sid
);
1273 NTSTATUS
uid_to_sid(UINT32 uid
, PSID
* sid
);
1274 NTSTATUS
fcb_get_new_sd(fcb
* fcb
, file_ref
* parfileref
, ACCESS_STATE
* as
);
1275 void find_gid(struct _fcb
* fcb
, struct _fcb
* parfcb
, PSECURITY_SUBJECT_CONTEXT subjcont
);
1279 _Dispatch_type_(IRP_MJ_SET_INFORMATION
)
1280 _Function_class_(DRIVER_DISPATCH
)
1281 NTSTATUS
drv_set_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1283 _Dispatch_type_(IRP_MJ_QUERY_INFORMATION
)
1284 _Function_class_(DRIVER_DISPATCH
)
1285 NTSTATUS
drv_query_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1287 _Dispatch_type_(IRP_MJ_QUERY_EA
)
1288 _Function_class_(DRIVER_DISPATCH
)
1289 NTSTATUS
drv_query_ea(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1291 _Dispatch_type_(IRP_MJ_SET_EA
)
1292 _Function_class_(DRIVER_DISPATCH
)
1293 NTSTATUS
drv_set_ea(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1295 BOOL
has_open_children(file_ref
* fileref
);
1296 NTSTATUS
stream_set_end_of_file_information(device_extension
* Vcb
, UINT16 end
, fcb
* fcb
, file_ref
* fileref
, BOOL advance_only
);
1297 NTSTATUS
fileref_get_filename(file_ref
* fileref
, PUNICODE_STRING fn
, USHORT
* name_offset
, ULONG
* preqlen
);
1298 NTSTATUS
open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_
->fcb_lock
) device_extension
* Vcb
, root
* subvol
, UINT64 inode
, file_ref
** pfr
, PIRP Irp
);
1299 void insert_dir_child_into_hash_lists(fcb
* fcb
, dir_child
* dc
);
1300 void remove_dir_child_from_hash_lists(fcb
* fcb
, dir_child
* dc
);
1303 NTSTATUS
get_reparse_point(PDEVICE_OBJECT DeviceObject
, PFILE_OBJECT FileObject
, void* buffer
, DWORD buflen
, ULONG_PTR
* retlen
);
1304 NTSTATUS
set_reparse_point(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
1305 NTSTATUS
delete_reparse_point(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
1309 _Dispatch_type_(IRP_MJ_CREATE
)
1310 _Function_class_(DRIVER_DISPATCH
)
1311 NTSTATUS
drv_create(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1313 NTSTATUS
open_fileref(_Requires_lock_held_(_Curr_
->tree_lock
) _Requires_exclusive_lock_held_(_Curr_
->fcb_lock
) _In_ device_extension
* Vcb
, _Out_ file_ref
** pfr
,
1314 _In_ PUNICODE_STRING fnus
, _In_opt_ file_ref
* related
, _In_ BOOL parent
, _Out_opt_ USHORT
* parsed
, _Out_opt_ ULONG
* fn_offset
, _In_ POOL_TYPE pooltype
,
1315 _In_ BOOL case_sensitive
, _In_opt_ PIRP Irp
);
1316 NTSTATUS
open_fcb(_Requires_lock_held_(_Curr_
->tree_lock
) _Requires_exclusive_lock_held_(_Curr_
->fcb_lock
) device_extension
* Vcb
,
1317 root
* subvol
, UINT64 inode
, UINT8 type
, PANSI_STRING utf8
, fcb
* parent
, fcb
** pfcb
, POOL_TYPE pooltype
, PIRP Irp
);
1318 NTSTATUS
load_csum(_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, UINT32
* csum
, UINT64 start
, UINT64 length
, PIRP Irp
);
1319 NTSTATUS
load_dir_children(_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
, fcb
* fcb
, BOOL ignore_size
, PIRP Irp
);
1320 NTSTATUS
add_dir_child(fcb
* fcb
, UINT64 inode
, BOOL subvol
, PANSI_STRING utf8
, PUNICODE_STRING name
, UINT8 type
, dir_child
** pdc
);
1321 NTSTATUS
open_fileref_child(_Requires_lock_held_(_Curr_
->tree_lock
) _Requires_exclusive_lock_held_(_Curr_
->fcb_lock
) _In_ device_extension
* Vcb
,
1322 _In_ file_ref
* sf
, _In_ PUNICODE_STRING name
, _In_ BOOL case_sensitive
, _In_ BOOL lastpart
, _In_ BOOL streampart
,
1323 _In_ POOL_TYPE pooltype
, _Out_ file_ref
** psf2
, _In_opt_ PIRP Irp
);
1324 fcb
* create_fcb(device_extension
* Vcb
, POOL_TYPE pool_type
);
1325 NTSTATUS
find_file_in_dir(PUNICODE_STRING filename
, fcb
* fcb
, root
** subvol
, UINT64
* inode
, dir_child
** pdc
, BOOL case_sensitive
);
1326 UINT32
inherit_mode(fcb
* parfcb
, BOOL is_dir
);
1327 file_ref
* create_fileref(device_extension
* Vcb
);
1330 NTSTATUS
fsctl_request(PDEVICE_OBJECT DeviceObject
, PIRP
* Pirp
, UINT32 type
);
1331 void do_unlock_volume(device_extension
* Vcb
);
1332 void trim_whole_device(device
* dev
);
1333 void flush_subvol_fcbs(root
* subvol
);
1334 BOOL
fcb_is_inline(fcb
* fcb
);
1338 _Function_class_(KSTART_ROUTINE
)
1340 void NTAPI
flush_thread(void* context
);
1342 void flush_thread(void* context
);
1345 NTSTATUS
do_write(device_extension
* Vcb
, PIRP Irp
);
1346 NTSTATUS
get_tree_new_address(device_extension
* Vcb
, tree
* t
, PIRP Irp
, LIST_ENTRY
* rollback
);
1347 NTSTATUS
flush_fcb(fcb
* fcb
, BOOL cache
, LIST_ENTRY
* batchlist
, PIRP Irp
);
1348 NTSTATUS
write_data_phys(_In_ PDEVICE_OBJECT device
, _In_ UINT64 address
, _In_reads_bytes_(length
) void* data
, _In_ UINT32 length
);
1349 BOOL
is_tree_unique(device_extension
* Vcb
, tree
* t
, PIRP Irp
);
1350 NTSTATUS
do_tree_writes(device_extension
* Vcb
, LIST_ENTRY
* tree_writes
, BOOL no_free
);
1351 void add_checksum_entry(device_extension
* Vcb
, UINT64 address
, ULONG length
, UINT32
* csum
, PIRP Irp
);
1352 BOOL
find_metadata_address_in_chunk(device_extension
* Vcb
, chunk
* c
, UINT64
* address
);
1353 void add_trim_entry_avoid_sb(device_extension
* Vcb
, device
* dev
, UINT64 address
, UINT64 size
);
1354 NTSTATUS
insert_tree_item_batch(LIST_ENTRY
* batchlist
, device_extension
* Vcb
, root
* r
, UINT64 objid
, UINT8 objtype
, UINT64 offset
,
1355 _In_opt_
_When_(return >= 0, __drv_aliasesMem
) void* data
, UINT16 datalen
, enum batch_operation operation
);
1356 NTSTATUS
flush_partial_stripe(device_extension
* Vcb
, chunk
* c
, partial_stripe
* ps
);
1357 NTSTATUS
update_dev_item(device_extension
* Vcb
, device
* device
, PIRP Irp
);
1361 _Dispatch_type_(IRP_MJ_READ
)
1362 _Function_class_(DRIVER_DISPATCH
)
1363 NTSTATUS
drv_read(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
1365 NTSTATUS
read_data(_In_ device_extension
* Vcb
, _In_ UINT64 addr
, _In_ UINT32 length
, _In_reads_bytes_opt_(length
*sizeof(UINT32
)/Vcb
->superblock
.sector_size
) UINT32
* csum
,
1366 _In_ BOOL is_tree
, _Out_writes_bytes_(length
) UINT8
* buf
, _In_opt_ chunk
* c
, _Out_opt_ chunk
** pc
, _In_opt_ PIRP Irp
, _In_ UINT64 generation
, _In_ BOOL file_read
,
1367 _In_ ULONG priority
);
1368 NTSTATUS
read_file(fcb
* fcb
, UINT8
* data
, UINT64 start
, UINT64 length
, ULONG
* pbr
, PIRP Irp
);
1369 NTSTATUS
read_stream(fcb
* fcb
, UINT8
* data
, UINT64 start
, ULONG length
, ULONG
* pbr
);
1370 NTSTATUS
do_read(PIRP Irp
, BOOLEAN wait
, ULONG
* bytes_read
);
1371 NTSTATUS
check_csum(device_extension
* Vcb
, UINT8
* data
, UINT32 sectors
, UINT32
* csum
);
1372 void raid6_recover2(UINT8
* sectors
, UINT16 num_stripes
, ULONG sector_size
, UINT16 missing1
, UINT16 missing2
, UINT8
* out
);
1376 _Dispatch_type_(IRP_MJ_PNP
)
1377 _Function_class_(DRIVER_DISPATCH
)
1378 NTSTATUS
drv_pnp(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
1380 NTSTATUS
pnp_surprise_removal(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
1381 NTSTATUS
pnp_query_remove_device(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
1384 NTSTATUS
load_cache_chunk(device_extension
* Vcb
, chunk
* c
, PIRP Irp
);
1385 NTSTATUS
clear_free_space_cache(device_extension
* Vcb
, LIST_ENTRY
* batchlist
, PIRP Irp
);
1386 NTSTATUS
allocate_cache(device_extension
* Vcb
, BOOL
* changed
, PIRP Irp
, LIST_ENTRY
* rollback
);
1387 NTSTATUS
update_chunk_caches(device_extension
* Vcb
, PIRP Irp
, LIST_ENTRY
* rollback
);
1388 NTSTATUS
update_chunk_caches_tree(device_extension
* Vcb
, PIRP Irp
);
1389 NTSTATUS
add_space_entry(LIST_ENTRY
* list
, LIST_ENTRY
* list_size
, UINT64 offset
, UINT64 size
);
1390 void space_list_add(chunk
* c
, UINT64 address
, UINT64 length
, LIST_ENTRY
* rollback
);
1391 void space_list_add2(LIST_ENTRY
* list
, LIST_ENTRY
* list_size
, UINT64 address
, UINT64 length
, chunk
* c
, LIST_ENTRY
* rollback
);
1392 void space_list_subtract(chunk
* c
, BOOL deleting
, UINT64 address
, UINT64 length
, LIST_ENTRY
* rollback
);
1393 void space_list_subtract2(LIST_ENTRY
* list
, LIST_ENTRY
* list_size
, UINT64 address
, UINT64 length
, chunk
* c
, LIST_ENTRY
* rollback
);
1394 NTSTATUS
load_stored_free_space_cache(device_extension
* Vcb
, chunk
* c
, BOOL load_only
, PIRP Irp
);
1397 NTSTATUS
increase_extent_refcount_data(device_extension
* Vcb
, UINT64 address
, UINT64 size
, UINT64 root
, UINT64 inode
, UINT64 offset
, UINT32 refcount
, PIRP Irp
);
1398 NTSTATUS
decrease_extent_refcount_data(device_extension
* Vcb
, UINT64 address
, UINT64 size
, UINT64 root
, UINT64 inode
, UINT64 offset
,
1399 UINT32 refcount
, BOOL superseded
, PIRP Irp
);
1400 NTSTATUS
decrease_extent_refcount_tree(device_extension
* Vcb
, UINT64 address
, UINT64 size
, UINT64 root
, UINT8 level
, PIRP Irp
);
1401 UINT64
get_extent_refcount(device_extension
* Vcb
, UINT64 address
, UINT64 size
, PIRP Irp
);
1402 BOOL
is_extent_unique(device_extension
* Vcb
, UINT64 address
, UINT64 size
, PIRP Irp
);
1403 NTSTATUS
increase_extent_refcount(device_extension
* Vcb
, UINT64 address
, UINT64 size
, UINT8 type
, void* data
, KEY
* firstitem
, UINT8 level
, PIRP Irp
);
1404 UINT64
get_extent_flags(device_extension
* Vcb
, UINT64 address
, PIRP Irp
);
1405 void update_extent_flags(device_extension
* Vcb
, UINT64 address
, UINT64 flags
, PIRP Irp
);
1406 NTSTATUS
update_changed_extent_ref(device_extension
* Vcb
, chunk
* c
, UINT64 address
, UINT64 size
, UINT64 root
, UINT64 objid
, UINT64 offset
,
1407 INT32 count
, BOOL no_csum
, BOOL superseded
, PIRP Irp
);
1408 void add_changed_extent_ref(chunk
* c
, UINT64 address
, UINT64 size
, UINT64 root
, UINT64 objid
, UINT64 offset
, UINT32 count
, BOOL no_csum
);
1409 UINT64
find_extent_shared_tree_refcount(device_extension
* Vcb
, UINT64 address
, UINT64 parent
, PIRP Irp
);
1410 UINT32
find_extent_shared_data_refcount(device_extension
* Vcb
, UINT64 address
, UINT64 parent
, PIRP Irp
);
1411 NTSTATUS
decrease_extent_refcount(device_extension
* Vcb
, UINT64 address
, UINT64 size
, UINT8 type
, void* data
, KEY
* firstitem
,
1412 UINT8 level
, UINT64 parent
, BOOL superseded
, PIRP Irp
);
1413 UINT64
get_extent_data_ref_hash2(UINT64 root
, UINT64 objid
, UINT64 offset
);
1415 // in worker-thread.c
1416 void do_read_job(PIRP Irp
);
1417 void do_write_job(device_extension
* Vcb
, PIRP Irp
);
1418 BOOL
add_thread_job(device_extension
* Vcb
, PIRP Irp
);
1421 void read_registry(PUNICODE_STRING regpath
, BOOL refresh
);
1422 NTSTATUS
registry_mark_volume_mounted(BTRFS_UUID
* uuid
);
1423 NTSTATUS
registry_mark_volume_unmounted(BTRFS_UUID
* uuid
);
1424 NTSTATUS
registry_load_volume_options(device_extension
* Vcb
);
1425 void watch_registry(HANDLE regh
);
1428 NTSTATUS
zlib_decompress(UINT8
* inbuf
, UINT32 inlen
, UINT8
* outbuf
, UINT32 outlen
);
1429 NTSTATUS
lzo_decompress(UINT8
* inbuf
, UINT32 inlen
, UINT8
* outbuf
, UINT32 outlen
, UINT32 inpageoff
);
1430 NTSTATUS
write_compressed_bit(fcb
* fcb
, UINT64 start_data
, UINT64 end_data
, void* data
, BOOL
* compressed
, PIRP Irp
, LIST_ENTRY
* rollback
);
1433 void galois_double(UINT8
* data
, UINT32 len
);
1434 void galois_divpower(UINT8
* data
, UINT8 div
, UINT32 readlen
);
1435 UINT8
gpow2(UINT8 e
);
1436 UINT8
gmul(UINT8 a
, UINT8 b
);
1437 UINT8
gdiv(UINT8 a
, UINT8 b
);
1441 _Dispatch_type_(IRP_MJ_DEVICE_CONTROL
)
1442 _Function_class_(DRIVER_DISPATCH
)
1443 NTSTATUS
drv_device_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1447 _Function_class_(KSTART_ROUTINE
)
1449 void NTAPI
calc_thread(void* context
);
1451 void calc_thread(void* context
);
1454 NTSTATUS
add_calc_job(device_extension
* Vcb
, UINT8
* data
, UINT32 sectors
, UINT32
* csum
, calc_job
** pcj
);
1455 void free_calc_job(calc_job
* cj
);
1458 NTSTATUS
start_balance(device_extension
* Vcb
, void* data
, ULONG length
, KPROCESSOR_MODE processor_mode
);
1459 NTSTATUS
query_balance(device_extension
* Vcb
, void* data
, ULONG length
);
1460 NTSTATUS
pause_balance(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1461 NTSTATUS
resume_balance(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1462 NTSTATUS
stop_balance(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1463 NTSTATUS
look_for_balance_item(_Requires_lock_held_(_Curr_
->tree_lock
) device_extension
* Vcb
);
1464 NTSTATUS
remove_device(device_extension
* Vcb
, void* data
, ULONG length
, KPROCESSOR_MODE processor_mode
);
1466 _Function_class_(KSTART_ROUTINE
)
1468 void NTAPI
balance_thread(void* context
);
1470 void balance_thread(void* context
);
1474 NTSTATUS
vol_create(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1475 NTSTATUS
vol_close(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1476 NTSTATUS
vol_read(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1477 NTSTATUS
vol_write(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1478 NTSTATUS
vol_query_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1479 NTSTATUS
vol_set_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1480 NTSTATUS
vol_query_ea(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1481 NTSTATUS
vol_set_ea(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1482 NTSTATUS
vol_flush_buffers(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1483 NTSTATUS
vol_query_volume_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1484 NTSTATUS
vol_set_volume_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1485 NTSTATUS
vol_cleanup(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1486 NTSTATUS
vol_directory_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1487 NTSTATUS
vol_file_system_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1488 NTSTATUS
vol_lock_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1489 NTSTATUS
vol_device_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1490 NTSTATUS
vol_shutdown(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1491 NTSTATUS
vol_query_security(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1492 NTSTATUS
vol_set_security(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1493 NTSTATUS
vol_power(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
1494 void add_volume_device(superblock
* sb
, PDEVICE_OBJECT mountmgr
, PUNICODE_STRING devpath
, UINT64 length
, ULONG disk_num
, ULONG part_num
);
1495 NTSTATUS
mountmgr_add_drive_letter(PDEVICE_OBJECT mountmgr
, PUNICODE_STRING devpath
);
1497 _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE
)
1499 NTSTATUS NTAPI
pnp_removal(PVOID NotificationStructure
, PVOID Context
);
1501 NTSTATUS
pnp_removal(PVOID NotificationStructure
, PVOID Context
);
1505 NTSTATUS
start_scrub(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1506 NTSTATUS
query_scrub(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
, void* data
, ULONG length
);
1507 NTSTATUS
pause_scrub(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1508 NTSTATUS
resume_scrub(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1509 NTSTATUS
stop_scrub(device_extension
* Vcb
, KPROCESSOR_MODE processor_mode
);
1512 NTSTATUS
send_subvol(device_extension
* Vcb
, void* data
, ULONG datalen
, PFILE_OBJECT FileObject
, PIRP Irp
);
1513 NTSTATUS
read_send_buffer(device_extension
* Vcb
, PFILE_OBJECT FileObject
, void* data
, ULONG datalen
, ULONG_PTR
* retlen
, KPROCESSOR_MODE processor_mode
);
1515 // based on function in sys/sysmacros.h
1516 #define makedev(major, minor) (((minor) & 0xFF) | (((major) & 0xFFF) << 8) | (((UINT64)((minor) & ~0xFF)) << 12) | (((UINT64)((major) & ~0xFFF)) << 32))
1518 #define fast_io_possible(fcb) (!FsRtlAreThereCurrentFileLocks(&fcb->lock) && !fcb->Vcb->readonly ? FastIoIsPossible : FastIoIsQuestionable)
1520 static __inline
void print_open_trees(device_extension
* Vcb
) {
1521 LIST_ENTRY
* le
= Vcb
->trees
.Flink
;
1522 while (le
!= &Vcb
->trees
) {
1523 tree
* t
= CONTAINING_RECORD(le
, tree
, list_entry
);
1524 tree_data
* td
= CONTAINING_RECORD(t
->itemlist
.Flink
, tree_data
, list_entry
);
1525 ERR("tree %p: root %llx, level %u, first key (%llx,%x,%llx)\n",
1526 t
, t
->root
->id
, t
->header
.level
, td
->key
.obj_id
, td
->key
.obj_type
, td
->key
.offset
);
1532 static __inline BOOL
write_fcb_compressed(fcb
* fcb
) {
1533 // make sure we don't accidentally write the cache inodes or pagefile compressed
1534 if (fcb
->subvol
->id
== BTRFS_ROOT_ROOT
|| fcb
->Header
.Flags2
& FSRTL_FLAG2_IS_PAGING_FILE
)
1537 if (fcb
->Vcb
->options
.compress_force
)
1540 if (fcb
->inode_item
.flags
& BTRFS_INODE_NOCOMPRESS
)
1543 if (fcb
->inode_item
.flags
& BTRFS_INODE_COMPRESS
|| fcb
->Vcb
->options
.compress
)
1549 static __inline
void do_xor(UINT8
* buf1
, UINT8
* buf2
, UINT32 len
) {
1556 if (have_sse2
&& ((uintptr_t)buf1
& 0xf) == 0 && ((uintptr_t)buf2
& 0xf) == 0) {
1558 x1
= _mm_load_si128((__m128i
*)buf1
);
1559 x2
= _mm_load_si128((__m128i
*)buf2
);
1560 x1
= _mm_xor_si128(x1
, x2
);
1561 _mm_store_si128((__m128i
*)buf1
, x1
);
1570 for (j
= 0; j
< len
; j
++) {
1577 #ifdef DEBUG_FCB_REFCOUNTS
1578 #ifdef DEBUG_LONG_MESSAGES
1579 #define increase_fileref_refcount(fileref) {\
1580 LONG rc = InterlockedIncrement(&fileref->refcount);\
1581 MSG(funcname, __FILE__, __LINE__, "fileref %p: refcount now %i\n", 1, fileref, rc);\
1584 #define increase_fileref_refcount(fileref) {\
1585 LONG rc = InterlockedIncrement(&fileref->refcount);\
1586 MSG(funcname, "fileref %p: refcount now %i\n", 1, fileref, rc);\
1590 #define increase_fileref_refcount(fileref) InterlockedIncrement(&fileref->refcount)
1594 #define int3 __debugbreak()
1596 #define int3 asm("int3;")
1599 #define hex_digit(c) ((c) <= 9) ? ((c) + '0') : ((c) - 10 + 'a')
1601 // FIXME - find a way to catch unfreed trees again
1604 #define __S_IFMT 0170000 /* These bits determine file type. */
1605 #define __S_IFDIR 0040000 /* Directory. */
1606 #define __S_IFCHR 0020000 /* Character device. */
1607 #define __S_IFBLK 0060000 /* Block device. */
1608 #define __S_IFREG 0100000 /* Regular file. */
1609 #define __S_IFIFO 0010000 /* FIFO. */
1610 #define __S_IFLNK 0120000 /* Symbolic link. */
1611 #define __S_IFSOCK 0140000 /* Socket. */
1612 #define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
1615 #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
1619 #define S_IRUSR 0000400
1623 #define S_IWUSR 0000200
1627 #define S_IXUSR 0000100
1631 #define S_IFDIR __S_IFDIR
1632 #define S_IFREG __S_IFREG
1633 #endif /* __REACTOS__ */
1636 #define S_IRGRP (S_IRUSR >> 3)
1640 #define S_IWGRP (S_IWUSR >> 3)
1644 #define S_IXGRP (S_IXUSR >> 3)
1648 #define S_IROTH (S_IRGRP >> 3)
1652 #define S_IWOTH (S_IWGRP >> 3)
1656 #define S_IXOTH (S_IXGRP >> 3)
1660 #define S_ISUID 0004000
1664 #define S_ISGID 0002000
1668 #define S_ISVTX 0001000
1671 static __inline UINT64
fcb_alloc_size(fcb
* fcb
) {
1672 if (S_ISDIR(fcb
->inode_item
.st_mode
))
1674 else if (fcb
->atts
& FILE_ATTRIBUTE_SPARSE_FILE
)
1675 return fcb
->inode_item
.st_blocks
;
1677 return sector_align(fcb
->inode_item
.st_size
, fcb
->Vcb
->superblock
.sector_size
);
1680 typedef BOOLEAN (*tPsIsDiskCountersEnabled
)();
1682 typedef VOID (*tPsUpdateDiskCounters
)(PEPROCESS Process
, ULONG64 BytesRead
, ULONG64 BytesWritten
,
1683 ULONG ReadOperationCount
, ULONG WriteOperationCount
, ULONG FlushOperationCount
);
1685 typedef BOOLEAN (*tCcCopyWriteEx
)(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, ULONG Length
, BOOLEAN Wait
,
1686 PVOID Buffer
, PETHREAD IoIssuerThread
);
1688 typedef BOOLEAN (*tCcCopyReadEx
)(PFILE_OBJECT FileObject
, PLARGE_INTEGER FileOffset
, ULONG Length
, BOOLEAN Wait
,
1689 PVOID Buffer
, PIO_STATUS_BLOCK IoStatus
, PETHREAD IoIssuerThread
);
1691 #ifndef CC_ENABLE_DISK_IO_ACCOUNTING
1692 #define CC_ENABLE_DISK_IO_ACCOUNTING 0x00000010
1695 typedef VOID (*tCcSetAdditionalCacheAttributesEx
)(PFILE_OBJECT FileObject
, ULONG Flags
);
1697 typedef VOID (*tFsRtlUpdateDiskCounters
)(ULONG64 BytesRead
, ULONG64 BytesWritten
);
1702 #undef RtlIsNtDdiVersionAvailable
1704 BOOLEAN
RtlIsNtDdiVersionAvailable(ULONG Version
);
1706 PEPROCESS
PsGetThreadProcess(_In_ PETHREAD Thread
); // not in mingw
1709 // not in DDK headers - taken from winternl.h
1710 typedef struct _LDR_DATA_TABLE_ENTRY
{
1712 LIST_ENTRY InMemoryOrderLinks
;
1716 UNICODE_STRING FullDllName
;
1723 ULONG TimeDateStamp
;
1724 } LDR_DATA_TABLE_ENTRY
,*PLDR_DATA_TABLE_ENTRY
;
1726 typedef struct _PEB_LDR_DATA
{
1729 LIST_ENTRY InMemoryOrderModuleList
;
1730 } PEB_LDR_DATA
,*PPEB_LDR_DATA
;
1732 typedef struct _RTL_USER_PROCESS_PARAMETERS
{
1734 PVOID Reserved2
[10];
1735 UNICODE_STRING ImagePathName
;
1736 UNICODE_STRING CommandLine
;
1737 } RTL_USER_PROCESS_PARAMETERS
,*PRTL_USER_PROCESS_PARAMETERS
;
1739 typedef VOID (NTAPI
*PPS_POST_PROCESS_INIT_ROUTINE
)(VOID
);
1741 typedef struct _PEB
{
1747 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
1748 BYTE Reserved4
[104];
1749 PVOID Reserved5
[52];
1750 PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine
;
1751 BYTE Reserved6
[128];
1758 NTSTATUS NTAPI
ZwQueryInformationProcess(
1759 IN HANDLE ProcessHandle
,
1760 IN PROCESSINFOCLASS ProcessInformationClass
,
1761 OUT PVOID ProcessInformation
,
1762 IN ULONG ProcessInformationLength
,
1763 OUT PULONG ReturnLength OPTIONAL
1768 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7)
1769 NTSTATUS WINAPI
RtlUnicodeToUTF8N(CHAR
*utf8_dest
, ULONG utf8_bytes_max
,
1770 ULONG
*utf8_bytes_written
,
1771 const WCHAR
*uni_src
, ULONG uni_bytes
);
1772 NTSTATUS WINAPI
RtlUTF8ToUnicodeN(WCHAR
*uni_dest
, ULONG uni_bytes_max
,
1773 ULONG
*uni_bytes_written
,
1774 const CHAR
*utf8_src
, ULONG utf8_bytes
);
1775 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7) */
1776 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_VISTA)
1777 NTSTATUS NTAPI
FsRtlRemoveDotsFromPath(PWSTR OriginalString
,
1778 USHORT PathLength
, USHORT
*NewLength
);
1779 NTSTATUS NTAPI
FsRtlValidateReparsePointBuffer(ULONG BufferLength
,
1780 PREPARSE_DATA_BUFFER ReparseBuffer
);
1781 ULONG NTAPI
KeQueryActiveProcessorCount(PKAFFINITY ActiveProcessors
);
1782 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_VISTA) */