1
0
mirror of https://github.com/bobranten/Ext4Fsd.git synced 2025-10-30 05:18:31 -05:00

converted some files from UNIX to DOS line endings

This commit is contained in:
Bo Brantén
2020-07-21 01:12:02 +02:00
parent 612abae95a
commit 4fb9ddefa7
45 changed files with 20723 additions and 20723 deletions

View File

@@ -1 +1 @@
DIRS = nls ext3 ext4 jbd2 sys DIRS = nls ext3 ext4 jbd2 sys

View File

@@ -1,54 +1,54 @@
/* /*
* COPYRIGHT: See COPYRIGHT.TXT * COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: access.c * FILE: access.c
* PROGRAMMER: Matt Wu <mattwu@163.com> * PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com * HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "ext2fs.h" #include "ext2fs.h"
/* GLOBALS ***************************************************************/ /* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global; extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/ /* DEFINITIONS *************************************************************/
int Ext2CheckInodeAccess(PEXT2_VCB Vcb, struct inode *in, int attempt) int Ext2CheckInodeAccess(PEXT2_VCB Vcb, struct inode *in, int attempt)
{ {
int granted = 0; int granted = 0;
uid_t uid = Vcb->uid; uid_t uid = Vcb->uid;
gid_t gid = Vcb->gid; gid_t gid = Vcb->gid;
if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) { if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) {
uid = Vcb->euid; uid = Vcb->euid;
gid = Vcb->egid; gid = Vcb->egid;
} }
if (!uid || uid == in->i_uid) { if (!uid || uid == in->i_uid) {
/* grant all access for inode owner or root */ /* grant all access for inode owner or root */
granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute; granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute;
} else if (gid == in->i_gid) { } else if (gid == in->i_gid) {
if (Ext2IsGroupReadOnly(in->i_mode)) if (Ext2IsGroupReadOnly(in->i_mode))
granted = Ext2FileCanRead | Ext2FileCanExecute; granted = Ext2FileCanRead | Ext2FileCanExecute;
else if (Ext2IsGroupWritable(in->i_mode)) else if (Ext2IsGroupWritable(in->i_mode))
granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute; granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute;
} else { } else {
if (Ext2IsOtherReadOnly(in->i_mode)) if (Ext2IsOtherReadOnly(in->i_mode))
granted = Ext2FileCanRead | Ext2FileCanExecute; granted = Ext2FileCanRead | Ext2FileCanExecute;
else if (Ext2IsOtherWritable(in->i_mode)) else if (Ext2IsOtherWritable(in->i_mode))
granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute; granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute;
} }
return IsFlagOn(granted, attempt); return IsFlagOn(granted, attempt);
} }
int Ext2CheckFileAccess(PEXT2_VCB Vcb, PEXT2_MCB Mcb, int attempt) int Ext2CheckFileAccess(PEXT2_VCB Vcb, PEXT2_MCB Mcb, int attempt)
{ {
return Ext2CheckInodeAccess(Vcb, &Mcb->Inode, attempt); return Ext2CheckInodeAccess(Vcb, &Mcb->Inode, attempt);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,399 +1,399 @@
/* /*
* COPYRIGHT: See COPYRIGHT.TXT * COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: cleanup.c * FILE: cleanup.c
* PROGRAMMER: Matt Wu <mattwu@163.com> * PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com * HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "ext2fs.h" #include "ext2fs.h"
/* GLOBALS ***************************************************************/ /* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global; extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/ /* DEFINITIONS *************************************************************/
NTSTATUS NTSTATUS
Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
{ {
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PEXT2_VCB Vcb = NULL; PEXT2_VCB Vcb = NULL;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
PEXT2_FCB Fcb = NULL; PEXT2_FCB Fcb = NULL;
PEXT2_CCB Ccb = NULL; PEXT2_CCB Ccb = NULL;
PIRP Irp = NULL; PIRP Irp = NULL;
PEXT2_MCB Mcb = NULL; PEXT2_MCB Mcb = NULL;
BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN VcbResourceAcquired = FALSE;
BOOLEAN FcbResourceAcquired = FALSE; BOOLEAN FcbResourceAcquired = FALSE;
BOOLEAN FcbPagingIoResourceAcquired = FALSE; BOOLEAN FcbPagingIoResourceAcquired = FALSE;
BOOLEAN SymLinkDelete = FALSE; BOOLEAN SymLinkDelete = FALSE;
__try { __try {
ASSERT(IrpContext != NULL); ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject; DeviceObject = IrpContext->DeviceObject;
if (IsExt2FsDevice(DeviceObject)) { if (IsExt2FsDevice(DeviceObject)) {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
__leave; __leave;
} }
Irp = IrpContext->Irp; Irp = IrpContext->Irp;
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL); ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) && ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB))); (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
if (!IsVcbInited(Vcb)) { if (!IsVcbInited(Vcb)) {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
__leave; __leave;
} }
FileObject = IrpContext->FileObject; FileObject = IrpContext->FileObject;
Fcb = (PEXT2_FCB) FileObject->FsContext; Fcb = (PEXT2_FCB) FileObject->FsContext;
if (!Fcb || (Fcb->Identifier.Type != EXT2VCB && if (!Fcb || (Fcb->Identifier.Type != EXT2VCB &&
Fcb->Identifier.Type != EXT2FCB)) { Fcb->Identifier.Type != EXT2FCB)) {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
__leave; __leave;
} }
Mcb = Fcb->Mcb; Mcb = Fcb->Mcb;
Ccb = (PEXT2_CCB) FileObject->FsContext2; Ccb = (PEXT2_CCB) FileObject->FsContext2;
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) { if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
__leave; __leave;
} }
if (Fcb->Identifier.Type == EXT2VCB) { if (Fcb->Identifier.Type == EXT2VCB) {
ExAcquireResourceExclusiveLite( ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE); &Vcb->MainResource, TRUE);
VcbResourceAcquired = TRUE; VcbResourceAcquired = TRUE;
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
Vcb->LockFile == FileObject ){ Vcb->LockFile == FileObject ){
ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED); ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
Vcb->LockFile = NULL; Vcb->LockFile = NULL;
Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED); Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
} }
if (Ccb) { if (Ccb) {
Ext2DerefXcb(&Vcb->OpenHandleCount); Ext2DerefXcb(&Vcb->OpenHandleCount);
Ext2DerefXcb(&Vcb->OpenVolumeCount); Ext2DerefXcb(&Vcb->OpenVolumeCount);
} }
IoRemoveShareAccess(FileObject, &Vcb->ShareAccess); IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
__leave; __leave;
} }
ASSERT((Fcb->Identifier.Type == EXT2FCB) && ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB))); (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
FcbResourceAcquired = FcbResourceAcquired =
ExAcquireResourceExclusiveLite( ExAcquireResourceExclusiveLite(
&Fcb->MainResource, &Fcb->MainResource,
TRUE TRUE
); );
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) { if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) && if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) && IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
!IsVcbReadOnly(Vcb) ) { !IsVcbReadOnly(Vcb) ) {
Status = Ext2FlushFile(IrpContext, Fcb, Ccb); Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
} }
__leave; __leave;
} }
if (Ccb == NULL) { if (Ccb == NULL) {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
__leave; __leave;
} }
if (IsDirectory(Fcb)) { if (IsDirectory(Fcb)) {
if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) { if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING); SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
FsRtlNotifyFullChangeDirectory( FsRtlNotifyFullChangeDirectory(
Vcb->NotifySync, Vcb->NotifySync,
&Vcb->NotifyList, &Vcb->NotifyList,
Ccb, Ccb,
NULL, NULL,
FALSE, FALSE,
FALSE, FALSE,
0, 0,
NULL, NULL,
NULL, NULL,
NULL ); NULL );
} }
FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb); FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb);
} }
ASSERT((Ccb->Identifier.Type == EXT2CCB) && ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
(Ccb->Identifier.Size == sizeof(EXT2_CCB))); (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
Ext2DerefXcb(&Vcb->OpenHandleCount); Ext2DerefXcb(&Vcb->OpenHandleCount);
Ext2DerefXcb(&Fcb->OpenHandleCount); Ext2DerefXcb(&Fcb->OpenHandleCount);
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) { if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE; Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
} }
if (IsDirectory(Fcb)) { if (IsDirectory(Fcb)) {
ext3_release_dir(Fcb->Inode, &Ccb->filp); ext3_release_dir(Fcb->Inode, &Ccb->filp);
} else { } else {
if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) && if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) { !IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
LARGE_INTEGER SysTime; LARGE_INTEGER SysTime;
KeQuerySystemTime(&SysTime); KeQuerySystemTime(&SysTime);
Fcb->Inode->i_atime = Fcb->Inode->i_atime =
Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime); Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
Fcb->Mcb->LastAccessTime = Fcb->Mcb->LastAccessTime =
Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_atime); Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_atime);
Ext2SaveInode(IrpContext, Vcb, Fcb->Inode); Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
Ext2NotifyReportChange( Ext2NotifyReportChange(
IrpContext, IrpContext,
Vcb, Vcb,
Fcb->Mcb, Fcb->Mcb,
FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_LAST_ACCESS, FILE_NOTIFY_CHANGE_LAST_ACCESS,
FILE_ACTION_MODIFIED ); FILE_ACTION_MODIFIED );
} }
FsRtlCheckOplock( &Fcb->Oplock, FsRtlCheckOplock( &Fcb->Oplock,
Irp, Irp,
IrpContext, IrpContext,
NULL, NULL,
NULL ); NULL );
Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) { if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) {
Fcb->NonCachedOpenCount--; Fcb->NonCachedOpenCount--;
} }
if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) { if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
if (Ccb->SymLink || IsInodeSymLink(&Mcb->Inode)) { if (Ccb->SymLink || IsInodeSymLink(&Mcb->Inode)) {
SymLinkDelete = TRUE; SymLinkDelete = TRUE;
} else { } else {
SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING); SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
} }
} }
// //
// Drop any byte range locks this process may have on the file. // Drop any byte range locks this process may have on the file.
// //
FsRtlFastUnlockAll( FsRtlFastUnlockAll(
&Fcb->FileLockAnchor, &Fcb->FileLockAnchor,
FileObject, FileObject,
IoGetRequestorProcess(Irp), IoGetRequestorProcess(Irp),
NULL ); NULL );
// //
// If there are no byte range locks owned by other processes on the // If there are no byte range locks owned by other processes on the
// file the fast I/O read/write functions doesn't have to check for // file the fast I/O read/write functions doesn't have to check for
// locks so we set IsFastIoPossible to FastIoIsPossible again. // locks so we set IsFastIoPossible to FastIoIsPossible again.
// //
if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) { if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) {
if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) { if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) {
#if EXT2_DEBUG #if EXT2_DEBUG
DEBUG(DL_INF, (": %-16.16s %-31s %wZ\n", DEBUG(DL_INF, (": %-16.16s %-31s %wZ\n",
Ext2GetCurrentProcessName(), Ext2GetCurrentProcessName(),
"FastIoIsPossible", "FastIoIsPossible",
&Fcb->Mcb->FullName &Fcb->Mcb->FullName
)); ));
#endif #endif
Fcb->Header.IsFastIoPossible = FastIoIsPossible; Fcb->Header.IsFastIoPossible = FastIoIsPossible;
} }
} }
if (Fcb->OpenHandleCount == 0 && FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE | if (Fcb->OpenHandleCount == 0 && FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE |
FCB_ALLOC_IN_SETINFO) ){ FCB_ALLOC_IN_SETINFO) ){
if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_SETINFO)) { if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_SETINFO)) {
if (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart) { if (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart) {
if (!INODE_HAS_EXTENT(Fcb->Inode)) { if (!INODE_HAS_EXTENT(Fcb->Inode)) {
#if EXT2_PRE_ALLOCATION_SUPPORT #if EXT2_PRE_ALLOCATION_SUPPORT
__try { __try {
CcZeroData( FileObject, CcZeroData( FileObject,
&Fcb->Header.ValidDataLength, &Fcb->Header.ValidDataLength,
&Fcb->Header.AllocationSize, &Fcb->Header.AllocationSize,
TRUE); TRUE);
} __except (EXCEPTION_EXECUTE_HANDLER) { } __except (EXCEPTION_EXECUTE_HANDLER) {
DbgBreak(); DbgBreak();
} }
#endif #endif
} }
} }
} }
if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) { if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
LARGE_INTEGER Size; LARGE_INTEGER Size;
ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE); ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
FcbPagingIoResourceAcquired = TRUE; FcbPagingIoResourceAcquired = TRUE;
Size.QuadPart = CEILING_ALIGNED(ULONGLONG, Size.QuadPart = CEILING_ALIGNED(ULONGLONG,
(ULONGLONG)Fcb->Mcb->Inode.i_size, (ULONGLONG)Fcb->Mcb->Inode.i_size,
(ULONGLONG)BLOCK_SIZE); (ULONGLONG)BLOCK_SIZE);
if (!IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { if (!IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size); Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
Fcb->Header.AllocationSize = Size; Fcb->Header.AllocationSize = Size;
Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size; Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size;
if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart) if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart)
Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart; Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
if (CcIsFileCached(FileObject)) { if (CcIsFileCached(FileObject)) {
CcSetFileSizes(FileObject, CcSetFileSizes(FileObject,
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
} }
} }
ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE|FCB_ALLOC_IN_WRITE|FCB_ALLOC_IN_SETINFO); ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE|FCB_ALLOC_IN_WRITE|FCB_ALLOC_IN_SETINFO);
ExReleaseResourceLite(&Fcb->PagingIoResource); ExReleaseResourceLite(&Fcb->PagingIoResource);
FcbPagingIoResourceAcquired = FALSE; FcbPagingIoResourceAcquired = FALSE;
} }
} }
} }
IoRemoveShareAccess(FileObject, &Fcb->ShareAccess); IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
if (!IsDirectory(Fcb)) { if (!IsDirectory(Fcb)) {
if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) && if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
(Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) && (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) &&
(Fcb->SectionObject.DataSectionObject != NULL)) { (Fcb->SectionObject.DataSectionObject != NULL)) {
if (!IsVcbReadOnly(Vcb)) { if (!IsVcbReadOnly(Vcb)) {
CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL); CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
} }
/* purge cache if all remaining openings are non-cached */ /* purge cache if all remaining openings are non-cached */
if (Fcb->NonCachedOpenCount > 0 || if (Fcb->NonCachedOpenCount > 0 ||
IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) { if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
ExReleaseResourceLite(&(Fcb->PagingIoResource)); ExReleaseResourceLite(&(Fcb->PagingIoResource));
} }
/* CcPurge could generate recursive IRP_MJ_CLOSE request */ /* CcPurge could generate recursive IRP_MJ_CLOSE request */
CcPurgeCacheSection( &Fcb->SectionObject, CcPurgeCacheSection( &Fcb->SectionObject,
NULL, NULL,
0, 0,
FALSE ); FALSE );
} }
} }
CcUninitializeCacheMap(FileObject, NULL, NULL); CcUninitializeCacheMap(FileObject, NULL, NULL);
} }
if (SymLinkDelete || if (SymLinkDelete ||
(IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) && (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) &&
Fcb->OpenHandleCount == 0) ) { Fcb->OpenHandleCount == 0) ) {
// //
// Ext2DeleteFile will acquire these lock inside // Ext2DeleteFile will acquire these lock inside
// //
if (FcbResourceAcquired) { if (FcbResourceAcquired) {
ExReleaseResourceLite(&Fcb->MainResource); ExReleaseResourceLite(&Fcb->MainResource);
FcbResourceAcquired = FALSE; FcbResourceAcquired = FALSE;
} }
// //
// this file is to be deleted ... // this file is to be deleted ...
// //
if (Ccb->SymLink) { if (Ccb->SymLink) {
Mcb = Ccb->SymLink; Mcb = Ccb->SymLink;
FileObject->DeletePending = FALSE; FileObject->DeletePending = FALSE;
} }
Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb); Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
if (NT_SUCCESS(Status)) { if (NT_SUCCESS(Status)) {
if (IsMcbDirectory(Mcb)) { if (IsMcbDirectory(Mcb)) {
Ext2NotifyReportChange( IrpContext, Vcb, Mcb, Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
FILE_NOTIFY_CHANGE_DIR_NAME, FILE_NOTIFY_CHANGE_DIR_NAME,
FILE_ACTION_REMOVED ); FILE_ACTION_REMOVED );
} else { } else {
Ext2NotifyReportChange( IrpContext, Vcb, Mcb, Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
FILE_NOTIFY_CHANGE_FILE_NAME, FILE_NOTIFY_CHANGE_FILE_NAME,
FILE_ACTION_REMOVED ); FILE_ACTION_REMOVED );
} }
} }
// //
// re-acquire the main resource lock // re-acquire the main resource lock
// //
FcbResourceAcquired = FcbResourceAcquired =
ExAcquireResourceExclusiveLite( ExAcquireResourceExclusiveLite(
&Fcb->MainResource, &Fcb->MainResource,
TRUE TRUE
); );
if (!SymLinkDelete) { if (!SymLinkDelete) {
SetFlag(FileObject->Flags, FO_FILE_MODIFIED); SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
if (CcIsFileCached(FileObject)) { if (CcIsFileCached(FileObject)) {
CcSetFileSizes(FileObject, CcSetFileSizes(FileObject,
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
} }
} }
} }
DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n", DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n",
Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName)); Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName));
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
if (FileObject) { if (FileObject) {
SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE); SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
} }
} __finally { } __finally {
if (FcbPagingIoResourceAcquired) { if (FcbPagingIoResourceAcquired) {
ExReleaseResourceLite(&Fcb->PagingIoResource); ExReleaseResourceLite(&Fcb->PagingIoResource);
} }
if (FcbResourceAcquired) { if (FcbResourceAcquired) {
ExReleaseResourceLite(&Fcb->MainResource); ExReleaseResourceLite(&Fcb->MainResource);
} }
if (VcbResourceAcquired) { if (VcbResourceAcquired) {
ExReleaseResourceLite(&Vcb->MainResource); ExReleaseResourceLite(&Vcb->MainResource);
} }
if (!IrpContext->ExceptionInProgress) { if (!IrpContext->ExceptionInProgress) {
if (Status == STATUS_PENDING) { if (Status == STATUS_PENDING) {
Ext2QueueRequest(IrpContext); Ext2QueueRequest(IrpContext);
} else { } else {
IrpContext->Irp->IoStatus.Status = Status; IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteIrpContext(IrpContext, Status); Ext2CompleteIrpContext(IrpContext, Status);
} }
} }
} }
return Status; return Status;
} }

View File

@@ -1,247 +1,247 @@
/* /*
* COPYRIGHT: See COPYRIGHT.TXT * COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: close.c * FILE: close.c
* PROGRAMMER: Matt Wu <mattwu@163.com> * PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com * HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "ext2fs.h" #include "ext2fs.h"
/* GLOBALS ***************************************************************/ /* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global; extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/ /* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2QueueCloseRequest) #pragma alloc_text(PAGE, Ext2QueueCloseRequest)
#pragma alloc_text(PAGE, Ext2DeQueueCloseRequest) #pragma alloc_text(PAGE, Ext2DeQueueCloseRequest)
#endif #endif
NTSTATUS NTSTATUS
Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext) Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
{ {
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PEXT2_VCB Vcb = NULL; PEXT2_VCB Vcb = NULL;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
PEXT2_FCB Fcb = NULL; PEXT2_FCB Fcb = NULL;
PEXT2_CCB Ccb = NULL; PEXT2_CCB Ccb = NULL;
BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN VcbResourceAcquired = FALSE;
BOOLEAN FcbResourceAcquired = FALSE; BOOLEAN FcbResourceAcquired = FALSE;
BOOLEAN FcbDerefDeferred = FALSE; BOOLEAN FcbDerefDeferred = FALSE;
__try { __try {
ASSERT(IrpContext != NULL); ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject; DeviceObject = IrpContext->DeviceObject;
if (IsExt2FsDevice(DeviceObject)) { if (IsExt2FsDevice(DeviceObject)) {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
Vcb = NULL; Vcb = NULL;
__leave; __leave;
} }
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL); ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) && ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB))); (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) { if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
FileObject = NULL; FileObject = NULL;
Fcb = IrpContext->Fcb; Fcb = IrpContext->Fcb;
Ccb = IrpContext->Ccb; Ccb = IrpContext->Ccb;
} else { } else {
FileObject = IrpContext->FileObject; FileObject = IrpContext->FileObject;
Fcb = (PEXT2_FCB) FileObject->FsContext; Fcb = (PEXT2_FCB) FileObject->FsContext;
if (!Fcb) { if (!Fcb) {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
__leave; __leave;
} }
ASSERT(Fcb != NULL); ASSERT(Fcb != NULL);
Ccb = (PEXT2_CCB) FileObject->FsContext2; Ccb = (PEXT2_CCB) FileObject->FsContext2;
} }
DEBUG(DL_INF, ( "Ext2Close: (VCB) Vcb = %p ReferCount = %d\n", DEBUG(DL_INF, ( "Ext2Close: (VCB) Vcb = %p ReferCount = %d\n",
Vcb, Vcb->ReferenceCount)); Vcb, Vcb->ReferenceCount));
/* /*
* WARNING: don't release Vcb resource lock here. * WARNING: don't release Vcb resource lock here.
* *
* CcPurgeCacheSection will lead a recursive irp: IRP_MJ_CLOSE * CcPurgeCacheSection will lead a recursive irp: IRP_MJ_CLOSE
* which would cause revrese order of lock acquirision: * which would cause revrese order of lock acquirision:
* 1) IRP_MJ_CLEANUP: a) Vcb lock -> b) Fcb lock * 1) IRP_MJ_CLEANUP: a) Vcb lock -> b) Fcb lock
* 2) IRP_MJ_CLOSE: c) Vcb lock -> d) Fcb lock * 2) IRP_MJ_CLOSE: c) Vcb lock -> d) Fcb lock
*/ */
if (Fcb->Identifier.Type == EXT2VCB) { if (Fcb->Identifier.Type == EXT2VCB) {
if (!ExAcquireResourceExclusiveLite( if (!ExAcquireResourceExclusiveLite(
&Vcb->MainResource, &Vcb->MainResource,
TRUE )) { TRUE )) {
DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n", DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n",
Vcb->OpenHandleCount, Vcb->ReferenceCount)); Vcb->OpenHandleCount, Vcb->ReferenceCount));
Status = STATUS_PENDING; Status = STATUS_PENDING;
__leave; __leave;
} }
VcbResourceAcquired = TRUE; VcbResourceAcquired = TRUE;
if (Ccb) { if (Ccb) {
Ext2DerefXcb(&Vcb->ReferenceCount); Ext2DerefXcb(&Vcb->ReferenceCount);
Ext2FreeCcb(Vcb, Ccb); Ext2FreeCcb(Vcb, Ccb);
if (FileObject) { if (FileObject) {
FileObject->FsContext2 = Ccb = NULL; FileObject->FsContext2 = Ccb = NULL;
} }
} }
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
__leave; __leave;
} }
if ( Fcb->Identifier.Type != EXT2FCB || if ( Fcb->Identifier.Type != EXT2FCB ||
Fcb->Identifier.Size != sizeof(EXT2_FCB)) { Fcb->Identifier.Size != sizeof(EXT2_FCB)) {
__leave; __leave;
} }
if (!ExAcquireResourceExclusiveLite( if (!ExAcquireResourceExclusiveLite(
&Fcb->MainResource, &Fcb->MainResource,
TRUE )) { TRUE )) {
Status = STATUS_PENDING; Status = STATUS_PENDING;
__leave; __leave;
} }
FcbResourceAcquired = TRUE; FcbResourceAcquired = TRUE;
Fcb->Header.IsFastIoPossible = FastIoIsNotPossible; Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
if (Ccb == NULL || if (Ccb == NULL ||
Ccb->Identifier.Type != EXT2CCB || Ccb->Identifier.Type != EXT2CCB ||
Ccb->Identifier.Size != sizeof(EXT2_CCB)) { Ccb->Identifier.Size != sizeof(EXT2_CCB)) {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
__leave; __leave;
} }
DEBUG(DL_INF, ( "Ext2Close: Fcb = %p OpenHandleCount= %u ReferenceCount=%u NonCachedCount=%u %wZ\n", DEBUG(DL_INF, ( "Ext2Close: Fcb = %p OpenHandleCount= %u ReferenceCount=%u NonCachedCount=%u %wZ\n",
Fcb, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName )); Fcb, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName ));
Ext2FreeCcb(Vcb, Ccb); Ext2FreeCcb(Vcb, Ccb);
if (FileObject) { if (FileObject) {
FileObject->FsContext2 = Ccb = NULL; FileObject->FsContext2 = Ccb = NULL;
} }
/* only deref fcb, Ext2ReleaseFcb might lead deadlock */ /* only deref fcb, Ext2ReleaseFcb might lead deadlock */
FcbDerefDeferred = TRUE; FcbDerefDeferred = TRUE;
if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) || if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) ||
NULL == Fcb->Mcb || NULL == Fcb->Mcb ||
IsFileDeleted(Fcb->Mcb)) { IsFileDeleted(Fcb->Mcb)) {
Fcb->TsDrop.QuadPart = 0; Fcb->TsDrop.QuadPart = 0;
} else { } else {
KeQuerySystemTime(&Fcb->TsDrop); KeQuerySystemTime(&Fcb->TsDrop);
} }
Ext2DerefXcb(&Vcb->ReferenceCount); Ext2DerefXcb(&Vcb->ReferenceCount);
if (FileObject) { if (FileObject) {
FileObject->FsContext = NULL; FileObject->FsContext = NULL;
} }
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
} __finally { } __finally {
if (FcbResourceAcquired) { if (FcbResourceAcquired) {
ExReleaseResourceLite(&Fcb->MainResource); ExReleaseResourceLite(&Fcb->MainResource);
} }
if (VcbResourceAcquired) { if (VcbResourceAcquired) {
ExReleaseResourceLite(&Vcb->MainResource); ExReleaseResourceLite(&Vcb->MainResource);
} }
if (!IrpContext->ExceptionInProgress) { if (!IrpContext->ExceptionInProgress) {
if (Status == STATUS_PENDING) { if (Status == STATUS_PENDING) {
Ext2QueueCloseRequest(IrpContext); Ext2QueueCloseRequest(IrpContext);
} else { } else {
Ext2CompleteIrpContext(IrpContext, Status); Ext2CompleteIrpContext(IrpContext, Status);
} }
} }
if (FcbDerefDeferred) if (FcbDerefDeferred)
Ext2DerefXcb(&Fcb->ReferenceCount); Ext2DerefXcb(&Fcb->ReferenceCount);
} }
return Status; return Status;
} }
VOID VOID
Ext2QueueCloseRequest (IN PEXT2_IRP_CONTEXT IrpContext) Ext2QueueCloseRequest (IN PEXT2_IRP_CONTEXT IrpContext)
{ {
ASSERT(IrpContext); ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) { if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY)) { if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY)) {
Ext2Sleep(500); /* 0.5 sec*/ Ext2Sleep(500); /* 0.5 sec*/
} else { } else {
Ext2Sleep(50); /* 0.05 sec*/ Ext2Sleep(50); /* 0.05 sec*/
} }
} else { } else {
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE); SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE);
IrpContext->Fcb = (PEXT2_FCB) IrpContext->FileObject->FsContext; IrpContext->Fcb = (PEXT2_FCB) IrpContext->FileObject->FsContext;
IrpContext->Ccb = (PEXT2_CCB) IrpContext->FileObject->FsContext2; IrpContext->Ccb = (PEXT2_CCB) IrpContext->FileObject->FsContext2;
} }
ExInitializeWorkItem( ExInitializeWorkItem(
&IrpContext->WorkQueueItem, &IrpContext->WorkQueueItem,
Ext2DeQueueCloseRequest, Ext2DeQueueCloseRequest,
IrpContext); IrpContext);
ExQueueWorkItem(&IrpContext->WorkQueueItem, DelayedWorkQueue); ExQueueWorkItem(&IrpContext->WorkQueueItem, DelayedWorkQueue);
} }
VOID VOID
Ext2DeQueueCloseRequest (IN PVOID Context) Ext2DeQueueCloseRequest (IN PVOID Context)
{ {
PEXT2_IRP_CONTEXT IrpContext; PEXT2_IRP_CONTEXT IrpContext;
IrpContext = (PEXT2_IRP_CONTEXT) Context; IrpContext = (PEXT2_IRP_CONTEXT) Context;
ASSERT(IrpContext); ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
__try { __try {
__try { __try {
FsRtlEnterFileSystem(); FsRtlEnterFileSystem();
Ext2Close(IrpContext); Ext2Close(IrpContext);
} __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) { } __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) {
Ext2ExceptionHandler(IrpContext); Ext2ExceptionHandler(IrpContext);
} }
} __finally { } __finally {
FsRtlExitFileSystem(); FsRtlExitFileSystem();
} }
} }

View File

