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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,244 +1,244 @@
/*
* COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: extents.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "ext2fs.h"
/* GLOBALS *****************************************************************/
extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA
#endif
NTSTATUS
Ext2MapExtent(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_MCB Mcb,
IN ULONG Index,
IN BOOLEAN Alloc,
OUT PULONG Block,
OUT PULONG Number
)
{
EXT4_EXTENT_HEADER *eh;
struct buffer_head bh_got = {0};
int flags, rc;
ULONG max_blocks = 0;
memset(&bh_got, 0, sizeof(struct buffer_head));
eh = get_ext4_header(&Mcb->Inode);
if (eh->eh_magic != EXT4_EXT_MAGIC) {
if (Alloc) {
/* now initialize inode extent root node */
ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode);
} else {
/* return empty-mapping when inode extent isn't initialized */
if (Block)
*Block = 0;
if (Number) {
LONGLONG _len = _len = Mcb->Inode.i_size;
if (Mcb->Fcb)
_len = Mcb->Fcb->Header.AllocationSize.QuadPart;
*Number = (ULONG)((_len + BLOCK_SIZE - 1) >> BLOCK_BITS);
}
return STATUS_SUCCESS;
}
}
/* IrpContext is NULL when called during journal initialization */
if (IsMcbDirectory(Mcb) || IrpContext == NULL ||
IrpContext->MajorFunction == IRP_MJ_WRITE || !Alloc){
flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT;
max_blocks = EXT_INIT_MAX_LEN;
} else {
flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
max_blocks = EXT_UNWRITTEN_MAX_LEN;
}
if (Alloc) {
if (Number && !*Number) {
if (max_blocks > *Number) {
max_blocks = *Number;
}
} else {
max_blocks = 1;
}
}
if ((rc = ext4_ext_get_blocks(
IrpContext,
NULL,
&Mcb->Inode,
Index,
max_blocks,
&bh_got,
Alloc,
flags)) < 0) {
DEBUG(DL_ERR, ("Block insufficient resources, err: %d\n", rc));
return Ext2WinntError(rc);
}
if (Alloc)
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
if (Number)
*Number = rc ? rc : 1;
if (Block)
*Block = (ULONG)bh_got.b_blocknr;
return STATUS_SUCCESS;
}
NTSTATUS
Ext2DoExtentExpand(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_MCB Mcb,
IN ULONG Index,
IN OUT PULONG Block,
IN OUT PULONG Number
)
{
EXT4_EXTENT_HEADER *eh;
struct buffer_head bh_got;
int rc, flags;
if (IsMcbDirectory(Mcb) || IrpContext->MajorFunction == IRP_MJ_WRITE) {
flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT;
} else {
flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
}
memset(&bh_got, 0, sizeof(struct buffer_head));
eh = get_ext4_header(&Mcb->Inode);
if (eh->eh_magic != EXT4_EXT_MAGIC) {
ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode);
}
if ((rc = ext4_ext_get_blocks( IrpContext, NULL, &Mcb->Inode, Index,
*Number, &bh_got, 1, flags)) < 0) {
DEBUG(DL_ERR, ("Expand Block insufficient resources, Number: %u,"
" err: %d\n", *Number, rc));
DbgBreak();
return Ext2WinntError(rc);
}
if (Number)
*Number = rc ? rc : 1;
if (Block)
*Block = (ULONG)bh_got.b_blocknr;
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
return STATUS_SUCCESS;
}
NTSTATUS
Ext2ExpandExtent(
PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb,
PEXT2_MCB Mcb,
ULONG Start,
ULONG End,
PLARGE_INTEGER Size
)
{
ULONG Count = 0, Number = 0, Block = 0;
NTSTATUS Status = STATUS_SUCCESS;
if (End <= Start)
return Status;
while (End > Start + Count) {
Number = End - Start - Count;
Status = Ext2DoExtentExpand(IrpContext, Vcb, Mcb, Start + Count,
&Block, &Number);
if (!NT_SUCCESS(Status)) {
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
if (Number == 0) {
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
if (Block && IsZoneInited(Mcb)) {
if (!Ext2AddBlockExtent(Vcb, Mcb, Start + Count, Block, Number)) {
DbgBreak();
ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
Ext2ClearAllExtents(&Mcb->Extents);
}
}
Count += Number;
}
Size->QuadPart = ((LONGLONG)(Start + Count)) << BLOCK_BITS;
/* save inode whatever it succeeds to expand or not */
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
return Status;
}
NTSTATUS
Ext2TruncateExtent(
PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb,
PEXT2_MCB Mcb,
PLARGE_INTEGER Size
)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG Extra = 0;
ULONG Wanted = 0;
ULONG End;
ULONG Removed;
int err;
/* translate file size to block */
End = Vcb->max_data_blocks;
Wanted = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
/* calculate blocks to be freed */
Extra = End - Wanted;
err = ext4_ext_truncate(IrpContext, &Mcb->Inode, Wanted);
if (err == 0) {
if (!Ext2RemoveBlockExtent(Vcb, Mcb, Wanted, Extra)) {
ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
Ext2ClearAllExtents(&Mcb->Extents);
}
Extra = 0;
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
if (!NT_SUCCESS(Status)) {
Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS);
}
if (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. */
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
return Status;
}
/*
* COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: extents.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "ext2fs.h"
/* GLOBALS *****************************************************************/
extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA
#endif
NTSTATUS
Ext2MapExtent(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_MCB Mcb,
IN ULONG Index,
IN BOOLEAN Alloc,
OUT PULONG Block,
OUT PULONG Number
)
{
EXT4_EXTENT_HEADER *eh;
struct buffer_head bh_got = {0};
int flags, rc;
ULONG max_blocks = 0;
memset(&bh_got, 0, sizeof(struct buffer_head));
eh = get_ext4_header(&Mcb->Inode);
if (eh->eh_magic != EXT4_EXT_MAGIC) {
if (Alloc) {
/* now initialize inode extent root node */
ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode);
} else {
/* return empty-mapping when inode extent isn't initialized */
if (Block)
*Block = 0;
if (Number) {
LONGLONG _len = _len = Mcb->Inode.i_size;
if (Mcb->Fcb)
_len = Mcb->Fcb->Header.AllocationSize.QuadPart;
*Number = (ULONG)((_len + BLOCK_SIZE - 1) >> BLOCK_BITS);
}
return STATUS_SUCCESS;
}
}
/* IrpContext is NULL when called during journal initialization */
if (IsMcbDirectory(Mcb) || IrpContext == NULL ||
IrpContext->MajorFunction == IRP_MJ_WRITE || !Alloc){
flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT;
max_blocks = EXT_INIT_MAX_LEN;
} else {
flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
max_blocks = EXT_UNWRITTEN_MAX_LEN;
}
if (Alloc) {
if (Number && !*Number) {
if (max_blocks > *Number) {
max_blocks = *Number;
}
} else {
max_blocks = 1;
}
}
if ((rc = ext4_ext_get_blocks(
IrpContext,
NULL,
&Mcb->Inode,
Index,
max_blocks,
&bh_got,
Alloc,
flags)) < 0) {
DEBUG(DL_ERR, ("Block insufficient resources, err: %d\n", rc));
return Ext2WinntError(rc);
}
if (Alloc)
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
if (Number)
*Number = rc ? rc : 1;
if (Block)
*Block = (ULONG)bh_got.b_blocknr;
return STATUS_SUCCESS;
}
NTSTATUS
Ext2DoExtentExpand(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_MCB Mcb,
IN ULONG Index,
IN OUT PULONG Block,
IN OUT PULONG Number
)
{
EXT4_EXTENT_HEADER *eh;
struct buffer_head bh_got;
int rc, flags;
if (IsMcbDirectory(Mcb) || IrpContext->MajorFunction == IRP_MJ_WRITE) {
flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT;
} else {
flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
}
memset(&bh_got, 0, sizeof(struct buffer_head));
eh = get_ext4_header(&Mcb->Inode);
if (eh->eh_magic != EXT4_EXT_MAGIC) {
ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode);
}
if ((rc = ext4_ext_get_blocks( IrpContext, NULL, &Mcb->Inode, Index,
*Number, &bh_got, 1, flags)) < 0) {
DEBUG(DL_ERR, ("Expand Block insufficient resources, Number: %u,"
" err: %d\n", *Number, rc));
DbgBreak();
return Ext2WinntError(rc);
}
if (Number)
*Number = rc ? rc : 1;
if (Block)
*Block = (ULONG)bh_got.b_blocknr;
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
return STATUS_SUCCESS;
}
NTSTATUS
Ext2ExpandExtent(
PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb,
PEXT2_MCB Mcb,
ULONG Start,
ULONG End,
PLARGE_INTEGER Size
)
{
ULONG Count = 0, Number = 0, Block = 0;
NTSTATUS Status = STATUS_SUCCESS;
if (End <= Start)
return Status;
while (End > Start + Count) {
Number = End - Start - Count;
Status = Ext2DoExtentExpand(IrpContext, Vcb, Mcb, Start + Count,
&Block, &Number);
if (!NT_SUCCESS(Status)) {
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
if (Number == 0) {
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
if (Block && IsZoneInited(Mcb)) {
if (!Ext2AddBlockExtent(Vcb, Mcb, Start + Count, Block, Number)) {
DbgBreak();
ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
Ext2ClearAllExtents(&Mcb->Extents);
}
}
Count += Number;
}
Size->QuadPart = ((LONGLONG)(Start + Count)) << BLOCK_BITS;
/* save inode whatever it succeeds to expand or not */
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
return Status;
}
NTSTATUS
Ext2TruncateExtent(
PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb,
PEXT2_MCB Mcb,
PLARGE_INTEGER Size
)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG Extra = 0;
ULONG Wanted = 0;
ULONG End;
ULONG Removed;
int err;
/* translate file size to block */
End = Vcb->max_data_blocks;
Wanted = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
/* calculate blocks to be freed */
Extra = End - Wanted;
err = ext4_ext_truncate(IrpContext, &Mcb->Inode, Wanted);
if (err == 0) {
if (!Ext2RemoveBlockExtent(Vcb, Mcb, Wanted, Extra)) {
ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
Ext2ClearAllExtents(&Mcb->Extents);
}
Extra = 0;
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
if (!NT_SUCCESS(Status)) {
Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS);
}
if (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. */
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
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
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: flush.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "ext2fs.h"
/* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/
NTSTATUS
Ext2FlushCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context )
{
if (Irp->PendingReturned)
IoMarkIrpPending( Irp );
if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)
Irp->IoStatus.Status = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
NTSTATUS
Ext2FlushVolume (
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN BOOLEAN bShutDown
)
{
DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
ExReleaseResourceLite(&Vcb->PagingIoResource);
return Ext2FlushVcb(Vcb);
}
NTSTATUS
Ext2FlushFile (
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_FCB Fcb,
IN PEXT2_CCB Ccb
)
{
IO_STATUS_BLOCK IoStatus = {0};
ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
__try {
/* do nothing if target fie was deleted */
if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
IoStatus.Status = STATUS_FILE_DELETED;
__leave;
}
/* update timestamp and achieve attribute */
if (Ccb != NULL) {
if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
LARGE_INTEGER SysTime;
KeQuerySystemTime(&SysTime);
Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime);
Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode);
}
}
if (IsDirectory(Fcb)) {
IoStatus.Status = STATUS_SUCCESS;
__leave;
}
DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n",
Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer));
CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
} __finally {
/* do cleanup here */
}
return IoStatus.Status;
}
NTSTATUS
Ext2FlushFiles(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN BOOLEAN bShutDown
)
{
IO_STATUS_BLOCK IoStatus;
PEXT2_FCB Fcb;
PLIST_ENTRY ListEntry;
if (IsVcbReadOnly(Vcb)) {
return STATUS_SUCCESS;
}
IoStatus.Status = STATUS_SUCCESS;
DEBUG(DL_INF, ( "Flushing Files ...\n"));
// Flush all Fcbs in Vcb list queue.
for (ListEntry = Vcb->FcbList.Flink;
ListEntry != &Vcb->FcbList;
ListEntry = ListEntry->Flink ) {
Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next);
ExAcquireResourceExclusiveLite(
&Fcb->MainResource, TRUE);
Ext2FlushFile(IrpContext, Fcb, NULL);
ExReleaseResourceLite(&Fcb->MainResource);
}
return IoStatus.Status;
}
NTSTATUS
Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
{
NTSTATUS Status = STATUS_SUCCESS;
PIRP Irp = NULL;
PIO_STACK_LOCATION IrpSp = NULL;
PEXT2_VCB Vcb = NULL;
PEXT2_FCB Fcb = NULL;
PEXT2_FCBVCB FcbOrVcb = NULL;
PEXT2_CCB Ccb = NULL;
PFILE_OBJECT FileObject = NULL;
PDEVICE_OBJECT DeviceObject = NULL;
BOOLEAN MainResourceAcquired = FALSE;
__try {
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (IsExt2FsDevice(DeviceObject)) {
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
ASSERT(IsMounted(Vcb));
if (IsVcbReadOnly(Vcb)) {
Status = STATUS_SUCCESS;
__leave;
}
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
FileObject = IrpContext->FileObject;
FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
ASSERT(FcbOrVcb != NULL);
Ccb = (PEXT2_CCB) FileObject->FsContext2;
if (Ccb == NULL) {
Status = STATUS_SUCCESS;
__leave;
}
MainResourceAcquired =
ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, TRUE);
ASSERT(MainResourceAcquired);
DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n",
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
if (FcbOrVcb->Identifier.Type == EXT2VCB) {
Ext2VerifyVcb(IrpContext, Vcb);
Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
if (NT_SUCCESS(Status)) {
__leave;
}
Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) {
ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
}
} else if (FcbOrVcb->Identifier.Type == EXT2FCB) {
Fcb = (PEXT2_FCB)(FcbOrVcb);
Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
if (NT_SUCCESS(Status)) {
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
}
}
}
DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n",
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
} __finally {
if (MainResourceAcquired) {
ExReleaseResourceLite(&FcbOrVcb->MainResource);
}
if (!IrpContext->ExceptionInProgress) {
if (Vcb && Irp && IrpSp && !IsVcbReadOnly(Vcb)) {
// Call the disk driver to flush the physial media.
NTSTATUS DriverStatus;
PIO_STACK_LOCATION NextIrpSp;
NextIrpSp = IoGetNextIrpStackLocation(Irp);
*NextIrpSp = *IrpSp;
IoSetCompletionRoutine( Irp,
Ext2FlushCompletionRoutine,
NULL,
TRUE,
TRUE,
TRUE );
DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);
Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
Status : DriverStatus;
IrpContext->Irp = Irp = NULL;
}
Ext2CompleteIrpContext(IrpContext, Status);
}
}
return Status;
/*
* COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: flush.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://www.ext2fsd.com
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "ext2fs.h"
/* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/
NTSTATUS
Ext2FlushCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context )
{
if (Irp->PendingReturned)
IoMarkIrpPending( Irp );
if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)
Irp->IoStatus.Status = STATUS_SUCCESS;
return STATUS_SUCCESS;
}
NTSTATUS
Ext2FlushVolume (
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN BOOLEAN bShutDown
)
{
DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
ExReleaseResourceLite(&Vcb->PagingIoResource);
return Ext2FlushVcb(Vcb);
}
NTSTATUS
Ext2FlushFile (
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_FCB Fcb,
IN PEXT2_CCB Ccb
)
{
IO_STATUS_BLOCK IoStatus = {0};
ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
__try {
/* do nothing if target fie was deleted */
if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
IoStatus.Status = STATUS_FILE_DELETED;
__leave;
}
/* update timestamp and achieve attribute */
if (Ccb != NULL) {
if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
LARGE_INTEGER SysTime;
KeQuerySystemTime(&SysTime);
Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime);
Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode);
}
}
if (IsDirectory(Fcb)) {
IoStatus.Status = STATUS_SUCCESS;
__leave;
}
DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n",
Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer));
CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
} __finally {
/* do cleanup here */
}
return IoStatus.Status;
}
NTSTATUS
Ext2FlushFiles(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN BOOLEAN bShutDown
)
{
IO_STATUS_BLOCK IoStatus;
PEXT2_FCB Fcb;
PLIST_ENTRY ListEntry;
if (IsVcbReadOnly(Vcb)) {
return STATUS_SUCCESS;
}
IoStatus.Status = STATUS_SUCCESS;
DEBUG(DL_INF, ( "Flushing Files ...\n"));
// Flush all Fcbs in Vcb list queue.
for (ListEntry = Vcb->FcbList.Flink;
ListEntry != &Vcb->FcbList;
ListEntry = ListEntry->Flink ) {
Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next);
ExAcquireResourceExclusiveLite(
&Fcb->MainResource, TRUE);
Ext2FlushFile(IrpContext, Fcb, NULL);
ExReleaseResourceLite(&Fcb->MainResource);
}
return IoStatus.Status;
}
NTSTATUS
Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
{
NTSTATUS Status = STATUS_SUCCESS;
PIRP Irp = NULL;
PIO_STACK_LOCATION IrpSp = NULL;
PEXT2_VCB Vcb = NULL;
PEXT2_FCB Fcb = NULL;
PEXT2_FCBVCB FcbOrVcb = NULL;
PEXT2_CCB Ccb = NULL;
PFILE_OBJECT FileObject = NULL;
PDEVICE_OBJECT DeviceObject = NULL;
BOOLEAN MainResourceAcquired = FALSE;
__try {
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (IsExt2FsDevice(DeviceObject)) {
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
ASSERT(IsMounted(Vcb));
if (IsVcbReadOnly(Vcb)) {
Status = STATUS_SUCCESS;
__leave;
}
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
FileObject = IrpContext->FileObject;
FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
ASSERT(FcbOrVcb != NULL);
Ccb = (PEXT2_CCB) FileObject->FsContext2;
if (Ccb == NULL) {
Status = STATUS_SUCCESS;
__leave;
}
MainResourceAcquired =
ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, TRUE);
ASSERT(MainResourceAcquired);
DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n",
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
if (FcbOrVcb->Identifier.Type == EXT2VCB) {
Ext2VerifyVcb(IrpContext, Vcb);
Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
if (NT_SUCCESS(Status)) {
__leave;
}
Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) {
ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
}
} else if (FcbOrVcb->Identifier.Type == EXT2FCB) {
Fcb = (PEXT2_FCB)(FcbOrVcb);
Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
if (NT_SUCCESS(Status)) {
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
}
}
}
DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n",
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
} __finally {
if (MainResourceAcquired) {
ExReleaseResourceLite(&FcbOrVcb->MainResource);
}
if (!IrpContext->ExceptionInProgress) {
if (Vcb && Irp && IrpSp && !IsVcbReadOnly(Vcb)) {
// Call the disk driver to flush the physial media.
NTSTATUS DriverStatus;
PIO_STACK_LOCATION NextIrpSp;
NextIrpSp = IoGetNextIrpStackLocation(Irp);
*NextIrpSp = *IrpSp;
IoSetCompletionRoutine( Irp,
Ext2FlushCompletionRoutine,
NULL,
TRUE,
TRUE,
TRUE );
DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);
Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
Status : DriverStatus;
IrpContext->Irp = Irp = NULL;
}
Ext2CompleteIrpContext(IrpContext, Status);
}
}
return Status;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,161 +1,161 @@
/*
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
linux/include/linux/rbtree.h
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.
I know it's not the cleaner way, but in C (not in C++) to get
performances and genericity...
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
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
rb_insert_color() must be called. Such function will do the
not trivial work to rebalance the rbtree if necessary.
-----------------------------------------------------------------------
static inline struct page * rb_search_page_cache(struct inode * inode,
unsigned long offset)
{
struct rb_node * n = inode->i_rb_page_cache.rb_node;
struct page * page;
while (n)
{
page = rb_entry(n, struct page, rb_page_cache);
if (offset < page->offset)
n = n->rb_left;
else if (offset > page->offset)
n = n->rb_right;
else
return page;
}
return NULL;
}
static inline struct page * __rb_insert_page_cache(struct inode * inode,
unsigned long offset,
struct rb_node * node)
{
struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
struct rb_node * parent = NULL;
struct page * page;
while (*p)
{
parent = *p;
page = rb_entry(parent, struct page, rb_page_cache);
if (offset < page->offset)
p = &(*p)->rb_left;
else if (offset > page->offset)
p = &(*p)->rb_right;
else
return page;
}
rb_link_node(node, parent, p);
return NULL;
}
static inline struct page * rb_insert_page_cache(struct inode * inode,
unsigned long offset,
struct rb_node * node)
{
struct page * ret;
if ((ret = __rb_insert_page_cache(inode, offset, node)))
goto out;
rb_insert_color(node, &inode->i_rb_page_cache);
out:
return ret;
}
-----------------------------------------------------------------------
*/
#ifndef _LINUX_RBTREE_H
#define _LINUX_RBTREE_H
struct rb_node
{
ULONG_PTR rb_parent_color;
#define RB_RED 0
#define RB_BLACK 1
struct rb_node *rb_right;
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
/* The alignment might seem pointless, but allegedly CRIS needs it */
struct rb_root
{
struct rb_node *rb_node;
};
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r) ((r)->rb_parent_color & 1)
#define rb_is_red(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_black(r) do { (r)->rb_parent_color |= 1; } while (0)
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;
}
static inline void rb_set_color(struct rb_node *rb, ULONG_PTR color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
#define RB_ROOT (struct rb_root) { NULL, }
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
#define RB_EMPTY_NODE(node) (rb_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_erase(struct rb_node *, struct rb_root *);
/* Find logical next and previous nodes in a tree */
extern struct rb_node *rb_next(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_last(struct rb_root *);
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
struct rb_root *root);
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
{
node->rb_parent_color = (ULONG_PTR )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
extern void rb_insert(struct rb_root *root, struct rb_node *node,
int (*cmp)(struct rb_node *, struct rb_node *));
#endif /* _LINUX_RBTREE_H */
/*
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
linux/include/linux/rbtree.h
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.
I know it's not the cleaner way, but in C (not in C++) to get
performances and genericity...
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
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
rb_insert_color() must be called. Such function will do the
not trivial work to rebalance the rbtree if necessary.
-----------------------------------------------------------------------
static inline struct page * rb_search_page_cache(struct inode * inode,
unsigned long offset)
{
struct rb_node * n = inode->i_rb_page_cache.rb_node;
struct page * page;
while (n)
{
page = rb_entry(n, struct page, rb_page_cache);
if (offset < page->offset)
n = n->rb_left;
else if (offset > page->offset)
n = n->rb_right;
else
return page;
}
return NULL;
}
static inline struct page * __rb_insert_page_cache(struct inode * inode,
unsigned long offset,
struct rb_node * node)
{
struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
struct rb_node * parent = NULL;
struct page * page;
while (*p)
{
parent = *p;
page = rb_entry(parent, struct page, rb_page_cache);
if (offset < page->offset)
p = &(*p)->rb_left;
else if (offset > page->offset)
p = &(*p)->rb_right;
else
return page;
}
rb_link_node(node, parent, p);
return NULL;
}
static inline struct page * rb_insert_page_cache(struct inode * inode,
unsigned long offset,
struct rb_node * node)
{
struct page * ret;
if ((ret = __rb_insert_page_cache(inode, offset, node)))
goto out;
rb_insert_color(node, &inode->i_rb_page_cache);
out:
return ret;
}
-----------------------------------------------------------------------
*/
#ifndef _LINUX_RBTREE_H
#define _LINUX_RBTREE_H
struct rb_node
{
ULONG_PTR rb_parent_color;
#define RB_RED 0
#define RB_BLACK 1
struct rb_node *rb_right;
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
/* The alignment might seem pointless, but allegedly CRIS needs it */
struct rb_root
{
struct rb_node *rb_node;
};
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r) ((r)->rb_parent_color & 1)
#define rb_is_red(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_black(r) do { (r)->rb_parent_color |= 1; } while (0)
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;
}
static inline void rb_set_color(struct rb_node *rb, ULONG_PTR color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
#define RB_ROOT (struct rb_root) { NULL, }
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
#define RB_EMPTY_NODE(node) (rb_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_erase(struct rb_node *, struct rb_root *);
/* Find logical next and previous nodes in a tree */
extern struct rb_node *rb_next(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_last(struct rb_root *);
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
struct rb_root *root);
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
{
node->rb_parent_color = (ULONG_PTR )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
extern void rb_insert(struct rb_root *root, struct rb_node *node,
int (*cmp)(struct rb_node *, struct rb_node *));
#endif /* _LINUX_RBTREE_H */

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

File diff suppressed because it is too large Load Diff