1
0
mirror of https://github.com/bobranten/Ext4Fsd.git synced 2026-05-21 13:20:49 -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
+1 -1
View File
@@ -1 +1 @@
DIRS = nls ext3 ext4 jbd2 sys
DIRS = nls ext3 ext4 jbd2 sys
+54 -54
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);
}
+759 -759
View File
File diff suppressed because it is too large Load Diff
+399 -399
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;
}
+247 -247
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();
}
}
+138 -138
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;
}
+2705 -2705
View File
File diff suppressed because it is too large Load Diff
+812 -812
View File
File diff suppressed because it is too large Load Diff
+1274 -1274
View File
File diff suppressed because it is too large Load Diff
+354 -354
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;
}
+604 -604
View File
File diff suppressed because it is too large Load Diff
+273 -273
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;
}
+1159 -1159
View File
File diff suppressed because it is too large Load Diff
+68 -68
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);
}
+244 -244
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;
}
+1125 -1125
View File
File diff suppressed because it is too large Load Diff
+2089 -2089
View File
File diff suppressed because it is too large Load Diff
+276 -276
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;
}
+261 -261
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_ */
+154 -154
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 */
+95 -95
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 */
+280 -280
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
+6 -6
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 */
+147 -147
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
+257 -257
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 */
+65 -65
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
+205 -205
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
/**
* @}
*/
+160 -160
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_*/
+29 -29
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 */
+92 -92
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 */
+255 -255
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__ */
+140 -140
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
+161 -161
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 */
+13 -13
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 */
+15 -15
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
+125 -125
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;
}
+532 -532
View File
File diff suppressed because it is too large Load Diff
+231 -231
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);
}
+396 -396
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)
+415 -415
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);
+945 -945
View File
File diff suppressed because it is too large Load Diff
+117 -117
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;
}
+408 -408
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;
}
+1423 -1423
View File
File diff suppressed because it is too large Load Diff