@@ -1,138 +1,138 @@
/* /*
* COPYRIGHT: See COPYRIGHT.TXT * COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: cmcb.c * FILE: cmcb.c
* PROGRAMMER: Matt Wu <mattwu@163.com> * PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com * HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "ext2fs.h" #include "ext2fs.h"
/* GLOBALS ***************************************************************/ /* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global; extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/ /* DEFINITIONS *************************************************************/
#define CMCB_DEBUG_LEVEL DL_NVR #define CMCB_DEBUG_LEVEL DL_NVR
BOOLEAN BOOLEAN
Ext2AcquireForLazyWrite ( Ext2AcquireForLazyWrite (
IN PVOID Context, IN PVOID Context,
IN BOOLEAN Wait) IN BOOLEAN Wait)
{ {
// //
// On a readonly filesystem this function still has to exist but it // On a readonly filesystem this function still has to exist but it
// doesn't need to do anything. // doesn't need to do anything.
PEXT2_FCB Fcb; PEXT2_FCB Fcb;
Fcb = (PEXT2_FCB) Context; Fcb = (PEXT2_FCB) Context;
ASSERT(Fcb != NULL); ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == EXT2FCB) && ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB))); (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
#if EXT2_DEBUG #if EXT2_DEBUG
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireForLazyWrite: %s %s Fcb=%p\n", DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireForLazyWrite: %s %s Fcb=%p\n",
Ext2GetCurrentProcessName(), "ACQUIRE_FOR_LAZY_WRITE", Fcb)); Ext2GetCurrentProcessName(), "ACQUIRE_FOR_LAZY_WRITE", Fcb));
#endif #endif
if (!ExAcquireResourceExclusiveLite(Fcb->Header.Resource, Wait)) { if (!ExAcquireResourceExclusiveLite(Fcb->Header.Resource, Wait)) {
return FALSE; return FALSE;
} }
ASSERT(Fcb->LazyWriterThread == NULL); ASSERT(Fcb->LazyWriterThread == NULL);
Fcb->LazyWriterThread = PsGetCurrentThread(); Fcb->LazyWriterThread = PsGetCurrentThread();
ASSERT(IoGetTopLevelIrp() == NULL); ASSERT(IoGetTopLevelIrp() == NULL);
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
return TRUE; return TRUE;
} }
VOID VOID
Ext2ReleaseFromLazyWrite (IN PVOID Context) Ext2ReleaseFromLazyWrite (IN PVOID Context)
{ {
// //
// On a readonly filesystem this function still has to exist but it // On a readonly filesystem this function still has to exist but it
// doesn't need to do anything. // doesn't need to do anything.
PEXT2_FCB Fcb = (PEXT2_FCB) Context; PEXT2_FCB Fcb = (PEXT2_FCB) Context;
ASSERT(Fcb != NULL); ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == EXT2FCB) && ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB))); (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
#if EXT2_DEBUG #if EXT2_DEBUG
DEBUG(CMCB_DEBUG_LEVEL, ( "Ext2ReleaseFromLazyWrite: %s %s Fcb=%p\n", DEBUG(CMCB_DEBUG_LEVEL, ( "Ext2ReleaseFromLazyWrite: %s %s Fcb=%p\n",
Ext2GetCurrentProcessName(), "RELEASE_FROM_LAZY_WRITE", Fcb)); Ext2GetCurrentProcessName(), "RELEASE_FROM_LAZY_WRITE", Fcb));
#endif #endif
ASSERT(Fcb->LazyWriterThread == PsGetCurrentThread()); ASSERT(Fcb->LazyWriterThread == PsGetCurrentThread());
Fcb->LazyWriterThread = NULL; Fcb->LazyWriterThread = NULL;
ExReleaseResourceLite(Fcb->Header.Resource); ExReleaseResourceLite(Fcb->Header.Resource);
ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
IoSetTopLevelIrp( NULL ); IoSetTopLevelIrp( NULL );
} }
BOOLEAN BOOLEAN
Ext2AcquireForReadAhead (IN PVOID Context, Ext2AcquireForReadAhead (IN PVOID Context,
IN BOOLEAN Wait) IN BOOLEAN Wait)
{ {
PEXT2_FCB Fcb = (PEXT2_FCB) Context; PEXT2_FCB Fcb = (PEXT2_FCB) Context;
ASSERT(Fcb != NULL); ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == EXT2FCB) && ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB))); (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireForReadAhead: i=%xh Fcb=%p\n", DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireForReadAhead: i=%xh Fcb=%p\n",
Fcb->Mcb->Inode.i_ino, Fcb)); Fcb->Mcb->Inode.i_ino, Fcb));
if (!ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait)) if (!ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait))
return FALSE; return FALSE;
ASSERT(IoGetTopLevelIrp() == NULL); ASSERT(IoGetTopLevelIrp() == NULL);
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
return TRUE; return TRUE;
} }
VOID VOID
Ext2ReleaseFromReadAhead (IN PVOID Context) Ext2ReleaseFromReadAhead (IN PVOID Context)
{ {
PEXT2_FCB Fcb = (PEXT2_FCB) Context; PEXT2_FCB Fcb = (PEXT2_FCB) Context;
ASSERT(Fcb != NULL); ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == EXT2FCB) && ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB))); (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2ReleaseFromReadAhead: i=%xh Fcb=%p\n", DEBUG(CMCB_DEBUG_LEVEL, ("Ext2ReleaseFromReadAhead: i=%xh Fcb=%p\n",
Fcb->Mcb->Inode.i_ino, Fcb)); Fcb->Mcb->Inode.i_ino, Fcb));
IoSetTopLevelIrp(NULL); IoSetTopLevelIrp(NULL);
ExReleaseResourceLite(Fcb->Header.Resource); ExReleaseResourceLite(Fcb->Header.Resource);
} }
BOOLEAN BOOLEAN
Ext2NoOpAcquire ( Ext2NoOpAcquire (
IN PVOID Fcb, IN PVOID Fcb,
IN BOOLEAN Wait IN BOOLEAN Wait
) )
{ {
ASSERT(IoGetTopLevelIrp() == NULL); ASSERT(IoGetTopLevelIrp() == NULL);
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
return TRUE; return TRUE;
} }
VOID VOID
Ext2NoOpRelease ( Ext2NoOpRelease (
IN PVOID Fcb IN PVOID Fcb
) )
{ {
ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP); ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
IoSetTopLevelIrp( NULL ); IoSetTopLevelIrp( NULL );
return; return;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,354 +1,354 @@
/* /*
* COPYRIGHT: See COPYRIGHT.TXT * COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: dispatch.c * FILE: dispatch.c
* PROGRAMMER: Matt Wu <mattwu@163.com> * PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com * HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "ext2fs.h" #include "ext2fs.h"
/* GLOBALS ***************************************************************/ /* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global; extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/ /* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2QueueRequest) #pragma alloc_text(PAGE, Ext2QueueRequest)
#pragma alloc_text(PAGE, Ext2DeQueueRequest) #pragma alloc_text(PAGE, Ext2DeQueueRequest)
#endif #endif
/* /*
* Ext2OplockComplete * Ext2OplockComplete
* *
* callback routine of FsRtlCheckOplock when an oplock break has * callback routine of FsRtlCheckOplock when an oplock break has
* completed, allowing an Irp to resume execution. * completed, allowing an Irp to resume execution.
* *
* Arguments: * Arguments:
* *
* Context: the IrpContext to be queued * Context: the IrpContext to be queued
* Irp: the I/O request packet * Irp: the I/O request packet
* *
* Return Value: * Return Value:
* N/A * N/A
*/ */
VOID VOID
Ext2OplockComplete ( Ext2OplockComplete (
IN PVOID Context, IN PVOID Context,
IN PIRP Irp IN PIRP Irp
) )
{ {
// //
// Check on the return value in the Irp. // Check on the return value in the Irp.
// //
if (Irp->IoStatus.Status == STATUS_SUCCESS) { if (Irp->IoStatus.Status == STATUS_SUCCESS) {
// //
// queue the Irp context in the workqueue. // queue the Irp context in the workqueue.
// //
Ext2QueueRequest((PEXT2_IRP_CONTEXT)Context); Ext2QueueRequest((PEXT2_IRP_CONTEXT)Context);
} else { } else {
// //
// complete the request in case of failure // complete the request in case of failure
// //
Ext2CompleteIrpContext( (PEXT2_IRP_CONTEXT) Context, Ext2CompleteIrpContext( (PEXT2_IRP_CONTEXT) Context,
Irp->IoStatus.Status ); Irp->IoStatus.Status );
} }
return; return;
} }
/* /*
* Ext2LockIrp * Ext2LockIrp
* *
* performs buffer locking if we need pend the process of the Irp * performs buffer locking if we need pend the process of the Irp
* *
* Arguments: * Arguments:
* Context: the irp context * Context: the irp context
* Irp: the I/O request packet. * Irp: the I/O request packet.
* *
* Return Value: * Return Value:
* N/A * N/A
*/ */
VOID VOID
Ext2LockIrp ( Ext2LockIrp (
IN PVOID Context, IN PVOID Context,
IN PIRP Irp IN PIRP Irp
) )
{ {
PIO_STACK_LOCATION IrpSp; PIO_STACK_LOCATION IrpSp;
PEXT2_IRP_CONTEXT IrpContext; PEXT2_IRP_CONTEXT IrpContext;
if (Irp == NULL) { if (Irp == NULL) {
return; return;
} }
IrpSp = IoGetCurrentIrpStackLocation(Irp); IrpSp = IoGetCurrentIrpStackLocation(Irp);
IrpContext = (PEXT2_IRP_CONTEXT) Context; IrpContext = (PEXT2_IRP_CONTEXT) Context;
if ( IrpContext->MajorFunction == IRP_MJ_READ || if ( IrpContext->MajorFunction == IRP_MJ_READ ||
IrpContext->MajorFunction == IRP_MJ_WRITE ) { IrpContext->MajorFunction == IRP_MJ_WRITE ) {
// //
// lock the user's buffer to MDL, if the I/O is bufferred // lock the user's buffer to MDL, if the I/O is bufferred
// //
if (!IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { if (!IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
Ext2LockUserBuffer( Irp, IrpSp->Parameters.Write.Length, Ext2LockUserBuffer( Irp, IrpSp->Parameters.Write.Length,
(IrpContext->MajorFunction == IRP_MJ_READ) ? (IrpContext->MajorFunction == IRP_MJ_READ) ?
IoWriteAccess : IoReadAccess ); IoWriteAccess : IoReadAccess );
} }
} else if (IrpContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL } else if (IrpContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL
&& IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) { && IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) {
ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryDirectory.Length; ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryDirectory.Length;
Ext2LockUserBuffer(Irp, Length, IoWriteAccess); Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
} else if (IrpContext->MajorFunction == IRP_MJ_QUERY_EA) { } else if (IrpContext->MajorFunction == IRP_MJ_QUERY_EA) {
ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryEa.Length; ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryEa.Length;
Ext2LockUserBuffer(Irp, Length, IoWriteAccess); Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
} else if (IrpContext->MajorFunction == IRP_MJ_SET_EA) { } else if (IrpContext->MajorFunction == IRP_MJ_SET_EA) {
ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.SetEa.Length; ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.SetEa.Length;
Ext2LockUserBuffer(Irp, Length, IoReadAccess); Ext2LockUserBuffer(Irp, Length, IoReadAccess);
} else if ( (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) && } else if ( (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
(IrpContext->MinorFunction == IRP_MN_USER_FS_REQUEST) ) { (IrpContext->MinorFunction == IRP_MN_USER_FS_REQUEST) ) {
PEXTENDED_IO_STACK_LOCATION EIrpSp = (PEXTENDED_IO_STACK_LOCATION)IrpSp; PEXTENDED_IO_STACK_LOCATION EIrpSp = (PEXTENDED_IO_STACK_LOCATION)IrpSp;
if ( (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_VOLUME_BITMAP) || if ( (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_VOLUME_BITMAP) ||
(EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTERS) || (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTERS) ||
(EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTER_BASE) ) { (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTER_BASE) ) {
ULONG Length = EIrpSp->Parameters.FileSystemControl.OutputBufferLength; ULONG Length = EIrpSp->Parameters.FileSystemControl.OutputBufferLength;
Ext2LockUserBuffer(Irp, Length, IoWriteAccess); Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
} }
} }
// Mark the request as pending status // Mark the request as pending status
IoMarkIrpPending( Irp ); IoMarkIrpPending( Irp );
return; return;
} }
NTSTATUS NTSTATUS
Ext2QueueRequest (IN PEXT2_IRP_CONTEXT IrpContext) Ext2QueueRequest (IN PEXT2_IRP_CONTEXT IrpContext)
{ {
ASSERT(IrpContext); ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
/* set the flags of "can wait" and "queued" */ /* set the flags of "can wait" and "queued" */
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
/* make sure the buffer is kept valid in system context */ /* make sure the buffer is kept valid in system context */
Ext2LockIrp(IrpContext, IrpContext->Irp); Ext2LockIrp(IrpContext, IrpContext->Irp);
/* initialize workite*/ /* initialize workite*/
ExInitializeWorkItem( ExInitializeWorkItem(
&IrpContext->WorkQueueItem, &IrpContext->WorkQueueItem,
Ext2DeQueueRequest, Ext2DeQueueRequest,
IrpContext ); IrpContext );
/* dispatch it */ /* dispatch it */
ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue); ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
return STATUS_PENDING; return STATUS_PENDING;
} }
VOID VOID
Ext2DeQueueRequest (IN PVOID Context) Ext2DeQueueRequest (IN PVOID Context)
{ {
PEXT2_IRP_CONTEXT IrpContext; PEXT2_IRP_CONTEXT IrpContext;
IrpContext = (PEXT2_IRP_CONTEXT) Context; IrpContext = (PEXT2_IRP_CONTEXT) Context;
ASSERT(IrpContext); ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
__try { __try {
__try { __try {
FsRtlEnterFileSystem(); FsRtlEnterFileSystem();
if (!IrpContext->IsTopLevel) { if (!IrpContext->IsTopLevel) {
IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP); IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP);
} }
Ext2DispatchRequest(IrpContext); Ext2DispatchRequest(IrpContext);
} __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) { } __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) {
Ext2ExceptionHandler(IrpContext); Ext2ExceptionHandler(IrpContext);
} }
} __finally { } __finally {
IoSetTopLevelIrp(NULL); IoSetTopLevelIrp(NULL);
FsRtlExitFileSystem(); FsRtlExitFileSystem();
} }
} }
NTSTATUS NTSTATUS
Ext2DispatchRequest (IN PEXT2_IRP_CONTEXT IrpContext) Ext2DispatchRequest (IN PEXT2_IRP_CONTEXT IrpContext)
{ {
ASSERT(IrpContext); ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
switch (IrpContext->MajorFunction) { switch (IrpContext->MajorFunction) {
case IRP_MJ_CREATE: case IRP_MJ_CREATE:
return Ext2Create(IrpContext); return Ext2Create(IrpContext);
case IRP_MJ_CLOSE: case IRP_MJ_CLOSE:
return Ext2Close(IrpContext); return Ext2Close(IrpContext);
case IRP_MJ_READ: case IRP_MJ_READ:
return Ext2Read(IrpContext); return Ext2Read(IrpContext);
case IRP_MJ_WRITE: case IRP_MJ_WRITE:
return Ext2Write(IrpContext); return Ext2Write(IrpContext);
case IRP_MJ_FLUSH_BUFFERS: case IRP_MJ_FLUSH_BUFFERS:
return Ext2Flush(IrpContext); return Ext2Flush(IrpContext);
case IRP_MJ_QUERY_INFORMATION: case IRP_MJ_QUERY_INFORMATION:
return Ext2QueryFileInformation(IrpContext); return Ext2QueryFileInformation(IrpContext);
case IRP_MJ_SET_INFORMATION: case IRP_MJ_SET_INFORMATION:
return Ext2SetFileInformation(IrpContext); return Ext2SetFileInformation(IrpContext);
case IRP_MJ_QUERY_VOLUME_INFORMATION: case IRP_MJ_QUERY_VOLUME_INFORMATION:
return Ext2QueryVolumeInformation(IrpContext); return Ext2QueryVolumeInformation(IrpContext);
case IRP_MJ_SET_VOLUME_INFORMATION: case IRP_MJ_SET_VOLUME_INFORMATION:
return Ext2SetVolumeInformation(IrpContext); return Ext2SetVolumeInformation(IrpContext);
case IRP_MJ_DIRECTORY_CONTROL: case IRP_MJ_DIRECTORY_CONTROL:
return Ext2DirectoryControl(IrpContext); return Ext2DirectoryControl(IrpContext);
case IRP_MJ_FILE_SYSTEM_CONTROL: case IRP_MJ_FILE_SYSTEM_CONTROL:
return Ext2FileSystemControl(IrpContext); return Ext2FileSystemControl(IrpContext);
case IRP_MJ_DEVICE_CONTROL: case IRP_MJ_DEVICE_CONTROL:
return Ext2DeviceControl(IrpContext); return Ext2DeviceControl(IrpContext);
case IRP_MJ_LOCK_CONTROL: case IRP_MJ_LOCK_CONTROL:
return Ext2LockControl(IrpContext); return Ext2LockControl(IrpContext);
case IRP_MJ_CLEANUP: case IRP_MJ_CLEANUP:
return Ext2Cleanup(IrpContext); return Ext2Cleanup(IrpContext);
case IRP_MJ_SHUTDOWN: case IRP_MJ_SHUTDOWN:
return Ext2ShutDown(IrpContext); return Ext2ShutDown(IrpContext);
case IRP_MJ_QUERY_EA: case IRP_MJ_QUERY_EA:
return Ext2QueryEa(IrpContext); return Ext2QueryEa(IrpContext);
case IRP_MJ_SET_EA: case IRP_MJ_SET_EA:
return Ext2SetEa(IrpContext); return Ext2SetEa(IrpContext);
#if (_WIN32_WINNT >= 0x0500) #if (_WIN32_WINNT >= 0x0500)
case IRP_MJ_PNP: case IRP_MJ_PNP:
return Ext2Pnp(IrpContext); return Ext2Pnp(IrpContext);
#endif //(_WIN32_WINNT >= 0x0500) #endif //(_WIN32_WINNT >= 0x0500)
default: default:
DEBUG(DL_ERR, ( "Ext2DispatchRequest: Unexpected major function: %xh\n", DEBUG(DL_ERR, ( "Ext2DispatchRequest: Unexpected major function: %xh\n",
IrpContext->MajorFunction)); IrpContext->MajorFunction));
Ext2CompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR); Ext2CompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR);
return STATUS_DRIVER_INTERNAL_ERROR; return STATUS_DRIVER_INTERNAL_ERROR;
} }
} }
NTSTATUS NTSTATUS
Ext2BuildRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp) Ext2BuildRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp)
{ {
BOOLEAN AtIrqlPassiveLevel = FALSE; BOOLEAN AtIrqlPassiveLevel = FALSE;
BOOLEAN IsTopLevelIrp = FALSE; BOOLEAN IsTopLevelIrp = FALSE;
PEXT2_IRP_CONTEXT IrpContext = NULL; PEXT2_IRP_CONTEXT IrpContext = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL; NTSTATUS Status = STATUS_UNSUCCESSFUL;
__try { __try {
__try { __try {
#if EXT2_DEBUG #if EXT2_DEBUG
Ext2DbgPrintCall(DeviceObject, Irp); Ext2DbgPrintCall(DeviceObject, Irp);
#endif #endif
AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL); AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL);
if (AtIrqlPassiveLevel) { if (AtIrqlPassiveLevel) {
FsRtlEnterFileSystem(); FsRtlEnterFileSystem();
} }
if (!IoGetTopLevelIrp()) { if (!IoGetTopLevelIrp()) {
IsTopLevelIrp = TRUE; IsTopLevelIrp = TRUE;
IoSetTopLevelIrp(Irp); IoSetTopLevelIrp(Irp);
} }
IrpContext = Ext2AllocateIrpContext(DeviceObject, Irp); IrpContext = Ext2AllocateIrpContext(DeviceObject, Irp);
if (!IrpContext) { if (!IrpContext) {
Status = STATUS_INSUFFICIENT_RESOURCES; Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
Ext2CompleteRequest(Irp, TRUE, IO_NO_INCREMENT); Ext2CompleteRequest(Irp, TRUE, IO_NO_INCREMENT);
} else { } else {
if ((IrpContext->MajorFunction == IRP_MJ_CREATE) && if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
!AtIrqlPassiveLevel) { !AtIrqlPassiveLevel) {
DbgBreak(); DbgBreak();
} }
Status = Ext2DispatchRequest(IrpContext); Status = Ext2DispatchRequest(IrpContext);
} }
} __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) { } __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) {
Status = Ext2ExceptionHandler(IrpContext); Status = Ext2ExceptionHandler(IrpContext);
} }
} __finally { } __finally {
if (IsTopLevelIrp) { if (IsTopLevelIrp) {
IoSetTopLevelIrp(NULL); IoSetTopLevelIrp(NULL);
} }
if (AtIrqlPassiveLevel) { if (AtIrqlPassiveLevel) {
FsRtlExitFileSystem(); FsRtlExitFileSystem();
} }
} }
return Status; return Status;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,273 +1,273 @@
/* /*
* COPYRIGHT: See COPYRIGHT.TXT * COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: except.c * FILE: except.c
* PROGRAMMER: Matt Wu <mattwu@163.com> * PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com * HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "ext2fs.h" #include "ext2fs.h"
/* GLOBALS ***************************************************************/ /* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global; extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/ /* DEFINITIONS *************************************************************/
NTSTATUS NTSTATUS
Ext2ExceptionFilter ( Ext2ExceptionFilter (
IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXCEPTION_POINTERS ExceptionPointer IN PEXCEPTION_POINTERS ExceptionPointer
) )
{ {
NTSTATUS Status = EXCEPTION_EXECUTE_HANDLER; NTSTATUS Status = EXCEPTION_EXECUTE_HANDLER;
NTSTATUS ExceptionCode; NTSTATUS ExceptionCode;
PEXCEPTION_RECORD ExceptRecord; PEXCEPTION_RECORD ExceptRecord;
ExceptRecord = ExceptionPointer->ExceptionRecord; ExceptRecord = ExceptionPointer->ExceptionRecord;
ExceptionCode = ExceptRecord->ExceptionCode; ExceptionCode = ExceptRecord->ExceptionCode;
DbgPrint("-------------------------------------------------------------\n"); DbgPrint("-------------------------------------------------------------\n");
DbgPrint("Exception happends in Ext2Fsd (code %xh):\n", ExceptionCode); DbgPrint("Exception happends in Ext2Fsd (code %xh):\n", ExceptionCode);
DbgPrint(".exr %p;.cxr %p;\n", ExceptionPointer->ExceptionRecord, DbgPrint(".exr %p;.cxr %p;\n", ExceptionPointer->ExceptionRecord,
ExceptionPointer->ContextRecord); ExceptionPointer->ContextRecord);
DbgPrint("-------------------------------------------------------------\n"); DbgPrint("-------------------------------------------------------------\n");
DbgBreak(); DbgBreak();
// //
// Check IrpContext is valid or not // Check IrpContext is valid or not
// //
if (IrpContext) { if (IrpContext) {
if ((IrpContext->Identifier.Type != EXT2ICX) || if ((IrpContext->Identifier.Type != EXT2ICX) ||
(IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) { (IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) {
DbgBreak(); DbgBreak();
IrpContext = NULL; IrpContext = NULL;
} else if (IrpContext->DeviceObject) { } else if (IrpContext->DeviceObject) {
PEXT2_VCB Vcb = NULL; PEXT2_VCB Vcb = NULL;
Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension; Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension;
if (NULL == Vcb) { if (NULL == Vcb) {
Status = EXCEPTION_EXECUTE_HANDLER; Status = EXCEPTION_EXECUTE_HANDLER;
} else { } else {
if (Vcb->Identifier.Type == EXT2VCB && !IsMounted(Vcb)) { if (Vcb->Identifier.Type == EXT2VCB && !IsMounted(Vcb)) {
Status = EXCEPTION_EXECUTE_HANDLER; Status = EXCEPTION_EXECUTE_HANDLER;
} }
} }
} }
} else { } else {
if (FsRtlIsNtstatusExpected(ExceptionCode)) { if (FsRtlIsNtstatusExpected(ExceptionCode)) {
return EXCEPTION_EXECUTE_HANDLER; return EXCEPTION_EXECUTE_HANDLER;
} else { } else {
Ext2BugCheck( EXT2_BUGCHK_EXCEPT, (ULONG_PTR)ExceptRecord, Ext2BugCheck( EXT2_BUGCHK_EXCEPT, (ULONG_PTR)ExceptRecord,
(ULONG_PTR)ExceptionPointer->ContextRecord, (ULONG_PTR)ExceptionPointer->ContextRecord,
(ULONG_PTR)ExceptRecord->ExceptionAddress ); (ULONG_PTR)ExceptRecord->ExceptionAddress );
} }
} }
if (IrpContext) { if (IrpContext) {
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
} }
if ( Status == EXCEPTION_EXECUTE_HANDLER || if ( Status == EXCEPTION_EXECUTE_HANDLER ||
FsRtlIsNtstatusExpected(ExceptionCode)) { FsRtlIsNtstatusExpected(ExceptionCode)) {
// //
// If the exception is expected execute our handler // If the exception is expected execute our handler
// //
DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Catching exception %xh\n", DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Catching exception %xh\n",
ExceptionCode)); ExceptionCode));
Status = EXCEPTION_EXECUTE_HANDLER; Status = EXCEPTION_EXECUTE_HANDLER;
if (IrpContext) { if (IrpContext) {
IrpContext->ExceptionInProgress = TRUE; IrpContext->ExceptionInProgress = TRUE;
IrpContext->ExceptionCode = ExceptionCode; IrpContext->ExceptionCode = ExceptionCode;
} }
} else { } else {
// //
// Continue search for an higher level exception handler // Continue search for an higher level exception handler
// //
DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Passing on exception %#x\n", DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Passing on exception %#x\n",
ExceptionCode)); ExceptionCode));
Status = EXCEPTION_CONTINUE_SEARCH; Status = EXCEPTION_CONTINUE_SEARCH;
if (IrpContext) { if (IrpContext) {
Ext2FreeIrpContext(IrpContext); Ext2FreeIrpContext(IrpContext);
} }
} }
return Status; return Status;
} }
NTSTATUS NTSTATUS
Ext2ExceptionHandler (IN PEXT2_IRP_CONTEXT IrpContext) Ext2ExceptionHandler (IN PEXT2_IRP_CONTEXT IrpContext)
{ {
NTSTATUS Status; NTSTATUS Status;
if (IrpContext) { if (IrpContext) {
if ( (IrpContext->Identifier.Type != EXT2ICX) || if ( (IrpContext->Identifier.Type != EXT2ICX) ||
(IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) { (IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) {
DbgBreak(); DbgBreak();
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
Status = IrpContext->ExceptionCode; Status = IrpContext->ExceptionCode;
if (IrpContext->Irp) { if (IrpContext->Irp) {
// //
// Check if this error is a result of user actions // Check if this error is a result of user actions
// //
PEXT2_VCB Vcb = NULL; PEXT2_VCB Vcb = NULL;
PIRP Irp = IrpContext->Irp; PIRP Irp = IrpContext->Irp;
PIO_STACK_LOCATION IrpSp; PIO_STACK_LOCATION IrpSp;
IrpSp = IoGetCurrentIrpStackLocation(Irp); IrpSp = IoGetCurrentIrpStackLocation(Irp);
Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension; Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension;
if (NULL == Vcb) { if (NULL == Vcb) {
Status = STATUS_INVALID_PARAMETER; Status = STATUS_INVALID_PARAMETER;
} else if (Vcb->Identifier.Type != EXT2VCB) { } else if (Vcb->Identifier.Type != EXT2VCB) {
Status = STATUS_INVALID_PARAMETER; Status = STATUS_INVALID_PARAMETER;
} else if (!IsMounted(Vcb)) { } else if (!IsMounted(Vcb)) {
if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) { if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) {
Status = STATUS_NO_SUCH_DEVICE; Status = STATUS_NO_SUCH_DEVICE;
} else { } else {
Status = STATUS_VOLUME_DISMOUNTED; Status = STATUS_VOLUME_DISMOUNTED;
} }
} else { } else {
/* queue it again if our request is at top level */ /* queue it again if our request is at top level */
if (IrpContext->IsTopLevel && if (IrpContext->IsTopLevel &&
((Status == STATUS_CANT_WAIT) || ((Status == STATUS_CANT_WAIT) ||
((Status == STATUS_VERIFY_REQUIRED) && ((Status == STATUS_VERIFY_REQUIRED) &&
(KeGetCurrentIrql() >= APC_LEVEL)))) { (KeGetCurrentIrql() >= APC_LEVEL)))) {
Status = Ext2QueueRequest(IrpContext); Status = Ext2QueueRequest(IrpContext);
} }
} }
if (Status == STATUS_PENDING) { if (Status == STATUS_PENDING) {
goto errorout; goto errorout;
} }
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
if (IoIsErrorUserInduced(Status)) { if (IoIsErrorUserInduced(Status)) {
// //
// Now we will generate a pop-up to user // Now we will generate a pop-up to user
// //
PDEVICE_OBJECT RealDevice; PDEVICE_OBJECT RealDevice;
PVPB Vpb = NULL; PVPB Vpb = NULL;
PETHREAD Thread; PETHREAD Thread;
if (IrpSp->FileObject != NULL) { if (IrpSp->FileObject != NULL) {
Vpb = IrpSp->FileObject->Vpb; Vpb = IrpSp->FileObject->Vpb;
} }
// //
// Get the initial thread // Get the initial thread
// //
Thread = Irp->Tail.Overlay.Thread; Thread = Irp->Tail.Overlay.Thread;
RealDevice = IoGetDeviceToVerify( Thread ); RealDevice = IoGetDeviceToVerify( Thread );
if (RealDevice == NULL) { if (RealDevice == NULL) {
// //
// Get current thread // Get current thread
// //
Thread = PsGetCurrentThread(); Thread = PsGetCurrentThread();
RealDevice = IoGetDeviceToVerify( Thread ); RealDevice = IoGetDeviceToVerify( Thread );
ASSERT( RealDevice != NULL ); ASSERT( RealDevice != NULL );
} }
Status = IrpContext->ExceptionCode; Status = IrpContext->ExceptionCode;
if (RealDevice != NULL) { if (RealDevice != NULL) {
if (IrpContext->ExceptionCode == STATUS_VERIFY_REQUIRED) { if (IrpContext->ExceptionCode == STATUS_VERIFY_REQUIRED) {
Status = IoVerifyVolume (RealDevice, FALSE); Status = IoVerifyVolume (RealDevice, FALSE);
ExAcquireResourceSharedLite(&Vcb->MainResource, TRUE); ExAcquireResourceSharedLite(&Vcb->MainResource, TRUE);
if (NT_SUCCESS(Status) && (!IsMounted(Vcb) || if (NT_SUCCESS(Status) && (!IsMounted(Vcb) ||
IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))) { IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))) {
Status = STATUS_WRONG_VOLUME; Status = STATUS_WRONG_VOLUME;
} }
ExReleaseResourceLite(&Vcb->MainResource); ExReleaseResourceLite(&Vcb->MainResource);
if (Ext2CheckDismount(IrpContext, Vcb, FALSE)) { if (Ext2CheckDismount(IrpContext, Vcb, FALSE)) {
Ext2CompleteIrpContext( IrpContext, STATUS_VOLUME_DISMOUNTED); Ext2CompleteIrpContext( IrpContext, STATUS_VOLUME_DISMOUNTED);
Status = STATUS_VOLUME_DISMOUNTED; Status = STATUS_VOLUME_DISMOUNTED;
Irp = NULL; Irp = NULL;
goto errorout; goto errorout;
} }
if ( (IrpContext->MajorFunction == IRP_MJ_CREATE) && if ( (IrpContext->MajorFunction == IRP_MJ_CREATE) &&
(IrpContext->FileObject->RelatedFileObject == NULL) && (IrpContext->FileObject->RelatedFileObject == NULL) &&
((Status == STATUS_SUCCESS) || (Status == STATUS_WRONG_VOLUME))) { ((Status == STATUS_SUCCESS) || (Status == STATUS_WRONG_VOLUME))) {
Irp->IoStatus.Information = IO_REMOUNT; Irp->IoStatus.Information = IO_REMOUNT;
Ext2CompleteIrpContext( IrpContext, STATUS_REPARSE); Ext2CompleteIrpContext( IrpContext, STATUS_REPARSE);
Status = STATUS_REPARSE; Status = STATUS_REPARSE;
Irp = NULL; Irp = NULL;
} }
if (Irp) { if (Irp) {
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
IoSetHardErrorOrVerifyDevice(Irp, RealDevice); IoSetHardErrorOrVerifyDevice(Irp, RealDevice);
ASSERT (STATUS_VERIFY_REQUIRED != Status); ASSERT (STATUS_VERIFY_REQUIRED != Status);
Ext2NormalizeAndRaiseStatus(IrpContext, Status); Ext2NormalizeAndRaiseStatus(IrpContext, Status);
} }
Status = Ext2QueueRequest(IrpContext); Status = Ext2QueueRequest(IrpContext);
} }
goto errorout; goto errorout;
} else { } else {
Status = STATUS_PENDING; Status = STATUS_PENDING;
IoMarkIrpPending( Irp ); IoMarkIrpPending( Irp );
IoRaiseHardError( Irp, Vpb, RealDevice ); IoRaiseHardError( Irp, Vpb, RealDevice );
IoSetDeviceToVerify( Thread, NULL ); IoSetDeviceToVerify( Thread, NULL );
goto release_context; goto release_context;
} }
} }
} }
Ext2CompleteRequest(Irp, FALSE, IO_NO_INCREMENT); Ext2CompleteRequest(Irp, FALSE, IO_NO_INCREMENT);
} }
release_context: release_context:
Ext2FreeIrpContext(IrpContext); Ext2FreeIrpContext(IrpContext);
} else { } else {
Status = STATUS_INVALID_PARAMETER; Status = STATUS_INVALID_PARAMETER;
} }
errorout: errorout:
return Status; return Status;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,68 +1,68 @@
#include <ext2fs.h> #include <ext2fs.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/errno.h> #include <linux/errno.h>
/* /*
* extents_bread: This function is a wrapper of CcPinRead routine. * extents_bread: This function is a wrapper of CcPinRead routine.
* *
* @sb: the device we need to undergo buffered IO on. * @sb: the device we need to undergo buffered IO on.
* @block: the block we want to read from. * @block: the block we want to read from.
* *
* If the call to this routine succeeds, the pages underlying the buffer header * If the call to this routine succeeds, the pages underlying the buffer header
* will be locked into memory, so that the buffer header returned for use is safe. * will be locked into memory, so that the buffer header returned for use is safe.
*/ */
struct buffer_head * struct buffer_head *
extents_bread(struct super_block *sb, sector_t block) extents_bread(struct super_block *sb, sector_t block)
{ {
return sb_getblk(sb, block); return sb_getblk(sb, block);
} }
/* /*
* extents_bwrite: This function is a wrapper of CcPreparePinWrite routine. * extents_bwrite: This function is a wrapper of CcPreparePinWrite routine.
* *
* @sb: the device we need to undergo buffered IO on. * @sb: the device we need to undergo buffered IO on.
* @block: the block we want to write to. * @block: the block we want to write to.
*/ */
struct buffer_head * struct buffer_head *
extents_bwrite(struct super_block *sb, sector_t block) extents_bwrite(struct super_block *sb, sector_t block)
{ {
return sb_getblk_zero(sb, block); return sb_getblk_zero(sb, block);
} }
/* /*
* extents_mark_buffer_dirty: Mark the buffer dirtied and so * extents_mark_buffer_dirty: Mark the buffer dirtied and so
* that changes will be written back. * that changes will be written back.
* *
* @bh: The corresponding buffer header that is modified. * @bh: The corresponding buffer header that is modified.
*/ */
void extents_mark_buffer_dirty(struct buffer_head *bh) void extents_mark_buffer_dirty(struct buffer_head *bh)
{ {
set_buffer_dirty(bh); set_buffer_dirty(bh);
} }
/* /*
* extents_brelse: Release the corresponding buffer header. * extents_brelse: Release the corresponding buffer header.
* *
* @bh: The corresponding buffer header that is going to be freed. * @bh: The corresponding buffer header that is going to be freed.
* *
* The pages underlying the buffer header will be unlocked. * The pages underlying the buffer header will be unlocked.
*/ */
void extents_brelse(struct buffer_head *bh) void extents_brelse(struct buffer_head *bh)
{ {
brelse(bh); brelse(bh);
} }
/* /*
* extents_bforget: Release the corresponding buffer header. * extents_bforget: Release the corresponding buffer header.
* NOTE: The page owned by @bh will be marked invalidated. * NOTE: The page owned by @bh will be marked invalidated.
* *
* @bh: The corresponding buffer header that is going to be freed. * @bh: The corresponding buffer header that is going to be freed.
* *
* The pages underlying the buffer header will be unlocked. * The pages underlying the buffer header will be unlocked.
*/ */
void extents_bforget(struct buffer_head *bh) void extents_bforget(struct buffer_head *bh)
{ {
clear_buffer_uptodate(bh); clear_buffer_uptodate(bh);
bforget(bh); bforget(bh);
} }

View File

