Author: pschweitzer Date: Sat Mar 26 11:53:07 2016 New Revision: 71052
URL: http://svn.reactos.org/svn/reactos?rev=71052&view=rev Log: [BTRFS] Upgrade the WinBtrfs to release 0.3.
Mostly bugfixes
CORE-11024 #resolve #comment Committed in r71052
Added: trunk/reactos/drivers/filesystems/btrfs/btrfsioctl.h (with props) Modified: trunk/reactos/drivers/filesystems/btrfs/btrfs.c trunk/reactos/drivers/filesystems/btrfs/btrfs_drv.h trunk/reactos/drivers/filesystems/btrfs/cache.c trunk/reactos/drivers/filesystems/btrfs/create.c trunk/reactos/drivers/filesystems/btrfs/fastio.c trunk/reactos/drivers/filesystems/btrfs/fileinfo.c trunk/reactos/drivers/filesystems/btrfs/fsctl.c trunk/reactos/drivers/filesystems/btrfs/read.c trunk/reactos/drivers/filesystems/btrfs/treefuncs.c trunk/reactos/drivers/filesystems/btrfs/write.c
Modified: trunk/reactos/drivers/filesystems/btrfs/btrfs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/btrfs/b... ============================================================================== --- trunk/reactos/drivers/filesystems/btrfs/btrfs.c [iso-8859-1] (original) +++ trunk/reactos/drivers/filesystems/btrfs/btrfs.c [iso-8859-1] Sat Mar 26 11:53:07 2016 @@ -1550,8 +1550,8 @@ // FIXME - delete all children if deleting directory
if (fcb->deleted) { - ERR("trying to delete already-deleted file\n"); - return STATUS_INTERNAL_ERROR; + WARN("trying to delete already-deleted file\n"); + return STATUS_SUCCESS; }
if (!fcb->par) { @@ -1772,7 +1772,7 @@
InitializeListHead(&changed_sector_list);
- if (fcb->type != BTRFS_TYPE_DIRECTORY) { + if (fcb->type != BTRFS_TYPE_DIRECTORY && 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), &changed_sector_list, rollback); if (!NT_SUCCESS(Status)) { ERR("excise_extents returned %08x\n", Status); @@ -1879,9 +1879,9 @@ #ifdef DEBUG_FCB_REFCOUNTS // WARN("fcb %p: refcount now %i (%.*S)\n", fcb, rc, fcb->full_filename.Length / sizeof(WCHAR), fcb->full_filename.Buffer); #ifdef DEBUG_LONG_MESSAGES - _debug_message(func, file, line, "fcb %p: refcount now %i (%.*S)\n", fcb, rc, fcb->full_filename.Length / sizeof(WCHAR), fcb->full_filename.Buffer); + _debug_message(func, 1, file, line, "fcb %p: refcount now %i (%.*S)\n", fcb, rc, fcb->full_filename.Length / sizeof(WCHAR), fcb->full_filename.Buffer); #else - _debug_message(func, "fcb %p: refcount now %i (%.*S)\n", fcb, rc, fcb->full_filename.Length / sizeof(WCHAR), fcb->full_filename.Buffer); + _debug_message(func, 1, "fcb %p: refcount now %i (%.*S)\n", fcb, rc, fcb->full_filename.Length / sizeof(WCHAR), fcb->full_filename.Buffer); #endif #endif
@@ -1930,9 +1930,9 @@ ExFreePool(fcb); #ifdef DEBUG_FCB_REFCOUNTS #ifdef DEBUG_LONG_MESSAGES - _debug_message(func, file, line, "freeing fcb %p\n", fcb); + _debug_message(func, 1, file, line, "freeing fcb %p\n", fcb); #else - _debug_message(func, "freeing fcb %p\n", fcb); + _debug_message(func, 1, "freeing fcb %p\n", fcb); #endif #endif } @@ -1964,12 +1964,9 @@ ExFreePool(ccb); }
- if (fcb->refcount == 1) - CcUninitializeCacheMap(FileObject, NULL, NULL); + CcUninitializeCacheMap(FileObject, NULL, NULL);
free_fcb(fcb); - - FileObject->FsContext = NULL;
return STATUS_SUCCESS; } @@ -2072,6 +2069,9 @@ IoRemoveShareAccess(FileObject, &fcb->share_access);
oc = InterlockedDecrement(&fcb->open_count); +#ifdef DEBUG_FCB_REFCOUNTS + ERR("fcb %p: open_count now %i\n", fcb, oc); +#endif
if (oc == 0) { if (fcb->delete_on_close && fcb != fcb->Vcb->root_fcb && fcb != fcb->Vcb->volume_fcb) { @@ -2115,10 +2115,10 @@ TRACE("flushed cache on close (FileObject = %p, fcb = %p, AllocationSize = %llx, FileSize = %llx, ValidDataLength = %llx)\n", FileObject, fcb, fcb->Header.AllocationSize.QuadPart, fcb->Header.FileSize.QuadPart, fcb->Header.ValidDataLength.QuadPart); } - } - - if (fcb->Vcb && fcb != fcb->Vcb->volume_fcb) - CcUninitializeCacheMap(FileObject, NULL, NULL); + + if (fcb->Vcb && fcb != fcb->Vcb->volume_fcb) + CcUninitializeCacheMap(FileObject, NULL, NULL); + }
FileObject->Flags |= FO_CLEANUP_COMPLETE; } @@ -3029,12 +3029,23 @@
for (j = 0; j < ci->num_stripes; j++) { if (cis[j].offset + ci->size > superblock_addrs[i] && cis[j].offset <= superblock_addrs[i] + sizeof(superblock)) { + UINT32 size; + TRACE("cut out superblock in chunk %llx\n", c->offset);
addr = (superblock_addrs[i] - cis[j].offset) + c->offset; TRACE("addr %llx\n", addr);
- add_to_space_list(c, addr, sizeof(superblock), SPACE_TYPE_USED); + // This prevents trees from spanning a stripe boundary, which btrfs check complains + // about. It also prevents the chunk tree being placed at 0x11000, which for some + // reason makes the FS unmountable on Linux (it tries to read 0x10000, i.e. the + // superblock, instead). + if (ci->type & BLOCK_FLAG_SYSTEM || ci->type & BLOCK_FLAG_METADATA) + size = max(sizeof(superblock), Vcb->superblock.node_size); + else + size = sizeof(superblock); + + add_to_space_list(c, addr, size, SPACE_TYPE_USED); } }
Modified: trunk/reactos/drivers/filesystems/btrfs/btrfs_drv.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/btrfs/b... ============================================================================== --- trunk/reactos/drivers/filesystems/btrfs/btrfs_drv.h [iso-8859-1] (original) +++ trunk/reactos/drivers/filesystems/btrfs/btrfs_drv.h [iso-8859-1] Sat Mar 26 11:53:07 2016 @@ -204,6 +204,7 @@ // UINT8 level; tree_header header; LONG refcount; + BOOL has_address; UINT32 size; struct _device_extension* Vcb; struct _tree* parent; @@ -213,6 +214,7 @@ LIST_ENTRY itemlist; LIST_ENTRY list_entry; UINT64 new_address; + BOOL has_new_address; UINT64 flags; } tree;
Added: trunk/reactos/drivers/filesystems/btrfs/btrfsioctl.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/btrfs/b... ============================================================================== --- trunk/reactos/drivers/filesystems/btrfs/btrfsioctl.h (added) +++ trunk/reactos/drivers/filesystems/btrfs/btrfsioctl.h [iso-8859-1] Sat Mar 26 11:53:07 2016 @@ -0,0 +1,12 @@ +#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) + +typedef struct { + UINT64 subvol; + UINT64 inode; + BOOL top; +} btrfs_get_file_ids; + +#endif
Propchange: trunk/reactos/drivers/filesystems/btrfs/btrfsioctl.h ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/drivers/filesystems/btrfs/cache.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/btrfs/c... ============================================================================== --- trunk/reactos/drivers/filesystems/btrfs/cache.c [iso-8859-1] (original) +++ trunk/reactos/drivers/filesystems/btrfs/cache.c [iso-8859-1] Sat Mar 26 11:53:07 2016 @@ -26,7 +26,10 @@
TRACE("(%p, %u)\n", Context, Wait);
- if (!fcb || FileObject->Flags & FO_CLEANUP_COMPLETE) +// if (!fcb || FileObject->Flags & FO_CLEANUP_COMPLETE) +// return FALSE; + + if (!ExAcquireResourceSharedLite(fcb->Header.PagingIoResource, Wait)) return FALSE;
fcb->lazy_writer_thread = KeGetCurrentThread(); @@ -40,10 +43,12 @@
TRACE("(%p)\n", Context);
- if (!fcb || FileObject->Flags & FO_CLEANUP_COMPLETE) - return; +// if (!fcb || FileObject->Flags & FO_CLEANUP_COMPLETE) +// return;
fcb->lazy_writer_thread = NULL; + + ExReleaseResourceLite(fcb->Header.PagingIoResource); }
static BOOLEAN STDCALL acquire_for_read_ahead(PVOID Context, BOOLEAN Wait) {
Modified: trunk/reactos/drivers/filesystems/btrfs/create.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/btrfs/c... ============================================================================== --- trunk/reactos/drivers/filesystems/btrfs/create.c [iso-8859-1] (original) +++ trunk/reactos/drivers/filesystems/btrfs/create.c [iso-8859-1] Sat Mar 26 11:53:07 2016 @@ -648,6 +648,7 @@ static fcb* search_fcb_children(fcb* dir, PUNICODE_STRING name) { LIST_ENTRY* le; fcb *c, *deleted = NULL; + ULONG rc;
le = dir->children.Flink; while (le != &dir->children) { @@ -657,9 +658,9 @@ if (c->deleted) { deleted = c; } else { - c->refcount++; + rc = InterlockedIncrement(&c->refcount); #ifdef DEBUG_FCB_REFCOUNTS - WARN("fcb %p: refcount now %i (%.*S)\n", c, c->refcount, c->full_filename.Length / sizeof(WCHAR), c->full_filename.Buffer); + WARN("fcb %p: refcount now %i (%.*S)\n", c, rc, c->full_filename.Length / sizeof(WCHAR), c->full_filename.Buffer); #endif return c; } @@ -668,20 +669,27 @@ le = le->Flink; }
+ if (deleted) { + rc = InterlockedIncrement(&deleted->refcount); +#ifdef DEBUG_FCB_REFCOUNTS + WARN("fcb %p: refcount now %i (%.*S)\n", deleted, rc, deleted->full_filename.Length / sizeof(WCHAR), deleted->full_filename.Buffer); +#endif + } + return deleted; }
-#ifdef DEBUG_FCB_REFCOUNTS -static void print_fcbs(device_extension* Vcb) { - fcb* fcb = Vcb->fcbs; - - while (fcb) { - ERR("fcb %p (%.*S): refcount %u\n", fcb, fcb->full_filename.Length / sizeof(WCHAR), fcb->full_filename.Buffer, fcb->refcount); - - fcb = fcb->next; - } -} -#endif +// #ifdef DEBUG_FCB_REFCOUNTS +// static void print_fcbs(device_extension* Vcb) { +// fcb* fcb = Vcb->fcbs; +// +// while (fcb) { +// ERR("fcb %p (%.*S): refcount %u\n", fcb, fcb->full_filename.Length / sizeof(WCHAR), fcb->full_filename.Buffer, fcb->refcount); +// +// fcb = fcb->next; +// } +// } +// #endif
NTSTATUS get_fcb(device_extension* Vcb, fcb** pfcb, PUNICODE_STRING fnus, fcb* relatedfcb, BOOL parent) { fcb *dir, *sf, *sf2; @@ -693,9 +701,9 @@
TRACE("(%p, %p, %.*S, %p, %s)\n", Vcb, pfcb, fnus->Length / sizeof(WCHAR), fnus->Buffer, relatedfcb, parent ? "TRUE" : "FALSE");
-#ifdef DEBUG_FCB_REFCOUNTS - print_fcbs(Vcb); -#endif +// #ifdef DEBUG_FCB_REFCOUNTS +// print_fcbs(Vcb); +// #endif
fnus2 = *fnus;
@@ -713,10 +721,12 @@ }
if (fnus2.Length == sizeof(WCHAR)) { + LONG rc; + *pfcb = Vcb->root_fcb; - Vcb->root_fcb->refcount++; + rc = InterlockedIncrement(&Vcb->root_fcb->refcount); #ifdef DEBUG_FCB_REFCOUNTS - WARN("fcb %p: refcount now %i (root)\n", Vcb->root_fcb, Vcb->root_fcb->refcount); + WARN("fcb %p: refcount now %i (root)\n", Vcb->root_fcb, rc); #endif return STATUS_SUCCESS; } @@ -1028,9 +1038,9 @@ if (parts) ExFreePool(parts);
-#ifdef DEBUG_FCB_REFCOUNTS - print_fcbs(Vcb); -#endif +// #ifdef DEBUG_FCB_REFCOUNTS +// print_fcbs(Vcb); +// #endif
TRACE("returning %08x\n", Status);
@@ -1064,6 +1074,7 @@ PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); ANSI_STRING utf8as; ULONG defda; + LONG rc;
Status = RtlUnicodeToUTF8N(NULL, 0, &utf8len, fpus->Buffer, fpus->Length); if (!NT_SUCCESS(Status)) @@ -1281,9 +1292,9 @@ fcb->delete_on_close = TRUE;
fcb->par = parfcb; - parfcb->refcount++; + rc = InterlockedIncrement(&parfcb->refcount); #ifdef DEBUG_FCB_REFCOUNTS - WARN("fcb %p: refcount now %i (%.*S)\n", parfcb, parfcb->refcount, parfcb->full_filename.Length / sizeof(WCHAR), parfcb->full_filename.Buffer); + WARN("fcb %p: refcount now %i (%.*S)\n", parfcb, rc, parfcb->full_filename.Length / sizeof(WCHAR), parfcb->full_filename.Buffer); #endif fcb->subvol = parfcb->subvol; fcb->inode = inode; @@ -1355,6 +1366,7 @@ ccb* ccb; static WCHAR datasuf[] = {':','$','D','A','T','A',0}; UNICODE_STRING dsus, fpus, stream; + LONG oc;
TRACE("(%p, %p, %p, %.*S, %x, %x)\n", Irp, Vcb, FileObject, fnus->Length / sizeof(WCHAR), fnus->Buffer, disposition, options);
@@ -1444,6 +1456,7 @@ KEY searchkey; traverse_ptr tp; INODE_ITEM* ii; + LONG rc;
TRACE("fpus = %.*S\n", fpus.Length / sizeof(WCHAR), fpus.Buffer); TRACE("stream = %.*S\n", stream.Length / sizeof(WCHAR), stream.Buffer); @@ -1497,9 +1510,9 @@ fcb->delete_on_close = TRUE;
fcb->par = parfcb; - parfcb->refcount++; + rc = InterlockedIncrement(&parfcb->refcount); #ifdef DEBUG_FCB_REFCOUNTS - WARN("fcb %p: refcount now %i (%.*S)\n", parfcb, parfcb->refcount, parfcb->full_filename.Length / sizeof(WCHAR), parfcb->full_filename.Buffer); + WARN("fcb %p: refcount now %i (%.*S)\n", parfcb, rc, parfcb->full_filename.Length / sizeof(WCHAR), parfcb->full_filename.Buffer); #endif fcb->subvol = parfcb->subvol; fcb->inode = parfcb->inode; @@ -1658,7 +1671,10 @@ ccb->has_wildcard = FALSE; ccb->specific_file = FALSE;
- InterlockedIncrement(&fcb->open_count); + oc = InterlockedIncrement(&fcb->open_count); +#ifdef DEBUG_FCB_REFCOUNTS + ERR("fcb %p: open_count now %i\n", fcb, oc); +#endif
FileObject->FsContext2 = ccb;
@@ -1884,6 +1900,7 @@ PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); ULONG access; PACCESS_STATE access_state = Stack->Parameters.Create.SecurityContext->AccessState; + LONG oc;
Irp->IoStatus.Information = 0;
@@ -1948,6 +1965,7 @@ if (NT_SUCCESS(Status) && fcb->deleted) { free_fcb(fcb); Status = STATUS_OBJECT_NAME_NOT_FOUND; + goto exit; }
if (NT_SUCCESS(Status)) { @@ -2217,7 +2235,10 @@ } }
- InterlockedIncrement(&fcb->open_count); + oc = InterlockedIncrement(&fcb->open_count); +#ifdef DEBUG_FCB_REFCOUNTS + ERR("fcb %p: open_count now %i\n", fcb, oc); +#endif } else { Status = file_create(Irp, DeviceObject->DeviceExtension, FileObject, &FileObject->FileName, RequestedDisposition, options, rollback); Irp->IoStatus.Information = NT_SUCCESS(Status) ? FILE_CREATED : 0; @@ -2316,6 +2337,7 @@ if (IrpSp->FileObject->FileName.Length == 0 && !IrpSp->FileObject->RelatedFileObject) { ULONG RequestedDisposition = ((IrpSp->Parameters.Create.Options >> 24) & 0xff); ULONG RequestedOptions = IrpSp->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS; + LONG rc, oc;
TRACE("open operation for volume\n");
@@ -2332,14 +2354,18 @@ goto exit; }
- Vcb->volume_fcb->refcount++; + rc = InterlockedIncrement(&Vcb->volume_fcb->refcount); + oc = InterlockedIncrement(&Vcb->volume_fcb->open_count); #ifdef DEBUG_FCB_REFCOUNTS - WARN("fcb %p: refcount now %i (volume)\n", Vcb->volume_fcb, Vcb->volume_fcb->refcount); + WARN("fcb %p: refcount now %i (volume)\n", Vcb->volume_fcb, rc); + WARN("fcb %p: open_count now %i (volume)\n", Vcb->volume_fcb, oc); #endif attach_fcb_to_fileobject(Vcb, Vcb->volume_fcb, IrpSp->FileObject); // // NtfsAttachFCBToFileObject(DeviceExt, DeviceExt->VolumeFcb, FileObject); // // DeviceExt->VolumeFcb->RefCount++; -// + + IrpSp->FileObject->SectionObjectPointer = &Vcb->volume_fcb->nonpaged->segment_object; + Irp->IoStatus.Information = FILE_OPENED; Status = STATUS_SUCCESS; } else {
Modified: trunk/reactos/drivers/filesystems/btrfs/fastio.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/btrfs/f... ============================================================================== --- trunk/reactos/drivers/filesystems/btrfs/fastio.c [iso-8859-1] (original) +++ trunk/reactos/drivers/filesystems/btrfs/fastio.c [iso-8859-1] Sat Mar 26 11:53:07 2016 @@ -137,13 +137,51 @@
static NTSTATUS STDCALL fast_io_acquire_for_ccflush(PFILE_OBJECT FileObject, PDEVICE_OBJECT DeviceObject){ TRACE("STUB: fast_io_acquire_for_ccflush\n"); - return STATUS_NOT_IMPLEMENTED; + return STATUS_SUCCESS; }
static NTSTATUS STDCALL fast_io_release_for_ccflush(PFILE_OBJECT FileObject, PDEVICE_OBJECT DeviceObject){ TRACE("STUB: fast_io_release_for_ccflush\n"); - return STATUS_NOT_IMPLEMENTED; -} + return STATUS_SUCCESS; +} + +#ifdef DEBUG +static BOOLEAN STDCALL fast_io_read(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { + TRACE("(%p, %p, %x, %x, %x, %p, %p, %p)\n", FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject); + + return FsRtlCopyRead(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject); +} + +static BOOLEAN STDCALL fast_io_write(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { + TRACE("(%p, %p, %x, %x, %x, %p, %p, %p)\n", FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject); + + return FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject); +} + +static BOOLEAN STDCALL fast_io_mdl_read(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, ULONG LockKey, PMDL* MdlChain, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { + TRACE("(%p, %p, %x, %x, %p, %p, %p)\n", FileObject, FileOffset, Length, LockKey, MdlChain, IoStatus, DeviceObject); + + return FsRtlMdlReadDev(FileObject, FileOffset, Length, LockKey, MdlChain, IoStatus, DeviceObject); +} + +static BOOLEAN STDCALL fast_io_mdl_read_complete(PFILE_OBJECT FileObject, PMDL* MdlChain, PDEVICE_OBJECT DeviceObject) { + TRACE("(%p, %p, %p)\n", FileObject, MdlChain, DeviceObject); + + return FsRtlMdlReadCompleteDev(FileObject, MdlChain, DeviceObject); +} + +static BOOLEAN STDCALL fast_io_prepare_mdl_write(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, ULONG LockKey, PMDL* MdlChain, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { + TRACE("(%p, %p, %x, %x, %p, %p, %p)\n", FileObject, FileOffset, Length, LockKey, MdlChain, IoStatus, DeviceObject); + + return FsRtlPrepareMdlWriteDev(FileObject, FileOffset, Length, LockKey, MdlChain, IoStatus, DeviceObject); +} + +static BOOLEAN STDCALL fast_io_mdl_write_complete(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PMDL* MdlChain, PDEVICE_OBJECT DeviceObject) { + TRACE("(%p, %p, %p, %p)\n", FileObject, FileOffset, MdlChain, DeviceObject); + + return FsRtlMdlWriteCompleteDev(FileObject, FileOffset, MdlChain, DeviceObject); +} +#endif
void __stdcall init_fast_io_dispatch(FAST_IO_DISPATCH** fiod) { RtlZeroMemory(&FastIoDispatch, sizeof(FastIoDispatch)); @@ -151,8 +189,6 @@ FastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
FastIoDispatch.FastIoCheckIfPossible = fast_io_check_if_possible; - FastIoDispatch.FastIoRead = FsRtlCopyRead; - FastIoDispatch.FastIoWrite = FsRtlCopyWrite; FastIoDispatch.FastIoQueryBasicInfo = fast_query_basic_info; FastIoDispatch.FastIoQueryStandardInfo = fast_query_standard_info; FastIoDispatch.FastIoLock = fast_io_lock; @@ -165,10 +201,6 @@ FastIoDispatch.FastIoDetachDevice = fast_io_detach_device; FastIoDispatch.FastIoQueryNetworkOpenInfo = fast_io_query_network_open_info; FastIoDispatch.AcquireForModWrite = fast_io_acquire_for_mod_write; - FastIoDispatch.MdlRead = FsRtlMdlReadDev; - FastIoDispatch.MdlReadComplete = FsRtlMdlReadCompleteDev; - FastIoDispatch.PrepareMdlWrite = FsRtlPrepareMdlWriteDev; - FastIoDispatch.MdlWriteComplete = FsRtlMdlWriteCompleteDev; FastIoDispatch.FastIoReadCompressed = fast_io_read_compressed; FastIoDispatch.FastIoWriteCompressed = fast_io_write_compressed; FastIoDispatch.MdlReadCompleteCompressed = fast_io_mdl_read_complete_compressed; @@ -178,5 +210,21 @@ FastIoDispatch.AcquireForCcFlush = fast_io_acquire_for_ccflush; FastIoDispatch.ReleaseForCcFlush = fast_io_release_for_ccflush;
+#ifdef DEBUG + FastIoDispatch.FastIoRead = fast_io_read; + FastIoDispatch.FastIoWrite = fast_io_write; + FastIoDispatch.MdlRead = fast_io_mdl_read; + FastIoDispatch.MdlReadComplete = fast_io_mdl_read_complete; + FastIoDispatch.PrepareMdlWrite = fast_io_prepare_mdl_write; + FastIoDispatch.MdlWriteComplete = fast_io_mdl_write_complete; +#else + FastIoDispatch.FastIoRead = FsRtlCopyRead; + FastIoDispatch.FastIoWrite = FsRtlCopyWrite; + FastIoDispatch.MdlRead = FsRtlMdlReadDev; + FastIoDispatch.MdlReadComplete = FsRtlMdlReadCompleteDev; + FastIoDispatch.PrepareMdlWrite = FsRtlPrepareMdlWriteDev; + FastIoDispatch.MdlWriteComplete = FsRtlMdlWriteCompleteDev; +#endif + *fiod = &FastIoDispatch; -} +}
Modified: trunk/reactos/drivers/filesystems/btrfs/fileinfo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/btrfs/f... ============================================================================== --- trunk/reactos/drivers/filesystems/btrfs/fileinfo.c [iso-8859-1] (original) +++ trunk/reactos/drivers/filesystems/btrfs/fileinfo.c [iso-8859-1] Sat Mar 26 11:53:07 2016 @@ -2194,7 +2194,7 @@ break;
case FileRemoteProtocolInformation: - FIXME("STUB: FileRemoteProtocolInformation\n"); + TRACE("FileRemoteProtocolInformation\n"); break; #endif
@@ -2884,7 +2884,7 @@ }
case FileRemoteProtocolInformation: - FIXME("STUB: FileRemoteProtocolInformation\n"); + TRACE("FileRemoteProtocolInformation\n"); Status = STATUS_INVALID_PARAMETER; goto exit; #endif
Modified: trunk/reactos/drivers/filesystems/btrfs/fsctl.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/btrfs/f... ============================================================================== --- trunk/reactos/drivers/filesystems/btrfs/fsctl.c [iso-8859-1] (original) +++ trunk/reactos/drivers/filesystems/btrfs/fsctl.c [iso-8859-1] Sat Mar 26 11:53:07 2016 @@ -16,11 +16,36 @@ * along with WinBtrfs. If not, see http://www.gnu.org/licenses/. */
#include "btrfs_drv.h" +#include "btrfsioctl.h"
#ifndef FSCTL_CSV_CONTROL #define FSCTL_CSV_CONTROL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 181, METHOD_BUFFERED, FILE_ANY_ACCESS) #endif
+static NTSTATUS get_file_ids(PFILE_OBJECT FileObject, void* data, ULONG length) { + btrfs_get_file_ids* bgfi; + fcb* fcb; + + if (length < sizeof(btrfs_get_file_ids)) + return STATUS_BUFFER_OVERFLOW; + + if (!FileObject) + return STATUS_INVALID_PARAMETER; + + fcb = FileObject->FsContext; + + if (!fcb) + return STATUS_INVALID_PARAMETER; + + bgfi = data; + + bgfi->subvol = fcb->subvol->id; + bgfi->inode = fcb->inode; + bgfi->top = fcb->Vcb->root_fcb == fcb ? TRUE : FALSE; + + return STATUS_SUCCESS; +} + NTSTATUS fsctl_request(PDEVICE_OBJECT DeviceObject, PIRP Irp, UINT32 type, BOOL user) { PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); NTSTATUS Status; @@ -496,6 +521,9 @@ Status = STATUS_NOT_IMPLEMENTED; break; #endif + case FSCTL_BTRFS_GET_FILE_IDS: + Status = get_file_ids(IrpSp->FileObject, map_user_buffer(Irp), IrpSp->Parameters.DeviceIoControl.OutputBufferLength); + break;
default: WARN("unknown control code %x (DeviceType = %x, Access = %x, Function = %x, Method = %x)\n",
Modified: trunk/reactos/drivers/filesystems/btrfs/read.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/btrfs/r... ============================================================================== --- trunk/reactos/drivers/filesystems/btrfs/read.c [iso-8859-1] (original) +++ trunk/reactos/drivers/filesystems/btrfs/read.c [iso-8859-1] Sat Mar 26 11:53:07 2016 @@ -368,6 +368,9 @@ // }
do { + UINT64 len; + EXTENT_DATA2* ed2; + ed = (EXTENT_DATA*)tp.item->data;
if (tp.item->size < sizeof(EXTENT_DATA)) { @@ -384,7 +387,11 @@ goto exit; }
- if (tp.item->key.offset + ed->decoded_size < start) { + ed2 = (EXTENT_DATA2*)ed->data; + + len = ed->type == EXTENT_TYPE_INLINE ? ed->decoded_size : ed2->num_bytes; + + if (tp.item->key.offset + len < start) { ERR("Tried to read beyond end of file\n"); free_traverse_ptr(&tp); Status = STATUS_END_OF_FILE; @@ -416,9 +423,8 @@ case EXTENT_TYPE_INLINE: { UINT64 off = start + bytes_read - tp.item->key.offset; - UINT64 read; - - read = ed->decoded_size - off; + UINT64 read = len - off; + if (read > length) read = length;
RtlCopyMemory(data + bytes_read, &ed->data[off], read); @@ -430,12 +436,11 @@
case EXTENT_TYPE_REGULAR: { - EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ed->data; UINT64 off = start + bytes_read - tp.item->key.offset; UINT32 to_read, read; UINT8* buf;
- read = ed->decoded_size - off; + read = len - off; if (read > length) read = length;
if (ed2->address == 0) { @@ -476,9 +481,8 @@ case EXTENT_TYPE_PREALLOC: { UINT64 off = start + bytes_read - tp.item->key.offset; - UINT32 read; - - read = ed->decoded_size - off; + UINT32 read = len - off; + if (read > length) read = length;
RtlZeroMemory(data + bytes_read, read); @@ -503,7 +507,7 @@ break; else if (next_tp.item->key.obj_id != inode || next_tp.item->key.obj_type != TYPE_EXTENT_DATA || - next_tp.item->key.offset != tp.item->key.offset + ed->decoded_size + next_tp.item->key.offset != tp.item->key.offset + len ) { free_traverse_ptr(&next_tp); break;
Modified: trunk/reactos/drivers/filesystems/btrfs/treefuncs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/btrfs/t... ============================================================================== --- trunk/reactos/drivers/filesystems/btrfs/treefuncs.c [iso-8859-1] (original) +++ trunk/reactos/drivers/filesystems/btrfs/treefuncs.c [iso-8859-1] Sat Mar 26 11:53:07 2016 @@ -386,6 +386,7 @@ // t->address = addr; // t->level = th->level; t->refcount = 1; + t->has_address = TRUE; t->Vcb = Vcb; t->parent = NULL; t->root = r; @@ -393,6 +394,7 @@ t->paritem = NULL; t->size = 0; t->new_address = 0; + t->has_new_address = FALSE; #ifdef DEBUG_TREE_REFCOUNTS #ifdef DEBUG_LONG_MESSAGES _debug_message(func, file, line, "loaded tree %p (%llx)\n", t, addr); @@ -698,11 +700,20 @@ }
if (t->header.level == 0 && cmp == 0 && !ignore && td && td->ignore) { + tree_data* origtd = td; + while (td && td->ignore) td = next_item(t, td);
- if (td) + if (td) { cmp = keycmp(searchkey, &td->key); + + if (cmp != 0) { + td = origtd; + cmp = 0; + } + } else + td = origtd; } } while (td && cmp == 1);
Modified: trunk/reactos/drivers/filesystems/btrfs/write.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/btrfs/w... ============================================================================== --- trunk/reactos/drivers/filesystems/btrfs/write.c [iso-8859-1] (original) +++ trunk/reactos/drivers/filesystems/btrfs/write.c [iso-8859-1] Sat Mar 26 11:53:07 2016 @@ -1093,13 +1093,13 @@ tree_cache* tc2 = CONTAINING_RECORD(le, tree_cache, list_entry);
if (tc2->write) { - if (tc2->tree->header.num_items == 0) + if (tc2->tree->header.num_items == 0 && tc2->tree->parent) return FALSE;
if (tc2->tree->size > maxsize) return FALSE;
- if (tc2->tree->new_address == 0) + if (!tc2->tree->has_new_address) return FALSE; }
@@ -1263,6 +1263,7 @@ free_traverse_ptr(&insert_tp);
t->new_address = address; + t->has_new_address = TRUE;
return TRUE; } @@ -1272,7 +1273,7 @@ EXTENT_ITEM_TREE2* eit2; traverse_ptr insert_tp;
- TRACE("(%p, %p, %p, %p)\n", Vcb, t, c); + TRACE("(%p, %p, %p, %p)\n", Vcb, t, c, rollback);
if (!find_address_in_chunk(Vcb, c, Vcb->superblock.node_size, &address)) return FALSE; @@ -1316,6 +1317,7 @@ free_traverse_ptr(&insert_tp);
t->new_address = address; + t->has_new_address = TRUE;
return TRUE; } @@ -1341,7 +1343,7 @@ // } // }
- if (t->header.address != 0) { + if (t->has_address) { origchunk = get_chunk_from_address(Vcb, t->header.address);
if (insert_tree_extent(Vcb, t, origchunk, rollback)) @@ -1384,7 +1386,7 @@
searchkey.obj_id = address; searchkey.obj_type = TYPE_METADATA_ITEM; - searchkey.offset = t->header.level; + searchkey.offset = 0xffffffffffffffff;
Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE); if (!NT_SUCCESS(Status)) { @@ -1392,7 +1394,7 @@ return FALSE; }
- if (keycmp(&tp.item->key, &searchkey)) { + if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) { TRACE("could not find %llx,%x,%llx in extent_root\n", searchkey.obj_id, searchkey.obj_type, searchkey.offset); free_traverse_ptr(&tp); return FALSE; @@ -1765,7 +1767,7 @@ while (le != &Vcb->tree_cache) { tree_cache* tc2 = CONTAINING_RECORD(le, tree_cache, list_entry);
- if (tc2->write && tc2->tree->new_address == 0) { + if (tc2->write && !tc2->tree->has_new_address) { chunk* c;
Status = get_tree_new_address(Vcb, tc2->tree, rollback); @@ -1776,7 +1778,7 @@
TRACE("allocated extent %llx\n", tc2->tree->new_address);
- if (tc2->tree->header.address != 0) { + if (tc2->tree->has_address) { Status = reduce_tree_extent(Vcb, tc2->tree->header.address, tc2->tree, rollback);
if (!NT_SUCCESS(Status)) { @@ -2088,7 +2090,7 @@ traverse_ptr tp; EXTENT_ITEM_TREE* eit;
- if (tc2->tree->new_address == 0) { + if (!tc2->tree->has_new_address) { ERR("error - tried to write tree with no new address\n"); int3; } @@ -2226,13 +2228,8 @@ crash = TRUE; }
- if (tc2->tree->new_address == 0) { - ERR("tree %llx, level %x: tried to write tree to address 0\n", tc2->tree->root->id, tc2->tree->header.level); - crash = TRUE; - } - - if (tc2->tree->header.num_items == 0) { - ERR("tree %llx, level %x: tried to write empty tree\n", tc2->tree->root->id, tc2->tree->header.level); + if (tc2->tree->header.num_items == 0 && tc2->tree->parent) { + ERR("tree %llx, level %x: tried to write empty tree with parent\n", tc2->tree->root->id, tc2->tree->header.level); crash = TRUE; }
@@ -2257,6 +2254,7 @@ tc2->tree->header.address = tc2->tree->new_address; tc2->tree->header.generation = Vcb->superblock.generation; tc2->tree->header.flags |= HEADER_FLAG_MIXED_BACKREF; + tc2->tree->has_address = TRUE;
data = ExAllocatePoolWithTag(NonPagedPool, Vcb->superblock.node_size, ALLOC_TAG); if (!data) { @@ -2564,11 +2562,13 @@ nt->header.flags = HEADER_FLAG_MIXED_BACKREF;
nt->refcount = 0; + nt->has_address = FALSE; nt->Vcb = Vcb; nt->parent = t->parent; nt->root = t->root; // nt->nonpaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(tree_nonpaged), ALLOC_TAG); nt->new_address = 0; + nt->has_new_address = FALSE; nt->flags = t->flags; InitializeListHead(&nt->itemlist);
@@ -2637,6 +2637,22 @@
// // TRACE("last item is now (%x,%x,%x)\n", (UINT32)oldlastitem->key.obj_id, oldlastitem->key.obj_type, (UINT32)oldlastitem->key.offset);
+ if (nt->header.level > 0) { + LIST_ENTRY* le = nt->itemlist.Flink; + + while (le != &nt->itemlist) { + tree_data* td2 = CONTAINING_RECORD(le, tree_data, list_entry); + + if (td2->treeholder.tree) { + td2->treeholder.tree->parent = nt; + increase_tree_rc(nt); + free_tree(t); + } + + le = le->Flink; + } + } + if (nt->parent) { increase_tree_rc(nt->parent);
@@ -2648,7 +2664,7 @@
td->key = newfirstitem->key;
- InsertAfter(&t->itemlist, &td->list_entry, &t->paritem->list_entry); + InsertHeadList(&t->paritem->list_entry, &td->list_entry);
td->ignore = FALSE; td->inserted = TRUE; @@ -2683,11 +2699,13 @@ pt->header.flags = HEADER_FLAG_MIXED_BACKREF;
pt->refcount = 2; + pt->has_address = FALSE; pt->Vcb = Vcb; pt->parent = NULL; pt->paritem = NULL; pt->root = t->root; pt->new_address = 0; + pt->has_new_address = FALSE; // pt->nonpaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(tree_nonpaged), ALLOC_TAG); pt->size = pt->header.num_items * sizeof(internal_node); pt->flags = t->flags; @@ -2743,6 +2761,7 @@ nt->parent = pt;
end: + t->root->root_item.bytes_used += Vcb->superblock.node_size;
// #ifdef DEBUG_PARANOID // lastkey2.obj_id = 0xffffffffffffffff; @@ -2857,6 +2876,22 @@ t->header.num_items += next_tree->header.num_items; t->size += next_tree->size;
+ if (next_tree->header.level > 0) { + le = next_tree->itemlist.Flink; + + while (le != &next_tree->itemlist) { + tree_data* td2 = CONTAINING_RECORD(le, tree_data, list_entry); + + if (td2->treeholder.tree) { + td2->treeholder.tree->parent = t; + increase_tree_rc(t); + free_tree(next_tree); + } + + le = le->Flink; + } + } + t->itemlist.Blink->Flink = next_tree->itemlist.Flink; t->itemlist.Blink->Flink->Blink = t->itemlist.Blink; t->itemlist.Blink = next_tree->itemlist.Blink; @@ -2877,7 +2912,7 @@ next_tree->header.num_items = 0; next_tree->size = 0;
- if (next_tree->new_address != 0) { // delete associated EXTENT_ITEM + if (next_tree->has_new_address) { // delete associated EXTENT_ITEM Status = reduce_tree_extent(Vcb, next_tree->new_address, next_tree, rollback);
if (!NT_SUCCESS(Status)) { @@ -2885,7 +2920,7 @@ free_tree(next_tree); return Status; } - } else if (next_tree->header.address != 0) { + } else if (next_tree->has_address) { Status = reduce_tree_extent(Vcb, next_tree->header.address, next_tree, rollback);
if (!NT_SUCCESS(Status)) { @@ -2910,6 +2945,8 @@ RemoveEntryList(&nextparitem->list_entry); ExFreePool(next_tree->paritem); next_tree->paritem = NULL; + + next_tree->root->root_item.bytes_used -= Vcb->superblock.node_size;
free_tree(next_tree);
@@ -2950,6 +2987,12 @@ if (t->size + size < Vcb->superblock.node_size - sizeof(tree_header)) { RemoveEntryList(&td->list_entry); InsertTailList(&t->itemlist, &td->list_entry); + + if (next_tree->header.level > 0 && td->treeholder.tree) { + td->treeholder.tree->parent = t; + increase_tree_rc(t); + free_tree(next_tree); + }
if (!td->ignore) { next_tree->size -= size; @@ -2991,6 +3034,106 @@ }
return STATUS_SUCCESS; +} + +static NTSTATUS update_extent_level(device_extension* Vcb, UINT64 address, tree* t, UINT8 level, LIST_ENTRY* rollback) { + KEY searchkey; + traverse_ptr tp; + NTSTATUS Status; + + if (Vcb->superblock.incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA) { + searchkey.obj_id = address; + searchkey.obj_type = TYPE_METADATA_ITEM; + searchkey.offset = t->header.level; + + Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE); + if (!NT_SUCCESS(Status)) { + ERR("error - find_item returned %08x\n", Status); + return Status; + } + + if (!keycmp(&tp.item->key, &searchkey)) { + EXTENT_ITEM_SKINNY_METADATA* eism; + + if (tp.item->size > 0) { + eism = ExAllocatePoolWithTag(PagedPool, tp.item->size, ALLOC_TAG); + + if (!eism) { + ERR("out of memory\n"); + free_traverse_ptr(&tp); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlCopyMemory(eism, tp.item->data, tp.item->size); + } else + eism = NULL; + + delete_tree_item(Vcb, &tp, rollback); + + if (!insert_tree_item(Vcb, Vcb->extent_root, address, TYPE_METADATA_ITEM, level, eism, tp.item->size, NULL, rollback)) { + ERR("insert_tree_item failed\n"); + ExFreePool(eism); + free_traverse_ptr(&tp); + return STATUS_INTERNAL_ERROR; + } + + free_traverse_ptr(&tp); + return STATUS_SUCCESS; + } + + free_traverse_ptr(&tp); + } + + searchkey.obj_id = address; + searchkey.obj_type = TYPE_EXTENT_ITEM; + searchkey.offset = 0xffffffffffffffff; + + Status = find_item(Vcb, Vcb->extent_root, &tp, &searchkey, FALSE); + if (!NT_SUCCESS(Status)) { + ERR("error - find_item returned %08x\n", Status); + return Status; + } + + if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type) { + EXTENT_ITEM_TREE* eit; + + if (tp.item->size < sizeof(EXTENT_ITEM_TREE)) { + 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(EXTENT_ITEM_TREE)); + free_traverse_ptr(&tp); + return STATUS_INTERNAL_ERROR; + } + + eit = ExAllocatePoolWithTag(PagedPool, tp.item->size, ALLOC_TAG); + + if (!eit) { + ERR("out of memory\n"); + free_traverse_ptr(&tp); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlCopyMemory(eit, tp.item->data, tp.item->size); + + delete_tree_item(Vcb, &tp, rollback); + + eit->level = level; + + if (!insert_tree_item(Vcb, Vcb->extent_root, tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, eit, tp.item->size, NULL, rollback)) { + ERR("insert_tree_item failed\n"); + ExFreePool(eit); + free_traverse_ptr(&tp); + return STATUS_INTERNAL_ERROR; + } + + free_traverse_ptr(&tp); + + return STATUS_SUCCESS; + } + + ERR("could not find EXTENT_ITEM for address %llx\n", address); + + free_traverse_ptr(&tp); + + return STATUS_INTERNAL_ERROR; }
static NTSTATUS STDCALL do_splits(device_extension* Vcb, LIST_ENTRY* rollback) { @@ -3025,38 +3168,39 @@ empty = FALSE;
if (tc2->tree->header.num_items == 0) { - LIST_ENTRY* le2; - KEY firstitem = {0xcccccccccccccccc,0xcc,0xcccccccccccccccc}; - - done_deletions = TRUE; - - le2 = tc2->tree->itemlist.Flink; - while (le2 != &tc2->tree->itemlist) { - tree_data* td = CONTAINING_RECORD(le2, tree_data, list_entry); - firstitem = td->key; - break; - } - - ERR("deleting tree in root %llx (first item was %llx,%x,%llx)\n", - tc2->tree->root->id, firstitem.obj_id, firstitem.obj_type, firstitem.offset); - - if (tc2->tree->new_address != 0) { // delete associated EXTENT_ITEM - Status = reduce_tree_extent(Vcb, tc2->tree->new_address, tc2->tree, rollback); + if (tc2->tree->parent) { + LIST_ENTRY* le2; + KEY firstitem = {0xcccccccccccccccc,0xcc,0xcccccccccccccccc};
- if (!NT_SUCCESS(Status)) { - ERR("reduce_tree_extent returned %08x\n", Status); - return Status; + done_deletions = TRUE; + + le2 = tc2->tree->itemlist.Flink; + while (le2 != &tc2->tree->itemlist) { + tree_data* td = CONTAINING_RECORD(le2, tree_data, list_entry); + firstitem = td->key; + break; } - } else if (tc2->tree->header.address != 0) { - Status = reduce_tree_extent(Vcb,tc2->tree->header.address, tc2->tree, rollback); + TRACE("deleting tree in root %llx (first item was %llx,%x,%llx)\n", + tc2->tree->root->id, firstitem.obj_id, firstitem.obj_type, firstitem.offset);
- if (!NT_SUCCESS(Status)) { - ERR("reduce_tree_extent returned %08x\n", Status); - return Status; + tc2->tree->root->root_item.bytes_used -= Vcb->superblock.node_size; + + if (tc2->tree->has_new_address) { // delete associated EXTENT_ITEM + Status = reduce_tree_extent(Vcb, tc2->tree->new_address, tc2->tree, rollback); + + if (!NT_SUCCESS(Status)) { + ERR("reduce_tree_extent returned %08x\n", Status); + return Status; + } + } else if (tc2->tree->has_address) { + Status = reduce_tree_extent(Vcb,tc2->tree->header.address, tc2->tree, rollback); + + if (!NT_SUCCESS(Status)) { + ERR("reduce_tree_extent returned %08x\n", Status); + return Status; + } } - } - - if (tc2->tree->parent) { + if (!tc2->tree->paritem->ignore) { tc2->tree->paritem->ignore = TRUE; tc2->tree->parent->header.num_items--; @@ -3071,19 +3215,25 @@
RemoveEntryList(le); ExFreePool(tc2); - } else { - FIXME("trying to delete top root, not sure what to do here\n"); // FIXME - return STATUS_INTERNAL_ERROR; + } else if (tc2->tree->header.level != 0) { + if (tc2->tree->has_new_address) { + Status = update_extent_level(Vcb, tc2->tree->new_address, tc2->tree, 0, rollback); + + if (!NT_SUCCESS(Status)) { + ERR("update_extent_level returned %08x\n", Status); + return Status; + } + } + + tc2->tree->header.level = 0; } - } else { - if (tc2->tree->size > Vcb->superblock.node_size - sizeof(tree_header)) { - TRACE("splitting overlarge tree (%x > %x)\n", tc2->tree->size, Vcb->superblock.node_size - sizeof(tree_header)); - Status = split_tree(Vcb, tc2->tree); - - if (!NT_SUCCESS(Status)) { - ERR("split_tree returned %08x\n", Status); - return Status; - } + } else if (tc2->tree->size > Vcb->superblock.node_size - sizeof(tree_header)) { + TRACE("splitting overlarge tree (%x > %x)\n", tc2->tree->size, Vcb->superblock.node_size - sizeof(tree_header)); + Status = split_tree(Vcb, tc2->tree); + + if (!NT_SUCCESS(Status)) { + ERR("split_tree returned %08x\n", Status); + return Status; } } } @@ -3145,16 +3295,16 @@ le2 = le2->Flink; }
- ERR("deleting top-level tree in root %llx with one item\n", tc2->tree->root->id); + TRACE("deleting top-level tree in root %llx with one item\n", tc2->tree->root->id);
- if (tc2->tree->new_address != 0) { // delete associated EXTENT_ITEM + if (tc2->tree->has_new_address) { // delete associated EXTENT_ITEM Status = reduce_tree_extent(Vcb, tc2->tree->new_address, tc2->tree, rollback);
if (!NT_SUCCESS(Status)) { ERR("reduce_tree_extent returned %08x\n", Status); return Status; } - } else if (tc2->tree->header.address != 0) { + } else if (tc2->tree->has_address) { Status = reduce_tree_extent(Vcb,tc2->tree->header.address, tc2->tree, rollback);
if (!NT_SUCCESS(Status)) { @@ -3180,8 +3330,11 @@
if (child_tree) { child_tree->parent = NULL; + child_tree->paritem = NULL; free_tree(tc2->tree); } + + tc2->tree->root->root_item.bytes_used -= Vcb->superblock.node_size;
free_tree(tc2->tree);
@@ -3208,7 +3361,7 @@ TRACE("(%p)\n", Vcb);
// If only changing superblock, e.g. changing label, we still need to rewrite - // the root tree so the generations mach. Otherwise you won't be able to mount on Linux. + // the root tree so the generations match, otherwise you won't be able to mount on Linux. if (Vcb->write_trees > 0) { KEY searchkey; traverse_ptr tp; @@ -4236,6 +4389,8 @@
do { EXTENT_DATA* ed = (EXTENT_DATA*)tp.item->data; + EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ed->data; + UINT64 len;
if (tp.item->size < sizeof(EXTENT_DATA)) { 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(EXTENT_DATA)); @@ -4251,7 +4406,9 @@
b = find_next_item(Vcb, &tp, &next_tp, FALSE);
- if (tp.item->key.offset < end_data && tp.item->key.offset + ed->decoded_size >= start_data) { + len = ed->type == EXTENT_TYPE_INLINE ? ed->decoded_size : ed2->num_bytes; + + if (tp.item->key.offset < end_data && tp.item->key.offset + len >= start_data) { if (ed->compression != BTRFS_COMPRESSION_NONE) { FIXME("FIXME - compression not supported at present\n"); Status = STATUS_NOT_SUPPORTED; @@ -4270,20 +4427,18 @@ goto end; }
- // FIXME - is ed->decoded_size the size of the whole extent, or just this bit of it? - if (ed->type == EXTENT_TYPE_INLINE) { - if (start_data <= tp.item->key.offset && end_data >= tp.item->key.offset + ed->decoded_size) { // remove all + if (start_data <= tp.item->key.offset && end_data >= tp.item->key.offset + len) { // remove all delete_tree_item(Vcb, &tp, rollback);
- fcb->inode_item.st_blocks -= ed->decoded_size; - } else if (start_data <= tp.item->key.offset && end_data < tp.item->key.offset + ed->decoded_size) { // remove beginning + fcb->inode_item.st_blocks -= len; + } else if (start_data <= tp.item->key.offset && end_data < tp.item->key.offset + len) { // remove beginning EXTENT_DATA* ned; UINT64 size;
delete_tree_item(Vcb, &tp, rollback);
- size = ed->decoded_size - (end_data - tp.item->key.offset); + size = len - (end_data - tp.item->key.offset);
ned = ExAllocatePoolWithTag(PagedPool, sizeof(EXTENT_DATA) - 1 + size, ALLOC_TAG); if (!ned) { @@ -4309,7 +4464,7 @@ }
fcb->inode_item.st_blocks -= end_data - tp.item->key.offset; - } else if (start_data > tp.item->key.offset && end_data >= tp.item->key.offset + ed->decoded_size) { // remove end + } else if (start_data > tp.item->key.offset && end_data >= tp.item->key.offset + len) { // remove end EXTENT_DATA* ned; UINT64 size;
@@ -4340,8 +4495,8 @@ goto end; }
- fcb->inode_item.st_blocks -= tp.item->key.offset + ed->decoded_size - start_data; - } else if (start_data > tp.item->key.offset && end_data < tp.item->key.offset + ed->decoded_size) { // remove middle + fcb->inode_item.st_blocks -= tp.item->key.offset + len - start_data; + } else if (start_data > tp.item->key.offset && end_data < tp.item->key.offset + len) { // remove middle EXTENT_DATA* ned; UINT64 size;
@@ -4372,7 +4527,7 @@ goto end; }
- size = tp.item->key.offset + ed->decoded_size - end_data; + size = tp.item->key.offset + len - end_data;
ned = ExAllocatePoolWithTag(PagedPool, sizeof(EXTENT_DATA) - 1 + size, ALLOC_TAG); if (!ned) { @@ -4400,39 +4555,24 @@ fcb->inode_item.st_blocks -= end_data - start_data; } } else if (ed->type == EXTENT_TYPE_REGULAR || ed->type == EXTENT_TYPE_PREALLOC) { - EXTENT_DATA2* ed2 = (EXTENT_DATA2*)&ed->data[0]; - - if (start_data <= tp.item->key.offset && end_data >= tp.item->key.offset + ed->decoded_size) { // remove all + if (start_data <= tp.item->key.offset && end_data >= tp.item->key.offset + len) { // remove all if (ed2->address != 0) { - Status = remove_extent_ref(Vcb, ed2->address, ed2->size, fcb->subvol, fcb->inode, tp.item->key.offset, changed_sector_list, rollback); + Status = remove_extent_ref(Vcb, ed2->address, ed2->size, fcb->subvol, fcb->inode, tp.item->key.offset - ed2->offset, changed_sector_list, rollback); if (!NT_SUCCESS(Status)) { ERR("remove_extent_ref returned %08x\n", Status); goto end; }
- fcb->inode_item.st_blocks -= ed->decoded_size; + fcb->inode_item.st_blocks -= len; }
delete_tree_item(Vcb, &tp, rollback); - } else if (start_data <= tp.item->key.offset && end_data < tp.item->key.offset + ed->decoded_size) { // remove beginning + } else if (start_data <= tp.item->key.offset && end_data < tp.item->key.offset + len) { // remove beginning EXTENT_DATA* ned; EXTENT_DATA2* ned2;
- if (ed2->address != 0) { - Status = add_extent_ref(Vcb, ed2->address, ed2->size, fcb->subvol, fcb->inode, end_data, rollback); - if (!NT_SUCCESS(Status)) { - ERR("add_extent_ref returned %08x\n", Status); - goto end; - } - - Status = remove_extent_ref(Vcb, ed2->address, ed2->size, fcb->subvol, fcb->inode, tp.item->key.offset, changed_sector_list, rollback); - if (!NT_SUCCESS(Status)) { - ERR("remove_extent_ref returned %08x\n", Status); - goto end; - } - + if (ed2->address != 0) fcb->inode_item.st_blocks -= end_data - tp.item->key.offset; - }
delete_tree_item(Vcb, &tp, rollback);
@@ -4446,7 +4586,7 @@ ned2 = (EXTENT_DATA2*)&ned->data[0];
ned->generation = Vcb->superblock.generation; - ned->decoded_size = ed->decoded_size - (end_data - tp.item->key.offset); + ned->decoded_size = ed->decoded_size; ned->compression = ed->compression; ned->encryption = ed->encryption; ned->encoding = ed->encoding; @@ -4462,12 +4602,12 @@ Status = STATUS_INTERNAL_ERROR; goto end; } - } else if (start_data > tp.item->key.offset && end_data >= tp.item->key.offset + ed->decoded_size) { // remove end + } else if (start_data > tp.item->key.offset && end_data >= tp.item->key.offset + len) { // remove end EXTENT_DATA* ned; EXTENT_DATA2* ned2;
if (ed2->address != 0) - fcb->inode_item.st_blocks -= tp.item->key.offset + ed->decoded_size - start_data; + fcb->inode_item.st_blocks -= tp.item->key.offset + len - start_data;
delete_tree_item(Vcb, &tp, rollback);
@@ -4481,7 +4621,7 @@ ned2 = (EXTENT_DATA2*)&ned->data[0];
ned->generation = Vcb->superblock.generation; - ned->decoded_size = start_data - tp.item->key.offset; + ned->decoded_size = ed->decoded_size; ned->compression = ed->compression; ned->encryption = ed->encryption; ned->encoding = ed->encoding; @@ -4497,19 +4637,12 @@ Status = STATUS_INTERNAL_ERROR; goto end; } - } else if (start_data > tp.item->key.offset && end_data < tp.item->key.offset + ed->decoded_size) { // remove middle + } else if (start_data > tp.item->key.offset && end_data < tp.item->key.offset + len) { // remove middle EXTENT_DATA* ned; EXTENT_DATA2* ned2;
- if (ed2->address != 0) { - Status = add_extent_ref(Vcb, ed2->address, ed2->size, fcb->subvol, fcb->inode, end_data, rollback); - if (!NT_SUCCESS(Status)) { - ERR("add_extent_ref returned %08x\n", Status); - goto end; - } - + if (ed2->address != 0) fcb->inode_item.st_blocks -= end_data - start_data; - }
delete_tree_item(Vcb, &tp, rollback);
@@ -4523,7 +4656,7 @@ ned2 = (EXTENT_DATA2*)&ned->data[0];
ned->generation = Vcb->superblock.generation; - ned->decoded_size = start_data - tp.item->key.offset; + ned->decoded_size = ed->decoded_size; ned->compression = ed->compression; ned->encryption = ed->encryption; ned->encoding = ed->encoding; @@ -4550,7 +4683,7 @@ ned2 = (EXTENT_DATA2*)&ned->data[0];
ned->generation = Vcb->superblock.generation; - ned->decoded_size = tp.item->key.offset + ed->decoded_size - end_data; + ned->decoded_size = ed->decoded_size; ned->compression = ed->compression; ned->encryption = ed->encryption; ned->encoding = ed->encoding; @@ -4558,7 +4691,7 @@ ned2->address = ed2->address; ned2->size = ed2->size; ned2->offset = ed2->address == 0 ? 0 : (ed2->offset + (end_data - tp.item->key.offset)); - ned2->num_bytes = tp.item->key.offset + ed->decoded_size - end_data; + ned2->num_bytes = tp.item->key.offset + len - end_data;
if (!insert_tree_item(Vcb, fcb->subvol, fcb->inode, TYPE_EXTENT_DATA, end_data, ned, sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2), NULL, rollback)) { ERR("insert_tree_item failed\n"); @@ -4830,9 +4963,16 @@ TRACE("not extending extent which is not EXTENT_TYPE_REGULAR\n"); goto end; } - - if (tp.item->key.offset + ed->decoded_size != start_data) { - TRACE("last EXTENT_DATA does not run up to start_data (%llx + %llx != %llx)\n", tp.item->key.offset, ed->decoded_size, start_data); + + ed2 = (EXTENT_DATA2*)ed->data; + + if (tp.item->size < sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2)) { + 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(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2)); + goto end; + } + + if (tp.item->key.offset + ed2->num_bytes != start_data) { + TRACE("last EXTENT_DATA does not run up to start_data (%llx + %llx != %llx)\n", tp.item->key.offset, ed2->num_bytes, start_data); goto end; }
@@ -4851,14 +4991,7 @@ goto end; }
- ed2 = (EXTENT_DATA2*)ed->data; - - if (tp.item->size < sizeof(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2)) { - 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(EXTENT_DATA) - 1 + sizeof(EXTENT_DATA2)); - goto end; - } - - if (ed2->size - ed2->offset != ed->decoded_size) { + if (ed2->size - ed2->offset != ed2->num_bytes) { TRACE("last EXTENT_DATA does not run all the way to the end of the extent\n"); goto end; } @@ -5033,6 +5166,7 @@ traverse_ptr tp; NTSTATUS Status; EXTENT_DATA* ed; + UINT64 len;
searchkey.obj_id = fcb->inode; searchkey.obj_type = TYPE_EXTENT_DATA; @@ -5065,19 +5199,24 @@ // return STATUS_INTERNAL_ERROR; // }
- if (tp.item->key.obj_type == TYPE_EXTENT_DATA && tp.item->size >= sizeof(EXTENT_DATA)) + if (tp.item->key.obj_type == TYPE_EXTENT_DATA && tp.item->size >= sizeof(EXTENT_DATA)) { + EXTENT_DATA2* ed2; + ed = (EXTENT_DATA*)tp.item->data; - else + ed2 = (EXTENT_DATA2*)ed->data; + + len = ed->type == EXTENT_TYPE_INLINE ? ed->decoded_size : ed2->num_bytes; + } else ed = NULL;
- if (tp.item->key.obj_id != fcb->inode || tp.item->key.obj_type != TYPE_EXTENT_DATA || !ed || tp.item->key.offset + ed->decoded_size < start_data) { + if (tp.item->key.obj_id != fcb->inode || tp.item->key.obj_type != TYPE_EXTENT_DATA || !ed || tp.item->key.offset + len < start_data) { if (tp.item->key.obj_id != fcb->inode || tp.item->key.obj_type != TYPE_EXTENT_DATA) Status = insert_sparse_extent(Vcb, fcb->subvol, fcb->inode, 0, start_data, rollback); else if (!ed) 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(EXTENT_DATA)); else { - Status = insert_sparse_extent(Vcb, fcb->subvol, fcb->inode, tp.item->key.offset + ed->decoded_size, - start_data - tp.item->key.offset - ed->decoded_size, rollback); + Status = insert_sparse_extent(Vcb, fcb->subvol, fcb->inode, tp.item->key.offset + len, + start_data - tp.item->key.offset - len, rollback); } if (!NT_SUCCESS(Status)) { ERR("insert_sparse_extent returned %08x\n", Status); @@ -5388,14 +5527,17 @@
oldalloc = 0; if (tp.item->key.obj_id == fcb->inode && tp.item->key.obj_type == TYPE_EXTENT_DATA) { + EXTENT_DATA* ed = (EXTENT_DATA*)tp.item->data; + EXTENT_DATA2* ed2 = (EXTENT_DATA2*)ed->data; + if (tp.item->size < sizeof(EXTENT_DATA)) { 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(EXTENT_DATA)); free_traverse_ptr(&tp); return STATUS_INTERNAL_ERROR; }
- oldalloc = tp.item->key.offset + ((EXTENT_DATA*)tp.item->data)->decoded_size; - cur_inline = ((EXTENT_DATA*)tp.item->data)->type == EXTENT_TYPE_INLINE; + oldalloc = tp.item->key.offset + (ed->type == EXTENT_TYPE_INLINE ? ed->decoded_size : ed2->num_bytes); + cur_inline = ed->type == EXTENT_TYPE_INLINE;
if (cur_inline && end > fcb->Vcb->max_inline) { LIST_ENTRY changed_sector_list; @@ -5405,7 +5547,7 @@
TRACE("giving inline file proper extents\n");
- origlength = ((EXTENT_DATA*)tp.item->data)->decoded_size; + origlength = ed->decoded_size;
cur_inline = FALSE;
@@ -5426,7 +5568,7 @@ if (length > origlength) RtlZeroMemory(data + origlength, length - origlength);
- RtlCopyMemory(data, ((EXTENT_DATA*)tp.item->data)->data, origlength); + RtlCopyMemory(data, ed->data, origlength);
fcb->inode_item.st_blocks -= origlength;
@@ -5447,7 +5589,6 @@ }
if (cur_inline) { - EXTENT_DATA* ed; ULONG edsize;
if (end > oldalloc) { @@ -5868,7 +6009,7 @@ ed = (EXTENT_DATA*)tp.item->data; ed2 = (EXTENT_DATA2*)&ed->data[0];
- length = oldlength = ed->decoded_size; + length = oldlength = ed->type == EXTENT_TYPE_INLINE ? ed->decoded_size : ed2->num_bytes; lastoff = tp.item->key.offset;
TRACE("(%llx,%x,%llx) length = %llx\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, length); @@ -5895,7 +6036,7 @@ ed = (EXTENT_DATA*)tp.item->data; ed2 = (EXTENT_DATA2*)&ed->data[0];
- length = ed->decoded_size; + length = ed->type == EXTENT_TYPE_INLINE ? ed->decoded_size : ed2->num_bytes;
TRACE("(%llx,%x,%llx) length = %llx\n", tp.item->key.obj_id, tp.item->key.obj_type, tp.item->key.offset, length);