// 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) {
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);
#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
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
}
ExFreePool(ccb);
}
- if (fcb->refcount == 1)
- CcUninitializeCacheMap(FileObject, NULL, NULL);
+ CcUninitializeCacheMap(FileObject, NULL, NULL);
free_fcb(fcb);
- FileObject->FsContext = NULL;
-
return STATUS_SUCCESS;
}
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) {
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;
}
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);
}
}