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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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);