@@ -1,244 +1,244 @@
/* /*
* COPYRIGHT: See COPYRIGHT.TXT * COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: extents.c * FILE: extents.c
* PROGRAMMER: Matt Wu <mattwu@163.com> * PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com * HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "ext2fs.h" #include "ext2fs.h"
/* GLOBALS *****************************************************************/ /* GLOBALS *****************************************************************/
extern PEXT2_GLOBAL Ext2Global; extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/ /* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
#endif #endif
NTSTATUS NTSTATUS
Ext2MapExtent( Ext2MapExtent(
IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb, IN PEXT2_VCB Vcb,
IN PEXT2_MCB Mcb, IN PEXT2_MCB Mcb,
IN ULONG Index, IN ULONG Index,
IN BOOLEAN Alloc, IN BOOLEAN Alloc,
OUT PULONG Block, OUT PULONG Block,
OUT PULONG Number OUT PULONG Number
) )
{ {
EXT4_EXTENT_HEADER *eh; EXT4_EXTENT_HEADER *eh;
struct buffer_head bh_got = {0}; struct buffer_head bh_got = {0};
int flags, rc; int flags, rc;
ULONG max_blocks = 0; ULONG max_blocks = 0;
memset(&bh_got, 0, sizeof(struct buffer_head)); memset(&bh_got, 0, sizeof(struct buffer_head));
eh = get_ext4_header(&Mcb->Inode); eh = get_ext4_header(&Mcb->Inode);
if (eh->eh_magic != EXT4_EXT_MAGIC) { if (eh->eh_magic != EXT4_EXT_MAGIC) {
if (Alloc) { if (Alloc) {
/* now initialize inode extent root node */ /* now initialize inode extent root node */
ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode); ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode);
} else { } else {
/* return empty-mapping when inode extent isn't initialized */ /* return empty-mapping when inode extent isn't initialized */
if (Block) if (Block)
*Block = 0; *Block = 0;
if (Number) { if (Number) {
LONGLONG _len = _len = Mcb->Inode.i_size; LONGLONG _len = _len = Mcb->Inode.i_size;
if (Mcb->Fcb) if (Mcb->Fcb)
_len = Mcb->Fcb->Header.AllocationSize.QuadPart; _len = Mcb->Fcb->Header.AllocationSize.QuadPart;
*Number = (ULONG)((_len + BLOCK_SIZE - 1) >> BLOCK_BITS); *Number = (ULONG)((_len + BLOCK_SIZE - 1) >> BLOCK_BITS);
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
} }
/* IrpContext is NULL when called during journal initialization */ /* IrpContext is NULL when called during journal initialization */
if (IsMcbDirectory(Mcb) || IrpContext == NULL || if (IsMcbDirectory(Mcb) || IrpContext == NULL ||
IrpContext->MajorFunction == IRP_MJ_WRITE || !Alloc){ IrpContext->MajorFunction == IRP_MJ_WRITE || !Alloc){
flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT; flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT;
max_blocks = EXT_INIT_MAX_LEN; max_blocks = EXT_INIT_MAX_LEN;
} else { } else {
flags = EXT4_GET_BLOCKS_IO_CREATE_EXT; flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
max_blocks = EXT_UNWRITTEN_MAX_LEN; max_blocks = EXT_UNWRITTEN_MAX_LEN;
} }
if (Alloc) { if (Alloc) {
if (Number && !*Number) { if (Number && !*Number) {
if (max_blocks > *Number) { if (max_blocks > *Number) {
max_blocks = *Number; max_blocks = *Number;
} }
} else { } else {
max_blocks = 1; max_blocks = 1;
} }
} }
if ((rc = ext4_ext_get_blocks( if ((rc = ext4_ext_get_blocks(
IrpContext, IrpContext,
NULL, NULL,
&Mcb->Inode, &Mcb->Inode,
Index, Index,
max_blocks, max_blocks,
&bh_got, &bh_got,
Alloc, Alloc,
flags)) < 0) { flags)) < 0) {
DEBUG(DL_ERR, ("Block insufficient resources, err: %d\n", rc)); DEBUG(DL_ERR, ("Block insufficient resources, err: %d\n", rc));
return Ext2WinntError(rc); return Ext2WinntError(rc);
} }
if (Alloc) if (Alloc)
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
if (Number) if (Number)
*Number = rc ? rc : 1; *Number = rc ? rc : 1;
if (Block) if (Block)
*Block = (ULONG)bh_got.b_blocknr; *Block = (ULONG)bh_got.b_blocknr;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
Ext2DoExtentExpand( Ext2DoExtentExpand(
IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb, IN PEXT2_VCB Vcb,
IN PEXT2_MCB Mcb, IN PEXT2_MCB Mcb,
IN ULONG Index, IN ULONG Index,
IN OUT PULONG Block, IN OUT PULONG Block,
IN OUT PULONG Number IN OUT PULONG Number
) )
{ {
EXT4_EXTENT_HEADER *eh; EXT4_EXTENT_HEADER *eh;
struct buffer_head bh_got; struct buffer_head bh_got;
int rc, flags; int rc, flags;
if (IsMcbDirectory(Mcb) || IrpContext->MajorFunction == IRP_MJ_WRITE) { if (IsMcbDirectory(Mcb) || IrpContext->MajorFunction == IRP_MJ_WRITE) {
flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT; flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT;
} else { } else {
flags = EXT4_GET_BLOCKS_IO_CREATE_EXT; flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
} }
memset(&bh_got, 0, sizeof(struct buffer_head)); memset(&bh_got, 0, sizeof(struct buffer_head));
eh = get_ext4_header(&Mcb->Inode); eh = get_ext4_header(&Mcb->Inode);
if (eh->eh_magic != EXT4_EXT_MAGIC) { if (eh->eh_magic != EXT4_EXT_MAGIC) {
ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode); ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode);
} }
if ((rc = ext4_ext_get_blocks( IrpContext, NULL, &Mcb->Inode, Index, if ((rc = ext4_ext_get_blocks( IrpContext, NULL, &Mcb->Inode, Index,
*Number, &bh_got, 1, flags)) < 0) { *Number, &bh_got, 1, flags)) < 0) {
DEBUG(DL_ERR, ("Expand Block insufficient resources, Number: %u," DEBUG(DL_ERR, ("Expand Block insufficient resources, Number: %u,"
" err: %d\n", *Number, rc)); " err: %d\n", *Number, rc));
DbgBreak(); DbgBreak();
return Ext2WinntError(rc); return Ext2WinntError(rc);
} }
if (Number) if (Number)
*Number = rc ? rc : 1; *Number = rc ? rc : 1;
if (Block) if (Block)
*Block = (ULONG)bh_got.b_blocknr; *Block = (ULONG)bh_got.b_blocknr;
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
Ext2ExpandExtent( Ext2ExpandExtent(
PEXT2_IRP_CONTEXT IrpContext, PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb, PEXT2_VCB Vcb,
PEXT2_MCB Mcb, PEXT2_MCB Mcb,
ULONG Start, ULONG Start,
ULONG End, ULONG End,
PLARGE_INTEGER Size PLARGE_INTEGER Size
) )
{ {
ULONG Count = 0, Number = 0, Block = 0; ULONG Count = 0, Number = 0, Block = 0;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
if (End <= Start) if (End <= Start)
return Status; return Status;
while (End > Start + Count) { while (End > Start + Count) {
Number = End - Start - Count; Number = End - Start - Count;
Status = Ext2DoExtentExpand(IrpContext, Vcb, Mcb, Start + Count, Status = Ext2DoExtentExpand(IrpContext, Vcb, Mcb, Start + Count,
&Block, &Number); &Block, &Number);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
Status = STATUS_INSUFFICIENT_RESOURCES; Status = STATUS_INSUFFICIENT_RESOURCES;
break; break;
} }
if (Number == 0) { if (Number == 0) {
Status = STATUS_INSUFFICIENT_RESOURCES; Status = STATUS_INSUFFICIENT_RESOURCES;
break; break;
} }
if (Block && IsZoneInited(Mcb)) { if (Block && IsZoneInited(Mcb)) {
if (!Ext2AddBlockExtent(Vcb, Mcb, Start + Count, Block, Number)) { if (!Ext2AddBlockExtent(Vcb, Mcb, Start + Count, Block, Number)) {
DbgBreak(); DbgBreak();
ClearFlag(Mcb->Flags, MCB_ZONE_INITED); ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
Ext2ClearAllExtents(&Mcb->Extents); Ext2ClearAllExtents(&Mcb->Extents);
} }
} }
Count += Number; Count += Number;
} }
Size->QuadPart = ((LONGLONG)(Start + Count)) << BLOCK_BITS; Size->QuadPart = ((LONGLONG)(Start + Count)) << BLOCK_BITS;
/* save inode whatever it succeeds to expand or not */ /* save inode whatever it succeeds to expand or not */
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
return Status; return Status;
} }
NTSTATUS NTSTATUS
Ext2TruncateExtent( Ext2TruncateExtent(
PEXT2_IRP_CONTEXT IrpContext, PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb, PEXT2_VCB Vcb,
PEXT2_MCB Mcb, PEXT2_MCB Mcb,
PLARGE_INTEGER Size PLARGE_INTEGER Size
) )
{ {
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
ULONG Extra = 0; ULONG Extra = 0;
ULONG Wanted = 0; ULONG Wanted = 0;
ULONG End; ULONG End;
ULONG Removed; ULONG Removed;
int err; int err;
/* translate file size to block */ /* translate file size to block */
End = Vcb->max_data_blocks; End = Vcb->max_data_blocks;
Wanted = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS); Wanted = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
/* calculate blocks to be freed */ /* calculate blocks to be freed */
Extra = End - Wanted; Extra = End - Wanted;
err = ext4_ext_truncate(IrpContext, &Mcb->Inode, Wanted); err = ext4_ext_truncate(IrpContext, &Mcb->Inode, Wanted);
if (err == 0) { if (err == 0) {
if (!Ext2RemoveBlockExtent(Vcb, Mcb, Wanted, Extra)) { if (!Ext2RemoveBlockExtent(Vcb, Mcb, Wanted, Extra)) {
ClearFlag(Mcb->Flags, MCB_ZONE_INITED); ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
Ext2ClearAllExtents(&Mcb->Extents); Ext2ClearAllExtents(&Mcb->Extents);
} }
Extra = 0; Extra = 0;
} else { } else {
Status = STATUS_INSUFFICIENT_RESOURCES; Status = STATUS_INSUFFICIENT_RESOURCES;
} }
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS); Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS);
} }
if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart)) if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart))
Mcb->Inode.i_size = (loff_t)(Size->QuadPart); Mcb->Inode.i_size = (loff_t)(Size->QuadPart);
/* Save modifications on i_blocks field and i_size field of the inode. */ /* Save modifications on i_blocks field and i_size field of the inode. */
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
return Status; return Status;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,277 +1,277 @@
/* /*
* COPYRIGHT: See COPYRIGHT.TXT * COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: flush.c * FILE: flush.c
* PROGRAMMER: Matt Wu <mattwu@163.com> * PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com * HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "ext2fs.h" #include "ext2fs.h"
/* GLOBALS ***************************************************************/ /* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global; extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/ /* DEFINITIONS *************************************************************/
NTSTATUS NTSTATUS
Ext2FlushCompletionRoutine ( Ext2FlushCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp, IN PIRP Irp,
IN PVOID Context ) IN PVOID Context )
{ {
if (Irp->PendingReturned) if (Irp->PendingReturned)
IoMarkIrpPending( Irp ); IoMarkIrpPending( Irp );
if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST) if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)
Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Status = STATUS_SUCCESS;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
NTSTATUS NTSTATUS
Ext2FlushVolume ( Ext2FlushVolume (
IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb, IN PEXT2_VCB Vcb,
IN BOOLEAN bShutDown IN BOOLEAN bShutDown
) )
{ {
DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n")); DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
ExReleaseResourceLite(&Vcb->PagingIoResource); ExReleaseResourceLite(&Vcb->PagingIoResource);
return Ext2FlushVcb(Vcb); return Ext2FlushVcb(Vcb);
} }
NTSTATUS NTSTATUS
Ext2FlushFile ( Ext2FlushFile (
IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_FCB Fcb, IN PEXT2_FCB Fcb,
IN PEXT2_CCB Ccb IN PEXT2_CCB Ccb
) )
{ {
IO_STATUS_BLOCK IoStatus = {0}; IO_STATUS_BLOCK IoStatus = {0};
ASSERT(Fcb != NULL); ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == EXT2FCB) && ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB))); (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
__try { __try {
/* do nothing if target fie was deleted */ /* do nothing if target fie was deleted */
if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
IoStatus.Status = STATUS_FILE_DELETED; IoStatus.Status = STATUS_FILE_DELETED;
__leave; __leave;
} }
/* update timestamp and achieve attribute */ /* update timestamp and achieve attribute */
if (Ccb != NULL) { if (Ccb != NULL) {
if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) { if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
LARGE_INTEGER SysTime; LARGE_INTEGER SysTime;
KeQuerySystemTime(&SysTime); KeQuerySystemTime(&SysTime);
Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime); Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime); Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime);
Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode); Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode);
} }
} }
if (IsDirectory(Fcb)) { if (IsDirectory(Fcb)) {
IoStatus.Status = STATUS_SUCCESS; IoStatus.Status = STATUS_SUCCESS;
__leave; __leave;
} }
DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n", DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n",
Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer)); Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer));
CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus); CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED); ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
} __finally { } __finally {
/* do cleanup here */ /* do cleanup here */
} }
return IoStatus.Status; return IoStatus.Status;
} }
NTSTATUS NTSTATUS
Ext2FlushFiles( Ext2FlushFiles(
IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb, IN PEXT2_VCB Vcb,
IN BOOLEAN bShutDown IN BOOLEAN bShutDown
) )
{ {
IO_STATUS_BLOCK IoStatus; IO_STATUS_BLOCK IoStatus;
PEXT2_FCB Fcb; PEXT2_FCB Fcb;
PLIST_ENTRY ListEntry; PLIST_ENTRY ListEntry;
if (IsVcbReadOnly(Vcb)) { if (IsVcbReadOnly(Vcb)) {
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
IoStatus.Status = STATUS_SUCCESS; IoStatus.Status = STATUS_SUCCESS;
DEBUG(DL_INF, ( "Flushing Files ...\n")); DEBUG(DL_INF, ( "Flushing Files ...\n"));
// Flush all Fcbs in Vcb list queue. // Flush all Fcbs in Vcb list queue.
for (ListEntry = Vcb->FcbList.Flink; for (ListEntry = Vcb->FcbList.Flink;
ListEntry != &Vcb->FcbList; ListEntry != &Vcb->FcbList;
ListEntry = ListEntry->Flink ) { ListEntry = ListEntry->Flink ) {
Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next); Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next);
ExAcquireResourceExclusiveLite( ExAcquireResourceExclusiveLite(
&Fcb->MainResource, TRUE); &Fcb->MainResource, TRUE);
Ext2FlushFile(IrpContext, Fcb, NULL); Ext2FlushFile(IrpContext, Fcb, NULL);
ExReleaseResourceLite(&Fcb->MainResource); ExReleaseResourceLite(&Fcb->MainResource);
} }
return IoStatus.Status; return IoStatus.Status;
} }
NTSTATUS NTSTATUS
Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext) Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
{ {
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PIRP Irp = NULL; PIRP Irp = NULL;
PIO_STACK_LOCATION IrpSp = NULL; PIO_STACK_LOCATION IrpSp = NULL;
PEXT2_VCB Vcb = NULL; PEXT2_VCB Vcb = NULL;
PEXT2_FCB Fcb = NULL; PEXT2_FCB Fcb = NULL;
PEXT2_FCBVCB FcbOrVcb = NULL; PEXT2_FCBVCB FcbOrVcb = NULL;
PEXT2_CCB Ccb = NULL; PEXT2_CCB Ccb = NULL;
PFILE_OBJECT FileObject = NULL; PFILE_OBJECT FileObject = NULL;
PDEVICE_OBJECT DeviceObject = NULL; PDEVICE_OBJECT DeviceObject = NULL;
BOOLEAN MainResourceAcquired = FALSE; BOOLEAN MainResourceAcquired = FALSE;
__try { __try {
ASSERT(IrpContext); ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject; DeviceObject = IrpContext->DeviceObject;
// //
// This request is not allowed on the main device object // This request is not allowed on the main device object
// //
if (IsExt2FsDevice(DeviceObject)) { if (IsExt2FsDevice(DeviceObject)) {
Status = STATUS_INVALID_DEVICE_REQUEST; Status = STATUS_INVALID_DEVICE_REQUEST;
__leave; __leave;
} }
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL); ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) && ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB))); (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
ASSERT(IsMounted(Vcb)); ASSERT(IsMounted(Vcb));
if (IsVcbReadOnly(Vcb)) { if (IsVcbReadOnly(Vcb)) {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
__leave; __leave;
} }
Irp = IrpContext->Irp; Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp); IrpSp = IoGetCurrentIrpStackLocation(Irp);
FileObject = IrpContext->FileObject; FileObject = IrpContext->FileObject;
FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext; FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
ASSERT(FcbOrVcb != NULL); ASSERT(FcbOrVcb != NULL);
Ccb = (PEXT2_CCB) FileObject->FsContext2; Ccb = (PEXT2_CCB) FileObject->FsContext2;
if (Ccb == NULL) { if (Ccb == NULL) {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
__leave; __leave;
} }
MainResourceAcquired = MainResourceAcquired =
ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, TRUE); ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, TRUE);
ASSERT(MainResourceAcquired); ASSERT(MainResourceAcquired);
DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n", DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n",
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents))); FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
if (FcbOrVcb->Identifier.Type == EXT2VCB) { if (FcbOrVcb->Identifier.Type == EXT2VCB) {
Ext2VerifyVcb(IrpContext, Vcb); Ext2VerifyVcb(IrpContext, Vcb);
Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE); Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
if (NT_SUCCESS(Status)) { if (NT_SUCCESS(Status)) {
__leave; __leave;
} }
Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE); Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) { if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) {
ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED); ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
} }
} else if (FcbOrVcb->Identifier.Type == EXT2FCB) { } else if (FcbOrVcb->Identifier.Type == EXT2FCB) {
Fcb = (PEXT2_FCB)(FcbOrVcb); Fcb = (PEXT2_FCB)(FcbOrVcb);
Status = Ext2FlushFile(IrpContext, Fcb, Ccb); Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
if (NT_SUCCESS(Status)) { if (NT_SUCCESS(Status)) {
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) { if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE; Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
ClearFlag(FileObject->Flags, FO_FILE_MODIFIED); ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
} }
} }
} }
DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n", DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n",
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents))); FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
} __finally { } __finally {
if (MainResourceAcquired) { if (MainResourceAcquired) {
ExReleaseResourceLite(&FcbOrVcb->MainResource); ExReleaseResourceLite(&FcbOrVcb->MainResource);
} }
if (!IrpContext->ExceptionInProgress) { if (!IrpContext->ExceptionInProgress) {
if (Vcb && Irp && IrpSp && !IsVcbReadOnly(Vcb)) { if (Vcb && Irp && IrpSp && !IsVcbReadOnly(Vcb)) {
// Call the disk driver to flush the physial media. // Call the disk driver to flush the physial media.
NTSTATUS DriverStatus; NTSTATUS DriverStatus;
PIO_STACK_LOCATION NextIrpSp; PIO_STACK_LOCATION NextIrpSp;
NextIrpSp = IoGetNextIrpStackLocation(Irp); NextIrpSp = IoGetNextIrpStackLocation(Irp);
*NextIrpSp = *IrpSp; *NextIrpSp = *IrpSp;
IoSetCompletionRoutine( Irp, IoSetCompletionRoutine( Irp,
Ext2FlushCompletionRoutine, Ext2FlushCompletionRoutine,
NULL, NULL,
TRUE, TRUE,
TRUE, TRUE,
TRUE ); TRUE );
DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp); DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);
Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ? Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
Status : DriverStatus; Status : DriverStatus;
IrpContext->Irp = Irp = NULL; IrpContext->Irp = Irp = NULL;
} }
Ext2CompleteIrpContext(IrpContext, Status); Ext2CompleteIrpContext(IrpContext, Status);
} }
} }
return Status; return Status;
} }

View File

@@ -1,261 +1,261 @@
#ifndef _EXT2_COMMON_INCLUDE_ #ifndef _EXT2_COMMON_INCLUDE_
#define _EXT2_COMMON_INCLUDE_ #define _EXT2_COMMON_INCLUDE_
/* global ioctl */ /* global ioctl */
#define IOCTL_APP_VOLUME_PROPERTY \ #define IOCTL_APP_VOLUME_PROPERTY \
CTL_CODE(FILE_DEVICE_UNKNOWN, 2000, METHOD_BUFFERED, FILE_ANY_ACCESS) CTL_CODE(FILE_DEVICE_UNKNOWN, 2000, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_APP_QUERY_PERFSTAT \ #define IOCTL_APP_QUERY_PERFSTAT \
CTL_CODE(FILE_DEVICE_UNKNOWN, 2001, METHOD_BUFFERED, FILE_ANY_ACCESS) CTL_CODE(FILE_DEVICE_UNKNOWN, 2001, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_APP_MOUNT_POINT \ #define IOCTL_APP_MOUNT_POINT \
CTL_CODE(FILE_DEVICE_UNKNOWN, 2002, METHOD_BUFFERED, FILE_ANY_ACCESS) CTL_CODE(FILE_DEVICE_UNKNOWN, 2002, METHOD_BUFFERED, FILE_ANY_ACCESS)
/* performance / memory allocaiton statistics */ /* performance / memory allocaiton statistics */
#define PS_IRP_CONTEXT 0x00 #define PS_IRP_CONTEXT 0x00
#define PS_VCB 0x01 #define PS_VCB 0x01
#define PS_FCB 0x02 #define PS_FCB 0x02
#define PS_CCB 0x03 #define PS_CCB 0x03
#define PS_MCB 0x04 #define PS_MCB 0x04
#define PS_EXTENT 0x05 #define PS_EXTENT 0x05
#define PS_RW_CONTEXT 0x06 #define PS_RW_CONTEXT 0x06
#define PS_VPB 0x07 #define PS_VPB 0x07
#define PS_FILE_NAME 0x08 #define PS_FILE_NAME 0x08
#define PS_MCB_NAME 0x09 #define PS_MCB_NAME 0x09
#define PS_INODE_NAME 0x0A #define PS_INODE_NAME 0x0A
#define PS_DIR_ENTRY 0x0B #define PS_DIR_ENTRY 0x0B
#define PS_DIR_PATTERN 0x0C #define PS_DIR_PATTERN 0x0C
#define PS_DISK_EVENT 0x0D #define PS_DISK_EVENT 0x0D
#define PS_DISK_BUFFER 0x0E #define PS_DISK_BUFFER 0x0E
#define PS_BLOCK_DATA 0x0F #define PS_BLOCK_DATA 0x0F
#define PS_EXT2_INODE 0x10 #define PS_EXT2_INODE 0x10
#define PS_DENTRY 0x11 #define PS_DENTRY 0x11
#define PS_BUFF_HEAD 0x12 #define PS_BUFF_HEAD 0x12
#define PS_MAX_TYPE_V1 (0x10) #define PS_MAX_TYPE_V1 (0x10)
#define PS_MAX_TYPE_V2 (0x30) #define PS_MAX_TYPE_V2 (0x30)
typedef union { typedef union {
ULONG Slot[PS_MAX_TYPE_V1]; ULONG Slot[PS_MAX_TYPE_V1];
struct { struct {
ULONG IrpContext; ULONG IrpContext;
ULONG Vcb; ULONG Vcb;
ULONG Fcb; ULONG Fcb;
ULONG Ccb; ULONG Ccb;
ULONG Mcb; ULONG Mcb;
ULONG Extent; ULONG Extent;
ULONG RwContext; /* rw context */ ULONG RwContext; /* rw context */
ULONG Vpb; ULONG Vpb;
ULONG FileName; ULONG FileName;
ULONG McbName; ULONG McbName;
ULONG InodeName; ULONG InodeName;
ULONG DirEntry; /* pDir */ ULONG DirEntry; /* pDir */
ULONG DirPattern; /* Ccb-> in Ext2QeuryDir */ ULONG DirPattern; /* Ccb-> in Ext2QeuryDir */
ULONG ReadDiskEvent; ULONG ReadDiskEvent;
ULONG ReadDiskBuffer; ULONG ReadDiskBuffer;
ULONG BlockData; /* Ext2Expand&TruncateFile*/ ULONG BlockData; /* Ext2Expand&TruncateFile*/
}; };
} EXT2_STAT_ARRAY_V1; } EXT2_STAT_ARRAY_V1;
typedef union { typedef union {
ULONG Slot[PS_MAX_TYPE_V2]; ULONG Slot[PS_MAX_TYPE_V2];
struct { struct {
ULONG IrpContext; ULONG IrpContext;
ULONG Vcb; ULONG Vcb;
ULONG Fcb; ULONG Fcb;
ULONG Ccb; ULONG Ccb;
ULONG Mcb; ULONG Mcb;
ULONG Extent; ULONG Extent;
ULONG RwContext; /* rw context */ ULONG RwContext; /* rw context */
ULONG Vpb; ULONG Vpb;
ULONG FileName; ULONG FileName;
ULONG McbName; ULONG McbName;
ULONG InodeName; ULONG InodeName;
ULONG DirEntry; /* pDir */ ULONG DirEntry; /* pDir */
ULONG DirPattern; /* Ccb-> in Ext2QeuryDir */ ULONG DirPattern; /* Ccb-> in Ext2QeuryDir */
ULONG ReadDiskEvent; ULONG ReadDiskEvent;
ULONG ReadDiskBuffer; ULONG ReadDiskBuffer;
ULONG BlockData; /* Ext2Expand&TruncateFile*/ ULONG BlockData; /* Ext2Expand&TruncateFile*/
ULONG Inodes; /* inodes */ ULONG Inodes; /* inodes */
ULONG NameEntries; /* name dentry */ ULONG NameEntries; /* name dentry */
ULONG BufferHead; /* Buffer Header allocations */ ULONG BufferHead; /* Buffer Header allocations */
}; };
} EXT2_STAT_ARRAY_V2; } EXT2_STAT_ARRAY_V2;
typedef struct _EXT2_PERF_STATISTICS_V1 { typedef struct _EXT2_PERF_STATISTICS_V1 {
/* totoal number of processed/being processed requests */ /* totoal number of processed/being processed requests */
struct { struct {
ULONG Processed; ULONG Processed;
ULONG Current; ULONG Current;
} Irps [IRP_MJ_MAXIMUM_FUNCTION + 1]; } Irps [IRP_MJ_MAXIMUM_FUNCTION + 1];
/* structure size */ /* structure size */
EXT2_STAT_ARRAY_V1 Unit; EXT2_STAT_ARRAY_V1 Unit;
/* current memory allocation statistics */ /* current memory allocation statistics */
EXT2_STAT_ARRAY_V1 Current; EXT2_STAT_ARRAY_V1 Current;
/* memory allocated in bytes */ /* memory allocated in bytes */
EXT2_STAT_ARRAY_V1 Size; EXT2_STAT_ARRAY_V1 Size;
/* totoal memory allocation statistics */ /* totoal memory allocation statistics */
EXT2_STAT_ARRAY_V1 Total; EXT2_STAT_ARRAY_V1 Total;
} EXT2_PERF_STATISTICS_V1, *PEXT2_PERF_STATISTICS_V1; } EXT2_PERF_STATISTICS_V1, *PEXT2_PERF_STATISTICS_V1;
#define EXT2_PERF_STAT_MAGIC '2SPE' #define EXT2_PERF_STAT_MAGIC '2SPE'
#define EXT2_PERF_STAT_VER2 2 #define EXT2_PERF_STAT_VER2 2
typedef struct _EXT2_PERF_STATISTICS_V2 { typedef struct _EXT2_PERF_STATISTICS_V2 {
ULONG Magic; /* EPS2 */ ULONG Magic; /* EPS2 */
USHORT Version; /* 02 */ USHORT Version; /* 02 */
USHORT Length; /* sizeof(EXT2_PERF_STATISTICS_V2) */ USHORT Length; /* sizeof(EXT2_PERF_STATISTICS_V2) */
/* totoal number of processed/being processed requests */ /* totoal number of processed/being processed requests */
struct { struct {
ULONG Processed; ULONG Processed;
ULONG Current; ULONG Current;
} Irps [IRP_MJ_MAXIMUM_FUNCTION + 1]; } Irps [IRP_MJ_MAXIMUM_FUNCTION + 1];
/* structure size */ /* structure size */
EXT2_STAT_ARRAY_V2 Unit; EXT2_STAT_ARRAY_V2 Unit;
/* current memory allocation statistics */ /* current memory allocation statistics */
EXT2_STAT_ARRAY_V2 Current; EXT2_STAT_ARRAY_V2 Current;
/* memory allocated in bytes */ /* memory allocated in bytes */
EXT2_STAT_ARRAY_V2 Size; EXT2_STAT_ARRAY_V2 Size;
/* totoal memory allocation statistics */ /* totoal memory allocation statistics */
EXT2_STAT_ARRAY_V2 Total; EXT2_STAT_ARRAY_V2 Total;
} EXT2_PERF_STATISTICS_V2, *PEXT2_PERF_STATISTICS_V2; } EXT2_PERF_STATISTICS_V2, *PEXT2_PERF_STATISTICS_V2;
/* volume property ... */ /* volume property ... */
#define EXT2_VOLUME_PROPERTY_MAGIC 'EVPM' #define EXT2_VOLUME_PROPERTY_MAGIC 'EVPM'
#define EXT2_FLAG_VP_SET_GLOBAL 0x00000001 #define EXT2_FLAG_VP_SET_GLOBAL 0x00000001
#define APP_CMD_QUERY_VERSION 0x00000000 /* with global flag set */ #define APP_CMD_QUERY_VERSION 0x00000000 /* with global flag set */
#define APP_CMD_QUERY_CODEPAGES 0x00000001 #define APP_CMD_QUERY_CODEPAGES 0x00000001
#define APP_CMD_QUERY_PROPERTY 0x00000002 #define APP_CMD_QUERY_PROPERTY 0x00000002
#define APP_CMD_SET_PROPERTY 0x00000003 #define APP_CMD_SET_PROPERTY 0x00000003
#define APP_CMD_QUERY_PROPERTY2 0x00000004 #define APP_CMD_QUERY_PROPERTY2 0x00000004
#define APP_CMD_SET_PROPERTY2 0x00000005 #define APP_CMD_SET_PROPERTY2 0x00000005
#define APP_CMD_QUERY_PROPERTY3 0x00000006 #define APP_CMD_QUERY_PROPERTY3 0x00000006
#define APP_CMD_SET_PROPERTY3 0x00000007 #define APP_CMD_SET_PROPERTY3 0x00000007
#define CODEPAGE_MAXLEN 0x20 #define CODEPAGE_MAXLEN 0x20
#define HIDINGPAT_LEN 0x20 #define HIDINGPAT_LEN 0x20
typedef struct _EXT2_VOLUME_PROPERTY { typedef struct _EXT2_VOLUME_PROPERTY {
ULONG Magic; ULONG Magic;
ULONG Flags; ULONG Flags;
ULONG Command; ULONG Command;
BOOLEAN bReadonly; BOOLEAN bReadonly;
BOOLEAN bExt3Writable; BOOLEAN bExt3Writable;
BOOLEAN bExt2; BOOLEAN bExt2;
BOOLEAN bExt3; BOOLEAN bExt3;
CHAR Codepage[CODEPAGE_MAXLEN]; CHAR Codepage[CODEPAGE_MAXLEN];
} EXT2_VOLUME_PROPERTY, *PEXT2_VOLUME_PROPERTY; } EXT2_VOLUME_PROPERTY, *PEXT2_VOLUME_PROPERTY;
#ifdef __cplusplus #ifdef __cplusplus
typedef struct _EXT2_VOLUME_PROPERTY2:EXT2_VOLUME_PROPERTY { typedef struct _EXT2_VOLUME_PROPERTY2:EXT2_VOLUME_PROPERTY {
#else // __cplusplus #else // __cplusplus
typedef struct _EXT2_VOLUME_PROPERTY2 { typedef struct _EXT2_VOLUME_PROPERTY2 {
EXT2_VOLUME_PROPERTY ; EXT2_VOLUME_PROPERTY ;
#endif // __cplusplus #endif // __cplusplus
/* new volume properties added after version 0.35 */ /* new volume properties added after version 0.35 */
/* volume uuid */ /* volume uuid */
__u8 UUID[16]; __u8 UUID[16];
/* mount point: driver letter only */ /* mount point: driver letter only */
UCHAR DrvLetter; UCHAR DrvLetter;
/* checking bitmap */ /* checking bitmap */
BOOLEAN bCheckBitmap; BOOLEAN bCheckBitmap;
/* global hiding patterns */ /* global hiding patterns */
BOOLEAN bHidingPrefix; BOOLEAN bHidingPrefix;
BOOLEAN bHidingSuffix; BOOLEAN bHidingSuffix;
CHAR sHidingPrefix[HIDINGPAT_LEN]; CHAR sHidingPrefix[HIDINGPAT_LEN];
CHAR sHidingSuffix[HIDINGPAT_LEN]; CHAR sHidingSuffix[HIDINGPAT_LEN];
} EXT2_VOLUME_PROPERTY2, *PEXT2_VOLUME_PROPERTY2; } EXT2_VOLUME_PROPERTY2, *PEXT2_VOLUME_PROPERTY2;
#define EXT2_VPROP3_AUTOMOUNT (1ui64 << 0) #define EXT2_VPROP3_AUTOMOUNT (1ui64 << 0)
#define EXT2_VPROP3_USERIDS (1ui64 << 1) #define EXT2_VPROP3_USERIDS (1ui64 << 1)
#ifdef __cplusplus #ifdef __cplusplus
typedef struct _EXT2_VOLUME_PROPERTY3:EXT2_VOLUME_PROPERTY2 { typedef struct _EXT2_VOLUME_PROPERTY3:EXT2_VOLUME_PROPERTY2 {
#else // __cplusplus #else // __cplusplus
typedef struct _EXT2_VOLUME_PROPERTY3 { typedef struct _EXT2_VOLUME_PROPERTY3 {
EXT2_VOLUME_PROPERTY2 ; EXT2_VOLUME_PROPERTY2 ;
#endif // __cplusplus #endif // __cplusplus
unsigned __int64 Flags2; unsigned __int64 Flags2;
ULONG AutoMount:1; ULONG AutoMount:1;
ULONG EIDS:1; ULONG EIDS:1;
ULONG Reserved1:30; ULONG Reserved1:30;
USHORT uid; USHORT uid;
USHORT gid; USHORT gid;
USHORT euid; USHORT euid;
USHORT egid; USHORT egid;
ULONG Reserved2[29]; ULONG Reserved2[29];
} EXT2_VOLUME_PROPERTY3, *PEXT2_VOLUME_PROPERTY3; } EXT2_VOLUME_PROPERTY3, *PEXT2_VOLUME_PROPERTY3;
/* Ext2Fsd driver version and built time */ /* Ext2Fsd driver version and built time */
typedef struct _EXT2_VOLUME_PROPERTY_VERSION { typedef struct _EXT2_VOLUME_PROPERTY_VERSION {
ULONG Magic; ULONG Magic;
ULONG Flags; ULONG Flags;
ULONG Command; ULONG Command;
CHAR Version[0x1C]; CHAR Version[0x1C];
CHAR Time[0x20]; CHAR Time[0x20];
CHAR Date[0x20]; CHAR Date[0x20];
} EXT2_VOLUME_PROPERTY_VERSION, *PEXT2_VOLUME_PROPERTY_VERSION; } EXT2_VOLUME_PROPERTY_VERSION, *PEXT2_VOLUME_PROPERTY_VERSION;
/* performance statistics */ /* performance statistics */
#define EXT2_QUERY_PERFSTAT_MAGIC 'EVPM' #define EXT2_QUERY_PERFSTAT_MAGIC 'EVPM'
#define EXT2_QUERY_PERFSTAT_VER2 0x8000000 #define EXT2_QUERY_PERFSTAT_VER2 0x8000000
typedef struct _EXT2_QUERY_PERFSTAT { typedef struct _EXT2_QUERY_PERFSTAT {
ULONG Magic; ULONG Magic;
ULONG Flags; ULONG Flags;
ULONG Command; ULONG Command;
union { union {
EXT2_PERF_STATISTICS_V1 PerfStatV1; EXT2_PERF_STATISTICS_V1 PerfStatV1;
EXT2_PERF_STATISTICS_V2 PerfStatV2; EXT2_PERF_STATISTICS_V2 PerfStatV2;
}; };
} EXT2_QUERY_PERFSTAT, *PEXT2_QUERY_PERFSTAT; } EXT2_QUERY_PERFSTAT, *PEXT2_QUERY_PERFSTAT;
#define EXT2_QUERY_PERFSTAT_SZV1 (FIELD_OFFSET(EXT2_QUERY_PERFSTAT, PerfStatV1) + sizeof(EXT2_PERF_STATISTICS_V1)) #define EXT2_QUERY_PERFSTAT_SZV1 (FIELD_OFFSET(EXT2_QUERY_PERFSTAT, PerfStatV1) + sizeof(EXT2_PERF_STATISTICS_V1))
#define EXT2_QUERY_PERFSTAT_SZV2 (FIELD_OFFSET(EXT2_QUERY_PERFSTAT, PerfStatV1) + sizeof(EXT2_PERF_STATISTICS_V2)) #define EXT2_QUERY_PERFSTAT_SZV2 (FIELD_OFFSET(EXT2_QUERY_PERFSTAT, PerfStatV1) + sizeof(EXT2_PERF_STATISTICS_V2))
/* mountpoint management */ /* mountpoint management */
#define EXT2_APP_MOUNTPOINT_MAGIC 'EAMM' #define EXT2_APP_MOUNTPOINT_MAGIC 'EAMM'
typedef struct _EXT2_MOUNT_POINT { typedef struct _EXT2_MOUNT_POINT {
ULONG Magic; ULONG Magic;
ULONG Flags; ULONG Flags;
ULONG Size; ULONG Size;
ULONG Command; ULONG Command;
USHORT Link[256]; USHORT Link[256];
USHORT Name[256]; USHORT Name[256];
} EXT2_MOUNT_POINT, *PEXT2_MOUNT_POINT; } EXT2_MOUNT_POINT, *PEXT2_MOUNT_POINT;
#define APP_CMD_ADD_DOS_SYMLINK 0x00000001 #define APP_CMD_ADD_DOS_SYMLINK 0x00000001
#define APP_CMD_DEL_DOS_SYMLINK 0x00000002 #define APP_CMD_DEL_DOS_SYMLINK 0x00000002
#endif /* _EXT2_COMMON_INCLUDE_ */ #endif /* _EXT2_COMMON_INCLUDE_ */

View File

@@ -1,155 +1,155 @@
#ifndef _LINUX_ATOMIC_H #ifndef _LINUX_ATOMIC_H
#define _LINUX_ATOMIC_H #define _LINUX_ATOMIC_H
#include <linux/types.h> #include <linux/types.h>
// //
// atomic // atomic
// //
typedef struct { typedef struct {
volatile LONG counter; volatile LONG counter;
} atomic_t; } atomic_t;
#define ATOMIC_INIT(i) (i) #define ATOMIC_INIT(i) (i)
/** /**
* atomic_read - read atomic variable * atomic_read - read atomic variable
* @v: pointer of type atomic_t * @v: pointer of type atomic_t
* *
* Atomically reads the value of @v. Note that the guaranteed * Atomically reads the value of @v. Note that the guaranteed
* useful range of an atomic_t is only 24 bits. * useful range of an atomic_t is only 24 bits.
*/ */
#define atomic_read(v) ((v)->counter) #define atomic_read(v) ((v)->counter)
/** /**
* atomic_set - set atomic variable * atomic_set - set atomic variable
* @v: pointer of type atomic_t * @v: pointer of type atomic_t
* @i: required value * @i: required value
* *
* Atomically sets the value of @v to @i. Note that the guaranteed * Atomically sets the value of @v to @i. Note that the guaranteed
* useful range of an atomic_t is only 24 bits. * useful range of an atomic_t is only 24 bits.
*/ */
#define atomic_set(v,i) InterlockedExchange((PLONG)(&(v)->counter), (LONG)(i)) #define atomic_set(v,i) InterlockedExchange((PLONG)(&(v)->counter), (LONG)(i))
/** /**
* atomic_add - add integer to atomic variable * atomic_add - add integer to atomic variable
* @i: integer value to add * @i: integer value to add
* @v: pointer of type atomic_t * @v: pointer of type atomic_t
* *
* Atomically adds @i to @v. Note that the guaranteed useful range * Atomically adds @i to @v. Note that the guaranteed useful range
* of an atomic_t is only 24 bits. * of an atomic_t is only 24 bits.
*/ */
static inline void atomic_add(int volatile i, atomic_t volatile *v) static inline void atomic_add(int volatile i, atomic_t volatile *v)
{ {
InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) i); InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) i);
} }
/** /**
* atomic_sub - subtract the atomic variable * atomic_sub - subtract the atomic variable
* @i: integer value to subtract * @i: integer value to subtract
* @v: pointer of type atomic_t * @v: pointer of type atomic_t
* *
* Atomically subtracts @i from @v. Note that the guaranteed * Atomically subtracts @i from @v. Note that the guaranteed
* useful range of an atomic_t is only 24 bits. * useful range of an atomic_t is only 24 bits.
*/ */
static inline void atomic_sub(int volatile i, atomic_t volatile *v) static inline void atomic_sub(int volatile i, atomic_t volatile *v)
{ {
InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) (-1*i)); InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) (-1*i));
} }
/** /**
* atomic_sub_and_test - subtract value from variable and test result * atomic_sub_and_test - subtract value from variable and test result
* @i: integer value to subtract * @i: integer value to subtract
* @v: pointer of type atomic_t * @v: pointer of type atomic_t
* *
* Atomically subtracts @i from @v and returns * Atomically subtracts @i from @v and returns
* true if the result is zero, or false for all * true if the result is zero, or false for all
* other cases. Note that the guaranteed * other cases. Note that the guaranteed
* useful range of an atomic_t is only 24 bits. * useful range of an atomic_t is only 24 bits.
*/ */
static inline int atomic_sub_and_test(int volatile i, atomic_t volatile *v) static inline int atomic_sub_and_test(int volatile i, atomic_t volatile *v)
{ {
int counter, result; int counter, result;
do { do {
counter = v->counter; counter = v->counter;
result = counter - i; result = counter - i;
} while ( InterlockedCompareExchange( } while ( InterlockedCompareExchange(
(PLONG) (&v->counter), (PLONG) (&v->counter),
(LONG) result, (LONG) result,
(LONG) counter) != counter); (LONG) counter) != counter);
return (result == 0); return (result == 0);
} }
/** /**
* atomic_inc - increment atomic variable * atomic_inc - increment atomic variable
* @v: pointer of type atomic_t * @v: pointer of type atomic_t
* *
* Atomically increments @v by 1. Note that the guaranteed * Atomically increments @v by 1. Note that the guaranteed
* useful range of an atomic_t is only 24 bits. * useful range of an atomic_t is only 24 bits.
*/ */
static inline void atomic_inc(atomic_t volatile *v) static inline void atomic_inc(atomic_t volatile *v)
{ {
InterlockedIncrement((PLONG)(&v->counter)); InterlockedIncrement((PLONG)(&v->counter));
} }
/** /**
* atomic_dec - decrement atomic variable * atomic_dec - decrement atomic variable
* @v: pointer of type atomic_t * @v: pointer of type atomic_t
* *
* Atomically decrements @v by 1. Note that the guaranteed * Atomically decrements @v by 1. Note that the guaranteed
* useful range of an atomic_t is only 24 bits. * useful range of an atomic_t is only 24 bits.
*/ */
static inline void atomic_dec(atomic_t volatile *v) static inline void atomic_dec(atomic_t volatile *v)
{ {
InterlockedDecrement((PLONG)(&v->counter)); InterlockedDecrement((PLONG)(&v->counter));
} }
/** /**
* atomic_dec_and_test - decrement and test * atomic_dec_and_test - decrement and test
* @v: pointer of type atomic_t * @v: pointer of type atomic_t
* *
* Atomically decrements @v by 1 and * Atomically decrements @v by 1 and
* returns true if the result is 0, or false for all other * returns true if the result is 0, or false for all other
* cases. Note that the guaranteed * cases. Note that the guaranteed
* useful range of an atomic_t is only 24 bits. * useful range of an atomic_t is only 24 bits.
*/ */
static inline int atomic_dec_and_test(atomic_t volatile *v) static inline int atomic_dec_and_test(atomic_t volatile *v)
{ {
return (0 == InterlockedDecrement((PLONG)(&v->counter))); return (0 == InterlockedDecrement((PLONG)(&v->counter)));
} }
/** /**
* atomic_inc_and_test - increment and test * atomic_inc_and_test - increment and test
* @v: pointer of type atomic_t * @v: pointer of type atomic_t
* *
* Atomically increments @v by 1 * Atomically increments @v by 1
* and returns true if the result is zero, or false for all * and returns true if the result is zero, or false for all
* other cases. Note that the guaranteed * other cases. Note that the guaranteed
* useful range of an atomic_t is only 24 bits. * useful range of an atomic_t is only 24 bits.
*/ */
static inline int atomic_inc_and_test(atomic_t volatile *v) static inline int atomic_inc_and_test(atomic_t volatile *v)
{ {
return (0 == InterlockedIncrement((PLONG)(&v->counter))); return (0 == InterlockedIncrement((PLONG)(&v->counter)));
} }
/** /**
* atomic_add_negative - add and test if negative * atomic_add_negative - add and test if negative
* @v: pointer of type atomic_t * @v: pointer of type atomic_t
* @i: integer value to add * @i: integer value to add
* *
* Atomically adds @i to @v and returns true * Atomically adds @i to @v and returns true
* if the result is negative, or false when * if the result is negative, or false when
* result is greater than or equal to zero. Note that the guaranteed * result is greater than or equal to zero. Note that the guaranteed
* useful range of an atomic_t is only 24 bits. * useful range of an atomic_t is only 24 bits.
*/ */
static inline int atomic_add_negative(int volatile i, atomic_t volatile *v) static inline int atomic_add_negative(int volatile i, atomic_t volatile *v)
{ {
return (InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) i) + i); return (InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) i) + i);
} }
#endif /* LINUX_ATOMIC_H */ #endif /* LINUX_ATOMIC_H */

