1 /* Copyright (c) Mark Harmstone 2016
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 0x0600
26 #define NTDDI_VERSION 0x06010000 // Win 7
27 #define _CRT_SECURE_NO_WARNINGS
28 #endif /* __REACTOS__ */
34 #endif /* __REACTOS__ */
39 #include <pseh/pseh2.h>
40 #endif /* __REACTOS__ */
41 //#include <windows.h>
47 #include <emmintrin.h>
51 // #define DEBUG_FCB_REFCOUNTS
52 // #define DEBUG_LONG_MESSAGES
53 // #define DEBUG_FLUSH_TIMES
54 // #define DEBUG_STATS
55 #define DEBUG_PARANOID
58 #define BTRFS_NODE_TYPE_CCB 0x2295
59 #define BTRFS_NODE_TYPE_FCB 0x2296
61 #define ALLOC_TAG 0x7442484D //'MHBt'
62 #define ALLOC_TAG_ZLIB 0x7A42484D //'MHBz'
64 #define STDCALL __stdcall
66 #define UID_NOBODY 65534
67 #define GID_NOBODY 65534
69 #define EA_NTACL "security.NTACL"
70 #define EA_NTACL_HASH 0x45922146
72 #define EA_DOSATTRIB "user.DOSATTRIB"
73 #define EA_DOSATTRIB_HASH 0x914f9939
75 #define EA_REPARSE "system.reparse"
76 #define EA_REPARSE_HASH 0x786f6167
78 #define EA_EA "user.EA"
79 #define EA_EA_HASH 0x8270dd43
81 #define MAX_EXTENT_SIZE 0x8000000 // 128 MB
82 #define COMPRESSED_EXTENT_SIZE 0x20000 // 128 KB
84 #define READ_AHEAD_GRANULARITY COMPRESSED_EXTENT_SIZE // really ought to be a multiple of COMPRESSED_EXTENT_SIZE
86 #define IO_REPARSE_TAG_LXSS_SYMLINK 0xa000001d // undocumented?
90 #define except __except
91 #define finally __finally
94 #define except(x) if (0 && (x))
95 #define finally if (1)
98 // #pragma pack(push, 1)
100 struct _device_extension
;
106 UNICODE_STRING devpath
;
111 LIST_ENTRY list_entry
;
114 typedef struct _fcb_nonpaged
{
115 FAST_MUTEX HeaderMutex
;
116 SECTION_OBJECT_POINTERS segment_object
;
118 ERESOURCE paging_resource
;
119 ERESOURCE index_lock
;
131 LIST_ENTRY list_entry
;
140 UNICODE_STRING filepart_uc
;
142 LIST_ENTRY list_entry
;
150 LIST_ENTRY list_entry
;
155 typedef struct _fcb
{
156 FSRTL_ADVANCED_FCB_HEADER Header
;
157 struct _fcb_nonpaged
* nonpaged
;
159 struct _device_extension
* Vcb
;
160 struct _root
* subvol
;
163 INODE_ITEM inode_item
;
164 SECURITY_DESCRIPTOR
* sd
;
167 PKTHREAD lazy_writer_thread
;
169 SHARE_ACCESS share_access
;
172 UINT64 last_dir_index
;
173 ANSI_STRING reparse_xattr
;
174 ANSI_STRING ea_xattr
;
176 LIST_ENTRY hardlinks
;
177 struct _file_ref
* fileref
;
178 BOOL inode_item_changed
;
181 LIST_ENTRY index_list
;
185 BOOL atts_changed
, atts_deleted
;
186 BOOL extents_changed
;
187 BOOL reparse_xattr_changed
;
194 ANSI_STRING adsxattr
;
197 LIST_ENTRY list_entry
;
198 LIST_ENTRY list_entry_all
;
203 LIST_ENTRY list_entry
;
207 ERESOURCE children_lock
;
210 typedef struct _file_ref
{
212 UNICODE_STRING filepart
;
213 UNICODE_STRING filepart_uc
;
217 BOOL delete_on_close
;
220 file_ref_nonpaged
* nonpaged
;
224 struct _file_ref
* parent
;
229 LIST_ENTRY list_entry
;
234 LIST_ENTRY list_entry
;
237 typedef struct _ccb
{
242 UINT64 query_dir_offset
;
243 // char* query_string;
244 UNICODE_STRING query_string
;
249 UNICODE_STRING filename
;
252 BOOL user_set_creation_time
;
253 BOOL user_set_access_time
;
254 BOOL user_set_write_time
;
255 BOOL user_set_change_time
;
258 // typedef struct _log_to_phys {
262 // UINT32 sector_size;
263 // struct _log_to_phys* next;
266 struct _device_extension
;
268 // enum tree_holder_status {
269 // tree_holder_unloaded,
270 // tree_holder_loading,
271 // tree_holder_loaded,
272 // tree_holder_unloading
276 // enum tree_holder_status status;
277 // KSPIN_LOCK spin_lock;
279 // } tree_holder_nonpaged;
285 // tree_holder_nonpaged* nonpaged;
288 typedef struct _tree_data
{
290 LIST_ENTRY list_entry
;
295 tree_holder treeholder
;
304 // typedef struct _tree_nonpaged {
305 // ERESOURCE load_tree_lock;
308 typedef struct _tree
{
314 struct _device_extension
* Vcb
;
315 struct _tree
* parent
;
318 // tree_nonpaged* nonpaged;
320 LIST_ENTRY list_entry
;
322 BOOL has_new_address
;
323 BOOL updated_extents
;
329 // KSPIN_LOCK load_tree_lock;
330 ERESOURCE load_tree_lock
;
333 typedef struct _root
{
335 LONGLONG lastinode
; // signed so we can use InterlockedIncrement64
336 tree_holder treeholder
;
337 root_nonpaged
* nonpaged
;
341 LIST_ENTRY list_entry
;
344 enum batch_operation
{
356 enum batch_operation operation
;
357 LIST_ENTRY list_entry
;
363 LIST_ENTRY list_entry
;
371 typedef struct _root_cache
{
373 struct _root_cache
* next
;
379 LIST_ENTRY list_entry
;
380 LIST_ENTRY list_entry_size
;
384 PDEVICE_OBJECT devobj
;
400 LIST_ENTRY list_entry
;
404 CHUNK_ITEM
* chunk_item
;
412 LIST_ENTRY space_size
;
414 LIST_ENTRY changed_extents
;
415 LIST_ENTRY range_locks
;
416 KSPIN_LOCK range_locks_spinlock
;
417 KEVENT range_locks_event
;
419 ERESOURCE changed_extents_lock
;
423 LIST_ENTRY list_entry
;
424 LIST_ENTRY list_entry_changed
;
437 LIST_ENTRY list_entry
;
448 LIST_ENTRY list_entry
;
449 } changed_extent_ref
;
455 LIST_ENTRY list_entry
;
465 UINT32 flush_interval
;
468 UINT32 raid5_recalculation
;
469 UINT32 raid6_recalculation
;
472 #define VCB_TYPE_VOLUME 1
473 #define VCB_TYPE_PARTITION0 2
479 UINT64 read_total_time
;
480 UINT64 read_csum_time
;
481 UINT64 read_disk_time
;
485 typedef struct _device_extension
{
487 mount_options options
;
493 UINT64 devices_loaded
;
494 // DISK_GEOMETRY geometry;
495 superblock superblock
;
496 // WCHAR label[MAX_LABEL_SIZE];
500 BOOL disallow_dismount
;
502 PFILE_OBJECT locked_fileobj
;
504 file_ref
* root_fileref
;
506 ERESOURCE DirResource
;
507 KSPIN_LOCK FcbListLock
;
511 PNOTIFY_SYNC NotifySync
;
512 LIST_ENTRY DirNotifyList
;
515 // ERESOURCE LogToPhysLock;
516 // UINT64 chunk_root_phys_addr;
517 UINT64 root_tree_phys_addr
;
519 // log_to_phys* log_to_phys;
521 LIST_ENTRY drop_roots
;
528 root
* data_reloc_root
;
529 BOOL log_to_phys_loaded
;
530 LIST_ENTRY sys_chunks
;
532 LIST_ENTRY chunks_changed
;
535 LIST_ENTRY dirty_fcbs
;
536 KSPIN_LOCK dirty_fcbs_lock
;
537 LIST_ENTRY dirty_filerefs
;
538 KSPIN_LOCK dirty_filerefs_lock
;
539 ERESOURCE checksum_lock
;
540 ERESOURCE chunk_lock
;
541 LIST_ENTRY sector_checksums
;
542 HANDLE flush_thread_handle
;
543 KTIMER flush_thread_timer
;
544 KEVENT flush_thread_finished
;
545 PFILE_OBJECT root_file
;
546 PAGED_LOOKASIDE_LIST tree_data_lookaside
;
547 PAGED_LOOKASIDE_LIST traverse_ptr_lookaside
;
548 PAGED_LOOKASIDE_LIST rollback_item_lookaside
;
549 PAGED_LOOKASIDE_LIST batch_item_lookaside
;
550 NPAGED_LOOKASIDE_LIST range_lock_lookaside
;
551 LIST_ENTRY list_entry
;
556 PDEVICE_OBJECT devobj
;
559 } part0_device_extension
;
562 LIST_ENTRY listentry
;
568 LIST_ENTRY list_entry
;
579 enum write_data_status
{
580 WriteDataStatus_Pending
,
581 WriteDataStatus_Success
,
582 WriteDataStatus_Error
,
583 WriteDataStatus_Cancelling
,
584 WriteDataStatus_Cancelled
,
585 WriteDataStatus_Ignore
588 struct _write_data_context
;
591 struct _write_data_context
* context
;
596 IO_STATUS_BLOCK iosb
;
597 enum write_data_status status
;
598 LIST_ENTRY list_entry
;
601 typedef struct _write_data_context
{
606 } write_data_context
;
610 static __inline
void* map_user_buffer(PIRP Irp
) {
611 if (!Irp
->MdlAddress
) {
612 return Irp
->UserBuffer
;
614 return MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
, NormalPagePriority
);
618 static __inline UINT64
unix_time_to_win(BTRFS_TIME
* t
) {
619 return (t
->seconds
* 10000000) + (t
->nanoseconds
/ 100) + 116444736000000000;
622 static __inline
void win_time_to_unix(LARGE_INTEGER t
, BTRFS_TIME
* out
) {
623 ULONGLONG l
= t
.QuadPart
- 116444736000000000;
625 out
->seconds
= l
/ 10000000;
626 out
->nanoseconds
= (l
% 10000000) * 100;
629 static __inline
void insert_into_ordered_list(LIST_ENTRY
* list
, ordered_list
* ins
) {
630 LIST_ENTRY
* le
= list
->Flink
;
634 ol
= (ordered_list
*)le
;
636 if (ol
->key
> ins
->key
) {
637 le
->Blink
->Flink
= &ins
->list_entry
;
638 ins
->list_entry
.Blink
= le
->Blink
;
639 le
->Blink
= &ins
->list_entry
;
640 ins
->list_entry
.Flink
= le
;
647 InsertTailList(list
, &ins
->list_entry
);
650 static __inline
void get_raid0_offset(UINT64 off
, UINT64 stripe_length
, UINT16 num_stripes
, UINT64
* stripeoff
, UINT16
* stripe
) {
651 UINT64 initoff
, startoff
;
653 startoff
= off
% (num_stripes
* stripe_length
);
654 initoff
= (off
/ (num_stripes
* stripe_length
)) * stripe_length
;
656 *stripe
= (UINT16
)(startoff
/ stripe_length
);
657 *stripeoff
= initoff
+ startoff
- (*stripe
* stripe_length
);
660 /* We only have 64 bits for a file ID, which isn't technically enough to be
661 * unique on Btrfs. We fudge it by having three bytes for the subvol and
662 * five for the inode, which should be good enough.
663 * Inodes are also 64 bits on Linux, but the Linux driver seems to get round
664 * this by tricking it into thinking subvols are separate volumes. */
666 static __inline UINT64
make_file_id(root
* r
, UINT64 inode
) {
668 static UINT64 __inline
make_file_id(root
* r
, UINT64 inode
) {
670 return (r
->id
<< 40) | (inode
& 0xffffffffff);
673 #define keycmp(key1, key2)\
674 ((key1.obj_id < key2.obj_id) ? -1 :\
675 ((key1.obj_id > key2.obj_id) ? 1 :\
676 ((key1.obj_type < key2.obj_type) ? -1 :\
677 ((key1.obj_type > key2.obj_type) ? 1 :\
678 ((key1.offset < key2.offset) ? -1 :\
679 ((key1.offset > key2.offset) ? 1 :\
683 device
* find_device_from_uuid(device_extension
* Vcb
, BTRFS_UUID
* uuid
);
684 UINT64
sector_align( UINT64 NumberToBeAligned
, UINT64 Alignment
);
685 ULONG STDCALL
get_file_attributes(device_extension
* Vcb
, INODE_ITEM
* ii
, root
* r
, UINT64 inode
, UINT8 type
, BOOL dotfile
, BOOL ignore_xa
, PIRP Irp
);
686 BOOL STDCALL
get_xattr(device_extension
* Vcb
, root
* subvol
, UINT64 inode
, char* name
, UINT32 crc32
, UINT8
** data
, UINT16
* datalen
, PIRP Irp
);
687 void _free_fcb(fcb
* fcb
, const char* func
, const char* file
, unsigned int line
);
688 void _free_fileref(file_ref
* fr
, const char* func
, const char* file
, unsigned int line
);
689 NTSTATUS
delete_dir_item(device_extension
* Vcb
, root
* subvol
, UINT64 parinode
, UINT32 crc32
, PANSI_STRING utf8
, PIRP Irp
, LIST_ENTRY
* rollback
);
690 NTSTATUS
delete_inode_ref(device_extension
* Vcb
, root
* subvol
, UINT64 inode
, UINT64 parinode
, PANSI_STRING utf8
, PIRP Irp
, LIST_ENTRY
* rollback
);
691 fcb
* create_fcb(POOL_TYPE pool_type
);
692 file_ref
* create_fileref();
693 void protect_superblocks(device_extension
* Vcb
, chunk
* c
);
694 BOOL
is_top_level(PIRP Irp
);
695 NTSTATUS
create_root(device_extension
* Vcb
, UINT64 id
, root
** rootptr
, BOOL no_tree
, UINT64 offset
, PIRP Irp
, LIST_ENTRY
* rollback
);
696 void STDCALL
uninit(device_extension
* Vcb
, BOOL flush
);
697 NTSTATUS STDCALL
dev_ioctl(PDEVICE_OBJECT DeviceObject
, ULONG ControlCode
, PVOID InputBuffer
,
698 ULONG InputBufferSize
, PVOID OutputBuffer
, ULONG OutputBufferSize
, BOOLEAN Override
, IO_STATUS_BLOCK
* iosb
);
699 BOOL
is_file_name_valid(PUNICODE_STRING us
);
700 void send_notification_fileref(file_ref
* fileref
, ULONG filter_match
, ULONG action
);
701 void send_notification_fcb(file_ref
* fileref
, ULONG filter_match
, ULONG action
);
702 WCHAR
* file_desc(PFILE_OBJECT FileObject
);
703 WCHAR
* file_desc_fileref(file_ref
* fileref
);
704 BOOL
add_thread_job(device_extension
* Vcb
, PIRP Irp
);
705 NTSTATUS
part0_passthrough(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
706 void mark_fcb_dirty(fcb
* fcb
);
707 void mark_fileref_dirty(file_ref
* fileref
);
708 NTSTATUS
delete_fileref(file_ref
* fileref
, PFILE_OBJECT FileObject
, PIRP Irp
, LIST_ENTRY
* rollback
);
709 void chunk_lock_range(device_extension
* Vcb
, chunk
* c
, UINT64 start
, UINT64 length
);
710 void chunk_unlock_range(device_extension
* Vcb
, chunk
* c
, UINT64 start
, UINT64 length
);
713 #define funcname __FUNCTION__
715 #define funcname __func__
718 // FIXME - we probably shouldn't be moving funcname etc. around if we're not printing debug messages
719 #define free_fcb(fcb) _free_fcb(fcb, funcname, __FILE__, __LINE__)
720 #define free_fileref(fileref) _free_fileref(fileref, funcname, __FILE__, __LINE__)
722 extern BOOL have_sse2
;
724 extern UINT32 mount_compress
;
725 extern UINT32 mount_compress_force
;
726 extern UINT32 mount_compress_type
;
727 extern UINT32 mount_zlib_level
;
728 extern UINT32 mount_flush_interval
;
729 extern UINT32 mount_max_inline
;
730 extern UINT32 mount_raid5_recalculation
;
731 extern UINT32 mount_raid6_recalculation
;
735 extern BOOL log_started
;
736 extern UINT32 debug_log_level
;
738 #ifdef DEBUG_LONG_MESSAGES
740 #define MSG(fn, file, line, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, file, line, s, ##__VA_ARGS__) : 0
742 #define TRACE(s, ...) MSG(funcname, __FILE__, __LINE__, s, 3, ##__VA_ARGS__)
743 #define WARN(s, ...) MSG(funcname, __FILE__, __LINE__, s, 2, ##__VA_ARGS__)
744 #define FIXME(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
745 #define ERR(s, ...) MSG(funcname, __FILE__, __LINE__, s, 1, ##__VA_ARGS__)
747 void STDCALL
_debug_message(const char* func
, const char* file
, unsigned int line
, char* s
, ...);
751 #define MSG(fn, s, level, ...) (!log_started || level <= debug_log_level) ? _debug_message(fn, s, ##__VA_ARGS__) : 0
753 #define TRACE(s, ...) MSG(funcname, s, 3, ##__VA_ARGS__)
754 #define WARN(s, ...) MSG(funcname, s, 2, ##__VA_ARGS__)
755 #define FIXME(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
756 #define ERR(s, ...) MSG(funcname, s, 1, ##__VA_ARGS__)
758 void STDCALL
_debug_message(const char* func
, char* s
, ...);
764 #define TRACE(s, ...)
767 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : " funcname " : " s, ##__VA_ARGS__)
768 #define ERR(s, ...) DbgPrint("Btrfs ERR : " funcname " : " s, ##__VA_ARGS__)
770 #define FIXME(s, ...) DbgPrint("Btrfs FIXME : %s : " s, funcname, ##__VA_ARGS__)
771 #define ERR(s, ...) DbgPrint("Btrfs ERR : %s : " s, funcname, ##__VA_ARGS__)
776 static __inline
void increase_chunk_usage(chunk
* c
, UINT64 delta
) {
779 TRACE("increasing size of chunk %llx by %llx\n", c
->offset
, delta
);
783 void STDCALL
init_fast_io_dispatch(FAST_IO_DISPATCH
** fiod
);
786 UINT32 STDCALL
calc_crc32c(UINT32 seed
, UINT8
* msg
, ULONG msglen
);
790 LIST_ENTRY
* list_size
;
802 ROLLBACK_INSERT_ITEM
,
803 ROLLBACK_DELETE_ITEM
,
804 ROLLBACK_INSERT_EXTENT
,
805 ROLLBACK_DELETE_EXTENT
,
807 ROLLBACK_SUBTRACT_SPACE
811 enum rollback_type type
;
813 LIST_ENTRY list_entry
;
817 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
);
818 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
);
819 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
);
820 void STDCALL
free_trees(device_extension
* Vcb
);
821 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
);
822 void STDCALL
delete_tree_item(device_extension
* Vcb
, traverse_ptr
* tp
, LIST_ENTRY
* rollback
);
823 tree
* STDCALL
_free_tree(tree
* t
, const char* func
, const char* file
, unsigned int line
);
824 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
);
825 NTSTATUS STDCALL
_do_load_tree(device_extension
* Vcb
, tree_holder
* th
, root
* r
, tree
* t
, tree_data
* td
, BOOL
* loaded
, PIRP Irp
,
826 const char* func
, const char* file
, unsigned int line
);
827 void clear_rollback(device_extension
* Vcb
, LIST_ENTRY
* rollback
);
828 void do_rollback(device_extension
* Vcb
, LIST_ENTRY
* rollback
);
829 void free_trees_root(device_extension
* Vcb
, root
* r
);
830 void add_rollback(device_extension
* Vcb
, LIST_ENTRY
* rollback
, enum rollback_type type
, void* ptr
);
831 void commit_batch_list(device_extension
* Vcb
, LIST_ENTRY
* batchlist
, PIRP Irp
, LIST_ENTRY
* rollback
);
832 void clear_batch_list(device_extension
* Vcb
, LIST_ENTRY
* batchlist
);
834 #define find_item(Vcb, r, tp, searchkey, ignore, Irp) _find_item(Vcb, r, tp, searchkey, ignore, Irp, funcname, __FILE__, __LINE__)
835 #define find_next_item(Vcb, tp, next_tp, ignore, Irp) _find_next_item(Vcb, tp, next_tp, ignore, Irp, funcname, __FILE__, __LINE__)
836 #define find_prev_item(Vcb, tp, prev_tp, ignore, Irp) _find_prev_item(Vcb, tp, prev_tp, ignore, Irp, funcname, __FILE__, __LINE__)
837 #define free_tree(t) _free_tree(t, funcname, __FILE__, __LINE__)
838 #define load_tree(t, addr, r, pt, parent, Irp) _load_tree(t, addr, r, pt, parent, Irp, funcname, __FILE__, __LINE__)
839 #define do_load_tree(Vcb, th, r, t, td, loaded, Irp) _do_load_tree(Vcb, th, r, t, td, loaded, Irp, funcname, __FILE__, __LINE__)
842 void STDCALL
look_for_vols(PDRIVER_OBJECT DriverObject
, LIST_ENTRY
* volumes
);
845 NTSTATUS STDCALL
init_cache();
846 void STDCALL
free_cache();
847 extern CACHE_MANAGER_CALLBACKS
* cache_callbacks
;
850 NTSTATUS
write_file(device_extension
* Vcb
, PIRP Irp
, BOOL wait
, BOOL deferred_write
);
851 NTSTATUS
write_file2(device_extension
* Vcb
, PIRP Irp
, LARGE_INTEGER offset
, void* buf
, ULONG
* length
, BOOL paging_io
, BOOL no_cache
,
852 BOOL wait
, BOOL deferred_write
, LIST_ENTRY
* rollback
);
853 NTSTATUS
truncate_file(fcb
* fcb
, UINT64 end
, PIRP Irp
, LIST_ENTRY
* rollback
);
854 NTSTATUS
extend_file(fcb
* fcb
, file_ref
* fileref
, UINT64 end
, BOOL prealloc
, PIRP Irp
, LIST_ENTRY
* rollback
);
855 NTSTATUS
excise_extents(device_extension
* Vcb
, fcb
* fcb
, UINT64 start_data
, UINT64 end_data
, PIRP Irp
, LIST_ENTRY
* rollback
);
856 void commit_checksum_changes(device_extension
* Vcb
, LIST_ENTRY
* changed_sector_list
);
857 chunk
* get_chunk_from_address(device_extension
* Vcb
, UINT64 address
);
858 chunk
* alloc_chunk(device_extension
* Vcb
, UINT64 flags
);
859 NTSTATUS STDCALL
write_data(device_extension
* Vcb
, UINT64 address
, void* data
, BOOL need_free
, UINT32 length
, write_data_context
* wtc
, PIRP Irp
, chunk
* c
);
860 NTSTATUS STDCALL
write_data_complete(device_extension
* Vcb
, UINT64 address
, void* data
, UINT32 length
, PIRP Irp
, chunk
* c
);
861 void free_write_data_stripes(write_data_context
* wtc
);
862 NTSTATUS STDCALL
drv_write(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
863 BOOL
insert_extent_chunk(device_extension
* Vcb
, fcb
* fcb
, chunk
* c
, UINT64 start_data
, UINT64 length
, BOOL prealloc
, void* data
, LIST_ENTRY
* changed_sector_list
,
864 PIRP Irp
, LIST_ENTRY
* rollback
, UINT8 compression
, UINT64 decoded_size
);
865 NTSTATUS
insert_extent(device_extension
* Vcb
, fcb
* fcb
, UINT64 start_data
, UINT64 length
, void* data
, LIST_ENTRY
* changed_sector_list
, PIRP Irp
, LIST_ENTRY
* rollback
);
866 NTSTATUS
do_write_file(fcb
* fcb
, UINT64 start_data
, UINT64 end_data
, void* data
, LIST_ENTRY
* changed_sector_list
, PIRP Irp
, LIST_ENTRY
* rollback
);
867 NTSTATUS
write_compressed(fcb
* fcb
, UINT64 start_data
, UINT64 end_data
, void* data
, LIST_ENTRY
* changed_sector_list
, PIRP Irp
, LIST_ENTRY
* rollback
);
868 BOOL
find_address_in_chunk(device_extension
* Vcb
, chunk
* c
, UINT64 length
, UINT64
* address
);
869 void get_raid56_lock_range(chunk
* c
, UINT64 address
, UINT64 length
, UINT64
* lockaddr
, UINT64
* locklen
);
872 NTSTATUS STDCALL
drv_directory_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
873 ULONG STDCALL
get_reparse_tag(device_extension
* Vcb
, root
* subvol
, UINT64 inode
, UINT8 type
, ULONG atts
, PIRP Irp
);
876 NTSTATUS STDCALL
drv_query_security(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
877 NTSTATUS STDCALL
drv_set_security(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
878 void fcb_get_sd(fcb
* fcb
, struct _fcb
* parent
, PIRP Irp
);
879 // UINT32 STDCALL get_uid();
880 void add_user_mapping(WCHAR
* sidstring
, ULONG sidstringlength
, UINT32 uid
);
881 UINT32
sid_to_uid(PSID sid
);
882 void uid_to_sid(UINT32 uid
, PSID
* sid
);
883 NTSTATUS
fcb_get_new_sd(fcb
* fcb
, file_ref
* parfileref
, ACCESS_STATE
* as
);
886 NTSTATUS STDCALL
drv_set_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
887 NTSTATUS STDCALL
drv_query_information(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
888 BOOL
has_open_children(file_ref
* fileref
);
889 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
);
890 NTSTATUS
fileref_get_filename(file_ref
* fileref
, PUNICODE_STRING fn
, USHORT
* name_offset
);
891 NTSTATUS
open_fileref_by_inode(device_extension
* Vcb
, root
* subvol
, UINT64 inode
, file_ref
** pfr
, PIRP Irp
);
892 NTSTATUS STDCALL
drv_query_ea(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
893 NTSTATUS STDCALL
drv_set_ea(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
896 NTSTATUS
get_reparse_point(PDEVICE_OBJECT DeviceObject
, PFILE_OBJECT FileObject
, void* buffer
, DWORD buflen
, ULONG_PTR
* retlen
);
897 NTSTATUS
set_reparse_point(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
898 NTSTATUS
delete_reparse_point(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
901 NTSTATUS STDCALL
drv_create(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
902 NTSTATUS STDCALL
find_file_in_dir(device_extension
* Vcb
, PUNICODE_STRING filename
, file_ref
* fr
,
903 root
** subvol
, UINT64
* inode
, UINT8
* type
, UINT64
* index
, PANSI_STRING utf8
, BOOL case_sensitive
, PIRP Irp
);
904 NTSTATUS
open_fileref(device_extension
* Vcb
, file_ref
** pfr
, PUNICODE_STRING fnus
, file_ref
* related
, BOOL parent
, USHORT
* unparsed
, ULONG
* fn_offset
,
905 POOL_TYPE pooltype
, BOOL case_sensitive
, PIRP Irp
);
906 NTSTATUS
open_fcb(device_extension
* Vcb
, root
* subvol
, UINT64 inode
, UINT8 type
, PANSI_STRING utf8
, fcb
* parent
, fcb
** pfcb
, POOL_TYPE pooltype
, PIRP Irp
);
907 NTSTATUS
open_fcb_stream(device_extension
* Vcb
, root
* subvol
, UINT64 inode
, ANSI_STRING
* xattr
, UINT32 streamhash
, fcb
* parent
, fcb
** pfcb
, PIRP Irp
);
908 void insert_fileref_child(file_ref
* parent
, file_ref
* child
, BOOL do_lock
);
909 NTSTATUS
fcb_get_last_dir_index(fcb
* fcb
, UINT64
* index
, PIRP Irp
);
910 NTSTATUS
verify_vcb(device_extension
* Vcb
, PIRP Irp
);
913 NTSTATUS
fsctl_request(PDEVICE_OBJECT DeviceObject
, PIRP Irp
, UINT32 type
, BOOL user
);
914 void do_unlock_volume(device_extension
* Vcb
);
917 void STDCALL
flush_thread(void* context
);
918 NTSTATUS STDCALL
do_write(device_extension
* Vcb
, PIRP Irp
, LIST_ENTRY
* rollback
);
919 NTSTATUS
get_tree_new_address(device_extension
* Vcb
, tree
* t
, PIRP Irp
, LIST_ENTRY
* rollback
);
920 void flush_fcb(fcb
* fcb
, BOOL cache
, LIST_ENTRY
* batchlist
, PIRP Irp
, LIST_ENTRY
* rollback
);
921 NTSTATUS STDCALL
write_data_phys(PDEVICE_OBJECT device
, UINT64 address
, void* data
, UINT32 length
);
922 BOOL
is_tree_unique(device_extension
* Vcb
, tree
* t
, PIRP Irp
);
925 NTSTATUS STDCALL
drv_read(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
926 NTSTATUS STDCALL
read_data(device_extension
* Vcb
, UINT64 addr
, UINT32 length
, UINT32
* csum
, BOOL is_tree
, UINT8
* buf
, chunk
* c
, chunk
** pc
, PIRP Irp
);
927 NTSTATUS STDCALL
read_file(fcb
* fcb
, UINT8
* data
, UINT64 start
, UINT64 length
, ULONG
* pbr
, PIRP Irp
);
928 NTSTATUS
do_read(PIRP Irp
, BOOL wait
, ULONG
* bytes_read
);
931 NTSTATUS STDCALL
drv_pnp(PDEVICE_OBJECT DeviceObject
, PIRP Irp
);
934 NTSTATUS
load_free_space_cache(device_extension
* Vcb
, chunk
* c
, PIRP Irp
);
935 NTSTATUS
clear_free_space_cache(device_extension
* Vcb
, LIST_ENTRY
* batchlist
, PIRP Irp
);
936 NTSTATUS
allocate_cache(device_extension
* Vcb
, BOOL
* changed
, PIRP Irp
, LIST_ENTRY
* rollback
);
937 NTSTATUS
update_chunk_caches(device_extension
* Vcb
, PIRP Irp
, LIST_ENTRY
* rollback
);
938 NTSTATUS
add_space_entry(LIST_ENTRY
* list
, LIST_ENTRY
* list_size
, UINT64 offset
, UINT64 size
);
939 void _space_list_add(device_extension
* Vcb
, chunk
* c
, BOOL deleting
, UINT64 address
, UINT64 length
, LIST_ENTRY
* rollback
, const char* func
);
940 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
);
941 void _space_list_subtract(device_extension
* Vcb
, chunk
* c
, BOOL deleting
, UINT64 address
, UINT64 length
, LIST_ENTRY
* rollback
, const char* func
);
942 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
);
944 #define space_list_add(Vcb, c, deleting, address, length, rollback) _space_list_add(Vcb, c, deleting, address, length, rollback, funcname)
945 #define space_list_add2(Vcb, list, list_size, address, length, rollback) _space_list_add2(Vcb, list, list_size, address, length, NULL, rollback, funcname)
946 #define space_list_subtract(Vcb, c, deleting, address, length, rollback) _space_list_subtract(Vcb, c, deleting, address, length, rollback, funcname)
947 #define space_list_subtract2(Vcb, list, list_size, address, length, rollback) _space_list_subtract2(Vcb, list, list_size, address, length, NULL, rollback, funcname)
950 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
);
951 NTSTATUS
decrease_extent_refcount_data(device_extension
* Vcb
, UINT64 address
, UINT64 size
, UINT64 root
, UINT64 inode
, UINT64 offset
, UINT32 refcount
, PIRP Irp
, LIST_ENTRY
* rollback
);
952 NTSTATUS
decrease_extent_refcount_tree(device_extension
* Vcb
, UINT64 address
, UINT64 size
, UINT64 root
, UINT8 level
, PIRP Irp
, LIST_ENTRY
* rollback
);
953 void decrease_chunk_usage(chunk
* c
, UINT64 delta
);
954 // NTSTATUS convert_old_data_extent(device_extension* Vcb, UINT64 address, UINT64 size, PIRP Irp, LIST_ENTRY* rollback);
955 UINT64
get_extent_refcount(device_extension
* Vcb
, UINT64 address
, UINT64 size
, PIRP Irp
);
956 BOOL
is_extent_unique(device_extension
* Vcb
, UINT64 address
, UINT64 size
, PIRP Irp
);
957 NTSTATUS
increase_extent_refcount(device_extension
* Vcb
, UINT64 address
, UINT64 size
, UINT8 type
, void* data
, KEY
* firstitem
, UINT8 level
, PIRP Irp
, LIST_ENTRY
* rollback
);
958 UINT64
get_extent_flags(device_extension
* Vcb
, UINT64 address
, PIRP Irp
);
959 void update_extent_flags(device_extension
* Vcb
, UINT64 address
, UINT64 flags
, PIRP Irp
);
960 NTSTATUS
update_changed_extent_ref(device_extension
* Vcb
, chunk
* c
, UINT64 address
, UINT64 size
, UINT64 root
, UINT64 objid
, UINT64 offset
,
961 signed long long count
, BOOL no_csum
, BOOL superseded
, PIRP Irp
);
962 void add_changed_extent_ref(chunk
* c
, UINT64 address
, UINT64 size
, UINT64 root
, UINT64 objid
, UINT64 offset
, UINT32 count
, BOOL no_csum
);
963 UINT64
find_extent_shared_tree_refcount(device_extension
* Vcb
, UINT64 address
, UINT64 parent
, PIRP Irp
);
964 UINT64
find_extent_shared_data_refcount(device_extension
* Vcb
, UINT64 address
, UINT64 parent
, PIRP Irp
);
965 NTSTATUS
decrease_extent_refcount(device_extension
* Vcb
, UINT64 address
, UINT64 size
, UINT8 type
, void* data
, KEY
* firstitem
,
966 UINT8 level
, UINT64 parent
, PIRP Irp
, LIST_ENTRY
* rollback
);
968 // in worker-thread.c
969 void do_read_job(PIRP Irp
);
970 void do_write_job(device_extension
* Vcb
, PIRP Irp
);
973 void STDCALL
read_registry(PUNICODE_STRING regpath
);
974 NTSTATUS
registry_mark_volume_mounted(BTRFS_UUID
* uuid
);
975 NTSTATUS
registry_mark_volume_unmounted(BTRFS_UUID
* uuid
);
976 NTSTATUS
registry_load_volume_options(device_extension
* Vcb
);
979 NTSTATUS
decompress(UINT8 type
, UINT8
* inbuf
, UINT64 inlen
, UINT8
* outbuf
, UINT64 outlen
);
980 NTSTATUS
write_compressed_bit(fcb
* fcb
, UINT64 start_data
, UINT64 end_data
, void* data
, BOOL
* compressed
, LIST_ENTRY
* changed_sector_list
, PIRP Irp
, LIST_ENTRY
* rollback
);
983 void galois_double(UINT8
* data
, UINT32 len
);
984 void galois_divpower(UINT8
* data
, UINT8 div
, UINT32 readlen
);
985 UINT8
gpow2(UINT8 e
);
986 UINT8
gmul(UINT8 a
, UINT8 b
);
987 UINT8
gdiv(UINT8 a
, UINT8 b
);
990 NTSTATUS STDCALL
drv_device_control(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
);
992 #define fast_io_possible(fcb) (!FsRtlAreThereCurrentFileLocks(&fcb->lock) && !fcb->Vcb->readonly ? FastIoIsPossible : FastIoIsQuestionable)
994 static __inline
void print_open_trees(device_extension
* Vcb
) {
995 LIST_ENTRY
* le
= Vcb
->trees
.Flink
;
996 while (le
!= &Vcb
->trees
) {
997 tree
* t
= CONTAINING_RECORD(le
, tree
, list_entry
);
998 tree_data
* td
= CONTAINING_RECORD(t
->itemlist
.Flink
, tree_data
, list_entry
);
999 ERR("tree %p: root %llx, level %u, first key (%llx,%x,%llx)\n",
1000 t
, t
->root
->id
, t
->header
.level
, td
->key
.obj_id
, td
->key
.obj_type
, td
->key
.offset
);
1006 static __inline BOOL
write_fcb_compressed(fcb
* fcb
) {
1007 // make sure we don't accidentally write the cache inodes or pagefile compressed
1008 if (fcb
->subvol
->id
== BTRFS_ROOT_ROOT
|| fcb
->Header
.Flags2
& FSRTL_FLAG2_IS_PAGING_FILE
)
1011 if (fcb
->Vcb
->options
.compress_force
)
1014 if (fcb
->inode_item
.flags
& BTRFS_INODE_NOCOMPRESS
)
1017 if (fcb
->inode_item
.flags
& BTRFS_INODE_COMPRESS
|| fcb
->Vcb
->options
.compress
)
1023 static __inline
void do_xor(UINT8
* buf1
, UINT8
* buf2
, UINT32 len
) {
1030 if (have_sse2
&& ((uintptr_t)buf1
& 0xf) == 0 && ((uintptr_t)buf2
& 0xf) == 0) {
1032 x1
= _mm_load_si128((__m128i
*)buf1
);
1033 x2
= _mm_load_si128((__m128i
*)buf2
);
1034 x1
= _mm_xor_si128(x1
, x2
);
1035 _mm_store_si128((__m128i
*)buf1
, x1
);
1044 for (j
= 0; j
< len
; j
++) {
1051 #ifdef DEBUG_FCB_REFCOUNTS
1052 #ifdef DEBUG_LONG_MESSAGES
1053 #define increase_fileref_refcount(fileref) {\
1054 LONG rc = InterlockedIncrement(&fileref->refcount);\
1055 MSG(funcname, __FILE__, __LINE__, "fileref %p: refcount now %i\n", 1, fileref, rc);\
1058 #define increase_fileref_refcount(fileref) {\
1059 LONG rc = InterlockedIncrement(&fileref->refcount);\
1060 MSG(funcname, "fileref %p: refcount now %i\n", 1, fileref, rc);\
1064 #define increase_fileref_refcount(fileref) InterlockedIncrement(&fileref->refcount)
1068 // #define int3 __asm { int 3 }
1069 #define int3 __debugbreak()
1071 #define int3 asm("int3;")
1074 // if (Vcb->open_trees > 0) { ERR("open tree count = %i\n", Vcb->open_trees); print_open_trees(Vcb); int3; }
1075 // else TRACE("open tree count = %i\n", Vcb->open_trees);
1077 // FIXME - find a way to catch unfreed trees again
1080 #define __S_IFMT 0170000 /* These bits determine file type. */
1081 #define __S_IFDIR 0040000 /* Directory. */
1082 #define __S_IFCHR 0020000 /* Character device. */
1083 #define __S_IFBLK 0060000 /* Block device. */
1084 #define __S_IFREG 0100000 /* Regular file. */
1085 #define __S_IFIFO 0010000 /* FIFO. */
1086 #define __S_IFLNK 0120000 /* Symbolic link. */
1087 #define __S_IFSOCK 0140000 /* Socket. */
1088 #define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
1091 #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
1095 #define S_IRUSR 0000400
1099 #define S_IWUSR 0000200
1103 #define S_IXUSR 0000100
1107 #define S_IFDIR __S_IFDIR
1108 #define S_IFREG __S_IFREG
1109 #endif /* __REACTOS__ */
1112 #define S_IRGRP (S_IRUSR >> 3)
1116 #define S_IWGRP (S_IWUSR >> 3)
1120 #define S_IXGRP (S_IXUSR >> 3)
1124 #define S_IROTH (S_IRGRP >> 3)
1128 #define S_IWOTH (S_IWGRP >> 3)
1132 #define S_IXOTH (S_IXGRP >> 3)
1135 // LXSS programs can be distinguished by the fact they have a NULL PEB.
1137 static __inline BOOL
called_from_lxss() {
1138 UINT8
* proc
= (UINT8
*)PsGetCurrentProcess();
1139 ULONG_PTR
* peb
= (ULONG_PTR
*)&proc
[0x3f8];
1144 #define called_from_lxss() FALSE
1147 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7)
1148 NTSTATUS WINAPI
RtlUnicodeToUTF8N(CHAR
*utf8_dest
, ULONG utf8_bytes_max
,
1149 ULONG
*utf8_bytes_written
,
1150 const WCHAR
*uni_src
, ULONG uni_bytes
);
1151 NTSTATUS WINAPI
RtlUTF8ToUnicodeN(WCHAR
*uni_dest
, ULONG uni_bytes_max
,
1152 ULONG
*uni_bytes_written
,
1153 const CHAR
*utf8_src
, ULONG utf8_bytes
);
1154 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7) */
1155 #if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_VISTA)
1156 NTSTATUS NTAPI
FsRtlRemoveDotsFromPath(PWSTR OriginalString
,
1157 USHORT PathLength
, USHORT
*NewLength
);
1158 NTSTATUS NTAPI
FsRtlValidateReparsePointBuffer(ULONG BufferLength
,
1159 PREPARSE_DATA_BUFFER ReparseBuffer
);
1160 ULONG NTAPI
KeQueryActiveProcessorCount(PKAFFINITY ActiveProcessors
);
1161 #endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_VISTA) */