mirror of
https://github.com/reactos/reactos.git
synced 2025-02-20 15:35:04 +00:00
[BTRFS]
Sync btrfs to 0.6. CORE-11937 svn path=/trunk/; revision=72576
This commit is contained in:
parent
2d33d95a7b
commit
74750c6d1a
24 changed files with 4693 additions and 2756 deletions
|
@ -1,10 +1,13 @@
|
|||
add_subdirectory(zlib)
|
||||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers
|
||||
${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/zlib
|
||||
inc)
|
||||
|
||||
list(APPEND SOURCE
|
||||
btrfs.c
|
||||
cache.c
|
||||
compress.c
|
||||
crc32c.c
|
||||
create.c
|
||||
dirctrl.c
|
||||
|
@ -29,7 +32,7 @@ add_library(btrfs SHARED ${SOURCE} btrfs.rc)
|
|||
|
||||
add_definitions(-D__KERNEL__)
|
||||
set_module_type(btrfs kernelmodedriver)
|
||||
target_link_libraries(btrfs ntoskrnl_vista ${PSEH_LIB})
|
||||
target_link_libraries(btrfs ntoskrnl_vista zlib_solo ${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)
|
||||
|
|
|
@ -35,8 +35,9 @@
|
|||
#endif
|
||||
#include <mountdev.h>
|
||||
|
||||
#define INCOMPAT_SUPPORTED (BTRFS_INCOMPAT_FLAGS_MIXED_BACKREF | BTRFS_INCOMPAT_FLAGS_DEFAULT_SUBVOL | BTRFS_INCOMPAT_FLAGS_BIG_METADATA | \
|
||||
BTRFS_INCOMPAT_FLAGS_EXTENDED_IREF | BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA)
|
||||
#define INCOMPAT_SUPPORTED (BTRFS_INCOMPAT_FLAGS_MIXED_BACKREF | BTRFS_INCOMPAT_FLAGS_DEFAULT_SUBVOL | BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS | \
|
||||
BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO | BTRFS_INCOMPAT_FLAGS_BIG_METADATA | BTRFS_INCOMPAT_FLAGS_EXTENDED_IREF | \
|
||||
BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA | BTRFS_INCOMPAT_FLAGS_NO_HOLES)
|
||||
#define COMPAT_RO_SUPPORTED 0
|
||||
|
||||
static WCHAR device_name[] = {'\\','B','t','r','f','s',0};
|
||||
|
@ -53,6 +54,12 @@ LIST_ENTRY volumes;
|
|||
LIST_ENTRY VcbList;
|
||||
ERESOURCE global_loading_lock;
|
||||
UINT32 debug_log_level = 0;
|
||||
UINT32 mount_compress = 0;
|
||||
UINT32 mount_compress_force = 0;
|
||||
UINT32 mount_compress_type = 0;
|
||||
UINT32 mount_zlib_level = 3;
|
||||
UINT32 mount_flush_interval = 30;
|
||||
UINT32 mount_max_inline = 2048;
|
||||
BOOL log_started = FALSE;
|
||||
UNICODE_STRING log_device, log_file, registry_path;
|
||||
|
||||
|
@ -313,7 +320,7 @@ static void STDCALL DriverUnload(PDRIVER_OBJECT DriverObject) {
|
|||
ExFreePool(registry_path.Buffer);
|
||||
}
|
||||
|
||||
BOOL STDCALL get_last_inode(device_extension* Vcb, root* r) {
|
||||
BOOL STDCALL get_last_inode(device_extension* Vcb, root* r, PIRP Irp) {
|
||||
KEY searchkey;
|
||||
traverse_ptr tp, prev_tp;
|
||||
NTSTATUS Status;
|
||||
|
@ -323,13 +330,13 @@ BOOL STDCALL get_last_inode(device_extension* Vcb, root* r) {
|
|||
searchkey.obj_type = 0xff;
|
||||
searchkey.offset = 0xffffffffffffffff;
|
||||
|
||||
Status = find_item(Vcb, r, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, r, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (find_prev_item(Vcb, &tp, &prev_tp, FALSE)) {
|
||||
while (find_prev_item(Vcb, &tp, &prev_tp, FALSE, Irp)) {
|
||||
tp = prev_tp;
|
||||
|
||||
TRACE("moving on to %llx,%x,%llx\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset);
|
||||
|
@ -348,7 +355,7 @@ BOOL STDCALL get_last_inode(device_extension* Vcb, root* r) {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL STDCALL get_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, 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) {
|
||||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
DIR_ITEM* xa;
|
||||
|
@ -361,7 +368,7 @@ BOOL STDCALL get_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char*
|
|||
searchkey.obj_type = TYPE_XATTR_ITEM;
|
||||
searchkey.offset = crc32;
|
||||
|
||||
Status = find_item(Vcb, subvol, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, subvol, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return FALSE;
|
||||
|
@ -419,7 +426,7 @@ BOOL STDCALL get_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char*
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
NTSTATUS add_dir_item(device_extension* Vcb, root* subvol, UINT64 inode, UINT32 crc32, DIR_ITEM* di, ULONG disize, LIST_ENTRY* rollback) {
|
||||
NTSTATUS add_dir_item(device_extension* Vcb, root* subvol, UINT64 inode, UINT32 crc32, DIR_ITEM* di, ULONG disize, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
UINT8* di2;
|
||||
|
@ -429,7 +436,7 @@ NTSTATUS add_dir_item(device_extension* Vcb, root* subvol, UINT64 inode, UINT32
|
|||
searchkey.obj_type = TYPE_DIR_ITEM;
|
||||
searchkey.offset = crc32;
|
||||
|
||||
Status = find_item(Vcb, subvol, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, subvol, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -456,11 +463,11 @@ NTSTATUS add_dir_item(device_extension* Vcb, root* subvol, UINT64 inode, UINT32
|
|||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
insert_tree_item(Vcb, subvol, inode, TYPE_DIR_ITEM, crc32, di2, tp.item->size + disize, NULL, rollback);
|
||||
insert_tree_item(Vcb, subvol, inode, TYPE_DIR_ITEM, crc32, di2, tp.item->size + disize, NULL, Irp, rollback);
|
||||
|
||||
ExFreePool(di);
|
||||
} else {
|
||||
insert_tree_item(Vcb, subvol, inode, TYPE_DIR_ITEM, crc32, di, disize, NULL, rollback);
|
||||
insert_tree_item(Vcb, subvol, inode, TYPE_DIR_ITEM, crc32, di, disize, NULL, Irp, rollback);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -704,8 +711,24 @@ static NTSTATUS STDCALL drv_query_volume_information(IN PDEVICE_OBJECT DeviceObj
|
|||
break;
|
||||
|
||||
case FileFsDeviceInformation:
|
||||
FIXME("STUB: FileFsDeviceInformation\n");
|
||||
{
|
||||
FILE_FS_DEVICE_INFORMATION* ffdi = Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
TRACE("FileFsDeviceInformation\n");
|
||||
|
||||
ffdi->DeviceType = FILE_DEVICE_DISK;
|
||||
ffdi->Characteristics = Vcb->devices[0].devobj->Characteristics;
|
||||
|
||||
if (Vcb->readonly)
|
||||
ffdi->Characteristics |= FILE_READ_ONLY_DEVICE;
|
||||
else
|
||||
ffdi->Characteristics &= ~FILE_READ_ONLY_DEVICE;
|
||||
|
||||
BytesCopied = sizeof(FILE_FS_DEVICE_INFORMATION);
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case FileFsDriverPathInformation:
|
||||
FIXME("STUB: FileFsDriverPathInformation\n");
|
||||
|
@ -919,7 +942,7 @@ static NTSTATUS STDCALL read_completion(PDEVICE_OBJECT DeviceObject, PIRP Irp, P
|
|||
// }
|
||||
// }
|
||||
|
||||
NTSTATUS create_root(device_extension* Vcb, UINT64 id, root** rootptr, BOOL no_tree, UINT64 offset, LIST_ENTRY* rollback) {
|
||||
NTSTATUS create_root(device_extension* Vcb, UINT64 id, root** rootptr, BOOL no_tree, UINT64 offset, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
root* r;
|
||||
tree* t;
|
||||
ROOT_ITEM* ri;
|
||||
|
@ -975,7 +998,7 @@ NTSTATUS create_root(device_extension* Vcb, UINT64 id, root** rootptr, BOOL no_t
|
|||
// We ask here for a traverse_ptr to the item we're inserting, so we can
|
||||
// copy some of the tree's variables
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->root_root, id, TYPE_ROOT_ITEM, offset, ri, sizeof(ROOT_ITEM), &tp, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->root_root, id, TYPE_ROOT_ITEM, offset, ri, sizeof(ROOT_ITEM), &tp, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
ExFreePool(ri);
|
||||
|
||||
|
@ -1159,30 +1182,46 @@ NTSTATUS create_root(device_extension* Vcb, UINT64 id, root** rootptr, BOOL no_t
|
|||
static NTSTATUS STDCALL set_label(device_extension* Vcb, FILE_FS_LABEL_INFORMATION* ffli) {
|
||||
ULONG utf8len;
|
||||
NTSTATUS Status;
|
||||
USHORT vollen, i;
|
||||
|
||||
TRACE("label = %.*S\n", ffli->VolumeLabelLength / sizeof(WCHAR), ffli->VolumeLabel);
|
||||
|
||||
Status = RtlUnicodeToUTF8N(NULL, 0, &utf8len, ffli->VolumeLabel, ffli->VolumeLabelLength);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto end;
|
||||
vollen = ffli->VolumeLabelLength;
|
||||
|
||||
if (utf8len > MAX_LABEL_SIZE) {
|
||||
Status = STATUS_INVALID_VOLUME_LABEL;
|
||||
goto end;
|
||||
for (i = 0; i < ffli->VolumeLabelLength / sizeof(WCHAR); i++) {
|
||||
if (ffli->VolumeLabel[i] == 0) {
|
||||
vollen = i * sizeof(WCHAR);
|
||||
break;
|
||||
} else if (ffli->VolumeLabel[i] == '/' || ffli->VolumeLabel[i] == '\\') {
|
||||
Status = STATUS_INVALID_VOLUME_LABEL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME - check for '/' and '\\' and reject
|
||||
|
||||
// utf8 = ExAllocatePoolWithTag(PagedPool, utf8len + 1, ALLOC_TAG);
|
||||
|
||||
Status = RtlUnicodeToUTF8N((PCHAR)&Vcb->superblock.label, MAX_LABEL_SIZE * sizeof(WCHAR), &utf8len, ffli->VolumeLabel, ffli->VolumeLabelLength);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto release;
|
||||
if (vollen == 0) {
|
||||
utf8len = 0;
|
||||
} else {
|
||||
Status = RtlUnicodeToUTF8N(NULL, 0, &utf8len, ffli->VolumeLabel, vollen);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto end;
|
||||
|
||||
if (utf8len > MAX_LABEL_SIZE) {
|
||||
Status = STATUS_INVALID_VOLUME_LABEL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE);
|
||||
|
||||
if (utf8len < MAX_LABEL_SIZE * sizeof(WCHAR))
|
||||
RtlZeroMemory(Vcb->superblock.label + utf8len, (MAX_LABEL_SIZE * sizeof(WCHAR)) - utf8len);
|
||||
if (utf8len > 0) {
|
||||
Status = RtlUnicodeToUTF8N((PCHAR)&Vcb->superblock.label, MAX_LABEL_SIZE, &utf8len, ffli->VolumeLabel, vollen);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto release;
|
||||
} else
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
if (utf8len < MAX_LABEL_SIZE)
|
||||
RtlZeroMemory(Vcb->superblock.label + utf8len, MAX_LABEL_SIZE - utf8len);
|
||||
|
||||
// test_tree_deletion(Vcb); // TESTING
|
||||
// test_tree_splitting(Vcb);
|
||||
|
@ -1266,7 +1305,7 @@ exit:
|
|||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS delete_dir_item(device_extension* Vcb, root* subvol, UINT64 parinode, UINT32 crc32, PANSI_STRING utf8, LIST_ENTRY* rollback) {
|
||||
NTSTATUS delete_dir_item(device_extension* Vcb, root* subvol, UINT64 parinode, UINT32 crc32, PANSI_STRING utf8, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
NTSTATUS Status;
|
||||
|
@ -1275,7 +1314,7 @@ NTSTATUS delete_dir_item(device_extension* Vcb, root* subvol, UINT64 parinode, U
|
|||
searchkey.obj_type = TYPE_DIR_ITEM;
|
||||
searchkey.offset = crc32;
|
||||
|
||||
Status = find_item(Vcb, subvol, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, subvol, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -1319,7 +1358,7 @@ NTSTATUS delete_dir_item(device_extension* Vcb, root* subvol, UINT64 parinode, U
|
|||
if ((UINT8*)&di->name[di->n + di->m] - tp.item->data < tp.item->size)
|
||||
RtlCopyMemory(dioff, &di->name[di->n + di->m], tp.item->size - ((UINT8*)&di->name[di->n + di->m] - tp.item->data));
|
||||
|
||||
insert_tree_item(Vcb, subvol, parinode, TYPE_DIR_ITEM, crc32, newdi, newlen, NULL, rollback);
|
||||
insert_tree_item(Vcb, subvol, parinode, TYPE_DIR_ITEM, crc32, newdi, newlen, NULL, Irp, rollback);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1336,7 +1375,7 @@ NTSTATUS delete_dir_item(device_extension* Vcb, root* subvol, UINT64 parinode, U
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS delete_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, PANSI_STRING utf8, LIST_ENTRY* rollback) {
|
||||
NTSTATUS delete_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, PANSI_STRING utf8, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
BOOL changed = FALSE;
|
||||
|
@ -1346,7 +1385,7 @@ NTSTATUS delete_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UIN
|
|||
searchkey.obj_type = TYPE_INODE_REF;
|
||||
searchkey.offset = parinode;
|
||||
|
||||
Status = find_item(Vcb, subvol, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, subvol, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -1400,7 +1439,7 @@ NTSTATUS delete_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UIN
|
|||
if ((UINT8*)&ir->name[ir->n] - tp.item->data < tp.item->size)
|
||||
RtlCopyMemory(iroff, &ir->name[ir->n], tp.item->size - ((UINT8*)&ir->name[ir->n] - tp.item->data));
|
||||
|
||||
insert_tree_item(Vcb, subvol, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newir, newlen, NULL, rollback);
|
||||
insert_tree_item(Vcb, subvol, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newir, newlen, NULL, Irp, rollback);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1431,7 +1470,7 @@ NTSTATUS delete_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UIN
|
|||
searchkey.obj_type = TYPE_INODE_EXTREF;
|
||||
searchkey.offset = calc_crc32c((UINT32)parinode, (UINT8*)utf8->Buffer, utf8->Length);
|
||||
|
||||
Status = find_item(Vcb, subvol, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, subvol, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -1485,7 +1524,7 @@ NTSTATUS delete_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UIN
|
|||
if ((UINT8*)&ier->name[ier->n] - tp.item->data < tp.item->size)
|
||||
RtlCopyMemory(ieroff, &ier->name[ier->n], tp.item->size - ((UINT8*)&ier->name[ier->n] - tp.item->data));
|
||||
|
||||
insert_tree_item(Vcb, subvol, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newier, newlen, NULL, rollback);
|
||||
insert_tree_item(Vcb, subvol, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newier, newlen, NULL, Irp, rollback);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1612,7 +1651,7 @@ void send_notification_fcb(file_ref* fileref, ULONG filter_match, ULONG action)
|
|||
hardlink* hl = CONTAINING_RECORD(le, hardlink, list_entry);
|
||||
file_ref* parfr;
|
||||
|
||||
Status = open_fileref_by_inode(fcb->Vcb, fcb->subvol, hl->parent, &parfr);
|
||||
Status = open_fileref_by_inode(fcb->Vcb, fcb->subvol, hl->parent, &parfr, NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("open_fileref_by_inode returned %08x\n", Status);
|
||||
|
@ -1732,6 +1771,13 @@ void mark_fileref_dirty(file_ref* fileref) {
|
|||
void _free_fcb(fcb* fcb, const char* func, const char* file, unsigned int line) {
|
||||
LONG rc;
|
||||
|
||||
// #ifdef DEBUG
|
||||
// if (!ExIsResourceAcquiredExclusiveLite(&fcb->Vcb->fcb_lock) && !ExIsResourceAcquiredExclusiveLite(&fcb->Vcb->tree_lock)) {
|
||||
// ERR("fcb_lock not acquired exclusively\n");
|
||||
// int3;
|
||||
// }
|
||||
// #endif
|
||||
|
||||
rc = InterlockedDecrement(&fcb->refcount);
|
||||
|
||||
#ifdef DEBUG_FCB_REFCOUNTS
|
||||
|
@ -1746,7 +1792,7 @@ void _free_fcb(fcb* fcb, const char* func, const char* file, unsigned int line)
|
|||
if (rc > 0)
|
||||
return;
|
||||
|
||||
ExAcquireResourceExclusiveLite(&fcb->Vcb->fcb_lock, TRUE);
|
||||
// ExAcquireResourceExclusiveLite(&fcb->Vcb->fcb_lock, TRUE);
|
||||
|
||||
if (fcb->list_entry.Flink)
|
||||
RemoveEntryList(&fcb->list_entry);
|
||||
|
@ -1754,7 +1800,7 @@ void _free_fcb(fcb* fcb, const char* func, const char* file, unsigned int line)
|
|||
if (fcb->list_entry_all.Flink)
|
||||
RemoveEntryList(&fcb->list_entry_all);
|
||||
|
||||
ExReleaseResourceLite(&fcb->Vcb->fcb_lock);
|
||||
// ExReleaseResourceLite(&fcb->Vcb->fcb_lock);
|
||||
|
||||
ExDeleteResourceLite(&fcb->nonpaged->resource);
|
||||
ExDeleteResourceLite(&fcb->nonpaged->paging_resource);
|
||||
|
@ -1821,6 +1867,13 @@ 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) {
|
||||
LONG rc;
|
||||
|
||||
// #ifdef DEBUG
|
||||
// if (!ExIsResourceAcquiredExclusiveLite(&fr->fcb->Vcb->fcb_lock) && !ExIsResourceAcquiredExclusiveLite(&fr->fcb->Vcb->tree_lock) && !fr->dirty) {
|
||||
// ERR("fcb_lock not acquired exclusively\n");
|
||||
// int3;
|
||||
// }
|
||||
// #endif
|
||||
|
||||
rc = InterlockedDecrement(&fr->refcount);
|
||||
|
||||
#ifdef DEBUG_FCB_REFCOUNTS
|
||||
|
@ -1915,6 +1968,9 @@ static NTSTATUS STDCALL close_file(device_extension* Vcb, PFILE_OBJECT FileObjec
|
|||
|
||||
CcUninitializeCacheMap(FileObject, NULL, NULL);
|
||||
|
||||
if (!(Vcb->Vpb->Flags & VPB_MOUNTED))
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE);
|
||||
|
||||
if (fileref)
|
||||
|
@ -1935,9 +1991,9 @@ void STDCALL uninit(device_extension* Vcb, BOOL flush) {
|
|||
LIST_ENTRY* le;
|
||||
LARGE_INTEGER time;
|
||||
|
||||
#ifndef __REACTOS__
|
||||
Vcb->removing = TRUE;
|
||||
|
||||
RemoveEntryList(&Vcb->list_entry);
|
||||
#endif
|
||||
|
||||
Status = registry_mark_volume_unmounted(&Vcb->superblock.uuid);
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -1948,8 +2004,8 @@ void STDCALL uninit(device_extension* Vcb, BOOL flush) {
|
|||
|
||||
ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE);
|
||||
|
||||
if (Vcb->need_write)
|
||||
do_write(Vcb, &rollback);
|
||||
if (Vcb->need_write && !Vcb->readonly)
|
||||
do_write(Vcb, NULL, &rollback);
|
||||
|
||||
free_trees(Vcb);
|
||||
|
||||
|
@ -1969,8 +2025,6 @@ void STDCALL uninit(device_extension* Vcb, BOOL flush) {
|
|||
|
||||
ExFreePool(Vcb->threads.threads);
|
||||
|
||||
Vcb->removing = TRUE;
|
||||
|
||||
time.QuadPart = 0;
|
||||
KeSetTimer(&Vcb->flush_thread_timer, time, NULL); // trigger the timer early
|
||||
KeWaitForSingleObject(&Vcb->flush_thread_finished, Executive, KernelMode, FALSE, NULL);
|
||||
|
@ -2027,10 +2081,9 @@ void STDCALL uninit(device_extension* Vcb, BOOL flush) {
|
|||
if (c->cache)
|
||||
free_fcb(c->cache);
|
||||
|
||||
ExDeleteResourceLite(&c->nonpaged->lock);
|
||||
ExDeleteResourceLite(&c->nonpaged->changed_extents_lock);
|
||||
ExDeleteResourceLite(&c->lock);
|
||||
ExDeleteResourceLite(&c->changed_extents_lock);
|
||||
|
||||
ExFreePool(c->nonpaged);
|
||||
ExFreePool(c->chunk_item);
|
||||
ExFreePool(c);
|
||||
}
|
||||
|
@ -2064,7 +2117,7 @@ void STDCALL uninit(device_extension* Vcb, BOOL flush) {
|
|||
ZwClose(Vcb->flush_thread_handle);
|
||||
}
|
||||
|
||||
NTSTATUS delete_fileref(file_ref* fileref, PFILE_OBJECT FileObject, LIST_ENTRY* rollback) {
|
||||
NTSTATUS delete_fileref(file_ref* fileref, PFILE_OBJECT FileObject, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
LARGE_INTEGER newlength, time;
|
||||
BTRFS_TIME now;
|
||||
NTSTATUS Status;
|
||||
|
@ -2103,7 +2156,7 @@ NTSTATUS delete_fileref(file_ref* fileref, PFILE_OBJECT FileObject, LIST_ENTRY*
|
|||
// excise extents
|
||||
|
||||
if (fileref->fcb->type != BTRFS_TYPE_DIRECTORY && fileref->fcb->inode_item.st_size > 0) {
|
||||
Status = excise_extents(fileref->fcb->Vcb, fileref->fcb, 0, sector_align(fileref->fcb->inode_item.st_size, fileref->fcb->Vcb->superblock.sector_size), rollback);
|
||||
Status = excise_extents(fileref->fcb->Vcb, fileref->fcb, 0, sector_align(fileref->fcb->inode_item.st_size, fileref->fcb->Vcb->superblock.sector_size), Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("excise_extents returned %08x\n", Status);
|
||||
ExReleaseResourceLite(fileref->fcb->Header.Resource);
|
||||
|
@ -2265,7 +2318,7 @@ static NTSTATUS STDCALL drv_cleanup(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
|
||||
ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, TRUE);
|
||||
|
||||
Status = delete_fileref(fileref, FileObject, &rollback);
|
||||
Status = delete_fileref(fileref, FileObject, Irp, &rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("delete_fileref returned %08x\n", Status);
|
||||
do_rollback(Vcb, &rollback);
|
||||
|
@ -2319,14 +2372,14 @@ exit2:
|
|||
return Status;
|
||||
}
|
||||
|
||||
ULONG STDCALL get_file_attributes(device_extension* Vcb, INODE_ITEM* ii, root* r, UINT64 inode, UINT8 type, BOOL dotfile, BOOL ignore_xa) {
|
||||
ULONG STDCALL get_file_attributes(device_extension* Vcb, INODE_ITEM* ii, root* r, UINT64 inode, UINT8 type, BOOL dotfile, BOOL ignore_xa, PIRP Irp) {
|
||||
ULONG att;
|
||||
char* eaval;
|
||||
UINT16 ealen;
|
||||
|
||||
// ii can be NULL
|
||||
|
||||
if (!ignore_xa && get_xattr(Vcb, r, inode, EA_DOSATTRIB, EA_DOSATTRIB_HASH, (UINT8**)&eaval, &ealen)) {
|
||||
if (!ignore_xa && get_xattr(Vcb, r, inode, EA_DOSATTRIB, EA_DOSATTRIB_HASH, (UINT8**)&eaval, &ealen, Irp)) {
|
||||
if (ealen > 2) {
|
||||
if (eaval[0] == '0' && eaval[1] == 'x') {
|
||||
int i;
|
||||
|
@ -2388,7 +2441,7 @@ ULONG STDCALL get_file_attributes(device_extension* Vcb, INODE_ITEM* ii, root* r
|
|||
return att;
|
||||
}
|
||||
|
||||
NTSTATUS sync_read_phys(PDEVICE_OBJECT DeviceObject, LONGLONG StartingOffset, ULONG Length, PUCHAR Buffer) {
|
||||
static NTSTATUS sync_read_phys(PDEVICE_OBJECT DeviceObject, LONGLONG StartingOffset, ULONG Length, PUCHAR Buffer, BOOL override) {
|
||||
IO_STATUS_BLOCK* IoStatus;
|
||||
LARGE_INTEGER Offset;
|
||||
PIRP Irp;
|
||||
|
@ -2425,9 +2478,13 @@ NTSTATUS sync_read_phys(PDEVICE_OBJECT DeviceObject, LONGLONG StartingOffset, UL
|
|||
goto exit;
|
||||
}
|
||||
|
||||
Irp->Flags |= IRP_NOCACHE;
|
||||
IrpSp = IoGetNextIrpStackLocation(Irp);
|
||||
IrpSp->MajorFunction = IRP_MJ_READ;
|
||||
|
||||
if (override)
|
||||
IrpSp->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
|
||||
|
||||
if (DeviceObject->Flags & DO_BUFFERED_IO) {
|
||||
FIXME("FIXME - buffered IO\n");
|
||||
} else if (DeviceObject->Flags & DO_DIRECT_IO) {
|
||||
|
@ -2461,20 +2518,10 @@ NTSTATUS sync_read_phys(PDEVICE_OBJECT DeviceObject, LONGLONG StartingOffset, UL
|
|||
|
||||
IoSetCompletionRoutine(Irp, read_completion, context, TRUE, TRUE, TRUE);
|
||||
|
||||
// if (Override)
|
||||
// {
|
||||
// Stack = IoGetNextIrpStackLocation(Irp);
|
||||
// Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
|
||||
// }
|
||||
|
||||
// TRACE("Calling IO Driver... with irp %p\n", Irp);
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
|
||||
// TRACE("Waiting for IO Operation for %p\n", Irp);
|
||||
if (Status == STATUS_PENDING) {
|
||||
// TRACE("Operation pending\n");
|
||||
KeWaitForSingleObject(&context->Event, Executive, KernelMode, FALSE, NULL);
|
||||
// TRACE("Getting IO Status... for %p\n", Irp);
|
||||
Status = context->iosb.Status;
|
||||
}
|
||||
|
||||
|
@ -2512,7 +2559,7 @@ static NTSTATUS STDCALL read_superblock(device_extension* Vcb, PDEVICE_OBJECT de
|
|||
if (i > 0 && superblock_addrs[i] + sizeof(superblock) > length)
|
||||
break;
|
||||
|
||||
Status = sync_read_phys(device, superblock_addrs[i], to_read, (PUCHAR)sb);
|
||||
Status = sync_read_phys(device, superblock_addrs[i], to_read, (PUCHAR)sb, FALSE);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("Failed to read superblock %u: %08x\n", i, Status);
|
||||
ExFreePool(sb);
|
||||
|
@ -2646,7 +2693,7 @@ static NTSTATUS STDCALL add_root(device_extension* Vcb, UINT64 id, UINT64 addr,
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS STDCALL look_for_roots(device_extension* Vcb) {
|
||||
static NTSTATUS STDCALL look_for_roots(device_extension* Vcb, PIRP Irp) {
|
||||
traverse_ptr tp, next_tp;
|
||||
KEY searchkey;
|
||||
BOOL b;
|
||||
|
@ -2656,7 +2703,7 @@ static NTSTATUS STDCALL look_for_roots(device_extension* Vcb) {
|
|||
searchkey.obj_type = 0;
|
||||
searchkey.offset = 0;
|
||||
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_tree returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -2681,7 +2728,7 @@ static NTSTATUS STDCALL look_for_roots(device_extension* Vcb) {
|
|||
}
|
||||
}
|
||||
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE);
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE, Irp);
|
||||
|
||||
if (b)
|
||||
tp = next_tp;
|
||||
|
@ -2690,7 +2737,7 @@ static NTSTATUS STDCALL look_for_roots(device_extension* Vcb) {
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS find_disk_holes(device_extension* Vcb, device* dev) {
|
||||
static NTSTATUS find_disk_holes(device_extension* Vcb, device* dev, PIRP Irp) {
|
||||
KEY searchkey;
|
||||
traverse_ptr tp, next_tp;
|
||||
BOOL b;
|
||||
|
@ -2703,7 +2750,7 @@ static NTSTATUS find_disk_holes(device_extension* Vcb, device* dev) {
|
|||
searchkey.obj_type = TYPE_DEV_EXTENT;
|
||||
searchkey.offset = 0;
|
||||
|
||||
Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->dev_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_tree returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -2730,7 +2777,7 @@ static NTSTATUS find_disk_holes(device_extension* Vcb, device* dev) {
|
|||
}
|
||||
}
|
||||
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE);
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE, Irp);
|
||||
|
||||
if (b) {
|
||||
tp = next_tp;
|
||||
|
@ -2858,7 +2905,7 @@ static void init_device(device_extension* Vcb, device* dev, BOOL get_length) {
|
|||
}
|
||||
}
|
||||
|
||||
static NTSTATUS STDCALL load_chunk_root(device_extension* Vcb) {
|
||||
static NTSTATUS STDCALL load_chunk_root(device_extension* Vcb, PIRP Irp) {
|
||||
traverse_ptr tp, next_tp;
|
||||
KEY searchkey;
|
||||
BOOL b;
|
||||
|
@ -2872,7 +2919,7 @@ static NTSTATUS STDCALL load_chunk_root(device_extension* Vcb) {
|
|||
|
||||
Vcb->data_flags = 0;
|
||||
|
||||
Status = find_item(Vcb, Vcb->chunk_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->chunk_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -2950,33 +2997,24 @@ static NTSTATUS STDCALL load_chunk_root(device_extension* Vcb) {
|
|||
if (tp.item->size < sizeof(CHUNK_ITEM)) {
|
||||
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(CHUNK_ITEM));
|
||||
} else {
|
||||
c = ExAllocatePoolWithTag(PagedPool, sizeof(chunk), ALLOC_TAG);
|
||||
c = ExAllocatePoolWithTag(NonPagedPool, sizeof(chunk), ALLOC_TAG);
|
||||
|
||||
if (!c) {
|
||||
ERR("out of memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
c->nonpaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(chunk_nonpaged), ALLOC_TAG);
|
||||
|
||||
if (!c->nonpaged) {
|
||||
ERR("out of memory\n");
|
||||
ExFreePool(c);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
c->size = tp.item->size;
|
||||
c->offset = tp.item->key.offset;
|
||||
c->used = c->oldused = 0;
|
||||
c->cache = NULL;
|
||||
c->created = FALSE;
|
||||
|
||||
c->chunk_item = ExAllocatePoolWithTag(PagedPool, tp.item->size, ALLOC_TAG);
|
||||
c->chunk_item = ExAllocatePoolWithTag(NonPagedPool, tp.item->size, ALLOC_TAG);
|
||||
|
||||
if (!c->chunk_item) {
|
||||
ERR("out of memory\n");
|
||||
ExFreePool(c);
|
||||
ExFreePool(c->nonpaged);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
|
@ -2988,12 +3026,11 @@ static NTSTATUS STDCALL load_chunk_root(device_extension* Vcb) {
|
|||
if (c->chunk_item->num_stripes > 0) {
|
||||
CHUNK_ITEM_STRIPE* cis = (CHUNK_ITEM_STRIPE*)&c->chunk_item[1];
|
||||
|
||||
c->devices = ExAllocatePoolWithTag(PagedPool, sizeof(device*) * c->chunk_item->num_stripes, ALLOC_TAG);
|
||||
c->devices = ExAllocatePoolWithTag(NonPagedPool, sizeof(device*) * c->chunk_item->num_stripes, ALLOC_TAG);
|
||||
|
||||
if (!c->devices) {
|
||||
ERR("out of memory\n");
|
||||
ExFreePool(c);
|
||||
ExFreePool(c->nonpaged);
|
||||
ExFreePool(c->chunk_item);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
@ -3005,8 +3042,8 @@ static NTSTATUS STDCALL load_chunk_root(device_extension* Vcb) {
|
|||
} else
|
||||
c->devices = NULL;
|
||||
|
||||
ExInitializeResourceLite(&c->nonpaged->lock);
|
||||
ExInitializeResourceLite(&c->nonpaged->changed_extents_lock);
|
||||
ExInitializeResourceLite(&c->lock);
|
||||
ExInitializeResourceLite(&c->changed_extents_lock);
|
||||
|
||||
InitializeListHead(&c->space);
|
||||
InitializeListHead(&c->space_size);
|
||||
|
@ -3019,7 +3056,7 @@ static NTSTATUS STDCALL load_chunk_root(device_extension* Vcb) {
|
|||
}
|
||||
}
|
||||
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE);
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE, Irp);
|
||||
|
||||
if (b)
|
||||
tp = next_tp;
|
||||
|
@ -3094,7 +3131,7 @@ void protect_superblocks(device_extension* Vcb, chunk* c) {
|
|||
}
|
||||
}
|
||||
|
||||
static NTSTATUS STDCALL find_chunk_usage(device_extension* Vcb) {
|
||||
static NTSTATUS STDCALL find_chunk_usage(device_extension* Vcb, PIRP Irp) {
|
||||
LIST_ENTRY* le = Vcb->chunks.Flink;
|
||||
chunk* c;
|
||||
KEY searchkey;
|
||||
|
@ -3113,7 +3150,7 @@ static NTSTATUS STDCALL find_chunk_usage(device_extension* Vcb) {
|
|||
searchkey.obj_id = c->offset;
|
||||
searchkey.offset = c->chunk_item->size;
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -3141,7 +3178,7 @@ static NTSTATUS STDCALL find_chunk_usage(device_extension* Vcb) {
|
|||
// FIXME - make sure we free occasionally after doing one of these, or we
|
||||
// might use up a lot of memory with a big disk.
|
||||
|
||||
Status = load_free_space_cache(Vcb, c);
|
||||
Status = load_free_space_cache(Vcb, c, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("load_free_space_cache returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -3253,12 +3290,24 @@ static NTSTATUS load_sys_chunks(device_extension* Vcb) {
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static root* find_default_subvol(device_extension* Vcb) {
|
||||
static root* find_default_subvol(device_extension* Vcb, PIRP Irp) {
|
||||
LIST_ENTRY* le;
|
||||
|
||||
static char fn[] = "default";
|
||||
static UINT32 crc32 = 0x8dbfc2d2;
|
||||
|
||||
if (Vcb->options.subvol_id != 0) {
|
||||
le = Vcb->roots.Flink;
|
||||
while (le != &Vcb->roots) {
|
||||
root* r = CONTAINING_RECORD(le, root, list_entry);
|
||||
|
||||
if (r->id == Vcb->options.subvol_id)
|
||||
return r;
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_DEFAULT_SUBVOL) {
|
||||
NTSTATUS Status;
|
||||
KEY searchkey;
|
||||
|
@ -3269,7 +3318,7 @@ static root* find_default_subvol(device_extension* Vcb) {
|
|||
searchkey.obj_type = TYPE_DIR_ITEM;
|
||||
searchkey.offset = crc32;
|
||||
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
goto end;
|
||||
|
@ -3334,7 +3383,7 @@ static NTSTATUS create_worker_threads(PDEVICE_OBJECT DeviceObject) {
|
|||
ULONG i;
|
||||
NTSTATUS Status;
|
||||
|
||||
Vcb->threads.num_threads = max(3, KeQueryActiveProcessorCount(NULL)); // FIXME - number of processors?
|
||||
Vcb->threads.num_threads = max(3, KeQueryActiveProcessorCount(NULL));
|
||||
|
||||
Vcb->threads.threads = ExAllocatePoolWithTag(NonPagedPool, sizeof(drv_thread) * Vcb->threads.num_threads, ALLOC_TAG);
|
||||
if (!Vcb->threads.threads) {
|
||||
|
@ -3366,6 +3415,8 @@ static NTSTATUS create_worker_threads(PDEVICE_OBJECT DeviceObject) {
|
|||
}
|
||||
}
|
||||
|
||||
Vcb->threads.pending_jobs = 0;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -3375,6 +3426,9 @@ BOOL add_thread_job(device_extension* Vcb, PIRP Irp) {
|
|||
|
||||
threadnum = InterlockedIncrement(&Vcb->threads.next_thread) % Vcb->threads.num_threads;
|
||||
|
||||
if (Vcb->threads.pending_jobs >= Vcb->threads.num_threads)
|
||||
return FALSE;
|
||||
|
||||
if (Vcb->threads.threads[threadnum].quit)
|
||||
return FALSE;
|
||||
|
||||
|
@ -3388,6 +3442,8 @@ BOOL add_thread_job(device_extension* Vcb, PIRP Irp) {
|
|||
|
||||
tj->Irp = Irp;
|
||||
|
||||
InterlockedIncrement(&Vcb->threads.pending_jobs);
|
||||
|
||||
ExInterlockedInsertTailList(&Vcb->threads.threads[threadnum].jobs, &tj->list_entry, &Vcb->threads.threads[threadnum].spin_lock);
|
||||
KeSetEvent(&Vcb->threads.threads[threadnum].event, 0, FALSE);
|
||||
|
||||
|
@ -3527,7 +3583,7 @@ static NTSTATUS STDCALL mount_vol(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
TRACE("btrfs magic found\n");
|
||||
}
|
||||
|
||||
Status = registry_load_volume_options(&Vcb->superblock.uuid, &Vcb->options);
|
||||
Status = registry_load_volume_options(Vcb);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("registry_load_volume_options returned %08x\n", Status);
|
||||
goto exit;
|
||||
|
@ -3564,10 +3620,13 @@ static NTSTATUS STDCALL mount_vol(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
Vcb->readonly = TRUE;
|
||||
}
|
||||
|
||||
if (Vcb->options.readonly)
|
||||
Vcb->readonly = TRUE;
|
||||
|
||||
Vcb->superblock.generation++;
|
||||
Vcb->superblock.incompat_flags |= BTRFS_INCOMPAT_FLAGS_MIXED_BACKREF;
|
||||
|
||||
Vcb->devices = ExAllocatePoolWithTag(PagedPool, sizeof(device) * Vcb->superblock.num_devices, ALLOC_TAG);
|
||||
Vcb->devices = ExAllocatePoolWithTag(NonPagedPool, sizeof(device) * Vcb->superblock.num_devices, ALLOC_TAG);
|
||||
if (!Vcb->devices) {
|
||||
ERR("out of memory\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
@ -3595,8 +3654,6 @@ static NTSTATUS STDCALL mount_vol(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
|
||||
Vcb->log_to_phys_loaded = FALSE;
|
||||
|
||||
Vcb->max_inline = Vcb->superblock.node_size / 2;
|
||||
|
||||
add_root(Vcb, BTRFS_ROOT_CHUNK, Vcb->superblock.chunk_tree_addr, NULL);
|
||||
|
||||
if (!Vcb->chunk_root) {
|
||||
|
@ -3629,7 +3686,7 @@ static NTSTATUS STDCALL mount_vol(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
|
||||
FsRtlNotifyInitializeSync(&Vcb->NotifySync);
|
||||
|
||||
Status = load_chunk_root(Vcb);
|
||||
Status = load_chunk_root(Vcb, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("load_chunk_root returned %08x\n", Status);
|
||||
goto exit;
|
||||
|
@ -3663,29 +3720,31 @@ static NTSTATUS STDCALL mount_vol(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
goto exit;
|
||||
}
|
||||
|
||||
Status = look_for_roots(Vcb);
|
||||
Status = look_for_roots(Vcb, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("look_for_roots returned %08x\n", Status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Status = find_chunk_usage(Vcb);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("find_chunk_usage returned %08x\n", Status);
|
||||
goto exit;
|
||||
if (!Vcb->readonly) {
|
||||
Status = find_chunk_usage(Vcb, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("find_chunk_usage returned %08x\n", Status);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
// We've already increased the generation by one
|
||||
if (!Vcb->readonly && Vcb->superblock.generation - 1 != Vcb->superblock.cache_generation) {
|
||||
WARN("generation was %llx, free-space cache generation was %llx; clearing cache...\n", Vcb->superblock.generation - 1, Vcb->superblock.cache_generation);
|
||||
Status = clear_free_space_cache(Vcb);
|
||||
Status = clear_free_space_cache(Vcb, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("clear_free_space_cache returned %08x\n", Status);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
Vcb->volume_fcb = create_fcb();
|
||||
Vcb->volume_fcb = create_fcb(NonPagedPool);
|
||||
if (!Vcb->volume_fcb) {
|
||||
ERR("out of memory\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
@ -3695,7 +3754,7 @@ static NTSTATUS STDCALL mount_vol(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
Vcb->volume_fcb->Vcb = Vcb;
|
||||
Vcb->volume_fcb->sd = NULL;
|
||||
|
||||
root_fcb = create_fcb();
|
||||
root_fcb = create_fcb(NonPagedPool);
|
||||
if (!root_fcb) {
|
||||
ERR("out of memory\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
@ -3711,7 +3770,7 @@ static NTSTATUS STDCALL mount_vol(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
WARN("root FCB = %p\n", root_fcb);
|
||||
#endif
|
||||
|
||||
root_fcb->subvol = find_default_subvol(Vcb);
|
||||
root_fcb->subvol = find_default_subvol(Vcb, Irp);
|
||||
|
||||
if (!root_fcb->subvol) {
|
||||
ERR("could not find top subvol\n");
|
||||
|
@ -3723,7 +3782,7 @@ static NTSTATUS STDCALL mount_vol(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
searchkey.obj_type = TYPE_INODE_ITEM;
|
||||
searchkey.offset = 0xffffffffffffffff;
|
||||
|
||||
Status = find_item(Vcb, root_fcb->subvol, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, root_fcb->subvol, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
goto exit;
|
||||
|
@ -3738,9 +3797,9 @@ static NTSTATUS STDCALL mount_vol(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
if (tp.item->size > 0)
|
||||
RtlCopyMemory(&root_fcb->inode_item, tp.item->data, min(sizeof(INODE_ITEM), tp.item->size));
|
||||
|
||||
fcb_get_sd(root_fcb, NULL);
|
||||
fcb_get_sd(root_fcb, NULL, Irp);
|
||||
|
||||
root_fcb->atts = get_file_attributes(Vcb, &root_fcb->inode_item, root_fcb->subvol, root_fcb->inode, root_fcb->type, FALSE, FALSE);
|
||||
root_fcb->atts = get_file_attributes(Vcb, &root_fcb->inode_item, root_fcb->subvol, root_fcb->inode, root_fcb->type, FALSE, FALSE, Irp);
|
||||
|
||||
Vcb->root_fileref = create_fileref();
|
||||
if (!Vcb->root_fileref) {
|
||||
|
@ -3764,18 +3823,13 @@ static NTSTATUS STDCALL mount_vol(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
|
||||
Vcb->root_file = IoCreateStreamFileObject(NULL, DeviceToMount);
|
||||
Vcb->root_file->FsContext = root_fcb;
|
||||
#ifdef __REACTOS__
|
||||
Vcb->root_file->SectionObjectPointer = &root_fcb->nonpaged->segment_object;
|
||||
Vcb->root_file->Vpb = DeviceObject->Vpb;
|
||||
#endif
|
||||
|
||||
RtlZeroMemory(root_ccb, sizeof(ccb));
|
||||
root_ccb->NodeType = BTRFS_NODE_TYPE_CCB;
|
||||
root_ccb->NodeSize = sizeof(ccb);
|
||||
|
||||
#ifndef __REACTOS__
|
||||
Vcb->root_file->FsContext = root_ccb;
|
||||
#else
|
||||
Vcb->root_file->FsContext2 = root_ccb;
|
||||
|
||||
_SEH2_TRY {
|
||||
|
@ -3784,10 +3838,9 @@ static NTSTATUS STDCALL mount_vol(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
Status = _SEH2_GetExceptionCode();
|
||||
goto exit;
|
||||
} _SEH2_END;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < Vcb->superblock.num_devices; i++) {
|
||||
Status = find_disk_holes(Vcb, &Vcb->devices[i]);
|
||||
Status = find_disk_holes(Vcb, &Vcb->devices[i], Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("find_disk_holes returned %08x\n", Status);
|
||||
goto exit;
|
||||
|
@ -3867,6 +3920,92 @@ exit:
|
|||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS verify_volume(PDEVICE_OBJECT device) {
|
||||
device_extension* Vcb = device->DeviceExtension;
|
||||
ULONG cc, to_read;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
NTSTATUS Status;
|
||||
superblock* sb;
|
||||
UINT32 crc32;
|
||||
UINT64 i;
|
||||
|
||||
if (Vcb->removing)
|
||||
return STATUS_WRONG_VOLUME;
|
||||
|
||||
Status = dev_ioctl(Vcb->Vpb->RealDevice, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, &cc, sizeof(ULONG), TRUE, &iosb);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("dev_ioctl returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
to_read = sector_align(sizeof(superblock), device->SectorSize);
|
||||
|
||||
sb = ExAllocatePoolWithTag(NonPagedPool, to_read, ALLOC_TAG);
|
||||
if (!sb) {
|
||||
ERR("out of memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Status = sync_read_phys(Vcb->Vpb->RealDevice, superblock_addrs[0], to_read, (PUCHAR)sb, TRUE);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("Failed to read superblock: %08x\n", Status);
|
||||
ExFreePool(sb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (sb->magic != BTRFS_MAGIC) {
|
||||
ERR("not a BTRFS volume\n");
|
||||
ExFreePool(sb);
|
||||
return STATUS_WRONG_VOLUME;
|
||||
}
|
||||
|
||||
if (RtlCompareMemory(&sb->uuid, &Vcb->superblock.uuid, sizeof(BTRFS_UUID)) != sizeof(BTRFS_UUID)) {
|
||||
ERR("different UUIDs\n");
|
||||
ExFreePool(sb);
|
||||
return STATUS_WRONG_VOLUME;
|
||||
}
|
||||
|
||||
crc32 = ~calc_crc32c(0xffffffff, (UINT8*)&sb->uuid, (ULONG)sizeof(superblock) - sizeof(sb->checksum));
|
||||
TRACE("crc32 was %08x, expected %08x\n", crc32, *((UINT32*)sb->checksum));
|
||||
|
||||
if (crc32 != *((UINT32*)sb->checksum)) {
|
||||
ERR("different UUIDs\n");
|
||||
ExFreePool(sb);
|
||||
return STATUS_WRONG_VOLUME;
|
||||
}
|
||||
|
||||
ExFreePool(sb);
|
||||
|
||||
for (i = 0; i < Vcb->superblock.num_devices; i++) {
|
||||
if (Vcb->devices[i].removable) {
|
||||
NTSTATUS Status;
|
||||
ULONG cc;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
|
||||
Status = dev_ioctl(Vcb->devices[i].devobj, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, &cc, sizeof(ULONG), TRUE, &iosb);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("dev_ioctl returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (iosb.Information < sizeof(ULONG)) {
|
||||
ERR("iosb.Information was too short\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
Vcb->devices[i].change_count = cc;
|
||||
}
|
||||
|
||||
Vcb->devices[i].devobj->Flags &= ~DO_VERIFY_VOLUME;
|
||||
}
|
||||
|
||||
Vcb->Vpb->RealDevice->Flags &= ~DO_VERIFY_VOLUME;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS STDCALL drv_file_system_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
NTSTATUS Status;
|
||||
|
@ -3910,7 +4049,15 @@ static NTSTATUS STDCALL drv_file_system_control(IN PDEVICE_OBJECT DeviceObject,
|
|||
break;
|
||||
|
||||
case IRP_MN_VERIFY_VOLUME:
|
||||
FIXME("STUB: IRP_MN_VERIFY_VOLUME\n");
|
||||
TRACE("IRP_MN_VERIFY_VOLUME\n");
|
||||
|
||||
Status = verify_volume(DeviceObject);
|
||||
|
||||
if (!NT_SUCCESS(Status) && Vcb->Vpb->Flags & VPB_MOUNTED) {
|
||||
uninit(Vcb, FALSE);
|
||||
// Vcb->Vpb->Flags &= ~VPB_MOUNTED;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -4136,8 +4283,7 @@ static NTSTATUS STDCALL drv_shutdown(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp
|
|||
Status = STATUS_SUCCESS;
|
||||
|
||||
while (!IsListEmpty(&VcbList)) {
|
||||
LIST_ENTRY* le = RemoveHeadList(&VcbList);
|
||||
Vcb = CONTAINING_RECORD(le, device_extension, list_entry);
|
||||
Vcb = CONTAINING_RECORD(VcbList.Flink, device_extension, list_entry);
|
||||
|
||||
TRACE("shutting down Vcb %p\n", Vcb);
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ BEGIN
|
|||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016"
|
||||
VALUE "OriginalFilename", "btrfs.sys"
|
||||
VALUE "ProductName", "WinBtrfs"
|
||||
VALUE "ProductVersion", "0.5"
|
||||
VALUE "ProductVersion", "0.6"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#define BTRFS_NODE_TYPE_FCB 0x2296
|
||||
|
||||
#define ALLOC_TAG 0x7442484D //'MHBt'
|
||||
#define ALLOC_TAG_ZLIB 0x7A42484D //'MHBz'
|
||||
|
||||
#define STDCALL __stdcall
|
||||
|
||||
|
@ -71,9 +72,10 @@
|
|||
#define EA_REPARSE "system.reparse"
|
||||
#define EA_REPARSE_HASH 0x786f6167
|
||||
|
||||
#define READ_AHEAD_GRANULARITY 0x10000 // 64 KB
|
||||
|
||||
#define MAX_EXTENT_SIZE 0x8000000 // 128 MB
|
||||
#define COMPRESSED_EXTENT_SIZE 0x20000 // 128 KB
|
||||
|
||||
#define READ_AHEAD_GRANULARITY COMPRESSED_EXTENT_SIZE // really ought to be a multiple of COMPRESSED_EXTENT_SIZE
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define try __try
|
||||
|
@ -87,7 +89,7 @@
|
|||
|
||||
// #pragma pack(push, 1)
|
||||
|
||||
struct device_extension;
|
||||
struct _device_extension;
|
||||
|
||||
typedef struct {
|
||||
BTRFS_UUID fsuuid;
|
||||
|
@ -176,6 +178,7 @@ typedef struct _fcb {
|
|||
|
||||
BOOL ads;
|
||||
UINT32 adshash;
|
||||
ULONG adsmaxlen;
|
||||
ANSI_STRING adsxattr;
|
||||
ANSI_STRING adsdata;
|
||||
|
||||
|
@ -344,11 +347,6 @@ typedef struct {
|
|||
LIST_ENTRY space;
|
||||
} device;
|
||||
|
||||
typedef struct {
|
||||
ERESOURCE lock;
|
||||
ERESOURCE changed_extents_lock;
|
||||
} chunk_nonpaged;
|
||||
|
||||
typedef struct {
|
||||
CHUNK_ITEM* chunk_item;
|
||||
UINT32 size;
|
||||
|
@ -361,7 +359,8 @@ typedef struct {
|
|||
LIST_ENTRY space_size;
|
||||
LIST_ENTRY deleting;
|
||||
LIST_ENTRY changed_extents;
|
||||
chunk_nonpaged* nonpaged;
|
||||
ERESOURCE lock;
|
||||
ERESOURCE changed_extents_lock;
|
||||
BOOL created;
|
||||
|
||||
LIST_ENTRY list_entry;
|
||||
|
@ -424,10 +423,19 @@ typedef struct {
|
|||
ULONG num_threads;
|
||||
LONG next_thread;
|
||||
drv_thread* threads;
|
||||
LONG pending_jobs;
|
||||
} drv_threads;
|
||||
|
||||
typedef struct {
|
||||
BOOL ignore;
|
||||
BOOL compress;
|
||||
BOOL compress_force;
|
||||
UINT8 compress_type;
|
||||
BOOL readonly;
|
||||
UINT32 zlib_level;
|
||||
UINT32 flush_interval;
|
||||
UINT32 max_inline;
|
||||
UINT64 subvol_id;
|
||||
} mount_options;
|
||||
|
||||
#define VCB_TYPE_VOLUME 1
|
||||
|
@ -471,7 +479,6 @@ typedef struct _device_extension {
|
|||
root* dev_root;
|
||||
root* uuid_root;
|
||||
BOOL log_to_phys_loaded;
|
||||
UINT32 max_inline;
|
||||
LIST_ENTRY sys_chunks;
|
||||
LIST_ENTRY chunks;
|
||||
LIST_ENTRY chunks_changed;
|
||||
|
@ -528,10 +535,10 @@ enum write_data_status {
|
|||
WriteDataStatus_Ignore
|
||||
};
|
||||
|
||||
struct write_data_context;
|
||||
struct _write_data_context;
|
||||
|
||||
typedef struct {
|
||||
struct write_data_context* context;
|
||||
struct _write_data_context* context;
|
||||
UINT8* buf;
|
||||
BOOL need_free;
|
||||
device* device;
|
||||
|
@ -541,7 +548,7 @@ typedef struct {
|
|||
LIST_ENTRY list_entry;
|
||||
} write_data_stripe;
|
||||
|
||||
typedef struct {
|
||||
typedef struct _write_data_context {
|
||||
KEVENT Event;
|
||||
LIST_ENTRY stripes;
|
||||
LONG stripes_left;
|
||||
|
@ -596,7 +603,7 @@ static __inline void get_raid0_offset(UINT64 off, UINT64 stripe_length, UINT16 n
|
|||
startoff = off % (num_stripes * stripe_length);
|
||||
initoff = (off / (num_stripes * stripe_length)) * stripe_length;
|
||||
|
||||
*stripe = startoff / stripe_length;
|
||||
*stripe = (UINT16)(startoff / stripe_length);
|
||||
*stripeoff = initoff + startoff - (*stripe * stripe_length);
|
||||
}
|
||||
|
||||
|
@ -604,19 +611,19 @@ static __inline void get_raid0_offset(UINT64 off, UINT64 stripe_length, UINT16 n
|
|||
device* find_device_from_uuid(device_extension* Vcb, BTRFS_UUID* uuid);
|
||||
UINT64 sector_align( UINT64 NumberToBeAligned, UINT64 Alignment );
|
||||
int keycmp(const KEY* key1, const KEY* key2);
|
||||
ULONG STDCALL get_file_attributes(device_extension* Vcb, INODE_ITEM* ii, root* r, UINT64 inode, UINT8 type, BOOL dotfile, BOOL ignore_xa);
|
||||
BOOL STDCALL get_xattr(device_extension* Vcb, root* subvol, UINT64 inode, char* name, UINT32 crc32, UINT8** data, UINT16* datalen);
|
||||
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 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);
|
||||
BOOL STDCALL get_last_inode(device_extension* Vcb, root* r);
|
||||
NTSTATUS add_dir_item(device_extension* Vcb, root* subvol, UINT64 inode, UINT32 crc32, DIR_ITEM* di, ULONG disize, LIST_ENTRY* rollback);
|
||||
NTSTATUS delete_dir_item(device_extension* Vcb, root* subvol, UINT64 parinode, UINT32 crc32, PANSI_STRING utf8, LIST_ENTRY* rollback);
|
||||
NTSTATUS delete_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, PANSI_STRING utf8, LIST_ENTRY* rollback);
|
||||
fcb* create_fcb();
|
||||
BOOL STDCALL get_last_inode(device_extension* Vcb, root* r, PIRP Irp);
|
||||
NTSTATUS add_dir_item(device_extension* Vcb, root* subvol, UINT64 inode, UINT32 crc32, DIR_ITEM* di, ULONG disize, PIRP Irp, LIST_ENTRY* rollback);
|
||||
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);
|
||||
BOOL is_top_level(PIRP Irp);
|
||||
NTSTATUS create_root(device_extension* Vcb, UINT64 id, root** rootptr, BOOL no_tree, UINT64 offset, LIST_ENTRY* rollback);
|
||||
NTSTATUS create_root(device_extension* Vcb, UINT64 id, root** rootptr, BOOL no_tree, UINT64 offset, PIRP Irp, LIST_ENTRY* rollback);
|
||||
void STDCALL uninit(device_extension* Vcb, BOOL flush);
|
||||
NTSTATUS STDCALL dev_ioctl(PDEVICE_OBJECT DeviceObject, ULONG ControlCode, PVOID InputBuffer,
|
||||
ULONG InputBufferSize, PVOID OutputBuffer, ULONG OutputBufferSize, BOOLEAN Override, IO_STATUS_BLOCK* iosb);
|
||||
|
@ -629,7 +636,7 @@ BOOL add_thread_job(device_extension* Vcb, PIRP Irp);
|
|||
NTSTATUS part0_passthrough(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
|
||||
void mark_fcb_dirty(fcb* fcb);
|
||||
void mark_fileref_dirty(file_ref* fileref);
|
||||
NTSTATUS delete_fileref(file_ref* fileref, PFILE_OBJECT FileObject, LIST_ENTRY* rollback);
|
||||
NTSTATUS delete_fileref(file_ref* fileref, PFILE_OBJECT FileObject, PIRP Irp, LIST_ENTRY* rollback);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define funcname __FUNCTION__
|
||||
|
@ -641,6 +648,13 @@ NTSTATUS delete_fileref(file_ref* fileref, PFILE_OBJECT FileObject, LIST_ENTRY*
|
|||
#define free_fcb(fcb) _free_fcb(fcb, funcname, __FILE__, __LINE__)
|
||||
#define free_fileref(fileref) _free_fileref(fileref, funcname, __FILE__, __LINE__)
|
||||
|
||||
extern UINT32 mount_compress;
|
||||
extern UINT32 mount_compress_force;
|
||||
extern UINT32 mount_compress_type;
|
||||
extern UINT32 mount_zlib_level;
|
||||
extern UINT32 mount_flush_interval;
|
||||
extern UINT32 mount_max_inline;
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
extern BOOL log_started;
|
||||
|
@ -696,34 +710,50 @@ void STDCALL init_fast_io_dispatch(FAST_IO_DISPATCH** fiod);
|
|||
// in crc32c.c
|
||||
UINT32 STDCALL calc_crc32c(UINT32 seed, UINT8* msg, ULONG msglen);
|
||||
|
||||
typedef struct {
|
||||
LIST_ENTRY* list;
|
||||
LIST_ENTRY* list_size;
|
||||
UINT64 address;
|
||||
UINT64 length;
|
||||
chunk* chunk;
|
||||
} rollback_space;
|
||||
|
||||
typedef struct {
|
||||
fcb* fcb;
|
||||
extent* ext;
|
||||
} rollback_extent;
|
||||
|
||||
enum rollback_type {
|
||||
ROLLBACK_INSERT_ITEM,
|
||||
ROLLBACK_DELETE_ITEM,
|
||||
ROLLBACK_INSERT_EXTENT,
|
||||
ROLLBACK_DELETE_EXTENT
|
||||
ROLLBACK_DELETE_EXTENT,
|
||||
ROLLBACK_ADD_SPACE,
|
||||
ROLLBACK_SUBTRACT_SPACE
|
||||
};
|
||||
|
||||
// in treefuncs.c
|
||||
NTSTATUS STDCALL _find_item(device_extension* Vcb, root* r, traverse_ptr* tp, const KEY* searchkey, BOOL ignore, 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, 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, const char* func, const char* file, unsigned int line);
|
||||
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);
|
||||
BOOL STDCALL _find_next_item(device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* next_tp, BOOL ignore, PIRP Irp, const char* func, const char* file, unsigned int line);
|
||||
BOOL STDCALL _find_prev_item(device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* prev_tp, BOOL ignore, PIRP Irp, const char* func, const char* file, unsigned int line);
|
||||
void STDCALL free_trees(device_extension* Vcb);
|
||||
BOOL STDCALL insert_tree_item(device_extension* Vcb, root* r, UINT64 obj_id, UINT8 obj_type, UINT64 offset, void* data, UINT32 size, traverse_ptr* ptp, LIST_ENTRY* rollback);
|
||||
BOOL STDCALL insert_tree_item(device_extension* Vcb, root* r, UINT64 obj_id, UINT8 obj_type, UINT64 offset, void* data, UINT32 size, traverse_ptr* ptp, PIRP Irp, LIST_ENTRY* rollback);
|
||||
void STDCALL delete_tree_item(device_extension* Vcb, traverse_ptr* tp, LIST_ENTRY* rollback);
|
||||
tree* STDCALL _free_tree(tree* t, const char* func, const char* file, unsigned int line);
|
||||
NTSTATUS STDCALL _load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, tree* parent, const char* func, const char* file, unsigned int line);
|
||||
NTSTATUS STDCALL _do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, BOOL* loaded, const char* func, const char* file, unsigned int line);
|
||||
NTSTATUS STDCALL _load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, tree* parent, PIRP Irp, const char* func, const char* file, unsigned int line);
|
||||
NTSTATUS STDCALL _do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, BOOL* loaded, PIRP Irp,
|
||||
const char* func, const char* file, unsigned int line);
|
||||
void clear_rollback(LIST_ENTRY* rollback);
|
||||
void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback);
|
||||
void free_trees_root(device_extension* Vcb, root* r);
|
||||
void add_rollback(LIST_ENTRY* rollback, enum rollback_type type, void* ptr);
|
||||
|
||||
#define find_item(Vcb, r, tp, searchkey, ignore) _find_item(Vcb, r, tp, searchkey, ignore, funcname, __FILE__, __LINE__)
|
||||
#define find_next_item(Vcb, tp, next_tp, ignore) _find_next_item(Vcb, tp, next_tp, ignore, funcname, __FILE__, __LINE__)
|
||||
#define find_prev_item(Vcb, tp, prev_tp, ignore) _find_prev_item(Vcb, tp, prev_tp, ignore, funcname, __FILE__, __LINE__)
|
||||
#define find_item(Vcb, r, tp, searchkey, ignore, Irp) _find_item(Vcb, r, tp, searchkey, ignore, Irp, funcname, __FILE__, __LINE__)
|
||||
#define find_next_item(Vcb, tp, next_tp, ignore, Irp) _find_next_item(Vcb, tp, next_tp, ignore, Irp, funcname, __FILE__, __LINE__)
|
||||
#define find_prev_item(Vcb, tp, prev_tp, ignore, Irp) _find_prev_item(Vcb, tp, prev_tp, ignore, Irp, funcname, __FILE__, __LINE__)
|
||||
#define free_tree(t) _free_tree(t, funcname, __FILE__, __LINE__)
|
||||
#define load_tree(t, addr, r, pt, parent) _load_tree(t, addr, r, pt, parent, funcname, __FILE__, __LINE__)
|
||||
#define do_load_tree(Vcb, th, r, t, td, loaded) _do_load_tree(Vcb, th, r, t, td, loaded, funcname, __FILE__, __LINE__)
|
||||
#define load_tree(t, addr, r, pt, parent, Irp) _load_tree(t, addr, r, pt, parent, Irp, funcname, __FILE__, __LINE__)
|
||||
#define do_load_tree(Vcb, th, r, t, td, loaded, Irp) _do_load_tree(Vcb, th, r, t, td, loaded, Irp, funcname, __FILE__, __LINE__)
|
||||
|
||||
// in search.c
|
||||
void STDCALL look_for_vols(PDRIVER_OBJECT DriverObject, LIST_ENTRY* volumes);
|
||||
|
@ -734,51 +764,52 @@ void STDCALL free_cache();
|
|||
extern CACHE_MANAGER_CALLBACKS* cache_callbacks;
|
||||
|
||||
// in write.c
|
||||
NTSTATUS STDCALL do_write(device_extension* Vcb, LIST_ENTRY* rollback);
|
||||
NTSTATUS STDCALL do_write(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback);
|
||||
NTSTATUS write_file(device_extension* Vcb, PIRP Irp, BOOL wait, BOOL deferred_write);
|
||||
NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void* buf, ULONG* length, BOOL paging_io, BOOL no_cache,
|
||||
BOOL wait, BOOL deferred_write, LIST_ENTRY* rollback);
|
||||
NTSTATUS truncate_file(fcb* fcb, UINT64 end, LIST_ENTRY* rollback);
|
||||
NTSTATUS truncate_file(fcb* fcb, UINT64 end, PIRP Irp, LIST_ENTRY* rollback);
|
||||
NTSTATUS extend_file(fcb* fcb, file_ref* fileref, UINT64 end, BOOL prealloc, PIRP Irp, LIST_ENTRY* rollback);
|
||||
NTSTATUS excise_extents(device_extension* Vcb, fcb* fcb, UINT64 start_data, UINT64 end_data, 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);
|
||||
NTSTATUS insert_sparse_extent(fcb* fcb, UINT64 start, UINT64 length, LIST_ENTRY* rollback);
|
||||
chunk* get_chunk_from_address(device_extension* Vcb, UINT64 address);
|
||||
chunk* alloc_chunk(device_extension* Vcb, UINT64 flags, LIST_ENTRY* rollback);
|
||||
NTSTATUS STDCALL write_data(device_extension* Vcb, UINT64 address, void* data, BOOL need_free, UINT32 length, write_data_context* wtc, PIRP Irp);
|
||||
NTSTATUS STDCALL write_data_complete(device_extension* Vcb, UINT64 address, void* data, UINT32 length, PIRP Irp);
|
||||
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 get_tree_new_address(device_extension* Vcb, tree* t, LIST_ENTRY* rollback);
|
||||
NTSTATUS get_tree_new_address(device_extension* Vcb, tree* t, PIRP Irp, LIST_ENTRY* rollback);
|
||||
NTSTATUS STDCALL drv_write(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
|
||||
void flush_fcb(fcb* fcb, BOOL cache, LIST_ENTRY* rollback);
|
||||
void flush_fcb(fcb* fcb, BOOL cache, PIRP Irp, LIST_ENTRY* rollback);
|
||||
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,
|
||||
PIRP Irp, LIST_ENTRY* rollback);
|
||||
NTSTATUS do_nocow_write(device_extension* Vcb, fcb* fcb, UINT64 start_data, UINT64 end_data, void* data, LIST_ENTRY* changed_sector_list, PIRP Irp, LIST_ENTRY* rollback);
|
||||
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);
|
||||
void remove_fcb_extent(extent* ext, LIST_ENTRY* rollback);
|
||||
NTSTATUS update_changed_extent_ref(device_extension* Vcb, chunk* c, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset,
|
||||
signed long long count, BOOL no_csum, UINT64 new_size);
|
||||
signed long long count, BOOL no_csum, UINT64 new_size, PIRP Irp);
|
||||
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);
|
||||
|
||||
// in dirctrl.c
|
||||
NTSTATUS STDCALL drv_directory_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
|
||||
ULONG STDCALL get_reparse_tag(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 type, ULONG atts, PIRP Irp);
|
||||
|
||||
// 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);
|
||||
void fcb_get_sd(fcb* fcb, struct _fcb* parent, PIRP Irp);
|
||||
// UINT32 STDCALL get_uid();
|
||||
void add_user_mapping(WCHAR* sidstring, ULONG sidstringlength, UINT32 uid);
|
||||
UINT32 sid_to_uid(PSID sid);
|
||||
void uid_to_sid(UINT32 uid, PSID* sid);
|
||||
NTSTATUS fcb_get_new_sd(fcb* fcb, file_ref* parfileref, ACCESS_STATE* as);
|
||||
|
||||
// in fileinfo.c
|
||||
NTSTATUS STDCALL drv_set_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
|
||||
NTSTATUS STDCALL drv_query_information(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
|
||||
NTSTATUS add_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, UINT64 index, PANSI_STRING utf8, LIST_ENTRY* rollback);
|
||||
NTSTATUS add_inode_ref(device_extension* Vcb, root* subvol, UINT64 inode, UINT64 parinode, UINT64 index, PANSI_STRING utf8, PIRP Irp, LIST_ENTRY* rollback);
|
||||
BOOL has_open_children(file_ref* fileref);
|
||||
NTSTATUS STDCALL stream_set_end_of_file_information(device_extension* Vcb, UINT64 end, fcb* fcb, file_ref* fileref, PFILE_OBJECT FileObject, BOOL advance_only, LIST_ENTRY* rollback);
|
||||
NTSTATUS fileref_get_filename(file_ref* fileref, PUNICODE_STRING fn, USHORT* name_offset);
|
||||
NTSTATUS open_fileref_by_inode(device_extension* Vcb, root* subvol, UINT64 inode, file_ref** pfr);
|
||||
NTSTATUS open_fileref_by_inode(device_extension* Vcb, root* subvol, UINT64 inode, file_ref** pfr, PIRP Irp);
|
||||
|
||||
// in reparse.c
|
||||
NTSTATUS get_reparse_point(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, void* buffer, DWORD buflen, DWORD* retlen);
|
||||
|
@ -787,15 +818,14 @@ 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_with_crc32(device_extension* Vcb, PUNICODE_STRING filename, UINT32 crc32, file_ref* fr, root** subvol,
|
||||
UINT64* inode, UINT8* type, UINT64* index, PANSI_STRING utf8);
|
||||
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);
|
||||
NTSTATUS open_fileref(device_extension* Vcb, file_ref** pfr, PUNICODE_STRING fnus, file_ref* related, BOOL parent, USHORT* unparsed);
|
||||
NTSTATUS open_fcb(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 type, PANSI_STRING utf8, fcb* parent, fcb** pfcb);
|
||||
NTSTATUS open_fcb_stream(device_extension* Vcb, root* subvol, UINT64 inode, ANSI_STRING* xattr, UINT32 streamhash, fcb* parent, fcb** pfcb);
|
||||
root** subvol, UINT64* inode, UINT8* type, UINT64* index, PANSI_STRING utf8, PIRP Irp);
|
||||
NTSTATUS open_fileref(device_extension* Vcb, file_ref** pfr, PUNICODE_STRING fnus, file_ref* related, BOOL parent, USHORT* unparsed, ULONG* fn_offset, PIRP Irp);
|
||||
NTSTATUS open_fcb(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 type, PANSI_STRING utf8, fcb* parent, fcb** pfcb, 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);
|
||||
NTSTATUS fcb_get_last_dir_index(fcb* fcb, UINT64* index, PIRP Irp);
|
||||
NTSTATUS verify_vcb(device_extension* Vcb, PIRP Irp);
|
||||
|
||||
// in fsctl.c
|
||||
NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP Irp, UINT32 type, BOOL user);
|
||||
|
@ -814,29 +844,29 @@ NTSTATUS do_read(PIRP Irp, BOOL wait, ULONG* bytes_read);
|
|||
NTSTATUS STDCALL drv_pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
|
||||
// in free-space.c
|
||||
NTSTATUS load_free_space_cache(device_extension* Vcb, chunk* c);
|
||||
NTSTATUS clear_free_space_cache(device_extension* Vcb);
|
||||
NTSTATUS allocate_cache(device_extension* Vcb, BOOL* changed, LIST_ENTRY* rollback);
|
||||
NTSTATUS update_chunk_caches(device_extension* Vcb, LIST_ENTRY* rollback);
|
||||
NTSTATUS load_free_space_cache(device_extension* Vcb, chunk* c, PIRP Irp);
|
||||
NTSTATUS clear_free_space_cache(device_extension* Vcb, PIRP Irp);
|
||||
NTSTATUS allocate_cache(device_extension* Vcb, BOOL* changed, PIRP Irp, LIST_ENTRY* rollback);
|
||||
NTSTATUS update_chunk_caches(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback);
|
||||
NTSTATUS add_space_entry(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 offset, UINT64 size);
|
||||
void _space_list_add(device_extension* Vcb, chunk* c, BOOL deleting, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func);
|
||||
void _space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func);
|
||||
void _space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, chunk* c, LIST_ENTRY* rollback, const char* func);
|
||||
void _space_list_subtract(device_extension* Vcb, chunk* c, BOOL deleting, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func);
|
||||
void _space_list_subtract2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func);
|
||||
void _space_list_subtract2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, chunk* c, LIST_ENTRY* rollback, const char* func);
|
||||
|
||||
#define space_list_add(Vcb, c, deleting, address, length, rollback) _space_list_add(Vcb, c, deleting, address, length, rollback, funcname)
|
||||
#define space_list_add2(list, list_size, address, length, rollback) _space_list_add2(list, list_size, address, length, rollback, funcname)
|
||||
#define space_list_add2(list, list_size, address, length, rollback) _space_list_add2(list, list_size, address, length, NULL, rollback, funcname)
|
||||
#define space_list_subtract(Vcb, c, deleting, address, length, rollback) _space_list_subtract(Vcb, c, deleting, address, length, rollback, funcname)
|
||||
#define space_list_subtract2(list, list_size, address, length, rollback) _space_list_subtract2(list, list_size, address, length, rollback, funcname)
|
||||
#define space_list_subtract2(list, list_size, address, length, rollback) _space_list_subtract2(list, list_size, address, length, NULL, rollback, funcname)
|
||||
|
||||
// in extent-tree.c
|
||||
NTSTATUS increase_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode, UINT64 offset, UINT32 refcount, LIST_ENTRY* rollback);
|
||||
NTSTATUS decrease_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode, UINT64 offset, UINT32 refcount, LIST_ENTRY* rollback);
|
||||
NTSTATUS decrease_extent_refcount_shared_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 treeaddr, UINT64 parent, LIST_ENTRY* rollback);
|
||||
NTSTATUS decrease_extent_refcount_old(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 treeaddr, LIST_ENTRY* rollback);
|
||||
NTSTATUS increase_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode, UINT64 offset, UINT32 refcount, PIRP Irp, 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_shared_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 treeaddr, UINT64 parent, PIRP Irp, LIST_ENTRY* rollback);
|
||||
NTSTATUS decrease_extent_refcount_old(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 treeaddr, 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, LIST_ENTRY* rollback);
|
||||
UINT64 find_extent_data_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset);
|
||||
NTSTATUS convert_old_data_extent(device_extension* Vcb, UINT64 address, UINT64 size, PIRP Irp, LIST_ENTRY* rollback);
|
||||
UINT64 find_extent_data_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset, PIRP Irp);
|
||||
|
||||
// in worker-thread.c
|
||||
void STDCALL worker_thread(void* context);
|
||||
|
@ -847,7 +877,11 @@ void do_write_job(device_extension* Vcb, PIRP Irp);
|
|||
void STDCALL read_registry(PUNICODE_STRING regpath);
|
||||
NTSTATUS registry_mark_volume_mounted(BTRFS_UUID* uuid);
|
||||
NTSTATUS registry_mark_volume_unmounted(BTRFS_UUID* uuid);
|
||||
NTSTATUS registry_load_volume_options(BTRFS_UUID* uuid, mount_options* options);
|
||||
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);
|
||||
|
||||
#define fast_io_possible(fcb) (!FsRtlAreThereCurrentFileLocks(&fcb->lock) && !fcb->Vcb->readonly ? FastIoIsPossible : FastIoIsQuestionable)
|
||||
|
||||
|
@ -874,6 +908,23 @@ static __inline void InsertAfter(LIST_ENTRY* head, LIST_ENTRY* item, LIST_ENTRY*
|
|||
head->Blink = item;
|
||||
}
|
||||
|
||||
static __inline BOOL write_fcb_compressed(fcb* fcb) {
|
||||
// make sure we don't accidentally write the cache inodes or pagefile compressed
|
||||
if (fcb->subvol->id == BTRFS_ROOT_ROOT || fcb->Header.Flags2 & FSRTL_FLAG2_IS_PAGING_FILE)
|
||||
return FALSE;
|
||||
|
||||
if (fcb->Vcb->options.compress_force)
|
||||
return TRUE;
|
||||
|
||||
if (fcb->inode_item.flags & BTRFS_INODE_NOCOMPRESS)
|
||||
return FALSE;
|
||||
|
||||
if (fcb->inode_item.flags & BTRFS_INODE_COMPRESS || fcb->Vcb->options.compress)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FCB_REFCOUNTS
|
||||
#ifdef DEBUG_LONG_MESSAGES
|
||||
#define increase_fileref_refcount(fileref) {\
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
// No copyright claimed in this file - do what you want with it.
|
||||
|
||||
#ifndef BTRFSIOCTL_H_DEFINED
|
||||
#define BTRFSIOCTL_H_DEFINED
|
||||
|
||||
#define FSCTL_BTRFS_GET_FILE_IDS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x829, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSCTL_BTRFS_CREATE_SUBVOL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82a, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
|
||||
#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)
|
||||
|
||||
typedef struct {
|
||||
UINT64 subvol;
|
||||
|
@ -17,4 +21,29 @@ typedef struct {
|
|||
WCHAR name[1];
|
||||
} btrfs_create_snapshot;
|
||||
|
||||
typedef struct {
|
||||
UINT64 subvol;
|
||||
UINT64 inode;
|
||||
BOOL top;
|
||||
UINT8 type;
|
||||
UINT32 st_uid;
|
||||
UINT32 st_gid;
|
||||
UINT32 st_mode;
|
||||
UINT64 st_rdev;
|
||||
UINT64 flags;
|
||||
UINT32 inline_length;
|
||||
UINT64 disk_size[3];
|
||||
} btrfs_inode_info;
|
||||
|
||||
typedef struct {
|
||||
UINT64 flags;
|
||||
BOOL flags_changed;
|
||||
UINT32 st_uid;
|
||||
BOOL uid_changed;
|
||||
UINT32 st_gid;
|
||||
BOOL gid_changed;
|
||||
UINT32 st_mode;
|
||||
BOOL mode_changed;
|
||||
} btrfs_set_inode_info;
|
||||
|
||||
#endif
|
||||
|
|
898
reactos/drivers/filesystems/btrfs/compress.c
Executable file
898
reactos/drivers/filesystems/btrfs/compress.c
Executable file
|
@ -0,0 +1,898 @@
|
|||
/* Copyright (c) Mark Harmstone 2016
|
||||
* Copyright (c) Reimar Doeffinger 2006
|
||||
* Copyright (c) Markus Oberhumer 1996
|
||||
*
|
||||
* 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/>. */
|
||||
|
||||
// Portion of the LZO decompression code here were cribbed from code in
|
||||
// libavcodec, also under the LGPL. Thank you, Reimar Doeffinger.
|
||||
|
||||
// The LZO compression code comes from v0.22 of lzo, written way back in
|
||||
// 1996, and available here:
|
||||
// https://www.ibiblio.org/pub/historic-linux/ftp-archives/sunsite.unc.edu/Sep-29-1996/libs/lzo-0.22.tar.gz
|
||||
// Modern versions of lzo are licensed under the GPL, but the very oldest
|
||||
// versions are under the LGPL and hence okay to use here.
|
||||
|
||||
#include "btrfs_drv.h"
|
||||
|
||||
#define Z_SOLO
|
||||
#define ZLIB_INTERNAL
|
||||
|
||||
#ifndef __REACTOS__
|
||||
#include "zlib/zlib.h"
|
||||
#include "zlib/inftrees.h"
|
||||
#include "zlib/inflate.h"
|
||||
#else
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#define LINUX_PAGE_SIZE 4096
|
||||
|
||||
typedef struct {
|
||||
UINT8* in;
|
||||
UINT32 inlen;
|
||||
UINT32 inpos;
|
||||
UINT8* out;
|
||||
UINT32 outlen;
|
||||
UINT32 outpos;
|
||||
BOOL error;
|
||||
void* wrkmem;
|
||||
} lzo_stream;
|
||||
|
||||
#define LZO1X_MEM_COMPRESS ((UINT32) (16384L * sizeof(UINT8*)))
|
||||
|
||||
#define M1_MAX_OFFSET 0x0400
|
||||
#define M2_MAX_OFFSET 0x0800
|
||||
#define M3_MAX_OFFSET 0x4000
|
||||
#define M4_MAX_OFFSET 0xbfff
|
||||
|
||||
#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET)
|
||||
|
||||
#define M1_MARKER 0
|
||||
#define M2_MARKER 64
|
||||
#define M3_MARKER 32
|
||||
#define M4_MARKER 16
|
||||
|
||||
#define _DV2(p, shift1, shift2) (((( (UINT32)(p[2]) << shift1) ^ p[1]) << shift2) ^ p[0])
|
||||
#define DVAL_NEXT(dv, p) dv ^= p[-1]; dv = (((dv) >> 5) ^ ((UINT32)(p[2]) << (2*5)))
|
||||
#define _DV(p, shift) _DV2(p, shift, shift)
|
||||
#define DVAL_FIRST(dv, p) dv = _DV((p), 5)
|
||||
#define _DINDEX(dv, p) ((40799u * (dv)) >> 5)
|
||||
#define DINDEX(dv, p) (((_DINDEX(dv, p)) & 0x3fff) << 0)
|
||||
#define UPDATE_D(dict, cycle, dv, p) dict[DINDEX(dv, p)] = (p)
|
||||
#define UPDATE_I(dict, cycle, index, p) dict[index] = (p)
|
||||
|
||||
#define LZO_CHECK_MPOS_NON_DET(m_pos, m_off, in, ip, max_offset) \
|
||||
((void*) m_pos < (void*) in || \
|
||||
(m_off = (UINT8*) ip - (UINT8*) m_pos) <= 0 || \
|
||||
m_off > max_offset)
|
||||
|
||||
#define LZO_BYTE(x) ((unsigned char) (x))
|
||||
|
||||
static UINT8 lzo_nextbyte(lzo_stream* stream) {
|
||||
UINT8 c;
|
||||
|
||||
if (stream->inpos >= stream->inlen) {
|
||||
stream->error = TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
c = stream->in[stream->inpos];
|
||||
stream->inpos++;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static int lzo_len(lzo_stream* stream, int byte, int mask) {
|
||||
int len = byte & mask;
|
||||
|
||||
if (len == 0) {
|
||||
while (!(byte = lzo_nextbyte(stream))) {
|
||||
if (stream->error) return 0;
|
||||
|
||||
len += 255;
|
||||
}
|
||||
|
||||
len += mask + byte;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void lzo_copy(lzo_stream* stream, int len) {
|
||||
if (stream->inpos + len > stream->inlen) {
|
||||
stream->error = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (stream->outpos + len > stream->outlen) {
|
||||
stream->error = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
stream->out[stream->outpos] = stream->in[stream->inpos];
|
||||
stream->inpos++;
|
||||
stream->outpos++;
|
||||
len--;
|
||||
} while (len > 0);
|
||||
}
|
||||
|
||||
static void lzo_copyback(lzo_stream* stream, int back, int len) {
|
||||
if (stream->outpos < back) {
|
||||
stream->error = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (stream->outpos + len > stream->outlen) {
|
||||
stream->error = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
stream->out[stream->outpos] = stream->out[stream->outpos - back];
|
||||
stream->outpos++;
|
||||
len--;
|
||||
} while (len > 0);
|
||||
}
|
||||
|
||||
static NTSTATUS do_lzo_decompress(lzo_stream* stream) {
|
||||
UINT8 byte;
|
||||
UINT32 len, back;
|
||||
BOOL backcopy = FALSE;
|
||||
|
||||
stream->error = FALSE;
|
||||
|
||||
byte = lzo_nextbyte(stream);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
|
||||
if (byte > 17) {
|
||||
lzo_copy(stream, byte - 17);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
|
||||
byte = lzo_nextbyte(stream);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
|
||||
if (byte < 16) return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (byte >> 4) {
|
||||
backcopy = TRUE;
|
||||
if (byte >> 6) {
|
||||
len = (byte >> 5) - 1;
|
||||
back = (lzo_nextbyte(stream) << 3) + ((byte >> 2) & 7) + 1;
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
} else if (byte >> 5) {
|
||||
len = lzo_len(stream, byte, 31);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
|
||||
byte = lzo_nextbyte(stream);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
|
||||
back = (lzo_nextbyte(stream) << 6) + (byte >> 2) + 1;
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
} else {
|
||||
len = lzo_len(stream, byte, 7);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
|
||||
back = (1 << 14) + ((byte & 8) << 11);
|
||||
|
||||
byte = lzo_nextbyte(stream);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
|
||||
back += (lzo_nextbyte(stream) << 6) + (byte >> 2);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
|
||||
if (back == (1 << 14)) {
|
||||
if (len != 1)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (backcopy) {
|
||||
len = 0;
|
||||
back = (lzo_nextbyte(stream) << 2) + (byte >> 2) + 1;
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
} else {
|
||||
len = lzo_len(stream, byte, 15);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
|
||||
lzo_copy(stream, len + 3);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
|
||||
byte = lzo_nextbyte(stream);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
|
||||
if (byte >> 4)
|
||||
continue;
|
||||
|
||||
len = 1;
|
||||
back = (1 << 11) + (lzo_nextbyte(stream) << 2) + (byte >> 2) + 1;
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
lzo_copyback(stream, back, len + 2);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
|
||||
len = byte & 3;
|
||||
|
||||
if (len) {
|
||||
lzo_copy(stream, len);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
} else
|
||||
backcopy = !backcopy;
|
||||
|
||||
byte = lzo_nextbyte(stream);
|
||||
if (stream->error) return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS lzo_decompress(UINT8* inbuf, UINT64 inlen, UINT8* outbuf, UINT64 outlen) {
|
||||
NTSTATUS Status;
|
||||
UINT32 extlen, partlen, inoff, outoff;
|
||||
lzo_stream stream;
|
||||
|
||||
extlen = *((UINT32*)inbuf);
|
||||
if (inlen < extlen) {
|
||||
ERR("compressed extent was %llx, should have been at least %x\n", inlen, extlen);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
inoff = sizeof(UINT32);
|
||||
outoff = 0;
|
||||
|
||||
do {
|
||||
partlen = *(UINT32*)&inbuf[inoff];
|
||||
|
||||
if (partlen + inoff > inlen) {
|
||||
ERR("overflow: %x + %x > %llx\n", partlen, inoff, inlen);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
inoff += sizeof(UINT32);
|
||||
|
||||
stream.in = &inbuf[inoff];
|
||||
stream.inlen = partlen;
|
||||
stream.inpos = 0;
|
||||
stream.out = &outbuf[outoff];
|
||||
stream.outlen = LINUX_PAGE_SIZE;
|
||||
stream.outpos = 0;
|
||||
|
||||
Status = do_lzo_decompress(&stream);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("do_lzo_decompress returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (stream.outpos < stream.outlen)
|
||||
RtlZeroMemory(&stream.out[stream.outpos], stream.outlen - stream.outpos);
|
||||
|
||||
inoff += partlen;
|
||||
outoff += stream.outlen;
|
||||
|
||||
if (LINUX_PAGE_SIZE - (inoff % LINUX_PAGE_SIZE) < sizeof(UINT32))
|
||||
inoff = ((inoff / LINUX_PAGE_SIZE) + 1) * LINUX_PAGE_SIZE;
|
||||
} while (inoff < extlen);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void* zlib_alloc(void* opaque, unsigned int items, unsigned int size) {
|
||||
return ExAllocatePoolWithTag(PagedPool, items * size, ALLOC_TAG_ZLIB);
|
||||
}
|
||||
|
||||
static void zlib_free(void* opaque, void* ptr) {
|
||||
ExFreePool(ptr);
|
||||
}
|
||||
|
||||
static NTSTATUS zlib_decompress(UINT8* inbuf, UINT64 inlen, UINT8* outbuf, UINT64 outlen) {
|
||||
z_stream c_stream;
|
||||
int ret;
|
||||
|
||||
c_stream.zalloc = zlib_alloc;
|
||||
c_stream.zfree = zlib_free;
|
||||
c_stream.opaque = (voidpf)0;
|
||||
|
||||
ret = inflateInit(&c_stream);
|
||||
|
||||
if (ret != Z_OK) {
|
||||
ERR("inflateInit returned %08x\n", ret);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
c_stream.next_in = inbuf;
|
||||
c_stream.avail_in = inlen;
|
||||
|
||||
c_stream.next_out = outbuf;
|
||||
c_stream.avail_out = outlen;
|
||||
|
||||
do {
|
||||
ret = inflate(&c_stream, Z_NO_FLUSH);
|
||||
|
||||
if (ret != Z_OK && ret != Z_STREAM_END) {
|
||||
ERR("inflate returned %08x\n", ret);
|
||||
inflateEnd(&c_stream);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
} while (ret != Z_STREAM_END);
|
||||
|
||||
ret = inflateEnd(&c_stream);
|
||||
|
||||
if (ret != Z_OK) {
|
||||
ERR("inflateEnd returned %08x\n", ret);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
// FIXME - if we're short, should we zero the end of outbuf so we don't leak information into userspace?
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS decompress(UINT8 type, UINT8* inbuf, UINT64 inlen, UINT8* outbuf, UINT64 outlen) {
|
||||
if (type == BTRFS_COMPRESSION_ZLIB)
|
||||
return zlib_decompress(inbuf, inlen, outbuf, outlen);
|
||||
else if (type == BTRFS_COMPRESSION_LZO)
|
||||
return lzo_decompress(inbuf, inlen, outbuf, outlen);
|
||||
else {
|
||||
ERR("unsupported compression type %x\n", type);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
NTSTATUS Status;
|
||||
UINT8 compression;
|
||||
UINT64 comp_length;
|
||||
UINT8* comp_data;
|
||||
UINT32 out_left;
|
||||
LIST_ENTRY* le;
|
||||
chunk* c;
|
||||
z_stream c_stream;
|
||||
int ret;
|
||||
|
||||
comp_data = ExAllocatePoolWithTag(PagedPool, end_data - start_data, ALLOC_TAG);
|
||||
if (!comp_data) {
|
||||
ERR("out of memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Status = excise_extents(fcb->Vcb, fcb, start_data, end_data, Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("excise_extents returned %08x\n", Status);
|
||||
ExFreePool(comp_data);
|
||||
return Status;
|
||||
}
|
||||
|
||||
c_stream.zalloc = zlib_alloc;
|
||||
c_stream.zfree = zlib_free;
|
||||
c_stream.opaque = (voidpf)0;
|
||||
|
||||
ret = deflateInit(&c_stream, fcb->Vcb->options.zlib_level);
|
||||
|
||||
if (ret != Z_OK) {
|
||||
ERR("deflateInit returned %08x\n", ret);
|
||||
ExFreePool(comp_data);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
c_stream.avail_in = end_data - start_data;
|
||||
c_stream.next_in = data;
|
||||
c_stream.avail_out = end_data - start_data;
|
||||
c_stream.next_out = comp_data;
|
||||
|
||||
do {
|
||||
ret = deflate(&c_stream, Z_FINISH);
|
||||
|
||||
if (ret == Z_STREAM_ERROR) {
|
||||
ERR("deflate returned %x\n", ret);
|
||||
ExFreePool(comp_data);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
} while (c_stream.avail_in > 0 && c_stream.avail_out > 0);
|
||||
|
||||
out_left = c_stream.avail_out;
|
||||
|
||||
ret = deflateEnd(&c_stream);
|
||||
|
||||
if (ret != Z_OK) {
|
||||
ERR("deflateEnd returned %08x\n", ret);
|
||||
ExFreePool(comp_data);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (out_left < fcb->Vcb->superblock.sector_size) { // compressed extent would be larger than or same size as uncompressed extent
|
||||
ExFreePool(comp_data);
|
||||
|
||||
comp_length = end_data - start_data;
|
||||
comp_data = data;
|
||||
compression = BTRFS_COMPRESSION_NONE;
|
||||
|
||||
*compressed = FALSE;
|
||||
} else {
|
||||
UINT32 cl;
|
||||
|
||||
compression = BTRFS_COMPRESSION_ZLIB;
|
||||
cl = end_data - start_data - out_left;
|
||||
comp_length = sector_align(cl, fcb->Vcb->superblock.sector_size);
|
||||
|
||||
RtlZeroMemory(comp_data + cl, comp_length - cl);
|
||||
|
||||
*compressed = TRUE;
|
||||
}
|
||||
|
||||
ExAcquireResourceSharedLite(&fcb->Vcb->chunk_lock, TRUE);
|
||||
|
||||
le = fcb->Vcb->chunks.Flink;
|
||||
while (le != &fcb->Vcb->chunks) {
|
||||
c = CONTAINING_RECORD(le, chunk, list_entry);
|
||||
|
||||
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)) {
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
|
||||
if (compression != BTRFS_COMPRESSION_NONE)
|
||||
ExFreePool(comp_data);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
|
||||
ExAcquireResourceExclusiveLite(&fcb->Vcb->chunk_lock, TRUE);
|
||||
|
||||
if ((c = alloc_chunk(fcb->Vcb, fcb->Vcb->data_flags))) {
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
|
||||
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)) {
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
|
||||
if (compression != BTRFS_COMPRESSION_NONE)
|
||||
ExFreePool(comp_data);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
} else
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
|
||||
WARN("couldn't find any data chunks with %llx bytes free\n", comp_length);
|
||||
|
||||
return STATUS_DISK_FULL;
|
||||
}
|
||||
|
||||
static NTSTATUS lzo_do_compress(const UINT8* in, UINT32 in_len, UINT8* out, UINT32* out_len, void* wrkmem) {
|
||||
const UINT8* ip;
|
||||
UINT32 dv;
|
||||
UINT8* op;
|
||||
const UINT8* in_end = in + in_len;
|
||||
const UINT8* ip_end = in + in_len - 9 - 4;
|
||||
const UINT8* ii;
|
||||
const UINT8** dict = (const UINT8**)wrkmem;
|
||||
|
||||
op = out;
|
||||
ip = in;
|
||||
ii = ip;
|
||||
|
||||
DVAL_FIRST(dv, ip); UPDATE_D(dict, cycle, dv, ip); ip++;
|
||||
DVAL_NEXT(dv, ip); UPDATE_D(dict, cycle, dv, ip); ip++;
|
||||
DVAL_NEXT(dv, ip); UPDATE_D(dict, cycle, dv, ip); ip++;
|
||||
DVAL_NEXT(dv, ip); UPDATE_D(dict, cycle, dv, ip); ip++;
|
||||
|
||||
while (1) {
|
||||
const UINT8* m_pos;
|
||||
UINT32 m_len;
|
||||
ptrdiff_t m_off;
|
||||
UINT32 lit, dindex;
|
||||
|
||||
dindex = DINDEX(dv, ip);
|
||||
m_pos = dict[dindex];
|
||||
UPDATE_I(dict, cycle, dindex, ip);
|
||||
|
||||
if (!LZO_CHECK_MPOS_NON_DET(m_pos, m_off, in, ip, M4_MAX_OFFSET) && m_pos[0] == ip[0] && m_pos[1] == ip[1] && m_pos[2] == ip[2]) {
|
||||
lit = ip - ii;
|
||||
m_pos += 3;
|
||||
if (m_off <= M2_MAX_OFFSET)
|
||||
goto match;
|
||||
|
||||
if (lit == 3) { /* better compression, but slower */
|
||||
if (op - 2 <= out)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
||||
op[-2] |= LZO_BYTE(3);
|
||||
*op++ = *ii++; *op++ = *ii++; *op++ = *ii++;
|
||||
goto code_match;
|
||||
}
|
||||
|
||||
if (*m_pos == ip[3])
|
||||
goto match;
|
||||
}
|
||||
|
||||
/* a literal */
|
||||
++ip;
|
||||
if (ip >= ip_end)
|
||||
break;
|
||||
DVAL_NEXT(dv, ip);
|
||||
continue;
|
||||
|
||||
/* a match */
|
||||
match:
|
||||
/* store current literal run */
|
||||
if (lit > 0) {
|
||||
UINT32 t = lit;
|
||||
|
||||
if (t <= 3) {
|
||||
if (op - 2 <= out)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
||||
op[-2] |= LZO_BYTE(t);
|
||||
} else if (t <= 18)
|
||||
*op++ = LZO_BYTE(t - 3);
|
||||
else {
|
||||
UINT32 tt = t - 18;
|
||||
|
||||
*op++ = 0;
|
||||
while (tt > 255) {
|
||||
tt -= 255;
|
||||
*op++ = 0;
|
||||
}
|
||||
|
||||
if (tt <= 0)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
||||
*op++ = LZO_BYTE(tt);
|
||||
}
|
||||
|
||||
do {
|
||||
*op++ = *ii++;
|
||||
} while (--t > 0);
|
||||
}
|
||||
|
||||
|
||||
/* code the match */
|
||||
code_match:
|
||||
if (ii != ip)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
||||
ip += 3;
|
||||
if (*m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++ ||
|
||||
*m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++) {
|
||||
--ip;
|
||||
m_len = ip - ii;
|
||||
|
||||
if (m_len < 3 || m_len > 8)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
||||
if (m_off <= M2_MAX_OFFSET) {
|
||||
m_off -= 1;
|
||||
*op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
|
||||
*op++ = LZO_BYTE(m_off >> 3);
|
||||
} else if (m_off <= M3_MAX_OFFSET) {
|
||||
m_off -= 1;
|
||||
*op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
|
||||
goto m3_m4_offset;
|
||||
} else {
|
||||
m_off -= 0x4000;
|
||||
|
||||
if (m_off <= 0 || m_off > 0x7fff)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
||||
*op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11) | (m_len - 2));
|
||||
goto m3_m4_offset;
|
||||
}
|
||||
} else {
|
||||
const UINT8* end;
|
||||
end = in_end;
|
||||
while (ip < end && *m_pos == *ip)
|
||||
m_pos++, ip++;
|
||||
m_len = (ip - ii);
|
||||
|
||||
if (m_len < 3)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
||||
if (m_off <= M3_MAX_OFFSET) {
|
||||
m_off -= 1;
|
||||
if (m_len <= 33)
|
||||
*op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
|
||||
else {
|
||||
m_len -= 33;
|
||||
*op++ = M3_MARKER | 0;
|
||||
goto m3_m4_len;
|
||||
}
|
||||
} else {
|
||||
m_off -= 0x4000;
|
||||
|
||||
if (m_off <= 0 || m_off > 0x7fff)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
||||
if (m_len <= 9)
|
||||
*op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11) | (m_len - 2));
|
||||
else {
|
||||
m_len -= 9;
|
||||
*op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11));
|
||||
m3_m4_len:
|
||||
while (m_len > 255) {
|
||||
m_len -= 255;
|
||||
*op++ = 0;
|
||||
}
|
||||
|
||||
if (m_len <= 0)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
||||
*op++ = LZO_BYTE(m_len);
|
||||
}
|
||||
}
|
||||
|
||||
m3_m4_offset:
|
||||
*op++ = LZO_BYTE((m_off & 63) << 2);
|
||||
*op++ = LZO_BYTE(m_off >> 6);
|
||||
}
|
||||
|
||||
ii = ip;
|
||||
if (ip >= ip_end)
|
||||
break;
|
||||
DVAL_FIRST(dv, ip);
|
||||
}
|
||||
|
||||
/* store final literal run */
|
||||
if (in_end - ii > 0) {
|
||||
UINT32 t = in_end - ii;
|
||||
|
||||
if (op == out && t <= 238)
|
||||
*op++ = LZO_BYTE(17 + t);
|
||||
else if (t <= 3)
|
||||
op[-2] |= LZO_BYTE(t);
|
||||
else if (t <= 18)
|
||||
*op++ = LZO_BYTE(t - 3);
|
||||
else {
|
||||
UINT32 tt = t - 18;
|
||||
|
||||
*op++ = 0;
|
||||
while (tt > 255) {
|
||||
tt -= 255;
|
||||
*op++ = 0;
|
||||
}
|
||||
|
||||
if (tt <= 0)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
||||
*op++ = LZO_BYTE(tt);
|
||||
}
|
||||
|
||||
do {
|
||||
*op++ = *ii++;
|
||||
} while (--t > 0);
|
||||
}
|
||||
|
||||
*out_len = op - out;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS lzo1x_1_compress(lzo_stream* stream) {
|
||||
UINT8 *op = stream->out;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
if (stream->inlen <= 0)
|
||||
stream->outlen = 0;
|
||||
else if (stream->inlen <= 9 + 4) {
|
||||
*op++ = LZO_BYTE(17 + stream->inlen);
|
||||
|
||||
stream->inpos = 0;
|
||||
do {
|
||||
*op++ = stream->in[stream->inpos];
|
||||
stream->inpos++;
|
||||
} while (stream->inlen < stream->inpos);
|
||||
stream->outlen = op - stream->out;
|
||||
} else
|
||||
Status = lzo_do_compress(stream->in, stream->inlen, stream->out, &stream->outlen, stream->wrkmem);
|
||||
|
||||
if (Status == STATUS_SUCCESS) {
|
||||
op = stream->out + stream->outlen;
|
||||
*op++ = M4_MARKER | 1;
|
||||
*op++ = 0;
|
||||
*op++ = 0;
|
||||
stream->outlen += 3;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
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) {
|
||||
NTSTATUS Status;
|
||||
UINT8 compression;
|
||||
UINT64 comp_length;
|
||||
ULONG comp_data_len, num_pages, i;
|
||||
UINT8* comp_data;
|
||||
BOOL skip_compression = FALSE;
|
||||
lzo_stream stream;
|
||||
UINT32* out_size;
|
||||
LIST_ENTRY* le;
|
||||
chunk* c;
|
||||
|
||||
num_pages = (sector_align(end_data - start_data, LINUX_PAGE_SIZE)) / LINUX_PAGE_SIZE;
|
||||
|
||||
// Four-byte overall header
|
||||
// Another four-byte header page
|
||||
// Each page has a maximum size of lzo_max_outlen(LINUX_PAGE_SIZE)
|
||||
// Plus another four bytes for possible padding
|
||||
comp_data_len = sizeof(UINT32) + ((lzo_max_outlen(LINUX_PAGE_SIZE) + (2 * sizeof(UINT32))) * num_pages);
|
||||
|
||||
comp_data = ExAllocatePoolWithTag(PagedPool, comp_data_len, ALLOC_TAG);
|
||||
if (!comp_data) {
|
||||
ERR("out of memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
stream.wrkmem = ExAllocatePoolWithTag(PagedPool, LZO1X_MEM_COMPRESS, ALLOC_TAG);
|
||||
if (!stream.wrkmem) {
|
||||
ERR("out of memory\n");
|
||||
ExFreePool(comp_data);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Status = excise_extents(fcb->Vcb, fcb, start_data, end_data, Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("excise_extents returned %08x\n", Status);
|
||||
ExFreePool(comp_data);
|
||||
ExFreePool(stream.wrkmem);
|
||||
return Status;
|
||||
}
|
||||
|
||||
out_size = (UINT32*)comp_data;
|
||||
*out_size = sizeof(UINT32);
|
||||
|
||||
stream.in = data;
|
||||
stream.out = comp_data + (2 * sizeof(UINT32));
|
||||
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
UINT32* pagelen = (UINT32*)(stream.out - sizeof(UINT32));
|
||||
|
||||
stream.inlen = min(LINUX_PAGE_SIZE, end_data - start_data - (i * LINUX_PAGE_SIZE));
|
||||
|
||||
Status = lzo1x_1_compress(&stream);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("lzo1x_1_compress returned %08x\n", Status);
|
||||
skip_compression = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
*pagelen = stream.outlen;
|
||||
*out_size += stream.outlen + sizeof(UINT32);
|
||||
|
||||
stream.in += LINUX_PAGE_SIZE;
|
||||
stream.out += stream.outlen + sizeof(UINT32);
|
||||
|
||||
if (LINUX_PAGE_SIZE - (*out_size % LINUX_PAGE_SIZE) < sizeof(UINT32)) {
|
||||
RtlZeroMemory(stream.out, LINUX_PAGE_SIZE - (*out_size % LINUX_PAGE_SIZE));
|
||||
stream.out += LINUX_PAGE_SIZE - (*out_size % LINUX_PAGE_SIZE);
|
||||
*out_size += LINUX_PAGE_SIZE - (*out_size % LINUX_PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
ExFreePool(stream.wrkmem);
|
||||
|
||||
if (skip_compression || *out_size >= end_data - start_data - fcb->Vcb->superblock.sector_size) { // compressed extent would be larger than or same size as uncompressed extent
|
||||
ExFreePool(comp_data);
|
||||
|
||||
comp_length = end_data - start_data;
|
||||
comp_data = data;
|
||||
compression = BTRFS_COMPRESSION_NONE;
|
||||
|
||||
*compressed = FALSE;
|
||||
} else {
|
||||
compression = BTRFS_COMPRESSION_LZO;
|
||||
comp_length = sector_align(*out_size, fcb->Vcb->superblock.sector_size);
|
||||
|
||||
RtlZeroMemory(comp_data + *out_size, comp_length - *out_size);
|
||||
|
||||
*compressed = TRUE;
|
||||
}
|
||||
|
||||
ExAcquireResourceSharedLite(&fcb->Vcb->chunk_lock, TRUE);
|
||||
|
||||
le = fcb->Vcb->chunks.Flink;
|
||||
while (le != &fcb->Vcb->chunks) {
|
||||
c = CONTAINING_RECORD(le, chunk, list_entry);
|
||||
|
||||
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)) {
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
|
||||
if (compression != BTRFS_COMPRESSION_NONE)
|
||||
ExFreePool(comp_data);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
|
||||
ExAcquireResourceExclusiveLite(&fcb->Vcb->chunk_lock, TRUE);
|
||||
|
||||
if ((c = alloc_chunk(fcb->Vcb, fcb->Vcb->data_flags))) {
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
|
||||
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)) {
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
|
||||
if (compression != BTRFS_COMPRESSION_NONE)
|
||||
ExFreePool(comp_data);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
} else
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
|
||||
WARN("couldn't find any data chunks with %llx bytes free\n", comp_length);
|
||||
|
||||
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) {
|
||||
UINT8 type;
|
||||
|
||||
if (fcb->Vcb->options.compress_type != 0)
|
||||
type = fcb->Vcb->options.compress_type;
|
||||
else {
|
||||
if (fcb->Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO)
|
||||
type = BTRFS_COMPRESSION_LZO;
|
||||
else
|
||||
type = BTRFS_COMPRESSION_ZLIB;
|
||||
}
|
||||
|
||||
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);
|
||||
} else
|
||||
return zlib_write_compressed_bit(fcb, start_data, end_data, data, compressed, changed_sector_list, Irp, rollback);
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -32,7 +32,7 @@ typedef struct {
|
|||
enum DirEntryType dir_entry_type;
|
||||
} dir_entry;
|
||||
|
||||
static ULONG STDCALL get_reparse_tag(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 type, ULONG atts) {
|
||||
ULONG STDCALL get_reparse_tag(device_extension* Vcb, root* subvol, UINT64 inode, UINT8 type, ULONG atts, PIRP Irp) {
|
||||
fcb* fcb;
|
||||
ULONG tag = 0, br;
|
||||
NTSTATUS Status;
|
||||
|
@ -49,7 +49,7 @@ static ULONG STDCALL get_reparse_tag(device_extension* Vcb, root* subvol, UINT64
|
|||
return 0;
|
||||
|
||||
ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE);
|
||||
Status = open_fcb(Vcb, subvol, inode, type, NULL, NULL, &fcb);
|
||||
Status = open_fcb(Vcb, subvol, inode, type, NULL, NULL, &fcb, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("open_fcb returned %08x\n", Status);
|
||||
ExReleaseResourceLite(&Vcb->fcb_lock);
|
||||
|
@ -78,7 +78,9 @@ static ULONG STDCALL get_reparse_tag(device_extension* Vcb, root* subvol, UINT64
|
|||
end:
|
||||
ExReleaseResourceLite(fcb->Header.Resource);
|
||||
|
||||
ExAcquireResourceExclusiveLite(&Vcb->fcb_lock, TRUE);
|
||||
free_fcb(fcb);
|
||||
ExReleaseResourceLite(&Vcb->fcb_lock);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
@ -154,7 +156,7 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
searchkey.obj_type = TYPE_INODE_ITEM;
|
||||
searchkey.offset = 0xffffffffffffffff;
|
||||
|
||||
Status = find_item(fcb->Vcb, r, &tp, &searchkey, FALSE);
|
||||
Status = find_item(fcb->Vcb, r, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -177,7 +179,7 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
|
||||
BOOL dotfile = de->namelen > 1 && de->name[0] == '.';
|
||||
|
||||
atts = get_file_attributes(fcb->Vcb, &ii, r, inode, de->type, dotfile, FALSE);
|
||||
atts = get_file_attributes(fcb->Vcb, &ii, r, inode, de->type, dotfile, FALSE, Irp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,12 +240,12 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
fbdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime);
|
||||
fbdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime);
|
||||
fbdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime);
|
||||
fbdi->ChangeTime.QuadPart = 0;
|
||||
fbdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime);
|
||||
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->EaSize = get_reparse_tag(fcb->Vcb, r, inode, de->type, atts);
|
||||
fbdi->EaSize = get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, Irp);
|
||||
fbdi->ShortNameLength = 0;
|
||||
// fibdi->ShortName[12];
|
||||
|
||||
|
@ -277,7 +279,7 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
fdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime);
|
||||
fdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime);
|
||||
fdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime);
|
||||
fdi->ChangeTime.QuadPart = 0;
|
||||
fdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime);
|
||||
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;
|
||||
|
@ -313,12 +315,12 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
ffdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime);
|
||||
ffdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime);
|
||||
ffdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime);
|
||||
ffdi->ChangeTime.QuadPart = 0;
|
||||
ffdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime);
|
||||
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->EaSize = get_reparse_tag(fcb->Vcb, r, inode, de->type, atts);
|
||||
ffdi->EaSize = get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, Irp);
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(ffdi->FileName, stringlen, &stringlen, de->name, de->namelen);
|
||||
|
||||
|
@ -353,12 +355,12 @@ static NTSTATUS STDCALL query_dir_item(fcb* fcb, file_ref* fileref, void* buf, L
|
|||
fibdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime);
|
||||
fibdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime);
|
||||
fibdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime);
|
||||
fibdi->ChangeTime.QuadPart = 0;
|
||||
fibdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime);
|
||||
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->EaSize = get_reparse_tag(fcb->Vcb, r, inode, de->type, atts);
|
||||
fibdi->EaSize = get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, Irp);
|
||||
fibdi->ShortNameLength = 0;
|
||||
// fibdi->ShortName[12];
|
||||
fibdi->FileId.QuadPart = inode;
|
||||
|
@ -428,7 +430,7 @@ 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) {
|
||||
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;
|
||||
|
@ -520,14 +522,14 @@ static NTSTATUS STDCALL next_dir_entry(file_ref* fileref, UINT64* offset, dir_en
|
|||
searchkey.obj_type = TYPE_DIR_INDEX;
|
||||
searchkey.offset = *offset;
|
||||
|
||||
Status = find_item(fileref->fcb->Vcb, fileref->fcb->subvol, &tp, &searchkey, FALSE);
|
||||
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))
|
||||
if (find_next_item(fileref->fcb->Vcb, &tp, &next_tp, FALSE, Irp))
|
||||
tp = next_tp;
|
||||
}
|
||||
|
||||
|
@ -766,7 +768,7 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
}
|
||||
|
||||
newoffset = ccb->query_dir_offset;
|
||||
Status = next_dir_entry(fileref, &newoffset, &de);
|
||||
Status = next_dir_entry(fileref, &newoffset, &de, Irp);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
if (Status == STATUS_NO_MORE_FILES && initial)
|
||||
|
@ -845,7 +847,7 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
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);
|
||||
Status = find_file_in_dir(fcb->Vcb, &ccb->query_string, fileref, &found_subvol, &found_inode, &found_type, &found_index, &utf8, Irp);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
Status = STATUS_NO_SUCH_FILE;
|
||||
|
@ -901,7 +903,7 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
ExFreePool(de.name);
|
||||
|
||||
newoffset = ccb->query_dir_offset;
|
||||
Status = next_dir_entry(fileref, &newoffset, &de);
|
||||
Status = next_dir_entry(fileref, &newoffset, &de, Irp);
|
||||
|
||||
ExFreePool(uni_fn);
|
||||
if (NT_SUCCESS(Status)) {
|
||||
|
@ -976,7 +978,7 @@ static NTSTATUS STDCALL query_directory(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
UNICODE_STRING di_uni_fn;
|
||||
|
||||
newoffset = ccb->query_dir_offset;
|
||||
Status = next_dir_entry(fileref, &newoffset, &de);
|
||||
Status = next_dir_entry(fileref, &newoffset, &de, Irp);
|
||||
if (NT_SUCCESS(Status)) {
|
||||
if (has_wildcard) {
|
||||
ULONG stringlen;
|
||||
|
|
|
@ -91,7 +91,7 @@ static UINT64 get_extent_hash(UINT8 type, void* data) {
|
|||
}
|
||||
}
|
||||
|
||||
static NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT8 type, void* data, KEY* firstitem, UINT8 level, LIST_ENTRY* rollback) {
|
||||
static NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT8 type, void* data, KEY* firstitem, UINT8 level, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
NTSTATUS Status;
|
||||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
|
@ -113,7 +113,7 @@ static NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
searchkey.obj_type = TYPE_EXTENT_ITEM;
|
||||
searchkey.offset = 0xffffffffffffffff;
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -153,7 +153,7 @@ static NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
*ptr = type;
|
||||
RtlCopyMemory(ptr + 1, data, datalen);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, address, TYPE_EXTENT_ITEM, size, ei, eisize, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, address, TYPE_EXTENT_ITEM, size, ei, eisize, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -184,13 +184,13 @@ static NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, ei, sizeof(EXTENT_ITEM), NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, ei, sizeof(EXTENT_ITEM), NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
ExFreePool(ei);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -265,7 +265,7 @@ static NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -335,7 +335,7 @@ static NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size + sizeof(UINT8) + datalen, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size + sizeof(UINT8) + datalen, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -352,7 +352,7 @@ static NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
searchkey.obj_type = type;
|
||||
searchkey.offset = offset;
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp2, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp2, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -381,7 +381,7 @@ static NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
|
||||
delete_tree_item(Vcb, &tp2, rollback);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset, data2, tp2.item->size, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset, data2, tp2.item->size, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -394,7 +394,7 @@ static NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -408,7 +408,7 @@ static NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
data2 = ExAllocatePoolWithTag(PagedPool, datalen, ALLOC_TAG);
|
||||
RtlCopyMemory(data2, data, datalen);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, address, type, offset, data2, datalen, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, address, type, offset, data2, datalen, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -421,7 +421,7 @@ static NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -429,7 +429,7 @@ static NTSTATUS increase_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS increase_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode, UINT64 offset, UINT32 refcount, LIST_ENTRY* rollback) {
|
||||
NTSTATUS increase_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode, UINT64 offset, UINT32 refcount, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
EXTENT_DATA_REF edr;
|
||||
|
||||
edr.root = root;
|
||||
|
@ -437,7 +437,7 @@ NTSTATUS increase_extent_refcount_data(device_extension* Vcb, UINT64 address, UI
|
|||
edr.offset = offset;
|
||||
edr.count = refcount;
|
||||
|
||||
return increase_extent_refcount(Vcb, address, size, TYPE_EXTENT_DATA_REF, &edr, NULL, 0, rollback);
|
||||
return increase_extent_refcount(Vcb, address, size, TYPE_EXTENT_DATA_REF, &edr, NULL, 0, Irp, rollback);
|
||||
}
|
||||
|
||||
void decrease_chunk_usage(chunk* c, UINT64 delta) {
|
||||
|
@ -447,7 +447,7 @@ void decrease_chunk_usage(chunk* c, UINT64 delta) {
|
|||
}
|
||||
|
||||
static NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT8 type, void* data, KEY* firstitem,
|
||||
UINT8 level, UINT64 parent, LIST_ENTRY* rollback) {
|
||||
UINT8 level, UINT64 parent, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
KEY searchkey;
|
||||
NTSTATUS Status;
|
||||
traverse_ptr tp, tp2;
|
||||
|
@ -464,7 +464,7 @@ static NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
searchkey.obj_type = TYPE_EXTENT_ITEM;
|
||||
searchkey.offset = 0xffffffffffffffff;
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -498,13 +498,13 @@ static NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, ei, sizeof(EXTENT_ITEM), &tp, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, ei, sizeof(EXTENT_ITEM), &tp, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
ExFreePool(ei);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -604,7 +604,7 @@ static NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, neweilen, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, neweilen, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -643,7 +643,7 @@ static NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, neweilen, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, neweilen, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -670,7 +670,7 @@ static NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
searchkey.obj_type = type;
|
||||
searchkey.offset = (type == TYPE_SHARED_DATA_REF || type == TYPE_EXTENT_REF_V0) ? parent : get_extent_hash(type, data);
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp2, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp2, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -717,7 +717,7 @@ static NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
|
||||
newedr->count -= edr->count;
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset, newedr, tp2.item->size, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp2.item->key.obj_id, tp2.item->key.obj_type, tp2.item->key.offset, newedr, tp2.item->size, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -736,7 +736,7 @@ static NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -775,7 +775,7 @@ static NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -810,7 +810,7 @@ static NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
|
||||
delete_tree_item(Vcb, &tp, rollback);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, newei, tp.item->size, NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -823,7 +823,7 @@ static NTSTATUS decrease_extent_refcount(device_extension* Vcb, UINT64 address,
|
|||
}
|
||||
|
||||
NTSTATUS decrease_extent_refcount_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 inode,
|
||||
UINT64 offset, UINT32 refcount, LIST_ENTRY* rollback) {
|
||||
UINT64 offset, UINT32 refcount, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
EXTENT_DATA_REF edr;
|
||||
|
||||
edr.root = root;
|
||||
|
@ -831,20 +831,20 @@ 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, rollback);
|
||||
return decrease_extent_refcount(Vcb, address, size, TYPE_EXTENT_DATA_REF, &edr, NULL, 0, 0, Irp, rollback);
|
||||
}
|
||||
|
||||
NTSTATUS decrease_extent_refcount_shared_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 treeaddr, UINT64 parent, LIST_ENTRY* rollback) {
|
||||
NTSTATUS decrease_extent_refcount_shared_data(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 treeaddr, UINT64 parent, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
SHARED_DATA_REF sdr;
|
||||
|
||||
sdr.offset = treeaddr;
|
||||
sdr.count = 1;
|
||||
|
||||
return decrease_extent_refcount(Vcb, address, size, TYPE_SHARED_DATA_REF, &sdr, NULL, 0, parent, rollback);
|
||||
return decrease_extent_refcount(Vcb, address, size, TYPE_SHARED_DATA_REF, &sdr, NULL, 0, parent, Irp, rollback);
|
||||
}
|
||||
|
||||
NTSTATUS decrease_extent_refcount_old(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 treeaddr, LIST_ENTRY* rollback) {
|
||||
return decrease_extent_refcount(Vcb, address, size, TYPE_EXTENT_REF_V0, NULL, NULL, 0, treeaddr, rollback);
|
||||
NTSTATUS decrease_extent_refcount_old(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 treeaddr, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
return decrease_extent_refcount(Vcb, address, size, TYPE_EXTENT_REF_V0, NULL, NULL, 0, treeaddr, Irp, rollback);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
@ -918,7 +918,7 @@ static NTSTATUS add_data_extent_ref(LIST_ENTRY* extent_refs, UINT64 tree_id, UIN
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS construct_extent_item(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 flags, LIST_ENTRY* extent_refs, LIST_ENTRY* rollback) {
|
||||
static NTSTATUS construct_extent_item(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 flags, LIST_ENTRY* extent_refs, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
LIST_ENTRY *le, *next_le;
|
||||
UINT64 refcount;
|
||||
ULONG inline_len;
|
||||
|
@ -1005,7 +1005,7 @@ static NTSTATUS construct_extent_item(device_extension* Vcb, UINT64 address, UIN
|
|||
le = le->Flink;
|
||||
}
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, address, TYPE_EXTENT_ITEM, size, ei, inline_len, NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, address, TYPE_EXTENT_ITEM, size, ei, inline_len, NULL, Irp, rollback)) {
|
||||
ERR("error - failed to insert item\n");
|
||||
ExFreePool(ei);
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
@ -1017,7 +1017,7 @@ static NTSTATUS construct_extent_item(device_extension* Vcb, UINT64 address, UIN
|
|||
while (le != extent_refs) {
|
||||
extent_ref* er = CONTAINING_RECORD(le, extent_ref, list_entry);
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, address, er->type, er->hash, er->data, get_extent_data_len(er->type), NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->extent_root, address, er->type, er->hash, er->data, get_extent_data_len(er->type), NULL, Irp, rollback)) {
|
||||
ERR("error - failed to insert item\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
@ -1081,7 +1081,7 @@ static NTSTATUS populate_extent_refs_from_tree(device_extension* Vcb, UINT64 tre
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS convert_old_data_extent(device_extension* Vcb, UINT64 address, UINT64 size, LIST_ENTRY* rollback) {
|
||||
NTSTATUS convert_old_data_extent(device_extension* Vcb, UINT64 address, UINT64 size, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
KEY searchkey;
|
||||
traverse_ptr tp, next_tp;
|
||||
BOOL b;
|
||||
|
@ -1092,7 +1092,7 @@ NTSTATUS convert_old_data_extent(device_extension* Vcb, UINT64 address, UINT64 s
|
|||
searchkey.obj_type = TYPE_EXTENT_ITEM;
|
||||
searchkey.offset = size;
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -1114,7 +1114,7 @@ NTSTATUS convert_old_data_extent(device_extension* Vcb, UINT64 address, UINT64 s
|
|||
searchkey.obj_type = TYPE_EXTENT_REF_V0;
|
||||
searchkey.offset = 0;
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -1123,7 +1123,7 @@ NTSTATUS convert_old_data_extent(device_extension* Vcb, UINT64 address, UINT64 s
|
|||
InitializeListHead(&extent_refs);
|
||||
|
||||
do {
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE);
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE, Irp);
|
||||
|
||||
if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
|
||||
Status = populate_extent_refs_from_tree(Vcb, tp.item->key.offset, address, &extent_refs);
|
||||
|
@ -1143,7 +1143,7 @@ NTSTATUS convert_old_data_extent(device_extension* Vcb, UINT64 address, UINT64 s
|
|||
}
|
||||
} while (b);
|
||||
|
||||
Status = construct_extent_item(Vcb, address, size, EXTENT_ITEM_DATA, &extent_refs, rollback);
|
||||
Status = construct_extent_item(Vcb, address, size, EXTENT_ITEM_DATA, &extent_refs, Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("construct_extent_item returned %08x\n", Status);
|
||||
free_extent_refs(&extent_refs);
|
||||
|
@ -1155,7 +1155,7 @@ NTSTATUS convert_old_data_extent(device_extension* Vcb, UINT64 address, UINT64 s
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
UINT64 find_extent_data_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset) {
|
||||
UINT64 find_extent_data_refcount(device_extension* Vcb, UINT64 address, UINT64 size, UINT64 root, UINT64 objid, UINT64 offset, PIRP Irp) {
|
||||
NTSTATUS Status;
|
||||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
|
@ -1166,14 +1166,14 @@ UINT64 find_extent_data_refcount(device_extension* Vcb, UINT64 address, UINT64 s
|
|||
searchkey.obj_type = TYPE_EXTENT_ITEM;
|
||||
searchkey.offset = 0xffffffffffffffff;
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) {
|
||||
ERR("could not find address %llx in extent tree\n", address);
|
||||
TRACE("could not find address %llx in extent tree\n", address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1249,7 +1249,7 @@ UINT64 find_extent_data_refcount(device_extension* Vcb, UINT64 address, UINT64 s
|
|||
searchkey.obj_type = TYPE_EXTENT_DATA_REF;
|
||||
searchkey.offset = get_extent_data_ref_hash2(root, objid, offset);
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return 0;
|
||||
|
@ -1272,7 +1272,7 @@ UINT64 find_extent_data_refcount(device_extension* Vcb, UINT64 address, UINT64 s
|
|||
searchkey.obj_type = TYPE_EXTENT_REF_V0;
|
||||
searchkey.offset = 0;
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return 0;
|
||||
|
@ -1281,7 +1281,7 @@ UINT64 find_extent_data_refcount(device_extension* Vcb, UINT64 address, UINT64 s
|
|||
do {
|
||||
traverse_ptr next_tp;
|
||||
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE);
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE, Irp);
|
||||
|
||||
if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
|
||||
if (tp.item->size >= sizeof(EXTENT_REF_V0)) {
|
||||
|
@ -1335,7 +1335,7 @@ UINT64 find_extent_data_refcount(device_extension* Vcb, UINT64 address, UINT64 s
|
|||
searchkey.obj_type = TYPE_SHARED_DATA_REF;
|
||||
searchkey.offset = 0;
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return 0;
|
||||
|
@ -1344,7 +1344,7 @@ UINT64 find_extent_data_refcount(device_extension* Vcb, UINT64 address, UINT64 s
|
|||
do {
|
||||
traverse_ptr next_tp;
|
||||
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE);
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE, Irp);
|
||||
|
||||
if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) {
|
||||
if (tp.item->size >= sizeof(SHARED_DATA_REF)) {
|
||||
|
|
|
@ -67,7 +67,7 @@ static BOOLEAN STDCALL fast_query_basic_info(PFILE_OBJECT FileObject, BOOLEAN wa
|
|||
fbi->CreationTime.QuadPart = unix_time_to_win(&fcb->inode_item.otime);
|
||||
fbi->LastAccessTime.QuadPart = unix_time_to_win(&fcb->inode_item.st_atime);
|
||||
fbi->LastWriteTime.QuadPart = unix_time_to_win(&fcb->inode_item.st_mtime);
|
||||
fbi->ChangeTime.QuadPart = 0;
|
||||
fbi->ChangeTime.QuadPart = unix_time_to_win(&fcb->inode_item.st_ctime);
|
||||
fbi->FileAttributes = fcb->atts;
|
||||
|
||||
IoStatus->Status = STATUS_SUCCESS;
|
||||
|
@ -212,9 +212,22 @@ static BOOLEAN STDCALL fast_io_query_network_open_info(PFILE_OBJECT FileObject,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static NTSTATUS STDCALL fast_io_acquire_for_mod_write(PFILE_OBJECT FileObject, PLARGE_INTEGER EndingOffset, struct _ERESOURCE **ResourceToRelease, PDEVICE_OBJECT DeviceObject){
|
||||
TRACE("STUB: fast_io_acquire_for_mod_write\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
static NTSTATUS STDCALL fast_io_acquire_for_mod_write(PFILE_OBJECT FileObject, PLARGE_INTEGER EndingOffset, struct _ERESOURCE **ResourceToRelease, PDEVICE_OBJECT DeviceObject) {
|
||||
fcb* fcb;
|
||||
|
||||
TRACE("(%p, %llx, %p, %p)\n", FileObject, EndingOffset->QuadPart, ResourceToRelease, DeviceObject);
|
||||
|
||||
fcb = FileObject->FsContext;
|
||||
|
||||
if (!fcb)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
*ResourceToRelease = fcb->Header.PagingIoResource;
|
||||
|
||||
if (!ExAcquireResourceSharedLite(*ResourceToRelease, FALSE))
|
||||
return STATUS_CANT_WAIT;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static BOOLEAN STDCALL fast_io_read_compressed(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, ULONG LockKey, PVOID Buffer, PMDL *MdlChain, PIO_STATUS_BLOCK IoStatus, struct _COMPRESSED_DATA_INFO *CompressedDataInfo, ULONG CompressedDataInfoLength, PDEVICE_OBJECT DeviceObject){
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -17,8 +17,6 @@
|
|||
|
||||
#include "btrfs_drv.h"
|
||||
|
||||
#define INTERVAL 15000 // in milliseconds
|
||||
|
||||
static void do_flush(device_extension* Vcb) {
|
||||
LIST_ENTRY rollback;
|
||||
|
||||
|
@ -28,8 +26,8 @@ static void do_flush(device_extension* Vcb) {
|
|||
|
||||
ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE);
|
||||
|
||||
if (Vcb->need_write)
|
||||
do_write(Vcb, &rollback);
|
||||
if (Vcb->need_write && !Vcb->readonly)
|
||||
do_write(Vcb, NULL, &rollback);
|
||||
|
||||
free_trees(Vcb);
|
||||
|
||||
|
@ -49,7 +47,7 @@ void STDCALL flush_thread(void* context) {
|
|||
|
||||
KeInitializeTimer(&Vcb->flush_thread_timer);
|
||||
|
||||
due_time.QuadPart = -INTERVAL * 10000;
|
||||
due_time.QuadPart = (UINT64)Vcb->options.flush_interval * -10000000;
|
||||
|
||||
KeSetTimer(&Vcb->flush_thread_timer, due_time, NULL);
|
||||
|
||||
|
|
|
@ -23,11 +23,11 @@
|
|||
|
||||
// #define DEBUG_SPACE_LISTS
|
||||
|
||||
static NTSTATUS remove_free_space_inode(device_extension* Vcb, UINT64 inode, LIST_ENTRY* rollback) {
|
||||
static NTSTATUS remove_free_space_inode(device_extension* Vcb, UINT64 inode, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
NTSTATUS Status;
|
||||
fcb* fcb;
|
||||
|
||||
Status = open_fcb(Vcb, Vcb->root_root, inode, BTRFS_TYPE_FILE, NULL, NULL, &fcb);
|
||||
Status = open_fcb(Vcb, Vcb->root_root, inode, BTRFS_TYPE_FILE, NULL, NULL, &fcb, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("open_fcb returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -36,7 +36,7 @@ static NTSTATUS remove_free_space_inode(device_extension* Vcb, UINT64 inode, LIS
|
|||
fcb->dirty = TRUE;
|
||||
|
||||
if (fcb->inode_item.st_size > 0) {
|
||||
Status = excise_extents(fcb->Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, fcb->Vcb->superblock.sector_size), rollback);
|
||||
Status = excise_extents(fcb->Vcb, fcb, 0, sector_align(fcb->inode_item.st_size, fcb->Vcb->superblock.sector_size), Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("excise_extents returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -45,14 +45,14 @@ static NTSTATUS remove_free_space_inode(device_extension* Vcb, UINT64 inode, LIS
|
|||
|
||||
fcb->deleted = TRUE;
|
||||
|
||||
flush_fcb(fcb, FALSE, rollback);
|
||||
flush_fcb(fcb, FALSE, Irp, rollback);
|
||||
|
||||
free_fcb(fcb);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS clear_free_space_cache(device_extension* Vcb) {
|
||||
NTSTATUS clear_free_space_cache(device_extension* Vcb, PIRP Irp) {
|
||||
KEY searchkey;
|
||||
traverse_ptr tp, next_tp;
|
||||
NTSTATUS Status;
|
||||
|
@ -65,7 +65,7 @@ NTSTATUS clear_free_space_cache(device_extension* Vcb) {
|
|||
searchkey.obj_type = 0;
|
||||
searchkey.offset = 0;
|
||||
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -86,7 +86,7 @@ NTSTATUS clear_free_space_cache(device_extension* Vcb) {
|
|||
else {
|
||||
LIST_ENTRY* le;
|
||||
|
||||
Status = remove_free_space_inode(Vcb, fsi->key.obj_id, &rollback);
|
||||
Status = remove_free_space_inode(Vcb, fsi->key.obj_id, Irp, &rollback);
|
||||
|
||||
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);
|
||||
|
@ -109,7 +109,7 @@ NTSTATUS clear_free_space_cache(device_extension* Vcb) {
|
|||
WARN("(%llx,%x,%llx) was %u bytes, expected %u\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(FREE_SPACE_ITEM));
|
||||
}
|
||||
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE);
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE, Irp);
|
||||
if (b)
|
||||
tp = next_tp;
|
||||
} while (b);
|
||||
|
@ -245,7 +245,7 @@ static void order_space_entry(space* s, LIST_ENTRY* list_size) {
|
|||
InsertTailList(list_size, &s->list_entry_size);
|
||||
}
|
||||
|
||||
static NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c) {
|
||||
static NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c, PIRP Irp) {
|
||||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
FREE_SPACE_ITEM* fsi;
|
||||
|
@ -266,7 +266,7 @@ static NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c) {
|
|||
searchkey.obj_type = 0;
|
||||
searchkey.offset = c->offset;
|
||||
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -293,10 +293,10 @@ static NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c) {
|
|||
num_entries = fsi->num_entries;
|
||||
num_bitmaps = fsi->num_bitmaps;
|
||||
|
||||
Status = open_fcb(Vcb, Vcb->root_root, inode, BTRFS_TYPE_FILE, NULL, NULL, &c->cache);
|
||||
Status = open_fcb(Vcb, Vcb->root_root, inode, BTRFS_TYPE_FILE, NULL, NULL, &c->cache, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("open_fcb returned %08x\n", Status);
|
||||
return Status;
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (c->cache->inode_item.st_size == 0) {
|
||||
|
@ -329,7 +329,7 @@ static NTSTATUS load_stored_free_space_cache(device_extension* Vcb, chunk* c) {
|
|||
|
||||
free_fcb(c->cache);
|
||||
c->cache = NULL;
|
||||
return Status;
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (size > c->cache->inode_item.st_size)
|
||||
|
@ -446,7 +446,7 @@ clearcache:
|
|||
|
||||
InitializeListHead(&rollback);
|
||||
|
||||
Status = excise_extents(Vcb, c->cache, 0, c->cache->inode_item.st_size, &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);
|
||||
do_rollback(Vcb, &rollback);
|
||||
|
@ -463,7 +463,7 @@ clearcache:
|
|||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
NTSTATUS load_free_space_cache(device_extension* Vcb, chunk* c) {
|
||||
NTSTATUS load_free_space_cache(device_extension* Vcb, chunk* c, PIRP Irp) {
|
||||
traverse_ptr tp, next_tp;
|
||||
KEY searchkey;
|
||||
UINT64 lastaddr;
|
||||
|
@ -473,7 +473,7 @@ NTSTATUS load_free_space_cache(device_extension* Vcb, chunk* c) {
|
|||
// LIST_ENTRY* le;
|
||||
|
||||
if (Vcb->superblock.generation - 1 == Vcb->superblock.cache_generation) {
|
||||
Status = load_stored_free_space_cache(Vcb, c);
|
||||
Status = load_stored_free_space_cache(Vcb, c, Irp);
|
||||
|
||||
if (!NT_SUCCESS(Status) && Status != STATUS_NOT_FOUND) {
|
||||
ERR("load_stored_free_space_cache returned %08x\n", Status);
|
||||
|
@ -489,7 +489,7 @@ NTSTATUS load_free_space_cache(device_extension* Vcb, chunk* c) {
|
|||
searchkey.obj_type = TYPE_EXTENT_ITEM;
|
||||
searchkey.offset = 0;
|
||||
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -525,7 +525,7 @@ NTSTATUS load_free_space_cache(device_extension* Vcb, chunk* c) {
|
|||
lastaddr = tp.item->key.obj_id + tp.item->key.offset;
|
||||
}
|
||||
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE);
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE, Irp);
|
||||
if (b)
|
||||
tp = next_tp;
|
||||
} while (b);
|
||||
|
@ -568,48 +568,52 @@ static NTSTATUS insert_cache_extent(fcb* fcb, UINT64 start, UINT64 length, LIST_
|
|||
|
||||
flags = fcb->Vcb->data_flags;
|
||||
|
||||
ExAcquireResourceExclusiveLite(&fcb->Vcb->chunk_lock, TRUE);
|
||||
ExAcquireResourceSharedLite(&fcb->Vcb->chunk_lock, TRUE);
|
||||
|
||||
while (le != &fcb->Vcb->chunks) {
|
||||
c = CONTAINING_RECORD(le, chunk, list_entry);
|
||||
|
||||
ExAcquireResourceExclusiveLite(&c->nonpaged->lock, TRUE);
|
||||
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)) {
|
||||
ExReleaseResourceLite(&c->nonpaged->lock);
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start, length, FALSE, NULL, NULL, NULL, rollback, BTRFS_COMPRESSION_NONE, length)) {
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&c->nonpaged->lock);
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
if ((c = alloc_chunk(fcb->Vcb, flags, rollback))) {
|
||||
ExAcquireResourceExclusiveLite(&c->nonpaged->lock, TRUE);
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
|
||||
ExAcquireResourceExclusiveLite(&fcb->Vcb->chunk_lock, TRUE);
|
||||
|
||||
if ((c = alloc_chunk(fcb->Vcb, flags))) {
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
|
||||
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)) {
|
||||
ExReleaseResourceLite(&c->nonpaged->lock);
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
if (insert_extent_chunk(fcb->Vcb, fcb, c, start, length, FALSE, NULL, NULL, NULL, rollback, BTRFS_COMPRESSION_NONE, length)) {
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&c->nonpaged->lock);
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
} else
|
||||
ExReleaseResourceLite(&fcb->Vcb->chunk_lock);
|
||||
|
||||
WARN("couldn't find any data chunks with %llx bytes free\n", length);
|
||||
|
||||
return STATUS_DISK_FULL;
|
||||
}
|
||||
|
||||
static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* changed, LIST_ENTRY* rollback) {
|
||||
static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* changed, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
LIST_ENTRY* le;
|
||||
NTSTATUS Status;
|
||||
UINT64 num_entries, new_cache_size, i;
|
||||
|
@ -669,7 +673,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
|
||||
// create new inode
|
||||
|
||||
c->cache = create_fcb();
|
||||
c->cache = create_fcb(PagedPool);
|
||||
if (!c->cache) {
|
||||
ERR("out of memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
@ -691,7 +695,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
c->cache->subvol = Vcb->root_root;
|
||||
|
||||
if (Vcb->root_root->lastinode == 0)
|
||||
get_last_inode(Vcb, Vcb->root_root);
|
||||
get_last_inode(Vcb, Vcb->root_root, Irp);
|
||||
|
||||
c->cache->inode = Vcb->root_root->lastinode > 0x100 ? (Vcb->root_root->lastinode + 1) : 0x101;
|
||||
|
||||
|
@ -712,9 +716,12 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
searchkey.obj_type = 0;
|
||||
searchkey.offset = c->offset;
|
||||
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
ExFreePool(fsi);
|
||||
free_fcb(c->cache);
|
||||
c->cache = NULL;
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -725,7 +732,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
fsi->key.obj_type = TYPE_INODE_ITEM;
|
||||
fsi->key.offset = 0;
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->root_root, FREE_SPACE_CACHE_ID, 0, c->offset, fsi, sizeof(FREE_SPACE_ITEM), NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->root_root, FREE_SPACE_CACHE_ID, 0, c->offset, fsi, sizeof(FREE_SPACE_ITEM), NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
free_fcb(c->cache);
|
||||
c->cache = NULL;
|
||||
|
@ -746,7 +753,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
|
||||
Vcb->root_root->lastinode = c->cache->inode;
|
||||
|
||||
flush_fcb(c->cache, TRUE, rollback);
|
||||
flush_fcb(c->cache, TRUE, Irp, rollback);
|
||||
|
||||
*changed = TRUE;
|
||||
} else if (new_cache_size > c->cache->inode_item.st_size) {
|
||||
|
@ -764,7 +771,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
searchkey.obj_type = 0;
|
||||
searchkey.offset = c->offset;
|
||||
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -795,7 +802,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
c->cache->inode_item.st_size = new_cache_size;
|
||||
c->cache->inode_item.st_blocks = new_cache_size;
|
||||
|
||||
flush_fcb(c->cache, TRUE, rollback);
|
||||
flush_fcb(c->cache, TRUE, Irp, rollback);
|
||||
|
||||
*changed = TRUE;
|
||||
} else {
|
||||
|
@ -808,7 +815,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
searchkey.obj_type = TYPE_INODE_ITEM;
|
||||
searchkey.offset = 0;
|
||||
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -820,10 +827,12 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
ii = ExAllocatePoolWithTag(PagedPool, sizeof(INODE_ITEM), ALLOC_TAG);
|
||||
RtlCopyMemory(ii, &c->cache->inode_item, sizeof(INODE_ITEM));
|
||||
|
||||
if (!insert_tree_item(Vcb, Vcb->root_root, c->cache->inode, TYPE_INODE_ITEM, 0, ii, sizeof(INODE_ITEM), NULL, rollback)) {
|
||||
if (!insert_tree_item(Vcb, Vcb->root_root, c->cache->inode, TYPE_INODE_ITEM, 0, ii, sizeof(INODE_ITEM), NULL, Irp, rollback)) {
|
||||
ERR("insert_tree_item failed\n");
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
*changed = TRUE;
|
||||
} else {
|
||||
if (tp.item->size < sizeof(INODE_ITEM)) {
|
||||
ERR("(%llx,%x,%llx) was %u bytes, expected %u\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, tp.item->size, sizeof(INODE_ITEM));
|
||||
|
@ -837,7 +846,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
searchkey.obj_type = 0;
|
||||
searchkey.offset = c->offset;
|
||||
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -861,7 +870,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, BOOL* chan
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS allocate_cache(device_extension* Vcb, BOOL* changed, LIST_ENTRY* rollback) {
|
||||
NTSTATUS allocate_cache(device_extension* Vcb, BOOL* changed, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
LIST_ENTRY* le = Vcb->chunks_changed.Flink;
|
||||
NTSTATUS Status;
|
||||
|
||||
|
@ -871,9 +880,9 @@ NTSTATUS allocate_cache(device_extension* Vcb, BOOL* changed, LIST_ENTRY* rollba
|
|||
BOOL b;
|
||||
chunk* c = CONTAINING_RECORD(le, chunk, list_entry_changed);
|
||||
|
||||
ExAcquireResourceExclusiveLite(&c->nonpaged->lock, TRUE);
|
||||
Status = allocate_cache_chunk(Vcb, c, &b, rollback);
|
||||
ExReleaseResourceLite(&c->nonpaged->lock);
|
||||
ExAcquireResourceExclusiveLite(&c->lock, TRUE);
|
||||
Status = allocate_cache_chunk(Vcb, c, &b, Irp, rollback);
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
|
||||
if (b)
|
||||
*changed = TRUE;
|
||||
|
@ -889,7 +898,25 @@ NTSTATUS allocate_cache(device_extension* Vcb, BOOL* changed, LIST_ENTRY* rollba
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void _space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func) {
|
||||
static void add_rollback_space(LIST_ENTRY* rollback, BOOL add, LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, chunk* c) {
|
||||
rollback_space* rs;
|
||||
|
||||
rs = ExAllocatePoolWithTag(PagedPool, sizeof(rollback_space), ALLOC_TAG);
|
||||
if (!rs) {
|
||||
ERR("out of memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rs->list = list;
|
||||
rs->list_size = list_size;
|
||||
rs->address = address;
|
||||
rs->length = length;
|
||||
rs->chunk = c;
|
||||
|
||||
add_rollback(rollback, add ? ROLLBACK_ADD_SPACE : ROLLBACK_SUBTRACT_SPACE, rs);
|
||||
}
|
||||
|
||||
void _space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, chunk* c, LIST_ENTRY* rollback, const char* func) {
|
||||
LIST_ENTRY* le;
|
||||
space *s, *s2;
|
||||
|
||||
|
@ -912,7 +939,8 @@ void _space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, U
|
|||
if (list_size)
|
||||
InsertTailList(list_size, &s->list_entry_size);
|
||||
|
||||
// FIXME - insert rollback entry
|
||||
if (rollback)
|
||||
add_rollback_space(rollback, TRUE, list, list_size, address, length, c);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -928,9 +956,11 @@ void _space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, U
|
|||
// new entry envelops old one completely
|
||||
if (address <= s2->address && address + length >= s2->address + s2->size) {
|
||||
if (address < s2->address) {
|
||||
if (rollback)
|
||||
add_rollback_space(rollback, TRUE, list, list_size, address, s2->address - address, c);
|
||||
|
||||
s2->size += s2->address - address;
|
||||
s2->address = address;
|
||||
// FIXME - insert rollback
|
||||
|
||||
while (s2->list_entry.Blink != list) {
|
||||
space* s3 = CONTAINING_RECORD(s2->list_entry.Blink, space, list_entry);
|
||||
|
@ -951,8 +981,10 @@ void _space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, U
|
|||
}
|
||||
|
||||
if (length > s2->size) {
|
||||
if (rollback)
|
||||
add_rollback_space(rollback, TRUE, list, list_size, s2->address + s2->size, address + length - s2->address - s2->size, c);
|
||||
|
||||
s2->size = length;
|
||||
// FIXME - insert rollback
|
||||
|
||||
while (s2->list_entry.Flink != list) {
|
||||
space* s3 = CONTAINING_RECORD(s2->list_entry.Flink, space, list_entry);
|
||||
|
@ -981,9 +1013,11 @@ void _space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, U
|
|||
|
||||
// new entry overlaps start of old one
|
||||
if (address < s2->address && address + length >= s2->address) {
|
||||
if (rollback)
|
||||
add_rollback_space(rollback, TRUE, list, list_size, address, s2->address - address, c);
|
||||
|
||||
s2->size += s2->address - address;
|
||||
s2->address = address;
|
||||
// FIXME - insert rollback
|
||||
|
||||
while (s2->list_entry.Blink != list) {
|
||||
space* s3 = CONTAINING_RECORD(s2->list_entry.Blink, space, list_entry);
|
||||
|
@ -1012,8 +1046,10 @@ void _space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, U
|
|||
|
||||
// new entry overlaps end of old one
|
||||
if (address <= s2->address + s2->size && address + length > s2->address + s2->size) {
|
||||
if (rollback)
|
||||
add_rollback_space(rollback, TRUE, list, list_size, address, s2->address + s2->size - address, c);
|
||||
|
||||
s2->size = address + length - s2->address;
|
||||
// FIXME - insert rollback
|
||||
|
||||
while (s2->list_entry.Flink != list) {
|
||||
space* s3 = CONTAINING_RECORD(s2->list_entry.Flink, space, list_entry);
|
||||
|
@ -1048,7 +1084,9 @@ void _space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, U
|
|||
return;
|
||||
}
|
||||
|
||||
// FIXME - insert rollback
|
||||
if (rollback)
|
||||
add_rollback_space(rollback, TRUE, list, list_size, address, length, c);
|
||||
|
||||
s->address = address;
|
||||
s->size = length;
|
||||
InsertHeadList(s2->list_entry.Blink, &s->list_entry);
|
||||
|
@ -1065,7 +1103,6 @@ void _space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, U
|
|||
// check if contiguous with last entry
|
||||
if (s2->address + s2->size == address) {
|
||||
s2->size += length;
|
||||
// FIXME - insert rollback
|
||||
|
||||
if (list_size) {
|
||||
RemoveEntryList(&s2->list_entry_size);
|
||||
|
@ -1090,7 +1127,8 @@ void _space_list_add2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, U
|
|||
if (list_size)
|
||||
order_space_entry(s, list_size);
|
||||
|
||||
// FIXME - insert rollback
|
||||
if (rollback)
|
||||
add_rollback_space(rollback, TRUE, list, list_size, address, length, c);
|
||||
}
|
||||
|
||||
static void space_list_merge(LIST_ENTRY* spacelist, LIST_ENTRY* spacelist_size, LIST_ENTRY* deleting) {
|
||||
|
@ -1108,7 +1146,7 @@ static void space_list_merge(LIST_ENTRY* spacelist, LIST_ENTRY* spacelist_size,
|
|||
}
|
||||
}
|
||||
|
||||
static NTSTATUS update_chunk_cache(device_extension* Vcb, chunk* c, BTRFS_TIME* now, LIST_ENTRY* rollback) {
|
||||
static NTSTATUS update_chunk_cache(device_extension* Vcb, chunk* c, BTRFS_TIME* now, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
NTSTATUS Status;
|
||||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
|
@ -1159,7 +1197,7 @@ static NTSTATUS update_chunk_cache(device_extension* Vcb, chunk* c, BTRFS_TIME*
|
|||
c->cache->inode_item.sequence++;
|
||||
c->cache->inode_item.st_ctime = *now;
|
||||
|
||||
flush_fcb(c->cache, TRUE, rollback);
|
||||
flush_fcb(c->cache, TRUE, Irp, rollback);
|
||||
|
||||
// update free_space item
|
||||
|
||||
|
@ -1167,7 +1205,7 @@ static NTSTATUS update_chunk_cache(device_extension* Vcb, chunk* c, BTRFS_TIME*
|
|||
searchkey.obj_type = 0;
|
||||
searchkey.offset = c->offset;
|
||||
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->root_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -1211,9 +1249,9 @@ static NTSTATUS update_chunk_cache(device_extension* Vcb, chunk* c, BTRFS_TIME*
|
|||
|
||||
// write cache
|
||||
|
||||
Status = do_nocow_write(Vcb, 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, NULL, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("do_nocow_write returned %08x\n", Status);
|
||||
ERR("do_write_file returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -1222,7 +1260,7 @@ static NTSTATUS update_chunk_cache(device_extension* Vcb, chunk* c, BTRFS_TIME*
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS update_chunk_caches(device_extension* Vcb, LIST_ENTRY* rollback) {
|
||||
NTSTATUS update_chunk_caches(device_extension* Vcb, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
LIST_ENTRY* le = Vcb->chunks_changed.Flink;
|
||||
NTSTATUS Status;
|
||||
chunk* c;
|
||||
|
@ -1235,9 +1273,9 @@ NTSTATUS update_chunk_caches(device_extension* Vcb, LIST_ENTRY* rollback) {
|
|||
while (le != &Vcb->chunks_changed) {
|
||||
c = CONTAINING_RECORD(le, chunk, list_entry_changed);
|
||||
|
||||
ExAcquireResourceExclusiveLite(&c->nonpaged->lock, TRUE);
|
||||
Status = update_chunk_cache(Vcb, c, &now, rollback);
|
||||
ExReleaseResourceLite(&c->nonpaged->lock);
|
||||
ExAcquireResourceExclusiveLite(&c->lock, TRUE);
|
||||
Status = update_chunk_cache(Vcb, c, &now, Irp, rollback);
|
||||
ExReleaseResourceLite(&c->lock);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("update_chunk_cache(%llx) returned %08x\n", c->offset, Status);
|
||||
|
@ -1260,10 +1298,10 @@ void _space_list_add(device_extension* Vcb, chunk* c, BOOL deleting, UINT64 addr
|
|||
if (!c->list_entry_changed.Flink)
|
||||
InsertTailList(&Vcb->chunks_changed, &c->list_entry_changed);
|
||||
|
||||
_space_list_add2(list, deleting ? NULL : &c->space_size, address, length, rollback, func);
|
||||
_space_list_add2(list, deleting ? NULL : &c->space_size, address, length, c, rollback, func);
|
||||
}
|
||||
|
||||
void _space_list_subtract2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, LIST_ENTRY* rollback, const char* func) {
|
||||
void _space_list_subtract2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 address, UINT64 length, chunk* c, LIST_ENTRY* rollback, const char* func) {
|
||||
LIST_ENTRY *le, *le2;
|
||||
space *s, *s2;
|
||||
|
||||
|
@ -1283,7 +1321,9 @@ void _space_list_subtract2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 addre
|
|||
return;
|
||||
|
||||
if (s2->address >= address && s2->address + s2->size <= address + length) { // remove entry entirely
|
||||
// FIXME - insert rollback
|
||||
if (rollback)
|
||||
add_rollback_space(rollback, FALSE, list, list_size, s2->address, s2->size, c);
|
||||
|
||||
RemoveEntryList(&s2->list_entry);
|
||||
|
||||
if (list_size)
|
||||
|
@ -1292,7 +1332,8 @@ void _space_list_subtract2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 addre
|
|||
ExFreePool(s2);
|
||||
} else if (address + length > s2->address && address + length < s2->address + s2->size) {
|
||||
if (address > s2->address) { // cut out hole
|
||||
// FIXME - insert rollback
|
||||
if (rollback)
|
||||
add_rollback_space(rollback, FALSE, list, list_size, address, length, c);
|
||||
|
||||
s = ExAllocatePoolWithTag(PagedPool, sizeof(space), ALLOC_TAG);
|
||||
|
||||
|
@ -1316,9 +1357,11 @@ void _space_list_subtract2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 addre
|
|||
|
||||
return;
|
||||
} else { // remove start of entry
|
||||
if (rollback)
|
||||
add_rollback_space(rollback, FALSE, list, list_size, s2->address, address + length - s2->address, c);
|
||||
|
||||
s2->size -= address + length - s2->address;
|
||||
s2->address = address + length;
|
||||
// FIXME - insert rollback
|
||||
|
||||
if (list_size) {
|
||||
RemoveEntryList(&s2->list_entry_size);
|
||||
|
@ -1326,7 +1369,9 @@ void _space_list_subtract2(LIST_ENTRY* list, LIST_ENTRY* list_size, UINT64 addre
|
|||
}
|
||||
}
|
||||
} else if (address > s2->address && address < s2->address + s2->size) { // remove end of entry
|
||||
// FIXME - insert rollback
|
||||
if (rollback)
|
||||
add_rollback_space(rollback, FALSE, list, list_size, address, s2->address + s2->size - address, c);
|
||||
|
||||
s2->size = address - s2->address;
|
||||
|
||||
if (list_size) {
|
||||
|
@ -1347,5 +1392,5 @@ void _space_list_subtract(device_extension* Vcb, chunk* c, BOOL deleting, UINT64
|
|||
if (!c->list_entry_changed.Flink)
|
||||
InsertTailList(&Vcb->chunks_changed, &c->list_entry_changed);
|
||||
|
||||
_space_list_subtract2(list, deleting ? NULL : &c->space_size, address, length, rollback, func);
|
||||
_space_list_subtract2(list, deleting ? NULL : &c->space_size, address, length, c, rollback, func);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,20 @@
|
|||
/* 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"
|
||||
|
||||
struct pnp_context;
|
||||
|
@ -176,8 +193,8 @@ static NTSTATUS pnp_query_remove_device(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
|
||||
ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE);
|
||||
|
||||
if (Vcb->need_write)
|
||||
do_write(Vcb, &rollback);
|
||||
if (Vcb->need_write && !Vcb->readonly)
|
||||
do_write(Vcb, Irp, &rollback);
|
||||
|
||||
clear_rollback(&rollback);
|
||||
|
||||
|
@ -219,7 +236,14 @@ static NTSTATUS pnp_start_device(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
}
|
||||
|
||||
static NTSTATUS pnp_surprise_removal(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
||||
FIXME("STUB\n");
|
||||
device_extension* Vcb = DeviceObject->DeviceExtension;
|
||||
|
||||
TRACE("(%p, %p)\n", DeviceObject, Irp);
|
||||
|
||||
if (DeviceObject->Vpb->Flags & VPB_MOUNTED) {
|
||||
uninit(Vcb, FALSE);
|
||||
Vcb->Vpb->Flags &= ~VPB_MOUNTED;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/* 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"
|
||||
|
||||
enum read_data_status {
|
||||
|
@ -159,6 +176,12 @@ NTSTATUS STDCALL read_data(device_extension* Vcb, UINT64 addr, UINT32 length, UI
|
|||
UINT64 *stripestart = NULL, *stripeend = NULL;
|
||||
UINT16 startoffstripe;
|
||||
|
||||
Status = verify_vcb(Vcb, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("verify_vcb returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (Vcb->log_to_phys_loaded) {
|
||||
chunk* c = get_chunk_from_address(Vcb, addr);
|
||||
|
||||
|
@ -433,7 +456,23 @@ NTSTATUS STDCALL read_data(device_extension* Vcb, UINT64 addr, UINT32 length, UI
|
|||
|
||||
for (i = 0; i < ci->num_stripes; i++) {
|
||||
if (context->stripes[i].status == ReadDataStatus_Error && IoIsErrorUserInduced(context->stripes[i].iosb.Status)) {
|
||||
IoSetHardErrorOrVerifyDevice(context->stripes[i].Irp, devices[i]->devobj);
|
||||
if (Irp && context->stripes[i].iosb.Status == STATUS_VERIFY_REQUIRED) {
|
||||
PDEVICE_OBJECT dev;
|
||||
|
||||
dev = IoGetDeviceToVerify(Irp->Tail.Overlay.Thread);
|
||||
IoSetDeviceToVerify(Irp->Tail.Overlay.Thread, NULL);
|
||||
|
||||
if (!dev) {
|
||||
dev = IoGetDeviceToVerify(PsGetCurrentThread());
|
||||
IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
|
||||
}
|
||||
|
||||
dev = Vcb->Vpb ? Vcb->Vpb->RealDevice : NULL;
|
||||
|
||||
if (dev)
|
||||
IoVerifyVolume(dev, FALSE);
|
||||
}
|
||||
// IoSetHardErrorOrVerifyDevice(context->stripes[i].Irp, devices[i]->devobj);
|
||||
|
||||
Status = context->stripes[i].iosb.Status;
|
||||
goto exit;
|
||||
|
@ -702,7 +741,7 @@ static NTSTATUS STDCALL read_stream(fcb* fcb, UINT8* data, UINT64 start, ULONG l
|
|||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS load_csum_from_disk(device_extension* Vcb, UINT32* csum, UINT64 start, UINT64 length) {
|
||||
static NTSTATUS load_csum_from_disk(device_extension* Vcb, UINT32* csum, UINT64 start, UINT64 length, PIRP Irp) {
|
||||
NTSTATUS Status;
|
||||
KEY searchkey;
|
||||
traverse_ptr tp, next_tp;
|
||||
|
@ -713,7 +752,7 @@ static NTSTATUS load_csum_from_disk(device_extension* Vcb, UINT32* csum, UINT64
|
|||
searchkey.obj_type = TYPE_EXTENT_CSUM;
|
||||
searchkey.offset = start;
|
||||
|
||||
Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, FALSE);
|
||||
Status = find_item(Vcb, Vcb->checksum_root, &tp, &searchkey, FALSE, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("error - find_item returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -742,7 +781,7 @@ static NTSTATUS load_csum_from_disk(device_extension* Vcb, UINT32* csum, UINT64
|
|||
break;
|
||||
}
|
||||
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE);
|
||||
b = find_next_item(Vcb, &tp, &next_tp, FALSE, Irp);
|
||||
|
||||
if (b)
|
||||
tp = next_tp;
|
||||
|
@ -756,7 +795,7 @@ static NTSTATUS load_csum_from_disk(device_extension* Vcb, UINT32* csum, UINT64
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS load_csum(device_extension* Vcb, UINT64 start, UINT64 length, UINT32** pcsum) {
|
||||
static NTSTATUS load_csum(device_extension* Vcb, UINT64 start, UINT64 length, UINT32** pcsum, PIRP Irp) {
|
||||
UINT32* csum = NULL;
|
||||
NTSTATUS Status;
|
||||
UINT64 end;
|
||||
|
@ -827,7 +866,7 @@ static NTSTATUS load_csum(device_extension* Vcb, UINT64 start, UINT64 length, UI
|
|||
runlength = RtlFindFirstRunClear(&bmp, &index);
|
||||
|
||||
while (runlength != 0) {
|
||||
Status = load_csum_from_disk(Vcb, &csum[index], start + (index * Vcb->superblock.sector_size), runlength);
|
||||
Status = load_csum_from_disk(Vcb, &csum[index], start + (index * Vcb->superblock.sector_size), runlength, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("load_csum_from_disk returned %08x\n", Status);
|
||||
goto end;
|
||||
|
@ -854,72 +893,23 @@ NTSTATUS STDCALL read_file(fcb* fcb, UINT8* data, UINT64 start, UINT64 length, U
|
|||
NTSTATUS Status;
|
||||
EXTENT_DATA* ed;
|
||||
UINT64 bytes_read = 0;
|
||||
UINT64 last_end;
|
||||
LIST_ENTRY* le;
|
||||
|
||||
TRACE("(%p, %p, %llx, %llx, %p)\n", fcb, data, start, length, pbr);
|
||||
|
||||
if (pbr)
|
||||
*pbr = 0;
|
||||
|
||||
if (start >= fcb->inode_item.st_size) {
|
||||
WARN("Tried to read beyond end of file\n");
|
||||
Status = STATUS_END_OF_FILE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
le = fcb->extents.Flink;
|
||||
|
||||
while (le != &fcb->extents) {
|
||||
extent* ext = CONTAINING_RECORD(le, extent, list_entry);
|
||||
|
||||
if (!ext->ignore) {
|
||||
if (ext->offset == start)
|
||||
break;
|
||||
else if (ext->offset > start) {
|
||||
LIST_ENTRY* le2 = le->Blink;
|
||||
|
||||
ext = NULL;
|
||||
|
||||
while (le2 != &fcb->extents) {
|
||||
extent* ext2 = CONTAINING_RECORD(le2, extent, list_entry);
|
||||
|
||||
if (!ext2->ignore) {
|
||||
le = le2;
|
||||
ext = ext2;
|
||||
break;
|
||||
}
|
||||
|
||||
le2 = le2->Blink;
|
||||
}
|
||||
|
||||
if (!ext) {
|
||||
ERR("first extent was after offset\n");
|
||||
Status = STATUS_INTERNAL_ERROR;
|
||||
goto exit;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
if (le == &fcb->extents) {
|
||||
LIST_ENTRY* le2 = le->Blink;
|
||||
extent* ext = NULL;
|
||||
|
||||
while (le2 != &fcb->extents) {
|
||||
extent* ext2 = CONTAINING_RECORD(le2, extent, list_entry);
|
||||
|
||||
if (!ext2->ignore) {
|
||||
le = le2;
|
||||
ext = ext2;
|
||||
break;
|
||||
}
|
||||
|
||||
le2 = le2->Blink;
|
||||
}
|
||||
|
||||
if (!ext) {
|
||||
ERR("could not find extent\n");
|
||||
Status = STATUS_INTERNAL_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
last_end = start;
|
||||
|
||||
while (le != &fcb->extents) {
|
||||
UINT64 len;
|
||||
|
@ -929,33 +919,25 @@ NTSTATUS STDCALL read_file(fcb* fcb, UINT8* data, UINT64 start, UINT64 length, U
|
|||
if (!ext->ignore) {
|
||||
ed = ext->data;
|
||||
|
||||
if (ext->datalen < sizeof(EXTENT_DATA)) {
|
||||
ERR("extent %llx was %u bytes, expected at least %u\n", ext->offset, ext->datalen, sizeof(EXTENT_DATA));
|
||||
Status = STATUS_INTERNAL_ERROR;
|
||||
goto exit;
|
||||
ed2 = (ed->type == EXTENT_TYPE_REGULAR || ed->type == EXTENT_TYPE_PREALLOC) ? (EXTENT_DATA2*)ed->data : NULL;
|
||||
|
||||
len = ed2 ? ed2->num_bytes : ed->decoded_size;
|
||||
|
||||
if (ext->offset + len <= start) {
|
||||
last_end = ext->offset + len;
|
||||
goto nextitem;
|
||||
}
|
||||
|
||||
if ((ed->type == EXTENT_TYPE_REGULAR || ed->type == EXTENT_TYPE_PREALLOC) && ext->datalen < sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2)) {
|
||||
ERR("extent %llx was %u bytes, expected at least %u\n", ext->offset, ext->datalen, sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2));
|
||||
Status = STATUS_INTERNAL_ERROR;
|
||||
goto exit;
|
||||
if (ext->offset > last_end && ext->offset > start + bytes_read) {
|
||||
UINT32 read = min(length, ext->offset - max(start, last_end));
|
||||
|
||||
RtlZeroMemory(data + bytes_read, read);
|
||||
bytes_read += read;
|
||||
length -= read;
|
||||
}
|
||||
|
||||
ed2 = (EXTENT_DATA2*)ed->data;
|
||||
|
||||
len = ed->type == EXTENT_TYPE_INLINE ? ed->decoded_size : ed2->num_bytes;
|
||||
|
||||
if (ext->offset + len < start) {
|
||||
ERR("Tried to read beyond end of file\n");
|
||||
Status = STATUS_END_OF_FILE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (ed->compression != BTRFS_COMPRESSION_NONE) {
|
||||
FIXME("FIXME - compression not yet supported\n");
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
goto exit;
|
||||
}
|
||||
if (length == 0 || ext->offset > start + bytes_read + length)
|
||||
break;
|
||||
|
||||
if (ed->encryption != BTRFS_ENCRYPTION_NONE) {
|
||||
WARN("Encryption not supported\n");
|
||||
|
@ -979,6 +961,8 @@ NTSTATUS STDCALL read_file(fcb* fcb, UINT8* data, UINT64 start, UINT64 length, U
|
|||
|
||||
RtlCopyMemory(data + bytes_read, &ed->data[off], read);
|
||||
|
||||
// FIXME - can we have compressed inline extents?
|
||||
|
||||
bytes_read += read;
|
||||
length -= read;
|
||||
break;
|
||||
|
@ -989,16 +973,13 @@ NTSTATUS STDCALL read_file(fcb* fcb, UINT8* data, UINT64 start, UINT64 length, U
|
|||
UINT64 off = start + bytes_read - ext->offset;
|
||||
UINT32 to_read, read;
|
||||
UINT8* buf;
|
||||
UINT32 *csum, bumpoff = 0;
|
||||
UINT64 addr;
|
||||
|
||||
read = len - off;
|
||||
if (read > length) read = length;
|
||||
|
||||
if (ed2->address == 0) {
|
||||
RtlZeroMemory(data + bytes_read, read);
|
||||
} else {
|
||||
UINT32 *csum, bumpoff = 0;
|
||||
UINT64 addr;
|
||||
|
||||
if (ed->compression == BTRFS_COMPRESSION_NONE) {
|
||||
addr = ed2->address + ed2->offset + off;
|
||||
to_read = sector_align(read, fcb->Vcb->superblock.sector_size);
|
||||
|
||||
|
@ -1007,41 +988,71 @@ NTSTATUS STDCALL read_file(fcb* fcb, UINT8* data, UINT64 start, UINT64 length, U
|
|||
addr -= bumpoff;
|
||||
to_read = sector_align(read + bumpoff, fcb->Vcb->superblock.sector_size);
|
||||
}
|
||||
} else {
|
||||
addr = ed2->address;
|
||||
to_read = sector_align(ed2->size, fcb->Vcb->superblock.sector_size);
|
||||
}
|
||||
|
||||
buf = ExAllocatePoolWithTag(PagedPool, to_read, ALLOC_TAG);
|
||||
|
||||
if (!buf) {
|
||||
ERR("out of memory\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(fcb->inode_item.flags & BTRFS_INODE_NODATASUM)) {
|
||||
Status = load_csum(fcb->Vcb, addr, to_read / fcb->Vcb->superblock.sector_size, &csum, Irp);
|
||||
|
||||
buf = ExAllocatePoolWithTag(PagedPool, to_read, ALLOC_TAG);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("load_csum returned %08x\n", Status);
|
||||
ExFreePool(buf);
|
||||
goto exit;
|
||||
}
|
||||
} else
|
||||
csum = NULL;
|
||||
|
||||
Status = read_data(fcb->Vcb, addr, to_read, csum, FALSE, buf, NULL, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("read_data returned %08x\n", Status);
|
||||
ExFreePool(buf);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (ed->compression == BTRFS_COMPRESSION_NONE) {
|
||||
RtlCopyMemory(data + bytes_read, buf + bumpoff, read);
|
||||
} else {
|
||||
UINT8* decomp = NULL;
|
||||
|
||||
if (!buf) {
|
||||
// FIXME - don't mess around with decomp if we're reading the whole extent
|
||||
|
||||
decomp = ExAllocatePoolWithTag(PagedPool, ed->decoded_size, ALLOC_TAG);
|
||||
if (!decomp) {
|
||||
ERR("out of memory\n");
|
||||
ExFreePool(buf);
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(fcb->inode_item.flags & BTRFS_INODE_NODATASUM)) {
|
||||
Status = load_csum(fcb->Vcb, addr, to_read / fcb->Vcb->superblock.sector_size, &csum);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("load_csum returned %08x\n", Status);
|
||||
ExFreePool(buf);
|
||||
goto exit;
|
||||
}
|
||||
} else
|
||||
csum = NULL;
|
||||
Status = decompress(ed->compression, buf, ed2->size, decomp, ed->decoded_size);
|
||||
|
||||
Status = read_data(fcb->Vcb, addr, to_read, csum, FALSE, buf, NULL, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("read_data returned %08x\n", Status);
|
||||
ERR("decompress returned %08x\n", Status);
|
||||
ExFreePool(buf);
|
||||
ExFreePool(decomp);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
RtlCopyMemory(data + bytes_read, buf + bumpoff, read);
|
||||
RtlCopyMemory(data + bytes_read, decomp + ed2->offset + off, min(read, ed2->num_bytes - off));
|
||||
|
||||
ExFreePool(buf);
|
||||
|
||||
if (csum)
|
||||
ExFreePool(csum);
|
||||
ExFreePool(decomp);
|
||||
}
|
||||
|
||||
ExFreePool(buf);
|
||||
|
||||
if (csum)
|
||||
ExFreePool(csum);
|
||||
|
||||
bytes_read += read;
|
||||
length -= read;
|
||||
|
||||
|
@ -1068,14 +1079,26 @@ NTSTATUS STDCALL read_file(fcb* fcb, UINT8* data, UINT64 start, UINT64 length, U
|
|||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
last_end = ext->offset + len;
|
||||
|
||||
if (length == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
nextitem:
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
if (length > 0 && start + bytes_read < fcb->inode_item.st_size) {
|
||||
UINT32 read = min(fcb->inode_item.st_size - start - bytes_read, length);
|
||||
|
||||
RtlZeroMemory(data + bytes_read, read);
|
||||
|
||||
bytes_read += read;
|
||||
length -= read;
|
||||
}
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
if (pbr)
|
||||
*pbr = bytes_read;
|
||||
|
@ -1131,7 +1154,7 @@ NTSTATUS do_read(PIRP Irp, BOOL wait, ULONG* bytes_read) {
|
|||
}
|
||||
|
||||
if (start >= fcb->Header.ValidDataLength.QuadPart) {
|
||||
length = min(start + length, fcb->Header.FileSize.QuadPart) - fcb->Header.ValidDataLength.QuadPart;
|
||||
length = min(length, min(start + length, fcb->Header.FileSize.QuadPart) - fcb->Header.ValidDataLength.QuadPart);
|
||||
RtlZeroMemory(data, length);
|
||||
Irp->IoStatus.Information = *bytes_read = length;
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -1233,7 +1256,7 @@ NTSTATUS STDCALL drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
BOOL top_level;
|
||||
fcb* fcb;
|
||||
ccb* ccb;
|
||||
BOOL tree_lock = FALSE, fcb_lock = FALSE;
|
||||
BOOL tree_lock = FALSE, fcb_lock = FALSE, pagefile;
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
|
||||
|
@ -1266,6 +1289,12 @@ NTSTATUS STDCALL drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (fcb == Vcb->volume_fcb) {
|
||||
TRACE("not allowing read of volume FCB\n");
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ccb = FileObject->FsContext2;
|
||||
|
||||
if (!ccb) {
|
||||
|
@ -1280,14 +1309,18 @@ NTSTATUS STDCALL drv_read(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
goto exit;
|
||||
}
|
||||
|
||||
pagefile = fcb->Header.Flags2 & FSRTL_FLAG2_IS_PAGING_FILE && Irp->Flags & IRP_PAGING_IO;
|
||||
|
||||
if (Irp->Flags & IRP_NOCACHE) {
|
||||
if (!ExAcquireResourceSharedLite(&Vcb->tree_lock, IoIsOperationSynchronous(Irp))) {
|
||||
Status = STATUS_PENDING;
|
||||
IoMarkIrpPending(Irp);
|
||||
goto exit;
|
||||
if (!pagefile) {
|
||||
if (!ExAcquireResourceSharedLite(&Vcb->tree_lock, IoIsOperationSynchronous(Irp))) {
|
||||
Status = STATUS_PENDING;
|
||||
IoMarkIrpPending(Irp);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
tree_lock = TRUE;
|
||||
}
|
||||
|
||||
tree_lock = TRUE;
|
||||
|
||||
if (!ExAcquireResourceSharedLite(fcb->Header.Resource, IoIsOperationSynchronous(Irp))) {
|
||||
Status = STATUS_PENDING;
|
||||
|
|
|
@ -1,20 +1,48 @@
|
|||
/* 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"
|
||||
|
||||
extern UNICODE_STRING log_device, log_file, registry_path;
|
||||
|
||||
static WCHAR option_mounted[] = L"Mounted";
|
||||
static WCHAR option_ignore[] = L"Ignore";
|
||||
|
||||
#define hex_digit(c) ((c) >= 0 && (c) <= 9) ? ((c) + '0') : ((c) - 10 + 'a')
|
||||
|
||||
NTSTATUS registry_load_volume_options(BTRFS_UUID* uuid, mount_options* options) {
|
||||
UNICODE_STRING path, ignoreus;
|
||||
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;
|
||||
OBJECT_ATTRIBUTES oa;
|
||||
NTSTATUS Status;
|
||||
ULONG i, j, kvfilen, index, retlen;
|
||||
KEY_VALUE_FULL_INFORMATION* kvfi = NULL;
|
||||
HANDLE h;
|
||||
|
||||
options->compress = mount_compress;
|
||||
options->compress_force = mount_compress_force;
|
||||
options->compress_type = mount_compress_type > BTRFS_COMPRESSION_LZO ? 0 : mount_compress_type;
|
||||
options->readonly = FALSE;
|
||||
options->zlib_level = mount_zlib_level;
|
||||
options->flush_interval = mount_flush_interval;
|
||||
options->max_inline = min(mount_max_inline, Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node) - sizeof(EXTENT_DATA) + 1);
|
||||
options->subvol_id = 0;
|
||||
|
||||
path.Length = path.MaximumLength = registry_path.Length + (37 * sizeof(WCHAR));
|
||||
path.Buffer = ExAllocatePoolWithTag(PagedPool, path.Length, ALLOC_TAG);
|
||||
|
||||
|
@ -62,8 +90,15 @@ NTSTATUS registry_load_volume_options(BTRFS_UUID* uuid, mount_options* options)
|
|||
|
||||
index = 0;
|
||||
|
||||
ignoreus.Buffer = option_ignore;
|
||||
ignoreus.Length = ignoreus.MaximumLength = wcslen(option_ignore) * sizeof(WCHAR);
|
||||
RtlInitUnicodeString(&ignoreus, L"Ignore");
|
||||
RtlInitUnicodeString(&compressus, L"Compress");
|
||||
RtlInitUnicodeString(&compressforceus, L"CompressForce");
|
||||
RtlInitUnicodeString(&compresstypeus, L"CompressType");
|
||||
RtlInitUnicodeString(&readonlyus, L"Readonly");
|
||||
RtlInitUnicodeString(&zliblevelus, L"ZlibLevel");
|
||||
RtlInitUnicodeString(&flushintervalus, L"FlushInterval");
|
||||
RtlInitUnicodeString(&maxinlineus, L"MaxInline");
|
||||
RtlInitUnicodeString(&subvolidus, L"SubvolId");
|
||||
|
||||
do {
|
||||
Status = ZwEnumerateValueKey(h, index, KeyValueFullInformation, kvfi, kvfilen, &retlen);
|
||||
|
@ -80,12 +115,53 @@ NTSTATUS registry_load_volume_options(BTRFS_UUID* uuid, mount_options* options)
|
|||
DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
|
||||
|
||||
options->ignore = *val != 0 ? TRUE : FALSE;
|
||||
} else if (FsRtlAreNamesEqual(&compressus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
|
||||
DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
|
||||
|
||||
options->compress = *val != 0 ? TRUE : FALSE;
|
||||
} else if (FsRtlAreNamesEqual(&compressforceus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
|
||||
DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
|
||||
|
||||
options->compress_force = *val != 0 ? TRUE : FALSE;
|
||||
} else if (FsRtlAreNamesEqual(&compresstypeus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
|
||||
DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
|
||||
|
||||
options->compress_type = *val > BTRFS_COMPRESSION_LZO ? 0 : *val;
|
||||
} else if (FsRtlAreNamesEqual(&readonlyus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
|
||||
DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
|
||||
|
||||
options->readonly = *val != 0 ? TRUE : FALSE;
|
||||
} else if (FsRtlAreNamesEqual(&zliblevelus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
|
||||
DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
|
||||
|
||||
options->zlib_level = *val;
|
||||
} else if (FsRtlAreNamesEqual(&flushintervalus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
|
||||
DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
|
||||
|
||||
options->flush_interval = *val;
|
||||
} else if (FsRtlAreNamesEqual(&maxinlineus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_DWORD) {
|
||||
DWORD* val = (DWORD*)((UINT8*)kvfi + kvfi->DataOffset);
|
||||
|
||||
options->max_inline = min(*val, Vcb->superblock.node_size - sizeof(tree_header) - sizeof(leaf_node) - sizeof(EXTENT_DATA) + 1);
|
||||
} else if (FsRtlAreNamesEqual(&subvolidus, &us, TRUE, NULL) && kvfi->DataOffset > 0 && kvfi->DataLength > 0 && kvfi->Type == REG_QWORD) {
|
||||
UINT64* val = (UINT64*)((UINT8*)kvfi + kvfi->DataOffset);
|
||||
|
||||
options->subvol_id = *val;
|
||||
}
|
||||
} else if (Status != STATUS_NO_MORE_ENTRIES) {
|
||||
ERR("ZwEnumerateValueKey returned %08x\n", Status);
|
||||
goto end2;
|
||||
}
|
||||
} while (NT_SUCCESS(Status));
|
||||
|
||||
if (!options->compress && options->compress_force)
|
||||
options->compress = TRUE;
|
||||
|
||||
if (options->zlib_level > 9)
|
||||
options->zlib_level = 9;
|
||||
|
||||
if (options->flush_interval == 0)
|
||||
options->flush_interval = mount_flush_interval;
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
|
@ -472,38 +548,13 @@ static void read_mappings(PUNICODE_STRING regpath) {
|
|||
ExFreePool(path);
|
||||
}
|
||||
|
||||
void STDCALL read_registry(PUNICODE_STRING regpath) {
|
||||
#ifndef __REACTOS__
|
||||
UNICODE_STRING us;
|
||||
#endif
|
||||
OBJECT_ATTRIBUTES oa;
|
||||
NTSTATUS Status;
|
||||
HANDLE h;
|
||||
ULONG dispos;
|
||||
#ifndef __REACTOS__
|
||||
static void get_registry_value(HANDLE h, WCHAR* string, ULONG type, void* val, ULONG size) {
|
||||
ULONG kvfilen;
|
||||
KEY_VALUE_FULL_INFORMATION* kvfi;
|
||||
#endif
|
||||
UNICODE_STRING us;
|
||||
NTSTATUS Status;
|
||||
|
||||
#ifndef __REACTOS__
|
||||
static WCHAR def_log_file[] = L"\\??\\C:\\btrfs.log";
|
||||
#endif
|
||||
|
||||
read_mappings(regpath);
|
||||
|
||||
InitializeObjectAttributes(&oa, regpath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
|
||||
Status = ZwCreateKey(&h, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &oa, 0, NULL, REG_OPTION_NON_VOLATILE, &dispos);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("ZwCreateKey returned %08x\n", Status);
|
||||
return;
|
||||
}
|
||||
|
||||
reset_subkeys(h, regpath);
|
||||
|
||||
#ifdef _DEBUG
|
||||
RtlInitUnicodeString(&us, L"DebugLogLevel");
|
||||
RtlInitUnicodeString(&us, string);
|
||||
|
||||
kvfi = NULL;
|
||||
kvfilen = 0;
|
||||
|
@ -521,31 +572,75 @@ void STDCALL read_registry(PUNICODE_STRING regpath) {
|
|||
Status = ZwQueryValueKey(h, &us, KeyValueFullInformation, kvfi, kvfilen, &kvfilen);
|
||||
|
||||
if (NT_SUCCESS(Status)) {
|
||||
if (kvfi->Type == REG_DWORD && kvfi->DataLength >= sizeof(UINT32)) {
|
||||
RtlCopyMemory(&debug_log_level, ((UINT8*)kvfi) + kvfi->DataOffset, sizeof(UINT32));
|
||||
if (kvfi->Type == type && kvfi->DataLength >= size) {
|
||||
RtlCopyMemory(val, ((UINT8*)kvfi) + kvfi->DataOffset, size);
|
||||
} else {
|
||||
Status = ZwDeleteValueKey(h, &us);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("ZwDeleteValueKey returned %08x\n", Status);
|
||||
}
|
||||
|
||||
Status = ZwSetValueKey(h, &us, 0, REG_DWORD, &debug_log_level, sizeof(debug_log_level));
|
||||
Status = ZwSetValueKey(h, &us, 0, type, val, size);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("ZwSetValueKey reutrned %08x\n", Status);
|
||||
ERR("ZwSetValueKey returned %08x\n", Status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExFreePool(kvfi);
|
||||
} else if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
|
||||
Status = ZwSetValueKey(h, &us, 0, REG_DWORD, &debug_log_level, sizeof(debug_log_level));
|
||||
Status = ZwSetValueKey(h, &us, 0, type, val, size);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("ZwSetValueKey reutrned %08x\n", Status);
|
||||
ERR("ZwSetValueKey returned %08x\n", Status);
|
||||
}
|
||||
} else {
|
||||
ERR("ZwQueryValueKey returned %08x\n", Status);
|
||||
}
|
||||
}
|
||||
|
||||
void STDCALL read_registry(PUNICODE_STRING regpath) {
|
||||
#ifndef __REACTOS__
|
||||
UNICODE_STRING us;
|
||||
#endif
|
||||
OBJECT_ATTRIBUTES oa;
|
||||
NTSTATUS Status;
|
||||
HANDLE h;
|
||||
ULONG dispos;
|
||||
#ifndef __REACTOS__
|
||||
ULONG kvfilen;
|
||||
KEY_VALUE_FULL_INFORMATION* kvfi;
|
||||
#endif
|
||||
|
||||
#ifndef __REACTOS__
|
||||
static WCHAR def_log_file[] = L"\\??\\C:\\btrfs.log";
|
||||
#endif
|
||||
|
||||
read_mappings(regpath);
|
||||
|
||||
InitializeObjectAttributes(&oa, regpath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
|
||||
Status = ZwCreateKey(&h, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &oa, 0, NULL, REG_OPTION_NON_VOLATILE, &dispos);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("ZwCreateKey returned %08x\n", Status);
|
||||
return;
|
||||
}
|
||||
|
||||
reset_subkeys(h, regpath);
|
||||
|
||||
get_registry_value(h, L"Compress", REG_DWORD, &mount_compress, sizeof(mount_compress));
|
||||
get_registry_value(h, L"CompressForce", REG_DWORD, &mount_compress_force, sizeof(mount_compress_force));
|
||||
get_registry_value(h, L"CompressType", REG_DWORD, &mount_compress_type, sizeof(mount_compress_type));
|
||||
get_registry_value(h, L"ZlibLevel", REG_DWORD, &mount_zlib_level, sizeof(mount_zlib_level));
|
||||
get_registry_value(h, L"FlushInterval", REG_DWORD, &mount_flush_interval, sizeof(mount_flush_interval));
|
||||
get_registry_value(h, L"MaxInline", REG_DWORD, &mount_max_inline, sizeof(mount_max_inline));
|
||||
|
||||
if (mount_flush_interval == 0)
|
||||
mount_flush_interval = 1;
|
||||
|
||||
#ifdef _DEBUG
|
||||
get_registry_value(h, L"DebugLogLevel", REG_DWORD, &debug_log_level, sizeof(debug_log_level));
|
||||
|
||||
RtlInitUnicodeString(&us, L"LogDevice");
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@ NTSTATUS get_reparse_point(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
|||
char* data;
|
||||
NTSTATUS Status;
|
||||
|
||||
// FIXME - check permissions
|
||||
|
||||
TRACE("(%p, %p, %p, %x, %p)\n", DeviceObject, FileObject, buffer, buflen, retlen);
|
||||
|
||||
ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, TRUE);
|
||||
|
@ -134,6 +132,7 @@ end:
|
|||
static NTSTATUS set_symlink(PIRP Irp, file_ref* fileref, REPARSE_DATA_BUFFER* rdb, ULONG buflen, LIST_ENTRY* rollback) {
|
||||
NTSTATUS Status;
|
||||
ULONG minlen;
|
||||
ULONG tlength;
|
||||
UNICODE_STRING subname;
|
||||
ANSI_STRING target;
|
||||
LARGE_INTEGER offset, time;
|
||||
|
@ -155,7 +154,7 @@ static NTSTATUS set_symlink(PIRP Irp, file_ref* fileref, REPARSE_DATA_BUFFER* rd
|
|||
|
||||
fileref->fcb->inode_item.st_mode |= __S_IFLNK;
|
||||
|
||||
Status = truncate_file(fileref->fcb, 0, rollback);
|
||||
Status = truncate_file(fileref->fcb, 0, Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("truncate_file returned %08x\n", Status);
|
||||
return Status;
|
||||
|
@ -187,7 +186,8 @@ static NTSTATUS set_symlink(PIRP Irp, file_ref* fileref, REPARSE_DATA_BUFFER* rd
|
|||
}
|
||||
|
||||
offset.QuadPart = 0;
|
||||
Status = write_file2(fileref->fcb->Vcb, Irp, offset, target.Buffer, (ULONG*)&target.Length, FALSE, TRUE,
|
||||
tlength = target.Length;
|
||||
Status = write_file2(fileref->fcb->Vcb, Irp, offset, target.Buffer, &tlength, FALSE, TRUE,
|
||||
TRUE, FALSE, rollback);
|
||||
ExFreePool(target.Buffer);
|
||||
|
||||
|
@ -221,9 +221,6 @@ NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
ULONG tag;
|
||||
LIST_ENTRY rollback;
|
||||
|
||||
// FIXME - send notification if this succeeds? The attributes will have changed.
|
||||
// FIXME - check permissions
|
||||
|
||||
TRACE("(%p, %p)\n", DeviceObject, Irp);
|
||||
|
||||
InitializeListHead(&rollback);
|
||||
|
@ -241,6 +238,13 @@ NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// It isn't documented what permissions FSCTL_SET_REPARSE_POINT needs, but CreateSymbolicLinkW
|
||||
// creates a file with FILE_WRITE_ATTRIBUTES | DELETE | SYNCHRONIZE.
|
||||
if (!(ccb->access & FILE_WRITE_ATTRIBUTES)) {
|
||||
WARN("insufficient privileges\n");
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
fileref = ccb->fileref;
|
||||
|
||||
if (!fileref) {
|
||||
|
@ -300,7 +304,7 @@ NTSTATUS set_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
|
||||
Status = STATUS_SUCCESS;
|
||||
} else { // otherwise, store as file data
|
||||
Status = truncate_file(fcb, 0, &rollback);
|
||||
Status = truncate_file(fcb, 0, Irp, &rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("truncate_file returned %08x\n", Status);
|
||||
goto end;
|
||||
|
@ -356,8 +360,6 @@ NTSTATUS delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
file_ref* fileref;
|
||||
LIST_ENTRY rollback;
|
||||
|
||||
// FIXME - check permissions
|
||||
|
||||
TRACE("(%p, %p)\n", DeviceObject, Irp);
|
||||
|
||||
InitializeListHead(&rollback);
|
||||
|
@ -368,13 +370,25 @@ NTSTATUS delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
}
|
||||
|
||||
fcb = FileObject->FsContext;
|
||||
|
||||
if (!fcb) {
|
||||
ERR("fcb was NULL\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ccb = FileObject->FsContext2;
|
||||
fileref = ccb ? ccb->fileref : NULL;
|
||||
|
||||
ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, TRUE);
|
||||
ExAcquireResourceExclusiveLite(fcb->Header.Resource, TRUE);
|
||||
if (!ccb) {
|
||||
ERR("ccb was NULL\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
TRACE("%S\n", file_desc(FileObject));
|
||||
if (!(ccb->access & FILE_WRITE_ATTRIBUTES)) {
|
||||
WARN("insufficient privileges\n");
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
fileref = ccb->fileref;
|
||||
|
||||
if (!fileref) {
|
||||
ERR("fileref was NULL\n");
|
||||
|
@ -382,6 +396,11 @@ NTSTATUS delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
goto end;
|
||||
}
|
||||
|
||||
ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, TRUE);
|
||||
ExAcquireResourceExclusiveLite(fcb->Header.Resource, TRUE);
|
||||
|
||||
TRACE("%S\n", file_desc(FileObject));
|
||||
|
||||
if (buflen < offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)) {
|
||||
ERR("buffer was too short\n");
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
|
@ -433,7 +452,7 @@ NTSTATUS delete_reparse_point(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
|
|||
|
||||
// FIXME - do we need to check that the reparse tags match?
|
||||
|
||||
Status = truncate_file(fcb, 0, &rollback);
|
||||
Status = truncate_file(fcb, 0, Irp, &rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("truncate_file returned %08x\n", Status);
|
||||
goto end;
|
||||
|
|
|
@ -201,6 +201,7 @@ void add_user_mapping(WCHAR* sidstring, ULONG sidstringlength, UINT32 uid) {
|
|||
um = ExAllocatePoolWithTag(PagedPool, sizeof(uid_map), ALLOC_TAG);
|
||||
if (!um) {
|
||||
ERR("out of memory\n");
|
||||
ExFreePool(sid);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -210,7 +211,7 @@ void add_user_mapping(WCHAR* sidstring, ULONG sidstringlength, UINT32 uid) {
|
|||
InsertTailList(&uid_map_list, &um->listentry);
|
||||
}
|
||||
|
||||
static void uid_to_sid(UINT32 uid, PSID* sid) {
|
||||
void uid_to_sid(UINT32 uid, PSID* sid) {
|
||||
LIST_ENTRY* le;
|
||||
uid_map* um;
|
||||
sid_header* sh;
|
||||
|
@ -400,12 +401,12 @@ static ACL* load_default_acl() {
|
|||
// }
|
||||
// }
|
||||
|
||||
static BOOL get_sd_from_xattr(fcb* fcb) {
|
||||
static BOOL get_sd_from_xattr(fcb* fcb, PIRP Irp) {
|
||||
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))
|
||||
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");
|
||||
|
@ -654,12 +655,12 @@ end:
|
|||
ExFreePool(groupsid);
|
||||
}
|
||||
|
||||
void fcb_get_sd(fcb* fcb, struct _fcb* parent) {
|
||||
void fcb_get_sd(fcb* fcb, struct _fcb* parent, PIRP Irp) {
|
||||
NTSTATUS Status;
|
||||
PSID usersid = NULL, groupsid = NULL;
|
||||
SECURITY_SUBJECT_CONTEXT subjcont;
|
||||
|
||||
if (get_sd_from_xattr(fcb))
|
||||
if (get_sd_from_xattr(fcb, Irp))
|
||||
return;
|
||||
|
||||
if (!parent) {
|
||||
|
@ -833,8 +834,7 @@ static NTSTATUS STDCALL set_file_security(device_extension* Vcb, PFILE_OBJECT Fi
|
|||
fcb = fileref->parent->fcb;
|
||||
else {
|
||||
ERR("could not find parent fcb for stream\n");
|
||||
Status = STATUS_INTERNAL_ERROR;
|
||||
goto end;
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -985,7 +985,7 @@ NTSTATUS fcb_get_new_sd(fcb* fcb, file_ref* parfileref, ACCESS_STATE* as) {
|
|||
ERR("RtlGetOwnerSecurityDescriptor returned %08x\n", Status);
|
||||
fcb->inode_item.st_uid = UID_NOBODY;
|
||||
} else {
|
||||
fcb->inode_item.st_uid = sid_to_uid(&owner);
|
||||
fcb->inode_item.st_uid = sid_to_uid(owner);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
|
|
@ -25,7 +25,7 @@ typedef struct {
|
|||
LIST_ENTRY list_entry;
|
||||
} rollback_item;
|
||||
|
||||
NTSTATUS STDCALL _load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, tree* parent, const char* func, const char* file, unsigned int line) {
|
||||
NTSTATUS STDCALL _load_tree(device_extension* Vcb, UINT64 addr, root* r, tree** pt, tree* parent, PIRP Irp, const char* func, const char* file, unsigned int line) {
|
||||
UINT8* buf;
|
||||
NTSTATUS Status;
|
||||
tree_header* th;
|
||||
|
@ -42,7 +42,7 @@ NTSTATUS STDCALL _load_tree(device_extension* Vcb, UINT64 addr, root* r, tree**
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Status = read_data(Vcb, addr, Vcb->superblock.node_size, NULL, TRUE, buf, &c, NULL);
|
||||
Status = read_data(Vcb, addr, Vcb->superblock.node_size, NULL, TRUE, buf, &c, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("read_data returned 0x%08x\n", Status);
|
||||
ExFreePool(buf);
|
||||
|
@ -288,7 +288,8 @@ static tree* free_tree2(tree* t, const char* func, const char* file, unsigned in
|
|||
return NULL;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL _do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, BOOL* loaded, const char* func, const char* file, unsigned int line) {
|
||||
NTSTATUS STDCALL _do_load_tree(device_extension* Vcb, tree_holder* th, root* r, tree* t, tree_data* td, BOOL* loaded, PIRP Irp,
|
||||
const char* func, const char* file, unsigned int line) {
|
||||
// KIRQL irql;
|
||||
// tree_holder_nonpaged* thnp = th->nonpaged;
|
||||
BOOL ret;
|
||||
|
@ -325,7 +326,7 @@ NTSTATUS STDCALL _do_load_tree(device_extension* Vcb, tree_holder* th, root* r,
|
|||
if (!th->tree) {
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = _load_tree(Vcb, th->address, r, &th->tree, t, func, file, line);
|
||||
Status = _load_tree(Vcb, th->address, r, &th->tree, t, Irp, func, file, line);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("load_tree returned %08x\n", Status);
|
||||
ExReleaseResourceLite(&r->nonpaged->load_tree_lock);
|
||||
|
@ -389,7 +390,8 @@ static __inline tree_data* next_item(tree* t, tree_data* td) {
|
|||
return CONTAINING_RECORD(le, tree_data, list_entry);
|
||||
}
|
||||
|
||||
static NTSTATUS STDCALL find_item_in_tree(device_extension* Vcb, tree* t, traverse_ptr* tp, const KEY* searchkey, BOOL ignore, const char* func, const char* file, unsigned int line) {
|
||||
static NTSTATUS STDCALL find_item_in_tree(device_extension* Vcb, tree* t, traverse_ptr* tp, const KEY* searchkey, BOOL ignore, PIRP Irp,
|
||||
const char* func, const char* file, unsigned int line) {
|
||||
int cmp;
|
||||
tree_data *td, *lasttd;
|
||||
|
||||
|
@ -399,7 +401,7 @@ static NTSTATUS STDCALL find_item_in_tree(device_extension* Vcb, tree* t, traver
|
|||
td = first_item(t);
|
||||
lasttd = NULL;
|
||||
|
||||
if (!td) return STATUS_INTERNAL_ERROR;
|
||||
if (!td) return STATUS_NOT_FOUND;
|
||||
|
||||
do {
|
||||
cmp = keycmp(searchkey, &td->key);
|
||||
|
@ -437,7 +439,7 @@ static NTSTATUS STDCALL find_item_in_tree(device_extension* Vcb, tree* t, traver
|
|||
oldtp.tree = t;
|
||||
oldtp.item = td;
|
||||
|
||||
while (_find_prev_item(Vcb, &oldtp, tp, TRUE, func, file, line)) {
|
||||
while (_find_prev_item(Vcb, &oldtp, tp, TRUE, Irp, func, file, line)) {
|
||||
if (!tp->item->ignore)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
|
@ -449,14 +451,14 @@ static NTSTATUS STDCALL find_item_in_tree(device_extension* Vcb, tree* t, traver
|
|||
oldtp.tree = t;
|
||||
oldtp.item = td;
|
||||
|
||||
while (_find_next_item(Vcb, &oldtp, tp, TRUE, func, file, line)) {
|
||||
while (_find_next_item(Vcb, &oldtp, tp, TRUE, Irp, func, file, line)) {
|
||||
if (!tp->item->ignore)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
oldtp = *tp;
|
||||
}
|
||||
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
return STATUS_NOT_FOUND;
|
||||
} else {
|
||||
tp->tree = t;
|
||||
tp->item = td;
|
||||
|
@ -472,24 +474,24 @@ static NTSTATUS STDCALL find_item_in_tree(device_extension* Vcb, tree* t, traver
|
|||
}
|
||||
|
||||
if (!td)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
return STATUS_NOT_FOUND;
|
||||
|
||||
// if (i > 0)
|
||||
// TRACE("entering tree from (%x,%x,%x) to (%x,%x,%x) (%p)\n", (UINT32)t->items[i].key.obj_id, t->items[i].key.obj_type, (UINT32)t->items[i].key.offset, (UINT32)t->items[i+1].key.obj_id, t->items[i+1].key.obj_type, (UINT32)t->items[i+1].key.offset, t->items[i].tree);
|
||||
|
||||
Status = _do_load_tree(Vcb, &td->treeholder, t->root, t, td, &loaded, func, file, line);
|
||||
Status = _do_load_tree(Vcb, &td->treeholder, t->root, t, td, &loaded, Irp, func, file, line);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("do_load_tree returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = find_item_in_tree(Vcb, td->treeholder.tree, tp, searchkey, ignore, func, file, line);
|
||||
Status = find_item_in_tree(Vcb, td->treeholder.tree, tp, searchkey, ignore, Irp, func, file, line);
|
||||
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL _find_item(device_extension* Vcb, root* r, traverse_ptr* tp, const KEY* searchkey, BOOL ignore, const char* func, const char* file, unsigned int line) {
|
||||
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 Status;
|
||||
BOOL loaded;
|
||||
// KIRQL irql;
|
||||
|
@ -497,15 +499,15 @@ NTSTATUS STDCALL _find_item(device_extension* Vcb, root* r, traverse_ptr* tp, co
|
|||
TRACE("(%p, %p, %p, %p)\n", Vcb, r, tp, searchkey);
|
||||
|
||||
if (!r->treeholder.tree) {
|
||||
Status = _do_load_tree(Vcb, &r->treeholder, r, NULL, NULL, &loaded, func, file, line);
|
||||
Status = _do_load_tree(Vcb, &r->treeholder, r, NULL, NULL, &loaded, Irp, func, file, line);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("do_load_tree returned %08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
Status = find_item_in_tree(Vcb, r->treeholder.tree, tp, searchkey, ignore, func, file, line);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
Status = find_item_in_tree(Vcb, r->treeholder.tree, tp, searchkey, ignore, Irp, func, file, line);
|
||||
if (!NT_SUCCESS(Status) && Status != STATUS_NOT_FOUND) {
|
||||
ERR("find_item_in_tree returned %08x\n", Status);
|
||||
}
|
||||
|
||||
|
@ -519,7 +521,8 @@ NTSTATUS STDCALL _find_item(device_extension* Vcb, root* r, traverse_ptr* tp, co
|
|||
return Status;
|
||||
}
|
||||
|
||||
BOOL STDCALL _find_next_item(device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* next_tp, BOOL ignore, 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) {
|
||||
tree* t;
|
||||
tree_data *td, *next;
|
||||
NTSTATUS Status;
|
||||
|
@ -563,7 +566,7 @@ BOOL STDCALL _find_next_item(device_extension* Vcb, const traverse_ptr* tp, trav
|
|||
if (!t)
|
||||
return FALSE;
|
||||
|
||||
Status = _do_load_tree(Vcb, &td->treeholder, t->parent->root, t->parent, td, &loaded, func, file, line);
|
||||
Status = _do_load_tree(Vcb, &td->treeholder, t->parent->root, t->parent, td, &loaded, Irp, func, file, line);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("do_load_tree returned %08x\n", Status);
|
||||
return FALSE;
|
||||
|
@ -576,7 +579,7 @@ BOOL STDCALL _find_next_item(device_extension* Vcb, const traverse_ptr* tp, trav
|
|||
|
||||
fi = first_item(t);
|
||||
|
||||
Status = _do_load_tree(Vcb, &fi->treeholder, t->parent->root, t, fi, &loaded, func, file, line);
|
||||
Status = _do_load_tree(Vcb, &fi->treeholder, t->parent->root, t, fi, &loaded, Irp, func, file, line);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("do_load_tree returned %08x\n", Status);
|
||||
return FALSE;
|
||||
|
@ -592,7 +595,7 @@ BOOL STDCALL _find_next_item(device_extension* Vcb, const traverse_ptr* tp, trav
|
|||
traverse_ptr ntp2;
|
||||
BOOL b;
|
||||
|
||||
while ((b = _find_next_item(Vcb, next_tp, &ntp2, TRUE, func, file, line))) {
|
||||
while ((b = _find_next_item(Vcb, next_tp, &ntp2, TRUE, Irp, func, file, line))) {
|
||||
*next_tp = ntp2;
|
||||
|
||||
if (!next_tp->item->ignore)
|
||||
|
@ -622,7 +625,8 @@ static __inline tree_data* last_item(tree* t) {
|
|||
return CONTAINING_RECORD(le, tree_data, list_entry);
|
||||
}
|
||||
|
||||
BOOL STDCALL _find_prev_item(device_extension* Vcb, const traverse_ptr* tp, traverse_ptr* prev_tp, BOOL ignore, 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) {
|
||||
tree* t;
|
||||
tree_data* td;
|
||||
NTSTATUS Status;
|
||||
|
@ -649,7 +653,7 @@ BOOL STDCALL _find_prev_item(device_extension* Vcb, const traverse_ptr* tp, trav
|
|||
|
||||
td = prev_item(t->parent, t->paritem);
|
||||
|
||||
Status = _do_load_tree(Vcb, &td->treeholder, t->parent->root, t, td, &loaded, func, file, line);
|
||||
Status = _do_load_tree(Vcb, &td->treeholder, t->parent->root, t, td, &loaded, Irp, func, file, line);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("do_load_tree returned %08x\n", Status);
|
||||
return FALSE;
|
||||
|
@ -662,7 +666,7 @@ BOOL STDCALL _find_prev_item(device_extension* Vcb, const traverse_ptr* tp, trav
|
|||
|
||||
li = last_item(t);
|
||||
|
||||
Status = _do_load_tree(Vcb, &li->treeholder, t->parent->root, t, li, &loaded, func, file, line);
|
||||
Status = _do_load_tree(Vcb, &li->treeholder, t->parent->root, t, li, &loaded, Irp, func, file, line);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("do_load_tree returned %08x\n", Status);
|
||||
return FALSE;
|
||||
|
@ -793,7 +797,7 @@ void add_rollback(LIST_ENTRY* rollback, enum rollback_type type, void* ptr) {
|
|||
InsertTailList(rollback, &ri->list_entry);
|
||||
}
|
||||
|
||||
BOOL STDCALL insert_tree_item(device_extension* Vcb, root* r, UINT64 obj_id, UINT8 obj_type, UINT64 offset, void* data, UINT32 size, traverse_ptr* ptp, LIST_ENTRY* rollback) {
|
||||
BOOL STDCALL insert_tree_item(device_extension* Vcb, root* r, UINT64 obj_id, UINT8 obj_type, UINT64 offset, void* data, UINT32 size, traverse_ptr* ptp, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
traverse_ptr tp;
|
||||
KEY searchkey;
|
||||
int cmp;
|
||||
|
@ -820,13 +824,13 @@ BOOL STDCALL insert_tree_item(device_extension* Vcb, root* r, UINT64 obj_id, UIN
|
|||
searchkey.obj_type = obj_type;
|
||||
searchkey.offset = offset;
|
||||
|
||||
Status = find_item(Vcb, r, &tp, &searchkey, TRUE);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
Status = find_item(Vcb, r, &tp, &searchkey, TRUE, Irp);
|
||||
if (Status == STATUS_NOT_FOUND) {
|
||||
if (r) {
|
||||
if (!r->treeholder.tree) {
|
||||
BOOL loaded;
|
||||
|
||||
Status = do_load_tree(Vcb, &r->treeholder, r, NULL, NULL, &loaded);
|
||||
Status = do_load_tree(Vcb, &r->treeholder, r, NULL, NULL, &loaded, Irp);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("do_load_tree returned %08x\n", Status);
|
||||
|
@ -845,6 +849,9 @@ BOOL STDCALL insert_tree_item(device_extension* Vcb, root* r, UINT64 obj_id, UIN
|
|||
ERR("error: find_item returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
} else if (!NT_SUCCESS(Status)) {
|
||||
ERR("find_item returned %08x\n", Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
TRACE("tp.item = %p\n", tp.item);
|
||||
|
@ -855,6 +862,7 @@ BOOL STDCALL insert_tree_item(device_extension* Vcb, root* r, UINT64 obj_id, UIN
|
|||
|
||||
if (cmp == 0 && !tp.item->ignore) { // FIXME - look for all items of the same key to make sure none are non-ignored
|
||||
ERR("error: key (%llx,%x,%llx) already present\n", obj_id, obj_type, offset);
|
||||
int3;
|
||||
goto end;
|
||||
}
|
||||
} else
|
||||
|
@ -970,10 +978,10 @@ void STDCALL delete_tree_item(device_extension* Vcb, traverse_ptr* tp, LIST_ENTR
|
|||
TRACE("deleting item %llx,%x,%llx (ignore = %s)\n", tp->item->key.obj_id, tp->item->key.obj_type, tp->item->key.offset, tp->item->ignore ? "TRUE" : "FALSE");
|
||||
|
||||
#ifdef DEBUG_PARANOID
|
||||
if (!ExIsResourceAcquiredExclusiveLite(&Vcb->tree_lock)) {
|
||||
ERR("ERROR - tree_lock not held exclusively\n");
|
||||
int3;
|
||||
}
|
||||
// if (!ExIsResourceAcquiredExclusiveLite(&Vcb->tree_lock)) {
|
||||
// ERR("ERROR - tree_lock not held exclusively\n");
|
||||
// int3;
|
||||
// }
|
||||
|
||||
if (tp->item->ignore) {
|
||||
ERR("trying to delete already-deleted item %llx,%x,%llx\n", tp->item->key.obj_id, tp->item->key.obj_type, tp->item->key.offset);
|
||||
|
@ -1025,6 +1033,10 @@ void clear_rollback(LIST_ENTRY* rollback) {
|
|||
switch (ri->type) {
|
||||
case ROLLBACK_INSERT_ITEM:
|
||||
case ROLLBACK_DELETE_ITEM:
|
||||
case ROLLBACK_ADD_SPACE:
|
||||
case ROLLBACK_SUBTRACT_SPACE:
|
||||
case ROLLBACK_INSERT_EXTENT:
|
||||
case ROLLBACK_DELETE_EXTENT:
|
||||
ExFreePool(ri->ptr);
|
||||
break;
|
||||
|
||||
|
@ -1037,6 +1049,7 @@ void clear_rollback(LIST_ENTRY* rollback) {
|
|||
}
|
||||
|
||||
void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback) {
|
||||
NTSTATUS Status;
|
||||
rollback_item* ri;
|
||||
|
||||
while (!IsListEmpty(rollback)) {
|
||||
|
@ -1082,17 +1095,105 @@ void do_rollback(device_extension* Vcb, LIST_ENTRY* rollback) {
|
|||
|
||||
case ROLLBACK_INSERT_EXTENT:
|
||||
{
|
||||
extent* ext = ri->ptr;
|
||||
rollback_extent* re = ri->ptr;
|
||||
|
||||
ext->ignore = TRUE;
|
||||
re->ext->ignore = TRUE;
|
||||
|
||||
if (re->ext->data->type == EXTENT_TYPE_REGULAR || re->ext->data->type == EXTENT_TYPE_PREALLOC) {
|
||||
EXTENT_DATA2* ed2 = (EXTENT_DATA2*)re->ext->data->data;
|
||||
|
||||
if (ed2->size != 0) {
|
||||
chunk* c = get_chunk_from_address(Vcb, ed2->address);
|
||||
|
||||
if (c) {
|
||||
Status = update_changed_extent_ref(Vcb, c, ed2->address, ed2->size, re->fcb->subvol->id,
|
||||
re->fcb->inode, re->ext->offset - ed2->offset, -1,
|
||||
re->fcb->inode_item.flags & BTRFS_INODE_NODATASUM, ed2->size, NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
ERR("update_changed_extent_ref returned %08x\n", Status);
|
||||
}
|
||||
|
||||
re->fcb->inode_item.st_blocks -= ed2->num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
ExFreePool(re);
|
||||
break;
|
||||
}
|
||||
|
||||
case ROLLBACK_DELETE_EXTENT:
|
||||
{
|
||||
extent* ext = ri->ptr;
|
||||
rollback_extent* re = ri->ptr;
|
||||
|
||||
re->ext->ignore = FALSE;
|
||||
|
||||
if (re->ext->data->type == EXTENT_TYPE_REGULAR || re->ext->data->type == EXTENT_TYPE_PREALLOC) {
|
||||
EXTENT_DATA2* ed2 = (EXTENT_DATA2*)re->ext->data->data;
|
||||
|
||||
if (ed2->size != 0) {
|
||||
chunk* c = get_chunk_from_address(Vcb, ed2->address);
|
||||
|
||||
if (c) {
|
||||
Status = update_changed_extent_ref(Vcb, c, ed2->address, ed2->size, re->fcb->subvol->id,
|
||||
re->fcb->inode, re->ext->offset - ed2->offset, 1,
|
||||
re->fcb->inode_item.flags & BTRFS_INODE_NODATASUM, ed2->size, NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
ERR("update_changed_extent_ref returned %08x\n", Status);
|
||||
}
|
||||
|
||||
re->fcb->inode_item.st_blocks += ed2->num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
ExFreePool(re);
|
||||
break;
|
||||
}
|
||||
|
||||
case ROLLBACK_ADD_SPACE:
|
||||
case ROLLBACK_SUBTRACT_SPACE:
|
||||
{
|
||||
rollback_space* rs = ri->ptr;
|
||||
|
||||
if (rs->chunk)
|
||||
ExAcquireResourceExclusiveLite(&rs->chunk->lock, TRUE);
|
||||
|
||||
if (ri->type == ROLLBACK_ADD_SPACE)
|
||||
space_list_subtract2(rs->list, rs->list_size, rs->address, rs->length, NULL);
|
||||
else
|
||||
space_list_add2(rs->list, rs->list_size, rs->address, rs->length, NULL);
|
||||
|
||||
if (rs->chunk) {
|
||||
LIST_ENTRY* le2 = le->Blink;
|
||||
|
||||
while (le2 != rollback) {
|
||||
LIST_ENTRY* le3 = le2->Blink;
|
||||
rollback_item* ri2 = CONTAINING_RECORD(le2, rollback_item, list_entry);
|
||||
|
||||
if (ri2->type == ROLLBACK_ADD_SPACE || ri2->type == ROLLBACK_SUBTRACT_SPACE) {
|
||||
rollback_space* rs2 = ri2->ptr;
|
||||
|
||||
if (rs2->chunk == rs->chunk) {
|
||||
if (ri2->type == ROLLBACK_ADD_SPACE)
|
||||
space_list_subtract2(rs2->list, rs2->list_size, rs2->address, rs2->length, NULL);
|
||||
else
|
||||
space_list_add2(rs2->list, rs2->list_size, rs2->address, rs2->length, NULL);
|
||||
|
||||
ExFreePool(rs2);
|
||||
RemoveEntryList(&ri2->list_entry);
|
||||
ExFreePool(ri2);
|
||||
}
|
||||
}
|
||||
|
||||
le2 = le3;
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&rs->chunk->lock);
|
||||
}
|
||||
|
||||
ExFreePool(rs);
|
||||
|
||||
ext->ignore = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/* 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"
|
||||
|
||||
void do_read_job(PIRP Irp) {
|
||||
|
@ -78,6 +95,7 @@ void STDCALL worker_thread(void* context) {
|
|||
|
||||
while (TRUE) {
|
||||
LIST_ENTRY* le;
|
||||
device_extension* Vcb = thread->DeviceObject->DeviceExtension;
|
||||
|
||||
KeAcquireSpinLock(&thread->spin_lock, &irql);
|
||||
|
||||
|
@ -91,6 +109,7 @@ void STDCALL worker_thread(void* context) {
|
|||
|
||||
KeReleaseSpinLock(&thread->spin_lock, irql);
|
||||
|
||||
InterlockedDecrement(&Vcb->threads.pending_jobs);
|
||||
do_job(thread, le);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
17
reactos/drivers/filesystems/btrfs/zlib/CMakeLists.txt
Normal file
17
reactos/drivers/filesystems/btrfs/zlib/CMakeLists.txt
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/zlib
|
||||
inc)
|
||||
|
||||
list(APPEND SOURCE
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/zlib/adler32.c
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/zlib/crc32.c
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/zlib/deflate.c
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/zlib/inffast.c
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/zlib/inflate.c
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/zlib/inftrees.c
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/zlib/trees.c
|
||||
${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/zlib/zutil.c)
|
||||
|
||||
add_library(zlib_solo ${SOURCE})
|
||||
|
||||
add_definitions(-DZ_SOLO)
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
The following FSD are shared with: https://github.com/maharmstone/btrfs.
|
||||
|
||||
reactos/drivers/filesystems/btrfs # Synced to 0.5
|
||||
reactos/drivers/filesystems/btrfs # Synced to 0.6
|
||||
|
||||
The following FSD are shared with: http://www.ext2fsd.com/
|
||||
|
||||
|
|
Loading…
Reference in a new issue