View File

@@ -1,95 +1,95 @@
#ifndef __LINUX_BIT_SPINLOCK_H #ifndef __LINUX_BIT_SPINLOCK_H
#define __LINUX_BIT_SPINLOCK_H #define __LINUX_BIT_SPINLOCK_H
/* /*
* bit-based spin_lock() * bit-based spin_lock()
* *
* Don't use this unless you really need to: spin_lock() and spin_unlock() * Don't use this unless you really need to: spin_lock() and spin_unlock()
* are significantly faster. * are significantly faster.
*/ */
static inline void bit_spin_lock(int bitnum, unsigned long *addr) static inline void bit_spin_lock(int bitnum, unsigned long *addr)
{ {
/* /*
* Assuming the lock is uncontended, this never enters * Assuming the lock is uncontended, this never enters
* the body of the outer loop. If it is contended, then * the body of the outer loop. If it is contended, then
* within the inner loop a non-atomic test is used to * within the inner loop a non-atomic test is used to
* busywait with less bus contention for a good time to * busywait with less bus contention for a good time to
* attempt to acquire the lock bit. * attempt to acquire the lock bit.
*/ */
preempt_disable(); preempt_disable();
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
while (unlikely(test_and_set_bit_lock(bitnum, addr))) { while (unlikely(test_and_set_bit_lock(bitnum, addr))) {
while (test_bit(bitnum, addr)) { while (test_bit(bitnum, addr)) {
preempt_enable(); preempt_enable();
cpu_relax(); cpu_relax();
preempt_disable(); preempt_disable();
} }
} }
#endif #endif
__acquire(bitlock); __acquire(bitlock);
} }
/* /*
* Return true if it was acquired * Return true if it was acquired
*/ */
static inline int bit_spin_trylock(int bitnum, unsigned long *addr) static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
{ {
preempt_disable(); preempt_disable();
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
if (unlikely(test_and_set_bit_lock(bitnum, addr))) { if (unlikely(test_and_set_bit_lock(bitnum, addr))) {
preempt_enable(); preempt_enable();
return 0; return 0;
} }
#endif #endif
__acquire(bitlock); __acquire(bitlock);
return 1; return 1;
} }
/* /*
* bit-based spin_unlock() * bit-based spin_unlock()
*/ */
static inline void bit_spin_unlock(int bitnum, unsigned long *addr) static inline void bit_spin_unlock(int bitnum, unsigned long *addr)
{ {
#ifdef CONFIG_DEBUG_SPINLOCK #ifdef CONFIG_DEBUG_SPINLOCK
BUG_ON(!test_bit(bitnum, addr)); BUG_ON(!test_bit(bitnum, addr));
#endif #endif
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
clear_bit_unlock(bitnum, addr); clear_bit_unlock(bitnum, addr);
#endif #endif
preempt_enable(); preempt_enable();
__release(bitlock); __release(bitlock);
} }
/* /*
* bit-based spin_unlock() * bit-based spin_unlock()
* non-atomic version, which can be used eg. if the bit lock itself is * non-atomic version, which can be used eg. if the bit lock itself is
* protecting the rest of the flags in the word. * protecting the rest of the flags in the word.
*/ */
static inline void __bit_spin_unlock(int bitnum, unsigned long *addr) static inline void __bit_spin_unlock(int bitnum, unsigned long *addr)
{ {
#ifdef CONFIG_DEBUG_SPINLOCK #ifdef CONFIG_DEBUG_SPINLOCK
BUG_ON(!test_bit(bitnum, addr)); BUG_ON(!test_bit(bitnum, addr));
#endif #endif
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
__clear_bit_unlock(bitnum, addr); __clear_bit_unlock(bitnum, addr);
#endif #endif
preempt_enable(); preempt_enable();
__release(bitlock); __release(bitlock);
} }
/* /*
* Return true if the lock is held. * Return true if the lock is held.
*/ */
static inline int bit_spin_is_locked(int bitnum, unsigned long *addr) static inline int bit_spin_is_locked(int bitnum, unsigned long *addr)
{ {
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
return test_bit(bitnum, addr); return test_bit(bitnum, addr);
#elif defined CONFIG_PREEMPT #elif defined CONFIG_PREEMPT
return preempt_count(); return preempt_count();
#else #else
return 1; return 1;
#endif #endif
} }
#endif /* __LINUX_BIT_SPINLOCK_H */ #endif /* __LINUX_BIT_SPINLOCK_H */

View File

@@ -1,280 +1,280 @@
#ifndef _LINUX_BITOPS_H #ifndef _LINUX_BITOPS_H
#define _LINUX_BITOPS_H #define _LINUX_BITOPS_H
#include <ntifs.h> #include <ntifs.h>
#include <linux/types.h> #include <linux/types.h>
#ifdef __KERNEL__ #ifdef __KERNEL__
#define BIT(nr) (1 << (nr)) #define BIT(nr) (1 << (nr))
#define BIT_MASK(nr) (1 << ((nr) % BITS_PER_LONG)) #define BIT_MASK(nr) (1 << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) #define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG) #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG)
#define BITS_PER_BYTE 8 #define BITS_PER_BYTE 8
#endif #endif
/* /*
* Include this here because some architectures need generic_ffs/fls in * Include this here because some architectures need generic_ffs/fls in
* scope * scope
*/ */
/** /**
* find_first_zero_bit - find the first zero bit in a memory region * find_first_zero_bit - find the first zero bit in a memory region
* @addr: The address to start the search at * @addr: The address to start the search at
* @size: The maximum size to search * @size: The maximum size to search
* *
* Returns the bit number of the first zero bit, not the number of the byte * Returns the bit number of the first zero bit, not the number of the byte
* containing a bit. * containing a bit.
*/ */
#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) #define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
/** /**
* find_next_zero_bit - find the first zero bit in a memory region * find_next_zero_bit - find the first zero bit in a memory region
* @addr: The address to base the search on * @addr: The address to base the search on
* @offset: The bit number to start searching at * @offset: The bit number to start searching at
* @size: The maximum size to search * @size: The maximum size to search
*/ */
int find_next_zero_bit(const unsigned long *addr, int size, int offset); int find_next_zero_bit(const unsigned long *addr, int size, int offset);
/** /**
* __ffs - find first bit in word. * __ffs - find first bit in word.
* @word: The word to search * @word: The word to search
* *
* Undefined if no bit exists, so code should check against 0 first. * Undefined if no bit exists, so code should check against 0 first.
*/ */
static inline unsigned long __ffs(unsigned long word) static inline unsigned long __ffs(unsigned long word)
{ {
int num = 0; int num = 0;
#if BITS_PER_LONG == 64 #if BITS_PER_LONG == 64
if ((word & 0xffffffff) == 0) { if ((word & 0xffffffff) == 0) {
num += 32; num += 32;
word >>= 32; word >>= 32;
} }
#endif #endif
if ((word & 0xffff) == 0) { if ((word & 0xffff) == 0) {
num += 16; num += 16;
word >>= 16; word >>= 16;
} }
if ((word & 0xff) == 0) { if ((word & 0xff) == 0) {
num += 8; num += 8;
word >>= 8; word >>= 8;
} }
if ((word & 0xf) == 0) { if ((word & 0xf) == 0) {
num += 4; num += 4;
word >>= 4; word >>= 4;
} }
if ((word & 0x3) == 0) { if ((word & 0x3) == 0) {
num += 2; num += 2;
word >>= 2; word >>= 2;
} }
if ((word & 0x1) == 0) if ((word & 0x1) == 0)
num += 1; num += 1;
return num; return num;
} }
/** /**
* find_first_bit - find the first set bit in a memory region * find_first_bit - find the first set bit in a memory region
* @addr: The address to start the search at * @addr: The address to start the search at
* @size: The maximum size to search * @size: The maximum size to search
* *
* Returns the bit number of the first set bit, not the number of the byte * Returns the bit number of the first set bit, not the number of the byte
* containing a bit. * containing a bit.
*/ */
static inline unsigned find_first_bit(const unsigned long *addr, unsigned size) static inline unsigned find_first_bit(const unsigned long *addr, unsigned size)
{ {
unsigned x = 0; unsigned x = 0;
while (x < size) { while (x < size) {
unsigned long val = *addr++; unsigned long val = *addr++;
if (val) if (val)
return __ffs(val) + x; return __ffs(val) + x;
x += (sizeof(*addr)<<3); x += (sizeof(*addr)<<3);
} }
return x; return x;
} }
/** /**
* find_next_bit - find the next set bit in a memory region * find_next_bit - find the next set bit in a memory region
* @addr: The address to base the search on * @addr: The address to base the search on
* @offset: The bitnumber to start searching at * @offset: The bitnumber to start searching at
* @size: The maximum size to search * @size: The maximum size to search
*/ */
/* /*
* ffz - find first zero in word. * ffz - find first zero in word.
* @word: The word to search * @word: The word to search
* *
* Undefined if no zero exists, so code should check against ~0UL first. * Undefined if no zero exists, so code should check against ~0UL first.
*/ */
#define ffz(x) __ffs(~(x)) #define ffz(x) __ffs(~(x))
/** /**
* ffs - find first bit set * ffs - find first bit set
* @x: the word to search * @x: the word to search
* *
* This is defined the same way as * This is defined the same way as
* the libc and compiler builtin ffs routines, therefore * the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs). * differs in spirit from the above ffz (man ffs).
*/ */
static inline int ffs(int x) static inline int ffs(int x)
{ {
int r = 1; int r = 1;
if (!x) if (!x)
return 0; return 0;
if (!(x & 0xffff)) { if (!(x & 0xffff)) {
x >>= 16; x >>= 16;
r += 16; r += 16;
} }
if (!(x & 0xff)) { if (!(x & 0xff)) {
x >>= 8; x >>= 8;
r += 8; r += 8;
} }
if (!(x & 0xf)) { if (!(x & 0xf)) {
x >>= 4; x >>= 4;
r += 4; r += 4;
} }
if (!(x & 3)) { if (!(x & 3)) {
x >>= 2; x >>= 2;
r += 2; r += 2;
} }
if (!(x & 1)) { if (!(x & 1)) {
x >>= 1; x >>= 1;
r += 1; r += 1;
} }
return r; return r;
} }
/** /**
* fls - find last (most-significant) bit set * fls - find last (most-significant) bit set
* @x: the word to search * @x: the word to search
* *
* This is defined the same way as ffs. * This is defined the same way as ffs.
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/ */
static inline int fls(int x) static inline int fls(int x)
{ {
int r = 32; int r = 32;
if (!x) if (!x)
return 0; return 0;
if (!(x & 0xffff0000u)) { if (!(x & 0xffff0000u)) {
x <<= 16; x <<= 16;
r -= 16; r -= 16;
} }
if (!(x & 0xff000000u)) { if (!(x & 0xff000000u)) {
x <<= 8; x <<= 8;
r -= 8; r -= 8;
} }
if (!(x & 0xf0000000u)) { if (!(x & 0xf0000000u)) {
x <<= 4; x <<= 4;
r -= 4; r -= 4;
} }
if (!(x & 0xc0000000u)) { if (!(x & 0xc0000000u)) {
x <<= 2; x <<= 2;
r -= 2; r -= 2;
} }
if (!(x & 0x80000000u)) { if (!(x & 0x80000000u)) {
x <<= 1; x <<= 1;
r -= 1; r -= 1;
} }
return r; return r;
} }
static inline int fls64(__u64 x) static inline int fls64(__u64 x)
{ {
__u32 h = (__u32) (x >> 32); __u32 h = (__u32) (x >> 32);
if (h) if (h)
return fls(h) + 32; return fls(h) + 32;
return fls((int)x); return fls((int)x);
} }
#define for_each_bit(bit, addr, size) \ #define for_each_bit(bit, addr, size) \
for ((bit) = find_first_bit((addr), (size)); \ for ((bit) = find_first_bit((addr), (size)); \
(bit) < (size); \ (bit) < (size); \
(bit) = find_next_bit((addr), (size), (bit) + 1)) (bit) = find_next_bit((addr), (size), (bit) + 1))
static __inline int get_bitmask_order(unsigned int count) static __inline int get_bitmask_order(unsigned int count)
{ {
int order; int order;
order = fls(count); order = fls(count);
return order; /* We could be slightly more clever with -1 here... */ return order; /* We could be slightly more clever with -1 here... */
} }
static __inline int get_count_order(unsigned int count) static __inline int get_count_order(unsigned int count)
{ {
int order; int order;
order = fls(count) - 1; order = fls(count) - 1;
if (count & (count - 1)) if (count & (count - 1))
order++; order++;
return order; return order;
} }
/** /**
* rol32 - rotate a 32-bit value left * rol32 - rotate a 32-bit value left
* @word: value to rotate * @word: value to rotate
* @shift: bits to roll * @shift: bits to roll
*/ */
static inline __u32 rol32(__u32 word, unsigned int shift) static inline __u32 rol32(__u32 word, unsigned int shift)
{ {
return (word << shift) | (word >> (32 - shift)); return (word << shift) | (word >> (32 - shift));
} }
/** /**
* ror32 - rotate a 32-bit value right * ror32 - rotate a 32-bit value right
* @word: value to rotate * @word: value to rotate
* @shift: bits to roll * @shift: bits to roll
*/ */
static inline __u32 ror32(__u32 word, unsigned int shift) static inline __u32 ror32(__u32 word, unsigned int shift)
{ {
return (word >> shift) | (word << (32 - shift)); return (word >> shift) | (word << (32 - shift));
} }
static inline unsigned fls_long(unsigned long l) static inline unsigned fls_long(unsigned long l)
{ {
if (sizeof(l) == 4) if (sizeof(l) == 4)
return fls(l); return fls(l);
return fls64(l); return fls64(l);
} }
/* /*
* hweightN: returns the hamming weight (i.e. the number * hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word * of bits set) of a N-bit word
*/ */
static inline unsigned long hweight32(unsigned long w) static inline unsigned long hweight32(unsigned long w)
{ {
unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
res = (res & 0x33333333) + ((res >> 2) & 0x33333333); res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
} }
static inline unsigned long hweight64(__u64 w) static inline unsigned long hweight64(__u64 w)
{ {
#if BITS_PER_LONG < 64 #if BITS_PER_LONG < 64
return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w); return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w);
#else #else
u64 res; u64 res;
res = (w & 0x5555555555555555U) + ((w >> 1) & 0x5555555555555555U); res = (w & 0x5555555555555555U) + ((w >> 1) & 0x5555555555555555U);
res = (res & 0x3333333333333333U) + ((res >> 2) & 0x3333333333333333U); res = (res & 0x3333333333333333U) + ((res >> 2) & 0x3333333333333333U);
res = (res & 0x0F0F0F0F0F0F0F0FU) + ((res >> 4) & 0x0F0F0F0F0F0F0F0FU); res = (res & 0x0F0F0F0F0F0F0F0FU) + ((res >> 4) & 0x0F0F0F0F0F0F0F0FU);
res = (res & 0x00FF00FF00FF00FFU) + ((res >> 8) & 0x00FF00FF00FF00FFU); res = (res & 0x00FF00FF00FF00FFU) + ((res >> 8) & 0x00FF00FF00FF00FFU);
res = (res & 0x0000FFFF0000FFFFU) + ((res >> 16) & 0x0000FFFF0000FFFFU); res = (res & 0x0000FFFF0000FFFFU) + ((res >> 16) & 0x0000FFFF0000FFFFU);
return (res & 0x00000000FFFFFFFFU) + ((res >> 32) & 0x00000000FFFFFFFFU); return (res & 0x00000000FFFFFFFFU) + ((res >> 32) & 0x00000000FFFFFFFFU);
#endif #endif
} }
static inline unsigned long hweight_long(unsigned long w) static inline unsigned long hweight_long(unsigned long w)
{ {
return sizeof(w) == 4 ? hweight32(w) : hweight64(w); return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
} }
#endif #endif

View File

@@ -1,7 +1,7 @@
#ifndef LINUX_CONFIG_H #ifndef LINUX_CONFIG_H
#define LINUX_CONFIG_H #define LINUX_CONFIG_H
#define EXT2_HTREE_INDEX 1 #define EXT2_HTREE_INDEX 1
//#undef EXT2_HTREE_INDEX //#undef EXT2_HTREE_INDEX
#endif /* LINUX_CONFIG_H */ #endif /* LINUX_CONFIG_H */

View File

@@ -1,147 +1,147 @@
#ifndef _I386_ERRNO_H #ifndef _I386_ERRNO_H
#define _I386_ERRNO_H #define _I386_ERRNO_H
#include <errno.h> #include <errno.h>
#define EPERM 1 /* Operation not permitted */ #define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */ #define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */ #define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */ #define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */ #define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */ #define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Arg list too long */ #define E2BIG 7 /* Arg list too long */
#define ENOEXEC 8 /* Exec format error */ #define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */ #define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */ #define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */ #define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */ #define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */ #define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */ #define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */ #define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */ #define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */ #define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */ #define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */ #define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */ #define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */ #define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */ #define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */ #define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */ #define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */ #define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */ #define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */ #define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */ #define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */ #define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */ #define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */ #define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */ #define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */ #define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */ #define ERANGE 34 /* Math result not representable */
#define ELOOP 40 /* Too many symbolic links encountered */ #define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */ #define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG 42 /* No message of desired type */ #define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */ #define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */ #define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */ #define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */ #define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */ #define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */ #define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */ #define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */ #define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */ #define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */ #define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */ #define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */ #define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */ #define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */ #define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */ #define EBADSLT 57 /* Invalid slot */
#define EDEADLOCK EDEADLK #define EDEADLOCK EDEADLK
#define EBFONT 59 /* Bad font file format */ #define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */ #define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */ #define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */ #define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */ #define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */ #define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */ #define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */ #define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */ #define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */ #define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */ #define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */ #define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */ #define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */ #define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */ #define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */ #define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */ #define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */ #define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */ #define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */ #define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */ #define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */ #define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */ #define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ #define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */ #define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define ERESTART 85 /* Interrupted system call should be restarted */ #define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */ #define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */ #define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */ #define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */ #define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */ #define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */ #define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */ #define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */ #define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ #define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */ #define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ #define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */ #define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ #define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */ #define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */ #define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */ #define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */ #define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */ #define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */ #define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */ #define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */ #define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ #define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */ #define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */ #define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */ #define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */ #define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */ #define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */ #define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */ #define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale NFS file handle */ #define ESTALE 116 /* Stale NFS file handle */
#define EUCLEAN 117 /* Structure needs cleaning */ #define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */ #define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */ #define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */ #define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */ #define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */ #define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* No medium found */ #define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */ #define EMEDIUMTYPE 124 /* Wrong medium type */
/* Should never be seen by user programs */ /* Should never be seen by user programs */
#define ERESTARTSYS 512 #define ERESTARTSYS 512
#define ERESTARTNOINTR 513 #define ERESTARTNOINTR 513
#define ERESTARTNOHAND 514 /* restart if no handler.. */ #define ERESTARTNOHAND 514 /* restart if no handler.. */
#define ENOIOCTLCMD 515 /* No ioctl command */ #define ENOIOCTLCMD 515 /* No ioctl command */
/* Defined for the NFSv3 protocol */ /* Defined for the NFSv3 protocol */
#define EBADHANDLE 521 /* Illegal NFS file handle */ #define EBADHANDLE 521 /* Illegal NFS file handle */
#define ENOTSYNC 522 /* Update synchronization mismatch */ #define ENOTSYNC 522 /* Update synchronization mismatch */
#define EBADCOOKIE 523 /* Cookie is stale */ #define EBADCOOKIE 523 /* Cookie is stale */
#define ENOTSUPP 524 /* Operation is not supported */ #define ENOTSUPP 524 /* Operation is not supported */
#define ETOOSMALL 525 /* Buffer or request is too small */ #define ETOOSMALL 525 /* Buffer or request is too small */
#define ESERVERFAULT 526 /* An untranslatable error occurred */ #define ESERVERFAULT 526 /* An untranslatable error occurred */
#define EBADTYPE 527 /* Type not supported by server */ #define EBADTYPE 527 /* Type not supported by server */
#define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */ #define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */
#if _MSC_VER > 1900 #if _MSC_VER > 1900
#define ENAMETOOLONG 1024; #define ENAMETOOLONG 1024;
#endif #endif
#endif #endif

View File

@@ -1,257 +1,257 @@
#ifndef _LINUX_EXT4_EXT #ifndef _LINUX_EXT4_EXT
#define _LINUX_EXT4_EXT #define _LINUX_EXT4_EXT
/* /*
* This is the extent tail on-disk structure. * This is the extent tail on-disk structure.
* All other extent structures are 12 bytes long. It turns out that * All other extent structures are 12 bytes long. It turns out that
* block_size % 12 >= 4 for at least all powers of 2 greater than 512, which * block_size % 12 >= 4 for at least all powers of 2 greater than 512, which
* covers all valid ext4 block sizes. Therefore, this tail structure can be * covers all valid ext4 block sizes. Therefore, this tail structure can be
* crammed into the end of the block without having to rebalance the tree. * crammed into the end of the block without having to rebalance the tree.
*/ */
struct ext4_extent_tail { struct ext4_extent_tail {
uint32_t et_checksum; /* crc32c(uuid+inum+extent_block) */ uint32_t et_checksum; /* crc32c(uuid+inum+extent_block) */
}; };
/* /*
* This is the extent on-disk structure. * This is the extent on-disk structure.
* It's used at the bottom of the tree. * It's used at the bottom of the tree.
*/ */
typedef struct ext4_extent { typedef struct ext4_extent {
uint32_t ee_block; /* first logical block extent covers */ uint32_t ee_block; /* first logical block extent covers */
uint16_t ee_len; /* number of blocks covered by extent */ uint16_t ee_len; /* number of blocks covered by extent */
uint16_t ee_start_hi; /* high 16 bits of physical block */ uint16_t ee_start_hi; /* high 16 bits of physical block */
uint32_t ee_start_lo; /* low 32 bits of physical block */ uint32_t ee_start_lo; /* low 32 bits of physical block */
} __attribute__ ((__packed__)) EXT4_EXTENT; } __attribute__ ((__packed__)) EXT4_EXTENT;
/* /*
* This is index on-disk structure. * This is index on-disk structure.
* It's used at all the levels except the bottom. * It's used at all the levels except the bottom.
*/ */
typedef struct ext4_extent_idx { typedef struct ext4_extent_idx {
uint32_t ei_block; /* index covers logical blocks from 'block' */ uint32_t ei_block; /* index covers logical blocks from 'block' */
uint32_t ei_leaf_lo; /* pointer to the physical block of the next * uint32_t ei_leaf_lo; /* pointer to the physical block of the next *
* level. leaf or next index could be there */ * level. leaf or next index could be there */
uint16_t ei_leaf_hi; /* high 16 bits of physical block */ uint16_t ei_leaf_hi; /* high 16 bits of physical block */
uint16_t ei_unused; uint16_t ei_unused;
}__attribute__ ((__packed__)) EXT4_EXTENT_IDX; }__attribute__ ((__packed__)) EXT4_EXTENT_IDX;
/* /*
* Each block (leaves and indexes), even inode-stored has header. * Each block (leaves and indexes), even inode-stored has header.
*/ */
typedef struct ext4_extent_header { typedef struct ext4_extent_header {
uint16_t eh_magic; /* probably will support different formats */ uint16_t eh_magic; /* probably will support different formats */
uint16_t eh_entries; /* number of valid entries */ uint16_t eh_entries; /* number of valid entries */
uint16_t eh_max; /* capacity of store in entries */ uint16_t eh_max; /* capacity of store in entries */
uint16_t eh_depth; /* has tree real underlying blocks? */ uint16_t eh_depth; /* has tree real underlying blocks? */
uint32_t eh_generation; /* generation of the tree */ uint32_t eh_generation; /* generation of the tree */
}__attribute__ ((__packed__)) EXT4_EXTENT_HEADER; }__attribute__ ((__packed__)) EXT4_EXTENT_HEADER;
#define EXT4_EXT_MAGIC 0xf30a #define EXT4_EXT_MAGIC 0xf30a
#define get_ext4_header(i) ((struct ext4_extent_header *) (i)->i_block) #define get_ext4_header(i) ((struct ext4_extent_header *) (i)->i_block)
#define EXT4_EXTENT_TAIL_OFFSET(hdr) \ #define EXT4_EXTENT_TAIL_OFFSET(hdr) \
(sizeof(struct ext4_extent_header) + \ (sizeof(struct ext4_extent_header) + \
(sizeof(struct ext4_extent) * (hdr)->eh_max)) (sizeof(struct ext4_extent) * (hdr)->eh_max))
static inline struct ext4_extent_tail * static inline struct ext4_extent_tail *
find_ext4_extent_tail(struct ext4_extent_header *eh) find_ext4_extent_tail(struct ext4_extent_header *eh)
{ {
return (struct ext4_extent_tail *)(((char *)eh) + return (struct ext4_extent_tail *)(((char *)eh) +
EXT4_EXTENT_TAIL_OFFSET(eh)); EXT4_EXTENT_TAIL_OFFSET(eh));
} }
/* /*
* Array of ext4_ext_path contains path to some extent. * Array of ext4_ext_path contains path to some extent.
* Creation/lookup routines use it for traversal/splitting/etc. * Creation/lookup routines use it for traversal/splitting/etc.
* Truncate uses it to simulate recursive walking. * Truncate uses it to simulate recursive walking.
*/ */
struct ext4_ext_path struct ext4_ext_path
{ {
ext4_fsblk_t p_block; ext4_fsblk_t p_block;
int p_depth; int p_depth;
int p_maxdepth; int p_maxdepth;
struct ext4_extent *p_ext; struct ext4_extent *p_ext;
struct ext4_extent_idx *p_idx; struct ext4_extent_idx *p_idx;
struct ext4_extent_header *p_hdr; struct ext4_extent_header *p_hdr;
struct buffer_head *p_bh; struct buffer_head *p_bh;
}; };
/* /*
* structure for external API * structure for external API
*/ */
/* /*
* EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
* initialized extent. This is 2^15 and not (2^16 - 1), since we use the * initialized extent. This is 2^15 and not (2^16 - 1), since we use the
* MSB of ee_len field in the extent datastructure to signify if this * MSB of ee_len field in the extent datastructure to signify if this
* particular extent is an initialized extent or an uninitialized (i.e. * particular extent is an initialized extent or an uninitialized (i.e.
* preallocated). * preallocated).
* EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an * EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an
* uninitialized extent. * uninitialized extent.
* If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an * If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an
* uninitialized one. In other words, if MSB of ee_len is set, it is an * uninitialized one. In other words, if MSB of ee_len is set, it is an
* uninitialized extent with only one special scenario when ee_len = 0x8000. * uninitialized extent with only one special scenario when ee_len = 0x8000.
* In this case we can not have an uninitialized extent of zero length and * In this case we can not have an uninitialized extent of zero length and
* thus we make it as a special case of initialized extent with 0x8000 length. * thus we make it as a special case of initialized extent with 0x8000 length.
* This way we get better extent-to-group alignment for initialized extents. * This way we get better extent-to-group alignment for initialized extents.
* Hence, the maximum number of blocks we can have in an *initialized* * Hence, the maximum number of blocks we can have in an *initialized*
* extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767). * extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767).
*/ */
#define EXT_INIT_MAX_LEN (1UL << 15) #define EXT_INIT_MAX_LEN (1UL << 15)
#define EXT_UNWRITTEN_MAX_LEN (EXT_INIT_MAX_LEN - 1) #define EXT_UNWRITTEN_MAX_LEN (EXT_INIT_MAX_LEN - 1)
#define EXT_EXTENT_SIZE sizeof(struct ext4_extent) #define EXT_EXTENT_SIZE sizeof(struct ext4_extent)
#define EXT_INDEX_SIZE sizeof(struct ext4_extent_idx) #define EXT_INDEX_SIZE sizeof(struct ext4_extent_idx)
#define EXT_FIRST_EXTENT(__hdr__) \ #define EXT_FIRST_EXTENT(__hdr__) \
((struct ext4_extent *)(((char *)(__hdr__)) + \ ((struct ext4_extent *)(((char *)(__hdr__)) + \
sizeof(struct ext4_extent_header))) sizeof(struct ext4_extent_header)))
#define EXT_FIRST_INDEX(__hdr__) \ #define EXT_FIRST_INDEX(__hdr__) \
((struct ext4_extent_idx *)(((char *)(__hdr__)) + \ ((struct ext4_extent_idx *)(((char *)(__hdr__)) + \
sizeof(struct ext4_extent_header))) sizeof(struct ext4_extent_header)))
#define EXT_HAS_FREE_INDEX(__path__) \ #define EXT_HAS_FREE_INDEX(__path__) \
((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max) ((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max)
#define EXT_LAST_EXTENT(__hdr__) \ #define EXT_LAST_EXTENT(__hdr__) \
(EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1) (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1)
#define EXT_LAST_INDEX(__hdr__) \ #define EXT_LAST_INDEX(__hdr__) \
(EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1) (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1)
#define EXT_MAX_EXTENT(__hdr__) \ #define EXT_MAX_EXTENT(__hdr__) \
(EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1) (EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
#define EXT_MAX_INDEX(__hdr__) \ #define EXT_MAX_INDEX(__hdr__) \
(EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1) (EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode) static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode)
{ {
return get_ext4_header(inode); return get_ext4_header(inode);
} }
static inline struct ext4_extent_header *ext_block_hdr(struct buffer_head *bh) static inline struct ext4_extent_header *ext_block_hdr(struct buffer_head *bh)
{ {
return (struct ext4_extent_header *)bh->b_data; return (struct ext4_extent_header *)bh->b_data;
} }
static inline unsigned short ext_depth(struct inode *inode) static inline unsigned short ext_depth(struct inode *inode)
{ {
return ext_inode_hdr(inode)->eh_depth; return ext_inode_hdr(inode)->eh_depth;
} }
static inline void ext4_ext_mark_uninitialized(struct ext4_extent *ext) static inline void ext4_ext_mark_uninitialized(struct ext4_extent *ext)
{ {
/* We can not have an uninitialized extent of zero length! */ /* We can not have an uninitialized extent of zero length! */
ext->ee_len |= EXT_INIT_MAX_LEN; ext->ee_len |= EXT_INIT_MAX_LEN;
} }
static inline int ext4_ext_is_uninitialized(struct ext4_extent *ext) static inline int ext4_ext_is_uninitialized(struct ext4_extent *ext)
{ {
/* Extent with ee_len of 0x8000 is treated as an initialized extent */ /* Extent with ee_len of 0x8000 is treated as an initialized extent */
return (ext->ee_len > EXT_INIT_MAX_LEN); return (ext->ee_len > EXT_INIT_MAX_LEN);
} }
static inline uint16_t ext4_ext_get_actual_len(struct ext4_extent *ext) static inline uint16_t ext4_ext_get_actual_len(struct ext4_extent *ext)
{ {
return (ext->ee_len <= EXT_INIT_MAX_LEN return (ext->ee_len <= EXT_INIT_MAX_LEN
? ext->ee_len ? ext->ee_len
: (ext->ee_len - EXT_INIT_MAX_LEN)); : (ext->ee_len - EXT_INIT_MAX_LEN));
} }
static inline void ext4_ext_mark_initialized(struct ext4_extent *ext) static inline void ext4_ext_mark_initialized(struct ext4_extent *ext)
{ {
ext->ee_len = ext4_ext_get_actual_len(ext); ext->ee_len = ext4_ext_get_actual_len(ext);
} }
static inline void ext4_ext_mark_unwritten(struct ext4_extent *ext) static inline void ext4_ext_mark_unwritten(struct ext4_extent *ext)
{ {
/* We can not have an unwritten extent of zero length! */ /* We can not have an unwritten extent of zero length! */
ext->ee_len |= EXT_INIT_MAX_LEN; ext->ee_len |= EXT_INIT_MAX_LEN;
} }
static inline int ext4_ext_is_unwritten(struct ext4_extent *ext) static inline int ext4_ext_is_unwritten(struct ext4_extent *ext)
{ {
/* Extent with ee_len of 0x8000 is treated as an initialized extent */ /* Extent with ee_len of 0x8000 is treated as an initialized extent */
return (ext->ee_len > EXT_INIT_MAX_LEN); return (ext->ee_len > EXT_INIT_MAX_LEN);
} }
/* /*
* ext4_ext_pblock: * ext4_ext_pblock:
* combine low and high parts of physical block number into ext4_fsblk_t * combine low and high parts of physical block number into ext4_fsblk_t
*/ */
static inline ext4_fsblk_t ext4_ext_pblock(struct ext4_extent *ex) static inline ext4_fsblk_t ext4_ext_pblock(struct ext4_extent *ex)
{ {
ext4_fsblk_t block; ext4_fsblk_t block;
block = ex->ee_start_lo; block = ex->ee_start_lo;
block |= ((ext4_fsblk_t)ex->ee_start_hi << 31) << 1; block |= ((ext4_fsblk_t)ex->ee_start_hi << 31) << 1;
return block; return block;
} }
/* /*
* ext4_idx_pblock: * ext4_idx_pblock:
* combine low and high parts of a leaf physical block number into ext4_fsblk_t * combine low and high parts of a leaf physical block number into ext4_fsblk_t
*/ */
static inline ext4_fsblk_t ext4_idx_pblock(struct ext4_extent_idx *ix) static inline ext4_fsblk_t ext4_idx_pblock(struct ext4_extent_idx *ix)
{ {
ext4_fsblk_t block; ext4_fsblk_t block;
block = ix->ei_leaf_lo; block = ix->ei_leaf_lo;
block |= ((ext4_fsblk_t)ix->ei_leaf_hi << 31) << 1; block |= ((ext4_fsblk_t)ix->ei_leaf_hi << 31) << 1;
return block; return block;
} }
/* /*
* ext4_ext_store_pblock: * ext4_ext_store_pblock:
* stores a large physical block number into an extent struct, * stores a large physical block number into an extent struct,
* breaking it into parts * breaking it into parts
*/ */
static inline void ext4_ext_store_pblock(struct ext4_extent *ex, static inline void ext4_ext_store_pblock(struct ext4_extent *ex,
ext4_fsblk_t pb) ext4_fsblk_t pb)
{ {
ex->ee_start_lo = (uint32_t)(pb & 0xffffffff); ex->ee_start_lo = (uint32_t)(pb & 0xffffffff);
ex->ee_start_hi = (uint16_t)((pb >> 31) >> 1) & 0xffff; ex->ee_start_hi = (uint16_t)((pb >> 31) >> 1) & 0xffff;
} }
/* /*
* ext4_idx_store_pblock: * ext4_idx_store_pblock:
* stores a large physical block number into an index struct, * stores a large physical block number into an index struct,
* breaking it into parts * breaking it into parts
*/ */
static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix, static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix,
ext4_fsblk_t pb) ext4_fsblk_t pb)
{ {
ix->ei_leaf_lo = (uint32_t)(pb & 0xffffffff); ix->ei_leaf_lo = (uint32_t)(pb & 0xffffffff);
ix->ei_leaf_hi = (uint16_t)((pb >> 31) >> 1) & 0xffff; ix->ei_leaf_hi = (uint16_t)((pb >> 31) >> 1) & 0xffff;
} }
#define ext4_ext_dirty(icb, handle, inode, path) \ #define ext4_ext_dirty(icb, handle, inode, path) \
__ext4_ext_dirty("", __LINE__, (icb), (handle), (inode), (path)) __ext4_ext_dirty("", __LINE__, (icb), (handle), (inode), (path))
#define INODE_HAS_EXTENT(i) ((i)->i_flags & EXT2_EXTENTS_FL) #define INODE_HAS_EXTENT(i) ((i)->i_flags & EXT2_EXTENTS_FL)
static inline uint64_t ext_to_block(EXT4_EXTENT *extent) static inline uint64_t ext_to_block(EXT4_EXTENT *extent)
{ {
uint64_t block; uint64_t block;
block = (uint64_t)extent->ee_start_lo; block = (uint64_t)extent->ee_start_lo;
block |= ((uint64_t) extent->ee_start_hi << 31) << 1; block |= ((uint64_t) extent->ee_start_hi << 31) << 1;
return block; return block;
} }
static inline uint64_t idx_to_block(EXT4_EXTENT_IDX *idx) static inline uint64_t idx_to_block(EXT4_EXTENT_IDX *idx)
{ {
uint64_t block; uint64_t block;
block = (uint64_t)idx->ei_leaf_lo; block = (uint64_t)idx->ei_leaf_lo;
block |= ((uint64_t) idx->ei_leaf_hi << 31) << 1; block |= ((uint64_t) idx->ei_leaf_hi << 31) << 1;
return block; return block;
} }
int ext4_ext_get_blocks(void *icb, handle_t *handle, struct inode *inode, ext4_fsblk_t iblock, int ext4_ext_get_blocks(void *icb, handle_t *handle, struct inode *inode, ext4_fsblk_t iblock,
unsigned long max_blocks, struct buffer_head *bh_result, unsigned long max_blocks, struct buffer_head *bh_result,
int create, int flags); int create, int flags);
int ext4_ext_tree_init(void *icb, handle_t *handle, struct inode *inode); int ext4_ext_tree_init(void *icb, handle_t *handle, struct inode *inode);
int ext4_ext_truncate(void *icb, struct inode *inode, unsigned long start); int ext4_ext_truncate(void *icb, struct inode *inode, unsigned long start);
#endif /* _LINUX_EXT4_EXT */ #endif /* _LINUX_EXT4_EXT */

