mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[BTRFS]
Sync btrfs to 0.8. CORE-12617 svn path=/trunk/; revision=73498
This commit is contained in:
parent
3175ed2860
commit
3049f1a5b4
28 changed files with 11655 additions and 5966 deletions
|
@ -4,8 +4,10 @@ include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers
|
|||
inc)
|
||||
|
||||
list(APPEND SOURCE
|
||||
balance.c
|
||||
btrfs.c
|
||||
cache.c
|
||||
calcthread.c
|
||||
compress.c
|
||||
crc32c.c
|
||||
create.c
|
||||
|
@ -33,7 +35,7 @@ add_library(btrfs SHARED ${SOURCE} btrfs.rc)
|
|||
|
||||
add_definitions(-D__KERNEL__)
|
||||
set_module_type(btrfs kernelmodedriver)
|
||||
target_link_libraries(btrfs ntoskrnl_vista zlib_solo ${PSEH_LIB})
|
||||
target_link_libraries(btrfs rtlver ntoskrnl_vista zlib_solo wdmguid ${PSEH_LIB})
|
||||
add_importlibs(btrfs ntoskrnl hal)
|
||||
add_pch(btrfs btrfs_drv.h SOURCE)
|
||||
add_cd_file(TARGET btrfs DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
||||
|
|
3180
reactos/drivers/filesystems/btrfs/balance.c
Normal file
3180
reactos/drivers/filesystems/btrfs/balance.c
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -37,6 +37,8 @@ static const UINT64 superblock_addrs[] = { 0x10000, 0x4000000, 0x4000000000, 0x4
|
|||
#define TYPE_DEV_EXTENT 0xCC
|
||||
#define TYPE_DEV_ITEM 0xD8
|
||||
#define TYPE_CHUNK_ITEM 0xE4
|
||||
#define TYPE_TEMP_ITEM 0xF8
|
||||
#define TYPE_DEV_STATS 0xF9
|
||||
#define TYPE_SUBVOL_UUID 0xFB
|
||||
|
||||
#define BTRFS_ROOT_ROOT 1
|
||||
|
@ -72,6 +74,7 @@ static const UINT64 superblock_addrs[] = { 0x10000, 0x4000000, 0x4000000000, 0x4
|
|||
|
||||
#define FREE_SPACE_CACHE_ID 0xFFFFFFFFFFFFFFF5
|
||||
#define EXTENT_CSUM_ID 0xFFFFFFFFFFFFFFF6
|
||||
#define BALANCE_ITEM_ID 0xFFFFFFFFFFFFFFFC
|
||||
|
||||
#define BTRFS_INODE_NODATASUM 0x001
|
||||
#define BTRFS_INODE_NODATACOW 0x002
|
||||
|
@ -436,6 +439,62 @@ typedef struct {
|
|||
BTRFS_UUID chunktree_uuid;
|
||||
} DEV_EXTENT;
|
||||
|
||||
#define BALANCE_FLAGS_DATA 0x1
|
||||
#define BALANCE_FLAGS_SYSTEM 0x2
|
||||
#define BALANCE_FLAGS_METADATA 0x4
|
||||
|
||||
#define BALANCE_ARGS_FLAGS_PROFILES 0x001
|
||||
#define BALANCE_ARGS_FLAGS_USAGE 0x002
|
||||
#define BALANCE_ARGS_FLAGS_DEVID 0x004
|
||||
#define BALANCE_ARGS_FLAGS_DRANGE 0x008
|
||||
#define BALANCE_ARGS_FLAGS_VRANGE 0x010
|
||||
#define BALANCE_ARGS_FLAGS_LIMIT 0x020
|
||||
#define BALANCE_ARGS_FLAGS_LIMIT_RANGE 0x040
|
||||
#define BALANCE_ARGS_FLAGS_STRIPES_RANGE 0x080
|
||||
#define BALANCE_ARGS_FLAGS_CONVERT 0x100
|
||||
#define BALANCE_ARGS_FLAGS_SOFT 0x200
|
||||
#define BALANCE_ARGS_FLAGS_USAGE_RANGE 0x400
|
||||
|
||||
typedef struct {
|
||||
UINT64 profiles;
|
||||
|
||||
union {
|
||||
UINT64 usage;
|
||||
struct {
|
||||
UINT32 usage_start;
|
||||
UINT32 usage_end;
|
||||
};
|
||||
};
|
||||
|
||||
UINT64 devid;
|
||||
UINT64 drange_start;
|
||||
UINT64 drange_end;
|
||||
UINT64 vrange_start;
|
||||
UINT64 vrange_end;
|
||||
UINT64 convert;
|
||||
UINT64 flags;
|
||||
|
||||
union {
|
||||
UINT64 limit;
|
||||
struct {
|
||||
UINT32 limit_start;
|
||||
UINT32 limit_end;
|
||||
};
|
||||
};
|
||||
|
||||
UINT32 stripes_start;
|
||||
UINT32 stripes_end;
|
||||
UINT8 reserved[48];
|
||||
} BALANCE_ARGS;
|
||||
|
||||
typedef struct {
|
||||
UINT64 flags;
|
||||
BALANCE_ARGS data;
|
||||
BALANCE_ARGS metadata;
|
||||
BALANCE_ARGS system;
|
||||
UINT8 reserved[32];
|
||||
} BALANCE_ITEM;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -70,12 +70,12 @@ BEGIN
|
|||
BLOCK "080904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "WinBtrfs"
|
||||
VALUE "FileVersion", "0.7"
|
||||
VALUE "FileVersion", "0.8"
|
||||
VALUE "InternalName", "btrfs"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016"
|
||||
VALUE "OriginalFilename", "btrfs.sys"
|
||||
VALUE "ProductName", "WinBtrfs"
|
||||
VALUE "ProductVersion", "0.7"
|
||||
VALUE "ProductVersion", "0.8"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include <stddef.h>
|
||||
#include <emmintrin.h>
|
||||
#include "btrfs.h"
|
||||
#include "btrfsioctl.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
// #define DEBUG_FCB_REFCOUNTS
|
||||
|
@ -108,15 +109,23 @@ typedef struct {
|
|||
UINT64 gen1, gen2;
|
||||
BOOL seeding;
|
||||
BOOL processed;
|
||||
DWORD disk_num;
|
||||
DWORD part_num;
|
||||
LIST_ENTRY list_entry;
|
||||
} volume;
|
||||
|
||||
typedef struct {
|
||||
UNICODE_STRING devpath;
|
||||
ULONG disk_num;
|
||||
LIST_ENTRY list_entry;
|
||||
} pnp_disk;
|
||||
|
||||
typedef struct _fcb_nonpaged {
|
||||
FAST_MUTEX HeaderMutex;
|
||||
SECTION_OBJECT_POINTERS segment_object;
|
||||
ERESOURCE resource;
|
||||
ERESOURCE paging_resource;
|
||||
ERESOURCE index_lock;
|
||||
ERESOURCE dir_children_lock;
|
||||
} fcb_nonpaged;
|
||||
|
||||
struct _root;
|
||||
|
@ -127,21 +136,12 @@ typedef struct {
|
|||
ULONG datalen;
|
||||
BOOL unique;
|
||||
BOOL ignore;
|
||||
BOOL inserted;
|
||||
UINT32* csum;
|
||||
|
||||
LIST_ENTRY list_entry;
|
||||
} extent;
|
||||
|
||||
typedef struct {
|
||||
UINT32 hash;
|
||||
KEY key;
|
||||
UINT8 type;
|
||||
UINT64 index;
|
||||
ANSI_STRING utf8;
|
||||
UNICODE_STRING filepart_uc;
|
||||
|
||||
LIST_ENTRY list_entry;
|
||||
} index_entry;
|
||||
|
||||
typedef struct {
|
||||
UINT64 parent;
|
||||
UINT64 index;
|
||||
|
@ -152,6 +152,21 @@ typedef struct {
|
|||
|
||||
struct _file_ref;
|
||||
|
||||
typedef struct {
|
||||
KEY key;
|
||||
UINT64 index;
|
||||
UINT8 type;
|
||||
ANSI_STRING utf8;
|
||||
UINT32 hash;
|
||||
UNICODE_STRING name;
|
||||
UINT32 hash_uc;
|
||||
UNICODE_STRING name_uc;
|
||||
struct _file_ref* fileref;
|
||||
LIST_ENTRY list_entry_index;
|
||||
LIST_ENTRY list_entry_hash;
|
||||
LIST_ENTRY list_entry_hash_uc;
|
||||
} dir_child;
|
||||
|
||||
typedef struct _fcb {
|
||||
FSRTL_ADVANCED_FCB_HEADER Header;
|
||||
struct _fcb_nonpaged* nonpaged;
|
||||
|
@ -177,8 +192,11 @@ typedef struct _fcb {
|
|||
struct _file_ref* fileref;
|
||||
BOOL inode_item_changed;
|
||||
|
||||
BOOL index_loaded;
|
||||
LIST_ENTRY index_list;
|
||||
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;
|
||||
|
@ -223,6 +241,7 @@ typedef struct _file_ref {
|
|||
LONG open_count;
|
||||
struct _file_ref* parent;
|
||||
WCHAR* debug_desc;
|
||||
dir_child* dc;
|
||||
|
||||
BOOL dirty;
|
||||
|
||||
|
@ -244,6 +263,8 @@ typedef struct _ccb {
|
|||
UNICODE_STRING query_string;
|
||||
BOOL has_wildcard;
|
||||
BOOL specific_file;
|
||||
BOOL manage_volume_privilege;
|
||||
BOOL allow_extended_dasd_io;
|
||||
ACCESS_MASK access;
|
||||
file_ref* fileref;
|
||||
UNICODE_STRING filename;
|
||||
|
@ -309,6 +330,7 @@ typedef struct _tree {
|
|||
// UINT64 address;
|
||||
// UINT8 level;
|
||||
tree_header header;
|
||||
UINT32 hash;
|
||||
BOOL has_address;
|
||||
UINT32 size;
|
||||
struct _device_extension* Vcb;
|
||||
|
@ -318,10 +340,10 @@ typedef struct _tree {
|
|||
// tree_nonpaged* nonpaged;
|
||||
LIST_ENTRY itemlist;
|
||||
LIST_ENTRY list_entry;
|
||||
LIST_ENTRY list_entry_hash;
|
||||
UINT64 new_address;
|
||||
BOOL has_new_address;
|
||||
BOOL updated_extents;
|
||||
UINT64 flags;
|
||||
BOOL write;
|
||||
} tree;
|
||||
|
||||
|
@ -343,10 +365,15 @@ typedef struct _root {
|
|||
|
||||
enum batch_operation {
|
||||
Batch_Insert,
|
||||
Batch_Delete,
|
||||
Batch_SetXattr,
|
||||
Batch_DirItem,
|
||||
Batch_InodeRef,
|
||||
Batch_InodeExtRef,
|
||||
Batch_DeleteInode,
|
||||
Batch_DeleteDirItem,
|
||||
Batch_DeleteInodeRef,
|
||||
Batch_DeleteInodeExtRef,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
@ -386,11 +413,15 @@ typedef struct {
|
|||
BOOL removable;
|
||||
BOOL seeding;
|
||||
BOOL readonly;
|
||||
BOOL reloc;
|
||||
BOOL ssd;
|
||||
BOOL trim;
|
||||
ULONG change_count;
|
||||
UINT64 length;
|
||||
ULONG disk_num;
|
||||
ULONG part_num;
|
||||
LIST_ENTRY space;
|
||||
LIST_ENTRY list_entry;
|
||||
} device;
|
||||
|
||||
typedef struct {
|
||||
|
@ -419,9 +450,13 @@ typedef struct {
|
|||
ERESOURCE changed_extents_lock;
|
||||
BOOL created;
|
||||
BOOL readonly;
|
||||
BOOL reloc;
|
||||
BOOL last_alloc_set;
|
||||
UINT64 last_alloc;
|
||||
|
||||
LIST_ENTRY list_entry;
|
||||
LIST_ENTRY list_entry_changed;
|
||||
LIST_ENTRY list_entry_balance;
|
||||
} chunk;
|
||||
|
||||
typedef struct {
|
||||
|
@ -455,6 +490,31 @@ typedef struct {
|
|||
LIST_ENTRY list_entry;
|
||||
} sys_chunk;
|
||||
|
||||
typedef struct {
|
||||
UINT8* data;
|
||||
UINT32* csum;
|
||||
UINT32 sectors;
|
||||
LONG pos, done;
|
||||
KEVENT event;
|
||||
LONG refcount;
|
||||
LIST_ENTRY list_entry;
|
||||
} calc_job;
|
||||
|
||||
typedef struct {
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
HANDLE handle;
|
||||
KEVENT finished;
|
||||
BOOL quit;
|
||||
} drv_calc_thread;
|
||||
|
||||
typedef struct {
|
||||
ULONG num_threads;
|
||||
LIST_ENTRY job_list;
|
||||
ERESOURCE lock;
|
||||
drv_calc_thread* threads;
|
||||
KEVENT event;
|
||||
} drv_calc_threads;
|
||||
|
||||
typedef struct {
|
||||
BOOL ignore;
|
||||
BOOL compress;
|
||||
|
@ -467,10 +527,12 @@ typedef struct {
|
|||
UINT64 subvol_id;
|
||||
UINT32 raid5_recalculation;
|
||||
UINT32 raid6_recalculation;
|
||||
BOOL skip_balance;
|
||||
} mount_options;
|
||||
|
||||
#define VCB_TYPE_VOLUME 1
|
||||
#define VCB_TYPE_PARTITION0 2
|
||||
#define VCB_TYPE_CONTROL 3
|
||||
|
||||
#ifdef DEBUG_STATS
|
||||
typedef struct {
|
||||
|
@ -479,14 +541,40 @@ 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;
|
||||
} debug_stats;
|
||||
#endif
|
||||
|
||||
#define BALANCE_OPTS_DATA 0
|
||||
#define BALANCE_OPTS_METADATA 1
|
||||
#define BALANCE_OPTS_SYSTEM 2
|
||||
|
||||
typedef struct {
|
||||
HANDLE thread;
|
||||
UINT64 total_chunks;
|
||||
UINT64 chunks_left;
|
||||
btrfs_balance_opts opts[3];
|
||||
BOOL paused;
|
||||
BOOL stopping;
|
||||
BOOL cancelling;
|
||||
BOOL removing;
|
||||
BOOL dev_readonly;
|
||||
NTSTATUS status;
|
||||
KEVENT event;
|
||||
KEVENT finished;
|
||||
} balance_info;
|
||||
|
||||
typedef struct _device_extension {
|
||||
UINT32 type;
|
||||
mount_options options;
|
||||
PVPB Vpb;
|
||||
device* devices;
|
||||
LIST_ENTRY devices;
|
||||
#ifdef DEBUG_STATS
|
||||
debug_stats stats;
|
||||
#endif
|
||||
|
@ -497,14 +585,13 @@ typedef struct _device_extension {
|
|||
BOOL readonly;
|
||||
BOOL removing;
|
||||
BOOL locked;
|
||||
BOOL lock_paused_balance;
|
||||
BOOL disallow_dismount;
|
||||
BOOL trim;
|
||||
PFILE_OBJECT locked_fileobj;
|
||||
fcb* volume_fcb;
|
||||
file_ref* root_fileref;
|
||||
LONG open_files;
|
||||
ERESOURCE DirResource;
|
||||
KSPIN_LOCK FcbListLock;
|
||||
ERESOURCE fcb_lock;
|
||||
ERESOURCE load_lock;
|
||||
ERESOURCE tree_lock;
|
||||
|
@ -514,8 +601,9 @@ typedef struct _device_extension {
|
|||
BOOL need_write;
|
||||
// ERESOURCE LogToPhysLock;
|
||||
// UINT64 chunk_root_phys_addr;
|
||||
UINT64 root_tree_phys_addr;
|
||||
UINT64 data_flags;
|
||||
UINT64 metadata_flags;
|
||||
UINT64 system_flags;
|
||||
// log_to_phys* log_to_phys;
|
||||
LIST_ENTRY roots;
|
||||
LIST_ENTRY drop_roots;
|
||||
|
@ -531,17 +619,19 @@ typedef struct _device_extension {
|
|||
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;
|
||||
LIST_ENTRY dirty_filerefs;
|
||||
KSPIN_LOCK dirty_filerefs_lock;
|
||||
ERESOURCE checksum_lock;
|
||||
ERESOURCE chunk_lock;
|
||||
LIST_ENTRY sector_checksums;
|
||||
HANDLE flush_thread_handle;
|
||||
KTIMER flush_thread_timer;
|
||||
KEVENT flush_thread_finished;
|
||||
drv_calc_threads calcthreads;
|
||||
balance_info balance;
|
||||
PFILE_OBJECT root_file;
|
||||
PAGED_LOOKASIDE_LIST tree_data_lookaside;
|
||||
PAGED_LOOKASIDE_LIST traverse_ptr_lookaside;
|
||||
|
@ -558,24 +648,16 @@ typedef struct {
|
|||
UNICODE_STRING name;
|
||||
} part0_device_extension;
|
||||
|
||||
typedef struct {
|
||||
UINT32 type;
|
||||
} control_device_extension;
|
||||
|
||||
typedef struct {
|
||||
LIST_ENTRY listentry;
|
||||
PSID sid;
|
||||
UINT32 uid;
|
||||
} uid_map;
|
||||
|
||||
typedef struct {
|
||||
LIST_ENTRY list_entry;
|
||||
UINT64 key;
|
||||
} ordered_list;
|
||||
|
||||
typedef struct {
|
||||
ordered_list ol;
|
||||
ULONG length;
|
||||
UINT32* checksums;
|
||||
BOOL deleted;
|
||||
} changed_sector;
|
||||
|
||||
enum write_data_status {
|
||||
WriteDataStatus_Pending,
|
||||
WriteDataStatus_Success,
|
||||
|
@ -605,6 +687,14 @@ typedef struct _write_data_context {
|
|||
BOOL tree;
|
||||
} write_data_context;
|
||||
|
||||
typedef struct {
|
||||
UINT64 address;
|
||||
UINT32 length;
|
||||
BOOL overlap;
|
||||
UINT8* data;
|
||||
LIST_ENTRY list_entry;
|
||||
} tree_write;
|
||||
|
||||
// #pragma pack(pop)
|
||||
|
||||
static __inline void* map_user_buffer(PIRP Irp) {
|
||||
|
@ -626,27 +716,6 @@ static __inline void win_time_to_unix(LARGE_INTEGER t, BTRFS_TIME* out) {
|
|||
out->nanoseconds = (l % 10000000) * 100;
|
||||
}
|
||||
|
||||
static __inline void insert_into_ordered_list(LIST_ENTRY* list, ordered_list* ins) {
|
||||
LIST_ENTRY* le = list->Flink;
|
||||
ordered_list* ol;
|
||||
|
||||
while (le != list) {
|
||||
ol = (ordered_list*)le;
|
||||
|
||||
if (ol->key > ins->key) {
|
||||
le->Blink->Flink = &ins->list_entry;
|
||||
ins->list_entry.Blink = le->Blink;
|
||||
le->Blink = &ins->list_entry;
|
||||
ins->list_entry.Flink = le;
|
||||
return;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
InsertTailList(list, &ins->list_entry);
|
||||
}
|
||||
|
||||
static __inline void get_raid0_offset(UINT64 off, UINT64 stripe_length, UINT16 num_stripes, UINT64* stripeoff, UINT16* stripe) {
|
||||
UINT64 initoff, startoff;
|
||||
|
||||
|
@ -682,12 +751,12 @@ static UINT64 __inline make_file_id(root* r, UINT64 inode) {
|
|||
// 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);
|
||||
NTSTATUS delete_dir_item(device_extension* Vcb, root* subvol, UINT64 parinode, UINT32 crc32, PANSI_STRING utf8, PIRP Irp, LIST_ENTRY* rollback);
|
||||
NTSTATUS delete_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, PANSI_STRING utf8, PIRP Irp, LIST_ENTRY* rollback);
|
||||
fcb* create_fcb(POOL_TYPE pool_type);
|
||||
file_ref* create_fileref();
|
||||
void protect_superblocks(device_extension* Vcb, chunk* c);
|
||||
|
@ -708,6 +777,9 @@ 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);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define funcname __FUNCTION__
|
||||
|
@ -729,6 +801,7 @@ 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;
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
|
@ -815,6 +888,8 @@ typedef struct {
|
|||
|
||||
// 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);
|
||||
|
@ -832,6 +907,7 @@ void commit_batch_list(device_extension* Vcb, LIST_ENTRY* batchlist, PIRP Irp, L
|
|||
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__)
|
||||
|
@ -839,7 +915,13 @@ void clear_batch_list(device_extension* Vcb, LIST_ENTRY* batchlist);
|
|||
#define do_load_tree(Vcb, th, r, t, td, loaded, Irp) _do_load_tree(Vcb, th, r, t, td, loaded, Irp, funcname, __FILE__, __LINE__)
|
||||
|
||||
// in search.c
|
||||
void STDCALL look_for_vols(PDRIVER_OBJECT DriverObject, LIST_ENTRY* volumes);
|
||||
void remove_drive_letter(PDEVICE_OBJECT mountmgr, volume* v);
|
||||
void add_volume(PDEVICE_OBJECT mountmgr, PUNICODE_STRING us);
|
||||
#ifdef __REACTOS__
|
||||
NTSTATUS NTAPI pnp_notification(PVOID NotificationStructure, PVOID Context);
|
||||
#else
|
||||
NTSTATUS pnp_notification(PVOID NotificationStructure, PVOID Context);
|
||||
#endif
|
||||
|
||||
// in cache.c
|
||||
NTSTATUS STDCALL init_cache();
|
||||
|
@ -853,19 +935,18 @@ NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void
|
|||
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);
|
||||
void commit_checksum_changes(device_extension* Vcb, LIST_ENTRY* changed_sector_list);
|
||||
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);
|
||||
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, LIST_ENTRY* changed_sector_list,
|
||||
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, LIST_ENTRY* changed_sector_list, PIRP Irp, LIST_ENTRY* rollback);
|
||||
NTSTATUS do_write_file(fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, LIST_ENTRY* changed_sector_list, PIRP Irp, LIST_ENTRY* rollback);
|
||||
NTSTATUS write_compressed(fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, LIST_ENTRY* changed_sector_list, PIRP Irp, LIST_ENTRY* rollback);
|
||||
BOOL find_address_in_chunk(device_extension* Vcb, chunk* c, UINT64 length, UINT64* address);
|
||||
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);
|
||||
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);
|
||||
|
||||
// in dirctrl.c
|
||||
|
@ -875,7 +956,8 @@ ULONG STDCALL get_reparse_tag(device_extension* Vcb, root* subvol, UINT64 inode,
|
|||
// 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);
|
||||
void fcb_get_sd(fcb* fcb, struct _fcb* parent, PIRP Irp);
|
||||
BOOL get_sd_from_xattr(fcb* fcb, ULONG buflen);
|
||||
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);
|
||||
UINT32 sid_to_uid(PSID sid);
|
||||
|
@ -891,6 +973,8 @@ NTSTATUS fileref_get_filename(file_ref* fileref, PUNICODE_STRING fn, USHORT* nam
|
|||
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);
|
||||
void insert_dir_child_into_hash_lists(fcb* fcb, dir_child* dc);
|
||||
void remove_dir_child_from_hash_lists(fcb* fcb, dir_child* dc);
|
||||
|
||||
// in reparse.c
|
||||
NTSTATUS get_reparse_point(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, void* buffer, DWORD buflen, ULONG_PTR* retlen);
|
||||
|
@ -899,15 +983,16 @@ NTSTATUS delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
|||
|
||||
// in create.c
|
||||
NTSTATUS STDCALL drv_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
|
||||
NTSTATUS STDCALL find_file_in_dir(device_extension* Vcb, PUNICODE_STRING filename, file_ref* fr,
|
||||
root** subvol, UINT64* inode, UINT8* type, UINT64* index, PANSI_STRING utf8, BOOL case_sensitive, PIRP Irp);
|
||||
NTSTATUS open_fileref(device_extension* Vcb, file_ref** pfr, PUNICODE_STRING fnus, file_ref* related, BOOL parent, USHORT* unparsed, ULONG* fn_offset,
|
||||
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);
|
||||
|
||||
// in fsctl.c
|
||||
NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP Irp, UINT32 type, BOOL user);
|
||||
|
@ -920,11 +1005,15 @@ NTSTATUS get_tree_new_address(device_extension* Vcb, tree* t, PIRP Irp, LIST_ENT
|
|||
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);
|
||||
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);
|
||||
BOOL find_metadata_address_in_chunk(device_extension* Vcb, chunk* c, UINT64* address);
|
||||
|
||||
// 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);
|
||||
NTSTATUS STDCALL read_file(fcb* fcb, UINT8* data, UINT64 start, UINT64 length, ULONG* pbr, 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);
|
||||
|
||||
// in pnp.c
|
||||
|
@ -948,7 +1037,8 @@ void _space_list_subtract2(device_extension* Vcb, LIST_ENTRY* list, LIST_ENTRY*
|
|||
|
||||
// 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 decrease_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode, UINT64 offset, UINT32 refcount, PIRP Irp, LIST_ENTRY* rollback);
|
||||
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);
|
||||
|
@ -963,7 +1053,8 @@ void add_changed_extent_ref(chunk* c, UINT64 address, UINT64 size, UINT64 root,
|
|||
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);
|
||||
NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT8 type, void* data, KEY* firstitem,
|
||||
UINT8 level, UINT64 parent, PIRP Irp, LIST_ENTRY* rollback);
|
||||
UINT8 level, UINT64 parent, BOOL superseded, PIRP Irp, LIST_ENTRY* rollback);
|
||||
UINT64 get_extent_data_ref_hash2(UINT64 root, UINT64 objid, UINT64 offset);
|
||||
|
||||
// in worker-thread.c
|
||||
void do_read_job(PIRP Irp);
|
||||
|
@ -977,7 +1068,7 @@ NTSTATUS registry_load_volume_options(device_extension* Vcb);
|
|||
|
||||
// in compress.c
|
||||
NTSTATUS decompress(UINT8 type, UINT8* inbuf, UINT64 inlen, UINT8* outbuf, UINT64 outlen);
|
||||
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);
|
||||
NTSTATUS write_compressed_bit(fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, BOOL* compressed, PIRP Irp, LIST_ENTRY* rollback);
|
||||
|
||||
// in galois.c
|
||||
void galois_double(UINT8* data, UINT32 len);
|
||||
|
@ -989,6 +1080,24 @@ UINT8 gdiv(UINT8 a, UINT8 b);
|
|||
// in devctrl.c
|
||||
NTSTATUS STDCALL drv_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
|
||||
|
||||
// in calcthread.c
|
||||
#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);
|
||||
|
||||
// in balance.c
|
||||
NTSTATUS start_balance(device_extension* Vcb, void* data, ULONG length, KPROCESSOR_MODE processor_mode);
|
||||
NTSTATUS query_balance(device_extension* Vcb, void* data, ULONG length);
|
||||
NTSTATUS pause_balance(device_extension* Vcb, KPROCESSOR_MODE processor_mode);
|
||||
NTSTATUS resume_balance(device_extension* Vcb, KPROCESSOR_MODE processor_mode);
|
||||
NTSTATUS stop_balance(device_extension* Vcb, KPROCESSOR_MODE processor_mode);
|
||||
NTSTATUS look_for_balance_item(device_extension* Vcb);
|
||||
NTSTATUS remove_device(device_extension* Vcb, void* data, ULONG length, KPROCESSOR_MODE processor_mode);
|
||||
|
||||
#define fast_io_possible(fcb) (!FsRtlAreThereCurrentFileLocks(&fcb->lock) && !fcb->Vcb->readonly ? FastIoIsPossible : FastIoIsQuestionable)
|
||||
|
||||
static __inline void print_open_trees(device_extension* Vcb) {
|
||||
|
@ -1048,6 +1157,8 @@ static __inline void do_xor(UINT8* buf1, UINT8* buf2, UINT32 len) {
|
|||
}
|
||||
}
|
||||
|
||||
#define first_device(Vcb) CONTAINING_RECORD(Vcb->devices.Flink, device, list_entry)
|
||||
|
||||
#ifdef DEBUG_FCB_REFCOUNTS
|
||||
#ifdef DEBUG_LONG_MESSAGES
|
||||
#define increase_fileref_refcount(fileref) {\
|
||||
|
@ -1144,6 +1255,29 @@ static __inline void do_xor(UINT8* buf1, UINT8* buf2, UINT32 len) {
|
|||
#define called_from_lxss() FALSE
|
||||
#endif
|
||||
|
||||
typedef BOOLEAN (*tPsIsDiskCountersEnabled)();
|
||||
|
||||
typedef VOID (*tPsUpdateDiskCounters)(PEPROCESS Process, ULONG64 BytesRead, ULONG64 BytesWritten,
|
||||
ULONG ReadOperationCount, ULONG WriteOperationCount, ULONG FlushOperationCount);
|
||||
|
||||
typedef BOOLEAN (*tCcCopyWriteEx)(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait,
|
||||
PVOID Buffer, PETHREAD IoIssuerThread);
|
||||
|
||||
typedef BOOLEAN (*tCcCopyReadEx)(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait,
|
||||
PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PETHREAD IoIssuerThread);
|
||||
|
||||
#define CC_ENABLE_DISK_IO_ACCOUNTING 0x00000010
|
||||
|
||||
typedef VOID (*tCcSetAdditionalCacheAttributesEx)(PFILE_OBJECT FileObject, ULONG Flags);
|
||||
|
||||
#ifndef __REACTOS__
|
||||
#undef RtlIsNtDdiVersionAvailable
|
||||
|
||||
BOOLEAN RtlIsNtDdiVersionAvailable(ULONG Version);
|
||||
|
||||
PEPROCESS PsGetThreadProcess(PETHREAD Thread); // not in mingw
|
||||
#endif
|
||||
|
||||
#if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7)
|
||||
NTSTATUS WINAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max,
|
||||
ULONG *utf8_bytes_written,
|
||||
|
|
|
@ -8,6 +8,17 @@
|
|||
#define FSCTL_BTRFS_CREATE_SNAPSHOT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82b, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSCTL_BTRFS_GET_INODE_INFO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82c, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSCTL_BTRFS_SET_INODE_INFO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82d, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSCTL_BTRFS_GET_DEVICES CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82e, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSCTL_BTRFS_GET_USAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82f, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSCTL_BTRFS_START_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x830, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSCTL_BTRFS_QUERY_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x831, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSCTL_BTRFS_PAUSE_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x832, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSCTL_BTRFS_RESUME_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x833, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSCTL_BTRFS_STOP_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x834, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSCTL_BTRFS_ADD_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x835, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSCTL_BTRFS_REMOVE_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x836, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IOCTL_BTRFS_QUERY_FILESYSTEMS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x837, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSCTL_BTRFS_GET_UUID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x838, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
|
||||
typedef struct {
|
||||
UINT64 subvol;
|
||||
|
@ -46,4 +57,92 @@ typedef struct {
|
|||
BOOL mode_changed;
|
||||
} btrfs_set_inode_info;
|
||||
|
||||
typedef struct {
|
||||
UINT32 next_entry;
|
||||
UINT64 dev_id;
|
||||
UINT64 size;
|
||||
BOOL readonly;
|
||||
ULONG device_number;
|
||||
ULONG partition_number;
|
||||
USHORT namelen;
|
||||
WCHAR name[1];
|
||||
} btrfs_device;
|
||||
|
||||
typedef struct {
|
||||
UINT64 dev_id;
|
||||
UINT64 alloc;
|
||||
} btrfs_usage_device;
|
||||
|
||||
typedef struct {
|
||||
UINT32 next_entry;
|
||||
UINT64 type;
|
||||
UINT64 size;
|
||||
UINT64 used;
|
||||
UINT64 num_devices;
|
||||
btrfs_usage_device devices[1];
|
||||
} btrfs_usage;
|
||||
|
||||
#define BTRFS_BALANCE_OPTS_ENABLED 0x001
|
||||
#define BTRFS_BALANCE_OPTS_PROFILES 0x002
|
||||
#define BTRFS_BALANCE_OPTS_DEVID 0x004
|
||||
#define BTRFS_BALANCE_OPTS_DRANGE 0x008
|
||||
#define BTRFS_BALANCE_OPTS_VRANGE 0x010
|
||||
#define BTRFS_BALANCE_OPTS_LIMIT 0x020
|
||||
#define BTRFS_BALANCE_OPTS_STRIPES 0x040
|
||||
#define BTRFS_BALANCE_OPTS_USAGE 0x080
|
||||
#define BTRFS_BALANCE_OPTS_CONVERT 0x100
|
||||
#define BTRFS_BALANCE_OPTS_SOFT 0x200
|
||||
|
||||
#define BLOCK_FLAG_SINGLE 0x1000000000000 // only used in balance
|
||||
|
||||
typedef struct {
|
||||
UINT64 flags;
|
||||
UINT64 profiles;
|
||||
UINT64 devid;
|
||||
UINT64 drange_start;
|
||||
UINT64 drange_end;
|
||||
UINT64 vrange_start;
|
||||
UINT64 vrange_end;
|
||||
UINT64 limit_start;
|
||||
UINT64 limit_end;
|
||||
UINT16 stripes_start;
|
||||
UINT16 stripes_end;
|
||||
UINT8 usage_start;
|
||||
UINT8 usage_end;
|
||||
UINT64 convert;
|
||||
} btrfs_balance_opts;
|
||||
|
||||
#define BTRFS_BALANCE_STOPPED 0
|
||||
#define BTRFS_BALANCE_RUNNING 1
|
||||
#define BTRFS_BALANCE_PAUSED 2
|
||||
#define BTRFS_BALANCE_REMOVAL 4
|
||||
#define BTRFS_BALANCE_ERROR 8
|
||||
|
||||
typedef struct {
|
||||
UINT32 status;
|
||||
UINT64 chunks_left;
|
||||
UINT64 total_chunks;
|
||||
NTSTATUS error;
|
||||
btrfs_balance_opts data_opts;
|
||||
btrfs_balance_opts metadata_opts;
|
||||
btrfs_balance_opts system_opts;
|
||||
} btrfs_query_balance;
|
||||
|
||||
typedef struct {
|
||||
btrfs_balance_opts opts[3];
|
||||
} btrfs_start_balance;
|
||||
|
||||
typedef struct {
|
||||
UINT8 uuid[16];
|
||||
USHORT name_length;
|
||||
WCHAR name[1];
|
||||
} btrfs_filesystem_device;
|
||||
|
||||
typedef struct {
|
||||
UINT32 next_entry;
|
||||
UINT8 uuid[16];
|
||||
UINT32 num_devices;
|
||||
btrfs_filesystem_device device;
|
||||
} btrfs_filesystem;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,9 +28,14 @@ static BOOLEAN STDCALL acquire_for_lazy_write(PVOID Context, BOOLEAN Wait) {
|
|||
|
||||
// if (!fcb || FileObject->Flags & FO_CLEANUP_COMPLETE)
|
||||
// return FALSE;
|
||||
|
||||
if (!ExAcquireResourceSharedLite(fcb->Header.PagingIoResource, Wait))
|
||||
|
||||
if (!ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, Wait))
|
||||
return FALSE;
|
||||
|
||||
if (!ExAcquireResourceExclusiveLite(fcb->Header.Resource, Wait)) {
|
||||
ExReleaseResourceLite(&fcb->Vcb->tree_lock);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fcb->lazy_writer_thread = KeGetCurrentThread();
|
||||
|
||||
|
@ -48,7 +53,9 @@ static void STDCALL release_from_lazy_write(PVOID Context) {
|
|||
|
||||
fcb->lazy_writer_thread = NULL;
|
||||
|
||||
ExReleaseResourceLite(fcb->Header.PagingIoResource);
|
||||
ExReleaseResourceLite(fcb->Header.Resource);
|
||||
|
||||
ExReleaseResourceLite(&fcb->Vcb->tree_lock);
|
||||
}
|
||||
|
||||
static BOOLEAN STDCALL acquire_for_read_ahead(PVOID Context, BOOLEAN Wait) {
|
||||
|
|
142
reactos/drivers/filesystems/btrfs/calcthread.c
Normal file
142
reactos/drivers/filesystems/btrfs/calcthread.c
Normal file
|
@ -0,0 +1,142 @@
|
|||
/* Copyright (c) Mark Harmstone 2016
|
||||
*
|
||||
* 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/>. */
|
||||
|
||||
#include "btrfs_drv.h"
|
||||
|
||||
#define SECTOR_BLOCK 16
|
||||
|
||||
NTSTATUS add_calc_job(device_extension* Vcb, UINT8* data, UINT32 sectors, UINT32* csum, calc_job** pcj) {
|
||||
calc_job* cj;
|
||||
|
||||
cj = ExAllocatePoolWithTag(NonPagedPool, sizeof(calc_job), ALLOC_TAG);
|
||||
if (!cj) {
|
||||
ERR("out of memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
cj->data = data;
|
||||
cj->sectors = sectors;
|
||||
cj->csum = csum;
|
||||
cj->pos = 0;
|
||||
cj->done = 0;
|
||||
cj->refcount = 1;
|
||||
KeInitializeEvent(&cj->event, NotificationEvent, FALSE);
|
||||
|
||||
ExAcquireResourceExclusiveLite(&Vcb->calcthreads.lock, TRUE);
|
||||
InsertTailList(&Vcb->calcthreads.job_list, &cj->list_entry);
|
||||
ExReleaseResourceLite(&Vcb->calcthreads.lock);
|
||||
|
||||
KeSetEvent(&Vcb->calcthreads.event, 0, FALSE);
|
||||
KeClearEvent(&Vcb->calcthreads.event);
|
||||
|
||||
*pcj = cj;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void free_calc_job(calc_job* cj) {
|
||||
LONG rc = InterlockedDecrement(&cj->refcount);
|
||||
|
||||
if (rc == 0)
|
||||
ExFreePool(cj);
|
||||
}
|
||||
|
||||
static BOOL do_calc(device_extension* Vcb, calc_job* cj) {
|
||||
LONG pos, done;
|
||||
UINT32* csum;
|
||||
UINT8* data;
|
||||
ULONG blocksize, i;
|
||||
|
||||
pos = InterlockedIncrement(&cj->pos) - 1;
|
||||
|
||||
if (pos * SECTOR_BLOCK >= cj->sectors)
|
||||
return FALSE;
|
||||
|
||||
csum = &cj->csum[pos * SECTOR_BLOCK];
|
||||
data = cj->data + (pos * SECTOR_BLOCK * Vcb->superblock.sector_size);
|
||||
|
||||
blocksize = min(SECTOR_BLOCK, cj->sectors - (pos * SECTOR_BLOCK));
|
||||
for (i = 0; i < blocksize; i++) {
|
||||
*csum = ~calc_crc32c(0xffffffff, data, Vcb->superblock.sector_size);
|
||||
csum++;
|
||||
data += Vcb->superblock.sector_size;
|
||||
}
|
||||
|
||||
done = InterlockedIncrement(&cj->done);
|
||||
|
||||
if (done * SECTOR_BLOCK >= cj->sectors) {
|
||||
ExAcquireResourceExclusiveLite(&Vcb->calcthreads.lock, TRUE);
|
||||
RemoveEntryList(&cj->list_entry);
|
||||
ExReleaseResourceLite(&Vcb->calcthreads.lock);
|
||||
|
||||
KeSetEvent(&cj->event, 0, FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef __REACTOS__
|
||||
void NTAPI calc_thread(void* context) {
|
||||
#else
|
||||
void calc_thread(void* context) {
|
||||
#endif
|
||||
drv_calc_thread* thread = context;
|
||||
device_extension* Vcb = thread->DeviceObject->DeviceExtension;
|
||||
|
||||
ObReferenceObject(thread->DeviceObject);
|
||||
|
||||
while (TRUE) {
|
||||
KeWaitForSingleObject(&Vcb->calcthreads.event, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
|
||||
while (TRUE) {
|
||||
calc_job* cj;
|
||||
BOOL b;
|
||||
|
||||
ExAcquireResourceExclusiveLite(&Vcb->calcthreads.lock, TRUE);
|
||||
|
||||
if (IsListEmpty(&Vcb->calcthreads.job_list)) {
|
||||
ExReleaseResourceLite(&Vcb->calcthreads.lock);
|
||||
break;
|
||||
}
|
||||
|
||||
cj = CONTAINING_RECORD(Vcb->calcthreads.job_list.Flink, calc_job, list_entry);
|
||||
cj->refcount++;
|
||||
|
||||
ExReleaseResourceLite(&Vcb->calcthreads.lock);
|
||||
|
||||
b = do_calc(Vcb, cj);
|
||||
|
||||
free_calc_job(cj);
|
||||
|
||||
if (!b)
|
||||
break;
|
||||
}
|
||||
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
if (thread->quit)
|
||||
break;
|
||||
}
|
||||
|
||||
ObDereferenceObject(thread->DeviceObject);
|
||||
|
||||
KeSetEvent(&thread->finished, 0, FALSE);
|
||||
|
||||
PsTerminateSystemThread(STATUS_SUCCESS);
|
||||
}
|
|
@ -357,7 +357,7 @@ NTSTATUS decompress(UINT8 type, UINT8* inbuf, UINT64 inlen, UINT8* outbuf, UINT6
|
|||
}
|
||||
}
|
||||
|
||||
static NTSTATUS zlib_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) {
|
||||
static NTSTATUS zlib_write_compressed_bit(fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, BOOL* compressed, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
NTSTATUS Status;
|
||||
UINT8 compression;
|
||||
UINT64 comp_length;
|
||||
|
@ -444,11 +444,11 @@ static NTSTATUS zlib_write_compressed_bit(fcb* fcb, UINT64 start_data, UINT64 en
|
|||
while (le != &fcb->Vcb->chunks) {
|
||||
c = CONTAINING_RECORD(le, chunk, list_entry);
|
||||
|
||||
if (!c->readonly) {
|
||||
if (!c->readonly && !c->reloc) {
|
||||
ExAcquireResourceExclusiveLite(&c->lock, TRUE);
|
||||
|
||||
if (c->chunk_item->type == fcb->Vcb->data_flags && (c->chunk_item->size - c->used) >= comp_length) {
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start_data, comp_length, FALSE, comp_data, changed_sector_list, Irp, rollback, compression, end_data - start_data)) {
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start_data, comp_length, FALSE, comp_data, Irp, rollback, compression, end_data - start_data)) {
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
|
||||
if (compression != BTRFS_COMPRESSION_NONE)
|
||||
|
@ -474,7 +474,7 @@ static NTSTATUS zlib_write_compressed_bit(fcb* fcb, UINT64 start_data, UINT64 en
|
|||
ExAcquireResourceExclusiveLite(&c->lock, TRUE);
|
||||
|
||||
if (c->chunk_item->type == fcb->Vcb->data_flags && (c->chunk_item->size - c->used) >= comp_length) {
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start_data, comp_length, FALSE, comp_data, changed_sector_list, Irp, rollback, compression, end_data - start_data)) {
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start_data, comp_length, FALSE, comp_data, Irp, rollback, compression, end_data - start_data)) {
|
||||
if (compression != BTRFS_COMPRESSION_NONE)
|
||||
ExFreePool(comp_data);
|
||||
|
||||
|
@ -732,7 +732,7 @@ static __inline UINT32 lzo_max_outlen(UINT32 inlen) {
|
|||
return inlen + (inlen / 16) + 64 + 3; // formula comes from LZO.FAQ
|
||||
}
|
||||
|
||||
static NTSTATUS lzo_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) {
|
||||
static NTSTATUS lzo_write_compressed_bit(fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, BOOL* compressed, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
NTSTATUS Status;
|
||||
UINT8 compression;
|
||||
UINT64 comp_length;
|
||||
|
@ -829,11 +829,11 @@ static NTSTATUS lzo_write_compressed_bit(fcb* fcb, UINT64 start_data, UINT64 end
|
|||
while (le != &fcb->Vcb->chunks) {
|
||||
c = CONTAINING_RECORD(le, chunk, list_entry);
|
||||
|
||||
if (!c->readonly) {
|
||||
if (!c->readonly && !c->reloc) {
|
||||
ExAcquireResourceExclusiveLite(&c->lock, TRUE);
|
||||
|
||||
if (c->chunk_item->type == fcb->Vcb->data_flags && (c->chunk_item->size - c->used) >= comp_length) {
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start_data, comp_length, FALSE, comp_data, changed_sector_list, Irp, rollback, compression, end_data - start_data)) {
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start_data, comp_length, FALSE, comp_data, Irp, rollback, compression, end_data - start_data)) {
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
|
||||
if (compression != BTRFS_COMPRESSION_NONE)
|
||||
|
@ -859,7 +859,7 @@ static NTSTATUS lzo_write_compressed_bit(fcb* fcb, UINT64 start_data, UINT64 end
|
|||
ExAcquireResourceExclusiveLite(&c->lock, TRUE);
|
||||
|
||||
if (c->chunk_item->type == fcb->Vcb->data_flags && (c->chunk_item->size - c->used) >= comp_length) {
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start_data, comp_length, FALSE, comp_data, changed_sector_list, Irp, rollback, compression, end_data - start_data)) {
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start_data, comp_length, FALSE, comp_data, Irp, rollback, compression, end_data - start_data)) {
|
||||
if (compression != BTRFS_COMPRESSION_NONE)
|
||||
ExFreePool(comp_data);
|
||||
|
||||
|
@ -876,7 +876,7 @@ static NTSTATUS lzo_write_compressed_bit(fcb* fcb, UINT64 start_data, UINT64 end
|
|||
return STATUS_DISK_FULL;
|
||||
}
|
||||
|
||||
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) {
|
||||
NTSTATUS write_compressed_bit(fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, BOOL* compressed, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
UINT8 type;
|
||||
|
||||
if (fcb->Vcb->options.compress_type != 0)
|
||||
|
@ -890,7 +890,7 @@ NTSTATUS write_compressed_bit(fcb* fcb, UINT64 start_data, UINT64 end_data, void
|
|||
|
||||
if (type == BTRFS_COMPRESSION_LZO) {
|
||||
fcb->Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO;
|
||||
return lzo_write_compressed_bit(fcb, start_data, end_data, data, compressed, changed_sector_list, Irp, rollback);
|
||||
return lzo_write_compressed_bit(fcb, start_data, end_data, data, compressed, Irp, rollback);
|
||||
} else
|
||||
return zlib_write_compressed_bit(fcb, start_data, end_data, data, compressed, changed_sector_list, Irp, rollback);
|
||||
return zlib_write_compressed_bit(fcb, start_data, end_data, data, compressed, Irp, rollback);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -23,6 +23,9 @@
|
|||
#include <initguid.h>
|
||||
#include <diskguid.h>
|
||||
|
||||
extern LIST_ENTRY VcbList;
|
||||
extern ERESOURCE global_loading_lock;
|
||||
|
||||
static NTSTATUS part0_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
|
||||
NTSTATUS Status;
|
||||
part0_device_extension* p0de = DeviceObject->DeviceExtension;
|
||||
|
@ -79,7 +82,7 @@ static NTSTATUS part0_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp
|
|||
name = Irp->AssociatedIrp.SystemBuffer;
|
||||
name->NameLength = p0de->name.Length;
|
||||
|
||||
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_NAME) - 1 + name->NameLength) {
|
||||
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < offsetof(MOUNTDEV_NAME, Name[0]) + name->NameLength) {
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
|
||||
|
@ -91,7 +94,7 @@ static NTSTATUS part0_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp
|
|||
|
||||
Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME) - 1 + name->NameLength;
|
||||
Irp->IoStatus.Information = offsetof(MOUNTDEV_NAME, Name[0]) + name->NameLength;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return Status;
|
||||
|
@ -130,7 +133,7 @@ static NTSTATUS get_partition_info_ex(device_extension* Vcb, PIRP Irp) {
|
|||
|
||||
TRACE("IOCTL_DISK_GET_PARTITION_INFO_EX\n");
|
||||
|
||||
Status = dev_ioctl(Vcb->devices[0].devobj, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0,
|
||||
Status = dev_ioctl(Vcb->Vpb->RealDevice, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0,
|
||||
Irp->UserBuffer, IrpSp->Parameters.DeviceIoControl.OutputBufferLength, TRUE, &Irp->IoStatus);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
@ -153,6 +156,132 @@ static NTSTATUS is_writable(device_extension* Vcb, PIRP Irp) {
|
|||
return Vcb->readonly ? STATUS_MEDIA_WRITE_PROTECTED : STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS query_filesystems(void* data, ULONG length) {
|
||||
NTSTATUS Status;
|
||||
LIST_ENTRY *le, *le2;
|
||||
btrfs_filesystem* bfs = NULL;
|
||||
ULONG itemsize;
|
||||
|
||||
ExAcquireResourceSharedLite(&global_loading_lock, TRUE);
|
||||
|
||||
if (IsListEmpty(&VcbList)) {
|
||||
if (length < sizeof(btrfs_filesystem)) {
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
goto end;
|
||||
} else {
|
||||
RtlZeroMemory(data, sizeof(btrfs_filesystem));
|
||||
Status = STATUS_SUCCESS;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
le = VcbList.Flink;
|
||||
|
||||
while (le != &VcbList) {
|
||||
device_extension* Vcb = CONTAINING_RECORD(le, device_extension, list_entry);
|
||||
btrfs_filesystem_device* bfd;
|
||||
|
||||
if (bfs) {
|
||||
bfs->next_entry = itemsize;
|
||||
bfs = (btrfs_filesystem*)((UINT8*)bfs + itemsize);
|
||||
} else
|
||||
bfs = data;
|
||||
|
||||
if (length < offsetof(btrfs_filesystem, device)) {
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
goto end;
|
||||
}
|
||||
|
||||
itemsize = offsetof(btrfs_filesystem, device);
|
||||
length -= offsetof(btrfs_filesystem, device);
|
||||
|
||||
bfs->next_entry = 0;
|
||||
RtlCopyMemory(&bfs->uuid, &Vcb->superblock.uuid, sizeof(BTRFS_UUID));
|
||||
|
||||
ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE);
|
||||
|
||||
bfs->num_devices = Vcb->superblock.num_devices;
|
||||
|
||||
bfd = NULL;
|
||||
|
||||
le2 = Vcb->devices.Flink;
|
||||
while (le2 != &Vcb->devices) {
|
||||
device* dev = CONTAINING_RECORD(le2, device, list_entry);
|
||||
MOUNTDEV_NAME mdn;
|
||||
|
||||
if (bfd)
|
||||
bfd = (btrfs_filesystem_device*)((UINT8*)bfd + offsetof(btrfs_filesystem_device, name[0]) + bfd->name_length);
|
||||
else
|
||||
bfd = &bfs->device;
|
||||
|
||||
if (length < offsetof(btrfs_filesystem_device, name[0])) {
|
||||
ExReleaseResourceLite(&Vcb->tree_lock);
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
goto end;
|
||||
}
|
||||
|
||||
itemsize += offsetof(btrfs_filesystem_device, name[0]);
|
||||
length -= offsetof(btrfs_filesystem_device, name[0]);
|
||||
|
||||
RtlCopyMemory(&bfd->uuid, &dev->devitem.device_uuid, sizeof(BTRFS_UUID));
|
||||
|
||||
Status = dev_ioctl(dev->devobj, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &mdn, sizeof(MOUNTDEV_NAME), TRUE, NULL);
|
||||
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) {
|
||||
ExReleaseResourceLite(&Vcb->tree_lock);
|
||||
ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (mdn.NameLength > length) {
|
||||
ExReleaseResourceLite(&Vcb->tree_lock);
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
goto end;
|
||||
}
|
||||
|
||||
Status = dev_ioctl(dev->devobj, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &bfd->name_length, offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength, TRUE, NULL);
|
||||
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) {
|
||||
ExReleaseResourceLite(&Vcb->tree_lock);
|
||||
ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
itemsize += bfd->name_length;
|
||||
length -= bfd->name_length;
|
||||
|
||||
le2 = le2->Flink;
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&Vcb->tree_lock);
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
end:
|
||||
ExReleaseResourceLite(&global_loading_lock);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS control_ioctl(PIRP Irp) {
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
NTSTATUS Status;
|
||||
|
||||
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
|
||||
case IOCTL_BTRFS_QUERY_FILESYSTEMS:
|
||||
Status = query_filesystems(map_user_buffer(Irp), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
|
||||
break;
|
||||
|
||||
default:
|
||||
TRACE("unhandled ioctl %x\n", IrpSp->Parameters.DeviceIoControl.IoControlCode);
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL drv_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
|
||||
NTSTATUS Status;
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
@ -165,9 +294,22 @@ NTSTATUS STDCALL drv_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
if (Vcb && Vcb->type == VCB_TYPE_PARTITION0) {
|
||||
Status = part0_device_control(DeviceObject, Irp);
|
||||
goto end2;
|
||||
if (Vcb) {
|
||||
if (Vcb->type == VCB_TYPE_PARTITION0) {
|
||||
Status = part0_device_control(DeviceObject, Irp);
|
||||
goto end2;
|
||||
} else if (Vcb->type == VCB_TYPE_CONTROL) {
|
||||
Status = control_ioctl(Irp);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!IrpSp->FileObject || IrpSp->FileObject->FsContext != Vcb->volume_fcb) {
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto end;
|
||||
}
|
||||
|
||||
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
|
||||
|
@ -190,7 +332,7 @@ NTSTATUS STDCALL drv_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
Status = IoCallDriver(Vcb->devices[0].devobj, Irp);
|
||||
Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
|
||||
|
||||
goto end2;
|
||||
|
||||
|
|
|
@ -25,9 +25,7 @@ enum DirEntryType {
|
|||
|
||||
typedef struct {
|
||||
KEY key;
|
||||
BOOL name_alloc;
|
||||
char* name;
|
||||
ULONG namelen;
|
||||
UNICODE_STRING name;
|
||||
UINT8 type;
|
||||
enum DirEntryType dir_entry_type;
|
||||
} dir_entry;
|
||||
|
@ -50,14 +48,11 @@ ULONG STDCALL get_reparse_tag(device_extension* Vcb, root* subvol, UINT64 inode,
|
|||
if (!(atts & FILE_ATTRIBUTE_REPARSE_POINT))
|
||||
return 0;
|
||||
|
||||
ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE);
|
||||
Status = open_fcb(Vcb, subvol, inode, type, NULL, NULL, &fcb, PagedPool, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("open_fcb returned %08x\n", Status);
|
||||
ExReleaseResourceLite(&Vcb->fcb_lock);
|
||||
return 0;
|
||||
}
|
||||
ExReleaseResourceLite(&Vcb->fcb_lock);
|
||||
|
||||
ExAcquireResourceSharedLite(fcb->Header.Resource, TRUE);
|
||||
|
||||
|
@ -67,7 +62,7 @@ ULONG STDCALL get_reparse_tag(device_extension* Vcb, root* subvol, UINT64 inode,
|
|||
|
||||
RtlCopyMemory(&tag, fcb->reparse_xattr.Buffer, sizeof(ULONG));
|
||||
} else {
|
||||
Status = read_file(fcb, (UINT8*)&tag, 0, sizeof(ULONG), &br, NULL);
|
||||
Status = read_file(fcb, (UINT8*)&tag, 0, sizeof(ULONG), &br, NULL, TRUE);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("read_file returned %08x\n", Status);
|
||||
goto end;
|
||||
|
@ -80,9 +75,7 @@ ULONG STDCALL get_reparse_tag(device_extension* Vcb, root* subvol, UINT64 inode,
|
|||
end:
|
||||
ExReleaseResourceLite(fcb->Header.Resource);
|
||||
|
||||
ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE);
|
||||
free_fcb(fcb);
|
||||
ExReleaseResourceLite(&Vcb->fcb_lock);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
@ -130,7 +123,6 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
UINT64 inode;
|
||||
INODE_ITEM ii;
|
||||
NTSTATUS Status;
|
||||
ULONG stringlen;
|
||||
ULONG atts, ealen;
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
@ -169,7 +161,6 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
LIST_ENTRY* le;
|
||||
BOOL found = FALSE;
|
||||
|
||||
ExAcquireResourceSharedLite(&fcb->Vcb->fcb_lock, TRUE);
|
||||
if (!IsListEmpty(&r->fcbs)) {
|
||||
le = r->fcbs.Flink;
|
||||
while (le != &r->fcbs) {
|
||||
|
@ -181,12 +172,12 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
ealen = fcb2->ealen;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
} else if (fcb2->inode > inode)
|
||||
break;
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
}
|
||||
ExReleaseResourceLite(&fcb->Vcb->fcb_lock);
|
||||
|
||||
if (!found) {
|
||||
KEY searchkey;
|
||||
|
@ -218,7 +209,7 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation) {
|
||||
|
||||
BOOL dotfile = de->namelen > 1 && de->name[0] == '.';
|
||||
BOOL dotfile = de->name.Length > sizeof(WCHAR) && de->name.Buffer[0] == '.';
|
||||
|
||||
atts = get_file_attributes(fcb->Vcb, &ii, r, inode, de->type, dotfile, FALSE, Irp);
|
||||
}
|
||||
|
@ -257,21 +248,6 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
}
|
||||
}
|
||||
|
||||
// FICs which return the filename
|
||||
if (IrpSp->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileFullDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation ||
|
||||
IrpSp->Parameters.QueryDirectory.FileInformationClass == FileNamesInformation) {
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(NULL, 0, &stringlen, de->name, de->namelen);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) {
|
||||
case FileBothDirectoryInformation:
|
||||
{
|
||||
|
@ -279,7 +255,7 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
|
||||
TRACE("FileBothDirectoryInformation\n");
|
||||
|
||||
needed = sizeof(FILE_BOTH_DIR_INFORMATION) - sizeof(WCHAR) + stringlen;
|
||||
needed = sizeof(FILE_BOTH_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length;
|
||||
|
||||
if (needed > *len) {
|
||||
TRACE("buffer overflow - %u > %u\n", needed, *len);
|
||||
|
@ -295,17 +271,12 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
fbdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
|
||||
fbdi->AllocationSize.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_blocks;
|
||||
fbdi->FileAttributes = atts;
|
||||
fbdi->FileNameLength = stringlen;
|
||||
fbdi->FileNameLength = de->name.Length;
|
||||
fbdi->EaSize = atts & FILE_ATTRIBUTE_REPARSE_POINT ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, Irp) : ealen;
|
||||
fbdi->ShortNameLength = 0;
|
||||
// fibdi->ShortName[12];
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(fbdi->FileName, stringlen, &stringlen, de->name, de->namelen);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
RtlCopyMemory(fbdi->FileName, de->name.Buffer, de->name.Length);
|
||||
|
||||
*len -= needed;
|
||||
|
||||
|
@ -318,7 +289,7 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
|
||||
TRACE("FileDirectoryInformation\n");
|
||||
|
||||
needed = sizeof(FILE_DIRECTORY_INFORMATION) - sizeof(WCHAR) + stringlen;
|
||||
needed = sizeof(FILE_DIRECTORY_INFORMATION) - sizeof(WCHAR) + de->name.Length;
|
||||
|
||||
if (needed > *len) {
|
||||
TRACE("buffer overflow - %u > %u\n", needed, *len);
|
||||
|
@ -334,14 +305,9 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
fdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
|
||||
fdi->AllocationSize.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_blocks;
|
||||
fdi->FileAttributes = atts;
|
||||
fdi->FileNameLength = stringlen;
|
||||
fdi->FileNameLength = de->name.Length;
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(fdi->FileName, stringlen, &stringlen, de->name, de->namelen);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
RtlCopyMemory(fdi->FileName, de->name.Buffer, de->name.Length);
|
||||
|
||||
*len -= needed;
|
||||
|
||||
|
@ -354,7 +320,7 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
|
||||
TRACE("FileFullDirectoryInformation\n");
|
||||
|
||||
needed = sizeof(FILE_FULL_DIR_INFORMATION) - sizeof(WCHAR) + stringlen;
|
||||
needed = sizeof(FILE_FULL_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length;
|
||||
|
||||
if (needed > *len) {
|
||||
TRACE("buffer overflow - %u > %u\n", needed, *len);
|
||||
|
@ -370,15 +336,10 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
ffdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
|
||||
ffdi->AllocationSize.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_blocks;
|
||||
ffdi->FileAttributes = atts;
|
||||
ffdi->FileNameLength = stringlen;
|
||||
ffdi->FileNameLength = de->name.Length;
|
||||
ffdi->EaSize = atts & FILE_ATTRIBUTE_REPARSE_POINT ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, Irp) : ealen;
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(ffdi->FileName, stringlen, &stringlen, de->name, de->namelen);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
RtlCopyMemory(ffdi->FileName, de->name.Buffer, de->name.Length);
|
||||
|
||||
*len -= needed;
|
||||
|
||||
|
@ -391,7 +352,7 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
|
||||
TRACE("FileIdBothDirectoryInformation\n");
|
||||
|
||||
needed = sizeof(FILE_ID_BOTH_DIR_INFORMATION) - sizeof(WCHAR) + stringlen;
|
||||
needed = sizeof(FILE_ID_BOTH_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length;
|
||||
|
||||
if (needed > *len) {
|
||||
TRACE("buffer overflow - %u > %u\n", needed, *len);
|
||||
|
@ -410,18 +371,13 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
fibdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
|
||||
fibdi->AllocationSize.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_blocks;
|
||||
fibdi->FileAttributes = atts;
|
||||
fibdi->FileNameLength = stringlen;
|
||||
fibdi->FileNameLength = de->name.Length;
|
||||
fibdi->EaSize = atts & FILE_ATTRIBUTE_REPARSE_POINT ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, Irp) : ealen;
|
||||
fibdi->ShortNameLength = 0;
|
||||
// fibdi->ShortName[12];
|
||||
fibdi->FileId.QuadPart = make_file_id(r, inode);
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(fibdi->FileName, stringlen, &stringlen, de->name, de->namelen);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
RtlCopyMemory(fibdi->FileName, de->name.Buffer, de->name.Length);
|
||||
|
||||
*len -= needed;
|
||||
|
||||
|
@ -434,7 +390,7 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
|
||||
TRACE("FileIdFullDirectoryInformation\n");
|
||||
|
||||
needed = sizeof(FILE_ID_FULL_DIR_INFORMATION) - sizeof(WCHAR) + stringlen;
|
||||
needed = sizeof(FILE_ID_FULL_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length;
|
||||
|
||||
if (needed > *len) {
|
||||
TRACE("buffer overflow - %u > %u\n", needed, *len);
|
||||
|
@ -453,16 +409,11 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
fifdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size;
|
||||
fifdi->AllocationSize.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_blocks;
|
||||
fifdi->FileAttributes = atts;
|
||||
fifdi->FileNameLength = stringlen;
|
||||
fifdi->FileNameLength = de->name.Length;
|
||||
fifdi->EaSize = atts & FILE_ATTRIBUTE_REPARSE_POINT ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, Irp) : ealen;
|
||||
fifdi->FileId.QuadPart = make_file_id(r, inode);
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(fifdi->FileName, stringlen, &stringlen, de->name, de->namelen);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
RtlCopyMemory(fifdi->FileName, de->name.Buffer, de->name.Length);
|
||||
|
||||
*len -= needed;
|
||||
|
||||
|
@ -475,7 +426,7 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
|
||||
TRACE("FileNamesInformation\n");
|
||||
|
||||
needed = sizeof(FILE_NAMES_INFORMATION) - sizeof(WCHAR) + stringlen;
|
||||
needed = sizeof(FILE_NAMES_INFORMATION) - sizeof(WCHAR) + de->name.Length;
|
||||
|
||||
if (needed > *len) {
|
||||
TRACE("buffer overflow - %u > %u\n", needed, *len);
|
||||
|
@ -484,14 +435,9 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
|
||||
fni->NextEntryOffset = 0;
|
||||
fni->FileIndex = 0;
|
||||
fni->FileNameLength = stringlen;
|
||||
fni->FileNameLength = de->name.Length;
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(fni->FileName, stringlen, &stringlen, de->name, de->namelen);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
RtlCopyMemory(fni->FileName, de->name.Buffer, de->name.Length);
|
||||
|
||||
*len -= needed;
|
||||
|
||||
|
@ -518,14 +464,20 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
return STATUS_NO_MORE_FILES;
|
||||
}
|
||||
|
||||
static NTSTATUS STDCALL next_dir_entry(file_ref* fileref, UINT64* offset, dir_entry* de, PIRP Irp) {
|
||||
KEY searchkey;
|
||||
traverse_ptr tp, next_tp;
|
||||
DIR_ITEM* di;
|
||||
NTSTATUS Status;
|
||||
file_ref* fr;
|
||||
static NTSTATUS STDCALL next_dir_entry(file_ref* fileref, UINT64* offset, dir_entry* de, dir_child** pdc, PIRP Irp) {
|
||||
LIST_ENTRY* le;
|
||||
char* name;
|
||||
dir_child* dc;
|
||||
|
||||
if (*pdc) {
|
||||
dir_child* dc2 = *pdc;
|
||||
|
||||
if (dc2->list_entry_index.Flink != &fileref->fcb->dir_children_index)
|
||||
dc = CONTAINING_RECORD(dc2->list_entry_index.Flink, dir_child, list_entry_index);
|
||||
else
|
||||
dc = NULL;
|
||||
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (fileref->parent) { // don't return . and .. if root directory
|
||||
if (*offset == 0) {
|
||||
|
@ -533,12 +485,12 @@ static NTSTATUS STDCALL next_dir_entry(file_ref* fileref, UINT64* offset, dir_en
|
|||
de->key.obj_type = TYPE_INODE_ITEM;
|
||||
de->key.offset = 0;
|
||||
de->dir_entry_type = DirEntryType_Self;
|
||||
de->name = ".";
|
||||
de->name_alloc = FALSE;
|
||||
de->namelen = 1;
|
||||
de->name.Buffer = L".";
|
||||
de->name.Length = de->name.MaximumLength = sizeof(WCHAR);
|
||||
de->type = BTRFS_TYPE_DIRECTORY;
|
||||
|
||||
*offset = 1;
|
||||
*pdc = NULL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
} else if (*offset == 1) {
|
||||
|
@ -546,12 +498,12 @@ static NTSTATUS STDCALL next_dir_entry(file_ref* fileref, UINT64* offset, dir_en
|
|||
de->key.obj_type = TYPE_INODE_ITEM;
|
||||
de->key.offset = 0;
|
||||
de->dir_entry_type = DirEntryType_Parent;
|
||||
de->name = "..";
|
||||
de->name_alloc = FALSE;
|
||||
de->namelen = 2;
|
||||
de->name.Buffer = L"..";
|
||||
de->name.Length = de->name.MaximumLength = sizeof(WCHAR) * 2;
|
||||
de->type = BTRFS_TYPE_DIRECTORY;
|
||||
|
||||
*offset = 2;
|
||||
*pdc = NULL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -560,168 +512,34 @@ static NTSTATUS STDCALL next_dir_entry(file_ref* fileref, UINT64* offset, dir_en
|
|||
if (*offset < 2)
|
||||
*offset = 2;
|
||||
|
||||
ExAcquireResourceSharedLite(&fileref->nonpaged->children_lock, TRUE);
|
||||
|
||||
fr = NULL;
|
||||
le = fileref->children.Flink;
|
||||
dc = NULL;
|
||||
le = fileref->fcb->dir_children_index.Flink;
|
||||
|
||||
// skip entries before offset
|
||||
while (le != &fileref->children) {
|
||||
file_ref* fr2 = CONTAINING_RECORD(le, file_ref, list_entry);
|
||||
while (le != &fileref->fcb->dir_children_index) {
|
||||
dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_index);
|
||||
|
||||
if (fr2->index >= *offset) {
|
||||
fr = fr2;
|
||||
if (dc2->index >= *offset) {
|
||||
dc = dc2;
|
||||
break;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
do {
|
||||
if (fr && fr->index == *offset) {
|
||||
if (!fr->deleted) {
|
||||
if (fr->fcb->subvol == fileref->fcb->subvol) {
|
||||
de->key.obj_id = fr->fcb->inode;
|
||||
de->key.obj_type = TYPE_INODE_ITEM;
|
||||
de->key.offset = 0;
|
||||
} else {
|
||||
de->key.obj_id = fr->fcb->subvol->id;
|
||||
de->key.obj_type = TYPE_ROOT_ITEM;
|
||||
de->key.offset = 0;
|
||||
}
|
||||
|
||||
name = fr->utf8.Buffer;
|
||||
de->namelen = fr->utf8.Length;
|
||||
de->type = fr->fcb->type;
|
||||
de->dir_entry_type = DirEntryType_File;
|
||||
|
||||
(*offset)++;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
goto end;
|
||||
} else {
|
||||
(*offset)++;
|
||||
fr = fr->list_entry.Flink == &fileref->children ? NULL : CONTAINING_RECORD(fr->list_entry.Flink, file_ref, list_entry);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
searchkey.obj_id = fileref->fcb->inode;
|
||||
searchkey.obj_type = TYPE_DIR_INDEX;
|
||||
searchkey.offset = *offset;
|
||||
|
||||
Status = find_item(fileref->fcb->Vcb, fileref->fcb->subvol, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (keycmp(tp.item->key, searchkey) == -1) {
|
||||
if (find_next_item(fileref->fcb->Vcb, &tp, &next_tp, FALSE, Irp))
|
||||
tp = next_tp;
|
||||
}
|
||||
|
||||
if (keycmp(tp.item->key, searchkey) != -1 && tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
|
||||
do {
|
||||
if (fr) {
|
||||
if (fr->index <= tp.item->key.offset && !fr->deleted) {
|
||||
if (fr->fcb->subvol == fileref->fcb->subvol) {
|
||||
de->key.obj_id = fr->fcb->inode;
|
||||
de->key.obj_type = TYPE_INODE_ITEM;
|
||||
de->key.offset = 0;
|
||||
} else {
|
||||
de->key.obj_id = fr->fcb->subvol->id;
|
||||
de->key.obj_type = TYPE_ROOT_ITEM;
|
||||
de->key.offset = 0;
|
||||
}
|
||||
|
||||
name = fr->utf8.Buffer;
|
||||
de->namelen = fr->utf8.Length;
|
||||
de->type = fr->fcb->type;
|
||||
de->dir_entry_type = DirEntryType_File;
|
||||
|
||||
*offset = fr->index + 1;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (fr->index == tp.item->key.offset && fr->deleted)
|
||||
break;
|
||||
|
||||
fr = fr->list_entry.Flink == &fileref->children ? NULL : CONTAINING_RECORD(fr->list_entry.Flink, file_ref, list_entry);
|
||||
}
|
||||
} while (fr && fr->index < tp.item->key.offset);
|
||||
|
||||
if (fr && fr->index == tp.item->key.offset && fr->deleted) {
|
||||
*offset = fr->index + 1;
|
||||
fr = fr->list_entry.Flink == &fileref->children ? NULL : CONTAINING_RECORD(fr->list_entry.Flink, file_ref, list_entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
*offset = tp.item->key.offset + 1;
|
||||
|
||||
di = (DIR_ITEM*)tp.item->data;
|
||||
|
||||
if (tp.item->size < sizeof(DIR_ITEM) || tp.item->size < sizeof(DIR_ITEM) - 1 + di->m + di->n) {
|
||||
ERR("(%llx,%x,%llx) was %u bytes, expected at least %u\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(DIR_ITEM));
|
||||
Status = STATUS_INTERNAL_ERROR;
|
||||
goto end;
|
||||
}
|
||||
|
||||
de->key = di->key;
|
||||
name = di->name;
|
||||
de->namelen = di->n;
|
||||
de->type = di->type;
|
||||
de->dir_entry_type = DirEntryType_File;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
goto end;
|
||||
} else {
|
||||
if (fr) {
|
||||
if (fr->fcb->subvol == fileref->fcb->subvol) {
|
||||
de->key.obj_id = fr->fcb->inode;
|
||||
de->key.obj_type = TYPE_INODE_ITEM;
|
||||
de->key.offset = 0;
|
||||
} else {
|
||||
de->key.obj_id = fr->fcb->subvol->id;
|
||||
de->key.obj_type = TYPE_ROOT_ITEM;
|
||||
de->key.offset = 0;
|
||||
}
|
||||
|
||||
name = fr->utf8.Buffer;
|
||||
de->namelen = fr->utf8.Length;
|
||||
de->type = fr->fcb->type;
|
||||
de->dir_entry_type = DirEntryType_File;
|
||||
|
||||
*offset = fr->index + 1;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
goto end;
|
||||
} else {
|
||||
Status = STATUS_NO_MORE_FILES;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
} while (TRUE);
|
||||
next:
|
||||
if (!dc)
|
||||
return STATUS_NO_MORE_FILES;
|
||||
|
||||
end:
|
||||
ExReleaseResourceLite(&fileref->nonpaged->children_lock);
|
||||
de->key = dc->key;
|
||||
de->name = dc->name;
|
||||
de->type = dc->type;
|
||||
de->dir_entry_type = DirEntryType_File;
|
||||
|
||||
if (NT_SUCCESS(Status)) {
|
||||
de->name_alloc = TRUE;
|
||||
|
||||
de->name = ExAllocatePoolWithTag(PagedPool, de->namelen, ALLOC_TAG);
|
||||
if (!de->name) {
|
||||
ERR("out of memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlCopyMemory(de->name, name, de->namelen);
|
||||
} else
|
||||
de->name_alloc = FALSE;
|
||||
*offset = dc->index + 1;
|
||||
*pdc = dc;
|
||||
|
||||
return Status;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
||||
|
@ -739,6 +557,7 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
dir_entry de;
|
||||
UINT64 newoffset;
|
||||
ANSI_STRING utf8;
|
||||
dir_child* dc = NULL;
|
||||
|
||||
TRACE("query directory\n");
|
||||
|
||||
|
@ -767,6 +586,7 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
}
|
||||
|
||||
ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, TRUE);
|
||||
ExAcquireResourceSharedLite(&fcb->Vcb->fcb_lock, TRUE);
|
||||
|
||||
TRACE("%S\n", file_desc(IrpSp->FileObject));
|
||||
|
||||
|
@ -828,7 +648,7 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
if (!ccb->query_string.Buffer) {
|
||||
ERR("out of memory\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto end;
|
||||
goto end2;
|
||||
}
|
||||
|
||||
ccb->query_string.Length = ccb->query_string.MaximumLength = IrpSp->Parameters.QueryDirectory.FileName->Length;
|
||||
|
@ -846,7 +666,7 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
|
||||
if (specific_file) {
|
||||
Status = STATUS_NO_MORE_FILES;
|
||||
goto end;
|
||||
goto end2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -856,7 +676,10 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
}
|
||||
|
||||
newoffset = ccb->query_dir_offset;
|
||||
Status = next_dir_entry(fileref, &newoffset, &de, Irp);
|
||||
|
||||
ExAcquireResourceSharedLite(&fileref->fcb->nonpaged->dir_children_lock, TRUE);
|
||||
|
||||
Status = next_dir_entry(fileref, &newoffset, &de, &dc, Irp);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
if (Status == STATUS_NO_MORE_FILES && initial)
|
||||
|
@ -878,11 +701,10 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
|
||||
if (specific_file) {
|
||||
BOOL found = FALSE;
|
||||
root* found_subvol;
|
||||
UINT64 found_inode, found_index;
|
||||
UINT8 found_type;
|
||||
UNICODE_STRING us;
|
||||
LIST_ENTRY* le;
|
||||
UINT32 hash;
|
||||
UINT8 c;
|
||||
|
||||
us.Buffer = NULL;
|
||||
|
||||
|
@ -892,163 +714,89 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
ERR("RtlUpcaseUnicodeString returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
ExAcquireResourceSharedLite(&fileref->nonpaged->children_lock, TRUE);
|
||||
|
||||
le = fileref->children.Flink;
|
||||
while (le != &fileref->children) {
|
||||
file_ref* fr2 = CONTAINING_RECORD(le, file_ref, list_entry);
|
||||
|
||||
if (!fr2->deleted) {
|
||||
if (!ccb->case_sensitive && fr2->filepart_uc.Length == us.Length &&
|
||||
RtlCompareMemory(fr2->filepart_uc.Buffer, us.Buffer, us.Length) == us.Length)
|
||||
found = TRUE;
|
||||
else if (ccb->case_sensitive && fr2->filepart.Length == ccb->query_string.Length &&
|
||||
RtlCompareMemory(fr2->filepart.Buffer, ccb->query_string.Buffer, ccb->query_string.Length) == ccb->query_string.Length)
|
||||
found = TRUE;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if (fr2->fcb->subvol == fcb->subvol) {
|
||||
de.key.obj_id = fr2->fcb->inode;
|
||||
de.key.obj_type = TYPE_INODE_ITEM;
|
||||
de.key.offset = 0;
|
||||
} else {
|
||||
de.key.obj_id = fr2->fcb->subvol->id;
|
||||
de.key.obj_type = TYPE_ROOT_ITEM;
|
||||
de.key.offset = 0;
|
||||
}
|
||||
|
||||
de.name = ExAllocatePoolWithTag(PagedPool, fr2->utf8.Length, ALLOC_TAG);
|
||||
if (!de.name) {
|
||||
ERR("out of memory\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto end;
|
||||
}
|
||||
|
||||
RtlCopyMemory(de.name, fr2->utf8.Buffer, fr2->utf8.Length);
|
||||
|
||||
de.name_alloc = TRUE;
|
||||
de.namelen = fr2->utf8.Length;
|
||||
de.type = fr2->fcb->type;
|
||||
de.dir_entry_type = DirEntryType_File;
|
||||
break;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
hash = calc_crc32c(0xffffffff, (UINT8*)us.Buffer, us.Length);
|
||||
} else
|
||||
hash = calc_crc32c(0xffffffff, (UINT8*)ccb->query_string.Buffer, ccb->query_string.Length);
|
||||
|
||||
ExReleaseResourceLite(&fileref->nonpaged->children_lock);
|
||||
c = hash >> 24;
|
||||
|
||||
if (ccb->case_sensitive) {
|
||||
if (fileref->fcb->hash_ptrs[c]) {
|
||||
le = fileref->fcb->hash_ptrs[c];
|
||||
while (le != &fileref->fcb->dir_children_hash) {
|
||||
dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_hash);
|
||||
|
||||
if (dc2->hash == hash) {
|
||||
if (dc2->name.Length == ccb->query_string.Length && RtlCompareMemory(dc2->name.Buffer, ccb->query_string.Buffer, ccb->query_string.Length) == ccb->query_string.Length) {
|
||||
found = TRUE;
|
||||
|
||||
de.key = dc2->key;
|
||||
de.name = dc2->name;
|
||||
de.type = dc2->type;
|
||||
de.dir_entry_type = DirEntryType_File;
|
||||
|
||||
break;
|
||||
}
|
||||
} else if (dc2->hash > hash)
|
||||
break;
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (fileref->fcb->hash_ptrs_uc[c]) {
|
||||
le = fileref->fcb->hash_ptrs_uc[c];
|
||||
while (le != &fileref->fcb->dir_children_hash_uc) {
|
||||
dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_hash_uc);
|
||||
|
||||
if (dc2->hash_uc == hash) {
|
||||
if (dc2->name_uc.Length == us.Length && RtlCompareMemory(dc2->name_uc.Buffer, us.Buffer, us.Length) == us.Length) {
|
||||
found = TRUE;
|
||||
|
||||
de.key = dc2->key;
|
||||
de.name = dc2->name;
|
||||
de.type = dc2->type;
|
||||
de.dir_entry_type = DirEntryType_File;
|
||||
|
||||
break;
|
||||
}
|
||||
} else if (dc2->hash_uc > hash)
|
||||
break;
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (us.Buffer)
|
||||
ExFreePool(us.Buffer);
|
||||
|
||||
if (!found) {
|
||||
Status = find_file_in_dir(fcb->Vcb, &ccb->query_string, fileref, &found_subvol, &found_inode, &found_type, &found_index, &utf8, FALSE, Irp);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
Status = STATUS_NO_SUCH_FILE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (found_subvol == fcb->subvol) {
|
||||
de.key.obj_id = found_inode;
|
||||
de.key.obj_type = TYPE_INODE_ITEM;
|
||||
de.key.offset = 0;
|
||||
} else {
|
||||
de.key.obj_id = found_subvol->id;
|
||||
de.key.obj_type = TYPE_ROOT_ITEM;
|
||||
de.key.offset = 0;
|
||||
}
|
||||
|
||||
de.name = utf8.Buffer;
|
||||
de.name_alloc = FALSE;
|
||||
de.namelen = utf8.Length;
|
||||
de.type = found_type;
|
||||
de.dir_entry_type = DirEntryType_File;
|
||||
Status = STATUS_NO_SUCH_FILE;
|
||||
goto end;
|
||||
}
|
||||
} else if (has_wildcard) {
|
||||
WCHAR* uni_fn;
|
||||
ULONG stringlen;
|
||||
UNICODE_STRING di_uni_fn;
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(NULL, 0, &stringlen, de.name, de.namelen);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
uni_fn = ExAllocatePoolWithTag(PagedPool, stringlen, ALLOC_TAG);
|
||||
if (!uni_fn) {
|
||||
ERR("out of memory\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto end;
|
||||
}
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(uni_fn, stringlen, &stringlen, de.name, de.namelen);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
di_uni_fn.Length = di_uni_fn.MaximumLength = stringlen;
|
||||
di_uni_fn.Buffer = uni_fn;
|
||||
|
||||
while (!FsRtlIsNameInExpression(&ccb->query_string, &di_uni_fn, !ccb->case_sensitive, NULL)) {
|
||||
if (de.name_alloc)
|
||||
ExFreePool(de.name);
|
||||
|
||||
while (!FsRtlIsNameInExpression(&ccb->query_string, &de.name, !ccb->case_sensitive, NULL)) {
|
||||
newoffset = ccb->query_dir_offset;
|
||||
Status = next_dir_entry(fileref, &newoffset, &de, Irp);
|
||||
Status = next_dir_entry(fileref, &newoffset, &de, &dc, Irp);
|
||||
|
||||
ExFreePool(uni_fn);
|
||||
if (NT_SUCCESS(Status)) {
|
||||
if (NT_SUCCESS(Status))
|
||||
ccb->query_dir_offset = newoffset;
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(NULL, 0, &stringlen, de.name, de.namelen);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
uni_fn = ExAllocatePoolWithTag(PagedPool, stringlen, ALLOC_TAG);
|
||||
if (!uni_fn) {
|
||||
ERR("out of memory\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto end;
|
||||
}
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(uni_fn, stringlen, &stringlen, de.name, de.namelen);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN returned %08x\n", Status);
|
||||
ExFreePool(uni_fn);
|
||||
goto end;
|
||||
}
|
||||
|
||||
di_uni_fn.Length = di_uni_fn.MaximumLength = stringlen;
|
||||
di_uni_fn.Buffer = uni_fn;
|
||||
} else {
|
||||
else {
|
||||
if (Status == STATUS_NO_MORE_FILES && initial)
|
||||
Status = STATUS_NO_SUCH_FILE;
|
||||
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
ExFreePool(uni_fn);
|
||||
}
|
||||
|
||||
TRACE("file(0) = %.*s\n", de.namelen, de.name);
|
||||
TRACE("file(0) = %.*S\n", de.name.Length / sizeof(WCHAR), de.name.Buffer);
|
||||
TRACE("offset = %u\n", ccb->query_dir_offset - 1);
|
||||
|
||||
Status = query_dir_item(fcb, fileref, buf, &length, Irp, &de, fcb->subvol);
|
||||
|
||||
if (de.name_alloc)
|
||||
ExFreePool(de.name);
|
||||
|
||||
|
||||
count = 0;
|
||||
if (NT_SUCCESS(Status) && !(IrpSp->Flags & SL_RETURN_SINGLE_ENTRY) && !specific_file) {
|
||||
lastitem = (UINT8*)buf;
|
||||
|
@ -1073,48 +821,14 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
}
|
||||
|
||||
if (length > 0) {
|
||||
WCHAR* uni_fn = NULL;
|
||||
UNICODE_STRING di_uni_fn;
|
||||
|
||||
newoffset = ccb->query_dir_offset;
|
||||
Status = next_dir_entry(fileref, &newoffset, &de, Irp);
|
||||
Status = next_dir_entry(fileref, &newoffset, &de, &dc, Irp);
|
||||
if (NT_SUCCESS(Status)) {
|
||||
if (has_wildcard) {
|
||||
ULONG stringlen;
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(NULL, 0, &stringlen, de.name, de.namelen);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN returned %08x\n", Status);
|
||||
if (de.name_alloc) ExFreePool(de.name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
uni_fn = ExAllocatePoolWithTag(PagedPool, stringlen, ALLOC_TAG);
|
||||
if (!uni_fn) {
|
||||
ERR("out of memory\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
if (de.name_alloc) ExFreePool(de.name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(uni_fn, stringlen, &stringlen, de.name, de.namelen);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("RtlUTF8ToUnicodeN returned %08x\n", Status);
|
||||
ExFreePool(uni_fn);
|
||||
if (de.name_alloc) ExFreePool(de.name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
di_uni_fn.Length = di_uni_fn.MaximumLength = stringlen;
|
||||
di_uni_fn.Buffer = uni_fn;
|
||||
}
|
||||
|
||||
if (!has_wildcard || FsRtlIsNameInExpression(&ccb->query_string, &di_uni_fn, !ccb->case_sensitive, NULL)) {
|
||||
if (!has_wildcard || FsRtlIsNameInExpression(&ccb->query_string, &de.name, !ccb->case_sensitive, NULL)) {
|
||||
curitem = (UINT8*)buf + IrpSp->Parameters.QueryDirectory.Length - length;
|
||||
count++;
|
||||
|
||||
TRACE("file(%u) %u = %.*s\n", count, curitem - (UINT8*)buf, de.namelen, de.name);
|
||||
TRACE("file(%u) %u = %.*S\n", count, curitem - (UINT8*)buf, de.name.Length / sizeof(WCHAR), de.name.Buffer);
|
||||
TRACE("offset = %u\n", ccb->query_dir_offset - 1);
|
||||
|
||||
status2 = query_dir_item(fcb, fileref, curitem, &length, Irp, &de, fcb->subvol);
|
||||
|
@ -1126,21 +840,10 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
ccb->query_dir_offset = newoffset;
|
||||
|
||||
lastitem = curitem;
|
||||
} else {
|
||||
if (uni_fn) ExFreePool(uni_fn);
|
||||
if (de.name_alloc) ExFreePool(de.name);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
} else
|
||||
ccb->query_dir_offset = newoffset;
|
||||
|
||||
if (uni_fn) {
|
||||
ExFreePool(uni_fn);
|
||||
uni_fn = NULL;
|
||||
}
|
||||
|
||||
if (de.name_alloc)
|
||||
ExFreePool(de.name);
|
||||
} else {
|
||||
if (Status == STATUS_NO_MORE_FILES)
|
||||
Status = STATUS_SUCCESS;
|
||||
|
@ -1155,6 +858,10 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
Irp->IoStatus.Information = IrpSp->Parameters.QueryDirectory.Length - length;
|
||||
|
||||
end:
|
||||
ExReleaseResourceLite(&fileref->fcb->nonpaged->dir_children_lock);
|
||||
|
||||
end2:
|
||||
ExReleaseResourceLite(&fcb->Vcb->fcb_lock);
|
||||
ExReleaseResourceLite(&fcb->Vcb->tree_lock);
|
||||
|
||||
TRACE("returning %08x\n", Status);
|
||||
|
|
|
@ -84,7 +84,7 @@ static __inline UINT64 get_extent_data_refcount(UINT8 type, void* data) {
|
|||
}
|
||||
}
|
||||
|
||||
static UINT64 get_extent_data_ref_hash2(UINT64 root, UINT64 objid, UINT64 offset) {
|
||||
UINT64 get_extent_data_ref_hash2(UINT64 root, UINT64 objid, UINT64 offset) {
|
||||
UINT32 high_crc = 0xffffffff, low_crc = 0xffffffff;
|
||||
|
||||
high_crc = calc_crc32c(high_crc, (UINT8*)&root, sizeof(UINT64));
|
||||
|
@ -474,7 +474,7 @@ NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
UINT8* ptr;
|
||||
|
||||
eisize = sizeof(EXTENT_ITEM);
|
||||
if (is_tree) eisize += sizeof(EXTENT_ITEM2);
|
||||
if (is_tree && !(Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA)) eisize += sizeof(EXTENT_ITEM2);
|
||||
eisize += sizeof(UINT8);
|
||||
eisize += datalen;
|
||||
|
||||
|
@ -590,7 +590,6 @@ NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
|
||||
RtlCopyMemory(newei, tp.item->data, tp.item->size);
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
newei->refcount += rc;
|
||||
|
||||
sectedr2 = (EXTENT_DATA_REF*)((UINT8*)newei + ((UINT8*)sectedr - tp.item->data));
|
||||
|
@ -635,7 +634,6 @@ NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
|
||||
RtlCopyMemory(newei, tp.item->data, tp.item->size);
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
newei->refcount += rc;
|
||||
|
||||
sectsdr2 = (SHARED_DATA_REF*)((UINT8*)newei + ((UINT8*)sectsdr - tp.item->data));
|
||||
|
@ -697,7 +695,6 @@ NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
newei = ExAllocatePoolWithTag(PagedPool, tp.item->size + sizeof(UINT8) + datalen, ALLOC_TAG);
|
||||
RtlCopyMemory(newei, tp.item->data, ptr - tp.item->data);
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
newei->refcount += get_extent_data_refcount(type, data);
|
||||
|
||||
if (len > 0)
|
||||
|
@ -733,9 +730,9 @@ NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
return Status;
|
||||
}
|
||||
|
||||
if (!keycmp(tp.item->key, searchkey)) {
|
||||
if (tp.item->size < datalen) {
|
||||
ERR("(%llx,%x,%llx) was %x bytes, expecting %x\n", tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset, tp.item->size, datalen);
|
||||
if (!keycmp(tp2.item->key, searchkey)) {
|
||||
if (tp2.item->size < datalen) {
|
||||
ERR("(%llx,%x,%llx) was %x bytes, expecting %x\n", tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset, tp2.item->size, datalen);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
|
@ -770,7 +767,6 @@ NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
newei = ExAllocatePoolWithTag(PagedPool, tp.item->size, ALLOC_TAG);
|
||||
RtlCopyMemory(newei, tp.item->data, tp.item->size);
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
newei->refcount += get_extent_data_refcount(type, data);
|
||||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
@ -797,7 +793,6 @@ NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
newei = ExAllocatePoolWithTag(PagedPool, tp.item->size, ALLOC_TAG);
|
||||
RtlCopyMemory(newei, tp.item->data, tp.item->size);
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
newei->refcount += get_extent_data_refcount(type, data);
|
||||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
@ -828,7 +823,7 @@ void decrease_chunk_usage(chunk* c, UINT64 delta) {
|
|||
}
|
||||
|
||||
NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT8 type, void* data, KEY* firstitem,
|
||||
UINT8 level, UINT64 parent, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
UINT8 level, UINT64 parent, BOOL superseded, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
KEY searchkey;
|
||||
NTSTATUS Status;
|
||||
traverse_ptr tp, tp2;
|
||||
|
@ -884,7 +879,7 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
return Status;
|
||||
}
|
||||
|
||||
return decrease_extent_refcount(Vcb, address, size, type, data, firstitem, level, parent, Irp, rollback);
|
||||
return decrease_extent_refcount(Vcb, address, size, type, data, firstitem, level, parent, superseded, Irp, rollback);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -944,6 +939,10 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
if (sectedr->root == edr->root && sectedr->objid == edr->objid && sectedr->offset == edr->offset) {
|
||||
if (ei->refcount == edr->count) {
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
if (!superseded)
|
||||
add_checksum_entry(Vcb, address, size / Vcb->superblock.sector_size, NULL, Irp, rollback);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -976,7 +975,6 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
RtlCopyMemory((UINT8*)newei + (ptr - tp.item->data), ptr + sectlen + sizeof(UINT8), len - sectlen);
|
||||
}
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
newei->refcount -= rc;
|
||||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
@ -995,14 +993,24 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
EXTENT_ITEM* newei;
|
||||
|
||||
if (sectsdr->offset == sdr->offset) {
|
||||
// We ignore sdr->count, and assume that we want to remove the whole bit
|
||||
|
||||
if (ei->refcount == sectsdr->count) {
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
if (!superseded)
|
||||
add_checksum_entry(Vcb, address, size / Vcb->superblock.sector_size, NULL, Irp, rollback);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
neweilen = tp.item->size - sizeof(UINT8) - sectlen;
|
||||
if (sectsdr->count < sdr->count) {
|
||||
ERR("error - SHARED_DATA_REF has refcount %x, trying to reduce by %x\n", sectsdr->count, sdr->count);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (sectsdr->count > sdr->count) // reduce section refcount
|
||||
neweilen = tp.item->size;
|
||||
else // remove section entirely
|
||||
neweilen = tp.item->size - sizeof(UINT8) - sectlen;
|
||||
|
||||
newei = ExAllocatePoolWithTag(PagedPool, neweilen, ALLOC_TAG);
|
||||
if (!newei) {
|
||||
|
@ -1010,12 +1018,19 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlCopyMemory(newei, ei, ptr - tp.item->data);
|
||||
|
||||
if (len > sectlen)
|
||||
RtlCopyMemory((UINT8*)newei + (ptr - tp.item->data), ptr + sectlen + sizeof(UINT8), len - sectlen);
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
if (sectsdr->count > sdr->count) {
|
||||
SHARED_DATA_REF* newsdr = (SHARED_DATA_REF*)((UINT8*)newei + ((UINT8*)sectsdr - tp.item->data));
|
||||
|
||||
RtlCopyMemory(newei, ei, neweilen);
|
||||
|
||||
newsdr->count -= rc;
|
||||
} else {
|
||||
RtlCopyMemory(newei, ei, ptr - tp.item->data);
|
||||
|
||||
if (len > sectlen)
|
||||
RtlCopyMemory((UINT8*)newei + (ptr - tp.item->data), ptr + sectlen + sizeof(UINT8), len - sectlen);
|
||||
}
|
||||
|
||||
newei->refcount -= rc;
|
||||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
@ -1052,7 +1067,6 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
if (len > sectlen)
|
||||
RtlCopyMemory((UINT8*)newei + (ptr - tp.item->data), ptr + sectlen + sizeof(UINT8), len - sectlen);
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
newei->refcount--;
|
||||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
@ -1089,7 +1103,6 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
if (len > sectlen)
|
||||
RtlCopyMemory((UINT8*)newei + (ptr - tp.item->data), ptr + sectlen + sizeof(UINT8), len - sectlen);
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
newei->refcount--;
|
||||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
@ -1146,6 +1159,10 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
if (ei->refcount == edr->count) {
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
delete_tree_item(Vcb, &tp2, rollback);
|
||||
|
||||
if (!superseded)
|
||||
add_checksum_entry(Vcb, address, size / Vcb->superblock.sector_size, NULL, Irp, rollback);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1182,7 +1199,6 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
|
||||
RtlCopyMemory(newei, tp.item->data, tp.item->size);
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
newei->refcount -= rc;
|
||||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
@ -1203,16 +1219,41 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
EXTENT_ITEM* newei;
|
||||
|
||||
if (sectsdr->offset == sdr->offset) {
|
||||
// As above, we assume that we want to remove the whole shared data ref
|
||||
|
||||
if (ei->refcount == sectsdr->count) {
|
||||
if (ei->refcount == sdr->count) {
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
delete_tree_item(Vcb, &tp2, rollback);
|
||||
|
||||
if (!superseded)
|
||||
add_checksum_entry(Vcb, address, size / Vcb->superblock.sector_size, NULL, Irp, rollback);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (sectsdr->count < sdr->count) {
|
||||
ERR("error - extent section has refcount %x, trying to reduce by %x\n", sectsdr->count, sdr->count);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
delete_tree_item(Vcb, &tp2, rollback);
|
||||
|
||||
if (sectsdr->count > sdr->count) {
|
||||
SHARED_DATA_REF* newsdr = ExAllocatePoolWithTag(PagedPool, tp2.item->size, ALLOC_TAG);
|
||||
|
||||
if (!newsdr) {
|
||||
ERR("out of memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlCopyMemory(newsdr, sectsdr, tp2.item->size);
|
||||
|
||||
newsdr->count -= sdr->count;
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset, newsdr, tp2.item->size, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
newei = ExAllocatePoolWithTag(PagedPool, tp.item->size, ALLOC_TAG);
|
||||
if (!newei) {
|
||||
ERR("out of memory\n");
|
||||
|
@ -1221,7 +1262,6 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
|
||||
RtlCopyMemory(newei, tp.item->data, tp.item->size);
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
newei->refcount -= rc;
|
||||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
@ -1258,7 +1298,6 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
|
||||
RtlCopyMemory(newei, tp.item->data, tp.item->size);
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
newei->refcount -= rc;
|
||||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
@ -1295,7 +1334,6 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
|
||||
RtlCopyMemory(newei, tp.item->data, tp.item->size);
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
newei->refcount -= rc;
|
||||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
@ -1317,6 +1355,10 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
if (ei->refcount == erv0->count) {
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
delete_tree_item(Vcb, &tp2, rollback);
|
||||
|
||||
if (!superseded)
|
||||
add_checksum_entry(Vcb, address, size / Vcb->superblock.sector_size, NULL, Irp, rollback);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1330,7 +1372,6 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
|
||||
RtlCopyMemory(newei, tp.item->data, tp.item->size);
|
||||
|
||||
newei->generation = Vcb->superblock.generation;
|
||||
newei->refcount -= rc;
|
||||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
@ -1348,7 +1389,7 @@ NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64
|
|||
}
|
||||
|
||||
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) {
|
||||
UINT64 offset, UINT32 refcount, BOOL superseded, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
EXTENT_DATA_REF edr;
|
||||
|
||||
edr.root = root;
|
||||
|
@ -1356,7 +1397,7 @@ NTSTATUS decrease_extent_refcount_data(device_extension* Vcb, UINT64 address, UI
|
|||
edr.offset = offset;
|
||||
edr.count = refcount;
|
||||
|
||||
return decrease_extent_refcount(Vcb, address, size, TYPE_EXTENT_DATA_REF, &edr, NULL, 0, 0, Irp, rollback);
|
||||
return decrease_extent_refcount(Vcb, address, size, TYPE_EXTENT_DATA_REF, &edr, NULL, 0, 0, superseded, Irp, rollback);
|
||||
}
|
||||
|
||||
NTSTATUS decrease_extent_refcount_tree(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root,
|
||||
|
@ -1365,7 +1406,7 @@ NTSTATUS decrease_extent_refcount_tree(device_extension* Vcb, UINT64 address, UI
|
|||
|
||||
tbr.offset = root;
|
||||
|
||||
return decrease_extent_refcount(Vcb, address, size, TYPE_TREE_BLOCK_REF, &tbr, NULL/*FIXME*/, level, 0, Irp, rollback);
|
||||
return decrease_extent_refcount(Vcb, address, size, TYPE_TREE_BLOCK_REF, &tbr, NULL/*FIXME*/, level, 0, FALSE, Irp, rollback);
|
||||
}
|
||||
|
||||
static UINT64 find_extent_data_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset, PIRP Irp) {
|
||||
|
|
|
@ -265,26 +265,35 @@ static NTSTATUS STDCALL fast_io_release_for_ccflush(PFILE_OBJECT FileObject, PDE
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static BOOLEAN STDCALL fast_io_write(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
|
||||
TRACE("(%p (%.*S), %llx, %x, %x, %x, %p, %p, %p)\n", FileObject, FileObject->FileName.Length / sizeof(WCHAR), FileObject->FileName.Buffer,
|
||||
*FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
|
||||
|
||||
if (FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject)) {
|
||||
fcb* fcb = FileObject->FsContext;
|
||||
|
||||
fcb->inode_item.st_size = fcb->Header.FileSize.QuadPart;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
static BOOLEAN STDCALL fast_io_read(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
|
||||
TRACE("(%p, %p, %x, %x, %x, %p, %p, %p)\n", FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
|
||||
|
||||
return FsRtlCopyRead(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
|
||||
}
|
||||
|
||||
static BOOLEAN STDCALL fast_io_write(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
|
||||
TRACE("(%p, %p, %x, %x, %x, %p, %p, %p)\n", FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
|
||||
|
||||
return FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
|
||||
}
|
||||
|
||||
static BOOLEAN STDCALL fast_io_mdl_read(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, ULONG LockKey, PMDL* MdlChain, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
|
||||
TRACE("(%p, %p, %x, %x, %p, %p, %p)\n", FileObject, FileOffset, Length, LockKey, MdlChain, IoStatus, DeviceObject);
|
||||
|
||||
return FsRtlMdlReadDev(FileObject, FileOffset, Length, LockKey, MdlChain, IoStatus, DeviceObject);
|
||||
}
|
||||
|
||||
static BOOLEAN STDCALL fast_io_mdl_read_complete(PFILE_OBJECT FileObject, PMDL* MdlChain, PDEVICE_OBJECT DeviceObject) {
|
||||
static BOOLEAN STDCALL fast_io_mdl_read_complete(PFILE_OBJECT FileObject, PMDL MdlChain, PDEVICE_OBJECT DeviceObject) {
|
||||
TRACE("(%p, %p, %p)\n", FileObject, MdlChain, DeviceObject);
|
||||
|
||||
return FsRtlMdlReadCompleteDev(FileObject, MdlChain, DeviceObject);
|
||||
|
@ -296,7 +305,7 @@ static BOOLEAN STDCALL fast_io_prepare_mdl_write(PFILE_OBJECT FileObject, PLARGE
|
|||
return FsRtlPrepareMdlWriteDev(FileObject, FileOffset, Length, LockKey, MdlChain, IoStatus, DeviceObject);
|
||||
}
|
||||
|
||||
static BOOLEAN STDCALL fast_io_mdl_write_complete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PMDL* MdlChain, PDEVICE_OBJECT DeviceObject) {
|
||||
static BOOLEAN STDCALL fast_io_mdl_write_complete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PMDL MdlChain, PDEVICE_OBJECT DeviceObject) {
|
||||
TRACE("(%p, %p, %p, %p)\n", FileObject, FileOffset, MdlChain, DeviceObject);
|
||||
|
||||
return FsRtlMdlWriteCompleteDev(FileObject, FileOffset, MdlChain, DeviceObject);
|
||||
|
@ -329,17 +338,16 @@ void __stdcall init_fast_io_dispatch(FAST_IO_DISPATCH** fiod) {
|
|||
FastIoDispatch.ReleaseForModWrite = fast_io_release_for_mod_write;
|
||||
FastIoDispatch.AcquireForCcFlush = fast_io_acquire_for_ccflush;
|
||||
FastIoDispatch.ReleaseForCcFlush = fast_io_release_for_ccflush;
|
||||
|
||||
#ifdef DEBUG
|
||||
FastIoDispatch.FastIoRead = fast_io_read;
|
||||
FastIoDispatch.FastIoWrite = fast_io_write;
|
||||
|
||||
#ifdef _DEBUG
|
||||
FastIoDispatch.FastIoRead = fast_io_read;
|
||||
FastIoDispatch.MdlRead = fast_io_mdl_read;
|
||||
FastIoDispatch.MdlReadComplete = fast_io_mdl_read_complete;
|
||||
FastIoDispatch.PrepareMdlWrite = fast_io_prepare_mdl_write;
|
||||
FastIoDispatch.MdlWriteComplete = fast_io_mdl_write_complete;
|
||||
#else
|
||||
FastIoDispatch.FastIoRead = FsRtlCopyRead;
|
||||
FastIoDispatch.FastIoWrite = FsRtlCopyWrite;
|
||||
FastIoDispatch.MdlRead = FsRtlMdlReadDev;
|
||||
FastIoDispatch.MdlReadComplete = FsRtlMdlReadCompleteDev;
|
||||
FastIoDispatch.PrepareMdlWrite = FsRtlPrepareMdlWriteDev;
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -88,10 +88,8 @@ NTSTATUS clear_free_space_cache(device_extension* Vcb, LIST_ENTRY* batchlist, PI
|
|||
|
||||
Status = remove_free_space_inode(Vcb, fsi->key.obj_id, batchlist, Irp, &rollback);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
if (!NT_SUCCESS(Status))
|
||||
ERR("remove_free_space_inode for (%llx,%x,%llx) returned %08x\n", fsi->key.obj_id, fsi->key.obj_type, fsi->key.offset, Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
le = Vcb->chunks.Flink;
|
||||
while (le != &Vcb->chunks) {
|
||||
|
@ -116,7 +114,6 @@ NTSTATUS clear_free_space_cache(device_extension* Vcb, LIST_ENTRY* batchlist, PI
|
|||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
end:
|
||||
if (NT_SUCCESS(Status))
|
||||
clear_rollback(Vcb, &rollback);
|
||||
else
|
||||
|
@ -251,30 +248,44 @@ typedef struct {
|
|||
LIST_ENTRY list_entry;
|
||||
} superblock_stripe;
|
||||
|
||||
static void add_superblock_stripe(LIST_ENTRY* stripes, UINT64 off, UINT64 len) {
|
||||
static NTSTATUS add_superblock_stripe(LIST_ENTRY* stripes, UINT64 off, UINT64 len) {
|
||||
UINT64 i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
LIST_ENTRY* le;
|
||||
superblock_stripe* ss;
|
||||
BOOL ignore = FALSE;
|
||||
|
||||
le = stripes->Flink;
|
||||
while (le != stripes) {
|
||||
ss = CONTAINING_RECORD(le, superblock_stripe, list_entry);
|
||||
|
||||
if (ss->stripe == off + i)
|
||||
continue;
|
||||
if (ss->stripe == off + i) {
|
||||
ignore = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
if (ignore)
|
||||
continue;
|
||||
|
||||
ss = ExAllocatePoolWithTag(PagedPool, sizeof(superblock_stripe), ALLOC_TAG);
|
||||
if (!ss) {
|
||||
ERR("out of memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
ss->stripe = off + i;
|
||||
InsertTailList(stripes, &ss->list_entry);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT64 get_superblock_size(chunk* c) {
|
||||
static NTSTATUS get_superblock_size(chunk* c, UINT64* size) {
|
||||
NTSTATUS Status;
|
||||
CHUNK_ITEM* ci = c->chunk_item;
|
||||
CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&ci[1];
|
||||
UINT64 off_start, off_end, space;
|
||||
|
@ -296,7 +307,11 @@ static UINT64 get_superblock_size(chunk* c) {
|
|||
|
||||
off_end = off_start + ci->stripe_length;
|
||||
|
||||
add_superblock_stripe(&stripes, off_start / ci->stripe_length, 1);
|
||||
Status = add_superblock_stripe(&stripes, off_start / ci->stripe_length, 1);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("add_superblock_stripe returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ci->type & BLOCK_FLAG_RAID5) {
|
||||
|
@ -310,7 +325,11 @@ static UINT64 get_superblock_size(chunk* c) {
|
|||
|
||||
off_end = off_start + (ci->stripe_length * (ci->num_stripes - 1));
|
||||
|
||||
add_superblock_stripe(&stripes, off_start / ci->stripe_length, (off_end - off_start) / ci->stripe_length);
|
||||
Status = add_superblock_stripe(&stripes, off_start / ci->stripe_length, (off_end - off_start) / ci->stripe_length);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("add_superblock_stripe returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ci->type & BLOCK_FLAG_RAID6) {
|
||||
|
@ -324,7 +343,11 @@ static UINT64 get_superblock_size(chunk* c) {
|
|||
|
||||
off_end = off_start + (ci->stripe_length * (ci->num_stripes - 2));
|
||||
|
||||
add_superblock_stripe(&stripes, off_start / ci->stripe_length, (off_end - off_start) / ci->stripe_length);
|
||||
Status = add_superblock_stripe(&stripes, off_start / ci->stripe_length, (off_end - off_start) / ci->stripe_length);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("add_superblock_stripe returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // SINGLE, DUPLICATE, RAID1
|
||||
|
@ -333,7 +356,11 @@ static UINT64 get_superblock_size(chunk* c) {
|
|||
off_start = ((superblock_addrs[i] - cis[j].offset) / c->chunk_item->stripe_length) * c->chunk_item->stripe_length;
|
||||
off_end = sector_align(superblock_addrs[i] - cis[j].offset + sizeof(superblock), c->chunk_item->stripe_length);
|
||||
|
||||
add_superblock_stripe(&stripes, off_start / ci->stripe_length, (off_end - off_start) / ci->stripe_length);
|
||||
Status = add_superblock_stripe(&stripes, off_start / ci->stripe_length, (off_end - off_start) / ci->stripe_length);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("add_superblock_stripe returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -343,6 +370,9 @@ static UINT64 get_superblock_size(chunk* c) {
|
|||
|
||||
space = 0;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
end:
|
||||
while (!IsListEmpty(&stripes)) {
|
||||
LIST_ENTRY* le = RemoveHeadList(&stripes);
|
||||
superblock_stripe* ss = CONTAINING_RECORD(le, superblock_stripe, list_entry);
|
||||
|
@ -352,7 +382,10 @@ static UINT64 get_superblock_size(chunk* c) {
|
|||
ExFreePool(ss);
|
||||
}
|
||||
|
||||
return space * ci->stripe_length;
|
||||
if (NT_SUCCESS(Status))
|
||||
*size = space * ci->stripe_length;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, PIRP Irp) {
|
||||
|
@ -368,7 +401,6 @@ static NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, PI
|
|||
LIST_ENTRY *le, rollback;
|
||||
|
||||
// FIXME - does this break if Vcb->superblock.sector_size is not 4096?
|
||||
// FIXME - remove INODE_ITEM etc. if cache invalid for whatever reason
|
||||
|
||||
TRACE("(%p, %llx)\n", Vcb, c->offset);
|
||||
|
||||
|
@ -432,7 +464,7 @@ static NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, PI
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Status = read_file(c->cache, data, 0, c->cache->inode_item.st_size, NULL, NULL);
|
||||
Status = read_file(c->cache, data, 0, c->cache->inode_item.st_size, NULL, NULL, FALSE);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("read_file returned %08x\n", Status);
|
||||
ExFreePool(data);
|
||||
|
@ -529,7 +561,13 @@ static NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, PI
|
|||
|
||||
// do sanity check
|
||||
|
||||
superblock_size = get_superblock_size(c);
|
||||
Status = get_superblock_size(c, &superblock_size);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("get_superblock_size returned %08x\n", Status);
|
||||
ExFreePool(data);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (c->chunk_item->size - c->used != total_space + superblock_size) {
|
||||
WARN("invalidating cache for chunk %llx: space was %llx, expected %llx\n", c->offset, total_space + superblock_size, c->chunk_item->size - c->used);
|
||||
goto clearcache;
|
||||
|
@ -569,6 +607,8 @@ clearcache:
|
|||
|
||||
InitializeListHead(&rollback);
|
||||
|
||||
delete_tree_item(Vcb, &tp, &rollback);
|
||||
|
||||
Status = excise_extents(Vcb, c->cache, 0, c->cache->inode_item.st_size, Irp, &rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("excise_extents returned %08x\n", Status);
|
||||
|
@ -696,11 +736,11 @@ static NTSTATUS insert_cache_extent(fcb* fcb, UINT64 start, UINT64 length, LIST_
|
|||
while (le != &fcb->Vcb->chunks) {
|
||||
c = CONTAINING_RECORD(le, chunk, list_entry);
|
||||
|
||||
if (!c->readonly) {
|
||||
if (!c->readonly && !c->reloc) {
|
||||
ExAcquireResourceExclusiveLite(&c->lock, TRUE);
|
||||
|
||||
if (c->chunk_item->type == flags && (c->chunk_item->size - c->used) >= length) {
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start, length, FALSE, NULL, NULL, NULL, rollback, BTRFS_COMPRESSION_NONE, length)) {
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start, length, FALSE, NULL, NULL, rollback, BTRFS_COMPRESSION_NONE, length)) {
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -722,7 +762,7 @@ static NTSTATUS insert_cache_extent(fcb* fcb, UINT64 start, UINT64 length, LIST_
|
|||
ExAcquireResourceExclusiveLite(&c->lock, TRUE);
|
||||
|
||||
if (c->chunk_item->type == flags && (c->chunk_item->size - c->used) >= length) {
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start, length, FALSE, NULL, NULL, NULL, rollback, BTRFS_COMPRESSION_NONE, length))
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start, length, FALSE, NULL, NULL, rollback, BTRFS_COMPRESSION_NONE, length))
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -740,6 +780,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
NTSTATUS Status;
|
||||
UINT64 num_entries, new_cache_size, i;
|
||||
UINT32 num_sectors;
|
||||
BOOL realloc_extents = FALSE;
|
||||
|
||||
// FIXME - also do bitmaps
|
||||
// FIXME - make sure this works when sector_size is not 4096
|
||||
|
@ -788,6 +829,33 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
|
||||
TRACE("chunk %llx: cache_size = %llx, new_cache_size = %llx\n", c->offset, c->cache ? c->cache->inode_item.st_size : 0, new_cache_size);
|
||||
|
||||
if (c->cache) {
|
||||
if (new_cache_size > c->cache->inode_item.st_size)
|
||||
realloc_extents = TRUE;
|
||||
else {
|
||||
le = c->cache->extents.Flink;
|
||||
|
||||
while (le != &c->cache->extents) {
|
||||
extent* ext = CONTAINING_RECORD(le, extent, list_entry);
|
||||
|
||||
if (!ext->ignore && (ext->data->type == EXTENT_TYPE_REGULAR || ext->data->type == EXTENT_TYPE_PREALLOC)) {
|
||||
EXTENT_DATA2* ed2 = (EXTENT_DATA2*)&ext->data->data[0];
|
||||
|
||||
if (ed2->size != 0) {
|
||||
chunk* c2 = get_chunk_from_address(Vcb, ed2->address);
|
||||
|
||||
if (c2 && (c2->readonly || c2->reloc)) {
|
||||
realloc_extents = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!c->cache) {
|
||||
FREE_SPACE_ITEM* fsi;
|
||||
KEY searchkey;
|
||||
|
@ -869,19 +937,17 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
}
|
||||
|
||||
c->cache->extents_changed = TRUE;
|
||||
InsertTailList(&Vcb->all_fcbs, &c->cache->list_entry_all);
|
||||
|
||||
flush_fcb(c->cache, TRUE, batchlist, Irp, rollback);
|
||||
|
||||
*changed = TRUE;
|
||||
} else if (new_cache_size > c->cache->inode_item.st_size) {
|
||||
} else if (realloc_extents) {
|
||||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
|
||||
ERR("extending existing inode\n");
|
||||
TRACE("reallocating extents\n");
|
||||
|
||||
// FIXME - try to extend existing extent first of all
|
||||
// Or ditch all existing extents and replace with one new one?
|
||||
|
||||
// add free_space entry to tree cache
|
||||
|
||||
searchkey.obj_id = FREE_SPACE_CACHE_ID;
|
||||
|
@ -906,9 +972,38 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
|
||||
tp.tree->write = TRUE;
|
||||
|
||||
// remove existing extents
|
||||
|
||||
if (c->cache->inode_item.st_size > 0) {
|
||||
le = c->cache->extents.Flink;
|
||||
|
||||
while (le != &c->cache->extents) {
|
||||
extent* ext = CONTAINING_RECORD(le, extent, list_entry);
|
||||
|
||||
if (!ext->ignore && (ext->data->type == EXTENT_TYPE_REGULAR || ext->data->type == EXTENT_TYPE_PREALLOC)) {
|
||||
EXTENT_DATA2* ed2 = (EXTENT_DATA2*)&ext->data->data[0];
|
||||
|
||||
if (ed2->size != 0) {
|
||||
chunk* c2 = get_chunk_from_address(Vcb, ed2->address);
|
||||
|
||||
if (!c2->list_entry_changed.Flink)
|
||||
InsertTailList(&Vcb->chunks_changed, &c2->list_entry_changed);
|
||||
}
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
Status = excise_extents(Vcb, c->cache, 0, c->cache->inode_item.st_size, Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("excise_extents returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
// add new extent
|
||||
|
||||
Status = insert_cache_extent(c->cache, c->cache->inode_item.st_size, new_cache_size - c->cache->inode_item.st_size, rollback);
|
||||
Status = insert_cache_extent(c->cache, 0, new_cache_size, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("insert_cache_extent returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -1372,7 +1467,7 @@ static NTSTATUS update_chunk_cache(device_extension* Vcb, chunk* c, BTRFS_TIME*
|
|||
|
||||
// write cache
|
||||
|
||||
Status = do_write_file(c->cache, 0, c->cache->inode_item.st_size, data, NULL, NULL, rollback);
|
||||
Status = do_write_file(c->cache, 0, c->cache->inode_item.st_size, data, NULL, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("do_write_file returned %08x\n", Status);
|
||||
return Status;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -24,6 +24,7 @@ typedef struct {
|
|||
PIRP Irp;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
NTSTATUS Status;
|
||||
device* dev;
|
||||
} pnp_stripe;
|
||||
|
||||
typedef struct {
|
||||
|
@ -51,6 +52,7 @@ static NTSTATUS send_disks_pnp_message(device_extension* Vcb, UCHAR minor) {
|
|||
pnp_context* context;
|
||||
UINT64 num_devices, i;
|
||||
NTSTATUS Status;
|
||||
LIST_ENTRY* le;
|
||||
|
||||
context = ExAllocatePoolWithTag(NonPagedPool, sizeof(pnp_context), ALLOC_TAG);
|
||||
if (!context) {
|
||||
|
@ -58,6 +60,8 @@ static NTSTATUS send_disks_pnp_message(device_extension* Vcb, UCHAR minor) {
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
ExAcquireResourceSharedLite(&Vcb->tree_lock, TRUE);
|
||||
|
||||
RtlZeroMemory(context, sizeof(pnp_context));
|
||||
KeInitializeEvent(&context->Event, NotificationEvent, FALSE);
|
||||
|
||||
|
@ -67,18 +71,23 @@ static NTSTATUS send_disks_pnp_message(device_extension* Vcb, UCHAR minor) {
|
|||
if (!context->stripes) {
|
||||
ERR("out of memory\n");
|
||||
ExFreePool(context);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto end2;
|
||||
}
|
||||
|
||||
RtlZeroMemory(context->stripes, sizeof(pnp_stripe) * num_devices);
|
||||
|
||||
for (i = 0; i < num_devices; i++) {
|
||||
i = 0;
|
||||
le = Vcb->devices.Flink;
|
||||
|
||||
while (le != &Vcb->devices) {
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
device* dev = CONTAINING_RECORD(le, device, list_entry);
|
||||
|
||||
if (Vcb->devices[i].devobj) {
|
||||
if (dev->devobj) {
|
||||
context->stripes[i].context = (struct pnp_context*)context;
|
||||
|
||||
context->stripes[i].Irp = IoAllocateIrp(Vcb->devices[i].devobj->StackSize, FALSE);
|
||||
context->stripes[i].Irp = IoAllocateIrp(dev->devobj->StackSize, FALSE);
|
||||
|
||||
if (!context->stripes[i].Irp) {
|
||||
UINT64 j;
|
||||
|
@ -86,14 +95,15 @@ static NTSTATUS send_disks_pnp_message(device_extension* Vcb, UCHAR minor) {
|
|||
ERR("IoAllocateIrp failed\n");
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
if (Vcb->devices[j].devobj) {
|
||||
if (context->stripes[j].dev->devobj) {
|
||||
IoFreeIrp(context->stripes[j].Irp);
|
||||
}
|
||||
}
|
||||
ExFreePool(context->stripes);
|
||||
ExFreePool(context);
|
||||
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto end2;
|
||||
}
|
||||
|
||||
IrpSp = IoGetNextIrpStackLocation(context->stripes[i].Irp);
|
||||
|
@ -105,9 +115,12 @@ static NTSTATUS send_disks_pnp_message(device_extension* Vcb, UCHAR minor) {
|
|||
IoSetCompletionRoutine(context->stripes[i].Irp, pnp_completion, &context->stripes[i], TRUE, TRUE, TRUE);
|
||||
|
||||
context->stripes[i].Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
context->stripes[i].dev = dev;
|
||||
|
||||
context->left++;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
if (context->left == 0) {
|
||||
|
@ -117,7 +130,7 @@ static NTSTATUS send_disks_pnp_message(device_extension* Vcb, UCHAR minor) {
|
|||
|
||||
for (i = 0; i < num_devices; i++) {
|
||||
if (context->stripes[i].Irp) {
|
||||
IoCallDriver(Vcb->devices[i].devobj, context->stripes[i].Irp);
|
||||
IoCallDriver(context->stripes[i].dev->devobj, context->stripes[i].Irp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,6 +154,9 @@ end:
|
|||
|
||||
ExFreePool(context->stripes);
|
||||
ExFreePool(context);
|
||||
|
||||
end2:
|
||||
ExReleaseResourceLite(&Vcb->tree_lock);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -296,7 +312,7 @@ NTSTATUS STDCALL drv_pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
TRACE("passing minor function 0x%x on\n", IrpSp->MinorFunction);
|
||||
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
Status = IoCallDriver(Vcb->devices[0].devobj, Irp);
|
||||
Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -305,7 +321,7 @@ NTSTATUS STDCALL drv_pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
//
|
||||
// IoSkipCurrentIrpStackLocation(Irp);
|
||||
//
|
||||
// Status = IoCallDriver(Vcb->devices[0].devobj, Irp);
|
||||
// Status = IoCallDriver(first_device(Vcb)->devobj, Irp);
|
||||
//
|
||||
// // IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,7 +27,7 @@ NTSTATUS registry_load_volume_options(device_extension* Vcb) {
|
|||
BTRFS_UUID* uuid = &Vcb->superblock.uuid;
|
||||
mount_options* options = &Vcb->options;
|
||||
UNICODE_STRING path, ignoreus, compressus, compressforceus, compresstypeus, readonlyus, zliblevelus, flushintervalus,
|
||||
maxinlineus, subvolidus, raid5recalcus, raid6recalcus;
|
||||
maxinlineus, subvolidus, raid5recalcus, raid6recalcus, skipbalanceus;
|
||||
OBJECT_ATTRIBUTES oa;
|
||||
NTSTATUS Status;
|
||||
ULONG i, j, kvfilen, index, retlen;
|
||||
|
@ -43,6 +43,7 @@ NTSTATUS registry_load_volume_options(device_extension* Vcb) {
|
|||
options->max_inline = min(mount_max_inline, Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node) - sizeof(EXTENT_DATA) + 1);
|
||||
options->raid5_recalculation = mount_raid5_recalculation;
|
||||
options->raid6_recalculation = mount_raid6_recalculation;
|
||||
options->skip_balance = mount_skip_balance;
|
||||
options->subvol_id = 0;
|
||||
|
||||
path.Length = path.MaximumLength = registry_path.Length + (37 * sizeof(WCHAR));
|
||||
|
@ -103,6 +104,7 @@ NTSTATUS registry_load_volume_options(device_extension* Vcb) {
|
|||
RtlInitUnicodeString(&subvolidus, L"SubvolId");
|
||||
RtlInitUnicodeString(&raid5recalcus, L"Raid5Recalculation");
|
||||
RtlInitUnicodeString(&raid6recalcus, L"Raid6Recalculation");
|
||||
RtlInitUnicodeString(&skipbalanceus, L"SkipBalance");
|
||||
|
||||
do {
|
||||
Status = ZwEnumerateValueKey(h, index, KeyValueFullInformation, kvfi, kvfilen, &retlen);
|
||||
|
@ -159,6 +161,10 @@ NTSTATUS registry_load_volume_options(device_extension* Vcb) {
|
|||
DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
|
||||
|
||||
options->raid6_recalculation = *val;
|
||||
} else if (FsRtlAreNamesEqual(&skipbalanceus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
|
||||
DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
|
||||
|
||||
options->skip_balance = *val;
|
||||
}
|
||||
} else if (Status != STATUS_NO_MORE_ENTRIES) {
|
||||
ERR("ZwEnumerateValueKey returned %08x\n", Status);
|
||||
|
@ -655,6 +661,7 @@ void STDCALL read_registry(PUNICODE_STRING regpath) {
|
|||
get_registry_value(h, L"MaxInline", REG_DWORD, &mount_max_inline, sizeof(mount_max_inline));
|
||||
get_registry_value(h, L"Raid5Recalculation", REG_DWORD, &mount_raid5_recalculation, sizeof(mount_raid5_recalculation));
|
||||
get_registry_value(h, L"Raid6Recalculation", REG_DWORD, &mount_raid6_recalculation, sizeof(mount_raid6_recalculation));
|
||||
get_registry_value(h, L"SkipBalance", REG_DWORD, &mount_skip_balance, sizeof(mount_skip_balance));
|
||||
|
||||
if (mount_flush_interval == 0)
|
||||
mount_flush_interval = 1;
|
||||
|
|
|
@ -56,7 +56,7 @@ NTSTATUS get_reparse_point(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
|||
}
|
||||
|
||||
TRACE("data = %p, size = %x\n", data, fcb->inode_item.st_size);
|
||||
Status = read_file(fcb, (UINT8*)data, 0, fcb->inode_item.st_size, NULL, NULL);
|
||||
Status = read_file(fcb, (UINT8*)data, 0, fcb->inode_item.st_size, NULL, NULL, TRUE);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("read_file returned %08x\n", Status);
|
||||
|
@ -119,7 +119,7 @@ NTSTATUS get_reparse_point(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
|||
if (fcb->type == BTRFS_TYPE_FILE) {
|
||||
ULONG len;
|
||||
|
||||
Status = read_file(fcb, buffer, 0, buflen, &len, NULL);
|
||||
Status = read_file(fcb, buffer, 0, buflen, &len, NULL, TRUE);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("read_file returned %08x\n", Status);
|
||||
|
@ -177,6 +177,9 @@ static NTSTATUS set_symlink(PIRP Irp, file_ref* fileref, ccb* ccb, REPARSE_DATA_
|
|||
|
||||
fileref->fcb->inode_item.st_mode |= __S_IFLNK;
|
||||
|
||||
if (fileref->dc)
|
||||
fileref->dc->type = fileref->fcb->type;
|
||||
|
||||
if (write) {
|
||||
Status = truncate_file(fileref->fcb, 0, Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
@ -485,6 +488,9 @@ NTSTATUS delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
|
||||
fileref->fcb->atts &= ~FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
|
||||
if (fileref->dc)
|
||||
fileref->dc->type = fileref->fcb->type;
|
||||
|
||||
mark_fileref_dirty(fileref);
|
||||
|
||||
fileref->fcb->inode_item_changed = TRUE;
|
||||
|
|
|
@ -30,47 +30,28 @@
|
|||
#endif
|
||||
#include <wdmguid.h>
|
||||
|
||||
#ifndef __REACTOS__
|
||||
typedef struct _OBJECT_DIRECTORY_INFORMATION {
|
||||
UNICODE_STRING Name;
|
||||
UNICODE_STRING TypeName;
|
||||
} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION;
|
||||
#endif
|
||||
extern LIST_ENTRY volumes;
|
||||
extern ERESOURCE volumes_lock;
|
||||
extern LIST_ENTRY pnp_disks;
|
||||
|
||||
#if !defined (_GNU_NTIFS_) || defined(__REACTOS__)
|
||||
NTSTATUS WINAPI ZwQueryDirectoryObject(HANDLE DirectoryHandle, PVOID Buffer, ULONG Length,
|
||||
BOOLEAN ReturnSingleEntry, BOOLEAN RestartScan, PULONG Context,
|
||||
PULONG ReturnLength);
|
||||
#endif
|
||||
|
||||
VOID WINAPI IopNotifyPlugPlayNotification(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
|
||||
IN LPCGUID Event,
|
||||
IN PVOID EventCategoryData1,
|
||||
IN PVOID EventCategoryData2
|
||||
);
|
||||
|
||||
static const WCHAR devpath[] = {'\\','D','e','v','i','c','e',0};
|
||||
|
||||
static NTSTATUS create_part0(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT DeviceObject, PUNICODE_STRING pardir, PUNICODE_STRING nameus,
|
||||
BTRFS_UUID* uuid) {
|
||||
static NTSTATUS create_part0(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT DeviceObject, PUNICODE_STRING devpath,
|
||||
PUNICODE_STRING nameus, BTRFS_UUID* uuid) {
|
||||
PDEVICE_OBJECT newdevobj;
|
||||
UNICODE_STRING name;
|
||||
NTSTATUS Status;
|
||||
part0_device_extension* p0de;
|
||||
|
||||
static const WCHAR btrfs_partition[] = L"\\BtrfsPartition";
|
||||
static const WCHAR part0_suffix[] = L"Btrfs";
|
||||
|
||||
name.Length = name.MaximumLength = pardir->Length + (wcslen(btrfs_partition) * sizeof(WCHAR));
|
||||
name.Length = name.MaximumLength = devpath->Length + (wcslen(part0_suffix) * sizeof(WCHAR));
|
||||
name.Buffer = ExAllocatePoolWithTag(PagedPool, name.Length, ALLOC_TAG);
|
||||
if (!name.Buffer) {
|
||||
ERR("out of memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlCopyMemory(name.Buffer, pardir->Buffer, pardir->Length);
|
||||
RtlCopyMemory(&name.Buffer[pardir->Length / sizeof(WCHAR)], btrfs_partition, wcslen(btrfs_partition) * sizeof(WCHAR));
|
||||
RtlCopyMemory(name.Buffer, devpath->Buffer, devpath->Length);
|
||||
RtlCopyMemory(&name.Buffer[devpath->Length / sizeof(WCHAR)], part0_suffix, wcslen(part0_suffix) * sizeof(WCHAR));
|
||||
|
||||
Status = IoCreateDevice(DriverObject, sizeof(part0_device_extension), &name, FILE_DEVICE_DISK, FILE_DEVICE_SECURE_OPEN, FALSE, &newdevobj);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
@ -101,6 +82,7 @@ static NTSTATUS create_part0(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT DeviceO
|
|||
ObReferenceObject(DeviceObject);
|
||||
|
||||
newdevobj->StackSize = DeviceObject->StackSize + 1;
|
||||
newdevobj->SectorSize = DeviceObject->SectorSize;
|
||||
|
||||
newdevobj->Flags |= DO_DIRECT_IO;
|
||||
newdevobj->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
@ -110,7 +92,7 @@ static NTSTATUS create_part0(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT DeviceO
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void STDCALL add_volume(PDEVICE_OBJECT mountmgr, PUNICODE_STRING us) {
|
||||
void add_volume(PDEVICE_OBJECT mountmgr, PUNICODE_STRING us) {
|
||||
ULONG tnsize;
|
||||
MOUNTMGR_TARGET_NAME* tn;
|
||||
KEVENT Event;
|
||||
|
@ -156,7 +138,7 @@ static void STDCALL add_volume(PDEVICE_OBJECT mountmgr, PUNICODE_STRING us) {
|
|||
|
||||
ExFreePool(tn);
|
||||
|
||||
mmdltsize = sizeof(MOUNTMGR_DRIVE_LETTER_TARGET) - 1 + us->Length;
|
||||
mmdltsize = offsetof(MOUNTMGR_DRIVE_LETTER_TARGET, DeviceName[0]) + us->Length;
|
||||
|
||||
mmdlt = ExAllocatePoolWithTag(NonPagedPool, mmdltsize, ALLOC_TAG);
|
||||
if (!mmdlt) {
|
||||
|
@ -191,7 +173,7 @@ static void STDCALL add_volume(PDEVICE_OBJECT mountmgr, PUNICODE_STRING us) {
|
|||
ExFreePool(mmdlt);
|
||||
}
|
||||
|
||||
static void STDCALL test_vol(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT mountmgr, PUNICODE_STRING pardir, PUNICODE_STRING us, BOOL part0, LIST_ENTRY* volumes) {
|
||||
static void STDCALL test_vol(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath, DWORD disk_num, DWORD part_num, LIST_ENTRY* volumes) {
|
||||
KEVENT Event;
|
||||
PIRP Irp;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
|
@ -200,31 +182,15 @@ static void STDCALL test_vol(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT mountmg
|
|||
PDEVICE_OBJECT DeviceObject;
|
||||
LARGE_INTEGER Offset;
|
||||
ULONG toread;
|
||||
UINT8* data;
|
||||
UNICODE_STRING us2;
|
||||
BOOL added_entry = FALSE;
|
||||
UINT8* data = NULL;
|
||||
UINT32 sector_size;
|
||||
|
||||
TRACE("%.*S\n", us->Length / sizeof(WCHAR), us->Buffer);
|
||||
TRACE("%.*S\n", devpath->Length / sizeof(WCHAR), devpath->Buffer);
|
||||
|
||||
us2.Length = pardir->Length + sizeof(WCHAR) + us->Length;
|
||||
us2.MaximumLength = us2.Length;
|
||||
us2.Buffer = ExAllocatePoolWithTag(PagedPool, us2.Length, ALLOC_TAG);
|
||||
if (!us2.Buffer) {
|
||||
ERR("out of memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
RtlCopyMemory(us2.Buffer, pardir->Buffer, pardir->Length);
|
||||
us2.Buffer[pardir->Length / sizeof(WCHAR)] = '\\';
|
||||
RtlCopyMemory(&us2.Buffer[(pardir->Length / sizeof(WCHAR))+1], us->Buffer, us->Length);
|
||||
|
||||
TRACE("%.*S\n", us2.Length / sizeof(WCHAR), us2.Buffer);
|
||||
|
||||
Status = IoGetDeviceObjectPointer(&us2, FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject);
|
||||
Status = IoGetDeviceObjectPointer(devpath, FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("IoGetDeviceObjectPointer returned %08x\n", Status);
|
||||
goto exit;
|
||||
return;
|
||||
}
|
||||
|
||||
sector_size = DeviceObject->SectorSize;
|
||||
|
@ -238,20 +204,20 @@ static void STDCALL test_vol(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT mountmg
|
|||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("%.*S had a sector size of 0, and IOCTL_DISK_GET_DRIVE_GEOMETRY returned %08x\n",
|
||||
us2.Length / sizeof(WCHAR), us2.Buffer, Status);
|
||||
goto exit;
|
||||
devpath->Length / sizeof(WCHAR), devpath->Buffer, Status);
|
||||
goto deref;
|
||||
}
|
||||
|
||||
if (iosb.Information < sizeof(DISK_GEOMETRY)) {
|
||||
ERR("%.*S: IOCTL_DISK_GET_DRIVE_GEOMETRY returned %u bytes, expected %u\n",
|
||||
us2.Length / sizeof(WCHAR), us2.Buffer, iosb.Information, sizeof(DISK_GEOMETRY));
|
||||
devpath->Length / sizeof(WCHAR), devpath->Buffer, iosb.Information, sizeof(DISK_GEOMETRY));
|
||||
}
|
||||
|
||||
sector_size = geometry.BytesPerSector;
|
||||
|
||||
if (sector_size == 0) {
|
||||
ERR("%.*S had a sector size of 0\n", us2.Length / sizeof(WCHAR), us2.Buffer);
|
||||
goto exit;
|
||||
ERR("%.*S had a sector size of 0\n", devpath->Length / sizeof(WCHAR), devpath->Buffer);
|
||||
goto deref;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,33 +261,49 @@ static void STDCALL test_vol(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT mountmg
|
|||
&gli, sizeof(gli), TRUE, NULL);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error reading length information: %08x\n", Status);
|
||||
ExFreePool(v);
|
||||
goto deref;
|
||||
}
|
||||
|
||||
if (part0) {
|
||||
if (part_num == 0) {
|
||||
UNICODE_STRING us3;
|
||||
|
||||
Status = create_part0(DriverObject, DeviceObject, pardir, &us3, &sb->dev_item.device_uuid);
|
||||
Status = create_part0(DriverObject, DeviceObject, devpath, &us3, &sb->dev_item.device_uuid);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("create_part0 returned %08x\n", Status);
|
||||
ExFreePool(v);
|
||||
goto deref;
|
||||
}
|
||||
|
||||
ExFreePool(us2.Buffer);
|
||||
us2 = us3;
|
||||
v->devpath = us3;
|
||||
} else {
|
||||
v->devpath.Length = v->devpath.MaximumLength = devpath->Length;
|
||||
v->devpath.Buffer = ExAllocatePoolWithTag(PagedPool, v->devpath.Length, ALLOC_TAG);
|
||||
|
||||
if (!v->devpath.Buffer) {
|
||||
ERR("out of memory\n");
|
||||
ExFreePool(v);
|
||||
goto deref;
|
||||
}
|
||||
|
||||
RtlCopyMemory(v->devpath.Buffer, devpath->Buffer, v->devpath.Length);
|
||||
}
|
||||
|
||||
RtlCopyMemory(&v->fsuuid, &sb->uuid, sizeof(BTRFS_UUID));
|
||||
RtlCopyMemory(&v->devuuid, &sb->dev_item.device_uuid, sizeof(BTRFS_UUID));
|
||||
v->devnum = sb->dev_item.dev_id;
|
||||
v->devpath = us2;
|
||||
v->processed = FALSE;
|
||||
v->length = gli.Length.QuadPart;
|
||||
v->gen1 = sb->generation;
|
||||
v->gen2 = 0;
|
||||
v->seeding = sb->flags & BTRFS_SUPERBLOCK_FLAGS_SEEDING ? TRUE : FALSE;
|
||||
v->disk_num = disk_num;
|
||||
v->part_num = part_num;
|
||||
|
||||
ExAcquireResourceExclusiveLite(&volumes_lock, TRUE);
|
||||
InsertTailList(volumes, &v->list_entry);
|
||||
ExReleaseResourceLite(&volumes_lock);
|
||||
|
||||
i = 1;
|
||||
while (superblock_addrs[i] != 0 && superblock_addrs[i] + toread <= v->length) {
|
||||
|
@ -368,120 +350,16 @@ static void STDCALL test_vol(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT mountmg
|
|||
v->devuuid.uuid[0], v->devuuid.uuid[1], v->devuuid.uuid[2], v->devuuid.uuid[3], v->devuuid.uuid[4], v->devuuid.uuid[5], v->devuuid.uuid[6], v->devuuid.uuid[7],
|
||||
v->devuuid.uuid[8], v->devuuid.uuid[9], v->devuuid.uuid[10], v->devuuid.uuid[11], v->devuuid.uuid[12], v->devuuid.uuid[13], v->devuuid.uuid[14], v->devuuid.uuid[15]);
|
||||
TRACE("device number %llx\n", v->devnum);
|
||||
|
||||
added_entry = TRUE;
|
||||
}
|
||||
|
||||
deref:
|
||||
ExFreePool(data);
|
||||
if (data)
|
||||
ExFreePool(data);
|
||||
|
||||
ObDereferenceObject(FileObject);
|
||||
|
||||
exit:
|
||||
if (!added_entry)
|
||||
ExFreePool(us2.Buffer);
|
||||
}
|
||||
|
||||
static NTSTATUS look_in_harddisk_dir(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT mountmgr, PUNICODE_STRING name, LIST_ENTRY* volumes) {
|
||||
UNICODE_STRING path;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
NTSTATUS Status;
|
||||
HANDLE h;
|
||||
OBJECT_DIRECTORY_INFORMATION* odi;
|
||||
ULONG odisize, context;
|
||||
BOOL restart, has_part0 = FALSE, has_parts = FALSE;
|
||||
|
||||
static const WCHAR partition[] = L"Partition";
|
||||
static WCHAR partition0[] = L"Partition0";
|
||||
|
||||
path.Buffer = ExAllocatePoolWithTag(PagedPool, ((wcslen(devpath) + 1) * sizeof(WCHAR)) + name->Length, ALLOC_TAG);
|
||||
if (!path.Buffer) {
|
||||
ERR("out of memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlCopyMemory(path.Buffer, devpath, wcslen(devpath) * sizeof(WCHAR));
|
||||
path.Buffer[wcslen(devpath)] = '\\';
|
||||
RtlCopyMemory(&path.Buffer[wcslen(devpath) + 1], name->Buffer, name->Length);
|
||||
path.Length = path.MaximumLength = ((wcslen(devpath) + 1) * sizeof(WCHAR)) + name->Length;
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
attr.ObjectName = &path;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
Status = ZwOpenDirectoryObject(&h, DIRECTORY_TRAVERSE, &attr);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("ZwOpenDirectoryObject returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
odisize = sizeof(OBJECT_DIRECTORY_INFORMATION) * 16;
|
||||
odi = ExAllocatePoolWithTag(PagedPool, odisize, ALLOC_TAG);
|
||||
if (!odi) {
|
||||
ERR("out of memory\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
ZwClose(h);
|
||||
goto end;
|
||||
}
|
||||
|
||||
restart = TRUE;
|
||||
do {
|
||||
Status = ZwQueryDirectoryObject(h, odi, odisize, FALSE, restart, &context, NULL/*&retlen*/);
|
||||
restart = FALSE;
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
if (Status != STATUS_NO_MORE_ENTRIES)
|
||||
ERR("ZwQueryDirectoryObject returned %08x\n", Status);
|
||||
} else {
|
||||
OBJECT_DIRECTORY_INFORMATION* odi2 = odi;
|
||||
|
||||
while (odi2->Name.Buffer) {
|
||||
TRACE("%.*S, %.*S\n", odi2->TypeName.Length / sizeof(WCHAR), odi2->TypeName.Buffer, odi2->Name.Length / sizeof(WCHAR), odi2->Name.Buffer);
|
||||
|
||||
if (odi2->Name.Length > wcslen(partition) * sizeof(WCHAR) &&
|
||||
RtlCompareMemory(odi2->Name.Buffer, partition, wcslen(partition) * sizeof(WCHAR)) == wcslen(partition) * sizeof(WCHAR)) {
|
||||
|
||||
if (odi2->Name.Length == (wcslen(partition) + 1) * sizeof(WCHAR) && odi2->Name.Buffer[(odi2->Name.Length / sizeof(WCHAR)) - 1] == '0') {
|
||||
// Partition0 refers to the whole disk
|
||||
has_part0 = TRUE;
|
||||
} else {
|
||||
has_parts = TRUE;
|
||||
|
||||
test_vol(DriverObject, mountmgr, &path, &odi2->Name, FALSE, volumes);
|
||||
}
|
||||
}
|
||||
|
||||
odi2 = &odi2[1];
|
||||
}
|
||||
}
|
||||
} while (NT_SUCCESS(Status));
|
||||
|
||||
// If disk had no partitions, test the whole disk
|
||||
if (!has_parts && has_part0) {
|
||||
UNICODE_STRING part0us;
|
||||
|
||||
part0us.Buffer = partition0;
|
||||
part0us.Length = part0us.MaximumLength = wcslen(partition0) * sizeof(WCHAR);
|
||||
|
||||
test_vol(DriverObject, mountmgr, &path, &part0us, TRUE, volumes);
|
||||
}
|
||||
|
||||
ZwClose(h);
|
||||
|
||||
ExFreePool(odi);
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
end:
|
||||
ExFreePool(path.Buffer);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static void remove_drive_letter(PDEVICE_OBJECT mountmgr, volume* v) {
|
||||
void remove_drive_letter(PDEVICE_OBJECT mountmgr, volume* v) {
|
||||
NTSTATUS Status;
|
||||
KEVENT Event;
|
||||
PIRP Irp;
|
||||
|
@ -566,79 +444,10 @@ static void remove_drive_letter(PDEVICE_OBJECT mountmgr, volume* v) {
|
|||
ExFreePool(mmp);
|
||||
}
|
||||
|
||||
void STDCALL look_for_vols(PDRIVER_OBJECT DriverObject, LIST_ENTRY* volumes) {
|
||||
PFILE_OBJECT FileObject;
|
||||
PDEVICE_OBJECT mountmgr;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
UNICODE_STRING mmdevpath, us;
|
||||
HANDLE h;
|
||||
OBJECT_DIRECTORY_INFORMATION* odi;
|
||||
ULONG odisize;
|
||||
ULONG context;
|
||||
BOOL restart;
|
||||
NTSTATUS Status;
|
||||
static void refresh_mountmgr(PDEVICE_OBJECT mountmgr, LIST_ENTRY* volumes) {
|
||||
LIST_ENTRY* le;
|
||||
|
||||
static const WCHAR directory[] = L"Directory";
|
||||
static const WCHAR harddisk[] = L"Harddisk";
|
||||
|
||||
RtlInitUnicodeString(&mmdevpath, MOUNTMGR_DEVICE_NAME);
|
||||
Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &FileObject, &mountmgr);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("IoGetDeviceObjectPointer returned %08x\n", Status);
|
||||
return;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&us, devpath);
|
||||
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
attr.ObjectName = &us;
|
||||
attr.SecurityDescriptor = NULL;
|
||||
attr.SecurityQualityOfService = NULL;
|
||||
|
||||
Status = ZwOpenDirectoryObject(&h, DIRECTORY_TRAVERSE, &attr);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("ZwOpenDirectoryObject returned %08x\n", Status);
|
||||
return;
|
||||
}
|
||||
|
||||
odisize = sizeof(OBJECT_DIRECTORY_INFORMATION) * 16;
|
||||
odi = ExAllocatePoolWithTag(PagedPool, odisize, ALLOC_TAG);
|
||||
if (!odi) {
|
||||
ERR("out of memory\n");
|
||||
ZwClose(h);
|
||||
return;
|
||||
}
|
||||
|
||||
restart = TRUE;
|
||||
do {
|
||||
Status = ZwQueryDirectoryObject(h, odi, odisize, FALSE, restart, &context, NULL/*&retlen*/);
|
||||
restart = FALSE;
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
if (Status != STATUS_NO_MORE_ENTRIES)
|
||||
ERR("ZwQueryDirectoryObject returned %08x\n", Status);
|
||||
} else {
|
||||
OBJECT_DIRECTORY_INFORMATION* odi2 = odi;
|
||||
|
||||
while (odi2->Name.Buffer) {
|
||||
if (odi2->TypeName.Length == wcslen(directory) * sizeof(WCHAR) &&
|
||||
RtlCompareMemory(odi2->TypeName.Buffer, directory, odi2->TypeName.Length) == odi2->TypeName.Length &&
|
||||
odi2->Name.Length > wcslen(harddisk) * sizeof(WCHAR) &&
|
||||
RtlCompareMemory(odi2->Name.Buffer, harddisk, wcslen(harddisk) * sizeof(WCHAR)) == wcslen(harddisk) * sizeof(WCHAR)) {
|
||||
look_in_harddisk_dir(DriverObject, mountmgr, &odi2->Name, volumes);
|
||||
}
|
||||
|
||||
odi2 = &odi2[1];
|
||||
}
|
||||
}
|
||||
} while (NT_SUCCESS(Status));
|
||||
|
||||
ExFreePool(odi);
|
||||
ZwClose(h);
|
||||
ExAcquireResourceExclusiveLite(&volumes_lock, TRUE);
|
||||
|
||||
le = volumes->Flink;
|
||||
while (le != volumes) {
|
||||
|
@ -670,5 +479,215 @@ void STDCALL look_for_vols(PDRIVER_OBJECT DriverObject, LIST_ENTRY* volumes) {
|
|||
le = le->Flink;
|
||||
}
|
||||
|
||||
ObDereferenceObject(FileObject);
|
||||
ExReleaseResourceLite(&volumes_lock);
|
||||
}
|
||||
|
||||
static void add_pnp_disk(ULONG disk_num, PUNICODE_STRING devpath) {
|
||||
LIST_ENTRY* le;
|
||||
pnp_disk* disk;
|
||||
|
||||
le = pnp_disks.Flink;
|
||||
while (le != &pnp_disks) {
|
||||
disk = CONTAINING_RECORD(le, pnp_disk, list_entry);
|
||||
|
||||
if (disk->devpath.Length == devpath->Length &&
|
||||
RtlCompareMemory(disk->devpath.Buffer, devpath->Buffer, devpath->Length) == devpath->Length)
|
||||
return;
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
disk = ExAllocatePoolWithTag(PagedPool, sizeof(pnp_disk), ALLOC_TAG);
|
||||
if (!disk) {
|
||||
ERR("out of memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
disk->devpath.Length = disk->devpath.MaximumLength = devpath->Length;
|
||||
disk->devpath.Buffer = ExAllocatePoolWithTag(PagedPool, devpath->Length, ALLOC_TAG);
|
||||
|
||||
if (!disk->devpath.Buffer) {
|
||||
ERR("out of memory\n");
|
||||
ExFreePool(disk);
|
||||
return;
|
||||
}
|
||||
|
||||
RtlCopyMemory(disk->devpath.Buffer, devpath->Buffer, devpath->Length);
|
||||
|
||||
disk->disk_num = disk_num;
|
||||
|
||||
InsertTailList(&pnp_disks, &disk->list_entry);
|
||||
}
|
||||
|
||||
static void disk_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) {
|
||||
PFILE_OBJECT FileObject, FileObject2;
|
||||
PDEVICE_OBJECT devobj, mountmgr;
|
||||
NTSTATUS Status;
|
||||
STORAGE_DEVICE_NUMBER sdn;
|
||||
ULONG dlisize;
|
||||
DRIVE_LAYOUT_INFORMATION_EX* dli;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
int i, num_parts = 0;
|
||||
UNICODE_STRING devname, num, bspus, mmdevpath;
|
||||
WCHAR devnamew[255], numw[20];
|
||||
USHORT preflen;
|
||||
|
||||
static WCHAR device_harddisk[] = L"\\Device\\Harddisk";
|
||||
static WCHAR bs_partition[] = L"\\Partition";
|
||||
|
||||
// FIXME - work with CD-ROMs and floppies(?)
|
||||
|
||||
Status = IoGetDeviceObjectPointer(devpath, FILE_READ_ATTRIBUTES, &FileObject, &devobj);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("IoGetDeviceObjectPointer returned %08x\n", Status);
|
||||
return;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&mmdevpath, MOUNTMGR_DEVICE_NAME);
|
||||
Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &FileObject2, &mountmgr);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("IoGetDeviceObjectPointer returned %08x\n", Status);
|
||||
ObDereferenceObject(FileObject);
|
||||
return;
|
||||
}
|
||||
|
||||
Status = dev_ioctl(devobj, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0,
|
||||
&sdn, sizeof(STORAGE_DEVICE_NUMBER), TRUE, &iosb);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("IOCTL_STORAGE_GET_DEVICE_NUMBER returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ExAcquireResourceExclusiveLite(&volumes_lock, TRUE);
|
||||
add_pnp_disk(sdn.DeviceNumber, devpath);
|
||||
ExReleaseResourceLite(&volumes_lock);
|
||||
|
||||
dlisize = 0;
|
||||
|
||||
do {
|
||||
dlisize += 1024;
|
||||
dli = ExAllocatePoolWithTag(PagedPool, dlisize, ALLOC_TAG);
|
||||
|
||||
Status = dev_ioctl(devobj, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0,
|
||||
dli, dlisize, TRUE, &iosb);
|
||||
} while (Status == STATUS_BUFFER_TOO_SMALL);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ExFreePool(dli);
|
||||
goto no_parts;
|
||||
}
|
||||
|
||||
wcscpy(devnamew, device_harddisk);
|
||||
devname.Buffer = devnamew;
|
||||
devname.MaximumLength = sizeof(devnamew);
|
||||
devname.Length = wcslen(device_harddisk) * sizeof(WCHAR);
|
||||
|
||||
num.Buffer = numw;
|
||||
num.MaximumLength = sizeof(numw);
|
||||
RtlIntegerToUnicodeString(sdn.DeviceNumber, 10, &num);
|
||||
RtlAppendUnicodeStringToString(&devname, &num);
|
||||
|
||||
bspus.Buffer = bs_partition;
|
||||
bspus.Length = bspus.MaximumLength = wcslen(bs_partition) * sizeof(WCHAR);
|
||||
RtlAppendUnicodeStringToString(&devname, &bspus);
|
||||
|
||||
preflen = devname.Length;
|
||||
|
||||
for (i = 0; i < dli->PartitionCount; i++) {
|
||||
if (dli->PartitionEntry[i].PartitionLength.QuadPart != 0 && dli->PartitionEntry[i].PartitionNumber != 0) {
|
||||
devname.Length = preflen;
|
||||
RtlIntegerToUnicodeString(dli->PartitionEntry[i].PartitionNumber, 10, &num);
|
||||
RtlAppendUnicodeStringToString(&devname, &num);
|
||||
|
||||
test_vol(DriverObject, mountmgr, &devname, sdn.DeviceNumber, dli->PartitionEntry[i].PartitionNumber, &volumes);
|
||||
|
||||
num_parts++;
|
||||
}
|
||||
}
|
||||
|
||||
ExFreePool(dli);
|
||||
|
||||
no_parts:
|
||||
if (num_parts == 0) {
|
||||
devname.Length = preflen;
|
||||
devname.Buffer[devname.Length / sizeof(WCHAR)] = '0';
|
||||
devname.Length += sizeof(WCHAR);
|
||||
|
||||
test_vol(DriverObject, mountmgr, &devname, sdn.DeviceNumber, 0, &volumes);
|
||||
}
|
||||
|
||||
end:
|
||||
refresh_mountmgr(mountmgr, &volumes);
|
||||
|
||||
ObDereferenceObject(FileObject);
|
||||
ObDereferenceObject(FileObject2);
|
||||
}
|
||||
|
||||
static void disk_removal(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) {
|
||||
LIST_ENTRY* le;
|
||||
pnp_disk* disk = NULL;
|
||||
|
||||
// FIXME - remove Partition0Btrfs devices and unlink from mountmgr
|
||||
// FIXME - emergency unmount of RAIDed volumes
|
||||
|
||||
ExAcquireResourceExclusiveLite(&volumes_lock, TRUE);
|
||||
|
||||
le = pnp_disks.Flink;
|
||||
while (le != &pnp_disks) {
|
||||
pnp_disk* disk2 = CONTAINING_RECORD(le, pnp_disk, list_entry);
|
||||
|
||||
if (disk2->devpath.Length == devpath->Length &&
|
||||
RtlCompareMemory(disk2->devpath.Buffer, devpath->Buffer, devpath->Length) == devpath->Length) {
|
||||
disk = disk2;
|
||||
break;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
if (!disk) {
|
||||
ExReleaseResourceLite(&volumes_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
le = volumes.Flink;
|
||||
while (le != &volumes) {
|
||||
volume* v = CONTAINING_RECORD(le, volume, list_entry);
|
||||
LIST_ENTRY* le2 = le->Flink;
|
||||
|
||||
if (v->disk_num == disk->disk_num) {
|
||||
if (v->devpath.Buffer)
|
||||
ExFreePool(v->devpath.Buffer);
|
||||
|
||||
RemoveEntryList(&v->list_entry);
|
||||
|
||||
ExFreePool(v);
|
||||
}
|
||||
|
||||
le = le2;
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&volumes_lock);
|
||||
|
||||
ExFreePool(disk->devpath.Buffer);
|
||||
|
||||
RemoveEntryList(&disk->list_entry);
|
||||
|
||||
ExFreePool(disk);
|
||||
}
|
||||
|
||||
#ifdef __REACTOS__
|
||||
NTSTATUS NTAPI pnp_notification(PVOID NotificationStructure, PVOID Context) {
|
||||
#else
|
||||
NTSTATUS pnp_notification(PVOID NotificationStructure, PVOID Context) {
|
||||
#endif
|
||||
DEVICE_INTERFACE_CHANGE_NOTIFICATION* dicn = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure;
|
||||
PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Context;
|
||||
|
||||
if (RtlCompareMemory(&dicn->Event, &GUID_DEVICE_INTERFACE_ARRIVAL, sizeof(GUID)) == sizeof(GUID))
|
||||
disk_arrival(DriverObject, dicn->SymbolicLinkName);
|
||||
else if (RtlCompareMemory(&dicn->Event, &GUID_DEVICE_INTERFACE_REMOVAL, sizeof(GUID)) == sizeof(GUID))
|
||||
disk_removal(DriverObject, dicn->SymbolicLinkName);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -401,14 +401,10 @@ static ACL* load_default_acl() {
|
|||
// }
|
||||
// }
|
||||
|
||||
static BOOL get_sd_from_xattr(fcb* fcb, PIRP Irp) {
|
||||
ULONG buflen;
|
||||
BOOL get_sd_from_xattr(fcb* fcb, ULONG buflen) {
|
||||
NTSTATUS Status;
|
||||
PSID sid, usersid;
|
||||
|
||||
if (!get_xattr(fcb->Vcb, fcb->subvol, fcb->inode, EA_NTACL, EA_NTACL_HASH, (UINT8**)&fcb->sd, (UINT16*)&buflen, Irp))
|
||||
return FALSE;
|
||||
|
||||
TRACE("using xattr " EA_NTACL " for security descriptor\n");
|
||||
|
||||
if (fcb->inode_item.st_uid != UID_NOBODY) {
|
||||
|
@ -655,13 +651,16 @@ end:
|
|||
ExFreePool(groupsid);
|
||||
}
|
||||
|
||||
void fcb_get_sd(fcb* fcb, struct _fcb* parent, PIRP Irp) {
|
||||
void fcb_get_sd(fcb* fcb, struct _fcb* parent, BOOL look_for_xattr, PIRP Irp) {
|
||||
NTSTATUS Status;
|
||||
PSID usersid = NULL, groupsid = NULL;
|
||||
SECURITY_SUBJECT_CONTEXT subjcont;
|
||||
ULONG buflen;
|
||||
|
||||
if (get_sd_from_xattr(fcb, Irp))
|
||||
return;
|
||||
if (look_for_xattr && get_xattr(fcb->Vcb, fcb->subvol, fcb->inode, EA_NTACL, EA_NTACL_HASH, (UINT8**)&fcb->sd, (UINT16*)&buflen, Irp)) {
|
||||
if (get_sd_from_xattr(fcb, buflen))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!parent) {
|
||||
get_top_level_sd(fcb);
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -3,7 +3,7 @@
|
|||
|
||||
The following FSD are shared with: https://github.com/maharmstone/btrfs.
|
||||
|
||||
reactos/drivers/filesystems/btrfs # Synced to 0.7
|
||||
reactos/drivers/filesystems/btrfs # Synced to 0.8
|
||||
reactos/dll/shellext/shellbtrfs # Synced to 0.7
|
||||
|
||||
The following FSD are shared with: http://www.ext2fsd.com/
|
||||
|
|
Loading…
Reference in a new issue