mirror of
https://github.com/bobranten/Ext4Fsd.git
synced 2025-10-30 05:18:31 -05:00
converted some files from UNIX to DOS line endings
This commit is contained in:
@@ -1 +1 @@
|
|||||||
DIRS = nls ext3 ext4 jbd2 sys
|
DIRS = nls ext3 ext4 jbd2 sys
|
||||||
|
|||||||
108
Ext4Fsd/access.c
108
Ext4Fsd/access.c
@@ -1,54 +1,54 @@
|
|||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYRIGHT.TXT
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: access.c
|
* FILE: access.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://www.ext2fsd.com
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
/* GLOBALS ***************************************************************/
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
extern PEXT2_GLOBAL Ext2Global;
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
int Ext2CheckInodeAccess(PEXT2_VCB Vcb, struct inode *in, int attempt)
|
int Ext2CheckInodeAccess(PEXT2_VCB Vcb, struct inode *in, int attempt)
|
||||||
{
|
{
|
||||||
int granted = 0;
|
int granted = 0;
|
||||||
|
|
||||||
uid_t uid = Vcb->uid;
|
uid_t uid = Vcb->uid;
|
||||||
gid_t gid = Vcb->gid;
|
gid_t gid = Vcb->gid;
|
||||||
|
|
||||||
if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) {
|
if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) {
|
||||||
uid = Vcb->euid;
|
uid = Vcb->euid;
|
||||||
gid = Vcb->egid;
|
gid = Vcb->egid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!uid || uid == in->i_uid) {
|
if (!uid || uid == in->i_uid) {
|
||||||
/* grant all access for inode owner or root */
|
/* grant all access for inode owner or root */
|
||||||
granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute;
|
granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute;
|
||||||
} else if (gid == in->i_gid) {
|
} else if (gid == in->i_gid) {
|
||||||
if (Ext2IsGroupReadOnly(in->i_mode))
|
if (Ext2IsGroupReadOnly(in->i_mode))
|
||||||
granted = Ext2FileCanRead | Ext2FileCanExecute;
|
granted = Ext2FileCanRead | Ext2FileCanExecute;
|
||||||
else if (Ext2IsGroupWritable(in->i_mode))
|
else if (Ext2IsGroupWritable(in->i_mode))
|
||||||
granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute;
|
granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute;
|
||||||
} else {
|
} else {
|
||||||
if (Ext2IsOtherReadOnly(in->i_mode))
|
if (Ext2IsOtherReadOnly(in->i_mode))
|
||||||
granted = Ext2FileCanRead | Ext2FileCanExecute;
|
granted = Ext2FileCanRead | Ext2FileCanExecute;
|
||||||
else if (Ext2IsOtherWritable(in->i_mode))
|
else if (Ext2IsOtherWritable(in->i_mode))
|
||||||
granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute;
|
granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return IsFlagOn(granted, attempt);
|
return IsFlagOn(granted, attempt);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Ext2CheckFileAccess(PEXT2_VCB Vcb, PEXT2_MCB Mcb, int attempt)
|
int Ext2CheckFileAccess(PEXT2_VCB Vcb, PEXT2_MCB Mcb, int attempt)
|
||||||
{
|
{
|
||||||
return Ext2CheckInodeAccess(Vcb, &Mcb->Inode, attempt);
|
return Ext2CheckInodeAccess(Vcb, &Mcb->Inode, attempt);
|
||||||
}
|
}
|
||||||
|
|||||||
1518
Ext4Fsd/block.c
1518
Ext4Fsd/block.c
File diff suppressed because it is too large
Load Diff
@@ -1,399 +1,399 @@
|
|||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYRIGHT.TXT
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: cleanup.c
|
* FILE: cleanup.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://www.ext2fsd.com
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
/* GLOBALS ***************************************************************/
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
extern PEXT2_GLOBAL Ext2Global;
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PEXT2_VCB Vcb = NULL;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
PEXT2_FCB Fcb = NULL;
|
PEXT2_FCB Fcb = NULL;
|
||||||
PEXT2_CCB Ccb = NULL;
|
PEXT2_CCB Ccb = NULL;
|
||||||
PIRP Irp = NULL;
|
PIRP Irp = NULL;
|
||||||
PEXT2_MCB Mcb = NULL;
|
PEXT2_MCB Mcb = NULL;
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
BOOLEAN FcbResourceAcquired = FALSE;
|
BOOLEAN FcbResourceAcquired = FALSE;
|
||||||
BOOLEAN FcbPagingIoResourceAcquired = FALSE;
|
BOOLEAN FcbPagingIoResourceAcquired = FALSE;
|
||||||
BOOLEAN SymLinkDelete = FALSE;
|
BOOLEAN SymLinkDelete = FALSE;
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
ASSERT(IrpContext != NULL);
|
ASSERT(IrpContext != NULL);
|
||||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
DeviceObject = IrpContext->DeviceObject;
|
DeviceObject = IrpContext->DeviceObject;
|
||||||
if (IsExt2FsDevice(DeviceObject)) {
|
if (IsExt2FsDevice(DeviceObject)) {
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp = IrpContext->Irp;
|
Irp = IrpContext->Irp;
|
||||||
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
|
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
|
||||||
ASSERT(Vcb != NULL);
|
ASSERT(Vcb != NULL);
|
||||||
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
||||||
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
|
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
|
||||||
|
|
||||||
if (!IsVcbInited(Vcb)) {
|
if (!IsVcbInited(Vcb)) {
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileObject = IrpContext->FileObject;
|
FileObject = IrpContext->FileObject;
|
||||||
Fcb = (PEXT2_FCB) FileObject->FsContext;
|
Fcb = (PEXT2_FCB) FileObject->FsContext;
|
||||||
if (!Fcb || (Fcb->Identifier.Type != EXT2VCB &&
|
if (!Fcb || (Fcb->Identifier.Type != EXT2VCB &&
|
||||||
Fcb->Identifier.Type != EXT2FCB)) {
|
Fcb->Identifier.Type != EXT2FCB)) {
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
Mcb = Fcb->Mcb;
|
Mcb = Fcb->Mcb;
|
||||||
Ccb = (PEXT2_CCB) FileObject->FsContext2;
|
Ccb = (PEXT2_CCB) FileObject->FsContext2;
|
||||||
|
|
||||||
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
|
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Fcb->Identifier.Type == EXT2VCB) {
|
if (Fcb->Identifier.Type == EXT2VCB) {
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(
|
ExAcquireResourceExclusiveLite(
|
||||||
&Vcb->MainResource, TRUE);
|
&Vcb->MainResource, TRUE);
|
||||||
VcbResourceAcquired = TRUE;
|
VcbResourceAcquired = TRUE;
|
||||||
|
|
||||||
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
|
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
|
||||||
Vcb->LockFile == FileObject ){
|
Vcb->LockFile == FileObject ){
|
||||||
|
|
||||||
ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
|
ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
|
||||||
Vcb->LockFile = NULL;
|
Vcb->LockFile = NULL;
|
||||||
Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
|
Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Ccb) {
|
if (Ccb) {
|
||||||
Ext2DerefXcb(&Vcb->OpenHandleCount);
|
Ext2DerefXcb(&Vcb->OpenHandleCount);
|
||||||
Ext2DerefXcb(&Vcb->OpenVolumeCount);
|
Ext2DerefXcb(&Vcb->OpenVolumeCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
|
IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
||||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||||
|
|
||||||
FcbResourceAcquired =
|
FcbResourceAcquired =
|
||||||
ExAcquireResourceExclusiveLite(
|
ExAcquireResourceExclusiveLite(
|
||||||
&Fcb->MainResource,
|
&Fcb->MainResource,
|
||||||
TRUE
|
TRUE
|
||||||
);
|
);
|
||||||
|
|
||||||
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
|
if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) {
|
||||||
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
|
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
|
||||||
IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
|
IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
|
||||||
!IsVcbReadOnly(Vcb) ) {
|
!IsVcbReadOnly(Vcb) ) {
|
||||||
Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
|
Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
|
||||||
}
|
}
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Ccb == NULL) {
|
if (Ccb == NULL) {
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsDirectory(Fcb)) {
|
if (IsDirectory(Fcb)) {
|
||||||
if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
|
if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
|
||||||
SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
|
SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
|
||||||
|
|
||||||
FsRtlNotifyFullChangeDirectory(
|
FsRtlNotifyFullChangeDirectory(
|
||||||
Vcb->NotifySync,
|
Vcb->NotifySync,
|
||||||
&Vcb->NotifyList,
|
&Vcb->NotifyList,
|
||||||
Ccb,
|
Ccb,
|
||||||
NULL,
|
NULL,
|
||||||
FALSE,
|
FALSE,
|
||||||
FALSE,
|
FALSE,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL );
|
NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb);
|
FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
|
ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
|
||||||
(Ccb->Identifier.Size == sizeof(EXT2_CCB)));
|
(Ccb->Identifier.Size == sizeof(EXT2_CCB)));
|
||||||
|
|
||||||
Ext2DerefXcb(&Vcb->OpenHandleCount);
|
Ext2DerefXcb(&Vcb->OpenHandleCount);
|
||||||
Ext2DerefXcb(&Fcb->OpenHandleCount);
|
Ext2DerefXcb(&Fcb->OpenHandleCount);
|
||||||
|
|
||||||
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
|
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
|
||||||
Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
|
Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsDirectory(Fcb)) {
|
if (IsDirectory(Fcb)) {
|
||||||
|
|
||||||
ext3_release_dir(Fcb->Inode, &Ccb->filp);
|
ext3_release_dir(Fcb->Inode, &Ccb->filp);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
|
if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
|
||||||
!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
|
!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
|
||||||
|
|
||||||
LARGE_INTEGER SysTime;
|
LARGE_INTEGER SysTime;
|
||||||
KeQuerySystemTime(&SysTime);
|
KeQuerySystemTime(&SysTime);
|
||||||
|
|
||||||
Fcb->Inode->i_atime =
|
Fcb->Inode->i_atime =
|
||||||
Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
|
Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
|
||||||
Fcb->Mcb->LastAccessTime =
|
Fcb->Mcb->LastAccessTime =
|
||||||
Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_atime);
|
Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_atime);
|
||||||
|
|
||||||
Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
|
Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
|
||||||
|
|
||||||
Ext2NotifyReportChange(
|
Ext2NotifyReportChange(
|
||||||
IrpContext,
|
IrpContext,
|
||||||
Vcb,
|
Vcb,
|
||||||
Fcb->Mcb,
|
Fcb->Mcb,
|
||||||
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
||||||
FILE_NOTIFY_CHANGE_LAST_WRITE |
|
FILE_NOTIFY_CHANGE_LAST_WRITE |
|
||||||
FILE_NOTIFY_CHANGE_LAST_ACCESS,
|
FILE_NOTIFY_CHANGE_LAST_ACCESS,
|
||||||
FILE_ACTION_MODIFIED );
|
FILE_ACTION_MODIFIED );
|
||||||
}
|
}
|
||||||
|
|
||||||
FsRtlCheckOplock( &Fcb->Oplock,
|
FsRtlCheckOplock( &Fcb->Oplock,
|
||||||
Irp,
|
Irp,
|
||||||
IrpContext,
|
IrpContext,
|
||||||
NULL,
|
NULL,
|
||||||
NULL );
|
NULL );
|
||||||
|
|
||||||
Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
|
Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
|
||||||
|
|
||||||
if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) {
|
if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) {
|
||||||
Fcb->NonCachedOpenCount--;
|
Fcb->NonCachedOpenCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
|
if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
|
||||||
if (Ccb->SymLink || IsInodeSymLink(&Mcb->Inode)) {
|
if (Ccb->SymLink || IsInodeSymLink(&Mcb->Inode)) {
|
||||||
SymLinkDelete = TRUE;
|
SymLinkDelete = TRUE;
|
||||||
} else {
|
} else {
|
||||||
SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
|
SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Drop any byte range locks this process may have on the file.
|
// Drop any byte range locks this process may have on the file.
|
||||||
//
|
//
|
||||||
|
|
||||||
FsRtlFastUnlockAll(
|
FsRtlFastUnlockAll(
|
||||||
&Fcb->FileLockAnchor,
|
&Fcb->FileLockAnchor,
|
||||||
FileObject,
|
FileObject,
|
||||||
IoGetRequestorProcess(Irp),
|
IoGetRequestorProcess(Irp),
|
||||||
NULL );
|
NULL );
|
||||||
|
|
||||||
//
|
//
|
||||||
// If there are no byte range locks owned by other processes on the
|
// If there are no byte range locks owned by other processes on the
|
||||||
// file the fast I/O read/write functions doesn't have to check for
|
// file the fast I/O read/write functions doesn't have to check for
|
||||||
// locks so we set IsFastIoPossible to FastIoIsPossible again.
|
// locks so we set IsFastIoPossible to FastIoIsPossible again.
|
||||||
//
|
//
|
||||||
if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) {
|
if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) {
|
||||||
if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) {
|
if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) {
|
||||||
#if EXT2_DEBUG
|
#if EXT2_DEBUG
|
||||||
DEBUG(DL_INF, (": %-16.16s %-31s %wZ\n",
|
DEBUG(DL_INF, (": %-16.16s %-31s %wZ\n",
|
||||||
Ext2GetCurrentProcessName(),
|
Ext2GetCurrentProcessName(),
|
||||||
"FastIoIsPossible",
|
"FastIoIsPossible",
|
||||||
&Fcb->Mcb->FullName
|
&Fcb->Mcb->FullName
|
||||||
));
|
));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Fcb->Header.IsFastIoPossible = FastIoIsPossible;
|
Fcb->Header.IsFastIoPossible = FastIoIsPossible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Fcb->OpenHandleCount == 0 && FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE |
|
if (Fcb->OpenHandleCount == 0 && FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE |
|
||||||
FCB_ALLOC_IN_SETINFO) ){
|
FCB_ALLOC_IN_SETINFO) ){
|
||||||
|
|
||||||
if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_SETINFO)) {
|
if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_SETINFO)) {
|
||||||
if (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart) {
|
if (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart) {
|
||||||
if (!INODE_HAS_EXTENT(Fcb->Inode)) {
|
if (!INODE_HAS_EXTENT(Fcb->Inode)) {
|
||||||
#if EXT2_PRE_ALLOCATION_SUPPORT
|
#if EXT2_PRE_ALLOCATION_SUPPORT
|
||||||
__try {
|
__try {
|
||||||
CcZeroData( FileObject,
|
CcZeroData( FileObject,
|
||||||
&Fcb->Header.ValidDataLength,
|
&Fcb->Header.ValidDataLength,
|
||||||
&Fcb->Header.AllocationSize,
|
&Fcb->Header.AllocationSize,
|
||||||
TRUE);
|
TRUE);
|
||||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
|
if (FlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
|
||||||
|
|
||||||
LARGE_INTEGER Size;
|
LARGE_INTEGER Size;
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
|
ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
|
||||||
FcbPagingIoResourceAcquired = TRUE;
|
FcbPagingIoResourceAcquired = TRUE;
|
||||||
|
|
||||||
Size.QuadPart = CEILING_ALIGNED(ULONGLONG,
|
Size.QuadPart = CEILING_ALIGNED(ULONGLONG,
|
||||||
(ULONGLONG)Fcb->Mcb->Inode.i_size,
|
(ULONGLONG)Fcb->Mcb->Inode.i_size,
|
||||||
(ULONGLONG)BLOCK_SIZE);
|
(ULONGLONG)BLOCK_SIZE);
|
||||||
if (!IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
|
if (!IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
|
||||||
|
|
||||||
Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
|
Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
|
||||||
Fcb->Header.AllocationSize = Size;
|
Fcb->Header.AllocationSize = Size;
|
||||||
Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size;
|
Fcb->Header.FileSize.QuadPart = Mcb->Inode.i_size;
|
||||||
if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart)
|
if (Fcb->Header.ValidDataLength.QuadPart > Fcb->Header.FileSize.QuadPart)
|
||||||
Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
|
Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
|
||||||
if (CcIsFileCached(FileObject)) {
|
if (CcIsFileCached(FileObject)) {
|
||||||
CcSetFileSizes(FileObject,
|
CcSetFileSizes(FileObject,
|
||||||
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
|
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE|FCB_ALLOC_IN_WRITE|FCB_ALLOC_IN_SETINFO);
|
ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE|FCB_ALLOC_IN_WRITE|FCB_ALLOC_IN_SETINFO);
|
||||||
ExReleaseResourceLite(&Fcb->PagingIoResource);
|
ExReleaseResourceLite(&Fcb->PagingIoResource);
|
||||||
FcbPagingIoResourceAcquired = FALSE;
|
FcbPagingIoResourceAcquired = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
|
IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
|
||||||
|
|
||||||
if (!IsDirectory(Fcb)) {
|
if (!IsDirectory(Fcb)) {
|
||||||
|
|
||||||
if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
|
if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
|
||||||
(Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) &&
|
(Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) &&
|
||||||
(Fcb->SectionObject.DataSectionObject != NULL)) {
|
(Fcb->SectionObject.DataSectionObject != NULL)) {
|
||||||
|
|
||||||
if (!IsVcbReadOnly(Vcb)) {
|
if (!IsVcbReadOnly(Vcb)) {
|
||||||
CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
|
CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
|
||||||
ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
|
ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* purge cache if all remaining openings are non-cached */
|
/* purge cache if all remaining openings are non-cached */
|
||||||
if (Fcb->NonCachedOpenCount > 0 ||
|
if (Fcb->NonCachedOpenCount > 0 ||
|
||||||
IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
|
IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
|
||||||
if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
|
if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
|
||||||
ExReleaseResourceLite(&(Fcb->PagingIoResource));
|
ExReleaseResourceLite(&(Fcb->PagingIoResource));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CcPurge could generate recursive IRP_MJ_CLOSE request */
|
/* CcPurge could generate recursive IRP_MJ_CLOSE request */
|
||||||
CcPurgeCacheSection( &Fcb->SectionObject,
|
CcPurgeCacheSection( &Fcb->SectionObject,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
FALSE );
|
FALSE );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CcUninitializeCacheMap(FileObject, NULL, NULL);
|
CcUninitializeCacheMap(FileObject, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SymLinkDelete ||
|
if (SymLinkDelete ||
|
||||||
(IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) &&
|
(IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) &&
|
||||||
Fcb->OpenHandleCount == 0) ) {
|
Fcb->OpenHandleCount == 0) ) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Ext2DeleteFile will acquire these lock inside
|
// Ext2DeleteFile will acquire these lock inside
|
||||||
//
|
//
|
||||||
|
|
||||||
if (FcbResourceAcquired) {
|
if (FcbResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
ExReleaseResourceLite(&Fcb->MainResource);
|
||||||
FcbResourceAcquired = FALSE;
|
FcbResourceAcquired = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// this file is to be deleted ...
|
// this file is to be deleted ...
|
||||||
//
|
//
|
||||||
if (Ccb->SymLink) {
|
if (Ccb->SymLink) {
|
||||||
Mcb = Ccb->SymLink;
|
Mcb = Ccb->SymLink;
|
||||||
FileObject->DeletePending = FALSE;
|
FileObject->DeletePending = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
|
Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
|
||||||
|
|
||||||
if (NT_SUCCESS(Status)) {
|
if (NT_SUCCESS(Status)) {
|
||||||
if (IsMcbDirectory(Mcb)) {
|
if (IsMcbDirectory(Mcb)) {
|
||||||
Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
|
Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
|
||||||
FILE_NOTIFY_CHANGE_DIR_NAME,
|
FILE_NOTIFY_CHANGE_DIR_NAME,
|
||||||
FILE_ACTION_REMOVED );
|
FILE_ACTION_REMOVED );
|
||||||
} else {
|
} else {
|
||||||
Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
|
Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
|
||||||
FILE_NOTIFY_CHANGE_FILE_NAME,
|
FILE_NOTIFY_CHANGE_FILE_NAME,
|
||||||
FILE_ACTION_REMOVED );
|
FILE_ACTION_REMOVED );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// re-acquire the main resource lock
|
// re-acquire the main resource lock
|
||||||
//
|
//
|
||||||
|
|
||||||
FcbResourceAcquired =
|
FcbResourceAcquired =
|
||||||
ExAcquireResourceExclusiveLite(
|
ExAcquireResourceExclusiveLite(
|
||||||
&Fcb->MainResource,
|
&Fcb->MainResource,
|
||||||
TRUE
|
TRUE
|
||||||
);
|
);
|
||||||
if (!SymLinkDelete) {
|
if (!SymLinkDelete) {
|
||||||
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
|
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
|
||||||
if (CcIsFileCached(FileObject)) {
|
if (CcIsFileCached(FileObject)) {
|
||||||
CcSetFileSizes(FileObject,
|
CcSetFileSizes(FileObject,
|
||||||
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
|
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n",
|
DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n",
|
||||||
Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName));
|
Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName));
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
if (FileObject) {
|
if (FileObject) {
|
||||||
SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
|
SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
if (FcbPagingIoResourceAcquired) {
|
if (FcbPagingIoResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Fcb->PagingIoResource);
|
ExReleaseResourceLite(&Fcb->PagingIoResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FcbResourceAcquired) {
|
if (FcbResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
ExReleaseResourceLite(&Fcb->MainResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VcbResourceAcquired) {
|
if (VcbResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IrpContext->ExceptionInProgress) {
|
if (!IrpContext->ExceptionInProgress) {
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
Ext2QueueRequest(IrpContext);
|
Ext2QueueRequest(IrpContext);
|
||||||
} else {
|
} else {
|
||||||
IrpContext->Irp->IoStatus.Status = Status;
|
IrpContext->Irp->IoStatus.Status = Status;
|
||||||
Ext2CompleteIrpContext(IrpContext, Status);
|
Ext2CompleteIrpContext(IrpContext, Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|||||||
494
Ext4Fsd/close.c
494
Ext4Fsd/close.c
@@ -1,247 +1,247 @@
|
|||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYRIGHT.TXT
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: close.c
|
* FILE: close.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://www.ext2fsd.com
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
/* GLOBALS ***************************************************************/
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
extern PEXT2_GLOBAL Ext2Global;
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, Ext2QueueCloseRequest)
|
#pragma alloc_text(PAGE, Ext2QueueCloseRequest)
|
||||||
#pragma alloc_text(PAGE, Ext2DeQueueCloseRequest)
|
#pragma alloc_text(PAGE, Ext2DeQueueCloseRequest)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PEXT2_VCB Vcb = NULL;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
PEXT2_FCB Fcb = NULL;
|
PEXT2_FCB Fcb = NULL;
|
||||||
PEXT2_CCB Ccb = NULL;
|
PEXT2_CCB Ccb = NULL;
|
||||||
|
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
BOOLEAN FcbResourceAcquired = FALSE;
|
BOOLEAN FcbResourceAcquired = FALSE;
|
||||||
BOOLEAN FcbDerefDeferred = FALSE;
|
BOOLEAN FcbDerefDeferred = FALSE;
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
ASSERT(IrpContext != NULL);
|
ASSERT(IrpContext != NULL);
|
||||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
DeviceObject = IrpContext->DeviceObject;
|
DeviceObject = IrpContext->DeviceObject;
|
||||||
if (IsExt2FsDevice(DeviceObject)) {
|
if (IsExt2FsDevice(DeviceObject)) {
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
Vcb = NULL;
|
Vcb = NULL;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
|
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
|
||||||
ASSERT(Vcb != NULL);
|
ASSERT(Vcb != NULL);
|
||||||
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
||||||
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
|
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
|
||||||
|
|
||||||
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
|
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
|
||||||
|
|
||||||
FileObject = NULL;
|
FileObject = NULL;
|
||||||
Fcb = IrpContext->Fcb;
|
Fcb = IrpContext->Fcb;
|
||||||
Ccb = IrpContext->Ccb;
|
Ccb = IrpContext->Ccb;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
FileObject = IrpContext->FileObject;
|
FileObject = IrpContext->FileObject;
|
||||||
Fcb = (PEXT2_FCB) FileObject->FsContext;
|
Fcb = (PEXT2_FCB) FileObject->FsContext;
|
||||||
if (!Fcb) {
|
if (!Fcb) {
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
ASSERT(Fcb != NULL);
|
ASSERT(Fcb != NULL);
|
||||||
Ccb = (PEXT2_CCB) FileObject->FsContext2;
|
Ccb = (PEXT2_CCB) FileObject->FsContext2;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Ext2Close: (VCB) Vcb = %p ReferCount = %d\n",
|
DEBUG(DL_INF, ( "Ext2Close: (VCB) Vcb = %p ReferCount = %d\n",
|
||||||
Vcb, Vcb->ReferenceCount));
|
Vcb, Vcb->ReferenceCount));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WARNING: don't release Vcb resource lock here.
|
* WARNING: don't release Vcb resource lock here.
|
||||||
*
|
*
|
||||||
* CcPurgeCacheSection will lead a recursive irp: IRP_MJ_CLOSE
|
* CcPurgeCacheSection will lead a recursive irp: IRP_MJ_CLOSE
|
||||||
* which would cause revrese order of lock acquirision:
|
* which would cause revrese order of lock acquirision:
|
||||||
* 1) IRP_MJ_CLEANUP: a) Vcb lock -> b) Fcb lock
|
* 1) IRP_MJ_CLEANUP: a) Vcb lock -> b) Fcb lock
|
||||||
* 2) IRP_MJ_CLOSE: c) Vcb lock -> d) Fcb lock
|
* 2) IRP_MJ_CLOSE: c) Vcb lock -> d) Fcb lock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (Fcb->Identifier.Type == EXT2VCB) {
|
if (Fcb->Identifier.Type == EXT2VCB) {
|
||||||
|
|
||||||
if (!ExAcquireResourceExclusiveLite(
|
if (!ExAcquireResourceExclusiveLite(
|
||||||
&Vcb->MainResource,
|
&Vcb->MainResource,
|
||||||
TRUE )) {
|
TRUE )) {
|
||||||
DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n",
|
DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n",
|
||||||
Vcb->OpenHandleCount, Vcb->ReferenceCount));
|
Vcb->OpenHandleCount, Vcb->ReferenceCount));
|
||||||
Status = STATUS_PENDING;
|
Status = STATUS_PENDING;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
VcbResourceAcquired = TRUE;
|
VcbResourceAcquired = TRUE;
|
||||||
|
|
||||||
if (Ccb) {
|
if (Ccb) {
|
||||||
|
|
||||||
Ext2DerefXcb(&Vcb->ReferenceCount);
|
Ext2DerefXcb(&Vcb->ReferenceCount);
|
||||||
Ext2FreeCcb(Vcb, Ccb);
|
Ext2FreeCcb(Vcb, Ccb);
|
||||||
|
|
||||||
if (FileObject) {
|
if (FileObject) {
|
||||||
FileObject->FsContext2 = Ccb = NULL;
|
FileObject->FsContext2 = Ccb = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( Fcb->Identifier.Type != EXT2FCB ||
|
if ( Fcb->Identifier.Type != EXT2FCB ||
|
||||||
Fcb->Identifier.Size != sizeof(EXT2_FCB)) {
|
Fcb->Identifier.Size != sizeof(EXT2_FCB)) {
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ExAcquireResourceExclusiveLite(
|
if (!ExAcquireResourceExclusiveLite(
|
||||||
&Fcb->MainResource,
|
&Fcb->MainResource,
|
||||||
TRUE )) {
|
TRUE )) {
|
||||||
Status = STATUS_PENDING;
|
Status = STATUS_PENDING;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
FcbResourceAcquired = TRUE;
|
FcbResourceAcquired = TRUE;
|
||||||
|
|
||||||
Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
|
Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
|
||||||
|
|
||||||
if (Ccb == NULL ||
|
if (Ccb == NULL ||
|
||||||
Ccb->Identifier.Type != EXT2CCB ||
|
Ccb->Identifier.Type != EXT2CCB ||
|
||||||
Ccb->Identifier.Size != sizeof(EXT2_CCB)) {
|
Ccb->Identifier.Size != sizeof(EXT2_CCB)) {
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Ext2Close: Fcb = %p OpenHandleCount= %u ReferenceCount=%u NonCachedCount=%u %wZ\n",
|
DEBUG(DL_INF, ( "Ext2Close: Fcb = %p OpenHandleCount= %u ReferenceCount=%u NonCachedCount=%u %wZ\n",
|
||||||
Fcb, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName ));
|
Fcb, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName ));
|
||||||
|
|
||||||
Ext2FreeCcb(Vcb, Ccb);
|
Ext2FreeCcb(Vcb, Ccb);
|
||||||
if (FileObject) {
|
if (FileObject) {
|
||||||
FileObject->FsContext2 = Ccb = NULL;
|
FileObject->FsContext2 = Ccb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only deref fcb, Ext2ReleaseFcb might lead deadlock */
|
/* only deref fcb, Ext2ReleaseFcb might lead deadlock */
|
||||||
FcbDerefDeferred = TRUE;
|
FcbDerefDeferred = TRUE;
|
||||||
if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) ||
|
if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) ||
|
||||||
NULL == Fcb->Mcb ||
|
NULL == Fcb->Mcb ||
|
||||||
IsFileDeleted(Fcb->Mcb)) {
|
IsFileDeleted(Fcb->Mcb)) {
|
||||||
Fcb->TsDrop.QuadPart = 0;
|
Fcb->TsDrop.QuadPart = 0;
|
||||||
} else {
|
} else {
|
||||||
KeQuerySystemTime(&Fcb->TsDrop);
|
KeQuerySystemTime(&Fcb->TsDrop);
|
||||||
}
|
}
|
||||||
Ext2DerefXcb(&Vcb->ReferenceCount);
|
Ext2DerefXcb(&Vcb->ReferenceCount);
|
||||||
|
|
||||||
if (FileObject) {
|
if (FileObject) {
|
||||||
FileObject->FsContext = NULL;
|
FileObject->FsContext = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
if (FcbResourceAcquired) {
|
if (FcbResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
ExReleaseResourceLite(&Fcb->MainResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VcbResourceAcquired) {
|
if (VcbResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IrpContext->ExceptionInProgress) {
|
if (!IrpContext->ExceptionInProgress) {
|
||||||
|
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
|
|
||||||
Ext2QueueCloseRequest(IrpContext);
|
Ext2QueueCloseRequest(IrpContext);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
Ext2CompleteIrpContext(IrpContext, Status);
|
Ext2CompleteIrpContext(IrpContext, Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FcbDerefDeferred)
|
if (FcbDerefDeferred)
|
||||||
Ext2DerefXcb(&Fcb->ReferenceCount);
|
Ext2DerefXcb(&Fcb->ReferenceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2QueueCloseRequest (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2QueueCloseRequest (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
ASSERT(IrpContext);
|
ASSERT(IrpContext);
|
||||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
|
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
|
||||||
|
|
||||||
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY)) {
|
if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY)) {
|
||||||
Ext2Sleep(500); /* 0.5 sec*/
|
Ext2Sleep(500); /* 0.5 sec*/
|
||||||
} else {
|
} else {
|
||||||
Ext2Sleep(50); /* 0.05 sec*/
|
Ext2Sleep(50); /* 0.05 sec*/
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
|
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
|
||||||
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE);
|
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE);
|
||||||
|
|
||||||
IrpContext->Fcb = (PEXT2_FCB) IrpContext->FileObject->FsContext;
|
IrpContext->Fcb = (PEXT2_FCB) IrpContext->FileObject->FsContext;
|
||||||
IrpContext->Ccb = (PEXT2_CCB) IrpContext->FileObject->FsContext2;
|
IrpContext->Ccb = (PEXT2_CCB) IrpContext->FileObject->FsContext2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExInitializeWorkItem(
|
ExInitializeWorkItem(
|
||||||
&IrpContext->WorkQueueItem,
|
&IrpContext->WorkQueueItem,
|
||||||
Ext2DeQueueCloseRequest,
|
Ext2DeQueueCloseRequest,
|
||||||
IrpContext);
|
IrpContext);
|
||||||
|
|
||||||
ExQueueWorkItem(&IrpContext->WorkQueueItem, DelayedWorkQueue);
|
ExQueueWorkItem(&IrpContext->WorkQueueItem, DelayedWorkQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2DeQueueCloseRequest (IN PVOID Context)
|
Ext2DeQueueCloseRequest (IN PVOID Context)
|
||||||
{
|
{
|
||||||
PEXT2_IRP_CONTEXT IrpContext;
|
PEXT2_IRP_CONTEXT IrpContext;
|
||||||
|
|
||||||
IrpContext = (PEXT2_IRP_CONTEXT) Context;
|
IrpContext = (PEXT2_IRP_CONTEXT) Context;
|
||||||
ASSERT(IrpContext);
|
ASSERT(IrpContext);
|
||||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
FsRtlEnterFileSystem();
|
FsRtlEnterFileSystem();
|
||||||
Ext2Close(IrpContext);
|
Ext2Close(IrpContext);
|
||||||
|
|
||||||
} __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) {
|
} __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) {
|
||||||
|
|
||||||
Ext2ExceptionHandler(IrpContext);
|
Ext2ExceptionHandler(IrpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
FsRtlExitFileSystem();
|
FsRtlExitFileSystem();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
276
Ext4Fsd/cmcb.c
276
Ext4Fsd/cmcb.c
@@ -1,138 +1,138 @@
|
|||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYRIGHT.TXT
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: cmcb.c
|
* FILE: cmcb.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://www.ext2fsd.com
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
/* GLOBALS ***************************************************************/
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
extern PEXT2_GLOBAL Ext2Global;
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
#define CMCB_DEBUG_LEVEL DL_NVR
|
#define CMCB_DEBUG_LEVEL DL_NVR
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
Ext2AcquireForLazyWrite (
|
Ext2AcquireForLazyWrite (
|
||||||
IN PVOID Context,
|
IN PVOID Context,
|
||||||
IN BOOLEAN Wait)
|
IN BOOLEAN Wait)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// On a readonly filesystem this function still has to exist but it
|
// On a readonly filesystem this function still has to exist but it
|
||||||
// doesn't need to do anything.
|
// doesn't need to do anything.
|
||||||
|
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb;
|
||||||
|
|
||||||
Fcb = (PEXT2_FCB) Context;
|
Fcb = (PEXT2_FCB) Context;
|
||||||
ASSERT(Fcb != NULL);
|
ASSERT(Fcb != NULL);
|
||||||
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
||||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||||
#if EXT2_DEBUG
|
#if EXT2_DEBUG
|
||||||
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireForLazyWrite: %s %s Fcb=%p\n",
|
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireForLazyWrite: %s %s Fcb=%p\n",
|
||||||
Ext2GetCurrentProcessName(), "ACQUIRE_FOR_LAZY_WRITE", Fcb));
|
Ext2GetCurrentProcessName(), "ACQUIRE_FOR_LAZY_WRITE", Fcb));
|
||||||
#endif
|
#endif
|
||||||
if (!ExAcquireResourceExclusiveLite(Fcb->Header.Resource, Wait)) {
|
if (!ExAcquireResourceExclusiveLite(Fcb->Header.Resource, Wait)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(Fcb->LazyWriterThread == NULL);
|
ASSERT(Fcb->LazyWriterThread == NULL);
|
||||||
Fcb->LazyWriterThread = PsGetCurrentThread();
|
Fcb->LazyWriterThread = PsGetCurrentThread();
|
||||||
|
|
||||||
ASSERT(IoGetTopLevelIrp() == NULL);
|
ASSERT(IoGetTopLevelIrp() == NULL);
|
||||||
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2ReleaseFromLazyWrite (IN PVOID Context)
|
Ext2ReleaseFromLazyWrite (IN PVOID Context)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// On a readonly filesystem this function still has to exist but it
|
// On a readonly filesystem this function still has to exist but it
|
||||||
// doesn't need to do anything.
|
// doesn't need to do anything.
|
||||||
PEXT2_FCB Fcb = (PEXT2_FCB) Context;
|
PEXT2_FCB Fcb = (PEXT2_FCB) Context;
|
||||||
|
|
||||||
ASSERT(Fcb != NULL);
|
ASSERT(Fcb != NULL);
|
||||||
|
|
||||||
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
||||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||||
#if EXT2_DEBUG
|
#if EXT2_DEBUG
|
||||||
DEBUG(CMCB_DEBUG_LEVEL, ( "Ext2ReleaseFromLazyWrite: %s %s Fcb=%p\n",
|
DEBUG(CMCB_DEBUG_LEVEL, ( "Ext2ReleaseFromLazyWrite: %s %s Fcb=%p\n",
|
||||||
Ext2GetCurrentProcessName(), "RELEASE_FROM_LAZY_WRITE", Fcb));
|
Ext2GetCurrentProcessName(), "RELEASE_FROM_LAZY_WRITE", Fcb));
|
||||||
#endif
|
#endif
|
||||||
ASSERT(Fcb->LazyWriterThread == PsGetCurrentThread());
|
ASSERT(Fcb->LazyWriterThread == PsGetCurrentThread());
|
||||||
Fcb->LazyWriterThread = NULL;
|
Fcb->LazyWriterThread = NULL;
|
||||||
|
|
||||||
ExReleaseResourceLite(Fcb->Header.Resource);
|
ExReleaseResourceLite(Fcb->Header.Resource);
|
||||||
|
|
||||||
ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
||||||
IoSetTopLevelIrp( NULL );
|
IoSetTopLevelIrp( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
Ext2AcquireForReadAhead (IN PVOID Context,
|
Ext2AcquireForReadAhead (IN PVOID Context,
|
||||||
IN BOOLEAN Wait)
|
IN BOOLEAN Wait)
|
||||||
{
|
{
|
||||||
PEXT2_FCB Fcb = (PEXT2_FCB) Context;
|
PEXT2_FCB Fcb = (PEXT2_FCB) Context;
|
||||||
|
|
||||||
ASSERT(Fcb != NULL);
|
ASSERT(Fcb != NULL);
|
||||||
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
||||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||||
|
|
||||||
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireForReadAhead: i=%xh Fcb=%p\n",
|
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireForReadAhead: i=%xh Fcb=%p\n",
|
||||||
Fcb->Mcb->Inode.i_ino, Fcb));
|
Fcb->Mcb->Inode.i_ino, Fcb));
|
||||||
|
|
||||||
if (!ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait))
|
if (!ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
ASSERT(IoGetTopLevelIrp() == NULL);
|
ASSERT(IoGetTopLevelIrp() == NULL);
|
||||||
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2ReleaseFromReadAhead (IN PVOID Context)
|
Ext2ReleaseFromReadAhead (IN PVOID Context)
|
||||||
{
|
{
|
||||||
PEXT2_FCB Fcb = (PEXT2_FCB) Context;
|
PEXT2_FCB Fcb = (PEXT2_FCB) Context;
|
||||||
|
|
||||||
ASSERT(Fcb != NULL);
|
ASSERT(Fcb != NULL);
|
||||||
|
|
||||||
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
||||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||||
|
|
||||||
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2ReleaseFromReadAhead: i=%xh Fcb=%p\n",
|
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2ReleaseFromReadAhead: i=%xh Fcb=%p\n",
|
||||||
Fcb->Mcb->Inode.i_ino, Fcb));
|
Fcb->Mcb->Inode.i_ino, Fcb));
|
||||||
|
|
||||||
IoSetTopLevelIrp(NULL);
|
IoSetTopLevelIrp(NULL);
|
||||||
ExReleaseResourceLite(Fcb->Header.Resource);
|
ExReleaseResourceLite(Fcb->Header.Resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
Ext2NoOpAcquire (
|
Ext2NoOpAcquire (
|
||||||
IN PVOID Fcb,
|
IN PVOID Fcb,
|
||||||
IN BOOLEAN Wait
|
IN BOOLEAN Wait
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ASSERT(IoGetTopLevelIrp() == NULL);
|
ASSERT(IoGetTopLevelIrp() == NULL);
|
||||||
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2NoOpRelease (
|
Ext2NoOpRelease (
|
||||||
IN PVOID Fcb
|
IN PVOID Fcb
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
||||||
IoSetTopLevelIrp( NULL );
|
IoSetTopLevelIrp( NULL );
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5410
Ext4Fsd/debug.c
5410
Ext4Fsd/debug.c
File diff suppressed because it is too large
Load Diff
1624
Ext4Fsd/devctl.c
1624
Ext4Fsd/devctl.c
File diff suppressed because it is too large
Load Diff
2548
Ext4Fsd/dirctl.c
2548
Ext4Fsd/dirctl.c
File diff suppressed because it is too large
Load Diff
@@ -1,354 +1,354 @@
|
|||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYRIGHT.TXT
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: dispatch.c
|
* FILE: dispatch.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://www.ext2fsd.com
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
/* GLOBALS ***************************************************************/
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
extern PEXT2_GLOBAL Ext2Global;
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, Ext2QueueRequest)
|
#pragma alloc_text(PAGE, Ext2QueueRequest)
|
||||||
#pragma alloc_text(PAGE, Ext2DeQueueRequest)
|
#pragma alloc_text(PAGE, Ext2DeQueueRequest)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ext2OplockComplete
|
* Ext2OplockComplete
|
||||||
*
|
*
|
||||||
* callback routine of FsRtlCheckOplock when an oplock break has
|
* callback routine of FsRtlCheckOplock when an oplock break has
|
||||||
* completed, allowing an Irp to resume execution.
|
* completed, allowing an Irp to resume execution.
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
*
|
*
|
||||||
* Context: the IrpContext to be queued
|
* Context: the IrpContext to be queued
|
||||||
* Irp: the I/O request packet
|
* Irp: the I/O request packet
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* N/A
|
* N/A
|
||||||
*/
|
*/
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2OplockComplete (
|
Ext2OplockComplete (
|
||||||
IN PVOID Context,
|
IN PVOID Context,
|
||||||
IN PIRP Irp
|
IN PIRP Irp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Check on the return value in the Irp.
|
// Check on the return value in the Irp.
|
||||||
//
|
//
|
||||||
|
|
||||||
if (Irp->IoStatus.Status == STATUS_SUCCESS) {
|
if (Irp->IoStatus.Status == STATUS_SUCCESS) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// queue the Irp context in the workqueue.
|
// queue the Irp context in the workqueue.
|
||||||
//
|
//
|
||||||
|
|
||||||
Ext2QueueRequest((PEXT2_IRP_CONTEXT)Context);
|
Ext2QueueRequest((PEXT2_IRP_CONTEXT)Context);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//
|
//
|
||||||
// complete the request in case of failure
|
// complete the request in case of failure
|
||||||
//
|
//
|
||||||
|
|
||||||
Ext2CompleteIrpContext( (PEXT2_IRP_CONTEXT) Context,
|
Ext2CompleteIrpContext( (PEXT2_IRP_CONTEXT) Context,
|
||||||
Irp->IoStatus.Status );
|
Irp->IoStatus.Status );
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ext2LockIrp
|
* Ext2LockIrp
|
||||||
*
|
*
|
||||||
* performs buffer locking if we need pend the process of the Irp
|
* performs buffer locking if we need pend the process of the Irp
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
* Context: the irp context
|
* Context: the irp context
|
||||||
* Irp: the I/O request packet.
|
* Irp: the I/O request packet.
|
||||||
*
|
*
|
||||||
* Return Value:
|
* Return Value:
|
||||||
* N/A
|
* N/A
|
||||||
*/
|
*/
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2LockIrp (
|
Ext2LockIrp (
|
||||||
IN PVOID Context,
|
IN PVOID Context,
|
||||||
IN PIRP Irp
|
IN PIRP Irp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IrpSp;
|
PIO_STACK_LOCATION IrpSp;
|
||||||
PEXT2_IRP_CONTEXT IrpContext;
|
PEXT2_IRP_CONTEXT IrpContext;
|
||||||
|
|
||||||
if (Irp == NULL) {
|
if (Irp == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
IrpContext = (PEXT2_IRP_CONTEXT) Context;
|
IrpContext = (PEXT2_IRP_CONTEXT) Context;
|
||||||
|
|
||||||
if ( IrpContext->MajorFunction == IRP_MJ_READ ||
|
if ( IrpContext->MajorFunction == IRP_MJ_READ ||
|
||||||
IrpContext->MajorFunction == IRP_MJ_WRITE ) {
|
IrpContext->MajorFunction == IRP_MJ_WRITE ) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// lock the user's buffer to MDL, if the I/O is bufferred
|
// lock the user's buffer to MDL, if the I/O is bufferred
|
||||||
//
|
//
|
||||||
|
|
||||||
if (!IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
|
if (!IsFlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
|
||||||
|
|
||||||
Ext2LockUserBuffer( Irp, IrpSp->Parameters.Write.Length,
|
Ext2LockUserBuffer( Irp, IrpSp->Parameters.Write.Length,
|
||||||
(IrpContext->MajorFunction == IRP_MJ_READ) ?
|
(IrpContext->MajorFunction == IRP_MJ_READ) ?
|
||||||
IoWriteAccess : IoReadAccess );
|
IoWriteAccess : IoReadAccess );
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (IrpContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL
|
} else if (IrpContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL
|
||||||
&& IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) {
|
&& IrpContext->MinorFunction == IRP_MN_QUERY_DIRECTORY) {
|
||||||
|
|
||||||
ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryDirectory.Length;
|
ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryDirectory.Length;
|
||||||
Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
|
Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
|
||||||
|
|
||||||
} else if (IrpContext->MajorFunction == IRP_MJ_QUERY_EA) {
|
} else if (IrpContext->MajorFunction == IRP_MJ_QUERY_EA) {
|
||||||
|
|
||||||
ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryEa.Length;
|
ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.QueryEa.Length;
|
||||||
Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
|
Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
|
||||||
|
|
||||||
} else if (IrpContext->MajorFunction == IRP_MJ_SET_EA) {
|
} else if (IrpContext->MajorFunction == IRP_MJ_SET_EA) {
|
||||||
ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.SetEa.Length;
|
ULONG Length = ((PEXTENDED_IO_STACK_LOCATION) IrpSp)->Parameters.SetEa.Length;
|
||||||
Ext2LockUserBuffer(Irp, Length, IoReadAccess);
|
Ext2LockUserBuffer(Irp, Length, IoReadAccess);
|
||||||
|
|
||||||
} else if ( (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
|
} else if ( (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
|
||||||
(IrpContext->MinorFunction == IRP_MN_USER_FS_REQUEST) ) {
|
(IrpContext->MinorFunction == IRP_MN_USER_FS_REQUEST) ) {
|
||||||
PEXTENDED_IO_STACK_LOCATION EIrpSp = (PEXTENDED_IO_STACK_LOCATION)IrpSp;
|
PEXTENDED_IO_STACK_LOCATION EIrpSp = (PEXTENDED_IO_STACK_LOCATION)IrpSp;
|
||||||
if ( (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_VOLUME_BITMAP) ||
|
if ( (EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_VOLUME_BITMAP) ||
|
||||||
(EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTERS) ||
|
(EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTERS) ||
|
||||||
(EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTER_BASE) ) {
|
(EIrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_GET_RETRIEVAL_POINTER_BASE) ) {
|
||||||
ULONG Length = EIrpSp->Parameters.FileSystemControl.OutputBufferLength;
|
ULONG Length = EIrpSp->Parameters.FileSystemControl.OutputBufferLength;
|
||||||
Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
|
Ext2LockUserBuffer(Irp, Length, IoWriteAccess);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark the request as pending status
|
// Mark the request as pending status
|
||||||
|
|
||||||
IoMarkIrpPending( Irp );
|
IoMarkIrpPending( Irp );
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2QueueRequest (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2QueueRequest (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
ASSERT(IrpContext);
|
ASSERT(IrpContext);
|
||||||
|
|
||||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
/* set the flags of "can wait" and "queued" */
|
/* set the flags of "can wait" and "queued" */
|
||||||
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
|
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
|
||||||
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
|
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);
|
||||||
|
|
||||||
/* make sure the buffer is kept valid in system context */
|
/* make sure the buffer is kept valid in system context */
|
||||||
Ext2LockIrp(IrpContext, IrpContext->Irp);
|
Ext2LockIrp(IrpContext, IrpContext->Irp);
|
||||||
|
|
||||||
/* initialize workite*/
|
/* initialize workite*/
|
||||||
ExInitializeWorkItem(
|
ExInitializeWorkItem(
|
||||||
&IrpContext->WorkQueueItem,
|
&IrpContext->WorkQueueItem,
|
||||||
Ext2DeQueueRequest,
|
Ext2DeQueueRequest,
|
||||||
IrpContext );
|
IrpContext );
|
||||||
|
|
||||||
/* dispatch it */
|
/* dispatch it */
|
||||||
ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
|
ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
|
||||||
|
|
||||||
return STATUS_PENDING;
|
return STATUS_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2DeQueueRequest (IN PVOID Context)
|
Ext2DeQueueRequest (IN PVOID Context)
|
||||||
{
|
{
|
||||||
PEXT2_IRP_CONTEXT IrpContext;
|
PEXT2_IRP_CONTEXT IrpContext;
|
||||||
|
|
||||||
IrpContext = (PEXT2_IRP_CONTEXT) Context;
|
IrpContext = (PEXT2_IRP_CONTEXT) Context;
|
||||||
|
|
||||||
ASSERT(IrpContext);
|
ASSERT(IrpContext);
|
||||||
|
|
||||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
FsRtlEnterFileSystem();
|
FsRtlEnterFileSystem();
|
||||||
|
|
||||||
if (!IrpContext->IsTopLevel) {
|
if (!IrpContext->IsTopLevel) {
|
||||||
IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP);
|
IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ext2DispatchRequest(IrpContext);
|
Ext2DispatchRequest(IrpContext);
|
||||||
|
|
||||||
} __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) {
|
} __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) {
|
||||||
|
|
||||||
Ext2ExceptionHandler(IrpContext);
|
Ext2ExceptionHandler(IrpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
IoSetTopLevelIrp(NULL);
|
IoSetTopLevelIrp(NULL);
|
||||||
|
|
||||||
FsRtlExitFileSystem();
|
FsRtlExitFileSystem();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2DispatchRequest (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2DispatchRequest (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
ASSERT(IrpContext);
|
ASSERT(IrpContext);
|
||||||
|
|
||||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
switch (IrpContext->MajorFunction) {
|
switch (IrpContext->MajorFunction) {
|
||||||
|
|
||||||
case IRP_MJ_CREATE:
|
case IRP_MJ_CREATE:
|
||||||
return Ext2Create(IrpContext);
|
return Ext2Create(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_CLOSE:
|
case IRP_MJ_CLOSE:
|
||||||
return Ext2Close(IrpContext);
|
return Ext2Close(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_READ:
|
case IRP_MJ_READ:
|
||||||
return Ext2Read(IrpContext);
|
return Ext2Read(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_WRITE:
|
case IRP_MJ_WRITE:
|
||||||
return Ext2Write(IrpContext);
|
return Ext2Write(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_FLUSH_BUFFERS:
|
case IRP_MJ_FLUSH_BUFFERS:
|
||||||
return Ext2Flush(IrpContext);
|
return Ext2Flush(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_QUERY_INFORMATION:
|
case IRP_MJ_QUERY_INFORMATION:
|
||||||
return Ext2QueryFileInformation(IrpContext);
|
return Ext2QueryFileInformation(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_SET_INFORMATION:
|
case IRP_MJ_SET_INFORMATION:
|
||||||
return Ext2SetFileInformation(IrpContext);
|
return Ext2SetFileInformation(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
||||||
return Ext2QueryVolumeInformation(IrpContext);
|
return Ext2QueryVolumeInformation(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_SET_VOLUME_INFORMATION:
|
case IRP_MJ_SET_VOLUME_INFORMATION:
|
||||||
return Ext2SetVolumeInformation(IrpContext);
|
return Ext2SetVolumeInformation(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_DIRECTORY_CONTROL:
|
case IRP_MJ_DIRECTORY_CONTROL:
|
||||||
return Ext2DirectoryControl(IrpContext);
|
return Ext2DirectoryControl(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_FILE_SYSTEM_CONTROL:
|
case IRP_MJ_FILE_SYSTEM_CONTROL:
|
||||||
return Ext2FileSystemControl(IrpContext);
|
return Ext2FileSystemControl(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_DEVICE_CONTROL:
|
case IRP_MJ_DEVICE_CONTROL:
|
||||||
return Ext2DeviceControl(IrpContext);
|
return Ext2DeviceControl(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_LOCK_CONTROL:
|
case IRP_MJ_LOCK_CONTROL:
|
||||||
return Ext2LockControl(IrpContext);
|
return Ext2LockControl(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_CLEANUP:
|
case IRP_MJ_CLEANUP:
|
||||||
return Ext2Cleanup(IrpContext);
|
return Ext2Cleanup(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_SHUTDOWN:
|
case IRP_MJ_SHUTDOWN:
|
||||||
return Ext2ShutDown(IrpContext);
|
return Ext2ShutDown(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_QUERY_EA:
|
case IRP_MJ_QUERY_EA:
|
||||||
return Ext2QueryEa(IrpContext);
|
return Ext2QueryEa(IrpContext);
|
||||||
|
|
||||||
case IRP_MJ_SET_EA:
|
case IRP_MJ_SET_EA:
|
||||||
return Ext2SetEa(IrpContext);
|
return Ext2SetEa(IrpContext);
|
||||||
|
|
||||||
#if (_WIN32_WINNT >= 0x0500)
|
#if (_WIN32_WINNT >= 0x0500)
|
||||||
case IRP_MJ_PNP:
|
case IRP_MJ_PNP:
|
||||||
return Ext2Pnp(IrpContext);
|
return Ext2Pnp(IrpContext);
|
||||||
#endif //(_WIN32_WINNT >= 0x0500)
|
#endif //(_WIN32_WINNT >= 0x0500)
|
||||||
default:
|
default:
|
||||||
DEBUG(DL_ERR, ( "Ext2DispatchRequest: Unexpected major function: %xh\n",
|
DEBUG(DL_ERR, ( "Ext2DispatchRequest: Unexpected major function: %xh\n",
|
||||||
IrpContext->MajorFunction));
|
IrpContext->MajorFunction));
|
||||||
|
|
||||||
Ext2CompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR);
|
Ext2CompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR);
|
||||||
|
|
||||||
return STATUS_DRIVER_INTERNAL_ERROR;
|
return STATUS_DRIVER_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2BuildRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
Ext2BuildRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||||
{
|
{
|
||||||
BOOLEAN AtIrqlPassiveLevel = FALSE;
|
BOOLEAN AtIrqlPassiveLevel = FALSE;
|
||||||
BOOLEAN IsTopLevelIrp = FALSE;
|
BOOLEAN IsTopLevelIrp = FALSE;
|
||||||
PEXT2_IRP_CONTEXT IrpContext = NULL;
|
PEXT2_IRP_CONTEXT IrpContext = NULL;
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
#if EXT2_DEBUG
|
#if EXT2_DEBUG
|
||||||
Ext2DbgPrintCall(DeviceObject, Irp);
|
Ext2DbgPrintCall(DeviceObject, Irp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL);
|
AtIrqlPassiveLevel = (KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||||
|
|
||||||
if (AtIrqlPassiveLevel) {
|
if (AtIrqlPassiveLevel) {
|
||||||
FsRtlEnterFileSystem();
|
FsRtlEnterFileSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IoGetTopLevelIrp()) {
|
if (!IoGetTopLevelIrp()) {
|
||||||
IsTopLevelIrp = TRUE;
|
IsTopLevelIrp = TRUE;
|
||||||
IoSetTopLevelIrp(Irp);
|
IoSetTopLevelIrp(Irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
IrpContext = Ext2AllocateIrpContext(DeviceObject, Irp);
|
IrpContext = Ext2AllocateIrpContext(DeviceObject, Irp);
|
||||||
|
|
||||||
if (!IrpContext) {
|
if (!IrpContext) {
|
||||||
|
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
|
|
||||||
Ext2CompleteRequest(Irp, TRUE, IO_NO_INCREMENT);
|
Ext2CompleteRequest(Irp, TRUE, IO_NO_INCREMENT);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
|
if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
|
||||||
!AtIrqlPassiveLevel) {
|
!AtIrqlPassiveLevel) {
|
||||||
|
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = Ext2DispatchRequest(IrpContext);
|
Status = Ext2DispatchRequest(IrpContext);
|
||||||
}
|
}
|
||||||
} __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) {
|
} __except (Ext2ExceptionFilter(IrpContext, GetExceptionInformation())) {
|
||||||
|
|
||||||
Status = Ext2ExceptionHandler(IrpContext);
|
Status = Ext2ExceptionHandler(IrpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
if (IsTopLevelIrp) {
|
if (IsTopLevelIrp) {
|
||||||
IoSetTopLevelIrp(NULL);
|
IoSetTopLevelIrp(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AtIrqlPassiveLevel) {
|
if (AtIrqlPassiveLevel) {
|
||||||
FsRtlExitFileSystem();
|
FsRtlExitFileSystem();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|||||||
1208
Ext4Fsd/ea.c
1208
Ext4Fsd/ea.c
File diff suppressed because it is too large
Load Diff
546
Ext4Fsd/except.c
546
Ext4Fsd/except.c
@@ -1,273 +1,273 @@
|
|||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYRIGHT.TXT
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: except.c
|
* FILE: except.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://www.ext2fsd.com
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
/* GLOBALS ***************************************************************/
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
extern PEXT2_GLOBAL Ext2Global;
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2ExceptionFilter (
|
Ext2ExceptionFilter (
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
IN PEXCEPTION_POINTERS ExceptionPointer
|
IN PEXCEPTION_POINTERS ExceptionPointer
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = EXCEPTION_EXECUTE_HANDLER;
|
NTSTATUS Status = EXCEPTION_EXECUTE_HANDLER;
|
||||||
NTSTATUS ExceptionCode;
|
NTSTATUS ExceptionCode;
|
||||||
PEXCEPTION_RECORD ExceptRecord;
|
PEXCEPTION_RECORD ExceptRecord;
|
||||||
|
|
||||||
ExceptRecord = ExceptionPointer->ExceptionRecord;
|
ExceptRecord = ExceptionPointer->ExceptionRecord;
|
||||||
ExceptionCode = ExceptRecord->ExceptionCode;
|
ExceptionCode = ExceptRecord->ExceptionCode;
|
||||||
|
|
||||||
DbgPrint("-------------------------------------------------------------\n");
|
DbgPrint("-------------------------------------------------------------\n");
|
||||||
DbgPrint("Exception happends in Ext2Fsd (code %xh):\n", ExceptionCode);
|
DbgPrint("Exception happends in Ext2Fsd (code %xh):\n", ExceptionCode);
|
||||||
DbgPrint(".exr %p;.cxr %p;\n", ExceptionPointer->ExceptionRecord,
|
DbgPrint(".exr %p;.cxr %p;\n", ExceptionPointer->ExceptionRecord,
|
||||||
ExceptionPointer->ContextRecord);
|
ExceptionPointer->ContextRecord);
|
||||||
DbgPrint("-------------------------------------------------------------\n");
|
DbgPrint("-------------------------------------------------------------\n");
|
||||||
|
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check IrpContext is valid or not
|
// Check IrpContext is valid or not
|
||||||
//
|
//
|
||||||
|
|
||||||
if (IrpContext) {
|
if (IrpContext) {
|
||||||
if ((IrpContext->Identifier.Type != EXT2ICX) ||
|
if ((IrpContext->Identifier.Type != EXT2ICX) ||
|
||||||
(IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) {
|
(IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
IrpContext = NULL;
|
IrpContext = NULL;
|
||||||
} else if (IrpContext->DeviceObject) {
|
} else if (IrpContext->DeviceObject) {
|
||||||
PEXT2_VCB Vcb = NULL;
|
PEXT2_VCB Vcb = NULL;
|
||||||
Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension;
|
Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension;
|
||||||
if (NULL == Vcb) {
|
if (NULL == Vcb) {
|
||||||
Status = EXCEPTION_EXECUTE_HANDLER;
|
Status = EXCEPTION_EXECUTE_HANDLER;
|
||||||
} else {
|
} else {
|
||||||
if (Vcb->Identifier.Type == EXT2VCB && !IsMounted(Vcb)) {
|
if (Vcb->Identifier.Type == EXT2VCB && !IsMounted(Vcb)) {
|
||||||
Status = EXCEPTION_EXECUTE_HANDLER;
|
Status = EXCEPTION_EXECUTE_HANDLER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (FsRtlIsNtstatusExpected(ExceptionCode)) {
|
if (FsRtlIsNtstatusExpected(ExceptionCode)) {
|
||||||
return EXCEPTION_EXECUTE_HANDLER;
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
} else {
|
} else {
|
||||||
Ext2BugCheck( EXT2_BUGCHK_EXCEPT, (ULONG_PTR)ExceptRecord,
|
Ext2BugCheck( EXT2_BUGCHK_EXCEPT, (ULONG_PTR)ExceptRecord,
|
||||||
(ULONG_PTR)ExceptionPointer->ContextRecord,
|
(ULONG_PTR)ExceptionPointer->ContextRecord,
|
||||||
(ULONG_PTR)ExceptRecord->ExceptionAddress );
|
(ULONG_PTR)ExceptRecord->ExceptionAddress );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IrpContext) {
|
if (IrpContext) {
|
||||||
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
|
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( Status == EXCEPTION_EXECUTE_HANDLER ||
|
if ( Status == EXCEPTION_EXECUTE_HANDLER ||
|
||||||
FsRtlIsNtstatusExpected(ExceptionCode)) {
|
FsRtlIsNtstatusExpected(ExceptionCode)) {
|
||||||
//
|
//
|
||||||
// If the exception is expected execute our handler
|
// If the exception is expected execute our handler
|
||||||
//
|
//
|
||||||
|
|
||||||
DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Catching exception %xh\n",
|
DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Catching exception %xh\n",
|
||||||
ExceptionCode));
|
ExceptionCode));
|
||||||
|
|
||||||
Status = EXCEPTION_EXECUTE_HANDLER;
|
Status = EXCEPTION_EXECUTE_HANDLER;
|
||||||
|
|
||||||
if (IrpContext) {
|
if (IrpContext) {
|
||||||
IrpContext->ExceptionInProgress = TRUE;
|
IrpContext->ExceptionInProgress = TRUE;
|
||||||
IrpContext->ExceptionCode = ExceptionCode;
|
IrpContext->ExceptionCode = ExceptionCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Continue search for an higher level exception handler
|
// Continue search for an higher level exception handler
|
||||||
//
|
//
|
||||||
|
|
||||||
DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Passing on exception %#x\n",
|
DEBUG(DL_ERR, ( "Ext2ExceptionFilter: Passing on exception %#x\n",
|
||||||
ExceptionCode));
|
ExceptionCode));
|
||||||
|
|
||||||
Status = EXCEPTION_CONTINUE_SEARCH;
|
Status = EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
|
||||||
if (IrpContext) {
|
if (IrpContext) {
|
||||||
Ext2FreeIrpContext(IrpContext);
|
Ext2FreeIrpContext(IrpContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2ExceptionHandler (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2ExceptionHandler (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
if (IrpContext) {
|
if (IrpContext) {
|
||||||
|
|
||||||
if ( (IrpContext->Identifier.Type != EXT2ICX) ||
|
if ( (IrpContext->Identifier.Type != EXT2ICX) ||
|
||||||
(IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) {
|
(IrpContext->Identifier.Size != sizeof(EXT2_IRP_CONTEXT))) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = IrpContext->ExceptionCode;
|
Status = IrpContext->ExceptionCode;
|
||||||
|
|
||||||
if (IrpContext->Irp) {
|
if (IrpContext->Irp) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if this error is a result of user actions
|
// Check if this error is a result of user actions
|
||||||
//
|
//
|
||||||
|
|
||||||
PEXT2_VCB Vcb = NULL;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PIRP Irp = IrpContext->Irp;
|
PIRP Irp = IrpContext->Irp;
|
||||||
PIO_STACK_LOCATION IrpSp;
|
PIO_STACK_LOCATION IrpSp;
|
||||||
|
|
||||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension;
|
Vcb = (PEXT2_VCB) IrpContext->DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
if (NULL == Vcb) {
|
if (NULL == Vcb) {
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
} else if (Vcb->Identifier.Type != EXT2VCB) {
|
} else if (Vcb->Identifier.Type != EXT2VCB) {
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
} else if (!IsMounted(Vcb)) {
|
} else if (!IsMounted(Vcb)) {
|
||||||
if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) {
|
if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) {
|
||||||
Status = STATUS_NO_SUCH_DEVICE;
|
Status = STATUS_NO_SUCH_DEVICE;
|
||||||
} else {
|
} else {
|
||||||
Status = STATUS_VOLUME_DISMOUNTED;
|
Status = STATUS_VOLUME_DISMOUNTED;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* queue it again if our request is at top level */
|
/* queue it again if our request is at top level */
|
||||||
if (IrpContext->IsTopLevel &&
|
if (IrpContext->IsTopLevel &&
|
||||||
((Status == STATUS_CANT_WAIT) ||
|
((Status == STATUS_CANT_WAIT) ||
|
||||||
((Status == STATUS_VERIFY_REQUIRED) &&
|
((Status == STATUS_VERIFY_REQUIRED) &&
|
||||||
(KeGetCurrentIrql() >= APC_LEVEL)))) {
|
(KeGetCurrentIrql() >= APC_LEVEL)))) {
|
||||||
|
|
||||||
Status = Ext2QueueRequest(IrpContext);
|
Status = Ext2QueueRequest(IrpContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Status = Status;
|
Irp->IoStatus.Status = Status;
|
||||||
|
|
||||||
if (IoIsErrorUserInduced(Status)) {
|
if (IoIsErrorUserInduced(Status)) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Now we will generate a pop-up to user
|
// Now we will generate a pop-up to user
|
||||||
//
|
//
|
||||||
|
|
||||||
PDEVICE_OBJECT RealDevice;
|
PDEVICE_OBJECT RealDevice;
|
||||||
PVPB Vpb = NULL;
|
PVPB Vpb = NULL;
|
||||||
PETHREAD Thread;
|
PETHREAD Thread;
|
||||||
|
|
||||||
if (IrpSp->FileObject != NULL) {
|
if (IrpSp->FileObject != NULL) {
|
||||||
Vpb = IrpSp->FileObject->Vpb;
|
Vpb = IrpSp->FileObject->Vpb;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the initial thread
|
// Get the initial thread
|
||||||
//
|
//
|
||||||
|
|
||||||
Thread = Irp->Tail.Overlay.Thread;
|
Thread = Irp->Tail.Overlay.Thread;
|
||||||
RealDevice = IoGetDeviceToVerify( Thread );
|
RealDevice = IoGetDeviceToVerify( Thread );
|
||||||
|
|
||||||
if (RealDevice == NULL) {
|
if (RealDevice == NULL) {
|
||||||
//
|
//
|
||||||
// Get current thread
|
// Get current thread
|
||||||
//
|
//
|
||||||
|
|
||||||
Thread = PsGetCurrentThread();
|
Thread = PsGetCurrentThread();
|
||||||
RealDevice = IoGetDeviceToVerify( Thread );
|
RealDevice = IoGetDeviceToVerify( Thread );
|
||||||
|
|
||||||
ASSERT( RealDevice != NULL );
|
ASSERT( RealDevice != NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = IrpContext->ExceptionCode;
|
Status = IrpContext->ExceptionCode;
|
||||||
|
|
||||||
if (RealDevice != NULL) {
|
if (RealDevice != NULL) {
|
||||||
|
|
||||||
if (IrpContext->ExceptionCode == STATUS_VERIFY_REQUIRED) {
|
if (IrpContext->ExceptionCode == STATUS_VERIFY_REQUIRED) {
|
||||||
|
|
||||||
Status = IoVerifyVolume (RealDevice, FALSE);
|
Status = IoVerifyVolume (RealDevice, FALSE);
|
||||||
|
|
||||||
ExAcquireResourceSharedLite(&Vcb->MainResource, TRUE);
|
ExAcquireResourceSharedLite(&Vcb->MainResource, TRUE);
|
||||||
if (NT_SUCCESS(Status) && (!IsMounted(Vcb) ||
|
if (NT_SUCCESS(Status) && (!IsMounted(Vcb) ||
|
||||||
IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))) {
|
IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))) {
|
||||||
Status = STATUS_WRONG_VOLUME;
|
Status = STATUS_WRONG_VOLUME;
|
||||||
}
|
}
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
|
|
||||||
if (Ext2CheckDismount(IrpContext, Vcb, FALSE)) {
|
if (Ext2CheckDismount(IrpContext, Vcb, FALSE)) {
|
||||||
Ext2CompleteIrpContext( IrpContext, STATUS_VOLUME_DISMOUNTED);
|
Ext2CompleteIrpContext( IrpContext, STATUS_VOLUME_DISMOUNTED);
|
||||||
Status = STATUS_VOLUME_DISMOUNTED;
|
Status = STATUS_VOLUME_DISMOUNTED;
|
||||||
Irp = NULL;
|
Irp = NULL;
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (IrpContext->MajorFunction == IRP_MJ_CREATE) &&
|
if ( (IrpContext->MajorFunction == IRP_MJ_CREATE) &&
|
||||||
(IrpContext->FileObject->RelatedFileObject == NULL) &&
|
(IrpContext->FileObject->RelatedFileObject == NULL) &&
|
||||||
((Status == STATUS_SUCCESS) || (Status == STATUS_WRONG_VOLUME))) {
|
((Status == STATUS_SUCCESS) || (Status == STATUS_WRONG_VOLUME))) {
|
||||||
|
|
||||||
Irp->IoStatus.Information = IO_REMOUNT;
|
Irp->IoStatus.Information = IO_REMOUNT;
|
||||||
|
|
||||||
Ext2CompleteIrpContext( IrpContext, STATUS_REPARSE);
|
Ext2CompleteIrpContext( IrpContext, STATUS_REPARSE);
|
||||||
Status = STATUS_REPARSE;
|
Status = STATUS_REPARSE;
|
||||||
Irp = NULL;
|
Irp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Irp) {
|
if (Irp) {
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
IoSetHardErrorOrVerifyDevice(Irp, RealDevice);
|
IoSetHardErrorOrVerifyDevice(Irp, RealDevice);
|
||||||
ASSERT (STATUS_VERIFY_REQUIRED != Status);
|
ASSERT (STATUS_VERIFY_REQUIRED != Status);
|
||||||
Ext2NormalizeAndRaiseStatus(IrpContext, Status);
|
Ext2NormalizeAndRaiseStatus(IrpContext, Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = Ext2QueueRequest(IrpContext);
|
Status = Ext2QueueRequest(IrpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
goto errorout;
|
goto errorout;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
Status = STATUS_PENDING;
|
Status = STATUS_PENDING;
|
||||||
|
|
||||||
IoMarkIrpPending( Irp );
|
IoMarkIrpPending( Irp );
|
||||||
IoRaiseHardError( Irp, Vpb, RealDevice );
|
IoRaiseHardError( Irp, Vpb, RealDevice );
|
||||||
IoSetDeviceToVerify( Thread, NULL );
|
IoSetDeviceToVerify( Thread, NULL );
|
||||||
goto release_context;
|
goto release_context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ext2CompleteRequest(Irp, FALSE, IO_NO_INCREMENT);
|
Ext2CompleteRequest(Irp, FALSE, IO_NO_INCREMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
release_context:
|
release_context:
|
||||||
|
|
||||||
Ext2FreeIrpContext(IrpContext);
|
Ext2FreeIrpContext(IrpContext);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
errorout:
|
errorout:
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,68 +1,68 @@
|
|||||||
#include <ext2fs.h>
|
#include <ext2fs.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* extents_bread: This function is a wrapper of CcPinRead routine.
|
* extents_bread: This function is a wrapper of CcPinRead routine.
|
||||||
*
|
*
|
||||||
* @sb: the device we need to undergo buffered IO on.
|
* @sb: the device we need to undergo buffered IO on.
|
||||||
* @block: the block we want to read from.
|
* @block: the block we want to read from.
|
||||||
*
|
*
|
||||||
* If the call to this routine succeeds, the pages underlying the buffer header
|
* If the call to this routine succeeds, the pages underlying the buffer header
|
||||||
* will be locked into memory, so that the buffer header returned for use is safe.
|
* will be locked into memory, so that the buffer header returned for use is safe.
|
||||||
*/
|
*/
|
||||||
struct buffer_head *
|
struct buffer_head *
|
||||||
extents_bread(struct super_block *sb, sector_t block)
|
extents_bread(struct super_block *sb, sector_t block)
|
||||||
{
|
{
|
||||||
return sb_getblk(sb, block);
|
return sb_getblk(sb, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* extents_bwrite: This function is a wrapper of CcPreparePinWrite routine.
|
* extents_bwrite: This function is a wrapper of CcPreparePinWrite routine.
|
||||||
*
|
*
|
||||||
* @sb: the device we need to undergo buffered IO on.
|
* @sb: the device we need to undergo buffered IO on.
|
||||||
* @block: the block we want to write to.
|
* @block: the block we want to write to.
|
||||||
*/
|
*/
|
||||||
struct buffer_head *
|
struct buffer_head *
|
||||||
extents_bwrite(struct super_block *sb, sector_t block)
|
extents_bwrite(struct super_block *sb, sector_t block)
|
||||||
{
|
{
|
||||||
return sb_getblk_zero(sb, block);
|
return sb_getblk_zero(sb, block);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* extents_mark_buffer_dirty: Mark the buffer dirtied and so
|
* extents_mark_buffer_dirty: Mark the buffer dirtied and so
|
||||||
* that changes will be written back.
|
* that changes will be written back.
|
||||||
*
|
*
|
||||||
* @bh: The corresponding buffer header that is modified.
|
* @bh: The corresponding buffer header that is modified.
|
||||||
*/
|
*/
|
||||||
void extents_mark_buffer_dirty(struct buffer_head *bh)
|
void extents_mark_buffer_dirty(struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
set_buffer_dirty(bh);
|
set_buffer_dirty(bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* extents_brelse: Release the corresponding buffer header.
|
* extents_brelse: Release the corresponding buffer header.
|
||||||
*
|
*
|
||||||
* @bh: The corresponding buffer header that is going to be freed.
|
* @bh: The corresponding buffer header that is going to be freed.
|
||||||
*
|
*
|
||||||
* The pages underlying the buffer header will be unlocked.
|
* The pages underlying the buffer header will be unlocked.
|
||||||
*/
|
*/
|
||||||
void extents_brelse(struct buffer_head *bh)
|
void extents_brelse(struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* extents_bforget: Release the corresponding buffer header.
|
* extents_bforget: Release the corresponding buffer header.
|
||||||
* NOTE: The page owned by @bh will be marked invalidated.
|
* NOTE: The page owned by @bh will be marked invalidated.
|
||||||
*
|
*
|
||||||
* @bh: The corresponding buffer header that is going to be freed.
|
* @bh: The corresponding buffer header that is going to be freed.
|
||||||
*
|
*
|
||||||
* The pages underlying the buffer header will be unlocked.
|
* The pages underlying the buffer header will be unlocked.
|
||||||
*/
|
*/
|
||||||
void extents_bforget(struct buffer_head *bh)
|
void extents_bforget(struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
clear_buffer_uptodate(bh);
|
clear_buffer_uptodate(bh);
|
||||||
bforget(bh);
|
bforget(bh);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,244 +1,244 @@
|
|||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYRIGHT.TXT
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: extents.c
|
* FILE: extents.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://www.ext2fsd.com
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
/* GLOBALS *****************************************************************/
|
/* GLOBALS *****************************************************************/
|
||||||
|
|
||||||
extern PEXT2_GLOBAL Ext2Global;
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2MapExtent(
|
Ext2MapExtent(
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
IN PEXT2_VCB Vcb,
|
IN PEXT2_VCB Vcb,
|
||||||
IN PEXT2_MCB Mcb,
|
IN PEXT2_MCB Mcb,
|
||||||
IN ULONG Index,
|
IN ULONG Index,
|
||||||
IN BOOLEAN Alloc,
|
IN BOOLEAN Alloc,
|
||||||
OUT PULONG Block,
|
OUT PULONG Block,
|
||||||
OUT PULONG Number
|
OUT PULONG Number
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EXT4_EXTENT_HEADER *eh;
|
EXT4_EXTENT_HEADER *eh;
|
||||||
struct buffer_head bh_got = {0};
|
struct buffer_head bh_got = {0};
|
||||||
int flags, rc;
|
int flags, rc;
|
||||||
ULONG max_blocks = 0;
|
ULONG max_blocks = 0;
|
||||||
|
|
||||||
memset(&bh_got, 0, sizeof(struct buffer_head));
|
memset(&bh_got, 0, sizeof(struct buffer_head));
|
||||||
eh = get_ext4_header(&Mcb->Inode);
|
eh = get_ext4_header(&Mcb->Inode);
|
||||||
|
|
||||||
if (eh->eh_magic != EXT4_EXT_MAGIC) {
|
if (eh->eh_magic != EXT4_EXT_MAGIC) {
|
||||||
if (Alloc) {
|
if (Alloc) {
|
||||||
/* now initialize inode extent root node */
|
/* now initialize inode extent root node */
|
||||||
ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode);
|
ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode);
|
||||||
} else {
|
} else {
|
||||||
/* return empty-mapping when inode extent isn't initialized */
|
/* return empty-mapping when inode extent isn't initialized */
|
||||||
if (Block)
|
if (Block)
|
||||||
*Block = 0;
|
*Block = 0;
|
||||||
if (Number) {
|
if (Number) {
|
||||||
LONGLONG _len = _len = Mcb->Inode.i_size;
|
LONGLONG _len = _len = Mcb->Inode.i_size;
|
||||||
if (Mcb->Fcb)
|
if (Mcb->Fcb)
|
||||||
_len = Mcb->Fcb->Header.AllocationSize.QuadPart;
|
_len = Mcb->Fcb->Header.AllocationSize.QuadPart;
|
||||||
*Number = (ULONG)((_len + BLOCK_SIZE - 1) >> BLOCK_BITS);
|
*Number = (ULONG)((_len + BLOCK_SIZE - 1) >> BLOCK_BITS);
|
||||||
}
|
}
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IrpContext is NULL when called during journal initialization */
|
/* IrpContext is NULL when called during journal initialization */
|
||||||
if (IsMcbDirectory(Mcb) || IrpContext == NULL ||
|
if (IsMcbDirectory(Mcb) || IrpContext == NULL ||
|
||||||
IrpContext->MajorFunction == IRP_MJ_WRITE || !Alloc){
|
IrpContext->MajorFunction == IRP_MJ_WRITE || !Alloc){
|
||||||
flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT;
|
flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT;
|
||||||
max_blocks = EXT_INIT_MAX_LEN;
|
max_blocks = EXT_INIT_MAX_LEN;
|
||||||
} else {
|
} else {
|
||||||
flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
|
flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
|
||||||
max_blocks = EXT_UNWRITTEN_MAX_LEN;
|
max_blocks = EXT_UNWRITTEN_MAX_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Alloc) {
|
if (Alloc) {
|
||||||
if (Number && !*Number) {
|
if (Number && !*Number) {
|
||||||
if (max_blocks > *Number) {
|
if (max_blocks > *Number) {
|
||||||
max_blocks = *Number;
|
max_blocks = *Number;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
max_blocks = 1;
|
max_blocks = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rc = ext4_ext_get_blocks(
|
if ((rc = ext4_ext_get_blocks(
|
||||||
IrpContext,
|
IrpContext,
|
||||||
NULL,
|
NULL,
|
||||||
&Mcb->Inode,
|
&Mcb->Inode,
|
||||||
Index,
|
Index,
|
||||||
max_blocks,
|
max_blocks,
|
||||||
&bh_got,
|
&bh_got,
|
||||||
Alloc,
|
Alloc,
|
||||||
flags)) < 0) {
|
flags)) < 0) {
|
||||||
DEBUG(DL_ERR, ("Block insufficient resources, err: %d\n", rc));
|
DEBUG(DL_ERR, ("Block insufficient resources, err: %d\n", rc));
|
||||||
return Ext2WinntError(rc);
|
return Ext2WinntError(rc);
|
||||||
}
|
}
|
||||||
if (Alloc)
|
if (Alloc)
|
||||||
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
|
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
|
||||||
if (Number)
|
if (Number)
|
||||||
*Number = rc ? rc : 1;
|
*Number = rc ? rc : 1;
|
||||||
if (Block)
|
if (Block)
|
||||||
*Block = (ULONG)bh_got.b_blocknr;
|
*Block = (ULONG)bh_got.b_blocknr;
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2DoExtentExpand(
|
Ext2DoExtentExpand(
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
IN PEXT2_VCB Vcb,
|
IN PEXT2_VCB Vcb,
|
||||||
IN PEXT2_MCB Mcb,
|
IN PEXT2_MCB Mcb,
|
||||||
IN ULONG Index,
|
IN ULONG Index,
|
||||||
IN OUT PULONG Block,
|
IN OUT PULONG Block,
|
||||||
IN OUT PULONG Number
|
IN OUT PULONG Number
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EXT4_EXTENT_HEADER *eh;
|
EXT4_EXTENT_HEADER *eh;
|
||||||
struct buffer_head bh_got;
|
struct buffer_head bh_got;
|
||||||
int rc, flags;
|
int rc, flags;
|
||||||
|
|
||||||
if (IsMcbDirectory(Mcb) || IrpContext->MajorFunction == IRP_MJ_WRITE) {
|
if (IsMcbDirectory(Mcb) || IrpContext->MajorFunction == IRP_MJ_WRITE) {
|
||||||
flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT;
|
flags = EXT4_GET_BLOCKS_IO_CONVERT_EXT;
|
||||||
} else {
|
} else {
|
||||||
flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
|
flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&bh_got, 0, sizeof(struct buffer_head));
|
memset(&bh_got, 0, sizeof(struct buffer_head));
|
||||||
eh = get_ext4_header(&Mcb->Inode);
|
eh = get_ext4_header(&Mcb->Inode);
|
||||||
|
|
||||||
if (eh->eh_magic != EXT4_EXT_MAGIC) {
|
if (eh->eh_magic != EXT4_EXT_MAGIC) {
|
||||||
ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode);
|
ext4_ext_tree_init(IrpContext, NULL, &Mcb->Inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rc = ext4_ext_get_blocks( IrpContext, NULL, &Mcb->Inode, Index,
|
if ((rc = ext4_ext_get_blocks( IrpContext, NULL, &Mcb->Inode, Index,
|
||||||
*Number, &bh_got, 1, flags)) < 0) {
|
*Number, &bh_got, 1, flags)) < 0) {
|
||||||
DEBUG(DL_ERR, ("Expand Block insufficient resources, Number: %u,"
|
DEBUG(DL_ERR, ("Expand Block insufficient resources, Number: %u,"
|
||||||
" err: %d\n", *Number, rc));
|
" err: %d\n", *Number, rc));
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
return Ext2WinntError(rc);
|
return Ext2WinntError(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Number)
|
if (Number)
|
||||||
*Number = rc ? rc : 1;
|
*Number = rc ? rc : 1;
|
||||||
if (Block)
|
if (Block)
|
||||||
*Block = (ULONG)bh_got.b_blocknr;
|
*Block = (ULONG)bh_got.b_blocknr;
|
||||||
|
|
||||||
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
|
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2ExpandExtent(
|
Ext2ExpandExtent(
|
||||||
PEXT2_IRP_CONTEXT IrpContext,
|
PEXT2_IRP_CONTEXT IrpContext,
|
||||||
PEXT2_VCB Vcb,
|
PEXT2_VCB Vcb,
|
||||||
PEXT2_MCB Mcb,
|
PEXT2_MCB Mcb,
|
||||||
ULONG Start,
|
ULONG Start,
|
||||||
ULONG End,
|
ULONG End,
|
||||||
PLARGE_INTEGER Size
|
PLARGE_INTEGER Size
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ULONG Count = 0, Number = 0, Block = 0;
|
ULONG Count = 0, Number = 0, Block = 0;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
if (End <= Start)
|
if (End <= Start)
|
||||||
return Status;
|
return Status;
|
||||||
|
|
||||||
while (End > Start + Count) {
|
while (End > Start + Count) {
|
||||||
|
|
||||||
Number = End - Start - Count;
|
Number = End - Start - Count;
|
||||||
Status = Ext2DoExtentExpand(IrpContext, Vcb, Mcb, Start + Count,
|
Status = Ext2DoExtentExpand(IrpContext, Vcb, Mcb, Start + Count,
|
||||||
&Block, &Number);
|
&Block, &Number);
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (Number == 0) {
|
if (Number == 0) {
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Block && IsZoneInited(Mcb)) {
|
if (Block && IsZoneInited(Mcb)) {
|
||||||
if (!Ext2AddBlockExtent(Vcb, Mcb, Start + Count, Block, Number)) {
|
if (!Ext2AddBlockExtent(Vcb, Mcb, Start + Count, Block, Number)) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
|
ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
|
||||||
Ext2ClearAllExtents(&Mcb->Extents);
|
Ext2ClearAllExtents(&Mcb->Extents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Count += Number;
|
Count += Number;
|
||||||
}
|
}
|
||||||
|
|
||||||
Size->QuadPart = ((LONGLONG)(Start + Count)) << BLOCK_BITS;
|
Size->QuadPart = ((LONGLONG)(Start + Count)) << BLOCK_BITS;
|
||||||
|
|
||||||
/* save inode whatever it succeeds to expand or not */
|
/* save inode whatever it succeeds to expand or not */
|
||||||
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
|
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2TruncateExtent(
|
Ext2TruncateExtent(
|
||||||
PEXT2_IRP_CONTEXT IrpContext,
|
PEXT2_IRP_CONTEXT IrpContext,
|
||||||
PEXT2_VCB Vcb,
|
PEXT2_VCB Vcb,
|
||||||
PEXT2_MCB Mcb,
|
PEXT2_MCB Mcb,
|
||||||
PLARGE_INTEGER Size
|
PLARGE_INTEGER Size
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
ULONG Extra = 0;
|
ULONG Extra = 0;
|
||||||
ULONG Wanted = 0;
|
ULONG Wanted = 0;
|
||||||
ULONG End;
|
ULONG End;
|
||||||
ULONG Removed;
|
ULONG Removed;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* translate file size to block */
|
/* translate file size to block */
|
||||||
End = Vcb->max_data_blocks;
|
End = Vcb->max_data_blocks;
|
||||||
Wanted = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
|
Wanted = (ULONG)((Size->QuadPart + BLOCK_SIZE - 1) >> BLOCK_BITS);
|
||||||
|
|
||||||
/* calculate blocks to be freed */
|
/* calculate blocks to be freed */
|
||||||
Extra = End - Wanted;
|
Extra = End - Wanted;
|
||||||
|
|
||||||
err = ext4_ext_truncate(IrpContext, &Mcb->Inode, Wanted);
|
err = ext4_ext_truncate(IrpContext, &Mcb->Inode, Wanted);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
if (!Ext2RemoveBlockExtent(Vcb, Mcb, Wanted, Extra)) {
|
if (!Ext2RemoveBlockExtent(Vcb, Mcb, Wanted, Extra)) {
|
||||||
ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
|
ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
|
||||||
Ext2ClearAllExtents(&Mcb->Extents);
|
Ext2ClearAllExtents(&Mcb->Extents);
|
||||||
}
|
}
|
||||||
Extra = 0;
|
Extra = 0;
|
||||||
} else {
|
} else {
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS);
|
Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart))
|
if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart))
|
||||||
Mcb->Inode.i_size = (loff_t)(Size->QuadPart);
|
Mcb->Inode.i_size = (loff_t)(Size->QuadPart);
|
||||||
|
|
||||||
/* Save modifications on i_blocks field and i_size field of the inode. */
|
/* Save modifications on i_blocks field and i_size field of the inode. */
|
||||||
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
|
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|||||||
2250
Ext4Fsd/fastio.c
2250
Ext4Fsd/fastio.c
File diff suppressed because it is too large
Load Diff
4178
Ext4Fsd/fileinfo.c
4178
Ext4Fsd/fileinfo.c
File diff suppressed because it is too large
Load Diff
552
Ext4Fsd/flush.c
552
Ext4Fsd/flush.c
@@ -1,277 +1,277 @@
|
|||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYRIGHT.TXT
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: flush.c
|
* FILE: flush.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://www.ext2fsd.com
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
/* GLOBALS ***************************************************************/
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
extern PEXT2_GLOBAL Ext2Global;
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2FlushCompletionRoutine (
|
Ext2FlushCompletionRoutine (
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp,
|
IN PIRP Irp,
|
||||||
IN PVOID Context )
|
IN PVOID Context )
|
||||||
|
|
||||||
{
|
{
|
||||||
if (Irp->PendingReturned)
|
if (Irp->PendingReturned)
|
||||||
IoMarkIrpPending( Irp );
|
IoMarkIrpPending( Irp );
|
||||||
|
|
||||||
|
|
||||||
if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)
|
if (Irp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST)
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2FlushVolume (
|
Ext2FlushVolume (
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
IN PEXT2_VCB Vcb,
|
IN PEXT2_VCB Vcb,
|
||||||
IN BOOLEAN bShutDown
|
IN BOOLEAN bShutDown
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
|
DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
|
||||||
|
|
||||||
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
|
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
|
||||||
ExReleaseResourceLite(&Vcb->PagingIoResource);
|
ExReleaseResourceLite(&Vcb->PagingIoResource);
|
||||||
|
|
||||||
return Ext2FlushVcb(Vcb);
|
return Ext2FlushVcb(Vcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2FlushFile (
|
Ext2FlushFile (
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
IN PEXT2_FCB Fcb,
|
IN PEXT2_FCB Fcb,
|
||||||
IN PEXT2_CCB Ccb
|
IN PEXT2_CCB Ccb
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
IO_STATUS_BLOCK IoStatus = {0};
|
IO_STATUS_BLOCK IoStatus = {0};
|
||||||
|
|
||||||
ASSERT(Fcb != NULL);
|
ASSERT(Fcb != NULL);
|
||||||
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
||||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
/* do nothing if target fie was deleted */
|
/* do nothing if target fie was deleted */
|
||||||
if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
|
if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
|
||||||
IoStatus.Status = STATUS_FILE_DELETED;
|
IoStatus.Status = STATUS_FILE_DELETED;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update timestamp and achieve attribute */
|
/* update timestamp and achieve attribute */
|
||||||
if (Ccb != NULL) {
|
if (Ccb != NULL) {
|
||||||
|
|
||||||
if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
|
if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
|
||||||
|
|
||||||
LARGE_INTEGER SysTime;
|
LARGE_INTEGER SysTime;
|
||||||
KeQuerySystemTime(&SysTime);
|
KeQuerySystemTime(&SysTime);
|
||||||
|
|
||||||
Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
|
Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
|
||||||
Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime);
|
Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime);
|
||||||
Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode);
|
Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsDirectory(Fcb)) {
|
if (IsDirectory(Fcb)) {
|
||||||
IoStatus.Status = STATUS_SUCCESS;
|
IoStatus.Status = STATUS_SUCCESS;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n",
|
DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n",
|
||||||
Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer));
|
Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer));
|
||||||
|
|
||||||
CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
|
CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
|
||||||
ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
|
ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
/* do cleanup here */
|
/* do cleanup here */
|
||||||
}
|
}
|
||||||
|
|
||||||
return IoStatus.Status;
|
return IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2FlushFiles(
|
Ext2FlushFiles(
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
IN PEXT2_VCB Vcb,
|
IN PEXT2_VCB Vcb,
|
||||||
IN BOOLEAN bShutDown
|
IN BOOLEAN bShutDown
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
IO_STATUS_BLOCK IoStatus;
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb;
|
||||||
PLIST_ENTRY ListEntry;
|
PLIST_ENTRY ListEntry;
|
||||||
|
|
||||||
if (IsVcbReadOnly(Vcb)) {
|
if (IsVcbReadOnly(Vcb)) {
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
IoStatus.Status = STATUS_SUCCESS;
|
IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Flushing Files ...\n"));
|
DEBUG(DL_INF, ( "Flushing Files ...\n"));
|
||||||
|
|
||||||
// Flush all Fcbs in Vcb list queue.
|
// Flush all Fcbs in Vcb list queue.
|
||||||
for (ListEntry = Vcb->FcbList.Flink;
|
for (ListEntry = Vcb->FcbList.Flink;
|
||||||
ListEntry != &Vcb->FcbList;
|
ListEntry != &Vcb->FcbList;
|
||||||
ListEntry = ListEntry->Flink ) {
|
ListEntry = ListEntry->Flink ) {
|
||||||
|
|
||||||
Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next);
|
Fcb = CONTAINING_RECORD(ListEntry, EXT2_FCB, Next);
|
||||||
ExAcquireResourceExclusiveLite(
|
ExAcquireResourceExclusiveLite(
|
||||||
&Fcb->MainResource, TRUE);
|
&Fcb->MainResource, TRUE);
|
||||||
Ext2FlushFile(IrpContext, Fcb, NULL);
|
Ext2FlushFile(IrpContext, Fcb, NULL);
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
ExReleaseResourceLite(&Fcb->MainResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
return IoStatus.Status;
|
return IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PIRP Irp = NULL;
|
PIRP Irp = NULL;
|
||||||
PIO_STACK_LOCATION IrpSp = NULL;
|
PIO_STACK_LOCATION IrpSp = NULL;
|
||||||
|
|
||||||
PEXT2_VCB Vcb = NULL;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PEXT2_FCB Fcb = NULL;
|
PEXT2_FCB Fcb = NULL;
|
||||||
PEXT2_FCBVCB FcbOrVcb = NULL;
|
PEXT2_FCBVCB FcbOrVcb = NULL;
|
||||||
PEXT2_CCB Ccb = NULL;
|
PEXT2_CCB Ccb = NULL;
|
||||||
PFILE_OBJECT FileObject = NULL;
|
PFILE_OBJECT FileObject = NULL;
|
||||||
|
|
||||||
PDEVICE_OBJECT DeviceObject = NULL;
|
PDEVICE_OBJECT DeviceObject = NULL;
|
||||||
|
|
||||||
BOOLEAN MainResourceAcquired = FALSE;
|
BOOLEAN MainResourceAcquired = FALSE;
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
ASSERT(IrpContext);
|
ASSERT(IrpContext);
|
||||||
|
|
||||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
DeviceObject = IrpContext->DeviceObject;
|
DeviceObject = IrpContext->DeviceObject;
|
||||||
|
|
||||||
//
|
//
|
||||||
// This request is not allowed on the main device object
|
// This request is not allowed on the main device object
|
||||||
//
|
//
|
||||||
if (IsExt2FsDevice(DeviceObject)) {
|
if (IsExt2FsDevice(DeviceObject)) {
|
||||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
|
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
|
||||||
ASSERT(Vcb != NULL);
|
ASSERT(Vcb != NULL);
|
||||||
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
||||||
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
|
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
|
||||||
|
|
||||||
ASSERT(IsMounted(Vcb));
|
ASSERT(IsMounted(Vcb));
|
||||||
if (IsVcbReadOnly(Vcb)) {
|
if (IsVcbReadOnly(Vcb)) {
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp = IrpContext->Irp;
|
Irp = IrpContext->Irp;
|
||||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
FileObject = IrpContext->FileObject;
|
FileObject = IrpContext->FileObject;
|
||||||
FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
|
FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
|
||||||
ASSERT(FcbOrVcb != NULL);
|
ASSERT(FcbOrVcb != NULL);
|
||||||
|
|
||||||
Ccb = (PEXT2_CCB) FileObject->FsContext2;
|
Ccb = (PEXT2_CCB) FileObject->FsContext2;
|
||||||
if (Ccb == NULL) {
|
if (Ccb == NULL) {
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
MainResourceAcquired =
|
MainResourceAcquired =
|
||||||
ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, TRUE);
|
ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, TRUE);
|
||||||
ASSERT(MainResourceAcquired);
|
ASSERT(MainResourceAcquired);
|
||||||
DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n",
|
DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n",
|
||||||
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
|
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
|
||||||
|
|
||||||
if (FcbOrVcb->Identifier.Type == EXT2VCB) {
|
if (FcbOrVcb->Identifier.Type == EXT2VCB) {
|
||||||
|
|
||||||
Ext2VerifyVcb(IrpContext, Vcb);
|
Ext2VerifyVcb(IrpContext, Vcb);
|
||||||
Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
|
Status = Ext2FlushFiles(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
|
||||||
if (NT_SUCCESS(Status)) {
|
if (NT_SUCCESS(Status)) {
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
|
Status = Ext2FlushVolume(IrpContext, (PEXT2_VCB)(FcbOrVcb), FALSE);
|
||||||
|
|
||||||
if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) {
|
if (NT_SUCCESS(Status) && IsFlagOn(Vcb->Volume->Flags, FO_FILE_MODIFIED)) {
|
||||||
ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
|
ClearFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (FcbOrVcb->Identifier.Type == EXT2FCB) {
|
} else if (FcbOrVcb->Identifier.Type == EXT2FCB) {
|
||||||
|
|
||||||
Fcb = (PEXT2_FCB)(FcbOrVcb);
|
Fcb = (PEXT2_FCB)(FcbOrVcb);
|
||||||
|
|
||||||
Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
|
Status = Ext2FlushFile(IrpContext, Fcb, Ccb);
|
||||||
if (NT_SUCCESS(Status)) {
|
if (NT_SUCCESS(Status)) {
|
||||||
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
|
if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
|
||||||
Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
|
Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE;
|
||||||
ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
|
ClearFlag(FileObject->Flags, FO_FILE_MODIFIED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n",
|
DEBUG(DL_INF, ("Ext2Flush-post: total mcb records=%u\n",
|
||||||
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
|
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
|
||||||
|
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
if (MainResourceAcquired) {
|
if (MainResourceAcquired) {
|
||||||
ExReleaseResourceLite(&FcbOrVcb->MainResource);
|
ExReleaseResourceLite(&FcbOrVcb->MainResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IrpContext->ExceptionInProgress) {
|
if (!IrpContext->ExceptionInProgress) {
|
||||||
|
|
||||||
if (Vcb && Irp && IrpSp && !IsVcbReadOnly(Vcb)) {
|
if (Vcb && Irp && IrpSp && !IsVcbReadOnly(Vcb)) {
|
||||||
|
|
||||||
// Call the disk driver to flush the physial media.
|
// Call the disk driver to flush the physial media.
|
||||||
NTSTATUS DriverStatus;
|
NTSTATUS DriverStatus;
|
||||||
PIO_STACK_LOCATION NextIrpSp;
|
PIO_STACK_LOCATION NextIrpSp;
|
||||||
|
|
||||||
NextIrpSp = IoGetNextIrpStackLocation(Irp);
|
NextIrpSp = IoGetNextIrpStackLocation(Irp);
|
||||||
|
|
||||||
*NextIrpSp = *IrpSp;
|
*NextIrpSp = *IrpSp;
|
||||||
|
|
||||||
IoSetCompletionRoutine( Irp,
|
IoSetCompletionRoutine( Irp,
|
||||||
Ext2FlushCompletionRoutine,
|
Ext2FlushCompletionRoutine,
|
||||||
NULL,
|
NULL,
|
||||||
TRUE,
|
TRUE,
|
||||||
TRUE,
|
TRUE,
|
||||||
TRUE );
|
TRUE );
|
||||||
|
|
||||||
DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);
|
DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);
|
||||||
|
|
||||||
Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
|
Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
|
||||||
Status : DriverStatus;
|
Status : DriverStatus;
|
||||||
|
|
||||||
IrpContext->Irp = Irp = NULL;
|
IrpContext->Irp = Irp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ext2CompleteIrpContext(IrpContext, Status);
|
Ext2CompleteIrpContext(IrpContext, Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
@@ -1,261 +1,261 @@
|
|||||||
#ifndef _EXT2_COMMON_INCLUDE_
|
#ifndef _EXT2_COMMON_INCLUDE_
|
||||||
#define _EXT2_COMMON_INCLUDE_
|
#define _EXT2_COMMON_INCLUDE_
|
||||||
|
|
||||||
/* global ioctl */
|
/* global ioctl */
|
||||||
#define IOCTL_APP_VOLUME_PROPERTY \
|
#define IOCTL_APP_VOLUME_PROPERTY \
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 2000, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_UNKNOWN, 2000, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
#define IOCTL_APP_QUERY_PERFSTAT \
|
#define IOCTL_APP_QUERY_PERFSTAT \
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 2001, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_UNKNOWN, 2001, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
#define IOCTL_APP_MOUNT_POINT \
|
#define IOCTL_APP_MOUNT_POINT \
|
||||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 2002, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
CTL_CODE(FILE_DEVICE_UNKNOWN, 2002, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
|
|
||||||
/* performance / memory allocaiton statistics */
|
/* performance / memory allocaiton statistics */
|
||||||
#define PS_IRP_CONTEXT 0x00
|
#define PS_IRP_CONTEXT 0x00
|
||||||
#define PS_VCB 0x01
|
#define PS_VCB 0x01
|
||||||
#define PS_FCB 0x02
|
#define PS_FCB 0x02
|
||||||
#define PS_CCB 0x03
|
#define PS_CCB 0x03
|
||||||
#define PS_MCB 0x04
|
#define PS_MCB 0x04
|
||||||
#define PS_EXTENT 0x05
|
#define PS_EXTENT 0x05
|
||||||
#define PS_RW_CONTEXT 0x06
|
#define PS_RW_CONTEXT 0x06
|
||||||
#define PS_VPB 0x07
|
#define PS_VPB 0x07
|
||||||
#define PS_FILE_NAME 0x08
|
#define PS_FILE_NAME 0x08
|
||||||
#define PS_MCB_NAME 0x09
|
#define PS_MCB_NAME 0x09
|
||||||
#define PS_INODE_NAME 0x0A
|
#define PS_INODE_NAME 0x0A
|
||||||
#define PS_DIR_ENTRY 0x0B
|
#define PS_DIR_ENTRY 0x0B
|
||||||
#define PS_DIR_PATTERN 0x0C
|
#define PS_DIR_PATTERN 0x0C
|
||||||
#define PS_DISK_EVENT 0x0D
|
#define PS_DISK_EVENT 0x0D
|
||||||
#define PS_DISK_BUFFER 0x0E
|
#define PS_DISK_BUFFER 0x0E
|
||||||
#define PS_BLOCK_DATA 0x0F
|
#define PS_BLOCK_DATA 0x0F
|
||||||
|
|
||||||
#define PS_EXT2_INODE 0x10
|
#define PS_EXT2_INODE 0x10
|
||||||
#define PS_DENTRY 0x11
|
#define PS_DENTRY 0x11
|
||||||
#define PS_BUFF_HEAD 0x12
|
#define PS_BUFF_HEAD 0x12
|
||||||
|
|
||||||
#define PS_MAX_TYPE_V1 (0x10)
|
#define PS_MAX_TYPE_V1 (0x10)
|
||||||
#define PS_MAX_TYPE_V2 (0x30)
|
#define PS_MAX_TYPE_V2 (0x30)
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
|
|
||||||
ULONG Slot[PS_MAX_TYPE_V1];
|
ULONG Slot[PS_MAX_TYPE_V1];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
ULONG IrpContext;
|
ULONG IrpContext;
|
||||||
ULONG Vcb;
|
ULONG Vcb;
|
||||||
ULONG Fcb;
|
ULONG Fcb;
|
||||||
ULONG Ccb;
|
ULONG Ccb;
|
||||||
ULONG Mcb;
|
ULONG Mcb;
|
||||||
ULONG Extent;
|
ULONG Extent;
|
||||||
ULONG RwContext; /* rw context */
|
ULONG RwContext; /* rw context */
|
||||||
ULONG Vpb;
|
ULONG Vpb;
|
||||||
ULONG FileName;
|
ULONG FileName;
|
||||||
ULONG McbName;
|
ULONG McbName;
|
||||||
ULONG InodeName;
|
ULONG InodeName;
|
||||||
ULONG DirEntry; /* pDir */
|
ULONG DirEntry; /* pDir */
|
||||||
ULONG DirPattern; /* Ccb-> in Ext2QeuryDir */
|
ULONG DirPattern; /* Ccb-> in Ext2QeuryDir */
|
||||||
ULONG ReadDiskEvent;
|
ULONG ReadDiskEvent;
|
||||||
ULONG ReadDiskBuffer;
|
ULONG ReadDiskBuffer;
|
||||||
ULONG BlockData; /* Ext2Expand&TruncateFile*/
|
ULONG BlockData; /* Ext2Expand&TruncateFile*/
|
||||||
};
|
};
|
||||||
|
|
||||||
} EXT2_STAT_ARRAY_V1;
|
} EXT2_STAT_ARRAY_V1;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
|
|
||||||
ULONG Slot[PS_MAX_TYPE_V2];
|
ULONG Slot[PS_MAX_TYPE_V2];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
ULONG IrpContext;
|
ULONG IrpContext;
|
||||||
ULONG Vcb;
|
ULONG Vcb;
|
||||||
ULONG Fcb;
|
ULONG Fcb;
|
||||||
ULONG Ccb;
|
ULONG Ccb;
|
||||||
ULONG Mcb;
|
ULONG Mcb;
|
||||||
ULONG Extent;
|
ULONG Extent;
|
||||||
ULONG RwContext; /* rw context */
|
ULONG RwContext; /* rw context */
|
||||||
ULONG Vpb;
|
ULONG Vpb;
|
||||||
ULONG FileName;
|
ULONG FileName;
|
||||||
ULONG McbName;
|
ULONG McbName;
|
||||||
ULONG InodeName;
|
ULONG InodeName;
|
||||||
ULONG DirEntry; /* pDir */
|
ULONG DirEntry; /* pDir */
|
||||||
ULONG DirPattern; /* Ccb-> in Ext2QeuryDir */
|
ULONG DirPattern; /* Ccb-> in Ext2QeuryDir */
|
||||||
ULONG ReadDiskEvent;
|
ULONG ReadDiskEvent;
|
||||||
ULONG ReadDiskBuffer;
|
ULONG ReadDiskBuffer;
|
||||||
ULONG BlockData; /* Ext2Expand&TruncateFile*/
|
ULONG BlockData; /* Ext2Expand&TruncateFile*/
|
||||||
ULONG Inodes; /* inodes */
|
ULONG Inodes; /* inodes */
|
||||||
ULONG NameEntries; /* name dentry */
|
ULONG NameEntries; /* name dentry */
|
||||||
ULONG BufferHead; /* Buffer Header allocations */
|
ULONG BufferHead; /* Buffer Header allocations */
|
||||||
};
|
};
|
||||||
|
|
||||||
} EXT2_STAT_ARRAY_V2;
|
} EXT2_STAT_ARRAY_V2;
|
||||||
|
|
||||||
typedef struct _EXT2_PERF_STATISTICS_V1 {
|
typedef struct _EXT2_PERF_STATISTICS_V1 {
|
||||||
|
|
||||||
/* totoal number of processed/being processed requests */
|
/* totoal number of processed/being processed requests */
|
||||||
struct {
|
struct {
|
||||||
ULONG Processed;
|
ULONG Processed;
|
||||||
ULONG Current;
|
ULONG Current;
|
||||||
} Irps [IRP_MJ_MAXIMUM_FUNCTION + 1];
|
} Irps [IRP_MJ_MAXIMUM_FUNCTION + 1];
|
||||||
|
|
||||||
/* structure size */
|
/* structure size */
|
||||||
EXT2_STAT_ARRAY_V1 Unit;
|
EXT2_STAT_ARRAY_V1 Unit;
|
||||||
|
|
||||||
/* current memory allocation statistics */
|
/* current memory allocation statistics */
|
||||||
EXT2_STAT_ARRAY_V1 Current;
|
EXT2_STAT_ARRAY_V1 Current;
|
||||||
|
|
||||||
/* memory allocated in bytes */
|
/* memory allocated in bytes */
|
||||||
EXT2_STAT_ARRAY_V1 Size;
|
EXT2_STAT_ARRAY_V1 Size;
|
||||||
|
|
||||||
/* totoal memory allocation statistics */
|
/* totoal memory allocation statistics */
|
||||||
EXT2_STAT_ARRAY_V1 Total;
|
EXT2_STAT_ARRAY_V1 Total;
|
||||||
|
|
||||||
} EXT2_PERF_STATISTICS_V1, *PEXT2_PERF_STATISTICS_V1;
|
} EXT2_PERF_STATISTICS_V1, *PEXT2_PERF_STATISTICS_V1;
|
||||||
|
|
||||||
#define EXT2_PERF_STAT_MAGIC '2SPE'
|
#define EXT2_PERF_STAT_MAGIC '2SPE'
|
||||||
#define EXT2_PERF_STAT_VER2 2
|
#define EXT2_PERF_STAT_VER2 2
|
||||||
|
|
||||||
typedef struct _EXT2_PERF_STATISTICS_V2 {
|
typedef struct _EXT2_PERF_STATISTICS_V2 {
|
||||||
|
|
||||||
ULONG Magic; /* EPS2 */
|
ULONG Magic; /* EPS2 */
|
||||||
USHORT Version; /* 02 */
|
USHORT Version; /* 02 */
|
||||||
USHORT Length; /* sizeof(EXT2_PERF_STATISTICS_V2) */
|
USHORT Length; /* sizeof(EXT2_PERF_STATISTICS_V2) */
|
||||||
|
|
||||||
/* totoal number of processed/being processed requests */
|
/* totoal number of processed/being processed requests */
|
||||||
struct {
|
struct {
|
||||||
ULONG Processed;
|
ULONG Processed;
|
||||||
ULONG Current;
|
ULONG Current;
|
||||||
} Irps [IRP_MJ_MAXIMUM_FUNCTION + 1];
|
} Irps [IRP_MJ_MAXIMUM_FUNCTION + 1];
|
||||||
|
|
||||||
/* structure size */
|
/* structure size */
|
||||||
EXT2_STAT_ARRAY_V2 Unit;
|
EXT2_STAT_ARRAY_V2 Unit;
|
||||||
|
|
||||||
/* current memory allocation statistics */
|
/* current memory allocation statistics */
|
||||||
EXT2_STAT_ARRAY_V2 Current;
|
EXT2_STAT_ARRAY_V2 Current;
|
||||||
|
|
||||||
/* memory allocated in bytes */
|
/* memory allocated in bytes */
|
||||||
EXT2_STAT_ARRAY_V2 Size;
|
EXT2_STAT_ARRAY_V2 Size;
|
||||||
|
|
||||||
/* totoal memory allocation statistics */
|
/* totoal memory allocation statistics */
|
||||||
EXT2_STAT_ARRAY_V2 Total;
|
EXT2_STAT_ARRAY_V2 Total;
|
||||||
|
|
||||||
} EXT2_PERF_STATISTICS_V2, *PEXT2_PERF_STATISTICS_V2;
|
} EXT2_PERF_STATISTICS_V2, *PEXT2_PERF_STATISTICS_V2;
|
||||||
|
|
||||||
/* volume property ... */
|
/* volume property ... */
|
||||||
|
|
||||||
#define EXT2_VOLUME_PROPERTY_MAGIC 'EVPM'
|
#define EXT2_VOLUME_PROPERTY_MAGIC 'EVPM'
|
||||||
|
|
||||||
#define EXT2_FLAG_VP_SET_GLOBAL 0x00000001
|
#define EXT2_FLAG_VP_SET_GLOBAL 0x00000001
|
||||||
|
|
||||||
#define APP_CMD_QUERY_VERSION 0x00000000 /* with global flag set */
|
#define APP_CMD_QUERY_VERSION 0x00000000 /* with global flag set */
|
||||||
#define APP_CMD_QUERY_CODEPAGES 0x00000001
|
#define APP_CMD_QUERY_CODEPAGES 0x00000001
|
||||||
#define APP_CMD_QUERY_PROPERTY 0x00000002
|
#define APP_CMD_QUERY_PROPERTY 0x00000002
|
||||||
#define APP_CMD_SET_PROPERTY 0x00000003
|
#define APP_CMD_SET_PROPERTY 0x00000003
|
||||||
#define APP_CMD_QUERY_PROPERTY2 0x00000004
|
#define APP_CMD_QUERY_PROPERTY2 0x00000004
|
||||||
#define APP_CMD_SET_PROPERTY2 0x00000005
|
#define APP_CMD_SET_PROPERTY2 0x00000005
|
||||||
#define APP_CMD_QUERY_PROPERTY3 0x00000006
|
#define APP_CMD_QUERY_PROPERTY3 0x00000006
|
||||||
#define APP_CMD_SET_PROPERTY3 0x00000007
|
#define APP_CMD_SET_PROPERTY3 0x00000007
|
||||||
|
|
||||||
#define CODEPAGE_MAXLEN 0x20
|
#define CODEPAGE_MAXLEN 0x20
|
||||||
#define HIDINGPAT_LEN 0x20
|
#define HIDINGPAT_LEN 0x20
|
||||||
|
|
||||||
typedef struct _EXT2_VOLUME_PROPERTY {
|
typedef struct _EXT2_VOLUME_PROPERTY {
|
||||||
ULONG Magic;
|
ULONG Magic;
|
||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
ULONG Command;
|
ULONG Command;
|
||||||
BOOLEAN bReadonly;
|
BOOLEAN bReadonly;
|
||||||
BOOLEAN bExt3Writable;
|
BOOLEAN bExt3Writable;
|
||||||
BOOLEAN bExt2;
|
BOOLEAN bExt2;
|
||||||
BOOLEAN bExt3;
|
BOOLEAN bExt3;
|
||||||
CHAR Codepage[CODEPAGE_MAXLEN];
|
CHAR Codepage[CODEPAGE_MAXLEN];
|
||||||
} EXT2_VOLUME_PROPERTY, *PEXT2_VOLUME_PROPERTY;
|
} EXT2_VOLUME_PROPERTY, *PEXT2_VOLUME_PROPERTY;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
typedef struct _EXT2_VOLUME_PROPERTY2:EXT2_VOLUME_PROPERTY {
|
typedef struct _EXT2_VOLUME_PROPERTY2:EXT2_VOLUME_PROPERTY {
|
||||||
#else // __cplusplus
|
#else // __cplusplus
|
||||||
typedef struct _EXT2_VOLUME_PROPERTY2 {
|
typedef struct _EXT2_VOLUME_PROPERTY2 {
|
||||||
EXT2_VOLUME_PROPERTY ;
|
EXT2_VOLUME_PROPERTY ;
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
/* new volume properties added after version 0.35 */
|
/* new volume properties added after version 0.35 */
|
||||||
|
|
||||||
/* volume uuid */
|
/* volume uuid */
|
||||||
__u8 UUID[16];
|
__u8 UUID[16];
|
||||||
|
|
||||||
/* mount point: driver letter only */
|
/* mount point: driver letter only */
|
||||||
UCHAR DrvLetter;
|
UCHAR DrvLetter;
|
||||||
|
|
||||||
/* checking bitmap */
|
/* checking bitmap */
|
||||||
BOOLEAN bCheckBitmap;
|
BOOLEAN bCheckBitmap;
|
||||||
|
|
||||||
/* global hiding patterns */
|
/* global hiding patterns */
|
||||||
BOOLEAN bHidingPrefix;
|
BOOLEAN bHidingPrefix;
|
||||||
BOOLEAN bHidingSuffix;
|
BOOLEAN bHidingSuffix;
|
||||||
CHAR sHidingPrefix[HIDINGPAT_LEN];
|
CHAR sHidingPrefix[HIDINGPAT_LEN];
|
||||||
CHAR sHidingSuffix[HIDINGPAT_LEN];
|
CHAR sHidingSuffix[HIDINGPAT_LEN];
|
||||||
|
|
||||||
} EXT2_VOLUME_PROPERTY2, *PEXT2_VOLUME_PROPERTY2;
|
} EXT2_VOLUME_PROPERTY2, *PEXT2_VOLUME_PROPERTY2;
|
||||||
|
|
||||||
#define EXT2_VPROP3_AUTOMOUNT (1ui64 << 0)
|
#define EXT2_VPROP3_AUTOMOUNT (1ui64 << 0)
|
||||||
#define EXT2_VPROP3_USERIDS (1ui64 << 1)
|
#define EXT2_VPROP3_USERIDS (1ui64 << 1)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
typedef struct _EXT2_VOLUME_PROPERTY3:EXT2_VOLUME_PROPERTY2 {
|
typedef struct _EXT2_VOLUME_PROPERTY3:EXT2_VOLUME_PROPERTY2 {
|
||||||
#else // __cplusplus
|
#else // __cplusplus
|
||||||
typedef struct _EXT2_VOLUME_PROPERTY3 {
|
typedef struct _EXT2_VOLUME_PROPERTY3 {
|
||||||
EXT2_VOLUME_PROPERTY2 ;
|
EXT2_VOLUME_PROPERTY2 ;
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
unsigned __int64 Flags2;
|
unsigned __int64 Flags2;
|
||||||
ULONG AutoMount:1;
|
ULONG AutoMount:1;
|
||||||
ULONG EIDS:1;
|
ULONG EIDS:1;
|
||||||
ULONG Reserved1:30;
|
ULONG Reserved1:30;
|
||||||
USHORT uid;
|
USHORT uid;
|
||||||
USHORT gid;
|
USHORT gid;
|
||||||
USHORT euid;
|
USHORT euid;
|
||||||
USHORT egid;
|
USHORT egid;
|
||||||
ULONG Reserved2[29];
|
ULONG Reserved2[29];
|
||||||
} EXT2_VOLUME_PROPERTY3, *PEXT2_VOLUME_PROPERTY3;
|
} EXT2_VOLUME_PROPERTY3, *PEXT2_VOLUME_PROPERTY3;
|
||||||
|
|
||||||
/* Ext2Fsd driver version and built time */
|
/* Ext2Fsd driver version and built time */
|
||||||
typedef struct _EXT2_VOLUME_PROPERTY_VERSION {
|
typedef struct _EXT2_VOLUME_PROPERTY_VERSION {
|
||||||
ULONG Magic;
|
ULONG Magic;
|
||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
ULONG Command;
|
ULONG Command;
|
||||||
CHAR Version[0x1C];
|
CHAR Version[0x1C];
|
||||||
CHAR Time[0x20];
|
CHAR Time[0x20];
|
||||||
CHAR Date[0x20];
|
CHAR Date[0x20];
|
||||||
} EXT2_VOLUME_PROPERTY_VERSION, *PEXT2_VOLUME_PROPERTY_VERSION;
|
} EXT2_VOLUME_PROPERTY_VERSION, *PEXT2_VOLUME_PROPERTY_VERSION;
|
||||||
|
|
||||||
/* performance statistics */
|
/* performance statistics */
|
||||||
#define EXT2_QUERY_PERFSTAT_MAGIC 'EVPM'
|
#define EXT2_QUERY_PERFSTAT_MAGIC 'EVPM'
|
||||||
#define EXT2_QUERY_PERFSTAT_VER2 0x8000000
|
#define EXT2_QUERY_PERFSTAT_VER2 0x8000000
|
||||||
|
|
||||||
typedef struct _EXT2_QUERY_PERFSTAT {
|
typedef struct _EXT2_QUERY_PERFSTAT {
|
||||||
ULONG Magic;
|
ULONG Magic;
|
||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
ULONG Command;
|
ULONG Command;
|
||||||
union {
|
union {
|
||||||
EXT2_PERF_STATISTICS_V1 PerfStatV1;
|
EXT2_PERF_STATISTICS_V1 PerfStatV1;
|
||||||
EXT2_PERF_STATISTICS_V2 PerfStatV2;
|
EXT2_PERF_STATISTICS_V2 PerfStatV2;
|
||||||
};
|
};
|
||||||
} EXT2_QUERY_PERFSTAT, *PEXT2_QUERY_PERFSTAT;
|
} EXT2_QUERY_PERFSTAT, *PEXT2_QUERY_PERFSTAT;
|
||||||
|
|
||||||
#define EXT2_QUERY_PERFSTAT_SZV1 (FIELD_OFFSET(EXT2_QUERY_PERFSTAT, PerfStatV1) + sizeof(EXT2_PERF_STATISTICS_V1))
|
#define EXT2_QUERY_PERFSTAT_SZV1 (FIELD_OFFSET(EXT2_QUERY_PERFSTAT, PerfStatV1) + sizeof(EXT2_PERF_STATISTICS_V1))
|
||||||
#define EXT2_QUERY_PERFSTAT_SZV2 (FIELD_OFFSET(EXT2_QUERY_PERFSTAT, PerfStatV1) + sizeof(EXT2_PERF_STATISTICS_V2))
|
#define EXT2_QUERY_PERFSTAT_SZV2 (FIELD_OFFSET(EXT2_QUERY_PERFSTAT, PerfStatV1) + sizeof(EXT2_PERF_STATISTICS_V2))
|
||||||
|
|
||||||
/* mountpoint management */
|
/* mountpoint management */
|
||||||
#define EXT2_APP_MOUNTPOINT_MAGIC 'EAMM'
|
#define EXT2_APP_MOUNTPOINT_MAGIC 'EAMM'
|
||||||
typedef struct _EXT2_MOUNT_POINT {
|
typedef struct _EXT2_MOUNT_POINT {
|
||||||
ULONG Magic;
|
ULONG Magic;
|
||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
ULONG Size;
|
ULONG Size;
|
||||||
ULONG Command;
|
ULONG Command;
|
||||||
USHORT Link[256];
|
USHORT Link[256];
|
||||||
USHORT Name[256];
|
USHORT Name[256];
|
||||||
} EXT2_MOUNT_POINT, *PEXT2_MOUNT_POINT;
|
} EXT2_MOUNT_POINT, *PEXT2_MOUNT_POINT;
|
||||||
|
|
||||||
#define APP_CMD_ADD_DOS_SYMLINK 0x00000001
|
#define APP_CMD_ADD_DOS_SYMLINK 0x00000001
|
||||||
#define APP_CMD_DEL_DOS_SYMLINK 0x00000002
|
#define APP_CMD_DEL_DOS_SYMLINK 0x00000002
|
||||||
|
|
||||||
|
|
||||||
#endif /* _EXT2_COMMON_INCLUDE_ */
|
#endif /* _EXT2_COMMON_INCLUDE_ */
|
||||||
|
|||||||
@@ -1,155 +1,155 @@
|
|||||||
#ifndef _LINUX_ATOMIC_H
|
#ifndef _LINUX_ATOMIC_H
|
||||||
#define _LINUX_ATOMIC_H
|
#define _LINUX_ATOMIC_H
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
//
|
//
|
||||||
// atomic
|
// atomic
|
||||||
//
|
//
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
volatile LONG counter;
|
volatile LONG counter;
|
||||||
} atomic_t;
|
} atomic_t;
|
||||||
|
|
||||||
#define ATOMIC_INIT(i) (i)
|
#define ATOMIC_INIT(i) (i)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* atomic_read - read atomic variable
|
* atomic_read - read atomic variable
|
||||||
* @v: pointer of type atomic_t
|
* @v: pointer of type atomic_t
|
||||||
*
|
*
|
||||||
* Atomically reads the value of @v. Note that the guaranteed
|
* Atomically reads the value of @v. Note that the guaranteed
|
||||||
* useful range of an atomic_t is only 24 bits.
|
* useful range of an atomic_t is only 24 bits.
|
||||||
*/
|
*/
|
||||||
#define atomic_read(v) ((v)->counter)
|
#define atomic_read(v) ((v)->counter)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* atomic_set - set atomic variable
|
* atomic_set - set atomic variable
|
||||||
* @v: pointer of type atomic_t
|
* @v: pointer of type atomic_t
|
||||||
* @i: required value
|
* @i: required value
|
||||||
*
|
*
|
||||||
* Atomically sets the value of @v to @i. Note that the guaranteed
|
* Atomically sets the value of @v to @i. Note that the guaranteed
|
||||||
* useful range of an atomic_t is only 24 bits.
|
* useful range of an atomic_t is only 24 bits.
|
||||||
*/
|
*/
|
||||||
#define atomic_set(v,i) InterlockedExchange((PLONG)(&(v)->counter), (LONG)(i))
|
#define atomic_set(v,i) InterlockedExchange((PLONG)(&(v)->counter), (LONG)(i))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* atomic_add - add integer to atomic variable
|
* atomic_add - add integer to atomic variable
|
||||||
* @i: integer value to add
|
* @i: integer value to add
|
||||||
* @v: pointer of type atomic_t
|
* @v: pointer of type atomic_t
|
||||||
*
|
*
|
||||||
* Atomically adds @i to @v. Note that the guaranteed useful range
|
* Atomically adds @i to @v. Note that the guaranteed useful range
|
||||||
* of an atomic_t is only 24 bits.
|
* of an atomic_t is only 24 bits.
|
||||||
*/
|
*/
|
||||||
static inline void atomic_add(int volatile i, atomic_t volatile *v)
|
static inline void atomic_add(int volatile i, atomic_t volatile *v)
|
||||||
{
|
{
|
||||||
InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) i);
|
InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* atomic_sub - subtract the atomic variable
|
* atomic_sub - subtract the atomic variable
|
||||||
* @i: integer value to subtract
|
* @i: integer value to subtract
|
||||||
* @v: pointer of type atomic_t
|
* @v: pointer of type atomic_t
|
||||||
*
|
*
|
||||||
* Atomically subtracts @i from @v. Note that the guaranteed
|
* Atomically subtracts @i from @v. Note that the guaranteed
|
||||||
* useful range of an atomic_t is only 24 bits.
|
* useful range of an atomic_t is only 24 bits.
|
||||||
*/
|
*/
|
||||||
static inline void atomic_sub(int volatile i, atomic_t volatile *v)
|
static inline void atomic_sub(int volatile i, atomic_t volatile *v)
|
||||||
{
|
{
|
||||||
InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) (-1*i));
|
InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) (-1*i));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* atomic_sub_and_test - subtract value from variable and test result
|
* atomic_sub_and_test - subtract value from variable and test result
|
||||||
* @i: integer value to subtract
|
* @i: integer value to subtract
|
||||||
* @v: pointer of type atomic_t
|
* @v: pointer of type atomic_t
|
||||||
*
|
*
|
||||||
* Atomically subtracts @i from @v and returns
|
* Atomically subtracts @i from @v and returns
|
||||||
* true if the result is zero, or false for all
|
* true if the result is zero, or false for all
|
||||||
* other cases. Note that the guaranteed
|
* other cases. Note that the guaranteed
|
||||||
* useful range of an atomic_t is only 24 bits.
|
* useful range of an atomic_t is only 24 bits.
|
||||||
*/
|
*/
|
||||||
static inline int atomic_sub_and_test(int volatile i, atomic_t volatile *v)
|
static inline int atomic_sub_and_test(int volatile i, atomic_t volatile *v)
|
||||||
{
|
{
|
||||||
int counter, result;
|
int counter, result;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
counter = v->counter;
|
counter = v->counter;
|
||||||
result = counter - i;
|
result = counter - i;
|
||||||
|
|
||||||
} while ( InterlockedCompareExchange(
|
} while ( InterlockedCompareExchange(
|
||||||
(PLONG) (&v->counter),
|
(PLONG) (&v->counter),
|
||||||
(LONG) result,
|
(LONG) result,
|
||||||
(LONG) counter) != counter);
|
(LONG) counter) != counter);
|
||||||
|
|
||||||
return (result == 0);
|
return (result == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* atomic_inc - increment atomic variable
|
* atomic_inc - increment atomic variable
|
||||||
* @v: pointer of type atomic_t
|
* @v: pointer of type atomic_t
|
||||||
*
|
*
|
||||||
* Atomically increments @v by 1. Note that the guaranteed
|
* Atomically increments @v by 1. Note that the guaranteed
|
||||||
* useful range of an atomic_t is only 24 bits.
|
* useful range of an atomic_t is only 24 bits.
|
||||||
*/
|
*/
|
||||||
static inline void atomic_inc(atomic_t volatile *v)
|
static inline void atomic_inc(atomic_t volatile *v)
|
||||||
{
|
{
|
||||||
InterlockedIncrement((PLONG)(&v->counter));
|
InterlockedIncrement((PLONG)(&v->counter));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* atomic_dec - decrement atomic variable
|
* atomic_dec - decrement atomic variable
|
||||||
* @v: pointer of type atomic_t
|
* @v: pointer of type atomic_t
|
||||||
*
|
*
|
||||||
* Atomically decrements @v by 1. Note that the guaranteed
|
* Atomically decrements @v by 1. Note that the guaranteed
|
||||||
* useful range of an atomic_t is only 24 bits.
|
* useful range of an atomic_t is only 24 bits.
|
||||||
*/
|
*/
|
||||||
static inline void atomic_dec(atomic_t volatile *v)
|
static inline void atomic_dec(atomic_t volatile *v)
|
||||||
{
|
{
|
||||||
InterlockedDecrement((PLONG)(&v->counter));
|
InterlockedDecrement((PLONG)(&v->counter));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* atomic_dec_and_test - decrement and test
|
* atomic_dec_and_test - decrement and test
|
||||||
* @v: pointer of type atomic_t
|
* @v: pointer of type atomic_t
|
||||||
*
|
*
|
||||||
* Atomically decrements @v by 1 and
|
* Atomically decrements @v by 1 and
|
||||||
* returns true if the result is 0, or false for all other
|
* returns true if the result is 0, or false for all other
|
||||||
* cases. Note that the guaranteed
|
* cases. Note that the guaranteed
|
||||||
* useful range of an atomic_t is only 24 bits.
|
* useful range of an atomic_t is only 24 bits.
|
||||||
*/
|
*/
|
||||||
static inline int atomic_dec_and_test(atomic_t volatile *v)
|
static inline int atomic_dec_and_test(atomic_t volatile *v)
|
||||||
{
|
{
|
||||||
return (0 == InterlockedDecrement((PLONG)(&v->counter)));
|
return (0 == InterlockedDecrement((PLONG)(&v->counter)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* atomic_inc_and_test - increment and test
|
* atomic_inc_and_test - increment and test
|
||||||
* @v: pointer of type atomic_t
|
* @v: pointer of type atomic_t
|
||||||
*
|
*
|
||||||
* Atomically increments @v by 1
|
* Atomically increments @v by 1
|
||||||
* and returns true if the result is zero, or false for all
|
* and returns true if the result is zero, or false for all
|
||||||
* other cases. Note that the guaranteed
|
* other cases. Note that the guaranteed
|
||||||
* useful range of an atomic_t is only 24 bits.
|
* useful range of an atomic_t is only 24 bits.
|
||||||
*/
|
*/
|
||||||
static inline int atomic_inc_and_test(atomic_t volatile *v)
|
static inline int atomic_inc_and_test(atomic_t volatile *v)
|
||||||
{
|
{
|
||||||
return (0 == InterlockedIncrement((PLONG)(&v->counter)));
|
return (0 == InterlockedIncrement((PLONG)(&v->counter)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* atomic_add_negative - add and test if negative
|
* atomic_add_negative - add and test if negative
|
||||||
* @v: pointer of type atomic_t
|
* @v: pointer of type atomic_t
|
||||||
* @i: integer value to add
|
* @i: integer value to add
|
||||||
*
|
*
|
||||||
* Atomically adds @i to @v and returns true
|
* Atomically adds @i to @v and returns true
|
||||||
* if the result is negative, or false when
|
* if the result is negative, or false when
|
||||||
* result is greater than or equal to zero. Note that the guaranteed
|
* result is greater than or equal to zero. Note that the guaranteed
|
||||||
* useful range of an atomic_t is only 24 bits.
|
* useful range of an atomic_t is only 24 bits.
|
||||||
*/
|
*/
|
||||||
static inline int atomic_add_negative(int volatile i, atomic_t volatile *v)
|
static inline int atomic_add_negative(int volatile i, atomic_t volatile *v)
|
||||||
{
|
{
|
||||||
return (InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) i) + i);
|
return (InterlockedExchangeAdd((PLONG)(&v->counter), (LONG) i) + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LINUX_ATOMIC_H */
|
#endif /* LINUX_ATOMIC_H */
|
||||||
@@ -1,95 +1,95 @@
|
|||||||
#ifndef __LINUX_BIT_SPINLOCK_H
|
#ifndef __LINUX_BIT_SPINLOCK_H
|
||||||
#define __LINUX_BIT_SPINLOCK_H
|
#define __LINUX_BIT_SPINLOCK_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bit-based spin_lock()
|
* bit-based spin_lock()
|
||||||
*
|
*
|
||||||
* Don't use this unless you really need to: spin_lock() and spin_unlock()
|
* Don't use this unless you really need to: spin_lock() and spin_unlock()
|
||||||
* are significantly faster.
|
* are significantly faster.
|
||||||
*/
|
*/
|
||||||
static inline void bit_spin_lock(int bitnum, unsigned long *addr)
|
static inline void bit_spin_lock(int bitnum, unsigned long *addr)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Assuming the lock is uncontended, this never enters
|
* Assuming the lock is uncontended, this never enters
|
||||||
* the body of the outer loop. If it is contended, then
|
* the body of the outer loop. If it is contended, then
|
||||||
* within the inner loop a non-atomic test is used to
|
* within the inner loop a non-atomic test is used to
|
||||||
* busywait with less bus contention for a good time to
|
* busywait with less bus contention for a good time to
|
||||||
* attempt to acquire the lock bit.
|
* attempt to acquire the lock bit.
|
||||||
*/
|
*/
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
|
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
|
||||||
while (unlikely(test_and_set_bit_lock(bitnum, addr))) {
|
while (unlikely(test_and_set_bit_lock(bitnum, addr))) {
|
||||||
while (test_bit(bitnum, addr)) {
|
while (test_bit(bitnum, addr)) {
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
__acquire(bitlock);
|
__acquire(bitlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return true if it was acquired
|
* Return true if it was acquired
|
||||||
*/
|
*/
|
||||||
static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
|
static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
|
||||||
{
|
{
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
|
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
|
||||||
if (unlikely(test_and_set_bit_lock(bitnum, addr))) {
|
if (unlikely(test_and_set_bit_lock(bitnum, addr))) {
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
__acquire(bitlock);
|
__acquire(bitlock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bit-based spin_unlock()
|
* bit-based spin_unlock()
|
||||||
*/
|
*/
|
||||||
static inline void bit_spin_unlock(int bitnum, unsigned long *addr)
|
static inline void bit_spin_unlock(int bitnum, unsigned long *addr)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_DEBUG_SPINLOCK
|
#ifdef CONFIG_DEBUG_SPINLOCK
|
||||||
BUG_ON(!test_bit(bitnum, addr));
|
BUG_ON(!test_bit(bitnum, addr));
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
|
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
|
||||||
clear_bit_unlock(bitnum, addr);
|
clear_bit_unlock(bitnum, addr);
|
||||||
#endif
|
#endif
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
__release(bitlock);
|
__release(bitlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bit-based spin_unlock()
|
* bit-based spin_unlock()
|
||||||
* non-atomic version, which can be used eg. if the bit lock itself is
|
* non-atomic version, which can be used eg. if the bit lock itself is
|
||||||
* protecting the rest of the flags in the word.
|
* protecting the rest of the flags in the word.
|
||||||
*/
|
*/
|
||||||
static inline void __bit_spin_unlock(int bitnum, unsigned long *addr)
|
static inline void __bit_spin_unlock(int bitnum, unsigned long *addr)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_DEBUG_SPINLOCK
|
#ifdef CONFIG_DEBUG_SPINLOCK
|
||||||
BUG_ON(!test_bit(bitnum, addr));
|
BUG_ON(!test_bit(bitnum, addr));
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
|
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
|
||||||
__clear_bit_unlock(bitnum, addr);
|
__clear_bit_unlock(bitnum, addr);
|
||||||
#endif
|
#endif
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
__release(bitlock);
|
__release(bitlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return true if the lock is held.
|
* Return true if the lock is held.
|
||||||
*/
|
*/
|
||||||
static inline int bit_spin_is_locked(int bitnum, unsigned long *addr)
|
static inline int bit_spin_is_locked(int bitnum, unsigned long *addr)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
|
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
|
||||||
return test_bit(bitnum, addr);
|
return test_bit(bitnum, addr);
|
||||||
#elif defined CONFIG_PREEMPT
|
#elif defined CONFIG_PREEMPT
|
||||||
return preempt_count();
|
return preempt_count();
|
||||||
#else
|
#else
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __LINUX_BIT_SPINLOCK_H */
|
#endif /* __LINUX_BIT_SPINLOCK_H */
|
||||||
|
|
||||||
|
|||||||
@@ -1,280 +1,280 @@
|
|||||||
#ifndef _LINUX_BITOPS_H
|
#ifndef _LINUX_BITOPS_H
|
||||||
#define _LINUX_BITOPS_H
|
#define _LINUX_BITOPS_H
|
||||||
|
|
||||||
#include <ntifs.h>
|
#include <ntifs.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
#define BIT(nr) (1 << (nr))
|
#define BIT(nr) (1 << (nr))
|
||||||
#define BIT_MASK(nr) (1 << ((nr) % BITS_PER_LONG))
|
#define BIT_MASK(nr) (1 << ((nr) % BITS_PER_LONG))
|
||||||
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||||
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG)
|
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG)
|
||||||
#define BITS_PER_BYTE 8
|
#define BITS_PER_BYTE 8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Include this here because some architectures need generic_ffs/fls in
|
* Include this here because some architectures need generic_ffs/fls in
|
||||||
* scope
|
* scope
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find_first_zero_bit - find the first zero bit in a memory region
|
* find_first_zero_bit - find the first zero bit in a memory region
|
||||||
* @addr: The address to start the search at
|
* @addr: The address to start the search at
|
||||||
* @size: The maximum size to search
|
* @size: The maximum size to search
|
||||||
*
|
*
|
||||||
* Returns the bit number of the first zero bit, not the number of the byte
|
* Returns the bit number of the first zero bit, not the number of the byte
|
||||||
* containing a bit.
|
* containing a bit.
|
||||||
*/
|
*/
|
||||||
#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
|
#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find_next_zero_bit - find the first zero bit in a memory region
|
* find_next_zero_bit - find the first zero bit in a memory region
|
||||||
* @addr: The address to base the search on
|
* @addr: The address to base the search on
|
||||||
* @offset: The bit number to start searching at
|
* @offset: The bit number to start searching at
|
||||||
* @size: The maximum size to search
|
* @size: The maximum size to search
|
||||||
*/
|
*/
|
||||||
int find_next_zero_bit(const unsigned long *addr, int size, int offset);
|
int find_next_zero_bit(const unsigned long *addr, int size, int offset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __ffs - find first bit in word.
|
* __ffs - find first bit in word.
|
||||||
* @word: The word to search
|
* @word: The word to search
|
||||||
*
|
*
|
||||||
* Undefined if no bit exists, so code should check against 0 first.
|
* Undefined if no bit exists, so code should check against 0 first.
|
||||||
*/
|
*/
|
||||||
static inline unsigned long __ffs(unsigned long word)
|
static inline unsigned long __ffs(unsigned long word)
|
||||||
{
|
{
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
#if BITS_PER_LONG == 64
|
#if BITS_PER_LONG == 64
|
||||||
if ((word & 0xffffffff) == 0) {
|
if ((word & 0xffffffff) == 0) {
|
||||||
num += 32;
|
num += 32;
|
||||||
word >>= 32;
|
word >>= 32;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if ((word & 0xffff) == 0) {
|
if ((word & 0xffff) == 0) {
|
||||||
num += 16;
|
num += 16;
|
||||||
word >>= 16;
|
word >>= 16;
|
||||||
}
|
}
|
||||||
if ((word & 0xff) == 0) {
|
if ((word & 0xff) == 0) {
|
||||||
num += 8;
|
num += 8;
|
||||||
word >>= 8;
|
word >>= 8;
|
||||||
}
|
}
|
||||||
if ((word & 0xf) == 0) {
|
if ((word & 0xf) == 0) {
|
||||||
num += 4;
|
num += 4;
|
||||||
word >>= 4;
|
word >>= 4;
|
||||||
}
|
}
|
||||||
if ((word & 0x3) == 0) {
|
if ((word & 0x3) == 0) {
|
||||||
num += 2;
|
num += 2;
|
||||||
word >>= 2;
|
word >>= 2;
|
||||||
}
|
}
|
||||||
if ((word & 0x1) == 0)
|
if ((word & 0x1) == 0)
|
||||||
num += 1;
|
num += 1;
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find_first_bit - find the first set bit in a memory region
|
* find_first_bit - find the first set bit in a memory region
|
||||||
* @addr: The address to start the search at
|
* @addr: The address to start the search at
|
||||||
* @size: The maximum size to search
|
* @size: The maximum size to search
|
||||||
*
|
*
|
||||||
* Returns the bit number of the first set bit, not the number of the byte
|
* Returns the bit number of the first set bit, not the number of the byte
|
||||||
* containing a bit.
|
* containing a bit.
|
||||||
*/
|
*/
|
||||||
static inline unsigned find_first_bit(const unsigned long *addr, unsigned size)
|
static inline unsigned find_first_bit(const unsigned long *addr, unsigned size)
|
||||||
{
|
{
|
||||||
unsigned x = 0;
|
unsigned x = 0;
|
||||||
|
|
||||||
while (x < size) {
|
while (x < size) {
|
||||||
unsigned long val = *addr++;
|
unsigned long val = *addr++;
|
||||||
if (val)
|
if (val)
|
||||||
return __ffs(val) + x;
|
return __ffs(val) + x;
|
||||||
x += (sizeof(*addr)<<3);
|
x += (sizeof(*addr)<<3);
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find_next_bit - find the next set bit in a memory region
|
* find_next_bit - find the next set bit in a memory region
|
||||||
* @addr: The address to base the search on
|
* @addr: The address to base the search on
|
||||||
* @offset: The bitnumber to start searching at
|
* @offset: The bitnumber to start searching at
|
||||||
* @size: The maximum size to search
|
* @size: The maximum size to search
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ffz - find first zero in word.
|
* ffz - find first zero in word.
|
||||||
* @word: The word to search
|
* @word: The word to search
|
||||||
*
|
*
|
||||||
* Undefined if no zero exists, so code should check against ~0UL first.
|
* Undefined if no zero exists, so code should check against ~0UL first.
|
||||||
*/
|
*/
|
||||||
#define ffz(x) __ffs(~(x))
|
#define ffz(x) __ffs(~(x))
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ffs - find first bit set
|
* ffs - find first bit set
|
||||||
* @x: the word to search
|
* @x: the word to search
|
||||||
*
|
*
|
||||||
* This is defined the same way as
|
* This is defined the same way as
|
||||||
* the libc and compiler builtin ffs routines, therefore
|
* the libc and compiler builtin ffs routines, therefore
|
||||||
* differs in spirit from the above ffz (man ffs).
|
* differs in spirit from the above ffz (man ffs).
|
||||||
*/
|
*/
|
||||||
static inline int ffs(int x)
|
static inline int ffs(int x)
|
||||||
{
|
{
|
||||||
int r = 1;
|
int r = 1;
|
||||||
|
|
||||||
if (!x)
|
if (!x)
|
||||||
return 0;
|
return 0;
|
||||||
if (!(x & 0xffff)) {
|
if (!(x & 0xffff)) {
|
||||||
x >>= 16;
|
x >>= 16;
|
||||||
r += 16;
|
r += 16;
|
||||||
}
|
}
|
||||||
if (!(x & 0xff)) {
|
if (!(x & 0xff)) {
|
||||||
x >>= 8;
|
x >>= 8;
|
||||||
r += 8;
|
r += 8;
|
||||||
}
|
}
|
||||||
if (!(x & 0xf)) {
|
if (!(x & 0xf)) {
|
||||||
x >>= 4;
|
x >>= 4;
|
||||||
r += 4;
|
r += 4;
|
||||||
}
|
}
|
||||||
if (!(x & 3)) {
|
if (!(x & 3)) {
|
||||||
x >>= 2;
|
x >>= 2;
|
||||||
r += 2;
|
r += 2;
|
||||||
}
|
}
|
||||||
if (!(x & 1)) {
|
if (!(x & 1)) {
|
||||||
x >>= 1;
|
x >>= 1;
|
||||||
r += 1;
|
r += 1;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fls - find last (most-significant) bit set
|
* fls - find last (most-significant) bit set
|
||||||
* @x: the word to search
|
* @x: the word to search
|
||||||
*
|
*
|
||||||
* This is defined the same way as ffs.
|
* This is defined the same way as ffs.
|
||||||
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
|
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline int fls(int x)
|
static inline int fls(int x)
|
||||||
{
|
{
|
||||||
int r = 32;
|
int r = 32;
|
||||||
|
|
||||||
if (!x)
|
if (!x)
|
||||||
return 0;
|
return 0;
|
||||||
if (!(x & 0xffff0000u)) {
|
if (!(x & 0xffff0000u)) {
|
||||||
x <<= 16;
|
x <<= 16;
|
||||||
r -= 16;
|
r -= 16;
|
||||||
}
|
}
|
||||||
if (!(x & 0xff000000u)) {
|
if (!(x & 0xff000000u)) {
|
||||||
x <<= 8;
|
x <<= 8;
|
||||||
r -= 8;
|
r -= 8;
|
||||||
}
|
}
|
||||||
if (!(x & 0xf0000000u)) {
|
if (!(x & 0xf0000000u)) {
|
||||||
x <<= 4;
|
x <<= 4;
|
||||||
r -= 4;
|
r -= 4;
|
||||||
}
|
}
|
||||||
if (!(x & 0xc0000000u)) {
|
if (!(x & 0xc0000000u)) {
|
||||||
x <<= 2;
|
x <<= 2;
|
||||||
r -= 2;
|
r -= 2;
|
||||||
}
|
}
|
||||||
if (!(x & 0x80000000u)) {
|
if (!(x & 0x80000000u)) {
|
||||||
x <<= 1;
|
x <<= 1;
|
||||||
r -= 1;
|
r -= 1;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int fls64(__u64 x)
|
static inline int fls64(__u64 x)
|
||||||
{
|
{
|
||||||
__u32 h = (__u32) (x >> 32);
|
__u32 h = (__u32) (x >> 32);
|
||||||
if (h)
|
if (h)
|
||||||
return fls(h) + 32;
|
return fls(h) + 32;
|
||||||
return fls((int)x);
|
return fls((int)x);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define for_each_bit(bit, addr, size) \
|
#define for_each_bit(bit, addr, size) \
|
||||||
for ((bit) = find_first_bit((addr), (size)); \
|
for ((bit) = find_first_bit((addr), (size)); \
|
||||||
(bit) < (size); \
|
(bit) < (size); \
|
||||||
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
(bit) = find_next_bit((addr), (size), (bit) + 1))
|
||||||
|
|
||||||
|
|
||||||
static __inline int get_bitmask_order(unsigned int count)
|
static __inline int get_bitmask_order(unsigned int count)
|
||||||
{
|
{
|
||||||
int order;
|
int order;
|
||||||
|
|
||||||
order = fls(count);
|
order = fls(count);
|
||||||
return order; /* We could be slightly more clever with -1 here... */
|
return order; /* We could be slightly more clever with -1 here... */
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline int get_count_order(unsigned int count)
|
static __inline int get_count_order(unsigned int count)
|
||||||
{
|
{
|
||||||
int order;
|
int order;
|
||||||
|
|
||||||
order = fls(count) - 1;
|
order = fls(count) - 1;
|
||||||
if (count & (count - 1))
|
if (count & (count - 1))
|
||||||
order++;
|
order++;
|
||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rol32 - rotate a 32-bit value left
|
* rol32 - rotate a 32-bit value left
|
||||||
* @word: value to rotate
|
* @word: value to rotate
|
||||||
* @shift: bits to roll
|
* @shift: bits to roll
|
||||||
*/
|
*/
|
||||||
static inline __u32 rol32(__u32 word, unsigned int shift)
|
static inline __u32 rol32(__u32 word, unsigned int shift)
|
||||||
{
|
{
|
||||||
return (word << shift) | (word >> (32 - shift));
|
return (word << shift) | (word >> (32 - shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ror32 - rotate a 32-bit value right
|
* ror32 - rotate a 32-bit value right
|
||||||
* @word: value to rotate
|
* @word: value to rotate
|
||||||
* @shift: bits to roll
|
* @shift: bits to roll
|
||||||
*/
|
*/
|
||||||
static inline __u32 ror32(__u32 word, unsigned int shift)
|
static inline __u32 ror32(__u32 word, unsigned int shift)
|
||||||
{
|
{
|
||||||
return (word >> shift) | (word << (32 - shift));
|
return (word >> shift) | (word << (32 - shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned fls_long(unsigned long l)
|
static inline unsigned fls_long(unsigned long l)
|
||||||
{
|
{
|
||||||
if (sizeof(l) == 4)
|
if (sizeof(l) == 4)
|
||||||
return fls(l);
|
return fls(l);
|
||||||
return fls64(l);
|
return fls64(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* hweightN: returns the hamming weight (i.e. the number
|
* hweightN: returns the hamming weight (i.e. the number
|
||||||
* of bits set) of a N-bit word
|
* of bits set) of a N-bit word
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline unsigned long hweight32(unsigned long w)
|
static inline unsigned long hweight32(unsigned long w)
|
||||||
{
|
{
|
||||||
unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
|
unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
|
||||||
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
|
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
|
||||||
res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
|
res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
|
||||||
res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
|
res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
|
||||||
return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
|
return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long hweight64(__u64 w)
|
static inline unsigned long hweight64(__u64 w)
|
||||||
{
|
{
|
||||||
#if BITS_PER_LONG < 64
|
#if BITS_PER_LONG < 64
|
||||||
return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w);
|
return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w);
|
||||||
#else
|
#else
|
||||||
u64 res;
|
u64 res;
|
||||||
res = (w & 0x5555555555555555U) + ((w >> 1) & 0x5555555555555555U);
|
res = (w & 0x5555555555555555U) + ((w >> 1) & 0x5555555555555555U);
|
||||||
res = (res & 0x3333333333333333U) + ((res >> 2) & 0x3333333333333333U);
|
res = (res & 0x3333333333333333U) + ((res >> 2) & 0x3333333333333333U);
|
||||||
res = (res & 0x0F0F0F0F0F0F0F0FU) + ((res >> 4) & 0x0F0F0F0F0F0F0F0FU);
|
res = (res & 0x0F0F0F0F0F0F0F0FU) + ((res >> 4) & 0x0F0F0F0F0F0F0F0FU);
|
||||||
res = (res & 0x00FF00FF00FF00FFU) + ((res >> 8) & 0x00FF00FF00FF00FFU);
|
res = (res & 0x00FF00FF00FF00FFU) + ((res >> 8) & 0x00FF00FF00FF00FFU);
|
||||||
res = (res & 0x0000FFFF0000FFFFU) + ((res >> 16) & 0x0000FFFF0000FFFFU);
|
res = (res & 0x0000FFFF0000FFFFU) + ((res >> 16) & 0x0000FFFF0000FFFFU);
|
||||||
return (res & 0x00000000FFFFFFFFU) + ((res >> 32) & 0x00000000FFFFFFFFU);
|
return (res & 0x00000000FFFFFFFFU) + ((res >> 32) & 0x00000000FFFFFFFFU);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long hweight_long(unsigned long w)
|
static inline unsigned long hweight_long(unsigned long w)
|
||||||
{
|
{
|
||||||
return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
|
return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef LINUX_CONFIG_H
|
#ifndef LINUX_CONFIG_H
|
||||||
#define LINUX_CONFIG_H
|
#define LINUX_CONFIG_H
|
||||||
|
|
||||||
#define EXT2_HTREE_INDEX 1
|
#define EXT2_HTREE_INDEX 1
|
||||||
//#undef EXT2_HTREE_INDEX
|
//#undef EXT2_HTREE_INDEX
|
||||||
|
|
||||||
#endif /* LINUX_CONFIG_H */
|
#endif /* LINUX_CONFIG_H */
|
||||||
@@ -1,147 +1,147 @@
|
|||||||
#ifndef _I386_ERRNO_H
|
#ifndef _I386_ERRNO_H
|
||||||
#define _I386_ERRNO_H
|
#define _I386_ERRNO_H
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#define EPERM 1 /* Operation not permitted */
|
#define EPERM 1 /* Operation not permitted */
|
||||||
#define ENOENT 2 /* No such file or directory */
|
#define ENOENT 2 /* No such file or directory */
|
||||||
#define ESRCH 3 /* No such process */
|
#define ESRCH 3 /* No such process */
|
||||||
#define EINTR 4 /* Interrupted system call */
|
#define EINTR 4 /* Interrupted system call */
|
||||||
#define EIO 5 /* I/O error */
|
#define EIO 5 /* I/O error */
|
||||||
#define ENXIO 6 /* No such device or address */
|
#define ENXIO 6 /* No such device or address */
|
||||||
#define E2BIG 7 /* Arg list too long */
|
#define E2BIG 7 /* Arg list too long */
|
||||||
#define ENOEXEC 8 /* Exec format error */
|
#define ENOEXEC 8 /* Exec format error */
|
||||||
#define EBADF 9 /* Bad file number */
|
#define EBADF 9 /* Bad file number */
|
||||||
#define ECHILD 10 /* No child processes */
|
#define ECHILD 10 /* No child processes */
|
||||||
#define EAGAIN 11 /* Try again */
|
#define EAGAIN 11 /* Try again */
|
||||||
#define ENOMEM 12 /* Out of memory */
|
#define ENOMEM 12 /* Out of memory */
|
||||||
#define EACCES 13 /* Permission denied */
|
#define EACCES 13 /* Permission denied */
|
||||||
#define EFAULT 14 /* Bad address */
|
#define EFAULT 14 /* Bad address */
|
||||||
#define ENOTBLK 15 /* Block device required */
|
#define ENOTBLK 15 /* Block device required */
|
||||||
#define EBUSY 16 /* Device or resource busy */
|
#define EBUSY 16 /* Device or resource busy */
|
||||||
#define EEXIST 17 /* File exists */
|
#define EEXIST 17 /* File exists */
|
||||||
#define EXDEV 18 /* Cross-device link */
|
#define EXDEV 18 /* Cross-device link */
|
||||||
#define ENODEV 19 /* No such device */
|
#define ENODEV 19 /* No such device */
|
||||||
#define ENOTDIR 20 /* Not a directory */
|
#define ENOTDIR 20 /* Not a directory */
|
||||||
#define EISDIR 21 /* Is a directory */
|
#define EISDIR 21 /* Is a directory */
|
||||||
#define EINVAL 22 /* Invalid argument */
|
#define EINVAL 22 /* Invalid argument */
|
||||||
#define ENFILE 23 /* File table overflow */
|
#define ENFILE 23 /* File table overflow */
|
||||||
#define EMFILE 24 /* Too many open files */
|
#define EMFILE 24 /* Too many open files */
|
||||||
#define ENOTTY 25 /* Not a typewriter */
|
#define ENOTTY 25 /* Not a typewriter */
|
||||||
#define ETXTBSY 26 /* Text file busy */
|
#define ETXTBSY 26 /* Text file busy */
|
||||||
#define EFBIG 27 /* File too large */
|
#define EFBIG 27 /* File too large */
|
||||||
#define ENOSPC 28 /* No space left on device */
|
#define ENOSPC 28 /* No space left on device */
|
||||||
#define ESPIPE 29 /* Illegal seek */
|
#define ESPIPE 29 /* Illegal seek */
|
||||||
#define EROFS 30 /* Read-only file system */
|
#define EROFS 30 /* Read-only file system */
|
||||||
#define EMLINK 31 /* Too many links */
|
#define EMLINK 31 /* Too many links */
|
||||||
#define EPIPE 32 /* Broken pipe */
|
#define EPIPE 32 /* Broken pipe */
|
||||||
#define EDOM 33 /* Math argument out of domain of func */
|
#define EDOM 33 /* Math argument out of domain of func */
|
||||||
#define ERANGE 34 /* Math result not representable */
|
#define ERANGE 34 /* Math result not representable */
|
||||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||||
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
||||||
#define ENOMSG 42 /* No message of desired type */
|
#define ENOMSG 42 /* No message of desired type */
|
||||||
#define EIDRM 43 /* Identifier removed */
|
#define EIDRM 43 /* Identifier removed */
|
||||||
#define ECHRNG 44 /* Channel number out of range */
|
#define ECHRNG 44 /* Channel number out of range */
|
||||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||||
#define EL3HLT 46 /* Level 3 halted */
|
#define EL3HLT 46 /* Level 3 halted */
|
||||||
#define EL3RST 47 /* Level 3 reset */
|
#define EL3RST 47 /* Level 3 reset */
|
||||||
#define ELNRNG 48 /* Link number out of range */
|
#define ELNRNG 48 /* Link number out of range */
|
||||||
#define EUNATCH 49 /* Protocol driver not attached */
|
#define EUNATCH 49 /* Protocol driver not attached */
|
||||||
#define ENOCSI 50 /* No CSI structure available */
|
#define ENOCSI 50 /* No CSI structure available */
|
||||||
#define EL2HLT 51 /* Level 2 halted */
|
#define EL2HLT 51 /* Level 2 halted */
|
||||||
#define EBADE 52 /* Invalid exchange */
|
#define EBADE 52 /* Invalid exchange */
|
||||||
#define EBADR 53 /* Invalid request descriptor */
|
#define EBADR 53 /* Invalid request descriptor */
|
||||||
#define EXFULL 54 /* Exchange full */
|
#define EXFULL 54 /* Exchange full */
|
||||||
#define ENOANO 55 /* No anode */
|
#define ENOANO 55 /* No anode */
|
||||||
#define EBADRQC 56 /* Invalid request code */
|
#define EBADRQC 56 /* Invalid request code */
|
||||||
#define EBADSLT 57 /* Invalid slot */
|
#define EBADSLT 57 /* Invalid slot */
|
||||||
|
|
||||||
#define EDEADLOCK EDEADLK
|
#define EDEADLOCK EDEADLK
|
||||||
|
|
||||||
#define EBFONT 59 /* Bad font file format */
|
#define EBFONT 59 /* Bad font file format */
|
||||||
#define ENOSTR 60 /* Device not a stream */
|
#define ENOSTR 60 /* Device not a stream */
|
||||||
#define ENODATA 61 /* No data available */
|
#define ENODATA 61 /* No data available */
|
||||||
#define ETIME 62 /* Timer expired */
|
#define ETIME 62 /* Timer expired */
|
||||||
#define ENOSR 63 /* Out of streams resources */
|
#define ENOSR 63 /* Out of streams resources */
|
||||||
#define ENONET 64 /* Machine is not on the network */
|
#define ENONET 64 /* Machine is not on the network */
|
||||||
#define ENOPKG 65 /* Package not installed */
|
#define ENOPKG 65 /* Package not installed */
|
||||||
#define EREMOTE 66 /* Object is remote */
|
#define EREMOTE 66 /* Object is remote */
|
||||||
#define ENOLINK 67 /* Link has been severed */
|
#define ENOLINK 67 /* Link has been severed */
|
||||||
#define EADV 68 /* Advertise error */
|
#define EADV 68 /* Advertise error */
|
||||||
#define ESRMNT 69 /* Srmount error */
|
#define ESRMNT 69 /* Srmount error */
|
||||||
#define ECOMM 70 /* Communication error on send */
|
#define ECOMM 70 /* Communication error on send */
|
||||||
#define EPROTO 71 /* Protocol error */
|
#define EPROTO 71 /* Protocol error */
|
||||||
#define EMULTIHOP 72 /* Multihop attempted */
|
#define EMULTIHOP 72 /* Multihop attempted */
|
||||||
#define EDOTDOT 73 /* RFS specific error */
|
#define EDOTDOT 73 /* RFS specific error */
|
||||||
#define EBADMSG 74 /* Not a data message */
|
#define EBADMSG 74 /* Not a data message */
|
||||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||||
#define EBADFD 77 /* File descriptor in bad state */
|
#define EBADFD 77 /* File descriptor in bad state */
|
||||||
#define EREMCHG 78 /* Remote address changed */
|
#define EREMCHG 78 /* Remote address changed */
|
||||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||||
#define ESTRPIPE 86 /* Streams pipe error */
|
#define ESTRPIPE 86 /* Streams pipe error */
|
||||||
#define EUSERS 87 /* Too many users */
|
#define EUSERS 87 /* Too many users */
|
||||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||||
#define EDESTADDRREQ 89 /* Destination address required */
|
#define EDESTADDRREQ 89 /* Destination address required */
|
||||||
#define EMSGSIZE 90 /* Message too long */
|
#define EMSGSIZE 90 /* Message too long */
|
||||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||||
#define EADDRINUSE 98 /* Address already in use */
|
#define EADDRINUSE 98 /* Address already in use */
|
||||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||||
#define ENETDOWN 100 /* Network is down */
|
#define ENETDOWN 100 /* Network is down */
|
||||||
#define ENETUNREACH 101 /* Network is unreachable */
|
#define ENETUNREACH 101 /* Network is unreachable */
|
||||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||||
#define ECONNRESET 104 /* Connection reset by peer */
|
#define ECONNRESET 104 /* Connection reset by peer */
|
||||||
#define ENOBUFS 105 /* No buffer space available */
|
#define ENOBUFS 105 /* No buffer space available */
|
||||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||||
#define ETIMEDOUT 110 /* Connection timed out */
|
#define ETIMEDOUT 110 /* Connection timed out */
|
||||||
#define ECONNREFUSED 111 /* Connection refused */
|
#define ECONNREFUSED 111 /* Connection refused */
|
||||||
#define EHOSTDOWN 112 /* Host is down */
|
#define EHOSTDOWN 112 /* Host is down */
|
||||||
#define EHOSTUNREACH 113 /* No route to host */
|
#define EHOSTUNREACH 113 /* No route to host */
|
||||||
#define EALREADY 114 /* Operation already in progress */
|
#define EALREADY 114 /* Operation already in progress */
|
||||||
#define EINPROGRESS 115 /* Operation now in progress */
|
#define EINPROGRESS 115 /* Operation now in progress */
|
||||||
#define ESTALE 116 /* Stale NFS file handle */
|
#define ESTALE 116 /* Stale NFS file handle */
|
||||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||||
#define EISNAM 120 /* Is a named type file */
|
#define EISNAM 120 /* Is a named type file */
|
||||||
#define EREMOTEIO 121 /* Remote I/O error */
|
#define EREMOTEIO 121 /* Remote I/O error */
|
||||||
#define EDQUOT 122 /* Quota exceeded */
|
#define EDQUOT 122 /* Quota exceeded */
|
||||||
|
|
||||||
#define ENOMEDIUM 123 /* No medium found */
|
#define ENOMEDIUM 123 /* No medium found */
|
||||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||||
|
|
||||||
/* Should never be seen by user programs */
|
/* Should never be seen by user programs */
|
||||||
#define ERESTARTSYS 512
|
#define ERESTARTSYS 512
|
||||||
#define ERESTARTNOINTR 513
|
#define ERESTARTNOINTR 513
|
||||||
#define ERESTARTNOHAND 514 /* restart if no handler.. */
|
#define ERESTARTNOHAND 514 /* restart if no handler.. */
|
||||||
#define ENOIOCTLCMD 515 /* No ioctl command */
|
#define ENOIOCTLCMD 515 /* No ioctl command */
|
||||||
|
|
||||||
/* Defined for the NFSv3 protocol */
|
/* Defined for the NFSv3 protocol */
|
||||||
#define EBADHANDLE 521 /* Illegal NFS file handle */
|
#define EBADHANDLE 521 /* Illegal NFS file handle */
|
||||||
#define ENOTSYNC 522 /* Update synchronization mismatch */
|
#define ENOTSYNC 522 /* Update synchronization mismatch */
|
||||||
#define EBADCOOKIE 523 /* Cookie is stale */
|
#define EBADCOOKIE 523 /* Cookie is stale */
|
||||||
#define ENOTSUPP 524 /* Operation is not supported */
|
#define ENOTSUPP 524 /* Operation is not supported */
|
||||||
#define ETOOSMALL 525 /* Buffer or request is too small */
|
#define ETOOSMALL 525 /* Buffer or request is too small */
|
||||||
#define ESERVERFAULT 526 /* An untranslatable error occurred */
|
#define ESERVERFAULT 526 /* An untranslatable error occurred */
|
||||||
#define EBADTYPE 527 /* Type not supported by server */
|
#define EBADTYPE 527 /* Type not supported by server */
|
||||||
#define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */
|
#define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */
|
||||||
#if _MSC_VER > 1900
|
#if _MSC_VER > 1900
|
||||||
#define ENAMETOOLONG 1024;
|
#define ENAMETOOLONG 1024;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,257 +1,257 @@
|
|||||||
#ifndef _LINUX_EXT4_EXT
|
#ifndef _LINUX_EXT4_EXT
|
||||||
#define _LINUX_EXT4_EXT
|
#define _LINUX_EXT4_EXT
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the extent tail on-disk structure.
|
* This is the extent tail on-disk structure.
|
||||||
* All other extent structures are 12 bytes long. It turns out that
|
* All other extent structures are 12 bytes long. It turns out that
|
||||||
* block_size % 12 >= 4 for at least all powers of 2 greater than 512, which
|
* block_size % 12 >= 4 for at least all powers of 2 greater than 512, which
|
||||||
* covers all valid ext4 block sizes. Therefore, this tail structure can be
|
* covers all valid ext4 block sizes. Therefore, this tail structure can be
|
||||||
* crammed into the end of the block without having to rebalance the tree.
|
* crammed into the end of the block without having to rebalance the tree.
|
||||||
*/
|
*/
|
||||||
struct ext4_extent_tail {
|
struct ext4_extent_tail {
|
||||||
uint32_t et_checksum; /* crc32c(uuid+inum+extent_block) */
|
uint32_t et_checksum; /* crc32c(uuid+inum+extent_block) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the extent on-disk structure.
|
* This is the extent on-disk structure.
|
||||||
* It's used at the bottom of the tree.
|
* It's used at the bottom of the tree.
|
||||||
*/
|
*/
|
||||||
typedef struct ext4_extent {
|
typedef struct ext4_extent {
|
||||||
uint32_t ee_block; /* first logical block extent covers */
|
uint32_t ee_block; /* first logical block extent covers */
|
||||||
uint16_t ee_len; /* number of blocks covered by extent */
|
uint16_t ee_len; /* number of blocks covered by extent */
|
||||||
uint16_t ee_start_hi; /* high 16 bits of physical block */
|
uint16_t ee_start_hi; /* high 16 bits of physical block */
|
||||||
uint32_t ee_start_lo; /* low 32 bits of physical block */
|
uint32_t ee_start_lo; /* low 32 bits of physical block */
|
||||||
} __attribute__ ((__packed__)) EXT4_EXTENT;
|
} __attribute__ ((__packed__)) EXT4_EXTENT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is index on-disk structure.
|
* This is index on-disk structure.
|
||||||
* It's used at all the levels except the bottom.
|
* It's used at all the levels except the bottom.
|
||||||
*/
|
*/
|
||||||
typedef struct ext4_extent_idx {
|
typedef struct ext4_extent_idx {
|
||||||
uint32_t ei_block; /* index covers logical blocks from 'block' */
|
uint32_t ei_block; /* index covers logical blocks from 'block' */
|
||||||
uint32_t ei_leaf_lo; /* pointer to the physical block of the next *
|
uint32_t ei_leaf_lo; /* pointer to the physical block of the next *
|
||||||
* level. leaf or next index could be there */
|
* level. leaf or next index could be there */
|
||||||
uint16_t ei_leaf_hi; /* high 16 bits of physical block */
|
uint16_t ei_leaf_hi; /* high 16 bits of physical block */
|
||||||
uint16_t ei_unused;
|
uint16_t ei_unused;
|
||||||
}__attribute__ ((__packed__)) EXT4_EXTENT_IDX;
|
}__attribute__ ((__packed__)) EXT4_EXTENT_IDX;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each block (leaves and indexes), even inode-stored has header.
|
* Each block (leaves and indexes), even inode-stored has header.
|
||||||
*/
|
*/
|
||||||
typedef struct ext4_extent_header {
|
typedef struct ext4_extent_header {
|
||||||
uint16_t eh_magic; /* probably will support different formats */
|
uint16_t eh_magic; /* probably will support different formats */
|
||||||
uint16_t eh_entries; /* number of valid entries */
|
uint16_t eh_entries; /* number of valid entries */
|
||||||
uint16_t eh_max; /* capacity of store in entries */
|
uint16_t eh_max; /* capacity of store in entries */
|
||||||
uint16_t eh_depth; /* has tree real underlying blocks? */
|
uint16_t eh_depth; /* has tree real underlying blocks? */
|
||||||
uint32_t eh_generation; /* generation of the tree */
|
uint32_t eh_generation; /* generation of the tree */
|
||||||
}__attribute__ ((__packed__)) EXT4_EXTENT_HEADER;
|
}__attribute__ ((__packed__)) EXT4_EXTENT_HEADER;
|
||||||
|
|
||||||
|
|
||||||
#define EXT4_EXT_MAGIC 0xf30a
|
#define EXT4_EXT_MAGIC 0xf30a
|
||||||
#define get_ext4_header(i) ((struct ext4_extent_header *) (i)->i_block)
|
#define get_ext4_header(i) ((struct ext4_extent_header *) (i)->i_block)
|
||||||
|
|
||||||
#define EXT4_EXTENT_TAIL_OFFSET(hdr) \
|
#define EXT4_EXTENT_TAIL_OFFSET(hdr) \
|
||||||
(sizeof(struct ext4_extent_header) + \
|
(sizeof(struct ext4_extent_header) + \
|
||||||
(sizeof(struct ext4_extent) * (hdr)->eh_max))
|
(sizeof(struct ext4_extent) * (hdr)->eh_max))
|
||||||
|
|
||||||
static inline struct ext4_extent_tail *
|
static inline struct ext4_extent_tail *
|
||||||
find_ext4_extent_tail(struct ext4_extent_header *eh)
|
find_ext4_extent_tail(struct ext4_extent_header *eh)
|
||||||
{
|
{
|
||||||
return (struct ext4_extent_tail *)(((char *)eh) +
|
return (struct ext4_extent_tail *)(((char *)eh) +
|
||||||
EXT4_EXTENT_TAIL_OFFSET(eh));
|
EXT4_EXTENT_TAIL_OFFSET(eh));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Array of ext4_ext_path contains path to some extent.
|
* Array of ext4_ext_path contains path to some extent.
|
||||||
* Creation/lookup routines use it for traversal/splitting/etc.
|
* Creation/lookup routines use it for traversal/splitting/etc.
|
||||||
* Truncate uses it to simulate recursive walking.
|
* Truncate uses it to simulate recursive walking.
|
||||||
*/
|
*/
|
||||||
struct ext4_ext_path
|
struct ext4_ext_path
|
||||||
{
|
{
|
||||||
ext4_fsblk_t p_block;
|
ext4_fsblk_t p_block;
|
||||||
int p_depth;
|
int p_depth;
|
||||||
int p_maxdepth;
|
int p_maxdepth;
|
||||||
struct ext4_extent *p_ext;
|
struct ext4_extent *p_ext;
|
||||||
struct ext4_extent_idx *p_idx;
|
struct ext4_extent_idx *p_idx;
|
||||||
struct ext4_extent_header *p_hdr;
|
struct ext4_extent_header *p_hdr;
|
||||||
struct buffer_head *p_bh;
|
struct buffer_head *p_bh;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* structure for external API
|
* structure for external API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
|
* EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
|
||||||
* initialized extent. This is 2^15 and not (2^16 - 1), since we use the
|
* initialized extent. This is 2^15 and not (2^16 - 1), since we use the
|
||||||
* MSB of ee_len field in the extent datastructure to signify if this
|
* MSB of ee_len field in the extent datastructure to signify if this
|
||||||
* particular extent is an initialized extent or an uninitialized (i.e.
|
* particular extent is an initialized extent or an uninitialized (i.e.
|
||||||
* preallocated).
|
* preallocated).
|
||||||
* EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an
|
* EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an
|
||||||
* uninitialized extent.
|
* uninitialized extent.
|
||||||
* If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an
|
* If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an
|
||||||
* uninitialized one. In other words, if MSB of ee_len is set, it is an
|
* uninitialized one. In other words, if MSB of ee_len is set, it is an
|
||||||
* uninitialized extent with only one special scenario when ee_len = 0x8000.
|
* uninitialized extent with only one special scenario when ee_len = 0x8000.
|
||||||
* In this case we can not have an uninitialized extent of zero length and
|
* In this case we can not have an uninitialized extent of zero length and
|
||||||
* thus we make it as a special case of initialized extent with 0x8000 length.
|
* thus we make it as a special case of initialized extent with 0x8000 length.
|
||||||
* This way we get better extent-to-group alignment for initialized extents.
|
* This way we get better extent-to-group alignment for initialized extents.
|
||||||
* Hence, the maximum number of blocks we can have in an *initialized*
|
* Hence, the maximum number of blocks we can have in an *initialized*
|
||||||
* extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767).
|
* extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767).
|
||||||
*/
|
*/
|
||||||
#define EXT_INIT_MAX_LEN (1UL << 15)
|
#define EXT_INIT_MAX_LEN (1UL << 15)
|
||||||
#define EXT_UNWRITTEN_MAX_LEN (EXT_INIT_MAX_LEN - 1)
|
#define EXT_UNWRITTEN_MAX_LEN (EXT_INIT_MAX_LEN - 1)
|
||||||
|
|
||||||
#define EXT_EXTENT_SIZE sizeof(struct ext4_extent)
|
#define EXT_EXTENT_SIZE sizeof(struct ext4_extent)
|
||||||
#define EXT_INDEX_SIZE sizeof(struct ext4_extent_idx)
|
#define EXT_INDEX_SIZE sizeof(struct ext4_extent_idx)
|
||||||
|
|
||||||
#define EXT_FIRST_EXTENT(__hdr__) \
|
#define EXT_FIRST_EXTENT(__hdr__) \
|
||||||
((struct ext4_extent *)(((char *)(__hdr__)) + \
|
((struct ext4_extent *)(((char *)(__hdr__)) + \
|
||||||
sizeof(struct ext4_extent_header)))
|
sizeof(struct ext4_extent_header)))
|
||||||
#define EXT_FIRST_INDEX(__hdr__) \
|
#define EXT_FIRST_INDEX(__hdr__) \
|
||||||
((struct ext4_extent_idx *)(((char *)(__hdr__)) + \
|
((struct ext4_extent_idx *)(((char *)(__hdr__)) + \
|
||||||
sizeof(struct ext4_extent_header)))
|
sizeof(struct ext4_extent_header)))
|
||||||
#define EXT_HAS_FREE_INDEX(__path__) \
|
#define EXT_HAS_FREE_INDEX(__path__) \
|
||||||
((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max)
|
((__path__)->p_hdr->eh_entries < (__path__)->p_hdr->eh_max)
|
||||||
#define EXT_LAST_EXTENT(__hdr__) \
|
#define EXT_LAST_EXTENT(__hdr__) \
|
||||||
(EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1)
|
(EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_entries - 1)
|
||||||
#define EXT_LAST_INDEX(__hdr__) \
|
#define EXT_LAST_INDEX(__hdr__) \
|
||||||
(EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1)
|
(EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_entries - 1)
|
||||||
#define EXT_MAX_EXTENT(__hdr__) \
|
#define EXT_MAX_EXTENT(__hdr__) \
|
||||||
(EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
|
(EXT_FIRST_EXTENT((__hdr__)) + (__hdr__)->eh_max - 1)
|
||||||
#define EXT_MAX_INDEX(__hdr__) \
|
#define EXT_MAX_INDEX(__hdr__) \
|
||||||
(EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
|
(EXT_FIRST_INDEX((__hdr__)) + (__hdr__)->eh_max - 1)
|
||||||
|
|
||||||
static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode)
|
static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode)
|
||||||
{
|
{
|
||||||
return get_ext4_header(inode);
|
return get_ext4_header(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct ext4_extent_header *ext_block_hdr(struct buffer_head *bh)
|
static inline struct ext4_extent_header *ext_block_hdr(struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
return (struct ext4_extent_header *)bh->b_data;
|
return (struct ext4_extent_header *)bh->b_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned short ext_depth(struct inode *inode)
|
static inline unsigned short ext_depth(struct inode *inode)
|
||||||
{
|
{
|
||||||
return ext_inode_hdr(inode)->eh_depth;
|
return ext_inode_hdr(inode)->eh_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ext4_ext_mark_uninitialized(struct ext4_extent *ext)
|
static inline void ext4_ext_mark_uninitialized(struct ext4_extent *ext)
|
||||||
{
|
{
|
||||||
/* We can not have an uninitialized extent of zero length! */
|
/* We can not have an uninitialized extent of zero length! */
|
||||||
ext->ee_len |= EXT_INIT_MAX_LEN;
|
ext->ee_len |= EXT_INIT_MAX_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ext4_ext_is_uninitialized(struct ext4_extent *ext)
|
static inline int ext4_ext_is_uninitialized(struct ext4_extent *ext)
|
||||||
{
|
{
|
||||||
/* Extent with ee_len of 0x8000 is treated as an initialized extent */
|
/* Extent with ee_len of 0x8000 is treated as an initialized extent */
|
||||||
return (ext->ee_len > EXT_INIT_MAX_LEN);
|
return (ext->ee_len > EXT_INIT_MAX_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint16_t ext4_ext_get_actual_len(struct ext4_extent *ext)
|
static inline uint16_t ext4_ext_get_actual_len(struct ext4_extent *ext)
|
||||||
{
|
{
|
||||||
return (ext->ee_len <= EXT_INIT_MAX_LEN
|
return (ext->ee_len <= EXT_INIT_MAX_LEN
|
||||||
? ext->ee_len
|
? ext->ee_len
|
||||||
: (ext->ee_len - EXT_INIT_MAX_LEN));
|
: (ext->ee_len - EXT_INIT_MAX_LEN));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ext4_ext_mark_initialized(struct ext4_extent *ext)
|
static inline void ext4_ext_mark_initialized(struct ext4_extent *ext)
|
||||||
{
|
{
|
||||||
ext->ee_len = ext4_ext_get_actual_len(ext);
|
ext->ee_len = ext4_ext_get_actual_len(ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ext4_ext_mark_unwritten(struct ext4_extent *ext)
|
static inline void ext4_ext_mark_unwritten(struct ext4_extent *ext)
|
||||||
{
|
{
|
||||||
/* We can not have an unwritten extent of zero length! */
|
/* We can not have an unwritten extent of zero length! */
|
||||||
ext->ee_len |= EXT_INIT_MAX_LEN;
|
ext->ee_len |= EXT_INIT_MAX_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ext4_ext_is_unwritten(struct ext4_extent *ext)
|
static inline int ext4_ext_is_unwritten(struct ext4_extent *ext)
|
||||||
{
|
{
|
||||||
/* Extent with ee_len of 0x8000 is treated as an initialized extent */
|
/* Extent with ee_len of 0x8000 is treated as an initialized extent */
|
||||||
return (ext->ee_len > EXT_INIT_MAX_LEN);
|
return (ext->ee_len > EXT_INIT_MAX_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ext4_ext_pblock:
|
* ext4_ext_pblock:
|
||||||
* combine low and high parts of physical block number into ext4_fsblk_t
|
* combine low and high parts of physical block number into ext4_fsblk_t
|
||||||
*/
|
*/
|
||||||
static inline ext4_fsblk_t ext4_ext_pblock(struct ext4_extent *ex)
|
static inline ext4_fsblk_t ext4_ext_pblock(struct ext4_extent *ex)
|
||||||
{
|
{
|
||||||
ext4_fsblk_t block;
|
ext4_fsblk_t block;
|
||||||
|
|
||||||
block = ex->ee_start_lo;
|
block = ex->ee_start_lo;
|
||||||
block |= ((ext4_fsblk_t)ex->ee_start_hi << 31) << 1;
|
block |= ((ext4_fsblk_t)ex->ee_start_hi << 31) << 1;
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ext4_idx_pblock:
|
* ext4_idx_pblock:
|
||||||
* combine low and high parts of a leaf physical block number into ext4_fsblk_t
|
* combine low and high parts of a leaf physical block number into ext4_fsblk_t
|
||||||
*/
|
*/
|
||||||
static inline ext4_fsblk_t ext4_idx_pblock(struct ext4_extent_idx *ix)
|
static inline ext4_fsblk_t ext4_idx_pblock(struct ext4_extent_idx *ix)
|
||||||
{
|
{
|
||||||
ext4_fsblk_t block;
|
ext4_fsblk_t block;
|
||||||
|
|
||||||
block = ix->ei_leaf_lo;
|
block = ix->ei_leaf_lo;
|
||||||
block |= ((ext4_fsblk_t)ix->ei_leaf_hi << 31) << 1;
|
block |= ((ext4_fsblk_t)ix->ei_leaf_hi << 31) << 1;
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ext4_ext_store_pblock:
|
* ext4_ext_store_pblock:
|
||||||
* stores a large physical block number into an extent struct,
|
* stores a large physical block number into an extent struct,
|
||||||
* breaking it into parts
|
* breaking it into parts
|
||||||
*/
|
*/
|
||||||
static inline void ext4_ext_store_pblock(struct ext4_extent *ex,
|
static inline void ext4_ext_store_pblock(struct ext4_extent *ex,
|
||||||
ext4_fsblk_t pb)
|
ext4_fsblk_t pb)
|
||||||
{
|
{
|
||||||
ex->ee_start_lo = (uint32_t)(pb & 0xffffffff);
|
ex->ee_start_lo = (uint32_t)(pb & 0xffffffff);
|
||||||
ex->ee_start_hi = (uint16_t)((pb >> 31) >> 1) & 0xffff;
|
ex->ee_start_hi = (uint16_t)((pb >> 31) >> 1) & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ext4_idx_store_pblock:
|
* ext4_idx_store_pblock:
|
||||||
* stores a large physical block number into an index struct,
|
* stores a large physical block number into an index struct,
|
||||||
* breaking it into parts
|
* breaking it into parts
|
||||||
*/
|
*/
|
||||||
static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix,
|
static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix,
|
||||||
ext4_fsblk_t pb)
|
ext4_fsblk_t pb)
|
||||||
{
|
{
|
||||||
ix->ei_leaf_lo = (uint32_t)(pb & 0xffffffff);
|
ix->ei_leaf_lo = (uint32_t)(pb & 0xffffffff);
|
||||||
ix->ei_leaf_hi = (uint16_t)((pb >> 31) >> 1) & 0xffff;
|
ix->ei_leaf_hi = (uint16_t)((pb >> 31) >> 1) & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ext4_ext_dirty(icb, handle, inode, path) \
|
#define ext4_ext_dirty(icb, handle, inode, path) \
|
||||||
__ext4_ext_dirty("", __LINE__, (icb), (handle), (inode), (path))
|
__ext4_ext_dirty("", __LINE__, (icb), (handle), (inode), (path))
|
||||||
|
|
||||||
#define INODE_HAS_EXTENT(i) ((i)->i_flags & EXT2_EXTENTS_FL)
|
#define INODE_HAS_EXTENT(i) ((i)->i_flags & EXT2_EXTENTS_FL)
|
||||||
|
|
||||||
static inline uint64_t ext_to_block(EXT4_EXTENT *extent)
|
static inline uint64_t ext_to_block(EXT4_EXTENT *extent)
|
||||||
{
|
{
|
||||||
uint64_t block;
|
uint64_t block;
|
||||||
|
|
||||||
block = (uint64_t)extent->ee_start_lo;
|
block = (uint64_t)extent->ee_start_lo;
|
||||||
block |= ((uint64_t) extent->ee_start_hi << 31) << 1;
|
block |= ((uint64_t) extent->ee_start_hi << 31) << 1;
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t idx_to_block(EXT4_EXTENT_IDX *idx)
|
static inline uint64_t idx_to_block(EXT4_EXTENT_IDX *idx)
|
||||||
{
|
{
|
||||||
uint64_t block;
|
uint64_t block;
|
||||||
|
|
||||||
block = (uint64_t)idx->ei_leaf_lo;
|
block = (uint64_t)idx->ei_leaf_lo;
|
||||||
block |= ((uint64_t) idx->ei_leaf_hi << 31) << 1;
|
block |= ((uint64_t) idx->ei_leaf_hi << 31) << 1;
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ext4_ext_get_blocks(void *icb, handle_t *handle, struct inode *inode, ext4_fsblk_t iblock,
|
int ext4_ext_get_blocks(void *icb, handle_t *handle, struct inode *inode, ext4_fsblk_t iblock,
|
||||||
unsigned long max_blocks, struct buffer_head *bh_result,
|
unsigned long max_blocks, struct buffer_head *bh_result,
|
||||||
int create, int flags);
|
int create, int flags);
|
||||||
int ext4_ext_tree_init(void *icb, handle_t *handle, struct inode *inode);
|
int ext4_ext_tree_init(void *icb, handle_t *handle, struct inode *inode);
|
||||||
int ext4_ext_truncate(void *icb, struct inode *inode, unsigned long start);
|
int ext4_ext_truncate(void *icb, struct inode *inode, unsigned long start);
|
||||||
|
|
||||||
#endif /* _LINUX_EXT4_EXT */
|
#endif /* _LINUX_EXT4_EXT */
|
||||||
|
|||||||
@@ -1,65 +1,65 @@
|
|||||||
#ifndef _EXT4_JBD2_H
|
#ifndef _EXT4_JBD2_H
|
||||||
#define _EXT4_JBD2_H
|
#define _EXT4_JBD2_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrapper functions with which ext4 calls into JBD.
|
* Wrapper functions with which ext4 calls into JBD.
|
||||||
*/
|
*/
|
||||||
void ext4_journal_abort_handle(const char *caller, unsigned int line,
|
void ext4_journal_abort_handle(const char *caller, unsigned int line,
|
||||||
const char *err_fn, struct buffer_head *bh,
|
const char *err_fn, struct buffer_head *bh,
|
||||||
handle_t *handle, int err);
|
handle_t *handle, int err);
|
||||||
|
|
||||||
int __ext4_handle_dirty_super(const char *where, unsigned int line,
|
int __ext4_handle_dirty_super(const char *where, unsigned int line,
|
||||||
handle_t *handle, struct super_block *sb);
|
handle_t *handle, struct super_block *sb);
|
||||||
|
|
||||||
int __ext4_journal_get_write_access(const char *where, unsigned int line,
|
int __ext4_journal_get_write_access(const char *where, unsigned int line,
|
||||||
void *icb, handle_t *handle, struct buffer_head *bh);
|
void *icb, handle_t *handle, struct buffer_head *bh);
|
||||||
|
|
||||||
int __ext4_forget(const char *where, unsigned int line, void *icb, handle_t *handle,
|
int __ext4_forget(const char *where, unsigned int line, void *icb, handle_t *handle,
|
||||||
int is_metadata, struct inode *inode,
|
int is_metadata, struct inode *inode,
|
||||||
struct buffer_head *bh, ext4_fsblk_t blocknr);
|
struct buffer_head *bh, ext4_fsblk_t blocknr);
|
||||||
|
|
||||||
int __ext4_journal_get_create_access(const char *where, unsigned int line,
|
int __ext4_journal_get_create_access(const char *where, unsigned int line,
|
||||||
void *icb, handle_t *handle, struct buffer_head *bh);
|
void *icb, handle_t *handle, struct buffer_head *bh);
|
||||||
|
|
||||||
int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
|
int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
|
||||||
void *icb, handle_t *handle, struct inode *inode,
|
void *icb, handle_t *handle, struct inode *inode,
|
||||||
struct buffer_head *bh);
|
struct buffer_head *bh);
|
||||||
|
|
||||||
#define ext4_journal_get_write_access(handle, icb, bh) \
|
#define ext4_journal_get_write_access(handle, icb, bh) \
|
||||||
__ext4_journal_get_write_access("", __LINE__, (icb), (handle), (bh))
|
__ext4_journal_get_write_access("", __LINE__, (icb), (handle), (bh))
|
||||||
#define ext4_forget(handle, icb, is_metadata, inode, bh, block_nr) \
|
#define ext4_forget(handle, icb, is_metadata, inode, bh, block_nr) \
|
||||||
__ext4_forget("", __LINE__, (icb), (handle), (is_metadata), (inode), \
|
__ext4_forget("", __LINE__, (icb), (handle), (is_metadata), (inode), \
|
||||||
(bh), (block_nr))
|
(bh), (block_nr))
|
||||||
#define ext4_journal_get_create_access(handle, icb, bh) \
|
#define ext4_journal_get_create_access(handle, icb, bh) \
|
||||||
__ext4_journal_get_create_access("", __LINE__, (icb), (handle), (bh))
|
__ext4_journal_get_create_access("", __LINE__, (icb), (handle), (bh))
|
||||||
#define ext4_handle_dirty_metadata(handle, icb, inode, bh) \
|
#define ext4_handle_dirty_metadata(handle, icb, inode, bh) \
|
||||||
__ext4_handle_dirty_metadata("", __LINE__, (icb), (handle), (inode), \
|
__ext4_handle_dirty_metadata("", __LINE__, (icb), (handle), (inode), \
|
||||||
(bh))
|
(bh))
|
||||||
|
|
||||||
handle_t *__ext4_journal_start_sb(void *icb, struct super_block *sb, unsigned int line,
|
handle_t *__ext4_journal_start_sb(void *icb, struct super_block *sb, unsigned int line,
|
||||||
int type, int blocks, int rsv_blocks);
|
int type, int blocks, int rsv_blocks);
|
||||||
int __ext4_journal_stop(const char *where, unsigned int line, void *icb, handle_t *handle);
|
int __ext4_journal_stop(const char *where, unsigned int line, void *icb, handle_t *handle);
|
||||||
|
|
||||||
#define ext4_journal_start_sb(icb, sb, type, nblocks) \
|
#define ext4_journal_start_sb(icb, sb, type, nblocks) \
|
||||||
__ext4_journal_start_sb((icb), (sb), __LINE__, (type), (nblocks), 0)
|
__ext4_journal_start_sb((icb), (sb), __LINE__, (type), (nblocks), 0)
|
||||||
|
|
||||||
#define ext4_journal_start(icb, inode, type, nblocks) \
|
#define ext4_journal_start(icb, inode, type, nblocks) \
|
||||||
__ext4_journal_start((icb), (inode), __LINE__, (type), (nblocks), 0)
|
__ext4_journal_start((icb), (inode), __LINE__, (type), (nblocks), 0)
|
||||||
|
|
||||||
static inline handle_t *__ext4_journal_start(void *icb, struct inode *inode,
|
static inline handle_t *__ext4_journal_start(void *icb, struct inode *inode,
|
||||||
unsigned int line, int type,
|
unsigned int line, int type,
|
||||||
int blocks, int rsv_blocks)
|
int blocks, int rsv_blocks)
|
||||||
{
|
{
|
||||||
return __ext4_journal_start_sb(icb, inode->i_sb, line, type, blocks,
|
return __ext4_journal_start_sb(icb, inode->i_sb, line, type, blocks,
|
||||||
rsv_blocks);
|
rsv_blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ext4_journal_stop(icb, handle) \
|
#define ext4_journal_stop(icb, handle) \
|
||||||
__ext4_journal_stop("", __LINE__, (icb), (handle))
|
__ext4_journal_stop("", __LINE__, (icb), (handle))
|
||||||
|
|
||||||
static inline int ext4_journal_extend(void *icb, handle_t *handle, int nblocks)
|
static inline int ext4_journal_extend(void *icb, handle_t *handle, int nblocks)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,205 +1,205 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 Grzegorz Kostka (kostka.grzegorz@gmail.com)
|
* Copyright (c) 2015 Grzegorz Kostka (kostka.grzegorz@gmail.com)
|
||||||
* Copyright (c) 2015 Kaho Ng (ngkaho1234@gmail.com)
|
* Copyright (c) 2015 Kaho Ng (ngkaho1234@gmail.com)
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
* are met:
|
* are met:
|
||||||
*
|
*
|
||||||
* - Redistributions of source code must retain the above copyright
|
* - Redistributions of source code must retain the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* - Redistributions in binary form must reproduce the above copyright
|
* - Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* - The name of the author may not be used to endorse or promote products
|
* - The name of the author may not be used to endorse or promote products
|
||||||
* derived from this software without specific prior written permission.
|
* derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @addtogroup lwext4
|
/** @addtogroup lwext4
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* @file ext4_xattr.h
|
* @file ext4_xattr.h
|
||||||
* @brief Extended Attribute manipulation.
|
* @brief Extended Attribute manipulation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXT4_XATTR_H_
|
#ifndef EXT4_XATTR_H_
|
||||||
#define EXT4_XATTR_H_
|
#define EXT4_XATTR_H_
|
||||||
|
|
||||||
#include <ext2fs.h>
|
#include <ext2fs.h>
|
||||||
#include <linux/rbtree.h>
|
#include <linux/rbtree.h>
|
||||||
|
|
||||||
/* Extended Attribute(EA) */
|
/* Extended Attribute(EA) */
|
||||||
|
|
||||||
/* Magic value in attribute blocks */
|
/* Magic value in attribute blocks */
|
||||||
#define EXT4_XATTR_MAGIC 0xEA020000
|
#define EXT4_XATTR_MAGIC 0xEA020000
|
||||||
|
|
||||||
/* Maximum number of references to one attribute block */
|
/* Maximum number of references to one attribute block */
|
||||||
#define EXT4_XATTR_REFCOUNT_MAX 1024
|
#define EXT4_XATTR_REFCOUNT_MAX 1024
|
||||||
|
|
||||||
/* Name indexes */
|
/* Name indexes */
|
||||||
#define EXT4_XATTR_INDEX_USER 1
|
#define EXT4_XATTR_INDEX_USER 1
|
||||||
#define EXT4_XATTR_INDEX_POSIX_ACL_ACCESS 2
|
#define EXT4_XATTR_INDEX_POSIX_ACL_ACCESS 2
|
||||||
#define EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT 3
|
#define EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT 3
|
||||||
#define EXT4_XATTR_INDEX_TRUSTED 4
|
#define EXT4_XATTR_INDEX_TRUSTED 4
|
||||||
#define EXT4_XATTR_INDEX_LUSTRE 5
|
#define EXT4_XATTR_INDEX_LUSTRE 5
|
||||||
#define EXT4_XATTR_INDEX_SECURITY 6
|
#define EXT4_XATTR_INDEX_SECURITY 6
|
||||||
#define EXT4_XATTR_INDEX_SYSTEM 7
|
#define EXT4_XATTR_INDEX_SYSTEM 7
|
||||||
#define EXT4_XATTR_INDEX_RICHACL 8
|
#define EXT4_XATTR_INDEX_RICHACL 8
|
||||||
#define EXT4_XATTR_INDEX_ENCRYPTION 9
|
#define EXT4_XATTR_INDEX_ENCRYPTION 9
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
struct ext4_xattr_header {
|
struct ext4_xattr_header {
|
||||||
__le32 h_magic; /* magic number for identification */
|
__le32 h_magic; /* magic number for identification */
|
||||||
__le32 h_refcount; /* reference count */
|
__le32 h_refcount; /* reference count */
|
||||||
__le32 h_blocks; /* number of disk blocks used */
|
__le32 h_blocks; /* number of disk blocks used */
|
||||||
__le32 h_hash; /* hash value of all attributes */
|
__le32 h_hash; /* hash value of all attributes */
|
||||||
__le32 h_checksum; /* crc32c(uuid+id+xattrblock) */
|
__le32 h_checksum; /* crc32c(uuid+id+xattrblock) */
|
||||||
/* id = inum if refcount=1, blknum otherwise */
|
/* id = inum if refcount=1, blknum otherwise */
|
||||||
__le32 h_reserved[3]; /* zero right now */
|
__le32 h_reserved[3]; /* zero right now */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ext4_xattr_ibody_header {
|
struct ext4_xattr_ibody_header {
|
||||||
__le32 h_magic; /* magic number for identification */
|
__le32 h_magic; /* magic number for identification */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ext4_xattr_entry {
|
struct ext4_xattr_entry {
|
||||||
__u8 e_name_len; /* length of name */
|
__u8 e_name_len; /* length of name */
|
||||||
__u8 e_name_index; /* attribute name index */
|
__u8 e_name_index; /* attribute name index */
|
||||||
__le16 e_value_offs; /* offset in disk block of value */
|
__le16 e_value_offs; /* offset in disk block of value */
|
||||||
__le32 e_value_block; /* disk block attribute is stored on (n/i) */
|
__le32 e_value_block; /* disk block attribute is stored on (n/i) */
|
||||||
__le32 e_value_size; /* size of attribute value */
|
__le32 e_value_size; /* size of attribute value */
|
||||||
__le32 e_hash; /* hash value of name and value */
|
__le32 e_hash; /* hash value of name and value */
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
//#define EXT4_GOOD_OLD_INODE_SIZE EXT2_GOOD_OLD_INODE_SIZE
|
//#define EXT4_GOOD_OLD_INODE_SIZE EXT2_GOOD_OLD_INODE_SIZE
|
||||||
|
|
||||||
#define EXT4_XATTR_PAD_BITS 2
|
#define EXT4_XATTR_PAD_BITS 2
|
||||||
#define EXT4_XATTR_PAD (1<<EXT4_XATTR_PAD_BITS)
|
#define EXT4_XATTR_PAD (1<<EXT4_XATTR_PAD_BITS)
|
||||||
#define EXT4_XATTR_ROUND (EXT4_XATTR_PAD-1)
|
#define EXT4_XATTR_ROUND (EXT4_XATTR_PAD-1)
|
||||||
#define EXT4_XATTR_LEN(name_len) \
|
#define EXT4_XATTR_LEN(name_len) \
|
||||||
(((name_len) + EXT4_XATTR_ROUND + \
|
(((name_len) + EXT4_XATTR_ROUND + \
|
||||||
sizeof(struct ext4_xattr_entry)) & ~EXT4_XATTR_ROUND)
|
sizeof(struct ext4_xattr_entry)) & ~EXT4_XATTR_ROUND)
|
||||||
#define EXT4_XATTR_NEXT(entry) \
|
#define EXT4_XATTR_NEXT(entry) \
|
||||||
((struct ext4_xattr_entry *)( \
|
((struct ext4_xattr_entry *)( \
|
||||||
(char *)(entry) + EXT4_XATTR_LEN((entry)->e_name_len)))
|
(char *)(entry) + EXT4_XATTR_LEN((entry)->e_name_len)))
|
||||||
#define EXT4_XATTR_SIZE(size) \
|
#define EXT4_XATTR_SIZE(size) \
|
||||||
(((size) + EXT4_XATTR_ROUND) & ~EXT4_XATTR_ROUND)
|
(((size) + EXT4_XATTR_ROUND) & ~EXT4_XATTR_ROUND)
|
||||||
#define EXT4_XATTR_NAME(entry) \
|
#define EXT4_XATTR_NAME(entry) \
|
||||||
((char *)((entry) + 1))
|
((char *)((entry) + 1))
|
||||||
|
|
||||||
#define EXT4_XATTR_IHDR(raw_inode) \
|
#define EXT4_XATTR_IHDR(raw_inode) \
|
||||||
((struct ext4_xattr_ibody_header *) \
|
((struct ext4_xattr_ibody_header *) \
|
||||||
((char *)raw_inode + \
|
((char *)raw_inode + \
|
||||||
EXT4_GOOD_OLD_INODE_SIZE + \
|
EXT4_GOOD_OLD_INODE_SIZE + \
|
||||||
(raw_inode)->i_extra_isize))
|
(raw_inode)->i_extra_isize))
|
||||||
#define EXT4_XATTR_IFIRST(hdr) \
|
#define EXT4_XATTR_IFIRST(hdr) \
|
||||||
((struct ext4_xattr_entry *)((hdr)+1))
|
((struct ext4_xattr_entry *)((hdr)+1))
|
||||||
|
|
||||||
#define EXT4_XATTR_BHDR(block) \
|
#define EXT4_XATTR_BHDR(block) \
|
||||||
((struct ext4_xattr_header *)((block)->b_data))
|
((struct ext4_xattr_header *)((block)->b_data))
|
||||||
#define EXT4_XATTR_ENTRY(ptr) \
|
#define EXT4_XATTR_ENTRY(ptr) \
|
||||||
((struct ext4_xattr_entry *)(ptr))
|
((struct ext4_xattr_entry *)(ptr))
|
||||||
#define EXT4_XATTR_BFIRST(block) \
|
#define EXT4_XATTR_BFIRST(block) \
|
||||||
EXT4_XATTR_ENTRY(EXT4_XATTR_BHDR(block)+1)
|
EXT4_XATTR_ENTRY(EXT4_XATTR_BHDR(block)+1)
|
||||||
#define EXT4_XATTR_IS_LAST_ENTRY(entry) \
|
#define EXT4_XATTR_IS_LAST_ENTRY(entry) \
|
||||||
(*(__le32 *)(entry) == 0)
|
(*(__le32 *)(entry) == 0)
|
||||||
|
|
||||||
#define EXT4_ZERO_XATTR_VALUE ((void *)-1)
|
#define EXT4_ZERO_XATTR_VALUE ((void *)-1)
|
||||||
|
|
||||||
|
|
||||||
struct ext4_xattr_item {
|
struct ext4_xattr_item {
|
||||||
/* This attribute should be stored in inode body */
|
/* This attribute should be stored in inode body */
|
||||||
BOOL in_inode;
|
BOOL in_inode;
|
||||||
BOOL is_data;
|
BOOL is_data;
|
||||||
|
|
||||||
__u8 name_index;
|
__u8 name_index;
|
||||||
char *name;
|
char *name;
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
void *data;
|
void *data;
|
||||||
size_t data_size;
|
size_t data_size;
|
||||||
|
|
||||||
struct rb_node node;
|
struct rb_node node;
|
||||||
struct list_head list_node;
|
struct list_head list_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ext4_xattr_ref {
|
struct ext4_xattr_ref {
|
||||||
PEXT2_IRP_CONTEXT IrpContext;
|
PEXT2_IRP_CONTEXT IrpContext;
|
||||||
BOOL block_loaded;
|
BOOL block_loaded;
|
||||||
struct buffer_head *block_bh;
|
struct buffer_head *block_bh;
|
||||||
PEXT2_MCB inode_ref;
|
PEXT2_MCB inode_ref;
|
||||||
|
|
||||||
PEXT2_INODE OnDiskInode;
|
PEXT2_INODE OnDiskInode;
|
||||||
BOOL IsOnDiskInodeDirty;
|
BOOL IsOnDiskInodeDirty;
|
||||||
|
|
||||||
BOOL dirty;
|
BOOL dirty;
|
||||||
size_t ea_size;
|
size_t ea_size;
|
||||||
size_t inode_size_rem;
|
size_t inode_size_rem;
|
||||||
size_t block_size_rem;
|
size_t block_size_rem;
|
||||||
PEXT2_VCB fs;
|
PEXT2_VCB fs;
|
||||||
|
|
||||||
void *iter_arg;
|
void *iter_arg;
|
||||||
struct ext4_xattr_item *iter_from;
|
struct ext4_xattr_item *iter_from;
|
||||||
|
|
||||||
struct rb_root root;
|
struct rb_root root;
|
||||||
struct list_head ordered_list;
|
struct list_head ordered_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EXT4_XATTR_ITERATE_CONT 0
|
#define EXT4_XATTR_ITERATE_CONT 0
|
||||||
#define EXT4_XATTR_ITERATE_STOP 1
|
#define EXT4_XATTR_ITERATE_STOP 1
|
||||||
#define EXT4_XATTR_ITERATE_PAUSE 2
|
#define EXT4_XATTR_ITERATE_PAUSE 2
|
||||||
|
|
||||||
int ext4_fs_get_xattr_ref(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB fs, PEXT2_MCB inode_ref,
|
int ext4_fs_get_xattr_ref(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB fs, PEXT2_MCB inode_ref,
|
||||||
struct ext4_xattr_ref *ref);
|
struct ext4_xattr_ref *ref);
|
||||||
|
|
||||||
int ext4_fs_put_xattr_ref(struct ext4_xattr_ref *ref);
|
int ext4_fs_put_xattr_ref(struct ext4_xattr_ref *ref);
|
||||||
|
|
||||||
int ext4_fs_set_xattr(struct ext4_xattr_ref *ref, __u8 name_index,
|
int ext4_fs_set_xattr(struct ext4_xattr_ref *ref, __u8 name_index,
|
||||||
const char *name, size_t name_len, const void *data,
|
const char *name, size_t name_len, const void *data,
|
||||||
size_t data_size, BOOL replace);
|
size_t data_size, BOOL replace);
|
||||||
|
|
||||||
int ext4_fs_set_xattr_ordered(struct ext4_xattr_ref *ref, __u8 name_index,
|
int ext4_fs_set_xattr_ordered(struct ext4_xattr_ref *ref, __u8 name_index,
|
||||||
const char *name, size_t name_len, const void *data,
|
const char *name, size_t name_len, const void *data,
|
||||||
size_t data_size);
|
size_t data_size);
|
||||||
|
|
||||||
int ext4_fs_remove_xattr(struct ext4_xattr_ref *ref, __u8 name_index,
|
int ext4_fs_remove_xattr(struct ext4_xattr_ref *ref, __u8 name_index,
|
||||||
const char *name, size_t name_len);
|
const char *name, size_t name_len);
|
||||||
|
|
||||||
int ext4_fs_get_xattr(struct ext4_xattr_ref *ref, __u8 name_index,
|
int ext4_fs_get_xattr(struct ext4_xattr_ref *ref, __u8 name_index,
|
||||||
const char *name, size_t name_len, void *buf,
|
const char *name, size_t name_len, void *buf,
|
||||||
size_t buf_size, size_t *data_size);
|
size_t buf_size, size_t *data_size);
|
||||||
|
|
||||||
void ext4_fs_xattr_iterate(struct ext4_xattr_ref *ref,
|
void ext4_fs_xattr_iterate(struct ext4_xattr_ref *ref,
|
||||||
int(*iter)(struct ext4_xattr_ref *ref,
|
int(*iter)(struct ext4_xattr_ref *ref,
|
||||||
struct ext4_xattr_item *item,
|
struct ext4_xattr_item *item,
|
||||||
BOOL is_last));
|
BOOL is_last));
|
||||||
|
|
||||||
void ext4_fs_xattr_iterate_reset(struct ext4_xattr_ref *ref);
|
void ext4_fs_xattr_iterate_reset(struct ext4_xattr_ref *ref);
|
||||||
|
|
||||||
const char *ext4_extract_xattr_name(const char *full_name, size_t full_name_len,
|
const char *ext4_extract_xattr_name(const char *full_name, size_t full_name_len,
|
||||||
__u8 *name_index, size_t *name_len,
|
__u8 *name_index, size_t *name_len,
|
||||||
BOOL *found);
|
BOOL *found);
|
||||||
|
|
||||||
const char *ext4_get_xattr_name_prefix(__u8 name_index,
|
const char *ext4_get_xattr_name_prefix(__u8 name_index,
|
||||||
size_t *ret_prefix_len);
|
size_t *ret_prefix_len);
|
||||||
|
|
||||||
void ext4_xattr_purge_items(struct ext4_xattr_ref *xattr_ref);
|
void ext4_xattr_purge_items(struct ext4_xattr_ref *xattr_ref);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,160 +1,160 @@
|
|||||||
#ifndef _LINUX_FS_INCLUDE_
|
#ifndef _LINUX_FS_INCLUDE_
|
||||||
#define _LINUX_FS_INCLUDE_
|
#define _LINUX_FS_INCLUDE_
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
#include <linux/rbtree.h>
|
#include <linux/rbtree.h>
|
||||||
|
|
||||||
//
|
//
|
||||||
// kdev
|
// kdev
|
||||||
//
|
//
|
||||||
|
|
||||||
#define NODEV 0
|
#define NODEV 0
|
||||||
|
|
||||||
typedef struct block_device * kdev_t;
|
typedef struct block_device * kdev_t;
|
||||||
|
|
||||||
#define MINORBITS 8
|
#define MINORBITS 8
|
||||||
#define MINORMASK ((1U << MINORBITS) - 1)
|
#define MINORMASK ((1U << MINORBITS) - 1)
|
||||||
|
|
||||||
#define MAJOR(dev) ((unsigned int)((int)(dev) >> MINORBITS))
|
#define MAJOR(dev) ((unsigned int)((int)(dev) >> MINORBITS))
|
||||||
#define MINOR(dev) ((unsigned int)((int)(dev) & MINORMASK))
|
#define MINOR(dev) ((unsigned int)((int)(dev) & MINORMASK))
|
||||||
|
|
||||||
static inline unsigned int kdev_t_to_nr(kdev_t dev) {
|
static inline unsigned int kdev_t_to_nr(kdev_t dev) {
|
||||||
/*return (unsigned int)(MAJOR(dev)<<8) | MINOR(dev);*/
|
/*return (unsigned int)(MAJOR(dev)<<8) | MINOR(dev);*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NODEV 0
|
#define NODEV 0
|
||||||
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
|
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
|
||||||
|
|
||||||
static inline kdev_t to_kdev_t(int dev)
|
static inline kdev_t to_kdev_t(int dev)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
int major, minor;
|
int major, minor;
|
||||||
#if 0
|
#if 0
|
||||||
major = (dev >> 16);
|
major = (dev >> 16);
|
||||||
if (!major) {
|
if (!major) {
|
||||||
major = (dev >> 8);
|
major = (dev >> 8);
|
||||||
minor = (dev & 0xff);
|
minor = (dev & 0xff);
|
||||||
} else
|
} else
|
||||||
minor = (dev & 0xffff);
|
minor = (dev & 0xffff);
|
||||||
#else
|
#else
|
||||||
major = (dev >> 8);
|
major = (dev >> 8);
|
||||||
minor = (dev & 0xff);
|
minor = (dev & 0xff);
|
||||||
#endif
|
#endif
|
||||||
return (kdev_t) MKDEV(major, minor);
|
return (kdev_t) MKDEV(major, minor);
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// file system specific structures
|
// file system specific structures
|
||||||
//
|
//
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kernel pointers have redundant information, so we can use a
|
* Kernel pointers have redundant information, so we can use a
|
||||||
* scheme where we can return either an error code or a dentry
|
* scheme where we can return either an error code or a dentry
|
||||||
* pointer with the same return value.
|
* pointer with the same return value.
|
||||||
*
|
*
|
||||||
* This should be a per-architecture thing, to allow different
|
* This should be a per-architecture thing, to allow different
|
||||||
* error and pointer decisions.
|
* error and pointer decisions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct super_block {
|
struct super_block {
|
||||||
unsigned long s_magic;
|
unsigned long s_magic;
|
||||||
unsigned long s_flags;
|
unsigned long s_flags;
|
||||||
unsigned long s_blocksize; /* blocksize */
|
unsigned long s_blocksize; /* blocksize */
|
||||||
unsigned long long s_maxbytes;
|
unsigned long long s_maxbytes;
|
||||||
unsigned char s_blocksize_bits; /* bits of blocksize */
|
unsigned char s_blocksize_bits; /* bits of blocksize */
|
||||||
unsigned char s_dirt; /* any thing */
|
unsigned char s_dirt; /* any thing */
|
||||||
char s_id[30]; /* id string */
|
char s_id[30]; /* id string */
|
||||||
kdev_t s_bdev; /* block_device */
|
kdev_t s_bdev; /* block_device */
|
||||||
void * s_priv; /* EXT2_VCB */
|
void * s_priv; /* EXT2_VCB */
|
||||||
struct dentry *s_root;
|
struct dentry *s_root;
|
||||||
void *s_fs_info;
|
void *s_fs_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct inode {
|
struct inode {
|
||||||
__u32 i_ino; /* inode number */
|
__u32 i_ino; /* inode number */
|
||||||
loff_t i_size; /* size */
|
loff_t i_size; /* size */
|
||||||
__u32 i_atime; /* Access time */
|
__u32 i_atime; /* Access time */
|
||||||
__u32 i_ctime; /* Creation time */
|
__u32 i_ctime; /* Creation time */
|
||||||
__u32 i_mtime; /* Modification time */
|
__u32 i_mtime; /* Modification time */
|
||||||
__u32 i_dtime; /* Deletion Time */
|
__u32 i_dtime; /* Deletion Time */
|
||||||
__u64 i_blocks;
|
__u64 i_blocks;
|
||||||
__u32 i_block[15];
|
__u32 i_block[15];
|
||||||
umode_t i_mode; /* mode */
|
umode_t i_mode; /* mode */
|
||||||
uid_t i_uid;
|
uid_t i_uid;
|
||||||
gid_t i_gid;
|
gid_t i_gid;
|
||||||
atomic_t i_count; /* ref count */
|
atomic_t i_count; /* ref count */
|
||||||
__u16 i_nlink;
|
__u16 i_nlink;
|
||||||
__u32 i_generation;
|
__u32 i_generation;
|
||||||
__u32 i_version;
|
__u32 i_version;
|
||||||
__u32 i_flags;
|
__u32 i_flags;
|
||||||
|
|
||||||
struct super_block *i_sb; /* super_block */
|
struct super_block *i_sb; /* super_block */
|
||||||
void *i_priv; /* EXT2_MCB */
|
void *i_priv; /* EXT2_MCB */
|
||||||
|
|
||||||
__u16 i_extra_isize; /* extra fields' size */
|
__u16 i_extra_isize; /* extra fields' size */
|
||||||
__u64 i_file_acl;
|
__u64 i_file_acl;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Inode state bits
|
// Inode state bits
|
||||||
//
|
//
|
||||||
|
|
||||||
#define I_DIRTY_SYNC 1 /* Not dirty enough for O_DATASYNC */
|
#define I_DIRTY_SYNC 1 /* Not dirty enough for O_DATASYNC */
|
||||||
#define I_DIRTY_DATASYNC 2 /* Data-related inode changes pending */
|
#define I_DIRTY_DATASYNC 2 /* Data-related inode changes pending */
|
||||||
#define I_DIRTY_PAGES 4 /* Data-related inode changes pending */
|
#define I_DIRTY_PAGES 4 /* Data-related inode changes pending */
|
||||||
#define I_LOCK 8
|
#define I_LOCK 8
|
||||||
#define I_FREEING 16
|
#define I_FREEING 16
|
||||||
#define I_CLEAR 32
|
#define I_CLEAR 32
|
||||||
|
|
||||||
#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
|
#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
|
||||||
|
|
||||||
|
|
||||||
struct dentry {
|
struct dentry {
|
||||||
atomic_t d_count;
|
atomic_t d_count;
|
||||||
struct {
|
struct {
|
||||||
int len;
|
int len;
|
||||||
char *name;
|
char *name;
|
||||||
} d_name;
|
} d_name;
|
||||||
struct inode *d_inode;
|
struct inode *d_inode;
|
||||||
struct dentry *d_parent;
|
struct dentry *d_parent;
|
||||||
void *d_fsdata;
|
void *d_fsdata;
|
||||||
struct super_block *d_sb;
|
struct super_block *d_sb;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct file {
|
struct file {
|
||||||
|
|
||||||
unsigned int f_flags;
|
unsigned int f_flags;
|
||||||
umode_t f_mode;
|
umode_t f_mode;
|
||||||
__u32 f_version;
|
__u32 f_version;
|
||||||
__int64 f_size;
|
__int64 f_size;
|
||||||
loff_t f_pos;
|
loff_t f_pos;
|
||||||
struct dentry *f_dentry;
|
struct dentry *f_dentry;
|
||||||
void *private_data;
|
void *private_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* File types
|
* File types
|
||||||
*
|
*
|
||||||
* NOTE! These match bits 12..15 of stat.st_mode
|
* NOTE! These match bits 12..15 of stat.st_mode
|
||||||
* (ie "(i_mode >> 12) & 15").
|
* (ie "(i_mode >> 12) & 15").
|
||||||
*/
|
*/
|
||||||
#define DT_UNKNOWN 0
|
#define DT_UNKNOWN 0
|
||||||
#define DT_FIFO 1
|
#define DT_FIFO 1
|
||||||
#define DT_CHR 2
|
#define DT_CHR 2
|
||||||
#define DT_DIR 4
|
#define DT_DIR 4
|
||||||
#define DT_BLK 6
|
#define DT_BLK 6
|
||||||
#define DT_REG 8
|
#define DT_REG 8
|
||||||
#define DT_LNK 10
|
#define DT_LNK 10
|
||||||
#define DT_SOCK 12
|
#define DT_SOCK 12
|
||||||
#define DT_WHT 14
|
#define DT_WHT 14
|
||||||
|
|
||||||
void iget(struct inode *inode);
|
void iget(struct inode *inode);
|
||||||
void iput(struct inode *inode);
|
void iput(struct inode *inode);
|
||||||
ULONGLONG bmap(struct inode *i, ULONGLONG b);
|
ULONGLONG bmap(struct inode *i, ULONGLONG b);
|
||||||
|
|
||||||
#endif /*_LINUX_FS_INCLUDE_*/
|
#endif /*_LINUX_FS_INCLUDE_*/
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
/*
|
/*
|
||||||
* linux/fs/ext4/group.h
|
* linux/fs/ext4/group.h
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007 Cluster File Systems, Inc
|
* Copyright (C) 2007 Cluster File Systems, Inc
|
||||||
*
|
*
|
||||||
* Author: Andreas Dilger <adilger@clusterfs.com>
|
* Author: Andreas Dilger <adilger@clusterfs.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LINUX_EXT4_GROUP_H
|
#ifndef _LINUX_EXT4_GROUP_H
|
||||||
#define _LINUX_EXT4_GROUP_H
|
#define _LINUX_EXT4_GROUP_H
|
||||||
|
|
||||||
extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group,
|
extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group,
|
||||||
struct ext4_group_desc *gdp);
|
struct ext4_group_desc *gdp);
|
||||||
extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group,
|
extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group,
|
||||||
struct ext4_group_desc *gdp);
|
struct ext4_group_desc *gdp);
|
||||||
struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
|
struct buffer_head *ext4_read_block_bitmap(struct super_block *sb,
|
||||||
ext4_group_t block_group);
|
ext4_group_t block_group);
|
||||||
extern unsigned ext4_init_block_bitmap(struct super_block *sb,
|
extern unsigned ext4_init_block_bitmap(struct super_block *sb,
|
||||||
struct buffer_head *bh,
|
struct buffer_head *bh,
|
||||||
ext4_group_t group,
|
ext4_group_t group,
|
||||||
struct ext4_group_desc *desc);
|
struct ext4_group_desc *desc);
|
||||||
#define ext4_free_blocks_after_init(sb, group, desc) \
|
#define ext4_free_blocks_after_init(sb, group, desc) \
|
||||||
ext4_init_block_bitmap(sb, NULL, group, desc)
|
ext4_init_block_bitmap(sb, NULL, group, desc)
|
||||||
extern unsigned ext4_init_inode_bitmap(struct super_block *sb,
|
extern unsigned ext4_init_inode_bitmap(struct super_block *sb,
|
||||||
struct buffer_head *bh,
|
struct buffer_head *bh,
|
||||||
ext4_group_t group,
|
ext4_group_t group,
|
||||||
struct ext4_group_desc *desc);
|
struct ext4_group_desc *desc);
|
||||||
extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
|
extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap);
|
||||||
#endif /* _LINUX_EXT4_GROUP_H */
|
#endif /* _LINUX_EXT4_GROUP_H */
|
||||||
|
|||||||
@@ -1,92 +1,92 @@
|
|||||||
/*
|
/*
|
||||||
* include/linux/journal-head.h
|
* include/linux/journal-head.h
|
||||||
*
|
*
|
||||||
* buffer_head fields for JBD
|
* buffer_head fields for JBD
|
||||||
*
|
*
|
||||||
* 27 May 2001 Andrew Morton <akpm@digeo.com>
|
* 27 May 2001 Andrew Morton <akpm@digeo.com>
|
||||||
* Created - pulled out of fs.h
|
* Created - pulled out of fs.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef JOURNAL_HEAD_H_INCLUDED
|
#ifndef JOURNAL_HEAD_H_INCLUDED
|
||||||
#define JOURNAL_HEAD_H_INCLUDED
|
#define JOURNAL_HEAD_H_INCLUDED
|
||||||
|
|
||||||
typedef unsigned int tid_t; /* Unique transaction ID */
|
typedef unsigned int tid_t; /* Unique transaction ID */
|
||||||
typedef struct transaction_s transaction_t; /* Compound transaction type */
|
typedef struct transaction_s transaction_t; /* Compound transaction type */
|
||||||
struct buffer_head;
|
struct buffer_head;
|
||||||
|
|
||||||
struct journal_head {
|
struct journal_head {
|
||||||
/*
|
/*
|
||||||
* Points back to our buffer_head. [jbd_lock_bh_journal_head()]
|
* Points back to our buffer_head. [jbd_lock_bh_journal_head()]
|
||||||
*/
|
*/
|
||||||
struct buffer_head *b_bh;
|
struct buffer_head *b_bh;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reference count - see description in journal.c
|
* Reference count - see description in journal.c
|
||||||
* [jbd_lock_bh_journal_head()]
|
* [jbd_lock_bh_journal_head()]
|
||||||
*/
|
*/
|
||||||
int b_jcount;
|
int b_jcount;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Journalling list for this buffer [jbd_lock_bh_state()]
|
* Journalling list for this buffer [jbd_lock_bh_state()]
|
||||||
*/
|
*/
|
||||||
unsigned b_jlist;
|
unsigned b_jlist;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This flag signals the buffer has been modified by
|
* This flag signals the buffer has been modified by
|
||||||
* the currently running transaction
|
* the currently running transaction
|
||||||
* [jbd_lock_bh_state()]
|
* [jbd_lock_bh_state()]
|
||||||
*/
|
*/
|
||||||
unsigned b_modified;
|
unsigned b_modified;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy of the buffer data frozen for writing to the log.
|
* Copy of the buffer data frozen for writing to the log.
|
||||||
* [jbd_lock_bh_state()]
|
* [jbd_lock_bh_state()]
|
||||||
*/
|
*/
|
||||||
char *b_frozen_data;
|
char *b_frozen_data;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pointer to a saved copy of the buffer containing no uncommitted
|
* Pointer to a saved copy of the buffer containing no uncommitted
|
||||||
* deallocation references, so that allocations can avoid overwriting
|
* deallocation references, so that allocations can avoid overwriting
|
||||||
* uncommitted deletes. [jbd_lock_bh_state()]
|
* uncommitted deletes. [jbd_lock_bh_state()]
|
||||||
*/
|
*/
|
||||||
char *b_committed_data;
|
char *b_committed_data;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pointer to the compound transaction which owns this buffer's
|
* Pointer to the compound transaction which owns this buffer's
|
||||||
* metadata: either the running transaction or the committing
|
* metadata: either the running transaction or the committing
|
||||||
* transaction (if there is one). Only applies to buffers on a
|
* transaction (if there is one). Only applies to buffers on a
|
||||||
* transaction's data or metadata journaling list.
|
* transaction's data or metadata journaling list.
|
||||||
* [j_list_lock] [jbd_lock_bh_state()]
|
* [j_list_lock] [jbd_lock_bh_state()]
|
||||||
*/
|
*/
|
||||||
transaction_t *b_transaction;
|
transaction_t *b_transaction;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pointer to the running compound transaction which is currently
|
* Pointer to the running compound transaction which is currently
|
||||||
* modifying the buffer's metadata, if there was already a transaction
|
* modifying the buffer's metadata, if there was already a transaction
|
||||||
* committing it when the new transaction touched it.
|
* committing it when the new transaction touched it.
|
||||||
* [t_list_lock] [jbd_lock_bh_state()]
|
* [t_list_lock] [jbd_lock_bh_state()]
|
||||||
*/
|
*/
|
||||||
transaction_t *b_next_transaction;
|
transaction_t *b_next_transaction;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Doubly-linked list of buffers on a transaction's data, metadata or
|
* Doubly-linked list of buffers on a transaction's data, metadata or
|
||||||
* forget queue. [t_list_lock] [jbd_lock_bh_state()]
|
* forget queue. [t_list_lock] [jbd_lock_bh_state()]
|
||||||
*/
|
*/
|
||||||
struct journal_head *b_tnext, *b_tprev;
|
struct journal_head *b_tnext, *b_tprev;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pointer to the compound transaction against which this buffer
|
* Pointer to the compound transaction against which this buffer
|
||||||
* is checkpointed. Only dirty buffers can be checkpointed.
|
* is checkpointed. Only dirty buffers can be checkpointed.
|
||||||
* [j_list_lock]
|
* [j_list_lock]
|
||||||
*/
|
*/
|
||||||
transaction_t *b_cp_transaction;
|
transaction_t *b_cp_transaction;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Doubly-linked list of buffers still remaining to be flushed
|
* Doubly-linked list of buffers still remaining to be flushed
|
||||||
* before an old transaction can be checkpointed.
|
* before an old transaction can be checkpointed.
|
||||||
* [j_list_lock]
|
* [j_list_lock]
|
||||||
*/
|
*/
|
||||||
struct journal_head *b_cpnext, *b_cpprev;
|
struct journal_head *b_cpnext, *b_cpprev;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* JOURNAL_HEAD_H_INCLUDED */
|
#endif /* JOURNAL_HEAD_H_INCLUDED */
|
||||||
|
|||||||
@@ -1,255 +1,255 @@
|
|||||||
#ifndef __LINUX_LIST_H__
|
#ifndef __LINUX_LIST_H__
|
||||||
#define __LINUX_LIST_H__
|
#define __LINUX_LIST_H__
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Simple doubly linked list implementation.
|
* Simple doubly linked list implementation.
|
||||||
*
|
*
|
||||||
* Some of the internal functions ("__xxx") are useful when
|
* Some of the internal functions ("__xxx") are useful when
|
||||||
* manipulating whole lists rather than single entries, as
|
* manipulating whole lists rather than single entries, as
|
||||||
* sometimes we already know the next/prev entries and we can
|
* sometimes we already know the next/prev entries and we can
|
||||||
* generate better code by using them directly rather than
|
* generate better code by using them directly rather than
|
||||||
* using the generic single-entry routines.
|
* using the generic single-entry routines.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define prefetch(a) ((void *)a)
|
#define prefetch(a) ((void *)a)
|
||||||
|
|
||||||
struct list_head {
|
struct list_head {
|
||||||
struct list_head *next, *prev;
|
struct list_head *next, *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||||
|
|
||||||
#define LIST_HEAD(name) \
|
#define LIST_HEAD(name) \
|
||||||
struct list_head name = LIST_HEAD_INIT(name)
|
struct list_head name = LIST_HEAD_INIT(name)
|
||||||
|
|
||||||
static inline void INIT_LIST_HEAD(struct list_head *list)
|
static inline void INIT_LIST_HEAD(struct list_head *list)
|
||||||
{
|
{
|
||||||
list->next = list;
|
list->next = list;
|
||||||
list->prev = list;
|
list->prev = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert a new entry between two known consecutive entries.
|
* Insert a new entry between two known consecutive entries.
|
||||||
*
|
*
|
||||||
* This is only for internal list manipulation where we know
|
* This is only for internal list manipulation where we know
|
||||||
* the prev/next entries already!
|
* the prev/next entries already!
|
||||||
*/
|
*/
|
||||||
static inline void __list_add(struct list_head * new,
|
static inline void __list_add(struct list_head * new,
|
||||||
struct list_head * prev,
|
struct list_head * prev,
|
||||||
struct list_head * next)
|
struct list_head * next)
|
||||||
{
|
{
|
||||||
next->prev = new;
|
next->prev = new;
|
||||||
new->next = next;
|
new->next = next;
|
||||||
new->prev = prev;
|
new->prev = prev;
|
||||||
prev->next = new;
|
prev->next = new;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_add - add a new entry
|
* list_add - add a new entry
|
||||||
* @new: new entry to be added
|
* @new: new entry to be added
|
||||||
* @head: list head to add it after
|
* @head: list head to add it after
|
||||||
*
|
*
|
||||||
* Insert a new entry after the specified head.
|
* Insert a new entry after the specified head.
|
||||||
* This is good for implementing stacks.
|
* This is good for implementing stacks.
|
||||||
*/
|
*/
|
||||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||||
{
|
{
|
||||||
__list_add(new, head, head->next);
|
__list_add(new, head, head->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_add_tail - add a new entry
|
* list_add_tail - add a new entry
|
||||||
* @new: new entry to be added
|
* @new: new entry to be added
|
||||||
* @head: list head to add it before
|
* @head: list head to add it before
|
||||||
*
|
*
|
||||||
* Insert a new entry before the specified head.
|
* Insert a new entry before the specified head.
|
||||||
* This is useful for implementing queues.
|
* This is useful for implementing queues.
|
||||||
*/
|
*/
|
||||||
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||||
{
|
{
|
||||||
__list_add(new, head->prev, head);
|
__list_add(new, head->prev, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delete a list entry by making the prev/next entries
|
* Delete a list entry by making the prev/next entries
|
||||||
* point to each other.
|
* point to each other.
|
||||||
*
|
*
|
||||||
* This is only for internal list manipulation where we know
|
* This is only for internal list manipulation where we know
|
||||||
* the prev/next entries already!
|
* the prev/next entries already!
|
||||||
*/
|
*/
|
||||||
static inline void __list_del(struct list_head * prev, struct list_head * next)
|
static inline void __list_del(struct list_head * prev, struct list_head * next)
|
||||||
{
|
{
|
||||||
next->prev = prev;
|
next->prev = prev;
|
||||||
prev->next = next;
|
prev->next = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_del - deletes entry from list.
|
* list_del - deletes entry from list.
|
||||||
* @entry: the element to delete from the list.
|
* @entry: the element to delete from the list.
|
||||||
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
|
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
|
||||||
*/
|
*/
|
||||||
static inline void list_del(struct list_head *entry)
|
static inline void list_del(struct list_head *entry)
|
||||||
{
|
{
|
||||||
__list_del(entry->prev, entry->next);
|
__list_del(entry->prev, entry->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_del_init - deletes entry from list and reinitialize it.
|
* list_del_init - deletes entry from list and reinitialize it.
|
||||||
* @entry: the element to delete from the list.
|
* @entry: the element to delete from the list.
|
||||||
*/
|
*/
|
||||||
static inline void list_del_init(struct list_head *entry)
|
static inline void list_del_init(struct list_head *entry)
|
||||||
{
|
{
|
||||||
__list_del(entry->prev, entry->next);
|
__list_del(entry->prev, entry->next);
|
||||||
INIT_LIST_HEAD(entry);
|
INIT_LIST_HEAD(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_move - delete from one list and add as another's head
|
* list_move - delete from one list and add as another's head
|
||||||
* @list: the entry to move
|
* @list: the entry to move
|
||||||
* @head: the head that will precede our entry
|
* @head: the head that will precede our entry
|
||||||
*/
|
*/
|
||||||
static inline void list_move(struct list_head *list, struct list_head *head)
|
static inline void list_move(struct list_head *list, struct list_head *head)
|
||||||
{
|
{
|
||||||
__list_del(list->prev, list->next);
|
__list_del(list->prev, list->next);
|
||||||
list_add(list, head);
|
list_add(list, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_move_tail - delete from one list and add as another's tail
|
* list_move_tail - delete from one list and add as another's tail
|
||||||
* @list: the entry to move
|
* @list: the entry to move
|
||||||
* @head: the head that will follow our entry
|
* @head: the head that will follow our entry
|
||||||
*/
|
*/
|
||||||
static inline void list_move_tail(struct list_head *list,
|
static inline void list_move_tail(struct list_head *list,
|
||||||
struct list_head *head)
|
struct list_head *head)
|
||||||
{
|
{
|
||||||
__list_del(list->prev, list->next);
|
__list_del(list->prev, list->next);
|
||||||
list_add_tail(list, head);
|
list_add_tail(list, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_empty - tests whether a list is empty
|
* list_empty - tests whether a list is empty
|
||||||
* @head: the list to test.
|
* @head: the list to test.
|
||||||
*/
|
*/
|
||||||
static inline int list_empty(struct list_head *head)
|
static inline int list_empty(struct list_head *head)
|
||||||
{
|
{
|
||||||
return head->next == head;
|
return head->next == head;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int list_empty_careful(const struct list_head *head)
|
static inline int list_empty_careful(const struct list_head *head)
|
||||||
{
|
{
|
||||||
struct list_head *next = head->next;
|
struct list_head *next = head->next;
|
||||||
return (next == head) && (next == head->prev);
|
return (next == head) && (next == head->prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __list_splice(struct list_head *list,
|
static inline void __list_splice(struct list_head *list,
|
||||||
struct list_head *head)
|
struct list_head *head)
|
||||||
{
|
{
|
||||||
struct list_head *first = list->next;
|
struct list_head *first = list->next;
|
||||||
struct list_head *last = list->prev;
|
struct list_head *last = list->prev;
|
||||||
struct list_head *at = head->next;
|
struct list_head *at = head->next;
|
||||||
|
|
||||||
first->prev = head;
|
first->prev = head;
|
||||||
head->next = first;
|
head->next = first;
|
||||||
|
|
||||||
last->next = at;
|
last->next = at;
|
||||||
at->prev = last;
|
at->prev = last;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_splice - join two lists
|
* list_splice - join two lists
|
||||||
* @list: the new list to add.
|
* @list: the new list to add.
|
||||||
* @head: the place to add it in the first list.
|
* @head: the place to add it in the first list.
|
||||||
*/
|
*/
|
||||||
static inline void list_splice(struct list_head *list, struct list_head *head)
|
static inline void list_splice(struct list_head *list, struct list_head *head)
|
||||||
{
|
{
|
||||||
if (!list_empty(list))
|
if (!list_empty(list))
|
||||||
__list_splice(list, head);
|
__list_splice(list, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_splice_init - join two lists and reinitialise the emptied list.
|
* list_splice_init - join two lists and reinitialise the emptied list.
|
||||||
* @list: the new list to add.
|
* @list: the new list to add.
|
||||||
* @head: the place to add it in the first list.
|
* @head: the place to add it in the first list.
|
||||||
*
|
*
|
||||||
* The list at @list is reinitialised
|
* The list at @list is reinitialised
|
||||||
*/
|
*/
|
||||||
static inline void list_splice_init(struct list_head *list,
|
static inline void list_splice_init(struct list_head *list,
|
||||||
struct list_head *head)
|
struct list_head *head)
|
||||||
{
|
{
|
||||||
if (!list_empty(list)) {
|
if (!list_empty(list)) {
|
||||||
__list_splice(list, head);
|
__list_splice(list, head);
|
||||||
INIT_LIST_HEAD(list);
|
INIT_LIST_HEAD(list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_entry - get the struct for this entry
|
* list_entry - get the struct for this entry
|
||||||
* @ptr: the &struct list_head pointer.
|
* @ptr: the &struct list_head pointer.
|
||||||
* @type: the type of the struct this is embedded in.
|
* @type: the type of the struct this is embedded in.
|
||||||
* @member: the name of the list_struct within the struct.
|
* @member: the name of the list_struct within the struct.
|
||||||
*/
|
*/
|
||||||
#define list_entry(ptr, type, member) \
|
#define list_entry(ptr, type, member) \
|
||||||
((type *)((char *)(ptr)-(char *)(&((type *)0)->member)))
|
((type *)((char *)(ptr)-(char *)(&((type *)0)->member)))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_for_each - iterate over a list
|
* list_for_each - iterate over a list
|
||||||
* @pos: the &struct list_head to use as a loop counter.
|
* @pos: the &struct list_head to use as a loop counter.
|
||||||
* @head: the head for your list.
|
* @head: the head for your list.
|
||||||
*/
|
*/
|
||||||
#define list_for_each(pos, head) \
|
#define list_for_each(pos, head) \
|
||||||
for (pos = (head)->next, prefetch(pos->next); pos != (head); \
|
for (pos = (head)->next, prefetch(pos->next); pos != (head); \
|
||||||
pos = pos->next, prefetch(pos->next))
|
pos = pos->next, prefetch(pos->next))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||||
* @pos: the &struct list_head to use as a loop counter.
|
* @pos: the &struct list_head to use as a loop counter.
|
||||||
* @n: another &struct list_head to use as temporary storage
|
* @n: another &struct list_head to use as temporary storage
|
||||||
* @head: the head for your list.
|
* @head: the head for your list.
|
||||||
*/
|
*/
|
||||||
#define list_for_each_safe(pos, n, head) \
|
#define list_for_each_safe(pos, n, head) \
|
||||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||||
pos = n, n = pos->next)
|
pos = n, n = pos->next)
|
||||||
|
|
||||||
#ifndef list_for_each_prev
|
#ifndef list_for_each_prev
|
||||||
/**
|
/**
|
||||||
* list_for_each_prev - iterate over a list in reverse order
|
* list_for_each_prev - iterate over a list in reverse order
|
||||||
* @pos: the &struct list_head to use as a loop counter.
|
* @pos: the &struct list_head to use as a loop counter.
|
||||||
* @head: the head for your list.
|
* @head: the head for your list.
|
||||||
*/
|
*/
|
||||||
#define list_for_each_prev(pos, head) \
|
#define list_for_each_prev(pos, head) \
|
||||||
for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
|
for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
|
||||||
pos = pos->prev, prefetch(pos->prev))
|
pos = pos->prev, prefetch(pos->prev))
|
||||||
|
|
||||||
#endif /* list_for_each_prev */
|
#endif /* list_for_each_prev */
|
||||||
|
|
||||||
#ifndef list_for_each_entry
|
#ifndef list_for_each_entry
|
||||||
/**
|
/**
|
||||||
* list_for_each_entry - iterate over list of given type
|
* list_for_each_entry - iterate over list of given type
|
||||||
* @pos: the type * to use as a loop counter.
|
* @pos: the type * to use as a loop counter.
|
||||||
* @head: the head for your list.
|
* @head: the head for your list.
|
||||||
* @member: the name of the list_struct within the struct.
|
* @member: the name of the list_struct within the struct.
|
||||||
*/
|
*/
|
||||||
#define list_for_each_entry(pos, head, type, member) \
|
#define list_for_each_entry(pos, head, type, member) \
|
||||||
for (pos = list_entry((head)->next, type, member), \
|
for (pos = list_entry((head)->next, type, member), \
|
||||||
prefetch(pos->member.next); \
|
prefetch(pos->member.next); \
|
||||||
&pos->member != (head); \
|
&pos->member != (head); \
|
||||||
pos = list_entry(pos->member.next, type, member), \
|
pos = list_entry(pos->member.next, type, member), \
|
||||||
prefetch(pos->member.next))
|
prefetch(pos->member.next))
|
||||||
#endif /* list_for_each_entry */
|
#endif /* list_for_each_entry */
|
||||||
|
|
||||||
#ifndef list_for_each_entry_safe
|
#ifndef list_for_each_entry_safe
|
||||||
/**
|
/**
|
||||||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||||
* @pos: the type * to use as a loop counter.
|
* @pos: the type * to use as a loop counter.
|
||||||
* @n: another type * to use as temporary storage
|
* @n: another type * to use as temporary storage
|
||||||
* @head: the head for your list.
|
* @head: the head for your list.
|
||||||
* @member: the name of the list_struct within the struct.
|
* @member: the name of the list_struct within the struct.
|
||||||
*/
|
*/
|
||||||
#define list_for_each_entry_safe(pos, n, head, type, member) \
|
#define list_for_each_entry_safe(pos, n, head, type, member) \
|
||||||
for (pos = list_entry((head)->next, type, member), \
|
for (pos = list_entry((head)->next, type, member), \
|
||||||
n = list_entry(pos->member.next, type, member); \
|
n = list_entry(pos->member.next, type, member); \
|
||||||
&pos->member != (head); \
|
&pos->member != (head); \
|
||||||
pos = n, n = list_entry(n->member.next, type, member))
|
pos = n, n = list_entry(n->member.next, type, member))
|
||||||
#endif /* list_for_each_entry_safe */
|
#endif /* list_for_each_entry_safe */
|
||||||
|
|
||||||
#endif /* __LINUX_LIST_H__ */
|
#endif /* __LINUX_LIST_H__ */
|
||||||
|
|||||||
@@ -1,140 +1,140 @@
|
|||||||
/* Integer base 2 logarithm calculation
|
/* Integer base 2 logarithm calculation
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
|
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
|
||||||
* Written by David Howells (dhowells@redhat.com)
|
* Written by David Howells (dhowells@redhat.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation; either version
|
* as published by the Free Software Foundation; either version
|
||||||
* 2 of the License, or (at your option) any later version.
|
* 2 of the License, or (at your option) any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LINUX_LOG2_H
|
#ifndef _LINUX_LOG2_H
|
||||||
#define _LINUX_LOG2_H
|
#define _LINUX_LOG2_H
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* deal with unrepresentable constant logarithms
|
* deal with unrepresentable constant logarithms
|
||||||
*/
|
*/
|
||||||
int ____ilog2_NaN(void);
|
int ____ilog2_NaN(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* non-constant log of base 2 calculators
|
* non-constant log of base 2 calculators
|
||||||
* - the arch may override these in asm/bitops.h if they can be implemented
|
* - the arch may override these in asm/bitops.h if they can be implemented
|
||||||
* more efficiently than using fls() and fls64()
|
* more efficiently than using fls() and fls64()
|
||||||
* - the arch is not required to handle n==0 if implementing the fallback
|
* - the arch is not required to handle n==0 if implementing the fallback
|
||||||
*/
|
*/
|
||||||
#ifndef CONFIG_ARCH_HAS_ILOG2_U32
|
#ifndef CONFIG_ARCH_HAS_ILOG2_U32
|
||||||
static inline __attribute__((const))
|
static inline __attribute__((const))
|
||||||
int __ilog2_u32(u32 n)
|
int __ilog2_u32(u32 n)
|
||||||
{
|
{
|
||||||
return fls(n) - 1;
|
return fls(n) - 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_ARCH_HAS_ILOG2_U64
|
#ifndef CONFIG_ARCH_HAS_ILOG2_U64
|
||||||
static inline __attribute__((const))
|
static inline __attribute__((const))
|
||||||
int __ilog2_u64(u64 n)
|
int __ilog2_u64(u64 n)
|
||||||
{
|
{
|
||||||
return fls64(n) - 1;
|
return fls64(n) - 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine whether some value is a power of two, where zero is
|
* Determine whether some value is a power of two, where zero is
|
||||||
* *not* considered a power of two.
|
* *not* considered a power of two.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline __attribute__((const))
|
static inline __attribute__((const))
|
||||||
bool is_power_of_2(unsigned long n)
|
bool is_power_of_2(unsigned long n)
|
||||||
{
|
{
|
||||||
return (n != 0 && ((n & (n - 1)) == 0));
|
return (n != 0 && ((n & (n - 1)) == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* round up to nearest power of two
|
* round up to nearest power of two
|
||||||
*/
|
*/
|
||||||
static inline __attribute__((const))
|
static inline __attribute__((const))
|
||||||
unsigned long __roundup_pow_of_two(unsigned long n)
|
unsigned long __roundup_pow_of_two(unsigned long n)
|
||||||
{
|
{
|
||||||
return 1UL << fls_long(n - 1);
|
return 1UL << fls_long(n - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* round down to nearest power of two
|
* round down to nearest power of two
|
||||||
*/
|
*/
|
||||||
static inline __attribute__((const))
|
static inline __attribute__((const))
|
||||||
unsigned long __rounddown_pow_of_two(unsigned long n)
|
unsigned long __rounddown_pow_of_two(unsigned long n)
|
||||||
{
|
{
|
||||||
return 1UL << (fls_long(n) - 1);
|
return 1UL << (fls_long(n) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
|
* ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
|
||||||
* @n - parameter
|
* @n - parameter
|
||||||
*
|
*
|
||||||
* constant-capable log of base 2 calculation
|
* constant-capable log of base 2 calculation
|
||||||
* - this can be used to initialise global variables from constant data, hence
|
* - this can be used to initialise global variables from constant data, hence
|
||||||
* the massive ternary operator construction
|
* the massive ternary operator construction
|
||||||
*
|
*
|
||||||
* selects the appropriately-sized optimised version depending on sizeof(n)
|
* selects the appropriately-sized optimised version depending on sizeof(n)
|
||||||
*/
|
*/
|
||||||
#define ilog2(n) \
|
#define ilog2(n) \
|
||||||
( \
|
( \
|
||||||
(sizeof(n) <= 4) ? \
|
(sizeof(n) <= 4) ? \
|
||||||
__ilog2_u32(n) : \
|
__ilog2_u32(n) : \
|
||||||
__ilog2_u64(n) \
|
__ilog2_u64(n) \
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* roundup_pow_of_two - round the given value up to nearest power of two
|
* roundup_pow_of_two - round the given value up to nearest power of two
|
||||||
* @n - parameter
|
* @n - parameter
|
||||||
*
|
*
|
||||||
* round the given value up to the nearest power of two
|
* round the given value up to the nearest power of two
|
||||||
* - the result is undefined when n == 0
|
* - the result is undefined when n == 0
|
||||||
* - this can be used to initialise global variables from constant data
|
* - this can be used to initialise global variables from constant data
|
||||||
*/
|
*/
|
||||||
#define roundup_pow_of_two(n) \
|
#define roundup_pow_of_two(n) \
|
||||||
( \
|
( \
|
||||||
__builtin_constant_p(n) ? ( \
|
__builtin_constant_p(n) ? ( \
|
||||||
(n == 1) ? 1 : \
|
(n == 1) ? 1 : \
|
||||||
(1UL << (ilog2((n) - 1) + 1)) \
|
(1UL << (ilog2((n) - 1) + 1)) \
|
||||||
) : \
|
) : \
|
||||||
__roundup_pow_of_two(n) \
|
__roundup_pow_of_two(n) \
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rounddown_pow_of_two - round the given value down to nearest power of two
|
* rounddown_pow_of_two - round the given value down to nearest power of two
|
||||||
* @n - parameter
|
* @n - parameter
|
||||||
*
|
*
|
||||||
* round the given value down to the nearest power of two
|
* round the given value down to the nearest power of two
|
||||||
* - the result is undefined when n == 0
|
* - the result is undefined when n == 0
|
||||||
* - this can be used to initialise global variables from constant data
|
* - this can be used to initialise global variables from constant data
|
||||||
*/
|
*/
|
||||||
#define rounddown_pow_of_two(n) \
|
#define rounddown_pow_of_two(n) \
|
||||||
( \
|
( \
|
||||||
__builtin_constant_p(n) ? ( \
|
__builtin_constant_p(n) ? ( \
|
||||||
(n == 1) ? 0 : \
|
(n == 1) ? 0 : \
|
||||||
(1UL << ilog2(n))) : \
|
(1UL << ilog2(n))) : \
|
||||||
__rounddown_pow_of_two(n) \
|
__rounddown_pow_of_two(n) \
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* order_base_2 - calculate the (rounded up) base 2 order of the argument
|
* order_base_2 - calculate the (rounded up) base 2 order of the argument
|
||||||
* @n: parameter
|
* @n: parameter
|
||||||
*
|
*
|
||||||
* The first few values calculated by this routine:
|
* The first few values calculated by this routine:
|
||||||
* ob2(0) = 0
|
* ob2(0) = 0
|
||||||
* ob2(1) = 0
|
* ob2(1) = 0
|
||||||
* ob2(2) = 1
|
* ob2(2) = 1
|
||||||
* ob2(3) = 2
|
* ob2(3) = 2
|
||||||
* ob2(4) = 2
|
* ob2(4) = 2
|
||||||
* ob2(5) = 3
|
* ob2(5) = 3
|
||||||
* ... and so on.
|
* ... and so on.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define order_base_2(n) ilog2(roundup_pow_of_two(n))
|
#define order_base_2(n) ilog2(roundup_pow_of_two(n))
|
||||||
|
|
||||||
#endif /* _LINUX_LOG2_H */
|
#endif /* _LINUX_LOG2_H */
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,161 +1,161 @@
|
|||||||
/*
|
/*
|
||||||
Red Black Trees
|
Red Black Trees
|
||||||
(C) 1999 Andrea Arcangeli <andrea@suse.de>
|
(C) 1999 Andrea Arcangeli <andrea@suse.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
linux/include/linux/rbtree.h
|
linux/include/linux/rbtree.h
|
||||||
|
|
||||||
To use rbtrees you'll have to implement your own insert and search cores.
|
To use rbtrees you'll have to implement your own insert and search cores.
|
||||||
This will avoid us to use callbacks and to drop drammatically performances.
|
This will avoid us to use callbacks and to drop drammatically performances.
|
||||||
I know it's not the cleaner way, but in C (not in C++) to get
|
I know it's not the cleaner way, but in C (not in C++) to get
|
||||||
performances and genericity...
|
performances and genericity...
|
||||||
|
|
||||||
Some example of insert and search follows here. The search is a plain
|
Some example of insert and search follows here. The search is a plain
|
||||||
normal search over an ordered tree. The insert instead must be implemented
|
normal search over an ordered tree. The insert instead must be implemented
|
||||||
int two steps: as first thing the code must insert the element in
|
int two steps: as first thing the code must insert the element in
|
||||||
order as a red leaf in the tree, then the support library function
|
order as a red leaf in the tree, then the support library function
|
||||||
rb_insert_color() must be called. Such function will do the
|
rb_insert_color() must be called. Such function will do the
|
||||||
not trivial work to rebalance the rbtree if necessary.
|
not trivial work to rebalance the rbtree if necessary.
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
static inline struct page * rb_search_page_cache(struct inode * inode,
|
static inline struct page * rb_search_page_cache(struct inode * inode,
|
||||||
unsigned long offset)
|
unsigned long offset)
|
||||||
{
|
{
|
||||||
struct rb_node * n = inode->i_rb_page_cache.rb_node;
|
struct rb_node * n = inode->i_rb_page_cache.rb_node;
|
||||||
struct page * page;
|
struct page * page;
|
||||||
|
|
||||||
while (n)
|
while (n)
|
||||||
{
|
{
|
||||||
page = rb_entry(n, struct page, rb_page_cache);
|
page = rb_entry(n, struct page, rb_page_cache);
|
||||||
|
|
||||||
if (offset < page->offset)
|
if (offset < page->offset)
|
||||||
n = n->rb_left;
|
n = n->rb_left;
|
||||||
else if (offset > page->offset)
|
else if (offset > page->offset)
|
||||||
n = n->rb_right;
|
n = n->rb_right;
|
||||||
else
|
else
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct page * __rb_insert_page_cache(struct inode * inode,
|
static inline struct page * __rb_insert_page_cache(struct inode * inode,
|
||||||
unsigned long offset,
|
unsigned long offset,
|
||||||
struct rb_node * node)
|
struct rb_node * node)
|
||||||
{
|
{
|
||||||
struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
|
struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
|
||||||
struct rb_node * parent = NULL;
|
struct rb_node * parent = NULL;
|
||||||
struct page * page;
|
struct page * page;
|
||||||
|
|
||||||
while (*p)
|
while (*p)
|
||||||
{
|
{
|
||||||
parent = *p;
|
parent = *p;
|
||||||
page = rb_entry(parent, struct page, rb_page_cache);
|
page = rb_entry(parent, struct page, rb_page_cache);
|
||||||
|
|
||||||
if (offset < page->offset)
|
if (offset < page->offset)
|
||||||
p = &(*p)->rb_left;
|
p = &(*p)->rb_left;
|
||||||
else if (offset > page->offset)
|
else if (offset > page->offset)
|
||||||
p = &(*p)->rb_right;
|
p = &(*p)->rb_right;
|
||||||
else
|
else
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_link_node(node, parent, p);
|
rb_link_node(node, parent, p);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct page * rb_insert_page_cache(struct inode * inode,
|
static inline struct page * rb_insert_page_cache(struct inode * inode,
|
||||||
unsigned long offset,
|
unsigned long offset,
|
||||||
struct rb_node * node)
|
struct rb_node * node)
|
||||||
{
|
{
|
||||||
struct page * ret;
|
struct page * ret;
|
||||||
if ((ret = __rb_insert_page_cache(inode, offset, node)))
|
if ((ret = __rb_insert_page_cache(inode, offset, node)))
|
||||||
goto out;
|
goto out;
|
||||||
rb_insert_color(node, &inode->i_rb_page_cache);
|
rb_insert_color(node, &inode->i_rb_page_cache);
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LINUX_RBTREE_H
|
#ifndef _LINUX_RBTREE_H
|
||||||
#define _LINUX_RBTREE_H
|
#define _LINUX_RBTREE_H
|
||||||
|
|
||||||
struct rb_node
|
struct rb_node
|
||||||
{
|
{
|
||||||
ULONG_PTR rb_parent_color;
|
ULONG_PTR rb_parent_color;
|
||||||
#define RB_RED 0
|
#define RB_RED 0
|
||||||
#define RB_BLACK 1
|
#define RB_BLACK 1
|
||||||
struct rb_node *rb_right;
|
struct rb_node *rb_right;
|
||||||
struct rb_node *rb_left;
|
struct rb_node *rb_left;
|
||||||
} __attribute__((aligned(sizeof(long))));
|
} __attribute__((aligned(sizeof(long))));
|
||||||
/* The alignment might seem pointless, but allegedly CRIS needs it */
|
/* The alignment might seem pointless, but allegedly CRIS needs it */
|
||||||
|
|
||||||
struct rb_root
|
struct rb_root
|
||||||
{
|
{
|
||||||
struct rb_node *rb_node;
|
struct rb_node *rb_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
|
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
|
||||||
#define rb_color(r) ((r)->rb_parent_color & 1)
|
#define rb_color(r) ((r)->rb_parent_color & 1)
|
||||||
#define rb_is_red(r) (!rb_color(r))
|
#define rb_is_red(r) (!rb_color(r))
|
||||||
#define rb_is_black(r) rb_color(r)
|
#define rb_is_black(r) rb_color(r)
|
||||||
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
|
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
|
||||||
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
|
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
|
||||||
|
|
||||||
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
|
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
|
||||||
{
|
{
|
||||||
rb->rb_parent_color = (rb->rb_parent_color & 3) | (ULONG_PTR)p;
|
rb->rb_parent_color = (rb->rb_parent_color & 3) | (ULONG_PTR)p;
|
||||||
}
|
}
|
||||||
static inline void rb_set_color(struct rb_node *rb, ULONG_PTR color)
|
static inline void rb_set_color(struct rb_node *rb, ULONG_PTR color)
|
||||||
{
|
{
|
||||||
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
|
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RB_ROOT (struct rb_root) { NULL, }
|
#define RB_ROOT (struct rb_root) { NULL, }
|
||||||
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
|
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
|
||||||
|
|
||||||
#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
|
#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
|
||||||
#define RB_EMPTY_NODE(node) (rb_parent(node) != node)
|
#define RB_EMPTY_NODE(node) (rb_parent(node) != node)
|
||||||
#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
|
#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
|
||||||
|
|
||||||
extern void rb_insert_color(struct rb_node *, struct rb_root *);
|
extern void rb_insert_color(struct rb_node *, struct rb_root *);
|
||||||
extern void rb_erase(struct rb_node *, struct rb_root *);
|
extern void rb_erase(struct rb_node *, struct rb_root *);
|
||||||
|
|
||||||
/* Find logical next and previous nodes in a tree */
|
/* Find logical next and previous nodes in a tree */
|
||||||
extern struct rb_node *rb_next(struct rb_node *);
|
extern struct rb_node *rb_next(struct rb_node *);
|
||||||
extern struct rb_node *rb_prev(struct rb_node *);
|
extern struct rb_node *rb_prev(struct rb_node *);
|
||||||
extern struct rb_node *rb_first(struct rb_root *);
|
extern struct rb_node *rb_first(struct rb_root *);
|
||||||
extern struct rb_node *rb_last(struct rb_root *);
|
extern struct rb_node *rb_last(struct rb_root *);
|
||||||
|
|
||||||
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
|
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
|
||||||
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
|
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
|
||||||
struct rb_root *root);
|
struct rb_root *root);
|
||||||
|
|
||||||
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
|
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
|
||||||
struct rb_node ** rb_link)
|
struct rb_node ** rb_link)
|
||||||
{
|
{
|
||||||
node->rb_parent_color = (ULONG_PTR )parent;
|
node->rb_parent_color = (ULONG_PTR )parent;
|
||||||
node->rb_left = node->rb_right = NULL;
|
node->rb_left = node->rb_right = NULL;
|
||||||
|
|
||||||
*rb_link = node;
|
*rb_link = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void rb_insert(struct rb_root *root, struct rb_node *node,
|
extern void rb_insert(struct rb_root *root, struct rb_node *node,
|
||||||
int (*cmp)(struct rb_node *, struct rb_node *));
|
int (*cmp)(struct rb_node *, struct rb_node *));
|
||||||
|
|
||||||
#endif /* _LINUX_RBTREE_H */
|
#endif /* _LINUX_RBTREE_H */
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
#ifndef _LINUX_STDDEF_H
|
#ifndef _LINUX_STDDEF_H
|
||||||
#define _LINUX_STDDEF_H
|
#define _LINUX_STDDEF_H
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
false = 0,
|
false = 0,
|
||||||
true = 1
|
true = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef offsetof
|
#ifndef offsetof
|
||||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _LINUX_STDDEF_H */
|
#endif /* _LINUX_STDDEF_H */
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
//{{NO_DEPENDENCIES}}
|
//{{NO_DEPENDENCIES}}
|
||||||
// Microsoft Developer Studio generated include file.
|
// Microsoft Developer Studio generated include file.
|
||||||
// Used by ext2fsd.rc
|
// Used by ext2fsd.rc
|
||||||
//
|
//
|
||||||
|
|
||||||
// Next default values for new objects
|
// Next default values for new objects
|
||||||
//
|
//
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 104
|
#define _APS_NEXT_RESOURCE_VALUE 104
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
250
Ext4Fsd/lock.c
250
Ext4Fsd/lock.c
@@ -1,125 +1,125 @@
|
|||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYRIGHT.TXT
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: lock.c
|
* FILE: lock.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://www.ext2fsd.com
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
/* GLOBALS ***************************************************************/
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
extern PEXT2_GLOBAL Ext2Global;
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, Ext2LockControl)
|
#pragma alloc_text(PAGE, Ext2LockControl)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject = NULL;
|
PDEVICE_OBJECT DeviceObject = NULL;
|
||||||
PFILE_OBJECT FileObject = NULL;
|
PFILE_OBJECT FileObject = NULL;
|
||||||
PEXT2_FCB Fcb = NULL;
|
PEXT2_FCB Fcb = NULL;
|
||||||
PIRP Irp = NULL;
|
PIRP Irp = NULL;
|
||||||
|
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
BOOLEAN CompleteContext = TRUE;
|
BOOLEAN CompleteContext = TRUE;
|
||||||
BOOLEAN CompleteIrp = TRUE;
|
BOOLEAN CompleteIrp = TRUE;
|
||||||
BOOLEAN bFcbAcquired = FALSE;
|
BOOLEAN bFcbAcquired = FALSE;
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
ASSERT(IrpContext != NULL);
|
ASSERT(IrpContext != NULL);
|
||||||
|
|
||||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
DeviceObject = IrpContext->DeviceObject;
|
DeviceObject = IrpContext->DeviceObject;
|
||||||
|
|
||||||
if (IsExt2FsDevice(DeviceObject)) {
|
if (IsExt2FsDevice(DeviceObject)) {
|
||||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileObject = IrpContext->FileObject;
|
FileObject = IrpContext->FileObject;
|
||||||
|
|
||||||
Fcb = (PEXT2_FCB) FileObject->FsContext;
|
Fcb = (PEXT2_FCB) FileObject->FsContext;
|
||||||
ASSERT(Fcb != NULL);
|
ASSERT(Fcb != NULL);
|
||||||
if (Fcb->Identifier.Type == EXT2VCB) {
|
if (Fcb->Identifier.Type == EXT2VCB) {
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
||||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||||
|
|
||||||
if (FlagOn(Fcb->Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
|
if (FlagOn(Fcb->Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE);
|
ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE);
|
||||||
bFcbAcquired = TRUE;
|
bFcbAcquired = TRUE;
|
||||||
|
|
||||||
Irp = IrpContext->Irp;
|
Irp = IrpContext->Irp;
|
||||||
|
|
||||||
CompleteIrp = FALSE;
|
CompleteIrp = FALSE;
|
||||||
|
|
||||||
Status = FsRtlCheckOplock( &Fcb->Oplock,
|
Status = FsRtlCheckOplock( &Fcb->Oplock,
|
||||||
Irp,
|
Irp,
|
||||||
IrpContext,
|
IrpContext,
|
||||||
Ext2OplockComplete,
|
Ext2OplockComplete,
|
||||||
NULL );
|
NULL );
|
||||||
|
|
||||||
if (Status != STATUS_SUCCESS) {
|
if (Status != STATUS_SUCCESS) {
|
||||||
CompleteContext = FALSE;
|
CompleteContext = FALSE;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// FsRtlProcessFileLock acquires FileObject->FsContext->Resource while
|
// FsRtlProcessFileLock acquires FileObject->FsContext->Resource while
|
||||||
// modifying the file locks and calls IoCompleteRequest when it's done.
|
// modifying the file locks and calls IoCompleteRequest when it's done.
|
||||||
//
|
//
|
||||||
|
|
||||||
Status = FsRtlProcessFileLock(
|
Status = FsRtlProcessFileLock(
|
||||||
&Fcb->FileLockAnchor,
|
&Fcb->FileLockAnchor,
|
||||||
Irp,
|
Irp,
|
||||||
NULL );
|
NULL );
|
||||||
#if EXT2_DEBUG
|
#if EXT2_DEBUG
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
DEBUG(DL_ERR, (
|
DEBUG(DL_ERR, (
|
||||||
"Ext2LockControl: %-16.16s %-31s Status: %#x ***\n",
|
"Ext2LockControl: %-16.16s %-31s Status: %#x ***\n",
|
||||||
Ext2GetCurrentProcessName(),
|
Ext2GetCurrentProcessName(),
|
||||||
"IRP_MJ_LOCK_CONTROL",
|
"IRP_MJ_LOCK_CONTROL",
|
||||||
Status ));
|
Status ));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
|
Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
if (bFcbAcquired) {
|
if (bFcbAcquired) {
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
ExReleaseResourceLite(&Fcb->MainResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IrpContext->ExceptionInProgress) {
|
if (!IrpContext->ExceptionInProgress) {
|
||||||
|
|
||||||
if (!CompleteIrp) {
|
if (!CompleteIrp) {
|
||||||
IrpContext->Irp = NULL;
|
IrpContext->Irp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CompleteContext) {
|
if (CompleteContext) {
|
||||||
Ext2CompleteIrpContext(IrpContext, Status);
|
Ext2CompleteIrpContext(IrpContext, Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|||||||
1064
Ext4Fsd/misc.c
1064
Ext4Fsd/misc.c
File diff suppressed because it is too large
Load Diff
462
Ext4Fsd/nls.c
462
Ext4Fsd/nls.c
@@ -1,232 +1,232 @@
|
|||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYRIGHT.TXT
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: nls.c
|
* FILE: nls.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://www.ext2fsd.com
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
/* GOBALS** ****************************************************************/
|
/* GOBALS** ****************************************************************/
|
||||||
|
|
||||||
extern struct nls_table *tables;
|
extern struct nls_table *tables;
|
||||||
extern spinlock_t nls_lock;
|
extern spinlock_t nls_lock;
|
||||||
|
|
||||||
/* DECLARES ****************************************************************/
|
/* DECLARES ****************************************************************/
|
||||||
|
|
||||||
#define FULL_CODEPAGES_SUPPORT
|
#define FULL_CODEPAGES_SUPPORT
|
||||||
|
|
||||||
#ifdef FULL_CODEPAGES_SUPPORT
|
#ifdef FULL_CODEPAGES_SUPPORT
|
||||||
|
|
||||||
DECLARE_INIT(init_nls_ascii);
|
DECLARE_INIT(init_nls_ascii);
|
||||||
DECLARE_EXIT(exit_nls_ascii);
|
DECLARE_EXIT(exit_nls_ascii);
|
||||||
DECLARE_INIT(init_nls_cp1250);
|
DECLARE_INIT(init_nls_cp1250);
|
||||||
DECLARE_EXIT(exit_nls_cp1250);
|
DECLARE_EXIT(exit_nls_cp1250);
|
||||||
DECLARE_INIT(init_nls_cp1251);
|
DECLARE_INIT(init_nls_cp1251);
|
||||||
DECLARE_EXIT(exit_nls_cp1251);
|
DECLARE_EXIT(exit_nls_cp1251);
|
||||||
DECLARE_INIT(init_nls_cp1255);
|
DECLARE_INIT(init_nls_cp1255);
|
||||||
DECLARE_EXIT(exit_nls_cp1255);
|
DECLARE_EXIT(exit_nls_cp1255);
|
||||||
DECLARE_INIT(init_nls_cp437);
|
DECLARE_INIT(init_nls_cp437);
|
||||||
DECLARE_EXIT(exit_nls_cp437);
|
DECLARE_EXIT(exit_nls_cp437);
|
||||||
DECLARE_INIT(init_nls_cp737);
|
DECLARE_INIT(init_nls_cp737);
|
||||||
DECLARE_EXIT(exit_nls_cp737);
|
DECLARE_EXIT(exit_nls_cp737);
|
||||||
DECLARE_INIT(init_nls_cp775);
|
DECLARE_INIT(init_nls_cp775);
|
||||||
DECLARE_EXIT(exit_nls_cp775);
|
DECLARE_EXIT(exit_nls_cp775);
|
||||||
DECLARE_INIT(init_nls_cp850);
|
DECLARE_INIT(init_nls_cp850);
|
||||||
DECLARE_EXIT(exit_nls_cp850);
|
DECLARE_EXIT(exit_nls_cp850);
|
||||||
DECLARE_INIT(init_nls_cp852);
|
DECLARE_INIT(init_nls_cp852);
|
||||||
DECLARE_EXIT(exit_nls_cp852);
|
DECLARE_EXIT(exit_nls_cp852);
|
||||||
DECLARE_INIT(init_nls_cp855);
|
DECLARE_INIT(init_nls_cp855);
|
||||||
DECLARE_EXIT(exit_nls_cp855);
|
DECLARE_EXIT(exit_nls_cp855);
|
||||||
DECLARE_INIT(init_nls_cp857);
|
DECLARE_INIT(init_nls_cp857);
|
||||||
DECLARE_EXIT(exit_nls_cp857);
|
DECLARE_EXIT(exit_nls_cp857);
|
||||||
DECLARE_INIT(init_nls_cp860);
|
DECLARE_INIT(init_nls_cp860);
|
||||||
DECLARE_EXIT(exit_nls_cp860);
|
DECLARE_EXIT(exit_nls_cp860);
|
||||||
DECLARE_INIT(init_nls_cp861);
|
DECLARE_INIT(init_nls_cp861);
|
||||||
DECLARE_EXIT(exit_nls_cp861);
|
DECLARE_EXIT(exit_nls_cp861);
|
||||||
DECLARE_INIT(init_nls_cp862);
|
DECLARE_INIT(init_nls_cp862);
|
||||||
DECLARE_EXIT(exit_nls_cp862);
|
DECLARE_EXIT(exit_nls_cp862);
|
||||||
DECLARE_INIT(init_nls_cp863);
|
DECLARE_INIT(init_nls_cp863);
|
||||||
DECLARE_EXIT(exit_nls_cp863);
|
DECLARE_EXIT(exit_nls_cp863);
|
||||||
DECLARE_INIT(init_nls_cp864);
|
DECLARE_INIT(init_nls_cp864);
|
||||||
DECLARE_EXIT(exit_nls_cp864);
|
DECLARE_EXIT(exit_nls_cp864);
|
||||||
DECLARE_INIT(init_nls_cp865);
|
DECLARE_INIT(init_nls_cp865);
|
||||||
DECLARE_EXIT(exit_nls_cp865);
|
DECLARE_EXIT(exit_nls_cp865);
|
||||||
DECLARE_INIT(init_nls_cp866);
|
DECLARE_INIT(init_nls_cp866);
|
||||||
DECLARE_EXIT(exit_nls_cp866);
|
DECLARE_EXIT(exit_nls_cp866);
|
||||||
DECLARE_INIT(init_nls_cp869);
|
DECLARE_INIT(init_nls_cp869);
|
||||||
DECLARE_EXIT(exit_nls_cp869);
|
DECLARE_EXIT(exit_nls_cp869);
|
||||||
DECLARE_INIT(init_nls_cp874);
|
DECLARE_INIT(init_nls_cp874);
|
||||||
DECLARE_EXIT(exit_nls_cp874);
|
DECLARE_EXIT(exit_nls_cp874);
|
||||||
DECLARE_INIT(init_nls_cp932);
|
DECLARE_INIT(init_nls_cp932);
|
||||||
DECLARE_EXIT(exit_nls_cp932);
|
DECLARE_EXIT(exit_nls_cp932);
|
||||||
DECLARE_INIT(init_nls_cp949);
|
DECLARE_INIT(init_nls_cp949);
|
||||||
DECLARE_EXIT(exit_nls_cp949);
|
DECLARE_EXIT(exit_nls_cp949);
|
||||||
DECLARE_INIT(init_nls_euc_jp);
|
DECLARE_INIT(init_nls_euc_jp);
|
||||||
DECLARE_EXIT(exit_nls_euc_jp);
|
DECLARE_EXIT(exit_nls_euc_jp);
|
||||||
DECLARE_INIT(init_nls_iso8859_1);
|
DECLARE_INIT(init_nls_iso8859_1);
|
||||||
DECLARE_EXIT(exit_nls_iso8859_1);
|
DECLARE_EXIT(exit_nls_iso8859_1);
|
||||||
DECLARE_INIT(init_nls_iso8859_13);
|
DECLARE_INIT(init_nls_iso8859_13);
|
||||||
DECLARE_EXIT(exit_nls_iso8859_13);
|
DECLARE_EXIT(exit_nls_iso8859_13);
|
||||||
DECLARE_INIT(init_nls_iso8859_14);
|
DECLARE_INIT(init_nls_iso8859_14);
|
||||||
DECLARE_EXIT(exit_nls_iso8859_14);
|
DECLARE_EXIT(exit_nls_iso8859_14);
|
||||||
DECLARE_INIT(init_nls_iso8859_15);
|
DECLARE_INIT(init_nls_iso8859_15);
|
||||||
DECLARE_EXIT(exit_nls_iso8859_15);
|
DECLARE_EXIT(exit_nls_iso8859_15);
|
||||||
DECLARE_INIT(init_nls_iso8859_2);
|
DECLARE_INIT(init_nls_iso8859_2);
|
||||||
DECLARE_EXIT(exit_nls_iso8859_2);
|
DECLARE_EXIT(exit_nls_iso8859_2);
|
||||||
DECLARE_INIT(init_nls_iso8859_3);
|
DECLARE_INIT(init_nls_iso8859_3);
|
||||||
DECLARE_EXIT(exit_nls_iso8859_3);
|
DECLARE_EXIT(exit_nls_iso8859_3);
|
||||||
DECLARE_INIT(init_nls_iso8859_4);
|
DECLARE_INIT(init_nls_iso8859_4);
|
||||||
DECLARE_EXIT(exit_nls_iso8859_4);
|
DECLARE_EXIT(exit_nls_iso8859_4);
|
||||||
DECLARE_INIT(init_nls_iso8859_5);
|
DECLARE_INIT(init_nls_iso8859_5);
|
||||||
DECLARE_EXIT(exit_nls_iso8859_5);
|
DECLARE_EXIT(exit_nls_iso8859_5);
|
||||||
DECLARE_INIT(init_nls_iso8859_6);
|
DECLARE_INIT(init_nls_iso8859_6);
|
||||||
DECLARE_EXIT(exit_nls_iso8859_6);
|
DECLARE_EXIT(exit_nls_iso8859_6);
|
||||||
DECLARE_INIT(init_nls_iso8859_7);
|
DECLARE_INIT(init_nls_iso8859_7);
|
||||||
DECLARE_EXIT(exit_nls_iso8859_7);
|
DECLARE_EXIT(exit_nls_iso8859_7);
|
||||||
DECLARE_INIT(init_nls_iso8859_9);
|
DECLARE_INIT(init_nls_iso8859_9);
|
||||||
DECLARE_EXIT(exit_nls_iso8859_9);
|
DECLARE_EXIT(exit_nls_iso8859_9);
|
||||||
DECLARE_INIT(init_nls_koi8_r);
|
DECLARE_INIT(init_nls_koi8_r);
|
||||||
DECLARE_EXIT(exit_nls_koi8_r);
|
DECLARE_EXIT(exit_nls_koi8_r);
|
||||||
DECLARE_INIT(init_nls_koi8_ru);
|
DECLARE_INIT(init_nls_koi8_ru);
|
||||||
DECLARE_EXIT(exit_nls_koi8_ru);
|
DECLARE_EXIT(exit_nls_koi8_ru);
|
||||||
DECLARE_INIT(init_nls_koi8_u);
|
DECLARE_INIT(init_nls_koi8_u);
|
||||||
DECLARE_EXIT(exit_nls_koi8_u);
|
DECLARE_EXIT(exit_nls_koi8_u);
|
||||||
#endif //FULL_CODEPAGES_SUPPORT
|
#endif //FULL_CODEPAGES_SUPPORT
|
||||||
|
|
||||||
/* gb2312 */
|
/* gb2312 */
|
||||||
DECLARE_INIT(init_nls_cp936);
|
DECLARE_INIT(init_nls_cp936);
|
||||||
DECLARE_EXIT(exit_nls_cp936);
|
DECLARE_EXIT(exit_nls_cp936);
|
||||||
|
|
||||||
/* big5 */
|
/* big5 */
|
||||||
DECLARE_INIT(init_nls_cp950);
|
DECLARE_INIT(init_nls_cp950);
|
||||||
DECLARE_EXIT(exit_nls_cp950);
|
DECLARE_EXIT(exit_nls_cp950);
|
||||||
|
|
||||||
/* utf8 */
|
/* utf8 */
|
||||||
DECLARE_INIT(init_nls_utf8);
|
DECLARE_INIT(init_nls_utf8);
|
||||||
DECLARE_EXIT(exit_nls_utf8);
|
DECLARE_EXIT(exit_nls_utf8);
|
||||||
|
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
Ext2LoadAllNls()
|
Ext2LoadAllNls()
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
tables = NULL;
|
tables = NULL;
|
||||||
spin_lock_init(&nls_lock);
|
spin_lock_init(&nls_lock);
|
||||||
|
|
||||||
/* loading utf8 ... */
|
/* loading utf8 ... */
|
||||||
LOAD_NLS(init_nls_utf8);
|
LOAD_NLS(init_nls_utf8);
|
||||||
|
|
||||||
#ifdef FULL_CODEPAGES_SUPPORT
|
#ifdef FULL_CODEPAGES_SUPPORT
|
||||||
|
|
||||||
/* loading chinese gb2312 and big5... */
|
/* loading chinese gb2312 and big5... */
|
||||||
LOAD_NLS(init_nls_cp936);
|
LOAD_NLS(init_nls_cp936);
|
||||||
LOAD_NLS(init_nls_cp950);
|
LOAD_NLS(init_nls_cp950);
|
||||||
|
|
||||||
/* loading all others */
|
/* loading all others */
|
||||||
|
|
||||||
LOAD_NLS(init_nls_ascii);
|
LOAD_NLS(init_nls_ascii);
|
||||||
LOAD_NLS(init_nls_cp1250);
|
LOAD_NLS(init_nls_cp1250);
|
||||||
LOAD_NLS(init_nls_cp1251);
|
LOAD_NLS(init_nls_cp1251);
|
||||||
LOAD_NLS(init_nls_cp1255);
|
LOAD_NLS(init_nls_cp1255);
|
||||||
LOAD_NLS(init_nls_cp437);
|
LOAD_NLS(init_nls_cp437);
|
||||||
LOAD_NLS(init_nls_cp737);
|
LOAD_NLS(init_nls_cp737);
|
||||||
LOAD_NLS(init_nls_cp775);
|
LOAD_NLS(init_nls_cp775);
|
||||||
LOAD_NLS(init_nls_cp850);
|
LOAD_NLS(init_nls_cp850);
|
||||||
LOAD_NLS(init_nls_cp852);
|
LOAD_NLS(init_nls_cp852);
|
||||||
LOAD_NLS(init_nls_cp855);
|
LOAD_NLS(init_nls_cp855);
|
||||||
LOAD_NLS(init_nls_cp857);
|
LOAD_NLS(init_nls_cp857);
|
||||||
LOAD_NLS(init_nls_cp860);
|
LOAD_NLS(init_nls_cp860);
|
||||||
LOAD_NLS(init_nls_cp861);
|
LOAD_NLS(init_nls_cp861);
|
||||||
LOAD_NLS(init_nls_cp862);
|
LOAD_NLS(init_nls_cp862);
|
||||||
LOAD_NLS(init_nls_cp863);
|
LOAD_NLS(init_nls_cp863);
|
||||||
LOAD_NLS(init_nls_cp864);
|
LOAD_NLS(init_nls_cp864);
|
||||||
LOAD_NLS(init_nls_cp865);
|
LOAD_NLS(init_nls_cp865);
|
||||||
LOAD_NLS(init_nls_cp866);
|
LOAD_NLS(init_nls_cp866);
|
||||||
LOAD_NLS(init_nls_cp869);
|
LOAD_NLS(init_nls_cp869);
|
||||||
LOAD_NLS(init_nls_cp874);
|
LOAD_NLS(init_nls_cp874);
|
||||||
LOAD_NLS(init_nls_cp932);
|
LOAD_NLS(init_nls_cp932);
|
||||||
LOAD_NLS(init_nls_euc_jp);
|
LOAD_NLS(init_nls_euc_jp);
|
||||||
LOAD_NLS(init_nls_cp949);
|
LOAD_NLS(init_nls_cp949);
|
||||||
LOAD_NLS(init_nls_iso8859_1);
|
LOAD_NLS(init_nls_iso8859_1);
|
||||||
LOAD_NLS(init_nls_iso8859_13);
|
LOAD_NLS(init_nls_iso8859_13);
|
||||||
LOAD_NLS(init_nls_iso8859_14);
|
LOAD_NLS(init_nls_iso8859_14);
|
||||||
LOAD_NLS(init_nls_iso8859_15);
|
LOAD_NLS(init_nls_iso8859_15);
|
||||||
LOAD_NLS(init_nls_iso8859_2);
|
LOAD_NLS(init_nls_iso8859_2);
|
||||||
LOAD_NLS(init_nls_iso8859_3);
|
LOAD_NLS(init_nls_iso8859_3);
|
||||||
LOAD_NLS(init_nls_iso8859_4);
|
LOAD_NLS(init_nls_iso8859_4);
|
||||||
LOAD_NLS(init_nls_iso8859_5);
|
LOAD_NLS(init_nls_iso8859_5);
|
||||||
LOAD_NLS(init_nls_iso8859_6);
|
LOAD_NLS(init_nls_iso8859_6);
|
||||||
LOAD_NLS(init_nls_iso8859_7);
|
LOAD_NLS(init_nls_iso8859_7);
|
||||||
LOAD_NLS(init_nls_iso8859_9);
|
LOAD_NLS(init_nls_iso8859_9);
|
||||||
LOAD_NLS(init_nls_koi8_r);
|
LOAD_NLS(init_nls_koi8_r);
|
||||||
LOAD_NLS(init_nls_koi8_u);
|
LOAD_NLS(init_nls_koi8_u);
|
||||||
LOAD_NLS(init_nls_koi8_ru);
|
LOAD_NLS(init_nls_koi8_ru);
|
||||||
|
|
||||||
#endif //FULL_CODEPAGES_SUPPORT
|
#endif //FULL_CODEPAGES_SUPPORT
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2UnloadAllNls()
|
Ext2UnloadAllNls()
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef FULL_CODEPAGES_SUPPORT
|
#ifdef FULL_CODEPAGES_SUPPORT
|
||||||
|
|
||||||
UNLOAD_NLS(init_nls_ascii);
|
UNLOAD_NLS(init_nls_ascii);
|
||||||
UNLOAD_NLS(init_nls_cp1250);
|
UNLOAD_NLS(init_nls_cp1250);
|
||||||
UNLOAD_NLS(exit_nls_cp1251);
|
UNLOAD_NLS(exit_nls_cp1251);
|
||||||
UNLOAD_NLS(exit_nls_cp1255);
|
UNLOAD_NLS(exit_nls_cp1255);
|
||||||
UNLOAD_NLS(exit_nls_cp437);
|
UNLOAD_NLS(exit_nls_cp437);
|
||||||
UNLOAD_NLS(exit_nls_cp737);
|
UNLOAD_NLS(exit_nls_cp737);
|
||||||
UNLOAD_NLS(exit_nls_cp775);
|
UNLOAD_NLS(exit_nls_cp775);
|
||||||
UNLOAD_NLS(exit_nls_cp850);
|
UNLOAD_NLS(exit_nls_cp850);
|
||||||
UNLOAD_NLS(exit_nls_cp852);
|
UNLOAD_NLS(exit_nls_cp852);
|
||||||
UNLOAD_NLS(exit_nls_cp855);
|
UNLOAD_NLS(exit_nls_cp855);
|
||||||
UNLOAD_NLS(exit_nls_cp857);
|
UNLOAD_NLS(exit_nls_cp857);
|
||||||
UNLOAD_NLS(exit_nls_cp860);
|
UNLOAD_NLS(exit_nls_cp860);
|
||||||
UNLOAD_NLS(exit_nls_cp861);
|
UNLOAD_NLS(exit_nls_cp861);
|
||||||
UNLOAD_NLS(exit_nls_cp862);
|
UNLOAD_NLS(exit_nls_cp862);
|
||||||
UNLOAD_NLS(exit_nls_cp863);
|
UNLOAD_NLS(exit_nls_cp863);
|
||||||
UNLOAD_NLS(exit_nls_cp864);
|
UNLOAD_NLS(exit_nls_cp864);
|
||||||
UNLOAD_NLS(exit_nls_cp865);
|
UNLOAD_NLS(exit_nls_cp865);
|
||||||
UNLOAD_NLS(exit_nls_cp866);
|
UNLOAD_NLS(exit_nls_cp866);
|
||||||
UNLOAD_NLS(exit_nls_cp869);
|
UNLOAD_NLS(exit_nls_cp869);
|
||||||
UNLOAD_NLS(exit_nls_cp874);
|
UNLOAD_NLS(exit_nls_cp874);
|
||||||
UNLOAD_NLS(exit_nls_euc_jp);
|
UNLOAD_NLS(exit_nls_euc_jp);
|
||||||
UNLOAD_NLS(exit_nls_cp932);
|
UNLOAD_NLS(exit_nls_cp932);
|
||||||
UNLOAD_NLS(exit_nls_cp949);
|
UNLOAD_NLS(exit_nls_cp949);
|
||||||
UNLOAD_NLS(exit_nls_iso8859_1);
|
UNLOAD_NLS(exit_nls_iso8859_1);
|
||||||
UNLOAD_NLS(exit_nls_iso8859_13);
|
UNLOAD_NLS(exit_nls_iso8859_13);
|
||||||
UNLOAD_NLS(exit_nls_iso8859_14);
|
UNLOAD_NLS(exit_nls_iso8859_14);
|
||||||
UNLOAD_NLS(exit_nls_iso8859_15);
|
UNLOAD_NLS(exit_nls_iso8859_15);
|
||||||
UNLOAD_NLS(exit_nls_iso8859_2);
|
UNLOAD_NLS(exit_nls_iso8859_2);
|
||||||
UNLOAD_NLS(exit_nls_iso8859_3);
|
UNLOAD_NLS(exit_nls_iso8859_3);
|
||||||
UNLOAD_NLS(exit_nls_iso8859_4);
|
UNLOAD_NLS(exit_nls_iso8859_4);
|
||||||
UNLOAD_NLS(exit_nls_iso8859_5);
|
UNLOAD_NLS(exit_nls_iso8859_5);
|
||||||
UNLOAD_NLS(exit_nls_iso8859_6);
|
UNLOAD_NLS(exit_nls_iso8859_6);
|
||||||
UNLOAD_NLS(exit_nls_iso8859_7);
|
UNLOAD_NLS(exit_nls_iso8859_7);
|
||||||
UNLOAD_NLS(exit_nls_iso8859_9);
|
UNLOAD_NLS(exit_nls_iso8859_9);
|
||||||
UNLOAD_NLS(exit_nls_koi8_ru);
|
UNLOAD_NLS(exit_nls_koi8_ru);
|
||||||
UNLOAD_NLS(exit_nls_koi8_r);
|
UNLOAD_NLS(exit_nls_koi8_r);
|
||||||
UNLOAD_NLS(exit_nls_koi8_u);
|
UNLOAD_NLS(exit_nls_koi8_u);
|
||||||
|
|
||||||
/* unloading chinese codepages */
|
/* unloading chinese codepages */
|
||||||
UNLOAD_NLS(exit_nls_cp950);
|
UNLOAD_NLS(exit_nls_cp950);
|
||||||
UNLOAD_NLS(exit_nls_cp936);
|
UNLOAD_NLS(exit_nls_cp936);
|
||||||
|
|
||||||
#endif //FULL_CODEPAGES_SUPPORT
|
#endif //FULL_CODEPAGES_SUPPORT
|
||||||
|
|
||||||
/* unloading nls of utf8 */
|
/* unloading nls of utf8 */
|
||||||
UNLOAD_NLS(exit_nls_utf8);
|
UNLOAD_NLS(exit_nls_utf8);
|
||||||
}
|
}
|
||||||
792
Ext4Fsd/pnp.c
792
Ext4Fsd/pnp.c
@@ -1,397 +1,397 @@
|
|||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYRIGHT.TXT
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: pnp.c
|
* FILE: pnp.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://www.ext2fsd.com
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if (_WIN32_WINNT >= 0x0500)
|
#if (_WIN32_WINNT >= 0x0500)
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
/* GLOBALS ***************************************************************/
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
extern PEXT2_GLOBAL Ext2Global;
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2PnpCompletionRoutine (
|
Ext2PnpCompletionRoutine (
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp,
|
IN PIRP Irp,
|
||||||
IN PVOID Contxt );
|
IN PVOID Contxt );
|
||||||
|
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, Ext2Pnp)
|
#pragma alloc_text(PAGE, Ext2Pnp)
|
||||||
#pragma alloc_text(PAGE, Ext2PnpQueryRemove)
|
#pragma alloc_text(PAGE, Ext2PnpQueryRemove)
|
||||||
#pragma alloc_text(PAGE, Ext2PnpRemove)
|
#pragma alloc_text(PAGE, Ext2PnpRemove)
|
||||||
#pragma alloc_text(PAGE, Ext2PnpCancelRemove)
|
#pragma alloc_text(PAGE, Ext2PnpCancelRemove)
|
||||||
#pragma alloc_text(PAGE, Ext2PnpSurpriseRemove)
|
#pragma alloc_text(PAGE, Ext2PnpSurpriseRemove)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* FUNCTIONS *************************************************************/
|
/* FUNCTIONS *************************************************************/
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2PnpCompletionRoutine (
|
Ext2PnpCompletionRoutine (
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp,
|
IN PIRP Irp,
|
||||||
IN PVOID Contxt
|
IN PVOID Contxt
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
PKEVENT Event = (PKEVENT) Contxt;
|
PKEVENT Event = (PKEVENT) Contxt;
|
||||||
|
|
||||||
KeSetEvent( Event, 0, FALSE );
|
KeSetEvent( Event, 0, FALSE );
|
||||||
|
|
||||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
|
|
||||||
UNREFERENCED_PARAMETER( DeviceObject );
|
UNREFERENCED_PARAMETER( DeviceObject );
|
||||||
UNREFERENCED_PARAMETER( Contxt );
|
UNREFERENCED_PARAMETER( Contxt );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2Pnp (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2Pnp (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
PIO_STACK_LOCATION IrpSp;
|
PIO_STACK_LOCATION IrpSp;
|
||||||
PEXT2_VCB Vcb = NULL;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
ASSERT(IrpContext);
|
ASSERT(IrpContext);
|
||||||
|
|
||||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
DeviceObject = IrpContext->DeviceObject;
|
DeviceObject = IrpContext->DeviceObject;
|
||||||
|
|
||||||
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
|
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
ASSERT(Vcb != NULL);
|
ASSERT(Vcb != NULL);
|
||||||
|
|
||||||
if ( !((Vcb->Identifier.Type == EXT2VCB) &&
|
if ( !((Vcb->Identifier.Type == EXT2VCB) &&
|
||||||
(Vcb->Identifier.Size == sizeof(EXT2_VCB)))) {
|
(Vcb->Identifier.Size == sizeof(EXT2_VCB)))) {
|
||||||
__leave; // Status = STATUS_INVALID_PARAMETER
|
__leave; // Status = STATUS_INVALID_PARAMETER
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp = IrpContext->Irp;
|
Irp = IrpContext->Irp;
|
||||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
|
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
|
||||||
|
|
||||||
switch ( IrpSp->MinorFunction ) {
|
switch ( IrpSp->MinorFunction ) {
|
||||||
|
|
||||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||||
|
|
||||||
DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpQueryRemove...\n"));
|
DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpQueryRemove...\n"));
|
||||||
Status = Ext2PnpQueryRemove(IrpContext, Vcb);
|
Status = Ext2PnpQueryRemove(IrpContext, Vcb);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRP_MN_REMOVE_DEVICE:
|
case IRP_MN_REMOVE_DEVICE:
|
||||||
|
|
||||||
DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpRemove...\n"));
|
DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpRemove...\n"));
|
||||||
Status = Ext2PnpRemove(IrpContext, Vcb);
|
Status = Ext2PnpRemove(IrpContext, Vcb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||||
|
|
||||||
DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpCancelRemove...\n"));
|
DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpCancelRemove...\n"));
|
||||||
Status = Ext2PnpCancelRemove(IrpContext, Vcb);
|
Status = Ext2PnpCancelRemove(IrpContext, Vcb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRP_MN_SURPRISE_REMOVAL:
|
case IRP_MN_SURPRISE_REMOVAL:
|
||||||
|
|
||||||
DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpSupriseRemove...\n"));
|
DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpSupriseRemove...\n"));
|
||||||
Status = Ext2PnpSurpriseRemove(IrpContext, Vcb);
|
Status = Ext2PnpSurpriseRemove(IrpContext, Vcb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
if (!IrpContext->ExceptionInProgress) {
|
if (!IrpContext->ExceptionInProgress) {
|
||||||
Irp = IrpContext->Irp;
|
Irp = IrpContext->Irp;
|
||||||
|
|
||||||
if (Irp) {
|
if (Irp) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Here we need pass the IRP to the disk driver.
|
// Here we need pass the IRP to the disk driver.
|
||||||
//
|
//
|
||||||
|
|
||||||
IoSkipCurrentIrpStackLocation( Irp );
|
IoSkipCurrentIrpStackLocation( Irp );
|
||||||
|
|
||||||
Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
|
Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
|
||||||
|
|
||||||
IrpContext->Irp = NULL;
|
IrpContext->Irp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ext2CompleteIrpContext(IrpContext, Status);
|
Ext2CompleteIrpContext(IrpContext, Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2PnpQueryRemove (
|
Ext2PnpQueryRemove (
|
||||||
PEXT2_IRP_CONTEXT IrpContext,
|
PEXT2_IRP_CONTEXT IrpContext,
|
||||||
PEXT2_VCB Vcb
|
PEXT2_VCB Vcb
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
KEVENT Event;
|
KEVENT Event;
|
||||||
BOOLEAN bDeleted = FALSE;
|
BOOLEAN bDeleted = FALSE;
|
||||||
BOOLEAN VcbAcquired = FALSE;
|
BOOLEAN VcbAcquired = FALSE;
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
CcWaitForCurrentLazyWriterActivity();
|
CcWaitForCurrentLazyWriterActivity();
|
||||||
|
|
||||||
VcbAcquired = ExAcquireResourceExclusiveLite(
|
VcbAcquired = ExAcquireResourceExclusiveLite(
|
||||||
&Vcb->MainResource, TRUE );
|
&Vcb->MainResource, TRUE );
|
||||||
|
|
||||||
Ext2FlushFiles(IrpContext, Vcb, FALSE);
|
Ext2FlushFiles(IrpContext, Vcb, FALSE);
|
||||||
Ext2FlushVolume(IrpContext, Vcb, FALSE);
|
Ext2FlushVolume(IrpContext, Vcb, FALSE);
|
||||||
|
|
||||||
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2LockVcb: Vcb=%xh FileObject=%xh ...\n",
|
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2LockVcb: Vcb=%xh FileObject=%xh ...\n",
|
||||||
Vcb, IrpContext->FileObject));
|
Vcb, IrpContext->FileObject));
|
||||||
Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
|
Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
|
||||||
|
|
||||||
if (VcbAcquired) {
|
if (VcbAcquired) {
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
VcbAcquired = FALSE;
|
VcbAcquired = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2PurgeVolume ...\n"));
|
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2PurgeVolume ...\n"));
|
||||||
Ext2PurgeVolume(Vcb, TRUE);
|
Ext2PurgeVolume(Vcb, TRUE);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
|
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
|
||||||
|
|
||||||
KeInitializeEvent( &Event, NotificationEvent, FALSE );
|
KeInitializeEvent( &Event, NotificationEvent, FALSE );
|
||||||
IoSetCompletionRoutine( IrpContext->Irp,
|
IoSetCompletionRoutine( IrpContext->Irp,
|
||||||
Ext2PnpCompletionRoutine,
|
Ext2PnpCompletionRoutine,
|
||||||
&Event,
|
&Event,
|
||||||
TRUE,
|
TRUE,
|
||||||
TRUE,
|
TRUE,
|
||||||
TRUE );
|
TRUE );
|
||||||
|
|
||||||
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Call lower level driver...\n"));
|
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Call lower level driver...\n"));
|
||||||
Status = IoCallDriver( Vcb->TargetDeviceObject,
|
Status = IoCallDriver( Vcb->TargetDeviceObject,
|
||||||
IrpContext->Irp);
|
IrpContext->Irp);
|
||||||
|
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
KeWaitForSingleObject( &Event,
|
KeWaitForSingleObject( &Event,
|
||||||
Executive,
|
Executive,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL );
|
NULL );
|
||||||
Status = IrpContext->Irp->IoStatus.Status;
|
Status = IrpContext->Irp->IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NT_SUCCESS(Status)) {
|
if (NT_SUCCESS(Status)) {
|
||||||
ASSERT(!VcbAcquired);
|
ASSERT(!VcbAcquired);
|
||||||
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2CheckDismount ...\n"));
|
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2CheckDismount ...\n"));
|
||||||
bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
|
bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
|
||||||
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2FlushVolume bDelted=%xh ...\n", bDeleted));
|
DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2FlushVolume bDelted=%xh ...\n", bDeleted));
|
||||||
}
|
}
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
if (VcbAcquired) {
|
if (VcbAcquired) {
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
IrpContext->Irp->IoStatus.Status = Status;
|
IrpContext->Irp->IoStatus.Status = Status;
|
||||||
Ext2CompleteRequest(
|
Ext2CompleteRequest(
|
||||||
IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
|
IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
|
||||||
IO_DISK_INCREMENT : IO_NO_INCREMENT) );
|
IO_DISK_INCREMENT : IO_NO_INCREMENT) );
|
||||||
|
|
||||||
IrpContext->Irp = NULL;
|
IrpContext->Irp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2PnpRemove (
|
Ext2PnpRemove (
|
||||||
PEXT2_IRP_CONTEXT IrpContext,
|
PEXT2_IRP_CONTEXT IrpContext,
|
||||||
PEXT2_VCB Vcb )
|
PEXT2_VCB Vcb )
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
KEVENT Event;
|
KEVENT Event;
|
||||||
BOOLEAN bDeleted;
|
BOOLEAN bDeleted;
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
DEBUG(DL_PNP, ("Ext2PnpRemove by Ext2Pnp ...\n"));
|
DEBUG(DL_PNP, ("Ext2PnpRemove by Ext2Pnp ...\n"));
|
||||||
|
|
||||||
CcWaitForCurrentLazyWriterActivity();
|
CcWaitForCurrentLazyWriterActivity();
|
||||||
ExAcquireResourceExclusiveLite(
|
ExAcquireResourceExclusiveLite(
|
||||||
&Vcb->MainResource, TRUE );
|
&Vcb->MainResource, TRUE );
|
||||||
Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
|
Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup the Irp. We'll send it to the lower disk driver.
|
// Setup the Irp. We'll send it to the lower disk driver.
|
||||||
//
|
//
|
||||||
|
|
||||||
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
|
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
|
||||||
|
|
||||||
KeInitializeEvent( &Event, NotificationEvent, FALSE );
|
KeInitializeEvent( &Event, NotificationEvent, FALSE );
|
||||||
IoSetCompletionRoutine( IrpContext->Irp,
|
IoSetCompletionRoutine( IrpContext->Irp,
|
||||||
Ext2PnpCompletionRoutine,
|
Ext2PnpCompletionRoutine,
|
||||||
&Event,
|
&Event,
|
||||||
TRUE,
|
TRUE,
|
||||||
TRUE,
|
TRUE,
|
||||||
TRUE );
|
TRUE );
|
||||||
|
|
||||||
Status = IoCallDriver( Vcb->TargetDeviceObject,
|
Status = IoCallDriver( Vcb->TargetDeviceObject,
|
||||||
IrpContext->Irp);
|
IrpContext->Irp);
|
||||||
|
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
|
|
||||||
KeWaitForSingleObject( &Event,
|
KeWaitForSingleObject( &Event,
|
||||||
Executive,
|
Executive,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL );
|
NULL );
|
||||||
|
|
||||||
Status = IrpContext->Irp->IoStatus.Status;
|
Status = IrpContext->Irp->IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* purge volume cache */
|
/* purge volume cache */
|
||||||
Ext2PurgeVolume(Vcb, FALSE);
|
Ext2PurgeVolume(Vcb, FALSE);
|
||||||
|
|
||||||
/* dismount volume */
|
/* dismount volume */
|
||||||
bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
|
bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
|
||||||
SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED);
|
SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED);
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
IrpContext->Irp->IoStatus.Status = Status;
|
IrpContext->Irp->IoStatus.Status = Status;
|
||||||
Ext2CompleteRequest(
|
Ext2CompleteRequest(
|
||||||
IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
|
IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
|
||||||
IO_DISK_INCREMENT : IO_NO_INCREMENT) );
|
IO_DISK_INCREMENT : IO_NO_INCREMENT) );
|
||||||
|
|
||||||
IrpContext->Irp = NULL;
|
IrpContext->Irp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2PnpSurpriseRemove (
|
Ext2PnpSurpriseRemove (
|
||||||
PEXT2_IRP_CONTEXT IrpContext,
|
PEXT2_IRP_CONTEXT IrpContext,
|
||||||
PEXT2_VCB Vcb )
|
PEXT2_VCB Vcb )
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
KEVENT Event;
|
KEVENT Event;
|
||||||
BOOLEAN bDeleted;
|
BOOLEAN bDeleted;
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
DEBUG(DL_PNP, ("Ext2PnpSupriseRemove by Ext2Pnp ...\n"));
|
DEBUG(DL_PNP, ("Ext2PnpSupriseRemove by Ext2Pnp ...\n"));
|
||||||
|
|
||||||
CcWaitForCurrentLazyWriterActivity();
|
CcWaitForCurrentLazyWriterActivity();
|
||||||
ExAcquireResourceExclusiveLite(
|
ExAcquireResourceExclusiveLite(
|
||||||
&Vcb->MainResource, TRUE );
|
&Vcb->MainResource, TRUE );
|
||||||
|
|
||||||
Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
|
Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
|
||||||
|
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup the Irp. We'll send it to the lower disk driver.
|
// Setup the Irp. We'll send it to the lower disk driver.
|
||||||
//
|
//
|
||||||
|
|
||||||
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
|
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
|
||||||
|
|
||||||
KeInitializeEvent( &Event, NotificationEvent, FALSE );
|
KeInitializeEvent( &Event, NotificationEvent, FALSE );
|
||||||
IoSetCompletionRoutine( IrpContext->Irp,
|
IoSetCompletionRoutine( IrpContext->Irp,
|
||||||
Ext2PnpCompletionRoutine,
|
Ext2PnpCompletionRoutine,
|
||||||
&Event,
|
&Event,
|
||||||
TRUE,
|
TRUE,
|
||||||
TRUE,
|
TRUE,
|
||||||
TRUE );
|
TRUE );
|
||||||
|
|
||||||
Status = IoCallDriver( Vcb->TargetDeviceObject,
|
Status = IoCallDriver( Vcb->TargetDeviceObject,
|
||||||
IrpContext->Irp);
|
IrpContext->Irp);
|
||||||
|
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
|
|
||||||
KeWaitForSingleObject( &Event,
|
KeWaitForSingleObject( &Event,
|
||||||
Executive,
|
Executive,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL );
|
NULL );
|
||||||
|
|
||||||
Status = IrpContext->Irp->IoStatus.Status;
|
Status = IrpContext->Irp->IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* purge volume cache */
|
/* purge volume cache */
|
||||||
Ext2PurgeVolume(Vcb, FALSE);
|
Ext2PurgeVolume(Vcb, FALSE);
|
||||||
|
|
||||||
/* dismount volume */
|
/* dismount volume */
|
||||||
bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
|
bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
|
||||||
SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED);
|
SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED);
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
IrpContext->Irp->IoStatus.Status = Status;
|
IrpContext->Irp->IoStatus.Status = Status;
|
||||||
Ext2CompleteRequest(
|
Ext2CompleteRequest(
|
||||||
IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
|
IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
|
||||||
IO_DISK_INCREMENT : IO_NO_INCREMENT) );
|
IO_DISK_INCREMENT : IO_NO_INCREMENT) );
|
||||||
|
|
||||||
IrpContext->Irp = NULL;
|
IrpContext->Irp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2PnpCancelRemove (
|
Ext2PnpCancelRemove (
|
||||||
PEXT2_IRP_CONTEXT IrpContext,
|
PEXT2_IRP_CONTEXT IrpContext,
|
||||||
PEXT2_VCB Vcb
|
PEXT2_VCB Vcb
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DEBUG(DL_PNP, ("Ext2PnpCancelRemove by Ext2Pnp ...\n"));
|
DEBUG(DL_PNP, ("Ext2PnpCancelRemove by Ext2Pnp ...\n"));
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(
|
ExAcquireResourceExclusiveLite(
|
||||||
&Vcb->MainResource, TRUE );
|
&Vcb->MainResource, TRUE );
|
||||||
|
|
||||||
Status = Ext2UnlockVcb(Vcb, IrpContext->FileObject);
|
Status = Ext2UnlockVcb(Vcb, IrpContext->FileObject);
|
||||||
|
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
|
|
||||||
IoSkipCurrentIrpStackLocation(IrpContext->Irp);
|
IoSkipCurrentIrpStackLocation(IrpContext->Irp);
|
||||||
|
|
||||||
Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp);
|
Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp);
|
||||||
|
|
||||||
IrpContext->Irp = NULL;
|
IrpContext->Irp = NULL;
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //(_WIN32_WINNT >= 0x0500)
|
#endif //(_WIN32_WINNT >= 0x0500)
|
||||||
830
Ext4Fsd/rbtree.c
830
Ext4Fsd/rbtree.c
@@ -1,415 +1,415 @@
|
|||||||
/*
|
/*
|
||||||
Red Black Trees
|
Red Black Trees
|
||||||
(C) 1999 Andrea Arcangeli <andrea@suse.de>
|
(C) 1999 Andrea Arcangeli <andrea@suse.de>
|
||||||
(C) 2002 David Woodhouse <dwmw2@infradead.org>
|
(C) 2002 David Woodhouse <dwmw2@infradead.org>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
linux/lib/rbtree.c
|
linux/lib/rbtree.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
||||||
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
|
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
|
||||||
{
|
{
|
||||||
struct rb_node *right = node->rb_right;
|
struct rb_node *right = node->rb_right;
|
||||||
struct rb_node *parent = rb_parent(node);
|
struct rb_node *parent = rb_parent(node);
|
||||||
|
|
||||||
if ((node->rb_right = right->rb_left))
|
if ((node->rb_right = right->rb_left))
|
||||||
rb_set_parent(right->rb_left, node);
|
rb_set_parent(right->rb_left, node);
|
||||||
right->rb_left = node;
|
right->rb_left = node;
|
||||||
|
|
||||||
rb_set_parent(right, parent);
|
rb_set_parent(right, parent);
|
||||||
|
|
||||||
if (parent)
|
if (parent)
|
||||||
{
|
{
|
||||||
if (node == parent->rb_left)
|
if (node == parent->rb_left)
|
||||||
parent->rb_left = right;
|
parent->rb_left = right;
|
||||||
else
|
else
|
||||||
parent->rb_right = right;
|
parent->rb_right = right;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
root->rb_node = right;
|
root->rb_node = right;
|
||||||
rb_set_parent(node, right);
|
rb_set_parent(node, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
|
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
|
||||||
{
|
{
|
||||||
struct rb_node *left = node->rb_left;
|
struct rb_node *left = node->rb_left;
|
||||||
struct rb_node *parent = rb_parent(node);
|
struct rb_node *parent = rb_parent(node);
|
||||||
|
|
||||||
if ((node->rb_left = left->rb_right))
|
if ((node->rb_left = left->rb_right))
|
||||||
rb_set_parent(left->rb_right, node);
|
rb_set_parent(left->rb_right, node);
|
||||||
left->rb_right = node;
|
left->rb_right = node;
|
||||||
|
|
||||||
rb_set_parent(left, parent);
|
rb_set_parent(left, parent);
|
||||||
|
|
||||||
if (parent)
|
if (parent)
|
||||||
{
|
{
|
||||||
if (node == parent->rb_right)
|
if (node == parent->rb_right)
|
||||||
parent->rb_right = left;
|
parent->rb_right = left;
|
||||||
else
|
else
|
||||||
parent->rb_left = left;
|
parent->rb_left = left;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
root->rb_node = left;
|
root->rb_node = left;
|
||||||
rb_set_parent(node, left);
|
rb_set_parent(node, left);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rb_insert_color(struct rb_node *node, struct rb_root *root)
|
void rb_insert_color(struct rb_node *node, struct rb_root *root)
|
||||||
{
|
{
|
||||||
struct rb_node *parent, *gparent;
|
struct rb_node *parent, *gparent;
|
||||||
|
|
||||||
while ((parent = rb_parent(node)) && rb_is_red(parent))
|
while ((parent = rb_parent(node)) && rb_is_red(parent))
|
||||||
{
|
{
|
||||||
gparent = rb_parent(parent);
|
gparent = rb_parent(parent);
|
||||||
|
|
||||||
if (parent == gparent->rb_left)
|
if (parent == gparent->rb_left)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
register struct rb_node *uncle = gparent->rb_right;
|
register struct rb_node *uncle = gparent->rb_right;
|
||||||
if (uncle && rb_is_red(uncle))
|
if (uncle && rb_is_red(uncle))
|
||||||
{
|
{
|
||||||
rb_set_black(uncle);
|
rb_set_black(uncle);
|
||||||
rb_set_black(parent);
|
rb_set_black(parent);
|
||||||
rb_set_red(gparent);
|
rb_set_red(gparent);
|
||||||
node = gparent;
|
node = gparent;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent->rb_right == node)
|
if (parent->rb_right == node)
|
||||||
{
|
{
|
||||||
register struct rb_node *tmp;
|
register struct rb_node *tmp;
|
||||||
__rb_rotate_left(parent, root);
|
__rb_rotate_left(parent, root);
|
||||||
tmp = parent;
|
tmp = parent;
|
||||||
parent = node;
|
parent = node;
|
||||||
node = tmp;
|
node = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_set_black(parent);
|
rb_set_black(parent);
|
||||||
rb_set_red(gparent);
|
rb_set_red(gparent);
|
||||||
__rb_rotate_right(gparent, root);
|
__rb_rotate_right(gparent, root);
|
||||||
} else {
|
} else {
|
||||||
{
|
{
|
||||||
register struct rb_node *uncle = gparent->rb_left;
|
register struct rb_node *uncle = gparent->rb_left;
|
||||||
if (uncle && rb_is_red(uncle))
|
if (uncle && rb_is_red(uncle))
|
||||||
{
|
{
|
||||||
rb_set_black(uncle);
|
rb_set_black(uncle);
|
||||||
rb_set_black(parent);
|
rb_set_black(parent);
|
||||||
rb_set_red(gparent);
|
rb_set_red(gparent);
|
||||||
node = gparent;
|
node = gparent;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent->rb_left == node)
|
if (parent->rb_left == node)
|
||||||
{
|
{
|
||||||
register struct rb_node *tmp;
|
register struct rb_node *tmp;
|
||||||
__rb_rotate_right(parent, root);
|
__rb_rotate_right(parent, root);
|
||||||
tmp = parent;
|
tmp = parent;
|
||||||
parent = node;
|
parent = node;
|
||||||
node = tmp;
|
node = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_set_black(parent);
|
rb_set_black(parent);
|
||||||
rb_set_red(gparent);
|
rb_set_red(gparent);
|
||||||
__rb_rotate_left(gparent, root);
|
__rb_rotate_left(gparent, root);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_set_black(root->rb_node);
|
rb_set_black(root->rb_node);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(rb_insert_color);
|
EXPORT_SYMBOL(rb_insert_color);
|
||||||
|
|
||||||
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
|
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
|
||||||
struct rb_root *root)
|
struct rb_root *root)
|
||||||
{
|
{
|
||||||
struct rb_node *other;
|
struct rb_node *other;
|
||||||
|
|
||||||
while ((!node || rb_is_black(node)) && node != root->rb_node)
|
while ((!node || rb_is_black(node)) && node != root->rb_node)
|
||||||
{
|
{
|
||||||
if (parent->rb_left == node)
|
if (parent->rb_left == node)
|
||||||
{
|
{
|
||||||
other = parent->rb_right;
|
other = parent->rb_right;
|
||||||
if (rb_is_red(other))
|
if (rb_is_red(other))
|
||||||
{
|
{
|
||||||
rb_set_black(other);
|
rb_set_black(other);
|
||||||
rb_set_red(parent);
|
rb_set_red(parent);
|
||||||
__rb_rotate_left(parent, root);
|
__rb_rotate_left(parent, root);
|
||||||
other = parent->rb_right;
|
other = parent->rb_right;
|
||||||
}
|
}
|
||||||
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
|
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
|
||||||
(!other->rb_right || rb_is_black(other->rb_right)))
|
(!other->rb_right || rb_is_black(other->rb_right)))
|
||||||
{
|
{
|
||||||
rb_set_red(other);
|
rb_set_red(other);
|
||||||
node = parent;
|
node = parent;
|
||||||
parent = rb_parent(node);
|
parent = rb_parent(node);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!other->rb_right || rb_is_black(other->rb_right))
|
if (!other->rb_right || rb_is_black(other->rb_right))
|
||||||
{
|
{
|
||||||
struct rb_node *o_left;
|
struct rb_node *o_left;
|
||||||
if ((o_left = other->rb_left))
|
if ((o_left = other->rb_left))
|
||||||
rb_set_black(o_left);
|
rb_set_black(o_left);
|
||||||
rb_set_red(other);
|
rb_set_red(other);
|
||||||
__rb_rotate_right(other, root);
|
__rb_rotate_right(other, root);
|
||||||
other = parent->rb_right;
|
other = parent->rb_right;
|
||||||
}
|
}
|
||||||
rb_set_color(other, rb_color(parent));
|
rb_set_color(other, rb_color(parent));
|
||||||
rb_set_black(parent);
|
rb_set_black(parent);
|
||||||
if (other->rb_right)
|
if (other->rb_right)
|
||||||
rb_set_black(other->rb_right);
|
rb_set_black(other->rb_right);
|
||||||
__rb_rotate_left(parent, root);
|
__rb_rotate_left(parent, root);
|
||||||
node = root->rb_node;
|
node = root->rb_node;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
other = parent->rb_left;
|
other = parent->rb_left;
|
||||||
if (rb_is_red(other))
|
if (rb_is_red(other))
|
||||||
{
|
{
|
||||||
rb_set_black(other);
|
rb_set_black(other);
|
||||||
rb_set_red(parent);
|
rb_set_red(parent);
|
||||||
__rb_rotate_right(parent, root);
|
__rb_rotate_right(parent, root);
|
||||||
other = parent->rb_left;
|
other = parent->rb_left;
|
||||||
}
|
}
|
||||||
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
|
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
|
||||||
(!other->rb_right || rb_is_black(other->rb_right)))
|
(!other->rb_right || rb_is_black(other->rb_right)))
|
||||||
{
|
{
|
||||||
rb_set_red(other);
|
rb_set_red(other);
|
||||||
node = parent;
|
node = parent;
|
||||||
parent = rb_parent(node);
|
parent = rb_parent(node);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!other->rb_left || rb_is_black(other->rb_left))
|
if (!other->rb_left || rb_is_black(other->rb_left))
|
||||||
{
|
{
|
||||||
register struct rb_node *o_right;
|
register struct rb_node *o_right;
|
||||||
if ((o_right = other->rb_right))
|
if ((o_right = other->rb_right))
|
||||||
rb_set_black(o_right);
|
rb_set_black(o_right);
|
||||||
rb_set_red(other);
|
rb_set_red(other);
|
||||||
__rb_rotate_left(other, root);
|
__rb_rotate_left(other, root);
|
||||||
other = parent->rb_left;
|
other = parent->rb_left;
|
||||||
}
|
}
|
||||||
rb_set_color(other, rb_color(parent));
|
rb_set_color(other, rb_color(parent));
|
||||||
rb_set_black(parent);
|
rb_set_black(parent);
|
||||||
if (other->rb_left)
|
if (other->rb_left)
|
||||||
rb_set_black(other->rb_left);
|
rb_set_black(other->rb_left);
|
||||||
__rb_rotate_right(parent, root);
|
__rb_rotate_right(parent, root);
|
||||||
node = root->rb_node;
|
node = root->rb_node;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node)
|
if (node)
|
||||||
rb_set_black(node);
|
rb_set_black(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rb_erase(struct rb_node *node, struct rb_root *root)
|
void rb_erase(struct rb_node *node, struct rb_root *root)
|
||||||
{
|
{
|
||||||
struct rb_node *child, *parent;
|
struct rb_node *child, *parent;
|
||||||
ULONG_PTR color;
|
ULONG_PTR color;
|
||||||
|
|
||||||
if (!node->rb_left)
|
if (!node->rb_left)
|
||||||
child = node->rb_right;
|
child = node->rb_right;
|
||||||
else if (!node->rb_right)
|
else if (!node->rb_right)
|
||||||
child = node->rb_left;
|
child = node->rb_left;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct rb_node *old = node, *left;
|
struct rb_node *old = node, *left;
|
||||||
|
|
||||||
node = node->rb_right;
|
node = node->rb_right;
|
||||||
while ((left = node->rb_left) != NULL)
|
while ((left = node->rb_left) != NULL)
|
||||||
node = left;
|
node = left;
|
||||||
child = node->rb_right;
|
child = node->rb_right;
|
||||||
parent = rb_parent(node);
|
parent = rb_parent(node);
|
||||||
color = rb_color(node);
|
color = rb_color(node);
|
||||||
|
|
||||||
if (child)
|
if (child)
|
||||||
rb_set_parent(child, parent);
|
rb_set_parent(child, parent);
|
||||||
if (parent == old) {
|
if (parent == old) {
|
||||||
parent->rb_right = child;
|
parent->rb_right = child;
|
||||||
parent = node;
|
parent = node;
|
||||||
} else
|
} else
|
||||||
parent->rb_left = child;
|
parent->rb_left = child;
|
||||||
|
|
||||||
node->rb_parent_color = old->rb_parent_color;
|
node->rb_parent_color = old->rb_parent_color;
|
||||||
node->rb_right = old->rb_right;
|
node->rb_right = old->rb_right;
|
||||||
node->rb_left = old->rb_left;
|
node->rb_left = old->rb_left;
|
||||||
|
|
||||||
if (rb_parent(old))
|
if (rb_parent(old))
|
||||||
{
|
{
|
||||||
if (rb_parent(old)->rb_left == old)
|
if (rb_parent(old)->rb_left == old)
|
||||||
rb_parent(old)->rb_left = node;
|
rb_parent(old)->rb_left = node;
|
||||||
else
|
else
|
||||||
rb_parent(old)->rb_right = node;
|
rb_parent(old)->rb_right = node;
|
||||||
} else
|
} else
|
||||||
root->rb_node = node;
|
root->rb_node = node;
|
||||||
|
|
||||||
rb_set_parent(old->rb_left, node);
|
rb_set_parent(old->rb_left, node);
|
||||||
if (old->rb_right)
|
if (old->rb_right)
|
||||||
rb_set_parent(old->rb_right, node);
|
rb_set_parent(old->rb_right, node);
|
||||||
goto color;
|
goto color;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent = rb_parent(node);
|
parent = rb_parent(node);
|
||||||
color = rb_color(node);
|
color = rb_color(node);
|
||||||
|
|
||||||
if (child)
|
if (child)
|
||||||
rb_set_parent(child, parent);
|
rb_set_parent(child, parent);
|
||||||
if (parent)
|
if (parent)
|
||||||
{
|
{
|
||||||
if (parent->rb_left == node)
|
if (parent->rb_left == node)
|
||||||
parent->rb_left = child;
|
parent->rb_left = child;
|
||||||
else
|
else
|
||||||
parent->rb_right = child;
|
parent->rb_right = child;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
root->rb_node = child;
|
root->rb_node = child;
|
||||||
|
|
||||||
color:
|
color:
|
||||||
if (color == RB_BLACK)
|
if (color == RB_BLACK)
|
||||||
__rb_erase_color(child, parent, root);
|
__rb_erase_color(child, parent, root);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(rb_erase);
|
EXPORT_SYMBOL(rb_erase);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function returns the first node (in sort order) of the tree.
|
* This function returns the first node (in sort order) of the tree.
|
||||||
*/
|
*/
|
||||||
struct rb_node *rb_first(struct rb_root *root)
|
struct rb_node *rb_first(struct rb_root *root)
|
||||||
{
|
{
|
||||||
struct rb_node *n;
|
struct rb_node *n;
|
||||||
|
|
||||||
n = root->rb_node;
|
n = root->rb_node;
|
||||||
if (!n)
|
if (!n)
|
||||||
return NULL;
|
return NULL;
|
||||||
while (n->rb_left)
|
while (n->rb_left)
|
||||||
n = n->rb_left;
|
n = n->rb_left;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(rb_first);
|
EXPORT_SYMBOL(rb_first);
|
||||||
|
|
||||||
struct rb_node *rb_last(struct rb_root *root)
|
struct rb_node *rb_last(struct rb_root *root)
|
||||||
{
|
{
|
||||||
struct rb_node *n;
|
struct rb_node *n;
|
||||||
|
|
||||||
n = root->rb_node;
|
n = root->rb_node;
|
||||||
if (!n)
|
if (!n)
|
||||||
return NULL;
|
return NULL;
|
||||||
while (n->rb_right)
|
while (n->rb_right)
|
||||||
n = n->rb_right;
|
n = n->rb_right;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(rb_last);
|
EXPORT_SYMBOL(rb_last);
|
||||||
|
|
||||||
struct rb_node *rb_next(struct rb_node *node)
|
struct rb_node *rb_next(struct rb_node *node)
|
||||||
{
|
{
|
||||||
struct rb_node *parent;
|
struct rb_node *parent;
|
||||||
|
|
||||||
/* If we have a right-hand child, go down and then left as far
|
/* If we have a right-hand child, go down and then left as far
|
||||||
as we can. */
|
as we can. */
|
||||||
if (node->rb_right) {
|
if (node->rb_right) {
|
||||||
node = node->rb_right;
|
node = node->rb_right;
|
||||||
while (node->rb_left)
|
while (node->rb_left)
|
||||||
node=node->rb_left;
|
node=node->rb_left;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No right-hand children. Everything down and left is
|
/* No right-hand children. Everything down and left is
|
||||||
smaller than us, so any 'next' node must be in the general
|
smaller than us, so any 'next' node must be in the general
|
||||||
direction of our parent. Go up the tree; any time the
|
direction of our parent. Go up the tree; any time the
|
||||||
ancestor is a right-hand child of its parent, keep going
|
ancestor is a right-hand child of its parent, keep going
|
||||||
up. First time it's a left-hand child of its parent, said
|
up. First time it's a left-hand child of its parent, said
|
||||||
parent is our 'next' node. */
|
parent is our 'next' node. */
|
||||||
while ((parent = rb_parent(node)) && node == parent->rb_right)
|
while ((parent = rb_parent(node)) && node == parent->rb_right)
|
||||||
node = parent;
|
node = parent;
|
||||||
|
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(rb_next);
|
EXPORT_SYMBOL(rb_next);
|
||||||
|
|
||||||
struct rb_node *rb_prev(struct rb_node *node)
|
struct rb_node *rb_prev(struct rb_node *node)
|
||||||
{
|
{
|
||||||
struct rb_node *parent;
|
struct rb_node *parent;
|
||||||
|
|
||||||
/* If we have a left-hand child, go down and then right as far
|
/* If we have a left-hand child, go down and then right as far
|
||||||
as we can. */
|
as we can. */
|
||||||
if (node->rb_left) {
|
if (node->rb_left) {
|
||||||
node = node->rb_left;
|
node = node->rb_left;
|
||||||
while (node->rb_right)
|
while (node->rb_right)
|
||||||
node=node->rb_right;
|
node=node->rb_right;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No left-hand children. Go up till we find an ancestor which
|
/* No left-hand children. Go up till we find an ancestor which
|
||||||
is a right-hand child of its parent */
|
is a right-hand child of its parent */
|
||||||
while ((parent = rb_parent(node)) && node == parent->rb_left)
|
while ((parent = rb_parent(node)) && node == parent->rb_left)
|
||||||
node = parent;
|
node = parent;
|
||||||
|
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(rb_prev);
|
EXPORT_SYMBOL(rb_prev);
|
||||||
|
|
||||||
void rb_replace_node(struct rb_node *victim, struct rb_node *new,
|
void rb_replace_node(struct rb_node *victim, struct rb_node *new,
|
||||||
struct rb_root *root)
|
struct rb_root *root)
|
||||||
{
|
{
|
||||||
struct rb_node *parent = rb_parent(victim);
|
struct rb_node *parent = rb_parent(victim);
|
||||||
|
|
||||||
/* Set the surrounding nodes to point to the replacement */
|
/* Set the surrounding nodes to point to the replacement */
|
||||||
if (parent) {
|
if (parent) {
|
||||||
if (victim == parent->rb_left)
|
if (victim == parent->rb_left)
|
||||||
parent->rb_left = new;
|
parent->rb_left = new;
|
||||||
else
|
else
|
||||||
parent->rb_right = new;
|
parent->rb_right = new;
|
||||||
} else {
|
} else {
|
||||||
root->rb_node = new;
|
root->rb_node = new;
|
||||||
}
|
}
|
||||||
if (victim->rb_left)
|
if (victim->rb_left)
|
||||||
rb_set_parent(victim->rb_left, new);
|
rb_set_parent(victim->rb_left, new);
|
||||||
if (victim->rb_right)
|
if (victim->rb_right)
|
||||||
rb_set_parent(victim->rb_right, new);
|
rb_set_parent(victim->rb_right, new);
|
||||||
|
|
||||||
/* Copy the pointers/colour from the victim to the replacement */
|
/* Copy the pointers/colour from the victim to the replacement */
|
||||||
*new = *victim;
|
*new = *victim;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(rb_replace_node);
|
EXPORT_SYMBOL(rb_replace_node);
|
||||||
|
|
||||||
void rb_insert(struct rb_root *root, struct rb_node *node,
|
void rb_insert(struct rb_root *root, struct rb_node *node,
|
||||||
int (*cmp)(struct rb_node *, struct rb_node *))
|
int (*cmp)(struct rb_node *, struct rb_node *))
|
||||||
{
|
{
|
||||||
struct rb_node **new = &(root->rb_node), *parent = NULL;
|
struct rb_node **new = &(root->rb_node), *parent = NULL;
|
||||||
|
|
||||||
/* Figure out where to put new node */
|
/* Figure out where to put new node */
|
||||||
while (*new) {
|
while (*new) {
|
||||||
int result = cmp(node, *new);
|
int result = cmp(node, *new);
|
||||||
|
|
||||||
parent = *new;
|
parent = *new;
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
new = &((*new)->rb_left);
|
new = &((*new)->rb_left);
|
||||||
else if (result > 0)
|
else if (result > 0)
|
||||||
new = &((*new)->rb_right);
|
new = &((*new)->rb_right);
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add new node and rebalance tree. */
|
/* Add new node and rebalance tree. */
|
||||||
rb_link_node(node, parent, new);
|
rb_link_node(node, parent, new);
|
||||||
rb_insert_color(node, root);
|
rb_insert_color(node, root);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(rb_insert);
|
EXPORT_SYMBOL(rb_insert);
|
||||||
|
|||||||
1890
Ext4Fsd/read.c
1890
Ext4Fsd/read.c
File diff suppressed because it is too large
Load Diff
@@ -1,118 +1,118 @@
|
|||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYRIGHT.TXT
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: shutdown.c
|
* FILE: shutdown.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://www.ext2fsd.com
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
/* GLOBALS ***************************************************************/
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
extern PEXT2_GLOBAL Ext2Global;
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, Ext2ShutDown)
|
#pragma alloc_text(PAGE, Ext2ShutDown)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2ShutDown (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2ShutDown (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
|
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb;
|
||||||
PLIST_ENTRY ListEntry;
|
PLIST_ENTRY ListEntry;
|
||||||
|
|
||||||
BOOLEAN GlobalResourceAcquired = FALSE;
|
BOOLEAN GlobalResourceAcquired = FALSE;
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
ASSERT(IrpContext);
|
ASSERT(IrpContext);
|
||||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
Irp = IrpContext->Irp;
|
Irp = IrpContext->Irp;
|
||||||
|
|
||||||
if (!ExAcquireResourceExclusiveLite(
|
if (!ExAcquireResourceExclusiveLite(
|
||||||
&Ext2Global->Resource,
|
&Ext2Global->Resource,
|
||||||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
|
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
|
||||||
Status = STATUS_PENDING;
|
Status = STATUS_PENDING;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalResourceAcquired = TRUE;
|
GlobalResourceAcquired = TRUE;
|
||||||
|
|
||||||
for (ListEntry = Ext2Global->VcbList.Flink;
|
for (ListEntry = Ext2Global->VcbList.Flink;
|
||||||
ListEntry != &(Ext2Global->VcbList);
|
ListEntry != &(Ext2Global->VcbList);
|
||||||
ListEntry = ListEntry->Flink ) {
|
ListEntry = ListEntry->Flink ) {
|
||||||
|
|
||||||
Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next);
|
Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next);
|
||||||
|
|
||||||
if (ExAcquireResourceExclusiveLite(
|
if (ExAcquireResourceExclusiveLite(
|
||||||
&Vcb->MainResource,
|
&Vcb->MainResource,
|
||||||
TRUE )) {
|
TRUE )) {
|
||||||
|
|
||||||
if (IsMounted(Vcb)) {
|
if (IsMounted(Vcb)) {
|
||||||
|
|
||||||
/* update mount count */
|
/* update mount count */
|
||||||
Vcb->SuperBlock->s_mnt_count++;
|
Vcb->SuperBlock->s_mnt_count++;
|
||||||
if (Vcb->SuperBlock->s_mnt_count >
|
if (Vcb->SuperBlock->s_mnt_count >
|
||||||
Vcb->SuperBlock->s_max_mnt_count ) {
|
Vcb->SuperBlock->s_max_mnt_count ) {
|
||||||
Vcb->SuperBlock->s_mnt_count =
|
Vcb->SuperBlock->s_mnt_count =
|
||||||
Vcb->SuperBlock->s_max_mnt_count;
|
Vcb->SuperBlock->s_max_mnt_count;
|
||||||
}
|
}
|
||||||
Ext2SaveSuper(IrpContext, Vcb);
|
Ext2SaveSuper(IrpContext, Vcb);
|
||||||
|
|
||||||
/* flush dirty cache for all files */
|
/* flush dirty cache for all files */
|
||||||
Status = Ext2FlushFiles(IrpContext, Vcb, TRUE);
|
Status = Ext2FlushFiles(IrpContext, Vcb, TRUE);
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* flush volume stream's cache to disk */
|
/* flush volume stream's cache to disk */
|
||||||
Status = Ext2FlushVolume(IrpContext, Vcb, TRUE);
|
Status = Ext2FlushVolume(IrpContext, Vcb, TRUE);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status) && Status != STATUS_MEDIA_WRITE_PROTECTED) {
|
if (!NT_SUCCESS(Status) && Status != STATUS_MEDIA_WRITE_PROTECTED) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send shutdown request to underlying disk */
|
/* send shutdown request to underlying disk */
|
||||||
Ext2DiskShutDown(Vcb);
|
Ext2DiskShutDown(Vcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
IoUnregisterFileSystem(Ext2Global->DiskdevObject);
|
IoUnregisterFileSystem(Ext2Global->DiskdevObject);
|
||||||
IoUnregisterFileSystem(Ext2Global->CdromdevObject);
|
IoUnregisterFileSystem(Ext2Global->CdromdevObject);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
if (GlobalResourceAcquired) {
|
if (GlobalResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Ext2Global->Resource);
|
ExReleaseResourceLite(&Ext2Global->Resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IrpContext->ExceptionInProgress) {
|
if (!IrpContext->ExceptionInProgress) {
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
Ext2QueueRequest(IrpContext);
|
Ext2QueueRequest(IrpContext);
|
||||||
} else {
|
} else {
|
||||||
Ext2CompleteIrpContext(IrpContext, Status);
|
Ext2CompleteIrpContext(IrpContext, Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
@@ -1,409 +1,409 @@
|
|||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYRIGHT.TXT
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: volinfo.c
|
* FILE: volinfo.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://www.ext2fsd.com
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
/* GLOBALS ***************************************************************/
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
extern PEXT2_GLOBAL Ext2Global;
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, Ext2QueryVolumeInformation)
|
#pragma alloc_text(PAGE, Ext2QueryVolumeInformation)
|
||||||
#pragma alloc_text(PAGE, Ext2SetVolumeInformation)
|
#pragma alloc_text(PAGE, Ext2SetVolumeInformation)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
PEXT2_VCB Vcb = NULL;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PIRP Irp = NULL;
|
PIRP Irp = NULL;
|
||||||
PIO_STACK_LOCATION IoStackLocation = NULL;
|
PIO_STACK_LOCATION IoStackLocation = NULL;
|
||||||
PVOID Buffer;
|
PVOID Buffer;
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
FS_INFORMATION_CLASS FsInformationClass;
|
FS_INFORMATION_CLASS FsInformationClass;
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
ASSERT(IrpContext != NULL);
|
ASSERT(IrpContext != NULL);
|
||||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
DeviceObject = IrpContext->DeviceObject;
|
DeviceObject = IrpContext->DeviceObject;
|
||||||
|
|
||||||
//
|
//
|
||||||
// This request is not allowed on the main device object
|
// This request is not allowed on the main device object
|
||||||
//
|
//
|
||||||
if (IsExt2FsDevice(DeviceObject)) {
|
if (IsExt2FsDevice(DeviceObject)) {
|
||||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
|
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
|
||||||
ASSERT(Vcb != NULL);
|
ASSERT(Vcb != NULL);
|
||||||
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
||||||
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
|
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
|
||||||
|
|
||||||
if (!IsMounted(Vcb)) {
|
if (!IsMounted(Vcb)) {
|
||||||
Status = STATUS_VOLUME_DISMOUNTED;
|
Status = STATUS_VOLUME_DISMOUNTED;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ExAcquireResourceSharedLite(
|
if (!ExAcquireResourceSharedLite(
|
||||||
&Vcb->MainResource,
|
&Vcb->MainResource,
|
||||||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
|
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
|
||||||
)) {
|
)) {
|
||||||
|
|
||||||
Status = STATUS_PENDING;
|
Status = STATUS_PENDING;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
VcbResourceAcquired = TRUE;
|
VcbResourceAcquired = TRUE;
|
||||||
|
|
||||||
Irp = IrpContext->Irp;
|
Irp = IrpContext->Irp;
|
||||||
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
||||||
FsInformationClass =
|
FsInformationClass =
|
||||||
IoStackLocation->Parameters.QueryVolume.FsInformationClass;
|
IoStackLocation->Parameters.QueryVolume.FsInformationClass;
|
||||||
|
|
||||||
Length = IoStackLocation->Parameters.QueryVolume.Length;
|
Length = IoStackLocation->Parameters.QueryVolume.Length;
|
||||||
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
RtlZeroMemory(Buffer, Length);
|
RtlZeroMemory(Buffer, Length);
|
||||||
|
|
||||||
switch (FsInformationClass) {
|
switch (FsInformationClass) {
|
||||||
|
|
||||||
case FileFsVolumeInformation:
|
case FileFsVolumeInformation:
|
||||||
{
|
{
|
||||||
PFILE_FS_VOLUME_INFORMATION FsVolInfo;
|
PFILE_FS_VOLUME_INFORMATION FsVolInfo;
|
||||||
ULONG VolumeLabelLength;
|
ULONG VolumeLabelLength;
|
||||||
ULONG RequiredLength;
|
ULONG RequiredLength;
|
||||||
|
|
||||||
if (Length < sizeof(FILE_FS_VOLUME_INFORMATION)) {
|
if (Length < sizeof(FILE_FS_VOLUME_INFORMATION)) {
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsVolInfo = (PFILE_FS_VOLUME_INFORMATION) Buffer;
|
FsVolInfo = (PFILE_FS_VOLUME_INFORMATION) Buffer;
|
||||||
FsVolInfo->VolumeCreationTime.QuadPart = 0;
|
FsVolInfo->VolumeCreationTime.QuadPart = 0;
|
||||||
FsVolInfo->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
|
FsVolInfo->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
|
||||||
VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
|
VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
|
||||||
FsVolInfo->VolumeLabelLength = VolumeLabelLength;
|
FsVolInfo->VolumeLabelLength = VolumeLabelLength;
|
||||||
/* We don't support ObjectId */
|
/* We don't support ObjectId */
|
||||||
FsVolInfo->SupportsObjects = FALSE;
|
FsVolInfo->SupportsObjects = FALSE;
|
||||||
|
|
||||||
RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION)
|
RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION)
|
||||||
+ VolumeLabelLength - sizeof(WCHAR);
|
+ VolumeLabelLength - sizeof(WCHAR);
|
||||||
|
|
||||||
if (Length < RequiredLength) {
|
if (Length < RequiredLength) {
|
||||||
Irp->IoStatus.Information =
|
Irp->IoStatus.Information =
|
||||||
sizeof(FILE_FS_VOLUME_INFORMATION);
|
sizeof(FILE_FS_VOLUME_INFORMATION);
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlCopyMemory(FsVolInfo->VolumeLabel, Vcb->Vpb->VolumeLabel, Vcb->Vpb->VolumeLabelLength);
|
RtlCopyMemory(FsVolInfo->VolumeLabel, Vcb->Vpb->VolumeLabel, Vcb->Vpb->VolumeLabelLength);
|
||||||
|
|
||||||
Irp->IoStatus.Information = RequiredLength;
|
Irp->IoStatus.Information = RequiredLength;
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileFsSizeInformation:
|
case FileFsSizeInformation:
|
||||||
{
|
{
|
||||||
PFILE_FS_SIZE_INFORMATION FsSizeInfo;
|
PFILE_FS_SIZE_INFORMATION FsSizeInfo;
|
||||||
|
|
||||||
if (Length < sizeof(FILE_FS_SIZE_INFORMATION)) {
|
if (Length < sizeof(FILE_FS_SIZE_INFORMATION)) {
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsSizeInfo = (PFILE_FS_SIZE_INFORMATION) Buffer;
|
FsSizeInfo = (PFILE_FS_SIZE_INFORMATION) Buffer;
|
||||||
FsSizeInfo->TotalAllocationUnits.QuadPart =
|
FsSizeInfo->TotalAllocationUnits.QuadPart =
|
||||||
ext3_blocks_count(SUPER_BLOCK);
|
ext3_blocks_count(SUPER_BLOCK);
|
||||||
FsSizeInfo->AvailableAllocationUnits.QuadPart =
|
FsSizeInfo->AvailableAllocationUnits.QuadPart =
|
||||||
ext3_free_blocks_count(SUPER_BLOCK);
|
ext3_free_blocks_count(SUPER_BLOCK);
|
||||||
FsSizeInfo->SectorsPerAllocationUnit =
|
FsSizeInfo->SectorsPerAllocationUnit =
|
||||||
Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
|
Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
|
||||||
FsSizeInfo->BytesPerSector =
|
FsSizeInfo->BytesPerSector =
|
||||||
Vcb->DiskGeometry.BytesPerSector;
|
Vcb->DiskGeometry.BytesPerSector;
|
||||||
|
|
||||||
Irp->IoStatus.Information = sizeof(FILE_FS_SIZE_INFORMATION);
|
Irp->IoStatus.Information = sizeof(FILE_FS_SIZE_INFORMATION);
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileFsDeviceInformation:
|
case FileFsDeviceInformation:
|
||||||
{
|
{
|
||||||
PFILE_FS_DEVICE_INFORMATION FsDevInfo;
|
PFILE_FS_DEVICE_INFORMATION FsDevInfo;
|
||||||
|
|
||||||
if (Length < sizeof(FILE_FS_DEVICE_INFORMATION)) {
|
if (Length < sizeof(FILE_FS_DEVICE_INFORMATION)) {
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsDevInfo = (PFILE_FS_DEVICE_INFORMATION) Buffer;
|
FsDevInfo = (PFILE_FS_DEVICE_INFORMATION) Buffer;
|
||||||
FsDevInfo->DeviceType =
|
FsDevInfo->DeviceType =
|
||||||
Vcb->TargetDeviceObject->DeviceType;
|
Vcb->TargetDeviceObject->DeviceType;
|
||||||
|
|
||||||
if (FsDevInfo->DeviceType != FILE_DEVICE_DISK) {
|
if (FsDevInfo->DeviceType != FILE_DEVICE_DISK) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
FsDevInfo->Characteristics =
|
FsDevInfo->Characteristics =
|
||||||
Vcb->TargetDeviceObject->Characteristics;
|
Vcb->TargetDeviceObject->Characteristics;
|
||||||
|
|
||||||
if (IsVcbReadOnly(Vcb)) {
|
if (IsVcbReadOnly(Vcb)) {
|
||||||
SetFlag( FsDevInfo->Characteristics,
|
SetFlag( FsDevInfo->Characteristics,
|
||||||
FILE_READ_ONLY_DEVICE );
|
FILE_READ_ONLY_DEVICE );
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION);
|
Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION);
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileFsAttributeInformation:
|
case FileFsAttributeInformation:
|
||||||
{
|
{
|
||||||
PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo;
|
PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo;
|
||||||
ULONG RequiredLength;
|
ULONG RequiredLength;
|
||||||
|
|
||||||
if (Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) {
|
if (Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) {
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsAttrInfo =
|
FsAttrInfo =
|
||||||
(PFILE_FS_ATTRIBUTE_INFORMATION) Buffer;
|
(PFILE_FS_ATTRIBUTE_INFORMATION) Buffer;
|
||||||
FsAttrInfo->FileSystemAttributes = FILE_SUPPORTS_HARD_LINKS |
|
FsAttrInfo->FileSystemAttributes = FILE_SUPPORTS_HARD_LINKS |
|
||||||
FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
|
FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
|
||||||
FILE_SUPPORTS_REPARSE_POINTS | FILE_SUPPORTS_EXTENDED_ATTRIBUTES;
|
FILE_SUPPORTS_REPARSE_POINTS | FILE_SUPPORTS_EXTENDED_ATTRIBUTES;
|
||||||
if (IsVcbReadOnly(Vcb)) {
|
if (IsVcbReadOnly(Vcb)) {
|
||||||
FsAttrInfo->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
|
FsAttrInfo->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
|
||||||
}
|
}
|
||||||
FsAttrInfo->MaximumComponentNameLength = EXT2_NAME_LEN;
|
FsAttrInfo->MaximumComponentNameLength = EXT2_NAME_LEN;
|
||||||
FsAttrInfo->FileSystemNameLength = 8;
|
FsAttrInfo->FileSystemNameLength = 8;
|
||||||
|
|
||||||
RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) +
|
RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) +
|
||||||
8 - sizeof(WCHAR);
|
8 - sizeof(WCHAR);
|
||||||
|
|
||||||
if (Length < RequiredLength) {
|
if (Length < RequiredLength) {
|
||||||
Irp->IoStatus.Information =
|
Irp->IoStatus.Information =
|
||||||
sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
|
sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
|
if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
|
||||||
RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT4\0", 10);
|
RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT4\0", 10);
|
||||||
} else if (Vcb->IsExt3fs) {
|
} else if (Vcb->IsExt3fs) {
|
||||||
RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT3\0", 10);
|
RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT3\0", 10);
|
||||||
} else {
|
} else {
|
||||||
RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT2\0", 10);
|
RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT2\0", 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Information = RequiredLength;
|
Irp->IoStatus.Information = RequiredLength;
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if (_WIN32_WINNT >= 0x0500)
|
#if (_WIN32_WINNT >= 0x0500)
|
||||||
|
|
||||||
case FileFsFullSizeInformation:
|
case FileFsFullSizeInformation:
|
||||||
{
|
{
|
||||||
PFILE_FS_FULL_SIZE_INFORMATION PFFFSI;
|
PFILE_FS_FULL_SIZE_INFORMATION PFFFSI;
|
||||||
|
|
||||||
if (Length < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) {
|
if (Length < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) {
|
||||||
Status = STATUS_BUFFER_OVERFLOW;
|
Status = STATUS_BUFFER_OVERFLOW;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
PFFFSI = (PFILE_FS_FULL_SIZE_INFORMATION) Buffer;
|
PFFFSI = (PFILE_FS_FULL_SIZE_INFORMATION) Buffer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
typedef struct _FILE_FS_FULL_SIZE_INFORMATION {
|
typedef struct _FILE_FS_FULL_SIZE_INFORMATION {
|
||||||
LARGE_INTEGER TotalAllocationUnits;
|
LARGE_INTEGER TotalAllocationUnits;
|
||||||
LARGE_INTEGER CallerAvailableAllocationUnits;
|
LARGE_INTEGER CallerAvailableAllocationUnits;
|
||||||
LARGE_INTEGER ActualAvailableAllocationUnits;
|
LARGE_INTEGER ActualAvailableAllocationUnits;
|
||||||
ULONG SectorsPerAllocationUnit;
|
ULONG SectorsPerAllocationUnit;
|
||||||
ULONG BytesPerSector;
|
ULONG BytesPerSector;
|
||||||
} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
|
} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
{
|
{
|
||||||
PFFFSI->TotalAllocationUnits.QuadPart =
|
PFFFSI->TotalAllocationUnits.QuadPart =
|
||||||
ext3_blocks_count(SUPER_BLOCK);
|
ext3_blocks_count(SUPER_BLOCK);
|
||||||
|
|
||||||
PFFFSI->CallerAvailableAllocationUnits.QuadPart =
|
PFFFSI->CallerAvailableAllocationUnits.QuadPart =
|
||||||
ext3_free_blocks_count(SUPER_BLOCK);
|
ext3_free_blocks_count(SUPER_BLOCK);
|
||||||
|
|
||||||
/* - Vcb->SuperBlock->s_r_blocks_count; */
|
/* - Vcb->SuperBlock->s_r_blocks_count; */
|
||||||
PFFFSI->ActualAvailableAllocationUnits.QuadPart =
|
PFFFSI->ActualAvailableAllocationUnits.QuadPart =
|
||||||
ext3_free_blocks_count(SUPER_BLOCK);
|
ext3_free_blocks_count(SUPER_BLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
PFFFSI->SectorsPerAllocationUnit =
|
PFFFSI->SectorsPerAllocationUnit =
|
||||||
Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
|
Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
|
||||||
|
|
||||||
PFFFSI->BytesPerSector = Vcb->DiskGeometry.BytesPerSector;
|
PFFFSI->BytesPerSector = Vcb->DiskGeometry.BytesPerSector;
|
||||||
|
|
||||||
Irp->IoStatus.Information = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
|
Irp->IoStatus.Information = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#endif // (_WIN32_WINNT >= 0x0500)
|
#endif // (_WIN32_WINNT >= 0x0500)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Status = STATUS_INVALID_INFO_CLASS;
|
Status = STATUS_INVALID_INFO_CLASS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
if (VcbResourceAcquired) {
|
if (VcbResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IrpContext->ExceptionInProgress) {
|
if (!IrpContext->ExceptionInProgress) {
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
Ext2QueueRequest(IrpContext);
|
Ext2QueueRequest(IrpContext);
|
||||||
} else {
|
} else {
|
||||||
Ext2CompleteIrpContext(IrpContext, Status);
|
Ext2CompleteIrpContext(IrpContext, Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
PEXT2_VCB Vcb = NULL;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
PIO_STACK_LOCATION IoStackLocation;
|
PIO_STACK_LOCATION IoStackLocation;
|
||||||
FS_INFORMATION_CLASS FsInformationClass;
|
FS_INFORMATION_CLASS FsInformationClass;
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
|
|
||||||
__try {
|
__try {
|
||||||
|
|
||||||
ASSERT(IrpContext != NULL);
|
ASSERT(IrpContext != NULL);
|
||||||
|
|
||||||
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
DeviceObject = IrpContext->DeviceObject;
|
DeviceObject = IrpContext->DeviceObject;
|
||||||
|
|
||||||
//
|
//
|
||||||
// This request is not allowed on the main device object
|
// This request is not allowed on the main device object
|
||||||
//
|
//
|
||||||
if (IsExt2FsDevice(DeviceObject)) {
|
if (IsExt2FsDevice(DeviceObject)) {
|
||||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
|
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
|
||||||
ASSERT(Vcb != NULL);
|
ASSERT(Vcb != NULL);
|
||||||
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
|
||||||
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
|
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
|
||||||
ASSERT(IsMounted(Vcb));
|
ASSERT(IsMounted(Vcb));
|
||||||
|
|
||||||
if (IsVcbReadOnly(Vcb)) {
|
if (IsVcbReadOnly(Vcb)) {
|
||||||
Status = STATUS_MEDIA_WRITE_PROTECTED;
|
Status = STATUS_MEDIA_WRITE_PROTECTED;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ExAcquireResourceExclusiveLite(
|
if (!ExAcquireResourceExclusiveLite(
|
||||||
&Vcb->MainResource, TRUE)) {
|
&Vcb->MainResource, TRUE)) {
|
||||||
Status = STATUS_PENDING;
|
Status = STATUS_PENDING;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
VcbResourceAcquired = TRUE;
|
VcbResourceAcquired = TRUE;
|
||||||
|
|
||||||
Ext2VerifyVcb(IrpContext, Vcb);
|
Ext2VerifyVcb(IrpContext, Vcb);
|
||||||
|
|
||||||
Irp = IrpContext->Irp;
|
Irp = IrpContext->Irp;
|
||||||
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
//Notes: SetVolume is not defined in ntddk.h of win2k ddk,
|
//Notes: SetVolume is not defined in ntddk.h of win2k ddk,
|
||||||
// But it's same to QueryVolume ....
|
// But it's same to QueryVolume ....
|
||||||
FsInformationClass =
|
FsInformationClass =
|
||||||
IoStackLocation->Parameters./*SetVolume*/QueryVolume.FsInformationClass;
|
IoStackLocation->Parameters./*SetVolume*/QueryVolume.FsInformationClass;
|
||||||
|
|
||||||
switch (FsInformationClass) {
|
switch (FsInformationClass) {
|
||||||
|
|
||||||
case FileFsLabelInformation:
|
case FileFsLabelInformation:
|
||||||
{
|
{
|
||||||
PFILE_FS_LABEL_INFORMATION VolLabelInfo = NULL;
|
PFILE_FS_LABEL_INFORMATION VolLabelInfo = NULL;
|
||||||
ULONG VolLabelLen;
|
ULONG VolLabelLen;
|
||||||
UNICODE_STRING LabelName ;
|
UNICODE_STRING LabelName ;
|
||||||
|
|
||||||
OEM_STRING OemName;
|
OEM_STRING OemName;
|
||||||
|
|
||||||
VolLabelInfo = (PFILE_FS_LABEL_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
|
VolLabelInfo = (PFILE_FS_LABEL_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
|
||||||
VolLabelLen = VolLabelInfo->VolumeLabelLength;
|
VolLabelLen = VolLabelInfo->VolumeLabelLength;
|
||||||
|
|
||||||
if (VolLabelLen > (16 * sizeof(WCHAR))) {
|
if (VolLabelLen > (16 * sizeof(WCHAR))) {
|
||||||
Status = STATUS_INVALID_VOLUME_LABEL;
|
Status = STATUS_INVALID_VOLUME_LABEL;
|
||||||
__leave;
|
__leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlCopyMemory( Vcb->Vpb->VolumeLabel,
|
RtlCopyMemory( Vcb->Vpb->VolumeLabel,
|
||||||
VolLabelInfo->VolumeLabel,
|
VolLabelInfo->VolumeLabel,
|
||||||
VolLabelLen );
|
VolLabelLen );
|
||||||
|
|
||||||
RtlZeroMemory(Vcb->SuperBlock->s_volume_name, 16);
|
RtlZeroMemory(Vcb->SuperBlock->s_volume_name, 16);
|
||||||
LabelName.Buffer = VolLabelInfo->VolumeLabel;
|
LabelName.Buffer = VolLabelInfo->VolumeLabel;
|
||||||
LabelName.MaximumLength = (USHORT)16 * sizeof(WCHAR);
|
LabelName.MaximumLength = (USHORT)16 * sizeof(WCHAR);
|
||||||
LabelName.Length = (USHORT)VolLabelLen;
|
LabelName.Length = (USHORT)VolLabelLen;
|
||||||
|
|
||||||
OemName.Buffer = SUPER_BLOCK->s_volume_name;
|
OemName.Buffer = SUPER_BLOCK->s_volume_name;
|
||||||
OemName.Length = 0;
|
OemName.Length = 0;
|
||||||
OemName.MaximumLength = 16;
|
OemName.MaximumLength = 16;
|
||||||
|
|
||||||
Ext2UnicodeToOEM(Vcb, &OemName, &LabelName);
|
Ext2UnicodeToOEM(Vcb, &OemName, &LabelName);
|
||||||
Vcb->Vpb->VolumeLabelLength = (USHORT) VolLabelLen;
|
Vcb->Vpb->VolumeLabelLength = (USHORT) VolLabelLen;
|
||||||
|
|
||||||
if (Ext2SaveSuper(IrpContext, Vcb)) {
|
if (Ext2SaveSuper(IrpContext, Vcb)) {
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Status = STATUS_INVALID_INFO_CLASS;
|
Status = STATUS_INVALID_INFO_CLASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
} __finally {
|
} __finally {
|
||||||
|
|
||||||
if (VcbResourceAcquired) {
|
if (VcbResourceAcquired) {
|
||||||
ExReleaseResourceLite(&Vcb->MainResource);
|
ExReleaseResourceLite(&Vcb->MainResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IrpContext->ExceptionInProgress) {
|
if (!IrpContext->ExceptionInProgress) {
|
||||||
if (Status == STATUS_PENDING) {
|
if (Status == STATUS_PENDING) {
|
||||||
Ext2QueueRequest(IrpContext);
|
Ext2QueueRequest(IrpContext);
|
||||||
} else {
|
} else {
|
||||||
Ext2CompleteIrpContext(IrpContext, Status);
|
Ext2CompleteIrpContext(IrpContext, Status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
2846
Ext4Fsd/write.c
2846
Ext4Fsd/write.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user