View File

@@ -1,65 +1,65 @@
#ifndef _EXT4_JBD2_H #ifndef _EXT4_JBD2_H
#define _EXT4_JBD2_H #define _EXT4_JBD2_H
/* /*
* Wrapper functions with which ext4 calls into JBD. * Wrapper functions with which ext4 calls into JBD.
*/ */
void ext4_journal_abort_handle(const char *caller, unsigned int line, void ext4_journal_abort_handle(const char *caller, unsigned int line,
const char *err_fn, struct buffer_head *bh, const char *err_fn, struct buffer_head *bh,
handle_t *handle, int err); handle_t *handle, int err);
int __ext4_handle_dirty_super(const char *where, unsigned int line, int __ext4_handle_dirty_super(const char *where, unsigned int line,
handle_t *handle, struct super_block *sb); handle_t *handle, struct super_block *sb);
int __ext4_journal_get_write_access(const char *where, unsigned int line, int __ext4_journal_get_write_access(const char *where, unsigned int line,
void *icb, handle_t *handle, struct buffer_head *bh); void *icb, handle_t *handle, struct buffer_head *bh);
int __ext4_forget(const char *where, unsigned int line, void *icb, handle_t *handle, int __ext4_forget(const char *where, unsigned int line, void *icb, handle_t *handle,
int is_metadata, struct inode *inode, int is_metadata, struct inode *inode,
struct buffer_head *bh, ext4_fsblk_t blocknr); struct buffer_head *bh, ext4_fsblk_t blocknr);
int __ext4_journal_get_create_access(const char *where, unsigned int line, int __ext4_journal_get_create_access(const char *where, unsigned int line,
void *icb, handle_t *handle, struct buffer_head *bh); void *icb, handle_t *handle, struct buffer_head *bh);
int __ext4_handle_dirty_metadata(const char *where, unsigned int line, int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
void *icb, handle_t *handle, struct inode *inode, void *icb, handle_t *handle, struct inode *inode,
struct buffer_head *bh); struct buffer_head *bh);
#define ext4_journal_get_write_access(handle, icb, bh) \ #define ext4_journal_get_write_access(handle, icb, bh) \
__ext4_journal_get_write_access("", __LINE__, (icb), (handle), (bh)) __ext4_journal_get_write_access("", __LINE__, (icb), (handle), (bh))
#define ext4_forget(handle, icb, is_metadata, inode, bh, block_nr) \ #define ext4_forget(handle, icb, is_metadata, inode, bh, block_nr) \
__ext4_forget("", __LINE__, (icb), (handle), (is_metadata), (inode), \ __ext4_forget("", __LINE__, (icb), (handle), (is_metadata), (inode), \
(bh), (block_nr)) (bh), (block_nr))
#define ext4_journal_get_create_access(handle, icb, bh) \ #define ext4_journal_get_create_access(handle, icb, bh) \
__ext4_journal_get_create_access("", __LINE__, (icb), (handle), (bh)) __ext4_journal_get_create_access("", __LINE__, (icb), (handle), (bh))
#define ext4_handle_dirty_metadata(handle, icb, inode, bh) \ #define ext4_handle_dirty_metadata(handle, icb, inode, bh) \
__ext4_handle_dirty_metadata("", __LINE__, (icb), (handle), (inode), \ __ext4_handle_dirty_metadata("", __LINE__, (icb), (handle), (inode), \
(bh)) (bh))
handle_t *__ext4_journal_start_sb(void *icb, struct super_block *sb, unsigned int line, handle_t *__ext4_journal_start_sb(void *icb, struct super_block *sb, unsigned int line,
int type, int blocks, int rsv_blocks); int type, int blocks, int rsv_blocks);
int __ext4_journal_stop(const char *where, unsigned int line, void *icb, handle_t *handle); int __ext4_journal_stop(const char *where, unsigned int line, void *icb, handle_t *handle);
#define ext4_journal_start_sb(icb, sb, type, nblocks) \ #define ext4_journal_start_sb(icb, sb, type, nblocks) \
__ext4_journal_start_sb((icb), (sb), __LINE__, (type), (nblocks), 0) __ext4_journal_start_sb((icb), (sb), __LINE__, (type), (nblocks), 0)
#define ext4_journal_start(icb, inode, type, nblocks) \ #define ext4_journal_start(icb, inode, type, nblocks) \
__ext4_journal_start((icb), (inode), __LINE__, (type), (nblocks), 0) __ext4_journal_start((icb), (inode), __LINE__, (type), (nblocks), 0)
static inline handle_t *__ext4_journal_start(void *icb, struct inode *inode, static inline handle_t *__ext4_journal_start(void *icb, struct inode *inode,
unsigned int line, int type, unsigned int line, int type,
int blocks, int rsv_blocks) int blocks, int rsv_blocks)
{ {
return __ext4_journal_start_sb(icb, inode->i_sb, line, type, blocks, return __ext4_journal_start_sb(icb, inode->i_sb, line, type, blocks,
rsv_blocks); rsv_blocks);
} }
#define ext4_journal_stop(icb, handle) \ #define ext4_journal_stop(icb, handle) \
__ext4_journal_stop("", __LINE__, (icb), (handle)) __ext4_journal_stop("", __LINE__, (icb), (handle))
static inline int ext4_journal_extend(void *icb, handle_t *handle, int nblocks) static inline int ext4_journal_extend(void *icb, handle_t *handle, int nblocks)
{ {
return 0; return 0;
} }
#endif #endif

View File

@@ -1,205 +1,205 @@
/* /*
* Copyright (c) 2015 Grzegorz Kostka (kostka.grzegorz@gmail.com) * Copyright (c) 2015 Grzegorz Kostka (kostka.grzegorz@gmail.com)
* Copyright (c) 2015 Kaho Ng (ngkaho1234@gmail.com) * Copyright (c) 2015 Kaho Ng (ngkaho1234@gmail.com)
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* *
* - Redistributions of source code must retain the above copyright * - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright * - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products * - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/** @addtogroup lwext4 /** @addtogroup lwext4
* @{ * @{
*/ */
/** /**
* @file ext4_xattr.h * @file ext4_xattr.h
* @brief Extended Attribute manipulation. * @brief Extended Attribute manipulation.
*/ */
#ifndef EXT4_XATTR_H_ #ifndef EXT4_XATTR_H_
#define EXT4_XATTR_H_ #define EXT4_XATTR_H_
#include <ext2fs.h> #include <ext2fs.h>
#include <linux/rbtree.h> #include <linux/rbtree.h>
/* Extended Attribute(EA) */ /* Extended Attribute(EA) */
/* Magic value in attribute blocks */ /* Magic value in attribute blocks */
#define EXT4_XATTR_MAGIC 0xEA020000 #define EXT4_XATTR_MAGIC 0xEA020000
/* Maximum number of references to one attribute block */ /* Maximum number of references to one attribute block */
#define EXT4_XATTR_REFCOUNT_MAX 1024 #define EXT4_XATTR_REFCOUNT_MAX 1024
/* Name indexes */ /* Name indexes */
#define EXT4_XATTR_INDEX_USER 1 #define EXT4_XATTR_INDEX_USER 1
#define EXT4_XATTR_INDEX_POSIX_ACL_ACCESS 2 #define EXT4_XATTR_INDEX_POSIX_ACL_ACCESS 2
#define EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT 3 #define EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT 3
#define EXT4_XATTR_INDEX_TRUSTED 4 #define EXT4_XATTR_INDEX_TRUSTED 4
#define EXT4_XATTR_INDEX_LUSTRE 5 #define EXT4_XATTR_INDEX_LUSTRE 5
#define EXT4_XATTR_INDEX_SECURITY 6 #define EXT4_XATTR_INDEX_SECURITY 6
#define EXT4_XATTR_INDEX_SYSTEM 7 #define EXT4_XATTR_INDEX_SYSTEM 7
#define EXT4_XATTR_INDEX_RICHACL 8 #define EXT4_XATTR_INDEX_RICHACL 8
#define EXT4_XATTR_INDEX_ENCRYPTION 9 #define EXT4_XATTR_INDEX_ENCRYPTION 9
#pragma pack(push, 1) #pragma pack(push, 1)
struct ext4_xattr_header { struct ext4_xattr_header {
__le32 h_magic; /* magic number for identification */ __le32 h_magic; /* magic number for identification */
__le32 h_refcount; /* reference count */ __le32 h_refcount; /* reference count */
__le32 h_blocks; /* number of disk blocks used */ __le32 h_blocks; /* number of disk blocks used */
__le32 h_hash; /* hash value of all attributes */ __le32 h_hash; /* hash value of all attributes */
__le32 h_checksum; /* crc32c(uuid+id+xattrblock) */ __le32 h_checksum; /* crc32c(uuid+id+xattrblock) */
/* id = inum if refcount=1, blknum otherwise */ /* id = inum if refcount=1, blknum otherwise */
__le32 h_reserved[3]; /* zero right now */ __le32 h_reserved[3]; /* zero right now */
}; };
struct ext4_xattr_ibody_header { struct ext4_xattr_ibody_header {
__le32 h_magic; /* magic number for identification */ __le32 h_magic; /* magic number for identification */
}; };
struct ext4_xattr_entry { struct ext4_xattr_entry {
__u8 e_name_len; /* length of name */ __u8 e_name_len; /* length of name */
__u8 e_name_index; /* attribute name index */ __u8 e_name_index; /* attribute name index */
__le16 e_value_offs; /* offset in disk block of value */ __le16 e_value_offs; /* offset in disk block of value */
__le32 e_value_block; /* disk block attribute is stored on (n/i) */ __le32 e_value_block; /* disk block attribute is stored on (n/i) */
__le32 e_value_size; /* size of attribute value */ __le32 e_value_size; /* size of attribute value */
__le32 e_hash; /* hash value of name and value */ __le32 e_hash; /* hash value of name and value */
}; };
#pragma pack(pop) #pragma pack(pop)
//#define EXT4_GOOD_OLD_INODE_SIZE EXT2_GOOD_OLD_INODE_SIZE //#define EXT4_GOOD_OLD_INODE_SIZE EXT2_GOOD_OLD_INODE_SIZE
#define EXT4_XATTR_PAD_BITS 2 #define EXT4_XATTR_PAD_BITS 2
#define EXT4_XATTR_PAD (1<<EXT4_XATTR_PAD_BITS) #define EXT4_XATTR_PAD (1<<EXT4_XATTR_PAD_BITS)
#define EXT4_XATTR_ROUND (EXT4_XATTR_PAD-1) #define EXT4_XATTR_ROUND (EXT4_XATTR_PAD-1)
#define EXT4_XATTR_LEN(name_len) \ #define EXT4_XATTR_LEN(name_len) \
(((name_len) + EXT4_XATTR_ROUND + \ (((name_len) + EXT4_XATTR_ROUND + \
sizeof(struct ext4_xattr_entry)) & ~EXT4_XATTR_ROUND) sizeof(struct ext4_xattr_entry)) & ~EXT4_XATTR_ROUND)
#define EXT4_XATTR_NEXT(entry) \ #define EXT4_XATTR_NEXT(entry) \
((struct ext4_xattr_entry *)( \ ((struct ext4_xattr_entry *)( \
(char *)(entry) + EXT4_XATTR_LEN((entry)->e_name_len))) (char *)(entry) + EXT4_XATTR_LEN((entry)->e_name_len)))
#define EXT4_XATTR_SIZE(size) \ #define EXT4_XATTR_SIZE(size) \
(((size) + EXT4_XATTR_ROUND) & ~EXT4_XATTR_ROUND) (((size) + EXT4_XATTR_ROUND) & ~EXT4_XATTR_ROUND)
#define EXT4_XATTR_NAME(entry) \ #define EXT4_XATTR_NAME(entry) \
((char *)((entry) + 1)) ((char *)((entry) + 1))
#define EXT4_XATTR_IHDR(raw_inode) \ #define EXT4_XATTR_IHDR(raw_inode) \
((struct ext4_xattr_ibody_header *) \ ((struct ext4_xattr_ibody_header *) \
((char *)raw_inode + \ ((char *)raw_inode + \
EXT4_GOOD_OLD_INODE_SIZE + \ EXT4_GOOD_OLD_INODE_SIZE + \
(raw_inode)->i_extra_isize)) (raw_inode)->i_extra_isize))
#define EXT4_XATTR_IFIRST(hdr) \ #define EXT4_XATTR_IFIRST(hdr) \
((struct ext4_xattr_entry *)((hdr)+1)) ((struct ext4_xattr_entry *)((hdr)+1))
#define EXT4_XATTR_BHDR(block) \ #define EXT4_XATTR_BHDR(block) \
((struct ext4_xattr_header *)((block)->b_data)) ((struct ext4_xattr_header *)((block)->b_data))
#define EXT4_XATTR_ENTRY(ptr) \ #define EXT4_XATTR_ENTRY(ptr) \
((struct ext4_xattr_entry *)(ptr)) ((struct ext4_xattr_entry *)(ptr))
#define EXT4_XATTR_BFIRST(block) \ #define EXT4_XATTR_BFIRST(block) \
EXT4_XATTR_ENTRY(EXT4_XATTR_BHDR(block)+1) EXT4_XATTR_ENTRY(EXT4_XATTR_BHDR(block)+1)
#define EXT4_XATTR_IS_LAST_ENTRY(entry) \ #define EXT4_XATTR_IS_LAST_ENTRY(entry) \
(*(__le32 *)(entry) == 0) (*(__le32 *)(entry) == 0)
#define EXT4_ZERO_XATTR_VALUE ((void *)-1) #define EXT4_ZERO_XATTR_VALUE ((void *)-1)
struct ext4_xattr_item { struct ext4_xattr_item {
/* This attribute should be stored in inode body */ /* This attribute should be stored in inode body */
BOOL in_inode; BOOL in_inode;
BOOL is_data; BOOL is_data;
__u8 name_index; __u8 name_index;
char *name; char *name;
size_t name_len; size_t name_len;
void *data; void *data;
size_t data_size; size_t data_size;
struct rb_node node; struct rb_node node;
struct list_head list_node; struct list_head list_node;
}; };
struct ext4_xattr_ref { struct ext4_xattr_ref {
PEXT2_IRP_CONTEXT IrpContext; PEXT2_IRP_CONTEXT IrpContext;
BOOL block_loaded; BOOL block_loaded;
struct buffer_head *block_bh; struct buffer_head *block_bh;
PEXT2_MCB inode_ref; PEXT2_MCB inode_ref;
PEXT2_INODE OnDiskInode; PEXT2_INODE OnDiskInode;
BOOL IsOnDiskInodeDirty; BOOL IsOnDiskInodeDirty;
BOOL dirty; BOOL dirty;
size_t ea_size; size_t ea_size;
size_t inode_size_rem; size_t inode_size_rem;
size_t block_size_rem; size_t block_size_rem;
PEXT2_VCB fs; PEXT2_VCB fs;
void *iter_arg; void *iter_arg;
struct ext4_xattr_item *iter_from; struct ext4_xattr_item *iter_from;
struct rb_root root; struct rb_root root;
struct list_head ordered_list; struct list_head ordered_list;
}; };
#define EXT4_XATTR_ITERATE_CONT 0 #define EXT4_XATTR_ITERATE_CONT 0
#define EXT4_XATTR_ITERATE_STOP 1 #define EXT4_XATTR_ITERATE_STOP 1
#define EXT4_XATTR_ITERATE_PAUSE 2 #define EXT4_XATTR_ITERATE_PAUSE 2
int ext4_fs_get_xattr_ref(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB fs, PEXT2_MCB inode_ref, int ext4_fs_get_xattr_ref(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB fs, PEXT2_MCB inode_ref,
struct ext4_xattr_ref *ref); struct ext4_xattr_ref *ref);
int ext4_fs_put_xattr_ref(struct ext4_xattr_ref *ref); int ext4_fs_put_xattr_ref(struct ext4_xattr_ref *ref);
int ext4_fs_set_xattr(struct ext4_xattr_ref *ref, __u8 name_index, int ext4_fs_set_xattr(struct ext4_xattr_ref *ref, __u8 name_index,
const char *name, size_t name_len, const void *data, const char *name, size_t name_len, const void *data,
size_t data_size, BOOL replace); size_t data_size, BOOL replace);
int ext4_fs_set_xattr_ordered(struct ext4_xattr_ref *ref, __u8 name_index, int ext4_fs_set_xattr_ordered(struct ext4_xattr_ref *ref, __u8 name_index,
const char *name, size_t name_len, const void *data, const char *name, size_t name_len, const void *data,
size_t data_size); size_t data_size);
int ext4_fs_remove_xattr(struct ext4_xattr_ref *ref, __u8 name_index, int ext4_fs_remove_xattr(struct ext4_xattr_ref *ref, __u8 name_index,
const char *name, size_t name_len); const char *name, size_t name_len);
int ext4_fs_get_xattr(struct ext4_xattr_ref *ref, __u8 name_index, int ext4_fs_get_xattr(struct ext4_xattr_ref *ref, __u8 name_index,
const char *name, size_t name_len, void *buf, const char *name, size_t name_len, void *buf,
size_t buf_size, size_t *data_size); size_t buf_size, size_t *data_size);
void ext4_fs_xattr_iterate(struct ext4_xattr_ref *ref, void ext4_fs_xattr_iterate(struct ext4_xattr_ref *ref,
int(*iter)(struct ext4_xattr_ref *ref, int(*iter)(struct ext4_xattr_ref *ref,
struct ext4_xattr_item *item, struct ext4_xattr_item *item,
BOOL is_last)); BOOL is_last));
void ext4_fs_xattr_iterate_reset(struct ext4_xattr_ref *ref); void ext4_fs_xattr_iterate_reset(struct ext4_xattr_ref *ref);
const char *ext4_extract_xattr_name(const char *full_name, size_t full_name_len, const char *ext4_extract_xattr_name(const char *full_name, size_t full_name_len,
__u8 *name_index, size_t *name_len, __u8 *name_index, size_t *name_len,
BOOL *found); BOOL *found);
const char *ext4_get_xattr_name_prefix(__u8 name_index, const char *ext4_get_xattr_name_prefix(__u8 name_index,
size_t *ret_prefix_len); size_t *ret_prefix_len);
void ext4_xattr_purge_items(struct ext4_xattr_ref *xattr_ref); void ext4_xattr_purge_items(struct ext4_xattr_ref *xattr_ref);
#endif #endif
/** /**
* @} * @}
*/ */

View File

@@ -1,160 +1,160 @@
#ifndef _LINUX_FS_INCLUDE_ #ifndef _LINUX_FS_INCLUDE_
#define _LINUX_FS_INCLUDE_ #define _LINUX_FS_INCLUDE_
#include <linux/types.h> #include <linux/types.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/rbtree.h> #include <linux/rbtree.h>
// //
// kdev // kdev
// //
#define NODEV 0 #define NODEV 0
typedef struct block_device * kdev_t; typedef struct block_device * kdev_t;
#define MINORBITS 8 #define MINORBITS 8
#define MINORMASK ((1U << MINORBITS) - 1) #define MINORMASK ((1U << MINORBITS) - 1)
#define MAJOR(dev) ((unsigned int)((int)(dev) >> MINORBITS)) #define MAJOR(dev) ((unsigned int)((int)(dev) >> MINORBITS))
#define MINOR(dev) ((unsigned int)((int)(dev) & MINORMASK)) #define MINOR(dev) ((unsigned int)((int)(dev) & MINORMASK))
static inline unsigned int kdev_t_to_nr(kdev_t dev) { static inline unsigned int kdev_t_to_nr(kdev_t dev) {
/*return (unsigned int)(MAJOR(dev)<<8) | MINOR(dev);*/ /*return (unsigned int)(MAJOR(dev)<<8) | MINOR(dev);*/
return 0; return 0;
} }
#define NODEV 0 #define NODEV 0
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi)) #define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
static inline kdev_t to_kdev_t(int dev) static inline kdev_t to_kdev_t(int dev)
{ {
#if 0 #if 0
int major, minor; int major, minor;
#if 0 #if 0
major = (dev >> 16); major = (dev >> 16);
if (!major) { if (!major) {
major = (dev >> 8); major = (dev >> 8);
minor = (dev & 0xff); minor = (dev & 0xff);
} else } else
minor = (dev & 0xffff); minor = (dev & 0xffff);
#else #else
major = (dev >> 8); major = (dev >> 8);
minor = (dev & 0xff); minor = (dev & 0xff);
#endif #endif
return (kdev_t) MKDEV(major, minor); return (kdev_t) MKDEV(major, minor);
#endif #endif
return 0; return 0;
} }
// //
// file system specific structures // file system specific structures
// //
/* /*
* Kernel pointers have redundant information, so we can use a * Kernel pointers have redundant information, so we can use a
* scheme where we can return either an error code or a dentry * scheme where we can return either an error code or a dentry
* pointer with the same return value. * pointer with the same return value.
* *
* This should be a per-architecture thing, to allow different * This should be a per-architecture thing, to allow different
* error and pointer decisions. * error and pointer decisions.
*/ */
struct super_block { struct super_block {
unsigned long s_magic; unsigned long s_magic;
unsigned long s_flags; unsigned long s_flags;
unsigned long s_blocksize; /* blocksize */ unsigned long s_blocksize; /* blocksize */
unsigned long long s_maxbytes; unsigned long long s_maxbytes;
unsigned char s_blocksize_bits; /* bits of blocksize */ unsigned char s_blocksize_bits; /* bits of blocksize */
unsigned char s_dirt; /* any thing */ unsigned char s_dirt; /* any thing */
char s_id[30]; /* id string */ char s_id[30]; /* id string */
kdev_t s_bdev; /* block_device */ kdev_t s_bdev; /* block_device */
void * s_priv; /* EXT2_VCB */ void * s_priv; /* EXT2_VCB */
struct dentry *s_root; struct dentry *s_root;
void *s_fs_info; void *s_fs_info;
}; };
struct inode { struct inode {
__u32 i_ino; /* inode number */ __u32 i_ino; /* inode number */
loff_t i_size; /* size */ loff_t i_size; /* size */
__u32 i_atime; /* Access time */ __u32 i_atime; /* Access time */
__u32 i_ctime; /* Creation time */ __u32 i_ctime; /* Creation time */
__u32 i_mtime; /* Modification time */ __u32 i_mtime; /* Modification time */
__u32 i_dtime; /* Deletion Time */ __u32 i_dtime; /* Deletion Time */
__u64 i_blocks; __u64 i_blocks;
__u32 i_block[15]; __u32 i_block[15];
umode_t i_mode; /* mode */ umode_t i_mode; /* mode */
uid_t i_uid; uid_t i_uid;
gid_t i_gid; gid_t i_gid;
atomic_t i_count; /* ref count */ atomic_t i_count; /* ref count */
__u16 i_nlink; __u16 i_nlink;
__u32 i_generation; __u32 i_generation;
__u32 i_version; __u32 i_version;
__u32 i_flags; __u32 i_flags;
struct super_block *i_sb; /* super_block */ struct super_block *i_sb; /* super_block */
void *i_priv; /* EXT2_MCB */ void *i_priv; /* EXT2_MCB */
__u16 i_extra_isize; /* extra fields' size */ __u16 i_extra_isize; /* extra fields' size */
__u64 i_file_acl; __u64 i_file_acl;
}; };
// //
// Inode state bits // Inode state bits
// //
#define I_DIRTY_SYNC 1 /* Not dirty enough for O_DATASYNC */ #define I_DIRTY_SYNC 1 /* Not dirty enough for O_DATASYNC */
#define I_DIRTY_DATASYNC 2 /* Data-related inode changes pending */ #define I_DIRTY_DATASYNC 2 /* Data-related inode changes pending */
#define I_DIRTY_PAGES 4 /* Data-related inode changes pending */ #define I_DIRTY_PAGES 4 /* Data-related inode changes pending */
#define I_LOCK 8 #define I_LOCK 8
#define I_FREEING 16 #define I_FREEING 16
#define I_CLEAR 32 #define I_CLEAR 32
#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
struct dentry { struct dentry {
atomic_t d_count; atomic_t d_count;
struct { struct {
int len; int len;
char *name; char *name;
} d_name; } d_name;
struct inode *d_inode; struct inode *d_inode;
struct dentry *d_parent; struct dentry *d_parent;
void *d_fsdata; void *d_fsdata;
struct super_block *d_sb; struct super_block *d_sb;
}; };
struct file { struct file {
unsigned int f_flags; unsigned int f_flags;
umode_t f_mode; umode_t f_mode;
__u32 f_version; __u32 f_version;
__int64 f_size; __int64 f_size;
loff_t f_pos; loff_t f_pos;
struct dentry *f_dentry; struct dentry *f_dentry;
void *private_data; void *private_data;
}; };
/* /*
* File types * File types
* *
* NOTE! These match bits 12..15 of stat.st_mode * NOTE! These match bits 12..15 of stat.st_mode
* (ie "(i_mode >> 12) & 15"). * (ie "(i_mode >> 12) & 15").
*/ */
#define DT_UNKNOWN 0 #define DT_UNKNOWN 0
#define DT_FIFO 1 #define DT_FIFO 1
#define DT_CHR 2 #define DT_CHR 2
#define DT_DIR 4 #define DT_DIR 4
#define DT_BLK 6 #define DT_BLK 6
#define DT_REG 8 #define DT_REG 8
#define DT_LNK 10 #define DT_LNK 10
#define DT_SOCK 12 #define DT_SOCK 12
#define DT_WHT 14 #define DT_WHT 14
void iget(struct inode *inode); void iget(struct inode *inode);
void iput(struct inode *inode); void iput(struct inode *inode);
ULONGLONG bmap(struct inode *i, ULONGLONG b); ULONGLONG bmap(struct inode *i, ULONGLONG b);
#endif /*_LINUX_FS_INCLUDE_*/ #endif /*_LINUX_FS_INCLUDE_*/

View File

@@ -1,29 +1,29 @@
/* /*
* linux/fs/ext4/group.h * linux/fs/ext4/group.h
* *
* Copyright (C) 2007 Cluster File Systems, Inc * Copyright (C) 2007 Cluster File Systems, Inc
* *
* Author: Andreas Dilger <adilger@clusterfs.com> * Author: Andreas Dilger <adilger@clusterfs.com>
*/ */
#ifndef _LINUX_EXT4_GROUP_H #ifndef _LINUX_EXT4_GROUP_H
#define _LINUX_EXT4_GROUP_H #define _LINUX_EXT4_GROUP_H
extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group, extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group,
struct ext4_group_desc *gdp); struct ext4_group_desc *gdp);
extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group, extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group,
struct ext4_group_desc *gdp); struct ext4_group_desc *gdp);
struct buffer_head *ext4_read_block_bitmap(struct super_block *sb, struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
ext4_group_t block_group); ext4_group_t block_group);
extern unsigned ext4_init_block_bitmap(struct super_block *sb, extern unsigned ext4_init_block_bitmap(struct super_block *sb,
struct buffer_head *bh, struct buffer_head *bh,
ext4_group_t group, ext4_group_t group,
struct ext4_group_desc *desc); struct ext4_group_desc *desc);
#define ext4_free_blocks_after_init(sb, group, desc) \ #define ext4_free_blocks_after_init(sb, group, desc) \
ext4_init_block_bitmap(sb, NULL, group, desc) ext4_init_block_bitmap(sb, NULL, group, desc)
extern unsigned ext4_init_inode_bitmap(struct super_block *sb, extern unsigned ext4_init_inode_bitmap(struct super_block *sb,
struct buffer_head *bh, struct buffer_head *bh,
ext4_group_t group, ext4_group_t group,
struct ext4_group_desc *desc); struct ext4_group_desc *desc);
extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap); extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
#endif /* _LINUX_EXT4_GROUP_H */ #endif /* _LINUX_EXT4_GROUP_H */

View File

@@ -1,92 +1,92 @@
/* /*
* include/linux/journal-head.h * include/linux/journal-head.h
* *
* buffer_head fields for JBD * buffer_head fields for JBD
* *
* 27 May 2001 Andrew Morton <akpm@digeo.com> * 27 May 2001 Andrew Morton <akpm@digeo.com>
* Created - pulled out of fs.h * Created - pulled out of fs.h
*/ */
#ifndef JOURNAL_HEAD_H_INCLUDED #ifndef JOURNAL_HEAD_H_INCLUDED
#define JOURNAL_HEAD_H_INCLUDED #define JOURNAL_HEAD_H_INCLUDED
typedef unsigned int tid_t; /* Unique transaction ID */ typedef unsigned int tid_t; /* Unique transaction ID */
typedef struct transaction_s transaction_t; /* Compound transaction type */ typedef struct transaction_s transaction_t; /* Compound transaction type */
struct buffer_head; struct buffer_head;
struct journal_head { struct journal_head {
/* /*
* Points back to our buffer_head. [jbd_lock_bh_journal_head()] * Points back to our buffer_head. [jbd_lock_bh_journal_head()]
*/ */
struct buffer_head *b_bh; struct buffer_head *b_bh;
/* /*
* Reference count - see description in journal.c * Reference count - see description in journal.c
* [jbd_lock_bh_journal_head()] * [jbd_lock_bh_journal_head()]
*/ */
int b_jcount; int b_jcount;
/* /*
* Journalling list for this buffer [jbd_lock_bh_state()] * Journalling list for this buffer [jbd_lock_bh_state()]
*/ */
unsigned b_jlist; unsigned b_jlist;
/* /*
* This flag signals the buffer has been modified by * This flag signals the buffer has been modified by
* the currently running transaction * the currently running transaction
* [jbd_lock_bh_state()] * [jbd_lock_bh_state()]
*/ */
unsigned b_modified; unsigned b_modified;
/* /*
* Copy of the buffer data frozen for writing to the log. * Copy of the buffer data frozen for writing to the log.
* [jbd_lock_bh_state()] * [jbd_lock_bh_state()]
*/ */
char *b_frozen_data; char *b_frozen_data;
/* /*
* Pointer to a saved copy of the buffer containing no uncommitted * Pointer to a saved copy of the buffer containing no uncommitted
* deallocation references, so that allocations can avoid overwriting * deallocation references, so that allocations can avoid overwriting
* uncommitted deletes. [jbd_lock_bh_state()] * uncommitted deletes. [jbd_lock_bh_state()]
*/ */
char *b_committed_data; char *b_committed_data;
/* /*
* Pointer to the compound transaction which owns this buffer's * Pointer to the compound transaction which owns this buffer's
* metadata: either the running transaction or the committing * metadata: either the running transaction or the committing
* transaction (if there is one). Only applies to buffers on a * transaction (if there is one). Only applies to buffers on a
* transaction's data or metadata journaling list. * transaction's data or metadata journaling list.
* [j_list_lock] [jbd_lock_bh_state()] * [j_list_lock] [jbd_lock_bh_state()]
*/ */
transaction_t *b_transaction; transaction_t *b_transaction;
/* /*
* Pointer to the running compound transaction which is currently * Pointer to the running compound transaction which is currently
* modifying the buffer's metadata, if there was already a transaction * modifying the buffer's metadata, if there was already a transaction
* committing it when the new transaction touched it. * committing it when the new transaction touched it.
* [t_list_lock] [jbd_lock_bh_state()] * [t_list_lock] [jbd_lock_bh_state()]
*/ */
transaction_t *b_next_transaction; transaction_t *b_next_transaction;
/* /*
* Doubly-linked list of buffers on a transaction's data, metadata or * Doubly-linked list of buffers on a transaction's data, metadata or
* forget queue. [t_list_lock] [jbd_lock_bh_state()] * forget queue. [t_list_lock] [jbd_lock_bh_state()]
*/ */
struct journal_head *b_tnext, *b_tprev; struct journal_head *b_tnext, *b_tprev;
/* /*
* Pointer to the compound transaction against which this buffer * Pointer to the compound transaction against which this buffer
* is checkpointed. Only dirty buffers can be checkpointed. * is checkpointed. Only dirty buffers can be checkpointed.
* [j_list_lock] * [j_list_lock]
*/ */
transaction_t *b_cp_transaction; transaction_t *b_cp_transaction;
/* /*
* Doubly-linked list of buffers still remaining to be flushed * Doubly-linked list of buffers still remaining to be flushed
* before an old transaction can be checkpointed. * before an old transaction can be checkpointed.
* [j_list_lock] * [j_list_lock]
*/ */
struct journal_head *b_cpnext, *b_cpprev; struct journal_head *b_cpnext, *b_cpprev;
}; };
#endif /* JOURNAL_HEAD_H_INCLUDED */ #endif /* JOURNAL_HEAD_H_INCLUDED */

View File

@@ -1,255 +1,255 @@
#ifndef __LINUX_LIST_H__ #ifndef __LINUX_LIST_H__
#define __LINUX_LIST_H__ #define __LINUX_LIST_H__
/* /*
* Simple doubly linked list implementation. * Simple doubly linked list implementation.
* *
* Some of the internal functions ("__xxx") are useful when * Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as * manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can * sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than * generate better code by using them directly rather than
* using the generic single-entry routines. * using the generic single-entry routines.
*/ */
#define prefetch(a) ((void *)a) #define prefetch(a) ((void *)a)
struct list_head { struct list_head {
struct list_head *next, *prev; struct list_head *next, *prev;
}; };
#define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \ #define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name) struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list) static inline void INIT_LIST_HEAD(struct list_head *list)
{ {
list->next = list; list->next = list;
list->prev = list; list->prev = list;
} }
/* /*
* Insert a new entry between two known consecutive entries. * Insert a new entry between two known consecutive entries.
* *
* This is only for internal list manipulation where we know * This is only for internal list manipulation where we know
* the prev/next entries already! * the prev/next entries already!
*/ */
static inline void __list_add(struct list_head * new, static inline void __list_add(struct list_head * new,
struct list_head * prev, struct list_head * prev,
struct list_head * next) struct list_head * next)
{ {
next->prev = new; next->prev = new;
new->next = next; new->next = next;
new->prev = prev; new->prev = prev;
prev->next = new; prev->next = new;
} }
/** /**
* list_add - add a new entry * list_add - add a new entry
* @new: new entry to be added * @new: new entry to be added
* @head: list head to add it after * @head: list head to add it after
* *
* Insert a new entry after the specified head. * Insert a new entry after the specified head.
* This is good for implementing stacks. * This is good for implementing stacks.
*/ */
static inline void list_add(struct list_head *new, struct list_head *head) static inline void list_add(struct list_head *new, struct list_head *head)
{ {
__list_add(new, head, head->next); __list_add(new, head, head->next);
} }
/** /**
* list_add_tail - add a new entry * list_add_tail - add a new entry
* @new: new entry to be added * @new: new entry to be added
* @head: list head to add it before * @head: list head to add it before
* *
* Insert a new entry before the specified head. * Insert a new entry before the specified head.
* This is useful for implementing queues. * This is useful for implementing queues.
*/ */
static inline void list_add_tail(struct list_head *new, struct list_head *head) static inline void list_add_tail(struct list_head *new, struct list_head *head)
{ {
__list_add(new, head->prev, head); __list_add(new, head->prev, head);
} }
/* /*
* Delete a list entry by making the prev/next entries * Delete a list entry by making the prev/next entries
* point to each other. * point to each other.
* *
* This is only for internal list manipulation where we know * This is only for internal list manipulation where we know
* the prev/next entries already! * the prev/next entries already!
*/ */
static inline void __list_del(struct list_head * prev, struct list_head * next) static inline void __list_del(struct list_head * prev, struct list_head * next)
{ {
next->prev = prev; next->prev = prev;
prev->next = next; prev->next = next;
} }
/** /**
* list_del - deletes entry from list. * list_del - deletes entry from list.
* @entry: the element to delete from the list. * @entry: the element to delete from the list.
* Note: list_empty on entry does not return true after this, the entry is in an undefined state. * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
*/ */
static inline void list_del(struct list_head *entry) static inline void list_del(struct list_head *entry)
{ {
__list_del(entry->prev, entry->next); __list_del(entry->prev, entry->next);
} }
/** /**
* list_del_init - deletes entry from list and reinitialize it. * list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list. * @entry: the element to delete from the list.
*/ */
static inline void list_del_init(struct list_head *entry) static inline void list_del_init(struct list_head *entry)
{ {
__list_del(entry->prev, entry->next); __list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry); INIT_LIST_HEAD(entry);
} }
/** /**
* list_move - delete from one list and add as another's head * list_move - delete from one list and add as another's head
* @list: the entry to move * @list: the entry to move
* @head: the head that will precede our entry * @head: the head that will precede our entry
*/ */
static inline void list_move(struct list_head *list, struct list_head *head) static inline void list_move(struct list_head *list, struct list_head *head)
{ {
__list_del(list->prev, list->next); __list_del(list->prev, list->next);
list_add(list, head); list_add(list, head);
} }
/** /**
* list_move_tail - delete from one list and add as another's tail * list_move_tail - delete from one list and add as another's tail
* @list: the entry to move * @list: the entry to move
* @head: the head that will follow our entry * @head: the head that will follow our entry
*/ */
static inline void list_move_tail(struct list_head *list, static inline void list_move_tail(struct list_head *list,
struct list_head *head) struct list_head *head)
{ {
__list_del(list->prev, list->next); __list_del(list->prev, list->next);
list_add_tail(list, head); list_add_tail(list, head);
} }
/** /**
* list_empty - tests whether a list is empty * list_empty - tests whether a list is empty
* @head: the list to test. * @head: the list to test.
*/ */
static inline int list_empty(struct list_head *head) static inline int list_empty(struct list_head *head)
{ {
return head->next == head; return head->next == head;
} }
static inline int list_empty_careful(const struct list_head *head) static inline int list_empty_careful(const struct list_head *head)
{ {
struct list_head *next = head->next; struct list_head *next = head->next;
return (next == head) && (next == head->prev); return (next == head) && (next == head->prev);
} }
static inline void __list_splice(struct list_head *list, static inline void __list_splice(struct list_head *list,
struct list_head *head) struct list_head *head)
{ {
struct list_head *first = list->next; struct list_head *first = list->next;
struct list_head *last = list->prev; struct list_head *last = list->prev;
struct list_head *at = head->next; struct list_head *at = head->next;
first->prev = head; first->prev = head;
head->next = first; head->next = first;
last->next = at; last->next = at;
at->prev = last; at->prev = last;
} }
/** /**
* list_splice - join two lists * list_splice - join two lists
* @list: the new list to add. * @list: the new list to add.
* @head: the place to add it in the first list. * @head: the place to add it in the first list.
*/ */
static inline void list_splice(struct list_head *list, struct list_head *head) static inline void list_splice(struct list_head *list, struct list_head *head)
{ {
if (!list_empty(list)) if (!list_empty(list))
__list_splice(list, head); __list_splice(list, head);
} }
/** /**
* list_splice_init - join two lists and reinitialise the emptied list. * list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add. * @list: the new list to add.
* @head: the place to add it in the first list. * @head: the place to add it in the first list.
* *
* The list at @list is reinitialised * The list at @list is reinitialised
*/ */
static inline void list_splice_init(struct list_head *list, static inline void list_splice_init(struct list_head *list,
struct list_head *head) struct list_head *head)
{ {
if (!list_empty(list)) { if (!list_empty(list)) {
__list_splice(list, head); __list_splice(list, head);
INIT_LIST_HEAD(list); INIT_LIST_HEAD(list);
} }
} }
/** /**
* list_entry - get the struct for this entry * list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer. * @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in. * @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct. * @member: the name of the list_struct within the struct.
*/ */
#define list_entry(ptr, type, member) \ #define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(char *)(&((type *)0)->member))) ((type *)((char *)(ptr)-(char *)(&((type *)0)->member)))
/** /**
* list_for_each - iterate over a list * list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop counter. * @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list. * @head: the head for your list.
*/ */
#define list_for_each(pos, head) \ #define list_for_each(pos, head) \
for (pos = (head)->next, prefetch(pos->next); pos != (head); \ for (pos = (head)->next, prefetch(pos->next); pos != (head); \
pos = pos->next, prefetch(pos->next)) pos = pos->next, prefetch(pos->next))
/** /**
* list_for_each_safe - iterate over a list safe against removal of list entry * list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop counter. * @pos: the &struct list_head to use as a loop counter.
* @n: another &struct list_head to use as temporary storage * @n: another &struct list_head to use as temporary storage
* @head: the head for your list. * @head: the head for your list.
*/ */
#define list_for_each_safe(pos, n, head) \ #define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \ for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next) pos = n, n = pos->next)
#ifndef list_for_each_prev #ifndef list_for_each_prev
/** /**
* list_for_each_prev - iterate over a list in reverse order * list_for_each_prev - iterate over a list in reverse order
* @pos: the &struct list_head to use as a loop counter. * @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list. * @head: the head for your list.
*/ */
#define list_for_each_prev(pos, head) \ #define list_for_each_prev(pos, head) \
for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
pos = pos->prev, prefetch(pos->prev)) pos = pos->prev, prefetch(pos->prev))
#endif /* list_for_each_prev */ #endif /* list_for_each_prev */
#ifndef list_for_each_entry #ifndef list_for_each_entry
/** /**
* list_for_each_entry - iterate over list of given type * list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop counter. * @pos: the type * to use as a loop counter.
* @head: the head for your list. * @head: the head for your list.
* @member: the name of the list_struct within the struct. * @member: the name of the list_struct within the struct.
*/ */
#define list_for_each_entry(pos, head, type, member) \ #define list_for_each_entry(pos, head, type, member) \
for (pos = list_entry((head)->next, type, member), \ for (pos = list_entry((head)->next, type, member), \
prefetch(pos->member.next); \ prefetch(pos->member.next); \
&pos->member != (head); \ &pos->member != (head); \
pos = list_entry(pos->member.next, type, member), \ pos = list_entry(pos->member.next, type, member), \
prefetch(pos->member.next)) prefetch(pos->member.next))
#endif /* list_for_each_entry */ #endif /* list_for_each_entry */
#ifndef list_for_each_entry_safe #ifndef list_for_each_entry_safe
/** /**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop counter. * @pos: the type * to use as a loop counter.
* @n: another type * to use as temporary storage * @n: another type * to use as temporary storage
* @head: the head for your list. * @head: the head for your list.
* @member: the name of the list_struct within the struct. * @member: the name of the list_struct within the struct.
*/ */
#define list_for_each_entry_safe(pos, n, head, type, member) \ #define list_for_each_entry_safe(pos, n, head, type, member) \
for (pos = list_entry((head)->next, type, member), \ for (pos = list_entry((head)->next, type, member), \
n = list_entry(pos->member.next, type, member); \ n = list_entry(pos->member.next, type, member); \
&pos->member != (head); \ &pos->member != (head); \
pos = n, n = list_entry(n->member.next, type, member)) pos = n, n = list_entry(n->member.next, type, member))
#endif /* list_for_each_entry_safe */ #endif /* list_for_each_entry_safe */
#endif /* __LINUX_LIST_H__ */ #endif /* __LINUX_LIST_H__ */

View File

@@ -1,140 +1,140 @@
/* Integer base 2 logarithm calculation /* Integer base 2 logarithm calculation
* *
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com) * Written by David Howells (dhowells@redhat.com)
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#ifndef _LINUX_LOG2_H #ifndef _LINUX_LOG2_H
#define _LINUX_LOG2_H #define _LINUX_LOG2_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/bitops.h> #include <linux/bitops.h>
/* /*
* deal with unrepresentable constant logarithms * deal with unrepresentable constant logarithms
*/ */
int ____ilog2_NaN(void); int ____ilog2_NaN(void);
/* /*
* non-constant log of base 2 calculators * non-constant log of base 2 calculators
* - the arch may override these in asm/bitops.h if they can be implemented * - the arch may override these in asm/bitops.h if they can be implemented
* more efficiently than using fls() and fls64() * more efficiently than using fls() and fls64()
* - the arch is not required to handle n==0 if implementing the fallback * - the arch is not required to handle n==0 if implementing the fallback
*/ */
#ifndef CONFIG_ARCH_HAS_ILOG2_U32 #ifndef CONFIG_ARCH_HAS_ILOG2_U32
static inline __attribute__((const)) static inline __attribute__((const))
int __ilog2_u32(u32 n) int __ilog2_u32(u32 n)
{ {
return fls(n) - 1; return fls(n) - 1;
} }
#endif #endif
#ifndef CONFIG_ARCH_HAS_ILOG2_U64 #ifndef CONFIG_ARCH_HAS_ILOG2_U64
static inline __attribute__((const)) static inline __attribute__((const))
int __ilog2_u64(u64 n) int __ilog2_u64(u64 n)
{ {
return fls64(n) - 1; return fls64(n) - 1;
} }
#endif #endif
/* /*
* Determine whether some value is a power of two, where zero is * Determine whether some value is a power of two, where zero is
* *not* considered a power of two. * *not* considered a power of two.
*/ */
static inline __attribute__((const)) static inline __attribute__((const))
bool is_power_of_2(unsigned long n) bool is_power_of_2(unsigned long n)
{ {
return (n != 0 && ((n & (n - 1)) == 0)); return (n != 0 && ((n & (n - 1)) == 0));
} }
/* /*
* round up to nearest power of two * round up to nearest power of two
*/ */
static inline __attribute__((const)) static inline __attribute__((const))
unsigned long __roundup_pow_of_two(unsigned long n) unsigned long __roundup_pow_of_two(unsigned long n)
{ {
return 1UL << fls_long(n - 1); return 1UL << fls_long(n - 1);
} }
/* /*
* round down to nearest power of two * round down to nearest power of two
*/ */
static inline __attribute__((const)) static inline __attribute__((const))
unsigned long __rounddown_pow_of_two(unsigned long n) unsigned long __rounddown_pow_of_two(unsigned long n)
{ {
return 1UL << (fls_long(n) - 1); return 1UL << (fls_long(n) - 1);
} }
/** /**
* ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value * ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
* @n - parameter * @n - parameter
* *
* constant-capable log of base 2 calculation * constant-capable log of base 2 calculation
* - this can be used to initialise global variables from constant data, hence * - this can be used to initialise global variables from constant data, hence
* the massive ternary operator construction * the massive ternary operator construction
* *
* selects the appropriately-sized optimised version depending on sizeof(n) * selects the appropriately-sized optimised version depending on sizeof(n)
*/ */
#define ilog2(n) \ #define ilog2(n) \
( \ ( \
(sizeof(n) <= 4) ? \ (sizeof(n) <= 4) ? \
__ilog2_u32(n) : \ __ilog2_u32(n) : \
__ilog2_u64(n) \ __ilog2_u64(n) \
) )
/** /**
* roundup_pow_of_two - round the given value up to nearest power of two * roundup_pow_of_two - round the given value up to nearest power of two
* @n - parameter * @n - parameter
* *
* round the given value up to the nearest power of two * round the given value up to the nearest power of two
* - the result is undefined when n == 0 * - the result is undefined when n == 0
* - this can be used to initialise global variables from constant data * - this can be used to initialise global variables from constant data
*/ */
#define roundup_pow_of_two(n) \ #define roundup_pow_of_two(n) \
( \ ( \
__builtin_constant_p(n) ? ( \ __builtin_constant_p(n) ? ( \
(n == 1) ? 1 : \ (n == 1) ? 1 : \
(1UL << (ilog2((n) - 1) + 1)) \ (1UL << (ilog2((n) - 1) + 1)) \
) : \ ) : \
__roundup_pow_of_two(n) \ __roundup_pow_of_two(n) \
) )
/** /**
* rounddown_pow_of_two - round the given value down to nearest power of two * rounddown_pow_of_two - round the given value down to nearest power of two
* @n - parameter * @n - parameter
* *
* round the given value down to the nearest power of two * round the given value down to the nearest power of two
* - the result is undefined when n == 0 * - the result is undefined when n == 0
* - this can be used to initialise global variables from constant data * - this can be used to initialise global variables from constant data
*/ */
#define rounddown_pow_of_two(n) \ #define rounddown_pow_of_two(n) \
( \ ( \
__builtin_constant_p(n) ? ( \ __builtin_constant_p(n) ? ( \
(n == 1) ? 0 : \ (n == 1) ? 0 : \
(1UL << ilog2(n))) : \ (1UL << ilog2(n))) : \
__rounddown_pow_of_two(n) \ __rounddown_pow_of_two(n) \
) )
/** /**
* order_base_2 - calculate the (rounded up) base 2 order of the argument * order_base_2 - calculate the (rounded up) base 2 order of the argument
* @n: parameter * @n: parameter
* *
* The first few values calculated by this routine: * The first few values calculated by this routine:
* ob2(0) = 0 * ob2(0) = 0
* ob2(1) = 0 * ob2(1) = 0
* ob2(2) = 1 * ob2(2) = 1
* ob2(3) = 2 * ob2(3) = 2
* ob2(4) = 2 * ob2(4) = 2
* ob2(5) = 3 * ob2(5) = 3
* ... and so on. * ... and so on.
*/ */
#define order_base_2(n) ilog2(roundup_pow_of_two(n)) #define order_base_2(n) ilog2(roundup_pow_of_two(n))
#endif /* _LINUX_LOG2_H */ #endif /* _LINUX_LOG2_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,161 +1,161 @@
/* /*
Red Black Trees Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de> (C) 1999 Andrea Arcangeli <andrea@suse.de>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
linux/include/linux/rbtree.h linux/include/linux/rbtree.h
To use rbtrees you'll have to implement your own insert and search cores. To use rbtrees you'll have to implement your own insert and search cores.
This will avoid us to use callbacks and to drop drammatically performances. This will avoid us to use callbacks and to drop drammatically performances.
I know it's not the cleaner way, but in C (not in C++) to get I know it's not the cleaner way, but in C (not in C++) to get
performances and genericity... performances and genericity...
Some example of insert and search follows here. The search is a plain Some example of insert and search follows here. The search is a plain
normal search over an ordered tree. The insert instead must be implemented normal search over an ordered tree. The insert instead must be implemented
int two steps: as first thing the code must insert the element in int two steps: as first thing the code must insert the element in
order as a red leaf in the tree, then the support library function order as a red leaf in the tree, then the support library function
rb_insert_color() must be called. Such function will do the rb_insert_color() must be called. Such function will do the
not trivial work to rebalance the rbtree if necessary. not trivial work to rebalance the rbtree if necessary.
----------------------------------------------------------------------- -----------------------------------------------------------------------
static inline struct page * rb_search_page_cache(struct inode * inode, static inline struct page * rb_search_page_cache(struct inode * inode,
unsigned long offset) unsigned long offset)
{ {
struct rb_node * n = inode->i_rb_page_cache.rb_node; struct rb_node * n = inode->i_rb_page_cache.rb_node;
struct page * page; struct page * page;
while (n) while (n)
{ {
page = rb_entry(n, struct page, rb_page_cache); page = rb_entry(n, struct page, rb_page_cache);
if (offset < page->offset) if (offset < page->offset)
n = n->rb_left; n = n->rb_left;
else if (offset > page->offset) else if (offset > page->offset)
n = n->rb_right; n = n->rb_right;
else else
return page; return page;
} }
return NULL; return NULL;
} }
static inline struct page * __rb_insert_page_cache(struct inode * inode, static inline struct page * __rb_insert_page_cache(struct inode * inode,
unsigned long offset, unsigned long offset,
struct rb_node * node) struct rb_node * node)
{ {
struct rb_node ** p = &inode->i_rb_page_cache.rb_node; struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
struct rb_node * parent = NULL; struct rb_node * parent = NULL;
struct page * page; struct page * page;
while (*p) while (*p)
{ {
parent = *p; parent = *p;
page = rb_entry(parent, struct page, rb_page_cache); page = rb_entry(parent, struct page, rb_page_cache);
if (offset < page->offset) if (offset < page->offset)
p = &(*p)->rb_left; p = &(*p)->rb_left;
else if (offset > page->offset) else if (offset > page->offset)
p = &(*p)->rb_right; p = &(*p)->rb_right;
else else
return page; return page;
} }
rb_link_node(node, parent, p); rb_link_node(node, parent, p);
return NULL; return NULL;
} }
static inline struct page * rb_insert_page_cache(struct inode * inode, static inline struct page * rb_insert_page_cache(struct inode * inode,
unsigned long offset, unsigned long offset,
struct rb_node * node) struct rb_node * node)
{ {
struct page * ret; struct page * ret;
if ((ret = __rb_insert_page_cache(inode, offset, node))) if ((ret = __rb_insert_page_cache(inode, offset, node)))
goto out; goto out;
rb_insert_color(node, &inode->i_rb_page_cache); rb_insert_color(node, &inode->i_rb_page_cache);
out: out:
return ret; return ret;
} }
----------------------------------------------------------------------- -----------------------------------------------------------------------
*/ */
#ifndef _LINUX_RBTREE_H #ifndef _LINUX_RBTREE_H
#define _LINUX_RBTREE_H #define _LINUX_RBTREE_H
struct rb_node struct rb_node
{ {
ULONG_PTR rb_parent_color; ULONG_PTR rb_parent_color;
#define RB_RED 0 #define RB_RED 0
#define RB_BLACK 1 #define RB_BLACK 1
struct rb_node *rb_right; struct rb_node *rb_right;
struct rb_node *rb_left; struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long)))); } __attribute__((aligned(sizeof(long))));
/* The alignment might seem pointless, but allegedly CRIS needs it */ /* The alignment might seem pointless, but allegedly CRIS needs it */
struct rb_root struct rb_root
{ {
struct rb_node *rb_node; struct rb_node *rb_node;
}; };
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) #define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r) ((r)->rb_parent_color & 1) #define rb_color(r) ((r)->rb_parent_color & 1)
#define rb_is_red(r) (!rb_color(r)) #define rb_is_red(r) (!rb_color(r))
#define rb_is_black(r) rb_color(r) #define rb_is_black(r) rb_color(r)
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) #define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) #define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{ {
rb->rb_parent_color = (rb->rb_parent_color & 3) | (ULONG_PTR)p; rb->rb_parent_color = (rb->rb_parent_color & 3) | (ULONG_PTR)p;
} }
static inline void rb_set_color(struct rb_node *rb, ULONG_PTR color) static inline void rb_set_color(struct rb_node *rb, ULONG_PTR color)
{ {
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
} }
#define RB_ROOT (struct rb_root) { NULL, } #define RB_ROOT (struct rb_root) { NULL, }
#define rb_entry(ptr, type, member) container_of(ptr, type, member) #define rb_entry(ptr, type, member) container_of(ptr, type, member)
#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
#define RB_EMPTY_NODE(node) (rb_parent(node) != node) #define RB_EMPTY_NODE(node) (rb_parent(node) != node)
#define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) #define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
extern void rb_insert_color(struct rb_node *, struct rb_root *); extern void rb_insert_color(struct rb_node *, struct rb_root *);
extern void rb_erase(struct rb_node *, struct rb_root *); extern void rb_erase(struct rb_node *, struct rb_root *);
/* Find logical next and previous nodes in a tree */ /* Find logical next and previous nodes in a tree */
extern struct rb_node *rb_next(struct rb_node *); extern struct rb_node *rb_next(struct rb_node *);
extern struct rb_node *rb_prev(struct rb_node *); extern struct rb_node *rb_prev(struct rb_node *);
extern struct rb_node *rb_first(struct rb_root *); extern struct rb_node *rb_first(struct rb_root *);
extern struct rb_node *rb_last(struct rb_root *); extern struct rb_node *rb_last(struct rb_root *);
/* Fast replacement of a single node without remove/rebalance/add/rebalance */ /* Fast replacement of a single node without remove/rebalance/add/rebalance */
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
struct rb_root *root); struct rb_root *root);
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link) struct rb_node ** rb_link)
{ {
node->rb_parent_color = (ULONG_PTR )parent; node->rb_parent_color = (ULONG_PTR )parent;
node->rb_left = node->rb_right = NULL; node->rb_left = node->rb_right = NULL;
*rb_link = node; *rb_link = node;
} }
extern void rb_insert(struct rb_root *root, struct rb_node *node, extern void rb_insert(struct rb_root *root, struct rb_node *node,
int (*cmp)(struct rb_node *, struct rb_node *)); int (*cmp)(struct rb_node *, struct rb_node *));
#endif /* _LINUX_RBTREE_H */ #endif /* _LINUX_RBTREE_H */

View File

@@ -1,13 +1,13 @@
#ifndef _LINUX_STDDEF_H #ifndef _LINUX_STDDEF_H
#define _LINUX_STDDEF_H #define _LINUX_STDDEF_H
enum { enum {
false = 0, false = 0,
true = 1 true = 1
}; };
#ifndef offsetof #ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif #endif
#endif /* _LINUX_STDDEF_H */ #endif /* _LINUX_STDDEF_H */

View File

@@ -1,15 +1,15 @@
//{{NO_DEPENDENCIES}} //{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file. // Microsoft Developer Studio generated include file.
// Used by ext2fsd.rc // Used by ext2fsd.rc
// //
// Next default values for new objects // Next default values for new objects
// //
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104 #define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101 #define _APS_NEXT_SYMED_VALUE 101
#endif #endif
#endif #endif

View File

@@ -1,125 +1,125 @@
/* /*
* COPYRIGHT: See COPYRIGHT.TXT * COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: lock.c * FILE: lock.c
* PROGRAMMER: Matt Wu <mattwu@163.com> * PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com * HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "ext2fs.h" #include "ext2fs.h"
/* GLOBALS ***************************************************************/ /* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global; extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/ /* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2LockControl) #pragma alloc_text(PAGE, Ext2LockControl)
#endif #endif
NTSTATUS NTSTATUS
Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext) Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext)
{ {
PDEVICE_OBJECT DeviceObject = NULL; PDEVICE_OBJECT DeviceObject = NULL;
PFILE_OBJECT FileObject = NULL; PFILE_OBJECT FileObject = NULL;
PEXT2_FCB Fcb = NULL; PEXT2_FCB Fcb = NULL;
PIRP Irp = NULL; PIRP Irp = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL; NTSTATUS Status = STATUS_UNSUCCESSFUL;
BOOLEAN CompleteContext = TRUE; BOOLEAN CompleteContext = TRUE;
BOOLEAN CompleteIrp = TRUE; BOOLEAN CompleteIrp = TRUE;
BOOLEAN bFcbAcquired = FALSE; BOOLEAN bFcbAcquired = FALSE;
__try { __try {
ASSERT(IrpContext != NULL); ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject; DeviceObject = IrpContext->DeviceObject;
if (IsExt2FsDevice(DeviceObject)) { if (IsExt2FsDevice(DeviceObject)) {
Status = STATUS_INVALID_DEVICE_REQUEST; Status = STATUS_INVALID_DEVICE_REQUEST;
__leave; __leave;
} }
FileObject = IrpContext->FileObject; FileObject = IrpContext->FileObject;
Fcb = (PEXT2_FCB) FileObject->FsContext; Fcb = (PEXT2_FCB) FileObject->FsContext;
ASSERT(Fcb != NULL); ASSERT(Fcb != NULL);
if (Fcb->Identifier.Type == EXT2VCB) { if (Fcb->Identifier.Type == EXT2VCB) {
Status = STATUS_INVALID_PARAMETER; Status = STATUS_INVALID_PARAMETER;
__leave; __leave;
} }
ASSERT((Fcb->Identifier.Type == EXT2FCB) && ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB))); (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
if (FlagOn(Fcb->Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) { if (FlagOn(Fcb->Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
Status = STATUS_INVALID_PARAMETER; Status = STATUS_INVALID_PARAMETER;
__leave; __leave;
} }
ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE); ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE);
bFcbAcquired = TRUE; bFcbAcquired = TRUE;
Irp = IrpContext->Irp; Irp = IrpContext->Irp;
CompleteIrp = FALSE; CompleteIrp = FALSE;
Status = FsRtlCheckOplock( &Fcb->Oplock, Status = FsRtlCheckOplock( &Fcb->Oplock,
Irp, Irp,
IrpContext, IrpContext,
Ext2OplockComplete, Ext2OplockComplete,
NULL ); NULL );
if (Status != STATUS_SUCCESS) { if (Status != STATUS_SUCCESS) {
CompleteContext = FALSE; CompleteContext = FALSE;
__leave; __leave;
} }
// //
// FsRtlProcessFileLock acquires FileObject->FsContext->Resource while // FsRtlProcessFileLock acquires FileObject->FsContext->Resource while
// modifying the file locks and calls IoCompleteRequest when it's done. // modifying the file locks and calls IoCompleteRequest when it's done.
// //
Status = FsRtlProcessFileLock( Status = FsRtlProcessFileLock(
&Fcb->FileLockAnchor, &Fcb->FileLockAnchor,
Irp, Irp,
NULL ); NULL );
#if EXT2_DEBUG #if EXT2_DEBUG
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
DEBUG(DL_ERR, ( DEBUG(DL_ERR, (
"Ext2LockControl: %-16.16s %-31s Status: %#x ***\n", "Ext2LockControl: %-16.16s %-31s Status: %#x ***\n",
Ext2GetCurrentProcessName(), Ext2GetCurrentProcessName(),
"IRP_MJ_LOCK_CONTROL", "IRP_MJ_LOCK_CONTROL",
Status )); Status ));
} }
#endif #endif
Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
} __finally { } __finally {
if (bFcbAcquired) { if (bFcbAcquired) {
ExReleaseResourceLite(&Fcb->MainResource); ExReleaseResourceLite(&Fcb->MainResource);
} }
if (!IrpContext->ExceptionInProgress) { if (!IrpContext->ExceptionInProgress) {
if (!CompleteIrp) { if (!CompleteIrp) {
IrpContext->Irp = NULL; IrpContext->Irp = NULL;
} }
if (CompleteContext) { if (CompleteContext) {
Ext2CompleteIrpContext(IrpContext, Status); Ext2CompleteIrpContext(IrpContext, Status);
} }
} }
} }
return Status; return Status;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,232 +1,232 @@
/* /*
* COPYRIGHT: See COPYRIGHT.TXT * COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: nls.c * FILE: nls.c
* PROGRAMMER: Matt Wu <mattwu@163.com> * PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com * HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "ext2fs.h" #include "ext2fs.h"
/* GOBALS** ****************************************************************/ /* GOBALS** ****************************************************************/
extern struct nls_table *tables; extern struct nls_table *tables;
extern spinlock_t nls_lock; extern spinlock_t nls_lock;
/* DECLARES ****************************************************************/ /* DECLARES ****************************************************************/
#define FULL_CODEPAGES_SUPPORT #define FULL_CODEPAGES_SUPPORT
#ifdef FULL_CODEPAGES_SUPPORT #ifdef FULL_CODEPAGES_SUPPORT
DECLARE_INIT(init_nls_ascii); DECLARE_INIT(init_nls_ascii);
DECLARE_EXIT(exit_nls_ascii); DECLARE_EXIT(exit_nls_ascii);
DECLARE_INIT(init_nls_cp1250); DECLARE_INIT(init_nls_cp1250);
DECLARE_EXIT(exit_nls_cp1250); DECLARE_EXIT(exit_nls_cp1250);
DECLARE_INIT(init_nls_cp1251); DECLARE_INIT(init_nls_cp1251);
DECLARE_EXIT(exit_nls_cp1251); DECLARE_EXIT(exit_nls_cp1251);
DECLARE_INIT(init_nls_cp1255); DECLARE_INIT(init_nls_cp1255);
DECLARE_EXIT(exit_nls_cp1255); DECLARE_EXIT(exit_nls_cp1255);
DECLARE_INIT(init_nls_cp437); DECLARE_INIT(init_nls_cp437);
DECLARE_EXIT(exit_nls_cp437); DECLARE_EXIT(exit_nls_cp437);
DECLARE_INIT(init_nls_cp737); DECLARE_INIT(init_nls_cp737);
DECLARE_EXIT(exit_nls_cp737); DECLARE_EXIT(exit_nls_cp737);
DECLARE_INIT(init_nls_cp775); DECLARE_INIT(init_nls_cp775);
DECLARE_EXIT(exit_nls_cp775); DECLARE_EXIT(exit_nls_cp775);
DECLARE_INIT(init_nls_cp850); DECLARE_INIT(init_nls_cp850);
DECLARE_EXIT(exit_nls_cp850); DECLARE_EXIT(exit_nls_cp850);
DECLARE_INIT(init_nls_cp852); DECLARE_INIT(init_nls_cp852);
DECLARE_EXIT(exit_nls_cp852); DECLARE_EXIT(exit_nls_cp852);
DECLARE_INIT(init_nls_cp855); DECLARE_INIT(init_nls_cp855);
DECLARE_EXIT(exit_nls_cp855); DECLARE_EXIT(exit_nls_cp855);
DECLARE_INIT(init_nls_cp857); DECLARE_INIT(init_nls_cp857);
DECLARE_EXIT(exit_nls_cp857); DECLARE_EXIT(exit_nls_cp857);
DECLARE_INIT(init_nls_cp860); DECLARE_INIT(init_nls_cp860);
DECLARE_EXIT(exit_nls_cp860); DECLARE_EXIT(exit_nls_cp860);
DECLARE_INIT(init_nls_cp861); DECLARE_INIT(init_nls_cp861);
DECLARE_EXIT(exit_nls_cp861); DECLARE_EXIT(exit_nls_cp861);
DECLARE_INIT(init_nls_cp862); DECLARE_INIT(init_nls_cp862);
DECLARE_EXIT(exit_nls_cp862); DECLARE_EXIT(exit_nls_cp862);
DECLARE_INIT(init_nls_cp863); DECLARE_INIT(init_nls_cp863);
DECLARE_EXIT(exit_nls_cp863); DECLARE_EXIT(exit_nls_cp863);
DECLARE_INIT(init_nls_cp864); DECLARE_INIT(init_nls_cp864);
DECLARE_EXIT(exit_nls_cp864); DECLARE_EXIT(exit_nls_cp864);
DECLARE_INIT(init_nls_cp865); DECLARE_INIT(init_nls_cp865);
DECLARE_EXIT(exit_nls_cp865); DECLARE_EXIT(exit_nls_cp865);
DECLARE_INIT(init_nls_cp866); DECLARE_INIT(init_nls_cp866);
DECLARE_EXIT(exit_nls_cp866); DECLARE_EXIT(exit_nls_cp866);
DECLARE_INIT(init_nls_cp869); DECLARE_INIT(init_nls_cp869);
DECLARE_EXIT(exit_nls_cp869); DECLARE_EXIT(exit_nls_cp869);
DECLARE_INIT(init_nls_cp874); DECLARE_INIT(init_nls_cp874);
DECLARE_EXIT(exit_nls_cp874); DECLARE_EXIT(exit_nls_cp874);
DECLARE_INIT(init_nls_cp932); DECLARE_INIT(init_nls_cp932);
DECLARE_EXIT(exit_nls_cp932); DECLARE_EXIT(exit_nls_cp932);
DECLARE_INIT(init_nls_cp949); DECLARE_INIT(init_nls_cp949);
DECLARE_EXIT(exit_nls_cp949); DECLARE_EXIT(exit_nls_cp949);
DECLARE_INIT(init_nls_euc_jp); DECLARE_INIT(init_nls_euc_jp);
DECLARE_EXIT(exit_nls_euc_jp); DECLARE_EXIT(exit_nls_euc_jp);
DECLARE_INIT(init_nls_iso8859_1); DECLARE_INIT(init_nls_iso8859_1);
DECLARE_EXIT(exit_nls_iso8859_1); DECLARE_EXIT(exit_nls_iso8859_1);
DECLARE_INIT(init_nls_iso8859_13); DECLARE_INIT(init_nls_iso8859_13);
DECLARE_EXIT(exit_nls_iso8859_13); DECLARE_EXIT(exit_nls_iso8859_13);
DECLARE_INIT(init_nls_iso8859_14); DECLARE_INIT(init_nls_iso8859_14);
DECLARE_EXIT(exit_nls_iso8859_14); DECLARE_EXIT(exit_nls_iso8859_14);
DECLARE_INIT(init_nls_iso8859_15); DECLARE_INIT(init_nls_iso8859_15);
DECLARE_EXIT(exit_nls_iso8859_15); DECLARE_EXIT(exit_nls_iso8859_15);
DECLARE_INIT(init_nls_iso8859_2); DECLARE_INIT(init_nls_iso8859_2);
DECLARE_EXIT(exit_nls_iso8859_2); DECLARE_EXIT(exit_nls_iso8859_2);
DECLARE_INIT(init_nls_iso8859_3); DECLARE_INIT(init_nls_iso8859_3);
DECLARE_EXIT(exit_nls_iso8859_3); DECLARE_EXIT(exit_nls_iso8859_3);
DECLARE_INIT(init_nls_iso8859_4); DECLARE_INIT(init_nls_iso8859_4);
DECLARE_EXIT(exit_nls_iso8859_4); DECLARE_EXIT(exit_nls_iso8859_4);
DECLARE_INIT(init_nls_iso8859_5); DECLARE_INIT(init_nls_iso8859_5);
DECLARE_EXIT(exit_nls_iso8859_5); DECLARE_EXIT(exit_nls_iso8859_5);
DECLARE_INIT(init_nls_iso8859_6); DECLARE_INIT(init_nls_iso8859_6);
DECLARE_EXIT(exit_nls_iso8859_6); DECLARE_EXIT(exit_nls_iso8859_6);
DECLARE_INIT(init_nls_iso8859_7); DECLARE_INIT(init_nls_iso8859_7);
DECLARE_EXIT(exit_nls_iso8859_7); DECLARE_EXIT(exit_nls_iso8859_7);
DECLARE_INIT(init_nls_iso8859_9); DECLARE_INIT(init_nls_iso8859_9);
DECLARE_EXIT(exit_nls_iso8859_9); DECLARE_EXIT(exit_nls_iso8859_9);
DECLARE_INIT(init_nls_koi8_r); DECLARE_INIT(init_nls_koi8_r);
DECLARE_EXIT(exit_nls_koi8_r); DECLARE_EXIT(exit_nls_koi8_r);
DECLARE_INIT(init_nls_koi8_ru); DECLARE_INIT(init_nls_koi8_ru);
DECLARE_EXIT(exit_nls_koi8_ru); DECLARE_EXIT(exit_nls_koi8_ru);
DECLARE_INIT(init_nls_koi8_u); DECLARE_INIT(init_nls_koi8_u);
DECLARE_EXIT(exit_nls_koi8_u); DECLARE_EXIT(exit_nls_koi8_u);
#endif //FULL_CODEPAGES_SUPPORT #endif //FULL_CODEPAGES_SUPPORT
/* gb2312 */ /* gb2312 */
DECLARE_INIT(init_nls_cp936); DECLARE_INIT(init_nls_cp936);
DECLARE_EXIT(exit_nls_cp936); DECLARE_EXIT(exit_nls_cp936);
/* big5 */ /* big5 */
DECLARE_INIT(init_nls_cp950); DECLARE_INIT(init_nls_cp950);
DECLARE_EXIT(exit_nls_cp950); DECLARE_EXIT(exit_nls_cp950);
/* utf8 */ /* utf8 */
DECLARE_INIT(init_nls_utf8); DECLARE_INIT(init_nls_utf8);
DECLARE_EXIT(exit_nls_utf8); DECLARE_EXIT(exit_nls_utf8);
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
int int
Ext2LoadAllNls() Ext2LoadAllNls()
{ {
int rc; int rc;
tables = NULL; tables = NULL;
spin_lock_init(&nls_lock); spin_lock_init(&nls_lock);
/* loading utf8 ... */ /* loading utf8 ... */
LOAD_NLS(init_nls_utf8); LOAD_NLS(init_nls_utf8);
#ifdef FULL_CODEPAGES_SUPPORT #ifdef FULL_CODEPAGES_SUPPORT
/* loading chinese gb2312 and big5... */ /* loading chinese gb2312 and big5... */
LOAD_NLS(init_nls_cp936); LOAD_NLS(init_nls_cp936);
LOAD_NLS(init_nls_cp950); LOAD_NLS(init_nls_cp950);
/* loading all others */ /* loading all others */
LOAD_NLS(init_nls_ascii); LOAD_NLS(init_nls_ascii);
LOAD_NLS(init_nls_cp1250); LOAD_NLS(init_nls_cp1250);
LOAD_NLS(init_nls_cp1251); LOAD_NLS(init_nls_cp1251);
LOAD_NLS(init_nls_cp1255); LOAD_NLS(init_nls_cp1255);
LOAD_NLS(init_nls_cp437); LOAD_NLS(init_nls_cp437);
LOAD_NLS(init_nls_cp737); LOAD_NLS(init_nls_cp737);
LOAD_NLS(init_nls_cp775); LOAD_NLS(init_nls_cp775);
LOAD_NLS(init_nls_cp850); LOAD_NLS(init_nls_cp850);
LOAD_NLS(init_nls_cp852); LOAD_NLS(init_nls_cp852);
LOAD_NLS(init_nls_cp855); LOAD_NLS(init_nls_cp855);
LOAD_NLS(init_nls_cp857); LOAD_NLS(init_nls_cp857);
LOAD_NLS(init_nls_cp860); LOAD_NLS(init_nls_cp860);
LOAD_NLS(init_nls_cp861); LOAD_NLS(init_nls_cp861);
LOAD_NLS(init_nls_cp862); LOAD_NLS(init_nls_cp862);
LOAD_NLS(init_nls_cp863); LOAD_NLS(init_nls_cp863);
LOAD_NLS(init_nls_cp864); LOAD_NLS(init_nls_cp864);
LOAD_NLS(init_nls_cp865); LOAD_NLS(init_nls_cp865);
LOAD_NLS(init_nls_cp866); LOAD_NLS(init_nls_cp866);
LOAD_NLS(init_nls_cp869); LOAD_NLS(init_nls_cp869);
LOAD_NLS(init_nls_cp874); LOAD_NLS(init_nls_cp874);
LOAD_NLS(init_nls_cp932); LOAD_NLS(init_nls_cp932);
LOAD_NLS(init_nls_euc_jp); LOAD_NLS(init_nls_euc_jp);
LOAD_NLS(init_nls_cp949); LOAD_NLS(init_nls_cp949);
LOAD_NLS(init_nls_iso8859_1); LOAD_NLS(init_nls_iso8859_1);
LOAD_NLS(init_nls_iso8859_13); LOAD_NLS(init_nls_iso8859_13);
LOAD_NLS(init_nls_iso8859_14); LOAD_NLS(init_nls_iso8859_14);
LOAD_NLS(init_nls_iso8859_15); LOAD_NLS(init_nls_iso8859_15);
LOAD_NLS(init_nls_iso8859_2); LOAD_NLS(init_nls_iso8859_2);
LOAD_NLS(init_nls_iso8859_3); LOAD_NLS(init_nls_iso8859_3);
LOAD_NLS(init_nls_iso8859_4); LOAD_NLS(init_nls_iso8859_4);
LOAD_NLS(init_nls_iso8859_5); LOAD_NLS(init_nls_iso8859_5);
LOAD_NLS(init_nls_iso8859_6); LOAD_NLS(init_nls_iso8859_6);
LOAD_NLS(init_nls_iso8859_7); LOAD_NLS(init_nls_iso8859_7);
LOAD_NLS(init_nls_iso8859_9); LOAD_NLS(init_nls_iso8859_9);
LOAD_NLS(init_nls_koi8_r); LOAD_NLS(init_nls_koi8_r);
LOAD_NLS(init_nls_koi8_u); LOAD_NLS(init_nls_koi8_u);
LOAD_NLS(init_nls_koi8_ru); LOAD_NLS(init_nls_koi8_ru);
#endif //FULL_CODEPAGES_SUPPORT #endif //FULL_CODEPAGES_SUPPORT
return rc; return rc;
} }
VOID VOID
Ext2UnloadAllNls() Ext2UnloadAllNls()
{ {
#ifdef FULL_CODEPAGES_SUPPORT #ifdef FULL_CODEPAGES_SUPPORT
UNLOAD_NLS(init_nls_ascii); UNLOAD_NLS(init_nls_ascii);
UNLOAD_NLS(init_nls_cp1250); UNLOAD_NLS(init_nls_cp1250);
UNLOAD_NLS(exit_nls_cp1251); UNLOAD_NLS(exit_nls_cp1251);
UNLOAD_NLS(exit_nls_cp1255); UNLOAD_NLS(exit_nls_cp1255);
UNLOAD_NLS(exit_nls_cp437); UNLOAD_NLS(exit_nls_cp437);
UNLOAD_NLS(exit_nls_cp737); UNLOAD_NLS(exit_nls_cp737);
UNLOAD_NLS(exit_nls_cp775); UNLOAD_NLS(exit_nls_cp775);
UNLOAD_NLS(exit_nls_cp850); UNLOAD_NLS(exit_nls_cp850);
UNLOAD_NLS(exit_nls_cp852); UNLOAD_NLS(exit_nls_cp852);
UNLOAD_NLS(exit_nls_cp855); UNLOAD_NLS(exit_nls_cp855);
UNLOAD_NLS(exit_nls_cp857); UNLOAD_NLS(exit_nls_cp857);
UNLOAD_NLS(exit_nls_cp860); UNLOAD_NLS(exit_nls_cp860);
UNLOAD_NLS(exit_nls_cp861); UNLOAD_NLS(exit_nls_cp861);
UNLOAD_NLS(exit_nls_cp862); UNLOAD_NLS(exit_nls_cp862);
UNLOAD_NLS(exit_nls_cp863); UNLOAD_NLS(exit_nls_cp863);
UNLOAD_NLS(exit_nls_cp864); UNLOAD_NLS(exit_nls_cp864);
UNLOAD_NLS(exit_nls_cp865); UNLOAD_NLS(exit_nls_cp865);
UNLOAD_NLS(exit_nls_cp866); UNLOAD_NLS(exit_nls_cp866);
UNLOAD_NLS(exit_nls_cp869); UNLOAD_NLS(exit_nls_cp869);
UNLOAD_NLS(exit_nls_cp874); UNLOAD_NLS(exit_nls_cp874);
UNLOAD_NLS(exit_nls_euc_jp); UNLOAD_NLS(exit_nls_euc_jp);
UNLOAD_NLS(exit_nls_cp932); UNLOAD_NLS(exit_nls_cp932);
UNLOAD_NLS(exit_nls_cp949); UNLOAD_NLS(exit_nls_cp949);
UNLOAD_NLS(exit_nls_iso8859_1); UNLOAD_NLS(exit_nls_iso8859_1);
UNLOAD_NLS(exit_nls_iso8859_13); UNLOAD_NLS(exit_nls_iso8859_13);
UNLOAD_NLS(exit_nls_iso8859_14); UNLOAD_NLS(exit_nls_iso8859_14);
UNLOAD_NLS(exit_nls_iso8859_15); UNLOAD_NLS(exit_nls_iso8859_15);
UNLOAD_NLS(exit_nls_iso8859_2); UNLOAD_NLS(exit_nls_iso8859_2);
UNLOAD_NLS(exit_nls_iso8859_3); UNLOAD_NLS(exit_nls_iso8859_3);
UNLOAD_NLS(exit_nls_iso8859_4); UNLOAD_NLS(exit_nls_iso8859_4);
UNLOAD_NLS(exit_nls_iso8859_5); UNLOAD_NLS(exit_nls_iso8859_5);
UNLOAD_NLS(exit_nls_iso8859_6); UNLOAD_NLS(exit_nls_iso8859_6);
UNLOAD_NLS(exit_nls_iso8859_7); UNLOAD_NLS(exit_nls_iso8859_7);
UNLOAD_NLS(exit_nls_iso8859_9); UNLOAD_NLS(exit_nls_iso8859_9);
UNLOAD_NLS(exit_nls_koi8_ru); UNLOAD_NLS(exit_nls_koi8_ru);
UNLOAD_NLS(exit_nls_koi8_r); UNLOAD_NLS(exit_nls_koi8_r);
UNLOAD_NLS(exit_nls_koi8_u); UNLOAD_NLS(exit_nls_koi8_u);
/* unloading chinese codepages */ /* unloading chinese codepages */
UNLOAD_NLS(exit_nls_cp950); UNLOAD_NLS(exit_nls_cp950);
UNLOAD_NLS(exit_nls_cp936); UNLOAD_NLS(exit_nls_cp936);
#endif //FULL_CODEPAGES_SUPPORT #endif //FULL_CODEPAGES_SUPPORT
/* unloading nls of utf8 */ /* unloading nls of utf8 */
UNLOAD_NLS(exit_nls_utf8); UNLOAD_NLS(exit_nls_utf8);
} }

View File

@@ -1,397 +1,397 @@
/* /*
* COPYRIGHT: See COPYRIGHT.TXT * COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: pnp.c * FILE: pnp.c
* PROGRAMMER: Matt Wu <mattwu@163.com> * PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com * HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */
#if (_WIN32_WINNT >= 0x0500) #if (_WIN32_WINNT >= 0x0500)
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "ext2fs.h" #include "ext2fs.h"
/* GLOBALS ***************************************************************/ /* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global; extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/ /* DEFINITIONS *************************************************************/
NTSTATUS NTSTATUS
Ext2PnpCompletionRoutine ( Ext2PnpCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp, IN PIRP Irp,
IN PVOID Contxt ); IN PVOID Contxt );
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2Pnp) #pragma alloc_text(PAGE, Ext2Pnp)
#pragma alloc_text(PAGE, Ext2PnpQueryRemove) #pragma alloc_text(PAGE, Ext2PnpQueryRemove)
#pragma alloc_text(PAGE, Ext2PnpRemove) #pragma alloc_text(PAGE, Ext2PnpRemove)
#pragma alloc_text(PAGE, Ext2PnpCancelRemove) #pragma alloc_text(PAGE, Ext2PnpCancelRemove)
#pragma alloc_text(PAGE, Ext2PnpSurpriseRemove) #pragma alloc_text(PAGE, Ext2PnpSurpriseRemove)
#endif #endif
/* FUNCTIONS *************************************************************/ /* FUNCTIONS *************************************************************/
NTSTATUS NTSTATUS
Ext2PnpCompletionRoutine ( Ext2PnpCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp, IN PIRP Irp,
IN PVOID Contxt IN PVOID Contxt
) )
{ {
PKEVENT Event = (PKEVENT) Contxt; PKEVENT Event = (PKEVENT) Contxt;
KeSetEvent( Event, 0, FALSE ); KeSetEvent( Event, 0, FALSE );
return STATUS_MORE_PROCESSING_REQUIRED; return STATUS_MORE_PROCESSING_REQUIRED;
UNREFERENCED_PARAMETER( DeviceObject ); UNREFERENCED_PARAMETER( DeviceObject );
UNREFERENCED_PARAMETER( Contxt ); UNREFERENCED_PARAMETER( Contxt );
} }
NTSTATUS NTSTATUS
Ext2Pnp (IN PEXT2_IRP_CONTEXT IrpContext) Ext2Pnp (IN PEXT2_IRP_CONTEXT IrpContext)
{ {
NTSTATUS Status = STATUS_INVALID_PARAMETER; NTSTATUS Status = STATUS_INVALID_PARAMETER;
PIRP Irp; PIRP Irp;
PIO_STACK_LOCATION IrpSp; PIO_STACK_LOCATION IrpSp;
PEXT2_VCB Vcb = NULL; PEXT2_VCB Vcb = NULL;
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
__try { __try {
ASSERT(IrpContext); ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject; DeviceObject = IrpContext->DeviceObject;
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL); ASSERT(Vcb != NULL);
if ( !((Vcb->Identifier.Type == EXT2VCB) && if ( !((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB)))) { (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) {
__leave; // Status = STATUS_INVALID_PARAMETER __leave; // Status = STATUS_INVALID_PARAMETER
} }
Irp = IrpContext->Irp; Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp); IrpSp = IoGetCurrentIrpStackLocation(Irp);
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
switch ( IrpSp->MinorFunction ) { switch ( IrpSp->MinorFunction ) {
case IRP_MN_QUERY_REMOVE_DEVICE: case IRP_MN_QUERY_REMOVE_DEVICE:
DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpQueryRemove...\n")); DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpQueryRemove...\n"));
Status = Ext2PnpQueryRemove(IrpContext, Vcb); Status = Ext2PnpQueryRemove(IrpContext, Vcb);
break; break;
case IRP_MN_REMOVE_DEVICE: case IRP_MN_REMOVE_DEVICE:
DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpRemove...\n")); DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpRemove...\n"));
Status = Ext2PnpRemove(IrpContext, Vcb); Status = Ext2PnpRemove(IrpContext, Vcb);
break; break;
case IRP_MN_CANCEL_REMOVE_DEVICE: case IRP_MN_CANCEL_REMOVE_DEVICE:
DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpCancelRemove...\n")); DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpCancelRemove...\n"));
Status = Ext2PnpCancelRemove(IrpContext, Vcb); Status = Ext2PnpCancelRemove(IrpContext, Vcb);
break; break;
case IRP_MN_SURPRISE_REMOVAL: case IRP_MN_SURPRISE_REMOVAL:
DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpSupriseRemove...\n")); DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpSupriseRemove...\n"));
Status = Ext2PnpSurpriseRemove(IrpContext, Vcb); Status = Ext2PnpSurpriseRemove(IrpContext, Vcb);
break; break;
default: default:
break; break;
} }
} __finally { } __finally {
if (!IrpContext->ExceptionInProgress) { if (!IrpContext->ExceptionInProgress) {
Irp = IrpContext->Irp; Irp = IrpContext->Irp;
if (Irp) { if (Irp) {
// //
// Here we need pass the IRP to the disk driver. // Here we need pass the IRP to the disk driver.
// //
IoSkipCurrentIrpStackLocation( Irp ); IoSkipCurrentIrpStackLocation( Irp );
Status = IoCallDriver(Vcb->TargetDeviceObject, Irp); Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
IrpContext->Irp = NULL; IrpContext->Irp = NULL;
} }
Ext2CompleteIrpContext(IrpContext, Status); Ext2CompleteIrpContext(IrpContext, Status);
} }
} }
return Status; return Status;
} }
NTSTATUS NTSTATUS
Ext2PnpQueryRemove ( Ext2PnpQueryRemove (
PEXT2_IRP_CONTEXT IrpContext, PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb PEXT2_VCB Vcb
) )
{ {
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
KEVENT Event; KEVENT Event;
BOOLEAN bDeleted = FALSE; BOOLEAN bDeleted = FALSE;
BOOLEAN VcbAcquired = FALSE; BOOLEAN VcbAcquired = FALSE;
__try { __try {
CcWaitForCurrentLazyWriterActivity(); CcWaitForCurrentLazyWriterActivity();
VcbAcquired = ExAcquireResourceExclusiveLite( VcbAcquired = ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE ); &Vcb->MainResource, TRUE );
Ext2FlushFiles(IrpContext, Vcb, FALSE); Ext2FlushFiles(IrpContext, Vcb, FALSE);
Ext2FlushVolume(IrpContext, Vcb, FALSE); Ext2FlushVolume(IrpContext, Vcb, FALSE);
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2LockVcb: Vcb=%xh FileObject=%xh ...\n", DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2LockVcb: Vcb=%xh FileObject=%xh ...\n",
Vcb, IrpContext->FileObject)); Vcb, IrpContext->FileObject));
Status = Ext2LockVcb(Vcb, IrpContext->FileObject); Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
if (VcbAcquired) { if (VcbAcquired) {
ExReleaseResourceLite(&Vcb->MainResource); ExReleaseResourceLite(&Vcb->MainResource);
VcbAcquired = FALSE; VcbAcquired = FALSE;
} }
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2PurgeVolume ...\n")); DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2PurgeVolume ...\n"));
Ext2PurgeVolume(Vcb, TRUE); Ext2PurgeVolume(Vcb, TRUE);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
__leave; __leave;
} }
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
KeInitializeEvent( &Event, NotificationEvent, FALSE ); KeInitializeEvent( &Event, NotificationEvent, FALSE );
IoSetCompletionRoutine( IrpContext->Irp, IoSetCompletionRoutine( IrpContext->Irp,
Ext2PnpCompletionRoutine, Ext2PnpCompletionRoutine,
&Event, &Event,
TRUE, TRUE,
TRUE, TRUE,
TRUE ); TRUE );
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Call lower level driver...\n")); DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Call lower level driver...\n"));
Status = IoCallDriver( Vcb->TargetDeviceObject, Status = IoCallDriver( Vcb->TargetDeviceObject,
IrpContext->Irp); IrpContext->Irp);
if (Status == STATUS_PENDING) { if (Status == STATUS_PENDING) {
KeWaitForSingleObject( &Event, KeWaitForSingleObject( &Event,
Executive, Executive,
KernelMode, KernelMode,
FALSE, FALSE,
NULL ); NULL );
Status = IrpContext->Irp->IoStatus.Status; Status = IrpContext->Irp->IoStatus.Status;
} }
if (NT_SUCCESS(Status)) { if (NT_SUCCESS(Status)) {
ASSERT(!VcbAcquired); ASSERT(!VcbAcquired);
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2CheckDismount ...\n")); DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2CheckDismount ...\n"));
bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2FlushVolume bDelted=%xh ...\n", bDeleted)); DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2FlushVolume bDelted=%xh ...\n", bDeleted));
} }
} __finally { } __finally {
if (VcbAcquired) { if (VcbAcquired) {
ExReleaseResourceLite(&Vcb->MainResource); ExReleaseResourceLite(&Vcb->MainResource);
} }
IrpContext->Irp->IoStatus.Status = Status; IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest( Ext2CompleteRequest(
IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
IO_DISK_INCREMENT : IO_NO_INCREMENT) ); IO_DISK_INCREMENT : IO_NO_INCREMENT) );
IrpContext->Irp = NULL; IrpContext->Irp = NULL;
} }
return Status; return Status;
} }
NTSTATUS NTSTATUS
Ext2PnpRemove ( Ext2PnpRemove (
PEXT2_IRP_CONTEXT IrpContext, PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb ) PEXT2_VCB Vcb )
{ {
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
KEVENT Event; KEVENT Event;
BOOLEAN bDeleted; BOOLEAN bDeleted;
__try { __try {
DEBUG(DL_PNP, ("Ext2PnpRemove by Ext2Pnp ...\n")); DEBUG(DL_PNP, ("Ext2PnpRemove by Ext2Pnp ...\n"));
CcWaitForCurrentLazyWriterActivity(); CcWaitForCurrentLazyWriterActivity();
ExAcquireResourceExclusiveLite( ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE ); &Vcb->MainResource, TRUE );
Status = Ext2LockVcb(Vcb, IrpContext->FileObject); Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
ExReleaseResourceLite(&Vcb->MainResource); ExReleaseResourceLite(&Vcb->MainResource);
// //
// Setup the Irp. We'll send it to the lower disk driver. // Setup the Irp. We'll send it to the lower disk driver.
// //
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
KeInitializeEvent( &Event, NotificationEvent, FALSE ); KeInitializeEvent( &Event, NotificationEvent, FALSE );
IoSetCompletionRoutine( IrpContext->Irp, IoSetCompletionRoutine( IrpContext->Irp,
Ext2PnpCompletionRoutine, Ext2PnpCompletionRoutine,
&Event, &Event,
TRUE, TRUE,
TRUE, TRUE,
TRUE ); TRUE );
Status = IoCallDriver( Vcb->TargetDeviceObject, Status = IoCallDriver( Vcb->TargetDeviceObject,
IrpContext->Irp); IrpContext->Irp);
if (Status == STATUS_PENDING) { if (Status == STATUS_PENDING) {
KeWaitForSingleObject( &Event, KeWaitForSingleObject( &Event,
Executive, Executive,
KernelMode, KernelMode,
FALSE, FALSE,
NULL ); NULL );
Status = IrpContext->Irp->IoStatus.Status; Status = IrpContext->Irp->IoStatus.Status;
} }
/* purge volume cache */ /* purge volume cache */
Ext2PurgeVolume(Vcb, FALSE); Ext2PurgeVolume(Vcb, FALSE);
/* dismount volume */ /* dismount volume */
bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED); SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED);
} __finally { } __finally {
IrpContext->Irp->IoStatus.Status = Status; IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest( Ext2CompleteRequest(
IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
IO_DISK_INCREMENT : IO_NO_INCREMENT) ); IO_DISK_INCREMENT : IO_NO_INCREMENT) );
IrpContext->Irp = NULL; IrpContext->Irp = NULL;
} }
return Status; return Status;
} }
NTSTATUS NTSTATUS
Ext2PnpSurpriseRemove ( Ext2PnpSurpriseRemove (
PEXT2_IRP_CONTEXT IrpContext, PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb ) PEXT2_VCB Vcb )
{ {
NTSTATUS Status; NTSTATUS Status;
KEVENT Event; KEVENT Event;
BOOLEAN bDeleted; BOOLEAN bDeleted;
__try { __try {
DEBUG(DL_PNP, ("Ext2PnpSupriseRemove by Ext2Pnp ...\n")); DEBUG(DL_PNP, ("Ext2PnpSupriseRemove by Ext2Pnp ...\n"));
CcWaitForCurrentLazyWriterActivity(); CcWaitForCurrentLazyWriterActivity();
ExAcquireResourceExclusiveLite( ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE ); &Vcb->MainResource, TRUE );
Status = Ext2LockVcb(Vcb, IrpContext->FileObject); Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
ExReleaseResourceLite(&Vcb->MainResource); ExReleaseResourceLite(&Vcb->MainResource);
// //
// Setup the Irp. We'll send it to the lower disk driver. // Setup the Irp. We'll send it to the lower disk driver.
// //
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
KeInitializeEvent( &Event, NotificationEvent, FALSE ); KeInitializeEvent( &Event, NotificationEvent, FALSE );
IoSetCompletionRoutine( IrpContext->Irp, IoSetCompletionRoutine( IrpContext->Irp,
Ext2PnpCompletionRoutine, Ext2PnpCompletionRoutine,
&Event, &Event,
TRUE, TRUE,
TRUE, TRUE,
TRUE ); TRUE );
Status = IoCallDriver( Vcb->TargetDeviceObject, Status = IoCallDriver( Vcb->TargetDeviceObject,
IrpContext->Irp); IrpContext->Irp);
if (Status == STATUS_PENDING) { if (Status == STATUS_PENDING) {
KeWaitForSingleObject( &Event, KeWaitForSingleObject( &Event,
Executive, Executive,
KernelMode, KernelMode,
FALSE, FALSE,
NULL ); NULL );
Status = IrpContext->Irp->IoStatus.Status; Status = IrpContext->Irp->IoStatus.Status;
} }
/* purge volume cache */ /* purge volume cache */
Ext2PurgeVolume(Vcb, FALSE); Ext2PurgeVolume(Vcb, FALSE);
/* dismount volume */ /* dismount volume */
bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE); bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED); SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED);
} __finally { } __finally {
IrpContext->Irp->IoStatus.Status = Status; IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest( Ext2CompleteRequest(
IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)? IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
IO_DISK_INCREMENT : IO_NO_INCREMENT) ); IO_DISK_INCREMENT : IO_NO_INCREMENT) );
IrpContext->Irp = NULL; IrpContext->Irp = NULL;
} }
return Status; return Status;
} }
NTSTATUS NTSTATUS
Ext2PnpCancelRemove ( Ext2PnpCancelRemove (
PEXT2_IRP_CONTEXT IrpContext, PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb PEXT2_VCB Vcb
) )
{ {
NTSTATUS Status; NTSTATUS Status;
DEBUG(DL_PNP, ("Ext2PnpCancelRemove by Ext2Pnp ...\n")); DEBUG(DL_PNP, ("Ext2PnpCancelRemove by Ext2Pnp ...\n"));
ExAcquireResourceExclusiveLite( ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE ); &Vcb->MainResource, TRUE );
Status = Ext2UnlockVcb(Vcb, IrpContext->FileObject); Status = Ext2UnlockVcb(Vcb, IrpContext->FileObject);
ExReleaseResourceLite(&Vcb->MainResource); ExReleaseResourceLite(&Vcb->MainResource);
IoSkipCurrentIrpStackLocation(IrpContext->Irp); IoSkipCurrentIrpStackLocation(IrpContext->Irp);
Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp); Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp);
IrpContext->Irp = NULL; IrpContext->Irp = NULL;
return Status; return Status;
} }
#endif //(_WIN32_WINNT >= 0x0500) #endif //(_WIN32_WINNT >= 0x0500)

View File

@@ -1,415 +1,415 @@
/* /*
Red Black Trees Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de> (C) 1999 Andrea Arcangeli <andrea@suse.de>
(C) 2002 David Woodhouse <dwmw2@infradead.org> (C) 2002 David Woodhouse <dwmw2@infradead.org>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
linux/lib/rbtree.c linux/lib/rbtree.c
*/ */
#include <linux/module.h> #include <linux/module.h>
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
{ {
struct rb_node *right = node->rb_right; struct rb_node *right = node->rb_right;
struct rb_node *parent = rb_parent(node); struct rb_node *parent = rb_parent(node);
if ((node->rb_right = right->rb_left)) if ((node->rb_right = right->rb_left))
rb_set_parent(right->rb_left, node); rb_set_parent(right->rb_left, node);
right->rb_left = node; right->rb_left = node;
rb_set_parent(right, parent); rb_set_parent(right, parent);
if (parent) if (parent)
{ {
if (node == parent->rb_left) if (node == parent->rb_left)
parent->rb_left = right; parent->rb_left = right;
else else
parent->rb_right = right; parent->rb_right = right;
} }
else else
root->rb_node = right; root->rb_node = right;
rb_set_parent(node, right); rb_set_parent(node, right);
} }
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
{ {
struct rb_node *left = node->rb_left; struct rb_node *left = node->rb_left;
struct rb_node *parent = rb_parent(node); struct rb_node *parent = rb_parent(node);
if ((node->rb_left = left->rb_right)) if ((node->rb_left = left->rb_right))
rb_set_parent(left->rb_right, node); rb_set_parent(left->rb_right, node);
left->rb_right = node; left->rb_right = node;
rb_set_parent(left, parent); rb_set_parent(left, parent);
if (parent) if (parent)
{ {
if (node == parent->rb_right) if (node == parent->rb_right)
parent->rb_right = left; parent->rb_right = left;
else else
parent->rb_left = left; parent->rb_left = left;
} }
else else
root->rb_node = left; root->rb_node = left;
rb_set_parent(node, left); rb_set_parent(node, left);
} }
void rb_insert_color(struct rb_node *node, struct rb_root *root) void rb_insert_color(struct rb_node *node, struct rb_root *root)
{ {
struct rb_node *parent, *gparent; struct rb_node *parent, *gparent;
while ((parent = rb_parent(node)) && rb_is_red(parent)) while ((parent = rb_parent(node)) && rb_is_red(parent))
{ {
gparent = rb_parent(parent); gparent = rb_parent(parent);
if (parent == gparent->rb_left) if (parent == gparent->rb_left)
{ {
{ {
register struct rb_node *uncle = gparent->rb_right; register struct rb_node *uncle = gparent->rb_right;
if (uncle && rb_is_red(uncle)) if (uncle && rb_is_red(uncle))
{ {
rb_set_black(uncle); rb_set_black(uncle);
rb_set_black(parent); rb_set_black(parent);
rb_set_red(gparent); rb_set_red(gparent);
node = gparent; node = gparent;
continue; continue;
} }
} }
if (parent->rb_right == node) if (parent->rb_right == node)
{ {
register struct rb_node *tmp; register struct rb_node *tmp;
__rb_rotate_left(parent, root); __rb_rotate_left(parent, root);
tmp = parent; tmp = parent;
parent = node; parent = node;
node = tmp; node = tmp;
} }
rb_set_black(parent); rb_set_black(parent);
rb_set_red(gparent); rb_set_red(gparent);
__rb_rotate_right(gparent, root); __rb_rotate_right(gparent, root);
} else { } else {
{ {
register struct rb_node *uncle = gparent->rb_left; register struct rb_node *uncle = gparent->rb_left;
if (uncle && rb_is_red(uncle)) if (uncle && rb_is_red(uncle))
{ {
rb_set_black(uncle); rb_set_black(uncle);
rb_set_black(parent); rb_set_black(parent);
rb_set_red(gparent); rb_set_red(gparent);
node = gparent; node = gparent;
continue; continue;
} }
} }
if (parent->rb_left == node) if (parent->rb_left == node)
{ {
register struct rb_node *tmp; register struct rb_node *tmp;
__rb_rotate_right(parent, root); __rb_rotate_right(parent, root);
tmp = parent; tmp = parent;
parent = node; parent = node;
node = tmp; node = tmp;
} }
rb_set_black(parent); rb_set_black(parent);
rb_set_red(gparent); rb_set_red(gparent);
__rb_rotate_left(gparent, root); __rb_rotate_left(gparent, root);
} }
} }
rb_set_black(root->rb_node); rb_set_black(root->rb_node);
} }
EXPORT_SYMBOL(rb_insert_color); EXPORT_SYMBOL(rb_insert_color);
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
struct rb_root *root) struct rb_root *root)
{ {
struct rb_node *other; struct rb_node *other;
while ((!node || rb_is_black(node)) && node != root->rb_node) while ((!node || rb_is_black(node)) && node != root->rb_node)
{ {
if (parent->rb_left == node) if (parent->rb_left == node)
{ {
other = parent->rb_right; other = parent->rb_right;
if (rb_is_red(other)) if (rb_is_red(other))
{ {
rb_set_black(other); rb_set_black(other);
rb_set_red(parent); rb_set_red(parent);
__rb_rotate_left(parent, root); __rb_rotate_left(parent, root);
other = parent->rb_right; other = parent->rb_right;
} }
if ((!other->rb_left || rb_is_black(other->rb_left)) && if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right))) (!other->rb_right || rb_is_black(other->rb_right)))
{ {
rb_set_red(other); rb_set_red(other);
node = parent; node = parent;
parent = rb_parent(node); parent = rb_parent(node);
} }
else else
{ {
if (!other->rb_right || rb_is_black(other->rb_right)) if (!other->rb_right || rb_is_black(other->rb_right))
{ {
struct rb_node *o_left; struct rb_node *o_left;
if ((o_left = other->rb_left)) if ((o_left = other->rb_left))
rb_set_black(o_left); rb_set_black(o_left);
rb_set_red(other); rb_set_red(other);
__rb_rotate_right(other, root); __rb_rotate_right(other, root);
other = parent->rb_right; other = parent->rb_right;
} }
rb_set_color(other, rb_color(parent)); rb_set_color(other, rb_color(parent));
rb_set_black(parent); rb_set_black(parent);
if (other->rb_right) if (other->rb_right)
rb_set_black(other->rb_right); rb_set_black(other->rb_right);
__rb_rotate_left(parent, root); __rb_rotate_left(parent, root);
node = root->rb_node; node = root->rb_node;
break; break;
} }
} }
else else
{ {
other = parent->rb_left; other = parent->rb_left;
if (rb_is_red(other)) if (rb_is_red(other))
{ {
rb_set_black(other); rb_set_black(other);
rb_set_red(parent); rb_set_red(parent);
__rb_rotate_right(parent, root); __rb_rotate_right(parent, root);
other = parent->rb_left; other = parent->rb_left;
} }
if ((!other->rb_left || rb_is_black(other->rb_left)) && if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right))) (!other->rb_right || rb_is_black(other->rb_right)))
{ {
rb_set_red(other); rb_set_red(other);
node = parent; node = parent;
parent = rb_parent(node); parent = rb_parent(node);
} }
else else
{ {
if (!other->rb_left || rb_is_black(other->rb_left)) if (!other->rb_left || rb_is_black(other->rb_left))
{ {
register struct rb_node *o_right; register struct rb_node *o_right;
if ((o_right = other->rb_right)) if ((o_right = other->rb_right))
rb_set_black(o_right); rb_set_black(o_right);
rb_set_red(other); rb_set_red(other);
__rb_rotate_left(other, root); __rb_rotate_left(other, root);
other = parent->rb_left; other = parent->rb_left;
} }
rb_set_color(other, rb_color(parent)); rb_set_color(other, rb_color(parent));
rb_set_black(parent); rb_set_black(parent);
if (other->rb_left) if (other->rb_left)
rb_set_black(other->rb_left); rb_set_black(other->rb_left);
__rb_rotate_right(parent, root); __rb_rotate_right(parent, root);
node = root->rb_node; node = root->rb_node;
break; break;
} }
} }
} }
if (node) if (node)
rb_set_black(node); rb_set_black(node);
} }
void rb_erase(struct rb_node *node, struct rb_root *root) void rb_erase(struct rb_node *node, struct rb_root *root)
{ {
struct rb_node *child, *parent; struct rb_node *child, *parent;
ULONG_PTR color; ULONG_PTR color;
if (!node->rb_left) if (!node->rb_left)
child = node->rb_right; child = node->rb_right;
else if (!node->rb_right) else if (!node->rb_right)
child = node->rb_left; child = node->rb_left;
else else
{ {
struct rb_node *old = node, *left; struct rb_node *old = node, *left;
node = node->rb_right; node = node->rb_right;
while ((left = node->rb_left) != NULL) while ((left = node->rb_left) != NULL)
node = left; node = left;
child = node->rb_right; child = node->rb_right;
parent = rb_parent(node); parent = rb_parent(node);
color = rb_color(node); color = rb_color(node);
if (child) if (child)
rb_set_parent(child, parent); rb_set_parent(child, parent);
if (parent == old) { if (parent == old) {
parent->rb_right = child; parent->rb_right = child;
parent = node; parent = node;
} else } else
parent->rb_left = child; parent->rb_left = child;
node->rb_parent_color = old->rb_parent_color; node->rb_parent_color = old->rb_parent_color;
node->rb_right = old->rb_right; node->rb_right = old->rb_right;
node->rb_left = old->rb_left; node->rb_left = old->rb_left;
if (rb_parent(old)) if (rb_parent(old))
{ {
if (rb_parent(old)->rb_left == old) if (rb_parent(old)->rb_left == old)
rb_parent(old)->rb_left = node; rb_parent(old)->rb_left = node;
else else
rb_parent(old)->rb_right = node; rb_parent(old)->rb_right = node;
} else } else
root->rb_node = node; root->rb_node = node;
rb_set_parent(old->rb_left, node); rb_set_parent(old->rb_left, node);
if (old->rb_right) if (old->rb_right)
rb_set_parent(old->rb_right, node); rb_set_parent(old->rb_right, node);
goto color; goto color;
} }
parent = rb_parent(node); parent = rb_parent(node);
color = rb_color(node); color = rb_color(node);
if (child) if (child)
rb_set_parent(child, parent); rb_set_parent(child, parent);
if (parent) if (parent)
{ {
if (parent->rb_left == node) if (parent->rb_left == node)
parent->rb_left = child; parent->rb_left = child;
else else
parent->rb_right = child; parent->rb_right = child;
} }
else else
root->rb_node = child; root->rb_node = child;
color: color:
if (color == RB_BLACK) if (color == RB_BLACK)
__rb_erase_color(child, parent, root); __rb_erase_color(child, parent, root);
} }
EXPORT_SYMBOL(rb_erase); EXPORT_SYMBOL(rb_erase);
/* /*
* This function returns the first node (in sort order) of the tree. * This function returns the first node (in sort order) of the tree.
*/ */
struct rb_node *rb_first(struct rb_root *root) struct rb_node *rb_first(struct rb_root *root)
{ {
struct rb_node *n; struct rb_node *n;
n = root->rb_node; n = root->rb_node;
if (!n) if (!n)
return NULL; return NULL;
while (n->rb_left) while (n->rb_left)
n = n->rb_left; n = n->rb_left;
return n; return n;
} }
EXPORT_SYMBOL(rb_first); EXPORT_SYMBOL(rb_first);
struct rb_node *rb_last(struct rb_root *root) struct rb_node *rb_last(struct rb_root *root)
{ {
struct rb_node *n; struct rb_node *n;
n = root->rb_node; n = root->rb_node;
if (!n) if (!n)
return NULL; return NULL;
while (n->rb_right) while (n->rb_right)
n = n->rb_right; n = n->rb_right;
return n; return n;
} }
EXPORT_SYMBOL(rb_last); EXPORT_SYMBOL(rb_last);
struct rb_node *rb_next(struct rb_node *node) struct rb_node *rb_next(struct rb_node *node)
{ {
struct rb_node *parent; struct rb_node *parent;
/* If we have a right-hand child, go down and then left as far /* If we have a right-hand child, go down and then left as far
as we can. */ as we can. */
if (node->rb_right) { if (node->rb_right) {
node = node->rb_right; node = node->rb_right;
while (node->rb_left) while (node->rb_left)
node=node->rb_left; node=node->rb_left;
return node; return node;
} }
/* No right-hand children. Everything down and left is /* No right-hand children. Everything down and left is
smaller than us, so any 'next' node must be in the general smaller than us, so any 'next' node must be in the general
direction of our parent. Go up the tree; any time the direction of our parent. Go up the tree; any time the
ancestor is a right-hand child of its parent, keep going ancestor is a right-hand child of its parent, keep going
up. First time it's a left-hand child of its parent, said up. First time it's a left-hand child of its parent, said
parent is our 'next' node. */ parent is our 'next' node. */
while ((parent = rb_parent(node)) && node == parent->rb_right) while ((parent = rb_parent(node)) && node == parent->rb_right)
node = parent; node = parent;
return parent; return parent;
} }
EXPORT_SYMBOL(rb_next); EXPORT_SYMBOL(rb_next);
struct rb_node *rb_prev(struct rb_node *node) struct rb_node *rb_prev(struct rb_node *node)
{ {
struct rb_node *parent; struct rb_node *parent;
/* If we have a left-hand child, go down and then right as far /* If we have a left-hand child, go down and then right as far
as we can. */ as we can. */
if (node->rb_left) { if (node->rb_left) {
node = node->rb_left; node = node->rb_left;
while (node->rb_right) while (node->rb_right)
node=node->rb_right; node=node->rb_right;
return node; return node;
} }
/* No left-hand children. Go up till we find an ancestor which /* No left-hand children. Go up till we find an ancestor which
is a right-hand child of its parent */ is a right-hand child of its parent */
while ((parent = rb_parent(node)) && node == parent->rb_left) while ((parent = rb_parent(node)) && node == parent->rb_left)
node = parent; node = parent;
return parent; return parent;
} }
EXPORT_SYMBOL(rb_prev); EXPORT_SYMBOL(rb_prev);
void rb_replace_node(struct rb_node *victim, struct rb_node *new, void rb_replace_node(struct rb_node *victim, struct rb_node *new,
struct rb_root *root) struct rb_root *root)
{ {
struct rb_node *parent = rb_parent(victim); struct rb_node *parent = rb_parent(victim);
/* Set the surrounding nodes to point to the replacement */ /* Set the surrounding nodes to point to the replacement */
if (parent) { if (parent) {
if (victim == parent->rb_left) if (victim == parent->rb_left)
parent->rb_left = new; parent->rb_left = new;
else else
parent->rb_right = new; parent->rb_right = new;
} else { } else {
root->rb_node = new; root->rb_node = new;
} }
if (victim->rb_left) if (victim->rb_left)
rb_set_parent(victim->rb_left, new); rb_set_parent(victim->rb_left, new);
if (victim->rb_right) if (victim->rb_right)
rb_set_parent(victim->rb_right, new); rb_set_parent(victim->rb_right, new);
/* Copy the pointers/colour from the victim to the replacement */ /* Copy the pointers/colour from the victim to the replacement */
*new = *victim; *new = *victim;
} }
EXPORT_SYMBOL(rb_replace_node); EXPORT_SYMBOL(rb_replace_node);
void rb_insert(struct rb_root *root, struct rb_node *node, void rb_insert(struct rb_root *root, struct rb_node *node,
int (*cmp)(struct rb_node *, struct rb_node *)) int (*cmp)(struct rb_node *, struct rb_node *))
{ {
struct rb_node **new = &(root->rb_node), *parent = NULL; struct rb_node **new = &(root->rb_node), *parent = NULL;
/* Figure out where to put new node */ /* Figure out where to put new node */
while (*new) { while (*new) {
int result = cmp(node, *new); int result = cmp(node, *new);
parent = *new; parent = *new;
if (result < 0) if (result < 0)
new = &((*new)->rb_left); new = &((*new)->rb_left);
else if (result > 0) else if (result > 0)
new = &((*new)->rb_right); new = &((*new)->rb_right);
else else
return; return;
} }
/* Add new node and rebalance tree. */ /* Add new node and rebalance tree. */
rb_link_node(node, parent, new); rb_link_node(node, parent, new);
rb_insert_color(node, root); rb_insert_color(node, root);
} }
EXPORT_SYMBOL(rb_insert); EXPORT_SYMBOL(rb_insert);

File diff suppressed because it is too large Load Diff

View File

@@ -1,118 +1,118 @@
/* /*
* COPYRIGHT: See COPYRIGHT.TXT * COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: shutdown.c * FILE: shutdown.c
* PROGRAMMER: Matt Wu <mattwu@163.com> * PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com * HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "ext2fs.h" #include "ext2fs.h"
/* GLOBALS ***************************************************************/ /* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global; extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/ /* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2ShutDown) #pragma alloc_text(PAGE, Ext2ShutDown)
#endif #endif
NTSTATUS NTSTATUS
Ext2ShutDown (IN PEXT2_IRP_CONTEXT IrpContext) Ext2ShutDown (IN PEXT2_IRP_CONTEXT IrpContext)
{ {
NTSTATUS Status; NTSTATUS Status;
PIRP Irp; PIRP Irp;
PEXT2_VCB Vcb; PEXT2_VCB Vcb;
PLIST_ENTRY ListEntry; PLIST_ENTRY ListEntry;
BOOLEAN GlobalResourceAcquired = FALSE; BOOLEAN GlobalResourceAcquired = FALSE;
__try { __try {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
ASSERT(IrpContext); ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
Irp = IrpContext->Irp; Irp = IrpContext->Irp;
if (!ExAcquireResourceExclusiveLite( if (!ExAcquireResourceExclusiveLite(
&Ext2Global->Resource, &Ext2Global->Resource,
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
Status = STATUS_PENDING; Status = STATUS_PENDING;
__leave; __leave;
} }
GlobalResourceAcquired = TRUE; GlobalResourceAcquired = TRUE;
for (ListEntry = Ext2Global->VcbList.Flink; for (ListEntry = Ext2Global->VcbList.Flink;
ListEntry != &(Ext2Global->VcbList); ListEntry != &(Ext2Global->VcbList);
ListEntry = ListEntry->Flink ) { ListEntry = ListEntry->Flink ) {
Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next); Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next);
if (ExAcquireResourceExclusiveLite( if (ExAcquireResourceExclusiveLite(
&Vcb->MainResource, &Vcb->MainResource,
TRUE )) { TRUE )) {
if (IsMounted(Vcb)) { if (IsMounted(Vcb)) {
/* update mount count */ /* update mount count */
Vcb->SuperBlock->s_mnt_count++; Vcb->SuperBlock->s_mnt_count++;
if (Vcb->SuperBlock->s_mnt_count > if (Vcb->SuperBlock->s_mnt_count >
Vcb->SuperBlock->s_max_mnt_count ) { Vcb->SuperBlock->s_max_mnt_count ) {
Vcb->SuperBlock->s_mnt_count = Vcb->SuperBlock->s_mnt_count =
Vcb->SuperBlock->s_max_mnt_count; Vcb->SuperBlock->s_max_mnt_count;
} }
Ext2SaveSuper(IrpContext, Vcb); Ext2SaveSuper(IrpContext, Vcb);
/* flush dirty cache for all files */ /* flush dirty cache for all files */
Status = Ext2FlushFiles(IrpContext, Vcb, TRUE); Status = Ext2FlushFiles(IrpContext, Vcb, TRUE);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
DbgBreak(); DbgBreak();
} }
/* flush volume stream's cache to disk */ /* flush volume stream's cache to disk */
Status = Ext2FlushVolume(IrpContext, Vcb, TRUE); Status = Ext2FlushVolume(IrpContext, Vcb, TRUE);
if (!NT_SUCCESS(Status) && Status != STATUS_MEDIA_WRITE_PROTECTED) { if (!NT_SUCCESS(Status) && Status != STATUS_MEDIA_WRITE_PROTECTED) {
DbgBreak(); DbgBreak();
} }
/* send shutdown request to underlying disk */ /* send shutdown request to underlying disk */
Ext2DiskShutDown(Vcb); Ext2DiskShutDown(Vcb);
} }
ExReleaseResourceLite(&Vcb->MainResource); ExReleaseResourceLite(&Vcb->MainResource);
} }
} }
/* /*
IoUnregisterFileSystem(Ext2Global->DiskdevObject); IoUnregisterFileSystem(Ext2Global->DiskdevObject);
IoUnregisterFileSystem(Ext2Global->CdromdevObject); IoUnregisterFileSystem(Ext2Global->CdromdevObject);
*/ */
} __finally { } __finally {
if (GlobalResourceAcquired) { if (GlobalResourceAcquired) {
ExReleaseResourceLite(&Ext2Global->Resource); ExReleaseResourceLite(&Ext2Global->Resource);
} }
if (!IrpContext->ExceptionInProgress) { if (!IrpContext->ExceptionInProgress) {
if (Status == STATUS_PENDING) { if (Status == STATUS_PENDING) {
Ext2QueueRequest(IrpContext); Ext2QueueRequest(IrpContext);
} else { } else {
Ext2CompleteIrpContext(IrpContext, Status); Ext2CompleteIrpContext(IrpContext, Status);
} }
} }
} }
return Status; return Status;
} }

View File

@@ -1,409 +1,409 @@
/* /*
* COPYRIGHT: See COPYRIGHT.TXT * COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP * PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: volinfo.c * FILE: volinfo.c
* PROGRAMMER: Matt Wu <mattwu@163.com> * PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com * HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY: * UPDATE HISTORY:
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include "ext2fs.h" #include "ext2fs.h"
/* GLOBALS ***************************************************************/ /* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global; extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/ /* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2QueryVolumeInformation) #pragma alloc_text(PAGE, Ext2QueryVolumeInformation)
#pragma alloc_text(PAGE, Ext2SetVolumeInformation) #pragma alloc_text(PAGE, Ext2SetVolumeInformation)
#endif #endif
NTSTATUS NTSTATUS
Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext) Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
{ {
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
PEXT2_VCB Vcb = NULL; PEXT2_VCB Vcb = NULL;
PIRP Irp = NULL; PIRP Irp = NULL;
PIO_STACK_LOCATION IoStackLocation = NULL; PIO_STACK_LOCATION IoStackLocation = NULL;
PVOID Buffer; PVOID Buffer;
ULONG Length; ULONG Length;
NTSTATUS Status = STATUS_UNSUCCESSFUL; NTSTATUS Status = STATUS_UNSUCCESSFUL;
FS_INFORMATION_CLASS FsInformationClass; FS_INFORMATION_CLASS FsInformationClass;
BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN VcbResourceAcquired = FALSE;
__try { __try {
ASSERT(IrpContext != NULL); ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject; DeviceObject = IrpContext->DeviceObject;
// //
// This request is not allowed on the main device object // This request is not allowed on the main device object
// //
if (IsExt2FsDevice(DeviceObject)) { if (IsExt2FsDevice(DeviceObject)) {
Status = STATUS_INVALID_DEVICE_REQUEST; Status = STATUS_INVALID_DEVICE_REQUEST;
__leave; __leave;
} }
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL); ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) && ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB))); (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
if (!IsMounted(Vcb)) { if (!IsMounted(Vcb)) {
Status = STATUS_VOLUME_DISMOUNTED; Status = STATUS_VOLUME_DISMOUNTED;
__leave; __leave;
} }
if (!ExAcquireResourceSharedLite( if (!ExAcquireResourceSharedLite(
&Vcb->MainResource, &Vcb->MainResource,
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
)) { )) {
Status = STATUS_PENDING; Status = STATUS_PENDING;
__leave; __leave;
} }
VcbResourceAcquired = TRUE; VcbResourceAcquired = TRUE;
Irp = IrpContext->Irp; Irp = IrpContext->Irp;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp); IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
FsInformationClass = FsInformationClass =
IoStackLocation->Parameters.QueryVolume.FsInformationClass; IoStackLocation->Parameters.QueryVolume.FsInformationClass;
Length = IoStackLocation->Parameters.QueryVolume.Length; Length = IoStackLocation->Parameters.QueryVolume.Length;
Buffer = Irp->AssociatedIrp.SystemBuffer; Buffer = Irp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(Buffer, Length); RtlZeroMemory(Buffer, Length);
switch (FsInformationClass) { switch (FsInformationClass) {
case FileFsVolumeInformation: case FileFsVolumeInformation:
{ {
PFILE_FS_VOLUME_INFORMATION FsVolInfo; PFILE_FS_VOLUME_INFORMATION FsVolInfo;
ULONG VolumeLabelLength; ULONG VolumeLabelLength;
ULONG RequiredLength; ULONG RequiredLength;
if (Length < sizeof(FILE_FS_VOLUME_INFORMATION)) { if (Length < sizeof(FILE_FS_VOLUME_INFORMATION)) {
Status = STATUS_BUFFER_OVERFLOW; Status = STATUS_BUFFER_OVERFLOW;
__leave; __leave;
} }
FsVolInfo = (PFILE_FS_VOLUME_INFORMATION) Buffer; FsVolInfo = (PFILE_FS_VOLUME_INFORMATION) Buffer;
FsVolInfo->VolumeCreationTime.QuadPart = 0; FsVolInfo->VolumeCreationTime.QuadPart = 0;
FsVolInfo->VolumeSerialNumber = Vcb->Vpb->SerialNumber; FsVolInfo->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
VolumeLabelLength = Vcb->Vpb->VolumeLabelLength; VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
FsVolInfo->VolumeLabelLength = VolumeLabelLength; FsVolInfo->VolumeLabelLength = VolumeLabelLength;
/* We don't support ObjectId */ /* We don't support ObjectId */
FsVolInfo->SupportsObjects = FALSE; FsVolInfo->SupportsObjects = FALSE;
RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION) RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION)
+ VolumeLabelLength - sizeof(WCHAR); + VolumeLabelLength - sizeof(WCHAR);
if (Length < RequiredLength) { if (Length < RequiredLength) {
Irp->IoStatus.Information = Irp->IoStatus.Information =
sizeof(FILE_FS_VOLUME_INFORMATION); sizeof(FILE_FS_VOLUME_INFORMATION);
Status = STATUS_BUFFER_OVERFLOW; Status = STATUS_BUFFER_OVERFLOW;
__leave; __leave;
} }
RtlCopyMemory(FsVolInfo->VolumeLabel, Vcb->Vpb->VolumeLabel, Vcb->Vpb->VolumeLabelLength); RtlCopyMemory(FsVolInfo->VolumeLabel, Vcb->Vpb->VolumeLabel, Vcb->Vpb->VolumeLabelLength);
Irp->IoStatus.Information = RequiredLength; Irp->IoStatus.Information = RequiredLength;
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
} }
break; break;
case FileFsSizeInformation: case FileFsSizeInformation:
{ {
PFILE_FS_SIZE_INFORMATION FsSizeInfo; PFILE_FS_SIZE_INFORMATION FsSizeInfo;
if (Length < sizeof(FILE_FS_SIZE_INFORMATION)) { if (Length < sizeof(FILE_FS_SIZE_INFORMATION)) {
Status = STATUS_BUFFER_OVERFLOW; Status = STATUS_BUFFER_OVERFLOW;
__leave; __leave;
} }
FsSizeInfo = (PFILE_FS_SIZE_INFORMATION) Buffer; FsSizeInfo = (PFILE_FS_SIZE_INFORMATION) Buffer;
FsSizeInfo->TotalAllocationUnits.QuadPart = FsSizeInfo->TotalAllocationUnits.QuadPart =
ext3_blocks_count(SUPER_BLOCK); ext3_blocks_count(SUPER_BLOCK);
FsSizeInfo->AvailableAllocationUnits.QuadPart = FsSizeInfo->AvailableAllocationUnits.QuadPart =
ext3_free_blocks_count(SUPER_BLOCK); ext3_free_blocks_count(SUPER_BLOCK);
FsSizeInfo->SectorsPerAllocationUnit = FsSizeInfo->SectorsPerAllocationUnit =
Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector; Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
FsSizeInfo->BytesPerSector = FsSizeInfo->BytesPerSector =
Vcb->DiskGeometry.BytesPerSector; Vcb->DiskGeometry.BytesPerSector;
Irp->IoStatus.Information = sizeof(FILE_FS_SIZE_INFORMATION); Irp->IoStatus.Information = sizeof(FILE_FS_SIZE_INFORMATION);
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
} }
break; break;
case FileFsDeviceInformation: case FileFsDeviceInformation:
{ {
PFILE_FS_DEVICE_INFORMATION FsDevInfo; PFILE_FS_DEVICE_INFORMATION FsDevInfo;
if (Length < sizeof(FILE_FS_DEVICE_INFORMATION)) { if (Length < sizeof(FILE_FS_DEVICE_INFORMATION)) {
Status = STATUS_BUFFER_OVERFLOW; Status = STATUS_BUFFER_OVERFLOW;
__leave; __leave;
} }
FsDevInfo = (PFILE_FS_DEVICE_INFORMATION) Buffer; FsDevInfo = (PFILE_FS_DEVICE_INFORMATION) Buffer;
FsDevInfo->DeviceType = FsDevInfo->DeviceType =
Vcb->TargetDeviceObject->DeviceType; Vcb->TargetDeviceObject->DeviceType;
if (FsDevInfo->DeviceType != FILE_DEVICE_DISK) { if (FsDevInfo->DeviceType != FILE_DEVICE_DISK) {
DbgBreak(); DbgBreak();
} }
FsDevInfo->Characteristics = FsDevInfo->Characteristics =
Vcb->TargetDeviceObject->Characteristics; Vcb->TargetDeviceObject->Characteristics;
if (IsVcbReadOnly(Vcb)) { if (IsVcbReadOnly(Vcb)) {
SetFlag( FsDevInfo->Characteristics, SetFlag( FsDevInfo->Characteristics,
FILE_READ_ONLY_DEVICE ); FILE_READ_ONLY_DEVICE );
} }
Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION); Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION);
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
} }
break; break;
case FileFsAttributeInformation: case FileFsAttributeInformation:
{ {
PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo; PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo;
ULONG RequiredLength; ULONG RequiredLength;
if (Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) { if (Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) {
Status = STATUS_BUFFER_OVERFLOW; Status = STATUS_BUFFER_OVERFLOW;
__leave; __leave;
} }
FsAttrInfo = FsAttrInfo =
(PFILE_FS_ATTRIBUTE_INFORMATION) Buffer; (PFILE_FS_ATTRIBUTE_INFORMATION) Buffer;
FsAttrInfo->FileSystemAttributes = FILE_SUPPORTS_HARD_LINKS | FsAttrInfo->FileSystemAttributes = FILE_SUPPORTS_HARD_LINKS |
FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
FILE_SUPPORTS_REPARSE_POINTS | FILE_SUPPORTS_EXTENDED_ATTRIBUTES; FILE_SUPPORTS_REPARSE_POINTS | FILE_SUPPORTS_EXTENDED_ATTRIBUTES;
if (IsVcbReadOnly(Vcb)) { if (IsVcbReadOnly(Vcb)) {
FsAttrInfo->FileSystemAttributes |= FILE_READ_ONLY_VOLUME; FsAttrInfo->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
} }
FsAttrInfo->MaximumComponentNameLength = EXT2_NAME_LEN; FsAttrInfo->MaximumComponentNameLength = EXT2_NAME_LEN;
FsAttrInfo->FileSystemNameLength = 8; FsAttrInfo->FileSystemNameLength = 8;
RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) +
8 - sizeof(WCHAR); 8 - sizeof(WCHAR);
if (Length < RequiredLength) { if (Length < RequiredLength) {
Irp->IoStatus.Information = Irp->IoStatus.Information =
sizeof(FILE_FS_ATTRIBUTE_INFORMATION); sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
Status = STATUS_BUFFER_OVERFLOW; Status = STATUS_BUFFER_OVERFLOW;
__leave; __leave;
} }
if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) { if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT4\0", 10); RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT4\0", 10);
} else if (Vcb->IsExt3fs) { } else if (Vcb->IsExt3fs) {
RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT3\0", 10); RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT3\0", 10);
} else { } else {
RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT2\0", 10); RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT2\0", 10);
} }
Irp->IoStatus.Information = RequiredLength; Irp->IoStatus.Information = RequiredLength;
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
} }
break; break;
#if (_WIN32_WINNT >= 0x0500) #if (_WIN32_WINNT >= 0x0500)
case FileFsFullSizeInformation: case FileFsFullSizeInformation:
{ {
PFILE_FS_FULL_SIZE_INFORMATION PFFFSI; PFILE_FS_FULL_SIZE_INFORMATION PFFFSI;
if (Length < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) { if (Length < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) {
Status = STATUS_BUFFER_OVERFLOW; Status = STATUS_BUFFER_OVERFLOW;
__leave; __leave;
} }
PFFFSI = (PFILE_FS_FULL_SIZE_INFORMATION) Buffer; PFFFSI = (PFILE_FS_FULL_SIZE_INFORMATION) Buffer;
/* /*
typedef struct _FILE_FS_FULL_SIZE_INFORMATION { typedef struct _FILE_FS_FULL_SIZE_INFORMATION {
LARGE_INTEGER TotalAllocationUnits; LARGE_INTEGER TotalAllocationUnits;
LARGE_INTEGER CallerAvailableAllocationUnits; LARGE_INTEGER CallerAvailableAllocationUnits;
LARGE_INTEGER ActualAvailableAllocationUnits; LARGE_INTEGER ActualAvailableAllocationUnits;
ULONG SectorsPerAllocationUnit; ULONG SectorsPerAllocationUnit;
ULONG BytesPerSector; ULONG BytesPerSector;
} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION; } FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
*/ */
{ {
PFFFSI->TotalAllocationUnits.QuadPart = PFFFSI->TotalAllocationUnits.QuadPart =
ext3_blocks_count(SUPER_BLOCK); ext3_blocks_count(SUPER_BLOCK);
PFFFSI->CallerAvailableAllocationUnits.QuadPart = PFFFSI->CallerAvailableAllocationUnits.QuadPart =
ext3_free_blocks_count(SUPER_BLOCK); ext3_free_blocks_count(SUPER_BLOCK);
/* - Vcb->SuperBlock->s_r_blocks_count; */ /* - Vcb->SuperBlock->s_r_blocks_count; */
PFFFSI->ActualAvailableAllocationUnits.QuadPart = PFFFSI->ActualAvailableAllocationUnits.QuadPart =
ext3_free_blocks_count(SUPER_BLOCK); ext3_free_blocks_count(SUPER_BLOCK);
} }
PFFFSI->SectorsPerAllocationUnit = PFFFSI->SectorsPerAllocationUnit =
Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector; Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
PFFFSI->BytesPerSector = Vcb->DiskGeometry.BytesPerSector; PFFFSI->BytesPerSector = Vcb->DiskGeometry.BytesPerSector;
Irp->IoStatus.Information = sizeof(FILE_FS_FULL_SIZE_INFORMATION); Irp->IoStatus.Information = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
} }
break; break;
#endif // (_WIN32_WINNT >= 0x0500) #endif // (_WIN32_WINNT >= 0x0500)
default: default:
Status = STATUS_INVALID_INFO_CLASS; Status = STATUS_INVALID_INFO_CLASS;
break; break;
} }
} __finally { } __finally {
if (VcbResourceAcquired) { if (VcbResourceAcquired) {
ExReleaseResourceLite(&Vcb->MainResource); ExReleaseResourceLite(&Vcb->MainResource);
} }
if (!IrpContext->ExceptionInProgress) { if (!IrpContext->ExceptionInProgress) {
if (Status == STATUS_PENDING) { if (Status == STATUS_PENDING) {
Ext2QueueRequest(IrpContext); Ext2QueueRequest(IrpContext);
} else { } else {
Ext2CompleteIrpContext(IrpContext, Status); Ext2CompleteIrpContext(IrpContext, Status);
} }
} }
} }
return Status; return Status;
} }
NTSTATUS NTSTATUS
Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext) Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
{ {
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_UNSUCCESSFUL; NTSTATUS Status = STATUS_UNSUCCESSFUL;
PEXT2_VCB Vcb = NULL; PEXT2_VCB Vcb = NULL;
PIRP Irp; PIRP Irp;
PIO_STACK_LOCATION IoStackLocation; PIO_STACK_LOCATION IoStackLocation;
FS_INFORMATION_CLASS FsInformationClass; FS_INFORMATION_CLASS FsInformationClass;
BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN VcbResourceAcquired = FALSE;
__try { __try {
ASSERT(IrpContext != NULL); ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject; DeviceObject = IrpContext->DeviceObject;
// //
// This request is not allowed on the main device object // This request is not allowed on the main device object
// //
if (IsExt2FsDevice(DeviceObject)) { if (IsExt2FsDevice(DeviceObject)) {
Status = STATUS_INVALID_DEVICE_REQUEST; Status = STATUS_INVALID_DEVICE_REQUEST;
__leave; __leave;
} }
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL); ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) && ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB))); (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
ASSERT(IsMounted(Vcb)); ASSERT(IsMounted(Vcb));
if (IsVcbReadOnly(Vcb)) { if (IsVcbReadOnly(Vcb)) {
Status = STATUS_MEDIA_WRITE_PROTECTED; Status = STATUS_MEDIA_WRITE_PROTECTED;
__leave; __leave;
} }
if (!ExAcquireResourceExclusiveLite( if (!ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE)) { &Vcb->MainResource, TRUE)) {
Status = STATUS_PENDING; Status = STATUS_PENDING;
__leave; __leave;
} }
VcbResourceAcquired = TRUE; VcbResourceAcquired = TRUE;
Ext2VerifyVcb(IrpContext, Vcb); Ext2VerifyVcb(IrpContext, Vcb);
Irp = IrpContext->Irp; Irp = IrpContext->Irp;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp); IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
//Notes: SetVolume is not defined in ntddk.h of win2k ddk, //Notes: SetVolume is not defined in ntddk.h of win2k ddk,
// But it's same to QueryVolume .... // But it's same to QueryVolume ....
FsInformationClass = FsInformationClass =
IoStackLocation->Parameters./*SetVolume*/QueryVolume.FsInformationClass; IoStackLocation->Parameters./*SetVolume*/QueryVolume.FsInformationClass;
switch (FsInformationClass) { switch (FsInformationClass) {
case FileFsLabelInformation: case FileFsLabelInformation:
{ {
PFILE_FS_LABEL_INFORMATION VolLabelInfo = NULL; PFILE_FS_LABEL_INFORMATION VolLabelInfo = NULL;
ULONG VolLabelLen; ULONG VolLabelLen;
UNICODE_STRING LabelName ; UNICODE_STRING LabelName ;
OEM_STRING OemName; OEM_STRING OemName;
VolLabelInfo = (PFILE_FS_LABEL_INFORMATION) Irp->AssociatedIrp.SystemBuffer; VolLabelInfo = (PFILE_FS_LABEL_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
VolLabelLen = VolLabelInfo->VolumeLabelLength; VolLabelLen = VolLabelInfo->VolumeLabelLength;
if (VolLabelLen > (16 * sizeof(WCHAR))) { if (VolLabelLen > (16 * sizeof(WCHAR))) {
Status = STATUS_INVALID_VOLUME_LABEL; Status = STATUS_INVALID_VOLUME_LABEL;
__leave; __leave;
} }
RtlCopyMemory( Vcb->Vpb->VolumeLabel, RtlCopyMemory( Vcb->Vpb->VolumeLabel,
VolLabelInfo->VolumeLabel, VolLabelInfo->VolumeLabel,
VolLabelLen ); VolLabelLen );
RtlZeroMemory(Vcb->SuperBlock->s_volume_name, 16); RtlZeroMemory(Vcb->SuperBlock->s_volume_name, 16);
LabelName.Buffer = VolLabelInfo->VolumeLabel; LabelName.Buffer = VolLabelInfo->VolumeLabel;
LabelName.MaximumLength = (USHORT)16 * sizeof(WCHAR); LabelName.MaximumLength = (USHORT)16 * sizeof(WCHAR);
LabelName.Length = (USHORT)VolLabelLen; LabelName.Length = (USHORT)VolLabelLen;
OemName.Buffer = SUPER_BLOCK->s_volume_name; OemName.Buffer = SUPER_BLOCK->s_volume_name;
OemName.Length = 0; OemName.Length = 0;
OemName.MaximumLength = 16; OemName.MaximumLength = 16;
Ext2UnicodeToOEM(Vcb, &OemName, &LabelName); Ext2UnicodeToOEM(Vcb, &OemName, &LabelName);
Vcb->Vpb->VolumeLabelLength = (USHORT) VolLabelLen; Vcb->Vpb->VolumeLabelLength = (USHORT) VolLabelLen;
if (Ext2SaveSuper(IrpContext, Vcb)) { if (Ext2SaveSuper(IrpContext, Vcb)) {
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
} }
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
} }
break; break;
default: default:
Status = STATUS_INVALID_INFO_CLASS; Status = STATUS_INVALID_INFO_CLASS;
} }
} __finally { } __finally {
if (VcbResourceAcquired) { if (VcbResourceAcquired) {
ExReleaseResourceLite(&Vcb->MainResource); ExReleaseResourceLite(&Vcb->MainResource);
} }
if (!IrpContext->ExceptionInProgress) { if (!IrpContext->ExceptionInProgress) {
if (Status == STATUS_PENDING) { if (Status == STATUS_PENDING) {
Ext2QueueRequest(IrpContext); Ext2QueueRequest(IrpContext);
} else { } else {
Ext2CompleteIrpContext(IrpContext, Status); Ext2CompleteIrpContext(IrpContext, Status);
} }
} }
} }
return Status; return Status;
} }

File diff suppressed because it is too large Load Diff