mirror of
https://github.com/reactos/reactos.git
synced 2025-07-24 14:23:41 +00:00
[EXT2]
Upgrade the driver to release 0.66. CORE-11295 #resolve #comment Committed in r71411 svn path=/trunk/; revision=71411
This commit is contained in:
parent
e6b12e4774
commit
f0a44d618b
21 changed files with 1848 additions and 1071 deletions
|
@ -167,8 +167,8 @@ typedef struct _EXT2_VOLUME_PROPERTY {
|
||||||
BOOLEAN bExt3Writable;
|
BOOLEAN bExt3Writable;
|
||||||
BOOLEAN bExt2;
|
BOOLEAN bExt2;
|
||||||
BOOLEAN bExt3;
|
BOOLEAN bExt3;
|
||||||
UCHAR Codepage[CODEPAGE_MAXLEN];
|
CHAR Codepage[CODEPAGE_MAXLEN];
|
||||||
} EXT2_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 {
|
||||||
|
@ -196,14 +196,24 @@ typedef struct _EXT2_VOLUME_PROPERTY2 {
|
||||||
|
|
||||||
} EXT2_VOLUME_PROPERTY2, *PEXT2_VOLUME_PROPERTY2;
|
} EXT2_VOLUME_PROPERTY2, *PEXT2_VOLUME_PROPERTY2;
|
||||||
|
|
||||||
#define EXT2_VPROP3_AUTOMOUNT 0x0000000000000001
|
#define EXT2_VPROP3_AUTOMOUNT (1ULL << 0)
|
||||||
|
#define EXT2_VPROP3_USERIDS (1ULL << 1)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
typedef struct _EXT2_VOLUME_PROPERTY3:EXT2_VOLUME_PROPERTY2 {
|
||||||
|
#else // __cplusplus
|
||||||
typedef struct _EXT2_VOLUME_PROPERTY3 {
|
typedef struct _EXT2_VOLUME_PROPERTY3 {
|
||||||
EXT2_VOLUME_PROPERTY2 Prop2;
|
EXT2_VOLUME_PROPERTY2 ;
|
||||||
unsigned __int64 Flags;
|
#endif // __cplusplus
|
||||||
int AutoMount:1;
|
unsigned __int64 Flags2;
|
||||||
int Reserved1:31;
|
ULONG AutoMount:1;
|
||||||
int Reserved2[31];
|
ULONG EIDS:1;
|
||||||
|
ULONG Reserved1:30;
|
||||||
|
USHORT uid;
|
||||||
|
USHORT gid;
|
||||||
|
USHORT euid;
|
||||||
|
USHORT egid;
|
||||||
|
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 */
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
|
|
||||||
/* STRUCTS & CONSTS******************************************************/
|
/* STRUCTS & CONSTS******************************************************/
|
||||||
|
|
||||||
#define EXT2FSD_VERSION "0.63"
|
#define EXT2FSD_VERSION "0.66"
|
||||||
|
|
||||||
|
|
||||||
/* WDK DEFINITIONS ******************************************************/
|
/* WDK DEFINITIONS ******************************************************/
|
||||||
|
@ -110,6 +110,26 @@ typedef struct ext3_dir_entry_2 EXT2_DIR_ENTRY2, *PEXT2_DIR_ENTRY2;
|
||||||
#define CEILING_ALIGNED(T, A, B) (((A) + (B) - 1) & (~((T)(B) - 1)))
|
#define CEILING_ALIGNED(T, A, B) (((A) + (B) - 1) & (~((T)(B) - 1)))
|
||||||
#define COCKLOFT_ALIGNED(T, A, B) (((A) + (B)) & (~((T)(B) - 1)))
|
#define COCKLOFT_ALIGNED(T, A, B) (((A) + (B)) & (~((T)(B) - 1)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compile-time assertion: (Lustre version)
|
||||||
|
*
|
||||||
|
* Check an invariant described by a constant expression at compile time by
|
||||||
|
* forcing a compiler error if it does not hold. \a cond must be a constant
|
||||||
|
* expression as defined by the ISO C Standard:
|
||||||
|
*
|
||||||
|
* 6.8.4.2 The switch statement
|
||||||
|
* ....
|
||||||
|
* [#3] The expression of each case label shall be an integer
|
||||||
|
* constant expression and no two of the case constant
|
||||||
|
* expressions in the same switch statement shall have the same
|
||||||
|
* value after conversion...
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CL_ASSERT(cond) do {switch('x') {case (cond): case 0: break;}} while (0)
|
||||||
|
|
||||||
/* File System Releated *************************************************/
|
/* File System Releated *************************************************/
|
||||||
|
|
||||||
#define DRIVER_NAME "Ext2Fsd"
|
#define DRIVER_NAME "Ext2Fsd"
|
||||||
|
@ -130,6 +150,10 @@ typedef struct ext3_dir_entry_2 EXT2_DIR_ENTRY2, *PEXT2_DIR_ENTRY2;
|
||||||
#define HIDING_SUFFIX L"HidingSuffix"
|
#define HIDING_SUFFIX L"HidingSuffix"
|
||||||
#define AUTO_MOUNT L"AutoMount"
|
#define AUTO_MOUNT L"AutoMount"
|
||||||
#define MOUNT_POINT L"MountPoint"
|
#define MOUNT_POINT L"MountPoint"
|
||||||
|
#define UID L"uid"
|
||||||
|
#define GID L"gid"
|
||||||
|
#define EUID L"euid"
|
||||||
|
#define EGID L"egid"
|
||||||
|
|
||||||
#define DOS_DEVICE_NAME L"\\DosDevices\\Ext2Fsd"
|
#define DOS_DEVICE_NAME L"\\DosDevices\\Ext2Fsd"
|
||||||
|
|
||||||
|
@ -464,6 +488,17 @@ typedef PVOID PBCB;
|
||||||
// Data that is not specific to a mounted volume
|
// Data that is not specific to a mounted volume
|
||||||
//
|
//
|
||||||
|
|
||||||
|
typedef VOID (NTAPI *EXT2_REAPER_RELEASE)(PVOID);
|
||||||
|
|
||||||
|
typedef struct _EXT2_REAPER {
|
||||||
|
KEVENT Engine;
|
||||||
|
KEVENT Wait;
|
||||||
|
EXT2_REAPER_RELEASE Free;
|
||||||
|
ULONG Flags;
|
||||||
|
} EXT2_REAPER, *PEXT2_REAPER;
|
||||||
|
|
||||||
|
#define EXT2_REAPER_FLAG_STOP (1 << 0)
|
||||||
|
|
||||||
typedef struct _EXT2_GLOBAL {
|
typedef struct _EXT2_GLOBAL {
|
||||||
|
|
||||||
/* Identifier for this structure */
|
/* Identifier for this structure */
|
||||||
|
@ -479,6 +514,9 @@ typedef struct _EXT2_GLOBAL {
|
||||||
/* Table of pointers to the fast I/O entry points */
|
/* Table of pointers to the fast I/O entry points */
|
||||||
FAST_IO_DISPATCH FastIoDispatch;
|
FAST_IO_DISPATCH FastIoDispatch;
|
||||||
|
|
||||||
|
/* Filter callbacks */
|
||||||
|
FS_FILTER_CALLBACKS FilterCallbacks;
|
||||||
|
|
||||||
/* Table of pointers to the Cache Manager callbacks */
|
/* Table of pointers to the Cache Manager callbacks */
|
||||||
CACHE_MANAGER_CALLBACKS CacheManagerCallbacks;
|
CACHE_MANAGER_CALLBACKS CacheManagerCallbacks;
|
||||||
CACHE_MANAGER_CALLBACKS CacheManagerNoOpCallbacks;
|
CACHE_MANAGER_CALLBACKS CacheManagerNoOpCallbacks;
|
||||||
|
@ -496,10 +534,8 @@ typedef struct _EXT2_GLOBAL {
|
||||||
LIST_ENTRY VcbList;
|
LIST_ENTRY VcbList;
|
||||||
|
|
||||||
/* Cleaning thread related: resource cleaner */
|
/* Cleaning thread related: resource cleaner */
|
||||||
struct {
|
EXT2_REAPER McbReaper;
|
||||||
KEVENT Engine;
|
EXT2_REAPER bhReaper;
|
||||||
KEVENT Wait;
|
|
||||||
} Reaper;
|
|
||||||
|
|
||||||
/* Look Aside table of IRP_CONTEXT, FCB, MCB, CCB */
|
/* Look Aside table of IRP_CONTEXT, FCB, MCB, CCB */
|
||||||
NPAGED_LOOKASIDE_LIST Ext2IrpContextLookasideList;
|
NPAGED_LOOKASIDE_LIST Ext2IrpContextLookasideList;
|
||||||
|
@ -512,11 +548,14 @@ typedef struct _EXT2_GLOBAL {
|
||||||
|
|
||||||
/* User specified global codepage name */
|
/* User specified global codepage name */
|
||||||
struct {
|
struct {
|
||||||
|
WCHAR PageName[CODEPAGE_MAXLEN];
|
||||||
UCHAR AnsiName[CODEPAGE_MAXLEN];
|
UCHAR AnsiName[CODEPAGE_MAXLEN];
|
||||||
struct nls_table * PageTable;
|
struct nls_table * PageTable;
|
||||||
} Codepage;
|
} Codepage;
|
||||||
|
|
||||||
/* global hiding patterns */
|
/* global hiding patterns */
|
||||||
|
WCHAR wHidingPrefix[HIDINGPAT_LEN];
|
||||||
|
WCHAR wHidingSuffix[HIDINGPAT_LEN];
|
||||||
BOOLEAN bHidingPrefix;
|
BOOLEAN bHidingPrefix;
|
||||||
CHAR sHidingPrefix[HIDINGPAT_LEN];
|
CHAR sHidingPrefix[HIDINGPAT_LEN];
|
||||||
BOOLEAN bHidingSuffix;
|
BOOLEAN bHidingSuffix;
|
||||||
|
@ -599,8 +638,11 @@ typedef struct _EXT2_VCB {
|
||||||
/* Common header */
|
/* Common header */
|
||||||
EXT2_FCBVCB;
|
EXT2_FCBVCB;
|
||||||
|
|
||||||
// Resource for metadata (super block, tables)
|
// Resource for metadata (inode)
|
||||||
ERESOURCE MetaLock;
|
ERESOURCE MetaInode;
|
||||||
|
|
||||||
|
// Resource for metadata (block)
|
||||||
|
ERESOURCE MetaBlock;
|
||||||
|
|
||||||
// Resource for Mcb (Meta data control block)
|
// Resource for Mcb (Meta data control block)
|
||||||
ERESOURCE McbLock;
|
ERESOURCE McbLock;
|
||||||
|
@ -669,12 +711,6 @@ typedef struct _EXT2_VCB {
|
||||||
BOOLEAN IsExt3fs;
|
BOOLEAN IsExt3fs;
|
||||||
PEXT2_SUPER_BLOCK SuperBlock;
|
PEXT2_SUPER_BLOCK SuperBlock;
|
||||||
|
|
||||||
/*
|
|
||||||
// Bitmap Block per group
|
|
||||||
PRTL_BITMAP BlockBitMaps;
|
|
||||||
PRTL_BITMAP InodeBitMaps;
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Block / Cluster size
|
// Block / Cluster size
|
||||||
ULONG BlockSize;
|
ULONG BlockSize;
|
||||||
|
|
||||||
|
@ -745,6 +781,7 @@ typedef struct _EXT2_VCB {
|
||||||
#define VCB_USER_IDS 0x00000040 /* uid/gid specified by user */
|
#define VCB_USER_IDS 0x00000040 /* uid/gid specified by user */
|
||||||
#define VCB_USER_EIDS 0x00000080 /* euid/egid specified by user */
|
#define VCB_USER_EIDS 0x00000080 /* euid/egid specified by user */
|
||||||
|
|
||||||
|
#define VCB_BEING_DROPPED 0x00002000
|
||||||
#define VCB_FORCE_WRITING 0x00004000
|
#define VCB_FORCE_WRITING 0x00004000
|
||||||
#define VCB_DEVICE_REMOVED 0x00008000
|
#define VCB_DEVICE_REMOVED 0x00008000
|
||||||
#define VCB_JOURNAL_RECOVER 0x00080000
|
#define VCB_JOURNAL_RECOVER 0x00080000
|
||||||
|
@ -1148,7 +1185,6 @@ int Ext2CheckFileAccess (PEXT2_VCB Vcb, PEXT2_MCB Mcb, int attempt);
|
||||||
PMDL
|
PMDL
|
||||||
Ext2CreateMdl (
|
Ext2CreateMdl (
|
||||||
IN PVOID Buffer,
|
IN PVOID Buffer,
|
||||||
IN BOOLEAN bPaged,
|
|
||||||
IN ULONG Length,
|
IN ULONG Length,
|
||||||
IN LOCK_OPERATION Operation
|
IN LOCK_OPERATION Operation
|
||||||
);
|
);
|
||||||
|
@ -1255,44 +1291,6 @@ Ext2NoOpAcquire (
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
Ext2NoOpRelease (IN PVOID Fcb);
|
Ext2NoOpRelease (IN PVOID Fcb);
|
||||||
|
|
||||||
VOID NTAPI
|
|
||||||
Ext2AcquireForCreateSection (
|
|
||||||
IN PFILE_OBJECT FileObject
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID NTAPI
|
|
||||||
Ext2ReleaseForCreateSection (
|
|
||||||
IN PFILE_OBJECT FileObject
|
|
||||||
);
|
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
|
||||||
Ext2AcquireFileForModWrite (
|
|
||||||
IN PFILE_OBJECT FileObject,
|
|
||||||
IN PLARGE_INTEGER EndingOffset,
|
|
||||||
OUT PERESOURCE *ResourceToRelease,
|
|
||||||
IN PDEVICE_OBJECT DeviceObject
|
|
||||||
);
|
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
|
||||||
Ext2ReleaseFileForModWrite (
|
|
||||||
IN PFILE_OBJECT FileObject,
|
|
||||||
IN PERESOURCE ResourceToRelease,
|
|
||||||
IN PDEVICE_OBJECT DeviceObject
|
|
||||||
);
|
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
|
||||||
Ext2AcquireFileForCcFlush (
|
|
||||||
IN PFILE_OBJECT FileObject,
|
|
||||||
IN PDEVICE_OBJECT DeviceObject
|
|
||||||
);
|
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
|
||||||
Ext2ReleaseFileForCcFlush (
|
|
||||||
IN PFILE_OBJECT FileObject,
|
|
||||||
IN PDEVICE_OBJECT DeviceObject
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Create.c
|
// Create.c
|
||||||
//
|
//
|
||||||
|
@ -1482,21 +1480,21 @@ Ext2FreePool(
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2ProcessGlobalProperty(
|
Ext2ProcessGlobalProperty(
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PEXT2_VOLUME_PROPERTY2 Property,
|
IN PEXT2_VOLUME_PROPERTY3 Property,
|
||||||
IN ULONG Length
|
IN ULONG Length
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2ProcessVolumeProperty(
|
Ext2ProcessVolumeProperty(
|
||||||
IN PEXT2_VCB Vcb,
|
IN PEXT2_VCB Vcb,
|
||||||
IN PEXT2_VOLUME_PROPERTY2 Property,
|
IN PEXT2_VOLUME_PROPERTY3 Property,
|
||||||
IN ULONG Length
|
IN ULONG Length
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2ProcessUserProperty(
|
Ext2ProcessUserProperty(
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
IN PEXT2_VOLUME_PROPERTY2 Property,
|
IN PEXT2_VOLUME_PROPERTY3 Property,
|
||||||
IN ULONG Length
|
IN ULONG Length
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1911,6 +1909,13 @@ Ext2NewInode(
|
||||||
OUT PULONG Inode
|
OUT PULONG Inode
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
Ext2UpdateGroupDirStat(
|
||||||
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
|
IN PEXT2_VCB Vcb,
|
||||||
|
IN ULONG Group
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2FreeInode(
|
Ext2FreeInode(
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
|
@ -1934,7 +1939,8 @@ Ext2SetFileType (
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
IN PEXT2_VCB Vcb,
|
IN PEXT2_VCB Vcb,
|
||||||
IN PEXT2_FCB Dcb,
|
IN PEXT2_FCB Dcb,
|
||||||
IN PEXT2_MCB Mcb
|
IN PEXT2_MCB Mcb,
|
||||||
|
IN umode_t mode
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -2110,6 +2116,56 @@ Ext2FastIoQueryNetworkOpenInfo (
|
||||||
OUT PIO_STATUS_BLOCK IoStatus,
|
OUT PIO_STATUS_BLOCK IoStatus,
|
||||||
IN PDEVICE_OBJECT DeviceObject);
|
IN PDEVICE_OBJECT DeviceObject);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
Ext2AcquireForCreateSection (
|
||||||
|
IN PFILE_OBJECT FileObject
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
Ext2ReleaseForCreateSection (
|
||||||
|
IN PFILE_OBJECT FileObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
Ext2AcquireFileForModWrite (
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN PLARGE_INTEGER EndingOffset,
|
||||||
|
OUT PERESOURCE *ResourceToRelease,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
Ext2ReleaseFileForModWrite (
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN PERESOURCE ResourceToRelease,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
Ext2AcquireFileForCcFlush (
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
Ext2ReleaseFileForCcFlush (
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
Ext2PreAcquireForCreateSection(
|
||||||
|
IN PFS_FILTER_CALLBACK_DATA cd,
|
||||||
|
OUT PVOID *cc
|
||||||
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// FileInfo.c
|
// FileInfo.c
|
||||||
|
@ -2402,8 +2458,10 @@ int ext3_is_dir_empty(struct ext2_icb *icb, struct inode *inode);
|
||||||
// Init.c
|
// Init.c
|
||||||
//
|
//
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
Ext2QueryGlobalParameters(IN PUNICODE_STRING RegistryPath);
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
Ext2QueryGlobalParameters (IN PUNICODE_STRING RegistryPath);
|
Ext2QueryRegistrySettings(IN PUNICODE_STRING RegistryPath);
|
||||||
|
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
DriverUnload (IN PDRIVER_OBJECT DriverObject);
|
DriverUnload (IN PDRIVER_OBJECT DriverObject);
|
||||||
|
@ -2465,6 +2523,19 @@ Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext);
|
||||||
// Memory.c
|
// Memory.c
|
||||||
//
|
//
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
Ext2McbReaperThread(
|
||||||
|
PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
Ext2bhReaperThread(
|
||||||
|
PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
PEXT2_IRP_CONTEXT
|
PEXT2_IRP_CONTEXT
|
||||||
Ext2AllocateIrpContext (IN PDEVICE_OBJECT DeviceObject,
|
Ext2AllocateIrpContext (IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp );
|
IN PIRP Irp );
|
||||||
|
@ -2769,7 +2840,10 @@ Ext2ReaperThread(
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2StartReaperThread();
|
Ext2StartReaper(PEXT2_REAPER, EXT2_REAPER_RELEASE);
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
Ext2StopReaper(PEXT2_REAPER Reaper);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Misc.c
|
// Misc.c
|
||||||
|
@ -2948,6 +3022,7 @@ Ext2WriteInode (
|
||||||
OUT PULONG dwReturn
|
OUT PULONG dwReturn
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2StartFloppyFlushDpc (
|
Ext2StartFloppyFlushDpc (
|
||||||
PEXT2_VCB Vcb,
|
PEXT2_VCB Vcb,
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
volatile int counter;
|
volatile LONG counter;
|
||||||
} atomic_t;
|
} atomic_t;
|
||||||
|
|
||||||
#define ATOMIC_INIT(i) (i)
|
#define ATOMIC_INIT(i) (i)
|
||||||
|
@ -152,4 +152,4 @@ 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 */
|
||||||
|
|
|
@ -22,8 +22,18 @@
|
||||||
/*
|
/*
|
||||||
* third extended-fs super-block data in memory
|
* third extended-fs super-block data in memory
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct ext3_gd {
|
||||||
|
ext3_fsblk_t block;
|
||||||
|
struct ext4_group_desc *gd;
|
||||||
|
struct buffer_head *bh;
|
||||||
|
};
|
||||||
|
|
||||||
struct ext3_sb_info {
|
struct ext3_sb_info {
|
||||||
|
|
||||||
|
ERESOURCE s_gd_lock;
|
||||||
|
struct ext3_gd *s_gd;
|
||||||
|
|
||||||
unsigned long s_desc_size; /* size of group desc */
|
unsigned long s_desc_size; /* size of group desc */
|
||||||
unsigned long s_gdb_count; /* Number of group descriptor blocks */
|
unsigned long s_gdb_count; /* Number of group descriptor blocks */
|
||||||
unsigned long s_desc_per_block; /* Number of group descriptors per block */
|
unsigned long s_desc_per_block; /* Number of group descriptors per block */
|
||||||
|
@ -36,7 +46,6 @@ struct ext3_sb_info {
|
||||||
int s_addr_per_block_bits;
|
int s_addr_per_block_bits;
|
||||||
int s_desc_per_block_bits;
|
int s_desc_per_block_bits;
|
||||||
|
|
||||||
ext3_fsblk_t *s_group_desc;
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
unsigned long s_frag_size; /* Size of a fragment in bytes */
|
unsigned long s_frag_size; /* Size of a fragment in bytes */
|
||||||
|
|
|
@ -546,9 +546,11 @@ struct block_device {
|
||||||
PFILE_OBJECT bd_volume; /* streaming object file */
|
PFILE_OBJECT bd_volume; /* streaming object file */
|
||||||
LARGE_MCB bd_extents; /* dirty extents */
|
LARGE_MCB bd_extents; /* dirty extents */
|
||||||
|
|
||||||
spinlock_t bd_bh_lock; /**/
|
kmem_cache_t * bd_bh_cache;/* memory cache for buffer_head */
|
||||||
kmem_cache_t * bd_bh_cache; /* memory cache for buffer_head */
|
ERESOURCE bd_bh_lock; /* lock for bh tree and reaper list */
|
||||||
struct rb_root bd_bh_root; /* buffer_head red-black tree root */
|
struct rb_root bd_bh_root; /* buffer_head red-black tree root */
|
||||||
|
LIST_ENTRY bd_bh_free; /* reaper list */
|
||||||
|
KEVENT bd_bh_notify; /* notification event for cleanup */
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -709,6 +711,7 @@ typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate);
|
||||||
* for backward compatibility reasons (e.g. submit_bh).
|
* for backward compatibility reasons (e.g. submit_bh).
|
||||||
*/
|
*/
|
||||||
struct buffer_head {
|
struct buffer_head {
|
||||||
|
LIST_ENTRY b_link; /* to be added to reaper list */
|
||||||
unsigned long b_state; /* buffer state bitmap (see above) */
|
unsigned long b_state; /* buffer state bitmap (see above) */
|
||||||
struct page *b_page; /* the page this bh is mapped to */
|
struct page *b_page; /* the page this bh is mapped to */
|
||||||
PMDL b_mdl; /* MDL of the locked buffer */
|
PMDL b_mdl; /* MDL of the locked buffer */
|
||||||
|
@ -725,7 +728,10 @@ struct buffer_head {
|
||||||
// struct list_head b_assoc_buffers; /* associated with another mapping */
|
// struct list_head b_assoc_buffers; /* associated with another mapping */
|
||||||
// struct address_space *b_assoc_map; /* mapping this buffer is associated with */
|
// struct address_space *b_assoc_map; /* mapping this buffer is associated with */
|
||||||
atomic_t b_count; /* users using this buffer_head */
|
atomic_t b_count; /* users using this buffer_head */
|
||||||
struct rb_node b_rb_node; /* Red-black tree node entry */
|
struct rb_node b_rb_node; /* Red-black tree node entry */
|
||||||
|
|
||||||
|
LARGE_INTEGER b_ts_creat; /* creation time*/
|
||||||
|
LARGE_INTEGER b_ts_drop; /* drop time (to be released) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,9 +51,8 @@ Ext2MediaEjectControlCompletion (
|
||||||
PMDL
|
PMDL
|
||||||
Ext2CreateMdl (
|
Ext2CreateMdl (
|
||||||
IN PVOID Buffer,
|
IN PVOID Buffer,
|
||||||
IN BOOLEAN bPaged,
|
|
||||||
IN ULONG Length,
|
IN ULONG Length,
|
||||||
IN LOCK_OPERATION Operation
|
IN LOCK_OPERATION op
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -65,10 +64,10 @@ Ext2CreateMdl (
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
} else {
|
} else {
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
if (bPaged) {
|
if (MmIsNonPagedSystemAddressValid(Buffer)) {
|
||||||
MmProbeAndLockPages(Mdl, KernelMode, Operation);
|
MmBuildMdlForNonPagedPool(Mdl);
|
||||||
} else {
|
} else {
|
||||||
MmBuildMdlForNonPagedPool (Mdl);
|
MmProbeAndLockPages(Mdl, KernelMode, op);
|
||||||
}
|
}
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
} _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
} _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
||||||
|
@ -89,6 +88,7 @@ Ext2DestroyMdl (IN PMDL Mdl)
|
||||||
while (Mdl) {
|
while (Mdl) {
|
||||||
PMDL Next;
|
PMDL Next;
|
||||||
Next = Mdl->Next;
|
Next = Mdl->Next;
|
||||||
|
Mdl->Next = NULL;
|
||||||
if (IsFlagOn(Mdl->MdlFlags, MDL_PAGES_LOCKED)) {
|
if (IsFlagOn(Mdl->MdlFlags, MDL_PAGES_LOCKED)) {
|
||||||
MmUnlockPages (Mdl);
|
MmUnlockPages (Mdl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
BOOLEAN FcbResourceAcquired = FALSE;
|
BOOLEAN FcbResourceAcquired = FALSE;
|
||||||
BOOLEAN FcbPagingIoResourceAcquired = FALSE;
|
BOOLEAN FcbPagingIoResourceAcquired = FALSE;
|
||||||
|
BOOLEAN SymLinkDelete = FALSE;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
|
@ -198,7 +199,11 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
|
if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) {
|
||||||
SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
|
if (Ccb->SymLink || IsInodeSymLink(&Mcb->Inode)) {
|
||||||
|
SymLinkDelete = TRUE;
|
||||||
|
} else {
|
||||||
|
SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -279,52 +284,52 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) {
|
if (SymLinkDelete ||
|
||||||
|
(IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING) &&
|
||||||
|
Fcb->OpenHandleCount == 0) ) {
|
||||||
|
|
||||||
if (Fcb->OpenHandleCount == 0 || (Mcb = Ccb->SymLink)) {
|
//
|
||||||
|
// Ext2DeleteFile will acquire these lock inside
|
||||||
|
//
|
||||||
|
|
||||||
//
|
if (FcbResourceAcquired) {
|
||||||
// Ext2DeleteFile will acquire these lock inside
|
ExReleaseResourceLite(&Fcb->MainResource);
|
||||||
//
|
FcbResourceAcquired = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (FcbResourceAcquired) {
|
//
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
// this file is to be deleted ...
|
||||||
FcbResourceAcquired = FALSE;
|
//
|
||||||
|
if (Ccb->SymLink) {
|
||||||
|
Mcb = Ccb->SymLink;
|
||||||
|
FileObject->DeletePending = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status)) {
|
||||||
|
if (IsMcbDirectory(Mcb)) {
|
||||||
|
Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
|
||||||
|
FILE_NOTIFY_CHANGE_DIR_NAME,
|
||||||
|
FILE_ACTION_REMOVED );
|
||||||
|
} else {
|
||||||
|
Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
|
||||||
|
FILE_NOTIFY_CHANGE_FILE_NAME,
|
||||||
|
FILE_ACTION_REMOVED );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// this file is to be deleted ...
|
// re-acquire the main resource lock
|
||||||
//
|
//
|
||||||
if (Ccb->SymLink) {
|
|
||||||
Mcb = Ccb->SymLink;
|
|
||||||
FileObject->DeletePending = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
|
FcbResourceAcquired =
|
||||||
|
ExAcquireResourceExclusiveLite(
|
||||||
if (NT_SUCCESS(Status)) {
|
&Fcb->MainResource,
|
||||||
if (IsMcbDirectory(Mcb)) {
|
TRUE
|
||||||
Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
|
);
|
||||||
FILE_NOTIFY_CHANGE_DIR_NAME,
|
if (!SymLinkDelete) {
|
||||||
FILE_ACTION_REMOVED );
|
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
|
||||||
} else {
|
|
||||||
Ext2NotifyReportChange( IrpContext, Vcb, Mcb,
|
|
||||||
FILE_NOTIFY_CHANGE_FILE_NAME,
|
|
||||||
FILE_ACTION_REMOVED );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// re-acquire the main resource lock
|
|
||||||
//
|
|
||||||
|
|
||||||
FcbResourceAcquired =
|
|
||||||
ExAcquireResourceExclusiveLite(
|
|
||||||
&Fcb->MainResource,
|
|
||||||
TRUE
|
|
||||||
);
|
|
||||||
|
|
||||||
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)));
|
||||||
|
|
|
@ -38,8 +38,7 @@ Ext2AcquireForLazyWrite (
|
||||||
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 (!ExAcquireResourceSharedLite(
|
if (!ExAcquireResourceExclusiveLite(Fcb->Header.Resource, Wait)) {
|
||||||
&Fcb->PagingIoResource, Wait)) {
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +46,6 @@ Ext2AcquireForLazyWrite (
|
||||||
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;
|
||||||
|
@ -59,9 +57,7 @@ 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 Fcb = (PEXT2_FCB) Context;
|
||||||
|
|
||||||
Fcb = (PEXT2_FCB) Context;
|
|
||||||
|
|
||||||
ASSERT(Fcb != NULL);
|
ASSERT(Fcb != NULL);
|
||||||
|
|
||||||
|
@ -74,7 +70,7 @@ Ext2ReleaseFromLazyWrite (IN PVOID Context)
|
||||||
ASSERT(Fcb->LazyWriterThread == PsGetCurrentThread());
|
ASSERT(Fcb->LazyWriterThread == PsGetCurrentThread());
|
||||||
Fcb->LazyWriterThread = NULL;
|
Fcb->LazyWriterThread = NULL;
|
||||||
|
|
||||||
ExReleaseResourceLite(&Fcb->PagingIoResource);
|
ExReleaseResourceLite(Fcb->Header.Resource);
|
||||||
|
|
||||||
ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
ASSERT(IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
|
||||||
IoSetTopLevelIrp( NULL );
|
IoSetTopLevelIrp( NULL );
|
||||||
|
@ -84,24 +80,18 @@ BOOLEAN NTAPI
|
||||||
Ext2AcquireForReadAhead (IN PVOID Context,
|
Ext2AcquireForReadAhead (IN PVOID Context,
|
||||||
IN BOOLEAN Wait)
|
IN BOOLEAN Wait)
|
||||||
{
|
{
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_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)));
|
||||||
|
|
||||||
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(
|
if (!ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait))
|
||||||
&Fcb->MainResource, 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;
|
||||||
|
@ -110,9 +100,7 @@ Ext2AcquireForReadAhead (IN PVOID Context,
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
Ext2ReleaseFromReadAhead (IN PVOID Context)
|
Ext2ReleaseFromReadAhead (IN PVOID Context)
|
||||||
{
|
{
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb = (PEXT2_FCB) Context;
|
||||||
|
|
||||||
Fcb = (PEXT2_FCB) Context;
|
|
||||||
|
|
||||||
ASSERT(Fcb != NULL);
|
ASSERT(Fcb != NULL);
|
||||||
|
|
||||||
|
@ -122,9 +110,8 @@ Ext2ReleaseFromReadAhead (IN PVOID Context)
|
||||||
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->MainResource);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN NTAPI
|
BOOLEAN NTAPI
|
||||||
|
@ -149,120 +136,3 @@ Ext2NoOpRelease (
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID NTAPI
|
|
||||||
Ext2AcquireForCreateSection (
|
|
||||||
IN PFILE_OBJECT FileObject
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
PEXT2_FCB Fcb = FileObject->FsContext;
|
|
||||||
|
|
||||||
if (Fcb->Header.Resource != NULL) {
|
|
||||||
ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireForCreateSection: Fcb=%p\n", Fcb));
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID NTAPI
|
|
||||||
Ext2ReleaseForCreateSection (
|
|
||||||
IN PFILE_OBJECT FileObject
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
PEXT2_FCB Fcb = FileObject->FsContext;
|
|
||||||
|
|
||||||
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2ReleaseForCreateSection: Fcb=%p\n", Fcb));
|
|
||||||
|
|
||||||
if (Fcb->Header.Resource != NULL) {
|
|
||||||
ExReleaseResourceLite(Fcb->Header.Resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
|
||||||
Ext2AcquireFileForModWrite (
|
|
||||||
IN PFILE_OBJECT FileObject,
|
|
||||||
IN PLARGE_INTEGER EndingOffset,
|
|
||||||
OUT PERESOURCE *ResourceToRelease,
|
|
||||||
IN PDEVICE_OBJECT DeviceObject
|
|
||||||
)
|
|
||||||
|
|
||||||
{
|
|
||||||
BOOLEAN ResourceAcquired = FALSE;
|
|
||||||
|
|
||||||
PEXT2_FCB Fcb = FileObject->FsContext;
|
|
||||||
|
|
||||||
if (Fcb->Header.PagingIoResource != NULL) {
|
|
||||||
*ResourceToRelease = Fcb->Header.PagingIoResource;
|
|
||||||
} else {
|
|
||||||
*ResourceToRelease = Fcb->Header.Resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResourceAcquired = ExAcquireResourceSharedLite(*ResourceToRelease, FALSE);
|
|
||||||
if (!ResourceAcquired) {
|
|
||||||
*ResourceToRelease = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireFileForModWrite: Fcb=%p Acquired=%d\n",
|
|
||||||
Fcb, ResourceAcquired));
|
|
||||||
|
|
||||||
return (ResourceAcquired ? STATUS_SUCCESS : STATUS_CANT_WAIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
|
||||||
Ext2ReleaseFileForModWrite (
|
|
||||||
IN PFILE_OBJECT FileObject,
|
|
||||||
IN PERESOURCE ResourceToRelease,
|
|
||||||
IN PDEVICE_OBJECT DeviceObject
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PEXT2_FCB Fcb = FileObject->FsContext;
|
|
||||||
|
|
||||||
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2ReleaseFileForModWrite: Fcb=%p\n", Fcb));
|
|
||||||
|
|
||||||
if (ResourceToRelease != NULL) {
|
|
||||||
ASSERT(ResourceToRelease == Fcb->Header.PagingIoResource ||
|
|
||||||
ResourceToRelease == Fcb->Header.Resource);
|
|
||||||
ExReleaseResourceLite(ResourceToRelease);
|
|
||||||
} else {
|
|
||||||
DbgBreak();
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
|
||||||
Ext2AcquireFileForCcFlush (
|
|
||||||
IN PFILE_OBJECT FileObject,
|
|
||||||
IN PDEVICE_OBJECT DeviceObject
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PEXT2_FCB Fcb = FileObject->FsContext;
|
|
||||||
|
|
||||||
if (Fcb->Header.PagingIoResource != NULL) {
|
|
||||||
ExAcquireResourceSharedLite(Fcb->Header.PagingIoResource, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2AcquireFileForCcFlush: Fcb=%p\n", Fcb));
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
|
||||||
Ext2ReleaseFileForCcFlush (
|
|
||||||
IN PFILE_OBJECT FileObject,
|
|
||||||
IN PDEVICE_OBJECT DeviceObject
|
|
||||||
)
|
|
||||||
{
|
|
||||||
PEXT2_FCB Fcb = FileObject->FsContext;
|
|
||||||
|
|
||||||
DEBUG(CMCB_DEBUG_LEVEL, ("Ext2ReleaseFileForCcFlush: Fcb=%p\n", Fcb));
|
|
||||||
|
|
||||||
if (Fcb->Header.PagingIoResource != NULL) {
|
|
||||||
ExReleaseResourceLite(Fcb->Header.PagingIoResource);
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ Ext2FollowLink (
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read the symlink target path */
|
/* read the symlink target path */
|
||||||
if (Mcb->Inode.i_size < EXT2_LINKLEN_IN_INODE) {
|
if (!Mcb->Inode.i_blocks) {
|
||||||
|
|
||||||
OemName.Buffer = (PUCHAR) (&Mcb->Inode.i_block[0]);
|
OemName.Buffer = (PUCHAR) (&Mcb->Inode.i_block[0]);
|
||||||
OemName.Length = (USHORT)Mcb->Inode.i_size;
|
OemName.Length = (USHORT)Mcb->Inode.i_size;
|
||||||
|
@ -871,6 +871,7 @@ McbExisting:
|
||||||
#ifndef __REACTOS__
|
#ifndef __REACTOS__
|
||||||
LONG i = 0;
|
LONG i = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PathName = FileName;
|
PathName = FileName;
|
||||||
Mcb = NULL;
|
Mcb = NULL;
|
||||||
|
|
||||||
|
@ -1388,6 +1389,7 @@ Openit:
|
||||||
//
|
//
|
||||||
// check the oplock state of the file
|
// check the oplock state of the file
|
||||||
//
|
//
|
||||||
|
|
||||||
Status = FsRtlCheckOplock( &Fcb->Oplock,
|
Status = FsRtlCheckOplock( &Fcb->Oplock,
|
||||||
IrpContext->Irp,
|
IrpContext->Irp,
|
||||||
IrpContext,
|
IrpContext,
|
||||||
|
@ -1895,8 +1897,13 @@ Ext2CreateInode(
|
||||||
Inode.i_ino = iNo;
|
Inode.i_ino = iNo;
|
||||||
Inode.i_ctime = Inode.i_mtime =
|
Inode.i_ctime = Inode.i_mtime =
|
||||||
Inode.i_atime = Ext2LinuxTime(SysTime);
|
Inode.i_atime = Ext2LinuxTime(SysTime);
|
||||||
Inode.i_uid = Vcb->uid;
|
if (IsFlagOn(Vcb->Flags, VCB_USER_IDS)) {
|
||||||
Inode.i_gid = Vcb->gid;
|
Inode.i_uid = Vcb->uid;
|
||||||
|
Inode.i_gid = Vcb->gid;
|
||||||
|
} else {
|
||||||
|
Inode.i_uid = Parent->Mcb->Inode.i_uid;
|
||||||
|
Inode.i_gid = Parent->Mcb->Inode.i_gid;
|
||||||
|
}
|
||||||
Inode.i_generation = Parent->Inode->i_generation;
|
Inode.i_generation = Parent->Inode->i_generation;
|
||||||
Inode.i_mode = S_IPERMISSION_MASK &
|
Inode.i_mode = S_IPERMISSION_MASK &
|
||||||
Parent->Inode->i_mode;
|
Parent->Inode->i_mode;
|
||||||
|
|
|
@ -231,13 +231,16 @@ extern CHAR gDate[];
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2ProcessGlobalProperty(
|
Ext2ProcessGlobalProperty(
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PEXT2_VOLUME_PROPERTY2 Property,
|
IN PEXT2_VOLUME_PROPERTY3 Property3,
|
||||||
IN ULONG Length
|
IN ULONG Length
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
PEXT2_VOLUME_PROPERTY3 Property2 = (PVOID)Property3;
|
||||||
|
PEXT2_VOLUME_PROPERTY Property = (PVOID)Property3;
|
||||||
|
struct nls_table * PageTable = NULL;
|
||||||
|
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
BOOLEAN GlobalDataResourceAcquired = FALSE;
|
BOOLEAN GlobalDataResourceAcquired = FALSE;
|
||||||
struct nls_table * PageTable = NULL;
|
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
|
@ -289,51 +292,57 @@ Ext2ProcessGlobalProperty(
|
||||||
ExAcquireResourceExclusiveLite(&Ext2Global->Resource, TRUE);
|
ExAcquireResourceExclusiveLite(&Ext2Global->Resource, TRUE);
|
||||||
GlobalDataResourceAcquired = TRUE;
|
GlobalDataResourceAcquired = TRUE;
|
||||||
|
|
||||||
if (Property->bReadonly) {
|
|
||||||
ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
|
|
||||||
ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
|
|
||||||
} else {
|
|
||||||
SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
|
|
||||||
if (Property->bExt3Writable) {
|
|
||||||
SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
|
|
||||||
} else {
|
|
||||||
ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PageTable = load_nls(Property->Codepage);
|
switch (Property->Command) {
|
||||||
if (PageTable) {
|
|
||||||
memcpy(Ext2Global->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN);
|
|
||||||
Ext2Global->Codepage.PageTable = PageTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Property->Command == APP_CMD_SET_PROPERTY2 ||
|
case APP_CMD_SET_PROPERTY3:
|
||||||
Property->Command == APP_CMD_SET_PROPERTY3 ) {
|
|
||||||
|
|
||||||
RtlZeroMemory(Ext2Global->sHidingPrefix, HIDINGPAT_LEN);
|
if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) {
|
||||||
if ((Ext2Global->bHidingPrefix = Property->bHidingPrefix)) {
|
if (Property3->AutoMount)
|
||||||
RtlCopyMemory( Ext2Global->sHidingPrefix,
|
|
||||||
Property->sHidingPrefix,
|
|
||||||
HIDINGPAT_LEN - 1);
|
|
||||||
}
|
|
||||||
RtlZeroMemory(Ext2Global->sHidingSuffix, HIDINGPAT_LEN);
|
|
||||||
if ((Ext2Global->bHidingSuffix = Property->bHidingSuffix)) {
|
|
||||||
RtlCopyMemory( Ext2Global->sHidingSuffix,
|
|
||||||
Property->sHidingSuffix,
|
|
||||||
HIDINGPAT_LEN - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Property->Command == APP_CMD_SET_PROPERTY3) {
|
|
||||||
|
|
||||||
PEXT2_VOLUME_PROPERTY3 Prop3 = (PEXT2_VOLUME_PROPERTY3)Property;
|
|
||||||
|
|
||||||
if (Prop3->Flags & EXT2_VPROP3_AUTOMOUNT) {
|
|
||||||
if (Prop3->AutoMount)
|
|
||||||
SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
|
SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
|
||||||
else
|
else
|
||||||
ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
|
ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case APP_CMD_SET_PROPERTY2:
|
||||||
|
|
||||||
|
RtlZeroMemory(Ext2Global->sHidingPrefix, HIDINGPAT_LEN);
|
||||||
|
if ((Ext2Global->bHidingPrefix = Property2->bHidingPrefix)) {
|
||||||
|
RtlCopyMemory( Ext2Global->sHidingPrefix,
|
||||||
|
Property2->sHidingPrefix,
|
||||||
|
HIDINGPAT_LEN - 1);
|
||||||
|
}
|
||||||
|
RtlZeroMemory(Ext2Global->sHidingSuffix, HIDINGPAT_LEN);
|
||||||
|
if ((Ext2Global->bHidingSuffix = Property2->bHidingSuffix)) {
|
||||||
|
RtlCopyMemory( Ext2Global->sHidingSuffix,
|
||||||
|
Property2->sHidingSuffix,
|
||||||
|
HIDINGPAT_LEN - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
case APP_CMD_SET_PROPERTY:
|
||||||
|
|
||||||
|
if (Property->bReadonly) {
|
||||||
|
ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
|
||||||
|
ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
|
||||||
|
} else {
|
||||||
|
SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
|
||||||
|
if (Property->bExt3Writable) {
|
||||||
|
SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
|
||||||
|
} else {
|
||||||
|
ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PageTable = load_nls(Property->Codepage);
|
||||||
|
if (PageTable) {
|
||||||
|
memcpy(Ext2Global->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN);
|
||||||
|
Ext2Global->Codepage.PageTable = PageTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} _SEH2_FINALLY {
|
} _SEH2_FINALLY {
|
||||||
|
@ -350,13 +359,15 @@ Ext2ProcessGlobalProperty(
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2ProcessVolumeProperty(
|
Ext2ProcessVolumeProperty(
|
||||||
IN PEXT2_VCB Vcb,
|
IN PEXT2_VCB Vcb,
|
||||||
IN PEXT2_VOLUME_PROPERTY2 Property,
|
IN PEXT2_VOLUME_PROPERTY3 Property3,
|
||||||
IN ULONG Length
|
IN ULONG Length
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
|
||||||
struct nls_table * PageTable = NULL;
|
struct nls_table * PageTable = NULL;
|
||||||
|
PEXT2_VOLUME_PROPERTY2 Property2 = (PVOID)Property3;
|
||||||
|
PEXT2_VOLUME_PROPERTY Property = (PVOID)Property3;
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
|
@ -364,7 +375,7 @@ Ext2ProcessVolumeProperty(
|
||||||
VcbResourceAcquired = TRUE;
|
VcbResourceAcquired = TRUE;
|
||||||
|
|
||||||
if (Property->Command == APP_CMD_SET_PROPERTY ||
|
if (Property->Command == APP_CMD_SET_PROPERTY ||
|
||||||
Property->Command == APP_CMD_QUERY_PROPERTY) {
|
Property->Command == APP_CMD_QUERY_PROPERTY) {
|
||||||
if (Length < sizeof(EXT2_VOLUME_PROPERTY)) {
|
if (Length < sizeof(EXT2_VOLUME_PROPERTY)) {
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
|
@ -375,17 +386,67 @@ Ext2ProcessVolumeProperty(
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
} else if (Property->Command == APP_CMD_SET_PROPERTY3 ||
|
||||||
|
Property->Command == APP_CMD_QUERY_PROPERTY3) {
|
||||||
|
if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) {
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Property->Command) {
|
switch (Property->Command) {
|
||||||
|
|
||||||
case APP_CMD_SET_PROPERTY:
|
case APP_CMD_SET_PROPERTY3:
|
||||||
|
|
||||||
|
if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) {
|
||||||
|
if (Property3->AutoMount)
|
||||||
|
SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
|
||||||
|
else
|
||||||
|
ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
|
||||||
|
}
|
||||||
|
if (Property3->Flags2 & EXT2_VPROP3_USERIDS) {
|
||||||
|
SetFlag(Vcb->Flags, VCB_USER_IDS);
|
||||||
|
Vcb->uid = Property3->uid;
|
||||||
|
Vcb->gid = Property3->gid;
|
||||||
|
if (Property3->EIDS) {
|
||||||
|
Vcb->euid = Property3->euid;
|
||||||
|
Vcb->egid = Property3->egid;
|
||||||
|
SetFlag(Vcb->Flags, VCB_USER_EIDS);
|
||||||
|
} else {
|
||||||
|
Vcb->euid = Vcb->egid = 0;
|
||||||
|
ClearFlag(Vcb->Flags, VCB_USER_EIDS);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ClearFlag(Vcb->Flags, VCB_USER_IDS);
|
||||||
|
ClearFlag(Vcb->Flags, VCB_USER_EIDS);
|
||||||
|
Vcb->uid = Vcb->gid = 0;
|
||||||
|
Vcb->euid = Vcb->egid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
case APP_CMD_SET_PROPERTY2:
|
case APP_CMD_SET_PROPERTY2:
|
||||||
|
|
||||||
if (Property->bReadonly) {
|
RtlZeroMemory(Vcb->sHidingPrefix, HIDINGPAT_LEN);
|
||||||
|
if (Vcb->bHidingPrefix == Property2->bHidingPrefix) {
|
||||||
|
RtlCopyMemory( Vcb->sHidingPrefix,
|
||||||
|
Property2->sHidingPrefix,
|
||||||
|
HIDINGPAT_LEN - 1);
|
||||||
|
}
|
||||||
|
|
||||||
Ext2FlushFiles(NULL, Vcb, FALSE);
|
RtlZeroMemory(Vcb->sHidingSuffix, HIDINGPAT_LEN);
|
||||||
Ext2FlushVolume(NULL, Vcb, FALSE);
|
if (Vcb->bHidingSuffix == Property2->bHidingSuffix) {
|
||||||
|
RtlCopyMemory( Vcb->sHidingSuffix,
|
||||||
|
Property2->sHidingSuffix,
|
||||||
|
HIDINGPAT_LEN - 1);
|
||||||
|
}
|
||||||
|
Vcb->DrvLetter = Property2->DrvLetter;
|
||||||
|
|
||||||
|
case APP_CMD_SET_PROPERTY:
|
||||||
|
|
||||||
|
if (Property->bReadonly) {
|
||||||
|
if (IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) {
|
||||||
|
Ext2FlushFiles(NULL, Vcb, FALSE);
|
||||||
|
Ext2FlushVolume(NULL, Vcb, FALSE);
|
||||||
|
}
|
||||||
SetLongFlag(Vcb->Flags, VCB_READ_ONLY);
|
SetLongFlag(Vcb->Flags, VCB_READ_ONLY);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -418,30 +479,58 @@ Ext2ProcessVolumeProperty(
|
||||||
Ext2InitializeLabel(Vcb, Vcb->SuperBlock);
|
Ext2InitializeLabel(Vcb, Vcb->SuperBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Property->Command == APP_CMD_SET_PROPERTY2) {
|
|
||||||
|
|
||||||
RtlZeroMemory(Vcb->sHidingPrefix, HIDINGPAT_LEN);
|
|
||||||
if ((Vcb->bHidingPrefix = Property->bHidingPrefix) != 0) {
|
|
||||||
RtlCopyMemory( Vcb->sHidingPrefix,
|
|
||||||
Property->sHidingPrefix,
|
|
||||||
HIDINGPAT_LEN - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlZeroMemory(Vcb->sHidingSuffix, HIDINGPAT_LEN);
|
|
||||||
if ((Vcb->bHidingSuffix = Property->bHidingSuffix) != 0) {
|
|
||||||
RtlCopyMemory( Vcb->sHidingSuffix,
|
|
||||||
Property->sHidingSuffix,
|
|
||||||
HIDINGPAT_LEN - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vcb->DrvLetter = Property->DrvLetter;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case APP_CMD_QUERY_PROPERTY:
|
case APP_CMD_QUERY_PROPERTY3:
|
||||||
|
|
||||||
|
if (IsFlagOn(Ext2Global->Flags, EXT2_AUTO_MOUNT)) {
|
||||||
|
SetFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT);
|
||||||
|
Property3->AutoMount = TRUE;
|
||||||
|
} else {
|
||||||
|
ClearFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT);
|
||||||
|
Property3->AutoMount = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsFlagOn(Vcb->Flags, VCB_USER_IDS)) {
|
||||||
|
SetFlag(Property3->Flags2, EXT2_VPROP3_USERIDS);
|
||||||
|
Property3->uid = Vcb->uid;
|
||||||
|
Property3->gid = Vcb->gid;
|
||||||
|
if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) {
|
||||||
|
Property3->EIDS = TRUE;
|
||||||
|
Property3->euid = Vcb->euid;
|
||||||
|
Property3->egid = Vcb->egid;
|
||||||
|
} else {
|
||||||
|
Property3->EIDS = FALSE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ClearFlag(Property3->Flags2, EXT2_VPROP3_USERIDS);
|
||||||
|
}
|
||||||
|
|
||||||
case APP_CMD_QUERY_PROPERTY2:
|
case APP_CMD_QUERY_PROPERTY2:
|
||||||
|
|
||||||
|
RtlCopyMemory(Property2->UUID, Vcb->SuperBlock->s_uuid, 16);
|
||||||
|
Property2->DrvLetter = Vcb->DrvLetter;
|
||||||
|
|
||||||
|
if (Property2->bHidingPrefix == Vcb->bHidingPrefix) {
|
||||||
|
RtlCopyMemory( Property2->sHidingPrefix,
|
||||||
|
Vcb->sHidingPrefix,
|
||||||
|
HIDINGPAT_LEN);
|
||||||
|
} else {
|
||||||
|
RtlZeroMemory( Property2->sHidingPrefix,
|
||||||
|
HIDINGPAT_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Property2->bHidingSuffix == Vcb->bHidingSuffix) {
|
||||||
|
RtlCopyMemory( Property2->sHidingSuffix,
|
||||||
|
Vcb->sHidingSuffix,
|
||||||
|
HIDINGPAT_LEN);
|
||||||
|
} else {
|
||||||
|
RtlZeroMemory( Property2->sHidingSuffix,
|
||||||
|
HIDINGPAT_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
case APP_CMD_QUERY_PROPERTY:
|
||||||
|
|
||||||
Property->bExt2 = TRUE;
|
Property->bExt2 = TRUE;
|
||||||
Property->bExt3 = Vcb->IsExt3fs;
|
Property->bExt3 = Vcb->IsExt3fs;
|
||||||
Property->bReadonly = IsFlagOn(Vcb->Flags, VCB_READ_ONLY);
|
Property->bReadonly = IsFlagOn(Vcb->Flags, VCB_READ_ONLY);
|
||||||
|
@ -457,32 +546,6 @@ Ext2ProcessVolumeProperty(
|
||||||
} else {
|
} else {
|
||||||
strncpy(Property->Codepage, "default", CODEPAGE_MAXLEN);
|
strncpy(Property->Codepage, "default", CODEPAGE_MAXLEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Property->Command == APP_CMD_QUERY_PROPERTY2) {
|
|
||||||
|
|
||||||
RtlCopyMemory(Property->UUID, Vcb->SuperBlock->s_uuid, 16);
|
|
||||||
|
|
||||||
Property->DrvLetter = Vcb->DrvLetter;
|
|
||||||
|
|
||||||
if ((Property->bHidingPrefix = Vcb->bHidingPrefix) != 0) {
|
|
||||||
RtlCopyMemory( Property->sHidingPrefix,
|
|
||||||
Vcb->sHidingPrefix,
|
|
||||||
HIDINGPAT_LEN);
|
|
||||||
} else {
|
|
||||||
RtlZeroMemory( Property->sHidingPrefix,
|
|
||||||
HIDINGPAT_LEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((Property->bHidingSuffix = Vcb->bHidingSuffix) != 0) {
|
|
||||||
RtlCopyMemory( Property->sHidingSuffix,
|
|
||||||
Vcb->sHidingSuffix,
|
|
||||||
HIDINGPAT_LEN);
|
|
||||||
} else {
|
|
||||||
RtlZeroMemory( Property->sHidingSuffix,
|
|
||||||
HIDINGPAT_LEN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -503,7 +566,7 @@ Ext2ProcessVolumeProperty(
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2ProcessUserProperty(
|
Ext2ProcessUserProperty(
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
IN PEXT2_VOLUME_PROPERTY2 Property,
|
IN PEXT2_VOLUME_PROPERTY3 Property,
|
||||||
IN ULONG Length
|
IN ULONG Length
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
|
@ -127,6 +127,27 @@ Ext2RefreshSuper (
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
Ext2PutGroup(IN PEXT2_VCB Vcb)
|
||||||
|
{
|
||||||
|
struct ext3_sb_info *sbi = &Vcb->sbi;
|
||||||
|
unsigned long i;
|
||||||
|
|
||||||
|
|
||||||
|
if (NULL == Vcb->sbi.s_gd) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < Vcb->sbi.s_gdb_count; i++) {
|
||||||
|
if (Vcb->sbi.s_gd[i].bh)
|
||||||
|
fini_bh(&sbi->s_gd[i].bh);
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree(Vcb->sbi.s_gd);
|
||||||
|
Vcb->sbi.s_gd = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
Ext2LoadGroup(IN PEXT2_VCB Vcb)
|
Ext2LoadGroup(IN PEXT2_VCB Vcb)
|
||||||
{
|
{
|
||||||
|
@ -134,34 +155,56 @@ Ext2LoadGroup(IN PEXT2_VCB Vcb)
|
||||||
struct ext3_sb_info *sbi = &Vcb->sbi;
|
struct ext3_sb_info *sbi = &Vcb->sbi;
|
||||||
ext3_fsblk_t sb_block = 1;
|
ext3_fsblk_t sb_block = 1;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
BOOLEAN rc = FALSE;
|
||||||
|
|
||||||
if (BLOCK_SIZE != EXT3_MIN_BLOCK_SIZE) {
|
_SEH2_TRY {
|
||||||
sb_block = EXT4_MIN_BLOCK_SIZE / BLOCK_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == sbi->s_group_desc) {
|
ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE);
|
||||||
sbi->s_group_desc = kzalloc(sbi->s_gdb_count * sizeof(ext3_fsblk_t),
|
|
||||||
GFP_KERNEL);
|
|
||||||
}
|
|
||||||
if (sbi->s_group_desc == NULL) {
|
|
||||||
DEBUG(DL_ERR, ("Ext2LoadGroup: not enough memory.\n"));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < sbi->s_gdb_count; i++) {
|
if (NULL == sbi->s_gd) {
|
||||||
sbi->s_group_desc[i] = descriptor_loc(sb, sb_block, i);
|
sbi->s_gd = kzalloc(sbi->s_gdb_count * sizeof(struct ext3_gd),
|
||||||
if (!sbi->s_group_desc[i]) {
|
GFP_KERNEL);
|
||||||
DEBUG(DL_ERR, ("Ext2LoadGroup: can't read group descriptor %d\n", i));
|
}
|
||||||
return FALSE;
|
if (sbi->s_gd == NULL) {
|
||||||
|
DEBUG(DL_ERR, ("Ext2LoadGroup: not enough memory.\n"));
|
||||||
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!ext4_check_descriptors(sb)) {
|
if (BLOCK_SIZE != EXT3_MIN_BLOCK_SIZE) {
|
||||||
DEBUG(DL_ERR, ("Ext2LoadGroup: group descriptors corrupted!\n"));
|
sb_block = EXT4_MIN_BLOCK_SIZE / BLOCK_SIZE;
|
||||||
return FALSE;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
for (i = 0; i < sbi->s_gdb_count; i++) {
|
||||||
|
sbi->s_gd[i].block = descriptor_loc(sb, sb_block, i);
|
||||||
|
if (!sbi->s_gd[i].block) {
|
||||||
|
DEBUG(DL_ERR, ("Ext2LoadGroup: can't locate group descriptor %d\n", i));
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
sbi->s_gd[i].bh = sb_getblk(sb, sbi->s_gd[i].block);
|
||||||
|
if (!sbi->s_gd[i].bh) {
|
||||||
|
DEBUG(DL_ERR, ("Ext2LoadGroup: can't read group descriptor %d\n", i));
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
sbi->s_gd[i].gd = (struct ext4_group_desc *)sbi->s_gd[i].bh->b_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ext4_check_descriptors(sb)) {
|
||||||
|
DbgBreak();
|
||||||
|
DEBUG(DL_ERR, ("Ext2LoadGroup: group descriptors corrupted!\n"));
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = TRUE;
|
||||||
|
|
||||||
|
} _SEH2_FINALLY {
|
||||||
|
|
||||||
|
if (!rc)
|
||||||
|
Ext2PutGroup(Vcb);
|
||||||
|
|
||||||
|
ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
|
||||||
|
} _SEH2_END;
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -169,14 +212,26 @@ VOID
|
||||||
Ext2DropGroup(IN PEXT2_VCB Vcb)
|
Ext2DropGroup(IN PEXT2_VCB Vcb)
|
||||||
{
|
{
|
||||||
struct ext3_sb_info *sbi = &Vcb->sbi;
|
struct ext3_sb_info *sbi = &Vcb->sbi;
|
||||||
|
LARGE_INTEGER timeout;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
|
||||||
if (NULL == sbi->s_group_desc) {
|
/* do nothing if Vcb is not initialized yet */
|
||||||
|
if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
kfree(sbi->s_group_desc);
|
_SEH2_TRY {
|
||||||
sbi->s_group_desc = NULL;
|
SetFlag(Vcb->Flags, VCB_BEING_DROPPED);
|
||||||
|
ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE);
|
||||||
|
Ext2PutGroup(Vcb);
|
||||||
|
} _SEH2_FINALLY {
|
||||||
|
ExReleaseResourceLite(&Vcb->sbi.s_gd_lock);
|
||||||
|
} _SEH2_END;
|
||||||
|
|
||||||
|
timeout.QuadPart = (LONGLONG)-10*1000*1000;
|
||||||
|
KeWaitForSingleObject(&Vcb->bd.bd_bh_notify,
|
||||||
|
Executive, KernelMode,
|
||||||
|
FALSE, &timeout);
|
||||||
|
ClearFlag(Vcb->Flags, VCB_BEING_DROPPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
|
@ -592,7 +647,7 @@ Ext2NewBlock(
|
||||||
|
|
||||||
*Block = 0;
|
*Block = 0;
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&Vcb->MetaLock, TRUE);
|
ExAcquireResourceExclusiveLite(&Vcb->MetaBlock, TRUE);
|
||||||
|
|
||||||
/* validate the hint group and hint block */
|
/* validate the hint group and hint block */
|
||||||
if (GroupHint >= Vcb->sbi.s_groups_count) {
|
if (GroupHint >= Vcb->sbi.s_groups_count) {
|
||||||
|
@ -762,7 +817,7 @@ Again:
|
||||||
|
|
||||||
errorout:
|
errorout:
|
||||||
|
|
||||||
ExReleaseResourceLite(&Vcb->MetaLock);
|
ExReleaseResourceLite(&Vcb->MetaBlock);
|
||||||
|
|
||||||
if (bh)
|
if (bh)
|
||||||
fini_bh(&bh);
|
fini_bh(&bh);
|
||||||
|
@ -799,7 +854,7 @@ Ext2FreeBlock(
|
||||||
|
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&Vcb->MetaLock, TRUE);
|
ExAcquireResourceExclusiveLite(&Vcb->MetaBlock, TRUE);
|
||||||
|
|
||||||
DEBUG(DL_INF, ("Ext2FreeBlock: Block %xh - %x to be freed.\n",
|
DEBUG(DL_INF, ("Ext2FreeBlock: Block %xh - %x to be freed.\n",
|
||||||
Block, Block + Number));
|
Block, Block + Number));
|
||||||
|
@ -916,7 +971,7 @@ errorout:
|
||||||
if (gb)
|
if (gb)
|
||||||
fini_bh(&gb);
|
fini_bh(&gb);
|
||||||
|
|
||||||
ExReleaseResourceLite(&Vcb->MetaLock);
|
ExReleaseResourceLite(&Vcb->MetaBlock);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -948,7 +1003,7 @@ Ext2NewInode(
|
||||||
|
|
||||||
*Inode = dwInode = 0XFFFFFFFF;
|
*Inode = dwInode = 0XFFFFFFFF;
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&Vcb->MetaLock, TRUE);
|
ExAcquireResourceExclusiveLite(&Vcb->MetaInode, TRUE);
|
||||||
|
|
||||||
if (GroupHint >= Vcb->sbi.s_groups_count)
|
if (GroupHint >= Vcb->sbi.s_groups_count)
|
||||||
GroupHint = GroupHint % Vcb->sbi.s_groups_count;
|
GroupHint = GroupHint % Vcb->sbi.s_groups_count;
|
||||||
|
@ -1088,7 +1143,7 @@ repeat:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fini_bh(&gb);
|
fini_bh(&gb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1272,7 +1327,7 @@ repeat:
|
||||||
|
|
||||||
errorout:
|
errorout:
|
||||||
|
|
||||||
ExReleaseResourceLite(&Vcb->MetaLock);
|
ExReleaseResourceLite(&Vcb->MetaInode);
|
||||||
|
|
||||||
if (bh)
|
if (bh)
|
||||||
fini_bh(&bh);
|
fini_bh(&bh);
|
||||||
|
@ -1284,6 +1339,44 @@ errorout:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
Ext2UpdateGroupDirStat(
|
||||||
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
|
IN PEXT2_VCB Vcb,
|
||||||
|
IN ULONG group
|
||||||
|
)
|
||||||
|
{
|
||||||
|
struct super_block *sb = &Vcb->sb;
|
||||||
|
PEXT2_GROUP_DESC gd;
|
||||||
|
struct buffer_head *gb = NULL;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
ExAcquireResourceExclusiveLite(&Vcb->MetaInode, TRUE);
|
||||||
|
|
||||||
|
/* get group desc */
|
||||||
|
gd = ext4_get_group_desc(sb, group, &gb);
|
||||||
|
if (!gd) {
|
||||||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto errorout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update group_desc and super_block */
|
||||||
|
ext4_used_dirs_set(sb, gd, ext4_used_dirs_count(sb, gd) - 1);
|
||||||
|
Ext2SaveGroup(IrpContext, Vcb, group);
|
||||||
|
Ext2UpdateVcbStat(IrpContext, Vcb);
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
errorout:
|
||||||
|
|
||||||
|
ExReleaseResourceLite(&Vcb->MetaInode);
|
||||||
|
|
||||||
|
if (gb)
|
||||||
|
fini_bh(&gb);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2FreeInode(
|
Ext2FreeInode(
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
|
@ -1308,7 +1401,7 @@ Ext2FreeInode(
|
||||||
|
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&Vcb->MetaLock, TRUE);
|
ExAcquireResourceExclusiveLite(&Vcb->MetaInode, TRUE);
|
||||||
|
|
||||||
Group = (Inode - 1) / INODES_PER_GROUP;
|
Group = (Inode - 1) / INODES_PER_GROUP;
|
||||||
dwIno = (Inode - 1) % INODES_PER_GROUP;
|
dwIno = (Inode - 1) % INODES_PER_GROUP;
|
||||||
|
@ -1385,7 +1478,7 @@ Ext2FreeInode(
|
||||||
|
|
||||||
errorout:
|
errorout:
|
||||||
|
|
||||||
ExReleaseResourceLite(&Vcb->MetaLock);
|
ExReleaseResourceLite(&Vcb->MetaInode);
|
||||||
|
|
||||||
if (bh)
|
if (bh)
|
||||||
fini_bh(&bh);
|
fini_bh(&bh);
|
||||||
|
@ -1474,7 +1567,8 @@ Ext2SetFileType (
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
IN PEXT2_VCB Vcb,
|
IN PEXT2_VCB Vcb,
|
||||||
IN PEXT2_FCB Dcb,
|
IN PEXT2_FCB Dcb,
|
||||||
IN PEXT2_MCB Mcb
|
IN PEXT2_MCB Mcb,
|
||||||
|
IN umode_t mode
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
struct inode *dir = Dcb->Inode;
|
struct inode *dir = Dcb->Inode;
|
||||||
|
@ -1507,15 +1601,21 @@ Ext2SetFileType (
|
||||||
if (le32_to_cpu(de->inode) != inode->i_ino)
|
if (le32_to_cpu(de->inode) != inode->i_ino)
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
|
|
||||||
ext3_set_de_type(inode->i_sb, de, inode->i_mode);
|
ext3_set_de_type(inode->i_sb, de, mode);
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
|
|
||||||
//if (!inode->i_nlink)
|
|
||||||
// ext3_orphan_add(handle, inode);
|
|
||||||
|
|
||||||
|
if (S_ISDIR(inode->i_mode) == S_ISDIR(mode)) {
|
||||||
|
} else if (S_ISDIR(inode->i_mode)) {
|
||||||
|
ext3_dec_count(dir);
|
||||||
|
} else if (S_ISDIR(mode)) {
|
||||||
|
ext3_inc_count(dir);
|
||||||
|
}
|
||||||
dir->i_ctime = dir->i_mtime = ext3_current_time(dir);
|
dir->i_ctime = dir->i_mtime = ext3_current_time(dir);
|
||||||
ext3_mark_inode_dirty(IrpContext, dir);
|
ext3_mark_inode_dirty(IrpContext, dir);
|
||||||
|
|
||||||
|
inode->i_mode = mode;
|
||||||
|
ext3_mark_inode_dirty(IrpContext, inode);
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
} _SEH2_FINALLY {
|
} _SEH2_FINALLY {
|
||||||
|
@ -2134,27 +2234,30 @@ __u16 crc16(__u16 crc, __u8 const *buffer, size_t len)
|
||||||
__le16 ext4_group_desc_csum(struct ext3_sb_info *sbi, __u32 block_group,
|
__le16 ext4_group_desc_csum(struct ext3_sb_info *sbi, __u32 block_group,
|
||||||
struct ext4_group_desc *gdp)
|
struct ext4_group_desc *gdp)
|
||||||
{
|
{
|
||||||
__u16 crc = 0;
|
int offset;
|
||||||
|
__u16 crc = 0;
|
||||||
|
__le32 le_group = cpu_to_le32(block_group);
|
||||||
|
|
||||||
if (sbi->s_es->s_feature_ro_compat &
|
/* old crc16 code */
|
||||||
cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
|
if (!(sbi->s_es->s_feature_ro_compat &
|
||||||
int offset = offsetof(struct ext4_group_desc, bg_checksum);
|
cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)))
|
||||||
__le32 le_group = cpu_to_le32(block_group);
|
return 0;
|
||||||
|
|
||||||
crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid));
|
offset = offsetof(struct ext4_group_desc, bg_checksum);
|
||||||
crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group));
|
|
||||||
crc = crc16(crc, (__u8 *)gdp, offset);
|
|
||||||
offset += sizeof(gdp->bg_checksum); /* skip checksum */
|
|
||||||
/* for checksum of struct ext4_group_desc do the rest...*/
|
|
||||||
if ((sbi->s_es->s_feature_incompat &
|
|
||||||
cpu_to_le32(EXT4_FEATURE_INCOMPAT_64BIT)) &&
|
|
||||||
offset < le16_to_cpu(sbi->s_es->s_desc_size))
|
|
||||||
crc = crc16(crc, (__u8 *)gdp + offset,
|
|
||||||
le16_to_cpu(sbi->s_es->s_desc_size) -
|
|
||||||
offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cpu_to_le16(crc);
|
crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid));
|
||||||
|
crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group));
|
||||||
|
crc = crc16(crc, (__u8 *)gdp, offset);
|
||||||
|
offset += sizeof(gdp->bg_checksum); /* skip checksum */
|
||||||
|
/* for checksum of struct ext4_group_desc do the rest...*/
|
||||||
|
if ((sbi->s_es->s_feature_incompat &
|
||||||
|
cpu_to_le32(EXT4_FEATURE_INCOMPAT_64BIT)) &&
|
||||||
|
offset < le16_to_cpu(sbi->s_es->s_desc_size))
|
||||||
|
crc = crc16(crc, (__u8 *)gdp + offset,
|
||||||
|
le16_to_cpu(sbi->s_es->s_desc_size) -
|
||||||
|
offset);
|
||||||
|
|
||||||
|
return cpu_to_le16(crc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ext4_group_desc_csum_verify(struct ext3_sb_info *sbi, __u32 block_group,
|
int ext4_group_desc_csum_verify(struct ext3_sb_info *sbi, __u32 block_group,
|
||||||
|
@ -2489,12 +2592,10 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
|
||||||
ext4_group_t block_group, struct buffer_head **bh)
|
ext4_group_t block_group, struct buffer_head **bh)
|
||||||
{
|
{
|
||||||
struct ext4_group_desc *desc = NULL;
|
struct ext4_group_desc *desc = NULL;
|
||||||
struct buffer_head *gb = NULL;
|
|
||||||
struct ext3_sb_info *sbi = EXT3_SB(sb);
|
struct ext3_sb_info *sbi = EXT3_SB(sb);
|
||||||
PEXT2_VCB vcb = sb->s_priv;
|
PEXT2_VCB vcb = sb->s_priv;
|
||||||
|
ext4_group_t group;
|
||||||
unsigned int group;
|
ext4_group_t offset;
|
||||||
unsigned int offset;
|
|
||||||
|
|
||||||
if (bh)
|
if (bh)
|
||||||
*bh = NULL;
|
*bh = NULL;
|
||||||
|
@ -2507,44 +2608,33 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
smp_rmb();
|
|
||||||
|
|
||||||
group = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
|
_SEH2_TRY {
|
||||||
offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
|
|
||||||
|
|
||||||
if (!sbi->s_group_desc || !sbi->s_group_desc[group]) {
|
group = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
|
||||||
Ext2LoadGroup(vcb);
|
offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
|
||||||
}
|
|
||||||
|
|
||||||
if (!sbi->s_group_desc[group]) {
|
if (!sbi->s_gd || !sbi->s_gd[group].block ||
|
||||||
ext4_error(sb, "ext4_get_group_desc",
|
!sbi->s_gd[group].bh) {
|
||||||
"Group descriptor not loaded - "
|
if (!Ext2LoadGroup(vcb)) {
|
||||||
"block_group = %u, group = %u, desc = %u",
|
_SEH2_LEAVE;
|
||||||
block_group, group, offset);
|
}
|
||||||
goto errorout;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
gb = sb_getblk(sb, sbi->s_group_desc[group]);
|
desc = (struct ext4_group_desc *)((PCHAR)sbi->s_gd[group].gd +
|
||||||
if (!gb) {
|
offset * EXT4_DESC_SIZE(sb));
|
||||||
ext4_error(sb, "ext4_get_group_desc",
|
if (bh) {
|
||||||
"failed to load group - "
|
atomic_inc(&sbi->s_gd[group].bh->b_count);
|
||||||
"block_group = %u, group = %u, desc = %u",
|
*bh = sbi->s_gd[group].bh;
|
||||||
block_group, group, offset);
|
}
|
||||||
goto errorout;
|
} _SEH2_FINALLY {
|
||||||
}
|
/* do cleanup */
|
||||||
|
} _SEH2_END;
|
||||||
desc = (struct ext4_group_desc *)(gb->b_data +
|
|
||||||
offset * EXT4_DESC_SIZE(sb));
|
|
||||||
if (bh)
|
|
||||||
*bh = gb;
|
|
||||||
else
|
|
||||||
fini_bh(&gb);
|
|
||||||
|
|
||||||
errorout:
|
|
||||||
|
|
||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ext4_count_free_blocks() -- count filesystem free blocks
|
* ext4_count_free_blocks() -- count filesystem free blocks
|
||||||
* @sb: superblock
|
* @sb: superblock
|
||||||
|
@ -2670,7 +2760,8 @@ int ext4_check_descriptors(struct super_block *sb)
|
||||||
printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
|
printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
|
||||||
"Checksum for group %u failed (%u!=%u)\n",
|
"Checksum for group %u failed (%u!=%u)\n",
|
||||||
i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
|
i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
|
||||||
gdp)), le16_to_cpu(gdp->bg_checksum));
|
gdp)),
|
||||||
|
le16_to_cpu(gdp->bg_checksum));
|
||||||
if (!IsVcbReadOnly(Vcb)) {
|
if (!IsVcbReadOnly(Vcb)) {
|
||||||
__brelse(bh);
|
__brelse(bh);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#pragma warning(disable: 4244)
|
#pragma warning(disable: 4244)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* used by extent splitting.
|
* used by extent splitting.
|
||||||
*/
|
*/
|
||||||
|
@ -1098,6 +1099,77 @@ out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ext4_ext_shrink_indepth(void *icb,
|
||||||
|
handle_t *handle,
|
||||||
|
struct inode *inode,
|
||||||
|
unsigned int flags,
|
||||||
|
int *shrinked)
|
||||||
|
{
|
||||||
|
struct ext4_extent_header *eh, *neh;
|
||||||
|
struct ext4_extent_idx *ix;
|
||||||
|
struct buffer_head *bh = NULL;
|
||||||
|
ext4_fsblk_t block;
|
||||||
|
int err = 0, depth = ext_depth(inode);
|
||||||
|
int neh_entries;
|
||||||
|
*shrinked = 0;
|
||||||
|
|
||||||
|
if (!depth)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
eh = ext_inode_hdr(inode);
|
||||||
|
if (le16_to_cpu(eh->eh_entries) != 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ix = EXT_FIRST_INDEX(eh);
|
||||||
|
block = ext4_idx_pblock(ix);
|
||||||
|
bh = extents_bread(inode->i_sb, block);
|
||||||
|
if (!bh)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* set size of new block */
|
||||||
|
neh = ext_block_hdr(bh);
|
||||||
|
neh_entries = le16_to_cpu(neh->eh_entries);
|
||||||
|
if (!neh->eh_depth &&
|
||||||
|
neh_entries > ext4_ext_space_root(inode, 0))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (neh->eh_depth &&
|
||||||
|
neh_entries > ext4_ext_space_root_idx(inode, 0))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* old root could have indexes or leaves
|
||||||
|
* so calculate e_max right way */
|
||||||
|
if (neh->eh_depth)
|
||||||
|
eh->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode, 0));
|
||||||
|
else
|
||||||
|
eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode, 0));
|
||||||
|
|
||||||
|
eh->eh_magic = cpu_to_le16(EXT4_EXT_MAGIC);
|
||||||
|
eh->eh_entries = neh_entries;
|
||||||
|
if (neh->eh_depth) {
|
||||||
|
memmove(EXT_FIRST_INDEX(eh),
|
||||||
|
EXT_FIRST_INDEX(neh),
|
||||||
|
sizeof(struct ext4_extent_idx) * neh_entries);
|
||||||
|
} else {
|
||||||
|
memmove(EXT_FIRST_EXTENT(eh),
|
||||||
|
EXT_FIRST_EXTENT(neh),
|
||||||
|
sizeof(struct ext4_extent) * neh_entries);
|
||||||
|
}
|
||||||
|
le16_add_cpu(&eh->eh_depth, -1);
|
||||||
|
|
||||||
|
ext4_mark_inode_dirty(icb, handle, inode);
|
||||||
|
*shrinked = 1;
|
||||||
|
out:
|
||||||
|
if (bh)
|
||||||
|
extents_brelse(bh);
|
||||||
|
|
||||||
|
if (*shrinked)
|
||||||
|
ext4_free_blocks(icb, handle, inode, NULL,
|
||||||
|
block, 1, flags);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ext4_ext_create_new_leaf:
|
* ext4_ext_create_new_leaf:
|
||||||
* finds empty index and adds new leaf.
|
* finds empty index and adds new leaf.
|
||||||
|
@ -1355,29 +1427,25 @@ found_extent:
|
||||||
* with leaves.
|
* with leaves.
|
||||||
*/
|
*/
|
||||||
ext4_lblk_t
|
ext4_lblk_t
|
||||||
ext4_ext_next_allocated_block(struct ext4_ext_path *path)
|
ext4_ext_next_allocated_block(struct ext4_ext_path *path, int at)
|
||||||
{
|
{
|
||||||
int depth;
|
if (at == 0 && !path->p_ext && !path->p_idx)
|
||||||
|
|
||||||
depth = path->p_depth;
|
|
||||||
|
|
||||||
if (depth == 0 && path->p_ext == NULL)
|
|
||||||
return EXT_MAX_BLOCKS;
|
return EXT_MAX_BLOCKS;
|
||||||
|
|
||||||
while (depth >= 0) {
|
while (at >= 0) {
|
||||||
if (depth == path->p_depth) {
|
if (at == path->p_depth) {
|
||||||
/* leaf */
|
/* leaf */
|
||||||
if (path[depth].p_ext &&
|
if (path[at].p_ext &&
|
||||||
path[depth].p_ext !=
|
path[at].p_ext !=
|
||||||
EXT_LAST_EXTENT(path[depth].p_hdr))
|
EXT_LAST_EXTENT(path[at].p_hdr))
|
||||||
return le32_to_cpu(path[depth].p_ext[1].ee_block);
|
return le32_to_cpu(path[at].p_ext[1].ee_block);
|
||||||
} else {
|
} else {
|
||||||
/* index */
|
/* index */
|
||||||
if (path[depth].p_idx !=
|
if (path[at].p_idx !=
|
||||||
EXT_LAST_INDEX(path[depth].p_hdr))
|
EXT_LAST_INDEX(path[at].p_hdr))
|
||||||
return le32_to_cpu(path[depth].p_idx[1].ei_block);
|
return le32_to_cpu(path[at].p_idx[1].ei_block);
|
||||||
}
|
}
|
||||||
depth--;
|
at--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXT_MAX_BLOCKS;
|
return EXT_MAX_BLOCKS;
|
||||||
|
@ -1414,12 +1482,14 @@ static ext4_lblk_t ext4_ext_next_leaf_block(struct ext4_ext_path *path)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ext4_ext_correct_indexes:
|
* ext4_ext_correct_indexes:
|
||||||
* if leaf gets modified and modified extent is first in the leaf,
|
* if leaf/node gets modified and modified extent/index
|
||||||
|
* is first in the leaf/node,
|
||||||
* then we have to correct all indexes above.
|
* then we have to correct all indexes above.
|
||||||
* TODO: do we need to correct tree in all cases?
|
|
||||||
*/
|
*/
|
||||||
static int ext4_ext_correct_indexes(void *icb, handle_t *handle, struct inode *inode,
|
static int ext4_ext_correct_indexes(void *icb, handle_t *handle,
|
||||||
struct ext4_ext_path *path)
|
struct inode *inode,
|
||||||
|
struct ext4_ext_path *path,
|
||||||
|
int at)
|
||||||
{
|
{
|
||||||
struct ext4_extent_header *eh;
|
struct ext4_extent_header *eh;
|
||||||
int depth = ext_depth(inode);
|
int depth = ext_depth(inode);
|
||||||
|
@ -1427,49 +1497,49 @@ static int ext4_ext_correct_indexes(void *icb, handle_t *handle, struct inode *i
|
||||||
__le32 border;
|
__le32 border;
|
||||||
int k, err = 0;
|
int k, err = 0;
|
||||||
|
|
||||||
eh = path[depth].p_hdr;
|
assert(at >= 0);
|
||||||
ex = path[depth].p_ext;
|
if (!at)
|
||||||
|
|
||||||
if (unlikely(ex == NULL || eh == NULL)) {
|
|
||||||
EXT4_ERROR_INODE(inode,
|
|
||||||
"ex %p == NULL or eh %p == NULL", ex, eh);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth == 0) {
|
|
||||||
/* there is no tree at all */
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (ex != EXT_FIRST_EXTENT(eh)) {
|
if (depth == at) {
|
||||||
/* we correct tree if first leaf got modified only */
|
eh = path[at].p_hdr;
|
||||||
return 0;
|
ex = path[at].p_ext;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
if (ex == NULL || eh == NULL)
|
||||||
* TODO: we need correction if border is smaller than current one
|
return -EIO;
|
||||||
*/
|
|
||||||
k = depth - 1;
|
|
||||||
border = path[depth].p_ext->ee_block;
|
|
||||||
err = ext4_ext_get_access(icb, handle, inode, path + k);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
path[k].p_idx->ei_block = border;
|
|
||||||
err = ext4_ext_dirty(icb, handle, inode, path + k);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
while (k--) {
|
if (at == 0) {
|
||||||
/* change all left-side indexes */
|
/* there is no tree at all */
|
||||||
if (path[k+1].p_idx != EXT_FIRST_INDEX(path[k+1].p_hdr))
|
return 0;
|
||||||
break;
|
}
|
||||||
err = ext4_ext_get_access(icb, handle, inode, path + k);
|
|
||||||
if (err)
|
if (ex != EXT_FIRST_EXTENT(eh)) {
|
||||||
break;
|
/* we correct tree if first leaf got modified only */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
k = at - 1;
|
||||||
|
border = path[at].p_ext->ee_block;
|
||||||
path[k].p_idx->ei_block = border;
|
path[k].p_idx->ei_block = border;
|
||||||
err = ext4_ext_dirty(icb, handle, inode, path + k);
|
err = ext4_ext_dirty(icb, handle, inode, path + k);
|
||||||
if (err)
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
border = path[at].p_idx->ei_block;
|
||||||
|
k = at;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (k) {
|
||||||
|
/* change all left-side indexes */
|
||||||
|
if (path[k].p_idx != EXT_FIRST_INDEX(path[k].p_hdr))
|
||||||
break;
|
break;
|
||||||
|
path[k-1].p_idx->ei_block = border;
|
||||||
|
err = ext4_ext_dirty(icb, handle, inode, path + k-1);
|
||||||
|
if (err)
|
||||||
|
break;
|
||||||
|
|
||||||
|
k--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -1844,9 +1914,11 @@ merge:
|
||||||
if (!(gb_flags & EXT4_GET_BLOCKS_PRE_IO))
|
if (!(gb_flags & EXT4_GET_BLOCKS_PRE_IO))
|
||||||
ext4_ext_try_to_merge(icb, handle, inode, path, nearex);
|
ext4_ext_try_to_merge(icb, handle, inode, path, nearex);
|
||||||
|
|
||||||
|
depth = ext_depth(inode);
|
||||||
|
|
||||||
/* time to correct all indexes above */
|
/* time to correct all indexes above */
|
||||||
err = ext4_ext_correct_indexes(icb, handle, inode, path);
|
err = ext4_ext_correct_indexes(icb, handle,
|
||||||
|
inode, path, depth);
|
||||||
if (err)
|
if (err)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
@ -1880,158 +1952,353 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ext4_remove_blocks(void *icb, handle_t *handle, struct inode *inode,
|
static void ext4_ext_remove_blocks(
|
||||||
struct ext4_extent *ex,
|
void *icb,
|
||||||
unsigned long from, unsigned long to)
|
handle_t *handle,
|
||||||
|
struct inode *inode, struct ext4_extent *ex,
|
||||||
|
ext4_lblk_t from, ext4_lblk_t to)
|
||||||
{
|
{
|
||||||
struct buffer_head *bh;
|
int len = to - from + 1;
|
||||||
int i;
|
ext4_lblk_t num;
|
||||||
|
ext4_fsblk_t start;
|
||||||
if (from >= le32_to_cpu(ex->ee_block)
|
num = from - le32_to_cpu(ex->ee_block);
|
||||||
&& to == le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - 1) {
|
start = ext4_ext_pblock(ex) + num;
|
||||||
/* tail removal */
|
ext_debug("Freeing %lu at %I64u, %d\n", from, start, len);
|
||||||
unsigned long num, start;
|
ext4_free_blocks(icb, handle, inode, NULL,
|
||||||
num = le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - from;
|
start, len, 0);
|
||||||
start = ext4_ext_pblock(ex) + ext4_ext_get_actual_len(ex) - num;
|
|
||||||
ext4_free_blocks(icb, handle, inode, NULL, start, num, 0);
|
|
||||||
} else if (from == le32_to_cpu(ex->ee_block)
|
|
||||||
&& to <= le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - 1) {
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static int ext4_ext_remove_idx(void *icb,
|
||||||
* routine removes index from the index block
|
handle_t *handle,
|
||||||
* it's used in truncate case only. thus all requests are for
|
struct inode *inode,
|
||||||
* last index in the block only
|
struct ext4_ext_path *path,
|
||||||
*/
|
int depth)
|
||||||
int ext4_ext_rm_idx(void *icb, handle_t *handle, struct inode *inode,
|
|
||||||
struct ext4_ext_path *path)
|
|
||||||
{
|
{
|
||||||
int err;
|
int err, i = depth;
|
||||||
ext4_fsblk_t leaf;
|
ext4_fsblk_t leaf;
|
||||||
|
|
||||||
/* free index block */
|
/* free index block */
|
||||||
path--;
|
leaf = ext4_idx_pblock(path[i].p_idx);
|
||||||
leaf = ext4_idx_pblock(path->p_idx);
|
|
||||||
BUG_ON(path->p_hdr->eh_entries == 0);
|
if (path[i].p_idx != EXT_LAST_INDEX(path[i].p_hdr)) {
|
||||||
if ((err = ext4_ext_get_access(icb, handle, inode, path)))
|
int len = EXT_LAST_INDEX(path[i].p_hdr) - path[i].p_idx;
|
||||||
|
memmove(path[i].p_idx, path[i].p_idx + 1,
|
||||||
|
len * sizeof(struct ext4_extent_idx));
|
||||||
|
}
|
||||||
|
|
||||||
|
le16_add_cpu(&path[i].p_hdr->eh_entries, -1);
|
||||||
|
err = ext4_ext_dirty(icb, handle, inode, path + i);
|
||||||
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
path->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(path->p_hdr->eh_entries)-1);
|
|
||||||
if ((err = ext4_ext_dirty(icb, handle, inode, path)))
|
ext_debug("IDX: Freeing %lu at %I64u, %d\n",
|
||||||
return err;
|
le32_to_cpu(path[i].p_idx->ei_block), leaf, 1);
|
||||||
ext4_free_blocks(icb, handle, inode, NULL, leaf, 1, 0);
|
ext4_free_blocks(icb, handle, inode, NULL,
|
||||||
|
leaf, 1, 0);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int ext4_ext_amalgamate(void *icb,
|
||||||
ext4_ext_rm_leaf(void *icb, handle_t *handle, struct inode *inode,
|
handle_t *handle,
|
||||||
struct ext4_ext_path *path, unsigned long start)
|
struct inode *inode,
|
||||||
|
struct ext4_ext_path *path,
|
||||||
|
int at)
|
||||||
{
|
{
|
||||||
int err = 0, correct_index = 0;
|
int new_entries, right_entries;
|
||||||
int depth = ext_depth(inode), credits;
|
int depth = ext_depth(inode);
|
||||||
struct ext4_extent_header *eh;
|
struct ext4_ext_path *right_path = NULL;
|
||||||
unsigned a, b, block, num;
|
ext4_lblk_t now;
|
||||||
unsigned long ex_ee_block;
|
int ret = 0;
|
||||||
unsigned short ex_ee_len;
|
if (!at)
|
||||||
struct ext4_extent *ex;
|
return 0;
|
||||||
|
|
||||||
/* the header must be checked already in ext4_ext_remove_space() */
|
now = ext4_ext_next_allocated_block(path, at - 1);
|
||||||
if (!path[depth].p_hdr)
|
if (now == EXT_MAX_BLOCKS)
|
||||||
path[depth].p_hdr = ext_block_hdr(path[depth].p_bh);
|
goto out;
|
||||||
eh = path[depth].p_hdr;
|
|
||||||
BUG_ON(eh == NULL);
|
|
||||||
|
|
||||||
/* find where to start removing */
|
right_path = ext4_find_extent(inode, now, NULL, 0);
|
||||||
ex = EXT_LAST_EXTENT(eh);
|
if (IS_ERR(right_path)) {
|
||||||
|
ret = PTR_ERR(right_path);
|
||||||
ex_ee_block = le32_to_cpu(ex->ee_block);
|
right_path = NULL;
|
||||||
ex_ee_len = ext4_ext_get_actual_len(ex);
|
goto out;
|
||||||
|
|
||||||
while (ex >= EXT_FIRST_EXTENT(eh) &&
|
|
||||||
ex_ee_block + ex_ee_len > start) {
|
|
||||||
path[depth].p_ext = ex;
|
|
||||||
|
|
||||||
a = ex_ee_block > start ? ex_ee_block : start;
|
|
||||||
b = (unsigned long long)ex_ee_block + ex_ee_len - 1 <
|
|
||||||
EXT_MAX_BLOCKS ? ex_ee_block + ex_ee_len - 1 : EXT_MAX_BLOCKS;
|
|
||||||
|
|
||||||
|
|
||||||
if (a != ex_ee_block && b != ex_ee_block + ex_ee_len - 1) {
|
|
||||||
block = 0;
|
|
||||||
num = 0;
|
|
||||||
BUG();
|
|
||||||
} else if (a != ex_ee_block) {
|
|
||||||
/* remove tail of the extent */
|
|
||||||
block = ex_ee_block;
|
|
||||||
num = a - block;
|
|
||||||
} else if (b != ex_ee_block + ex_ee_len - 1) {
|
|
||||||
/* remove head of the extent */
|
|
||||||
block = a;
|
|
||||||
num = b - a;
|
|
||||||
/* there is no "make a hole" API yet */
|
|
||||||
BUG();
|
|
||||||
} else {
|
|
||||||
/* remove whole extent: excellent! */
|
|
||||||
block = ex_ee_block;
|
|
||||||
num = 0;
|
|
||||||
BUG_ON(a != ex_ee_block);
|
|
||||||
BUG_ON(b != ex_ee_block + ex_ee_len - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at present, extent can't cross block group */
|
|
||||||
/* leaf + bitmap + group desc + sb + inode */
|
|
||||||
credits = 5;
|
|
||||||
if (ex == EXT_FIRST_EXTENT(eh)) {
|
|
||||||
correct_index = 1;
|
|
||||||
credits += (ext_depth(inode)) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*handle = ext4_ext_journal_restart(icb, handle, credits);*/
|
|
||||||
/*if (IS_ERR(icb, handle)) {*/
|
|
||||||
/*err = PTR_ERR(icb, handle);*/
|
|
||||||
/*goto out;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
err = ext4_ext_get_access(icb, handle, inode, path + depth);
|
|
||||||
if (err)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
err = ext4_remove_blocks(icb, handle, inode, ex, a, b);
|
|
||||||
if (err)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (num == 0) {
|
|
||||||
/* this extent is removed entirely mark slot unused */
|
|
||||||
ext4_ext_store_pblock(ex, 0);
|
|
||||||
eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries)-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ex->ee_block = cpu_to_le32(block);
|
|
||||||
ex->ee_len = cpu_to_le16(num);
|
|
||||||
|
|
||||||
err = ext4_ext_dirty(icb, handle, inode, path + depth);
|
|
||||||
if (err)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ex--;
|
|
||||||
ex_ee_block = le32_to_cpu(ex->ee_block);
|
|
||||||
ex_ee_len = ext4_ext_get_actual_len(ex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (correct_index && eh->eh_entries)
|
right_entries = le16_to_cpu(right_path[at].p_hdr->eh_entries);
|
||||||
err = ext4_ext_correct_indexes(icb, handle, inode, path);
|
new_entries = le16_to_cpu(path[at].p_hdr->eh_entries) +
|
||||||
|
right_entries;
|
||||||
|
if (new_entries > path[at].p_hdr->eh_max) {
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (at == depth) {
|
||||||
|
struct ext4_extent *last_ex = EXT_LAST_EXTENT(path[at].p_hdr);
|
||||||
|
memmove(last_ex + 1,
|
||||||
|
EXT_FIRST_EXTENT(right_path[at].p_hdr),
|
||||||
|
right_entries * sizeof(struct ext4_extent));
|
||||||
|
} else {
|
||||||
|
struct ext4_extent_idx *last_ix = EXT_LAST_INDEX(path[at].p_hdr);
|
||||||
|
memmove(last_ix + 1,
|
||||||
|
EXT_FIRST_INDEX(right_path[at].p_hdr),
|
||||||
|
right_entries * sizeof(struct ext4_extent_idx));
|
||||||
|
}
|
||||||
|
path[at].p_hdr->eh_entries = cpu_to_le16(new_entries);
|
||||||
|
right_path[at].p_hdr->eh_entries = 0;
|
||||||
|
ext4_ext_dirty(icb, handle, inode, path + at);
|
||||||
|
|
||||||
/* if this leaf is free, then we should
|
/*
|
||||||
* remove it from index block above */
|
* remove the empty node from index block above.
|
||||||
if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL)
|
*/
|
||||||
err = ext4_ext_rm_idx(icb, handle, inode, path + depth);
|
depth = at;
|
||||||
|
while (depth > 0) {
|
||||||
|
struct ext4_extent_header *eh = right_path[depth].p_hdr;
|
||||||
|
if (eh->eh_entries == 0 && right_path[depth].p_bh != NULL) {
|
||||||
|
ext4_ext_drop_refs(right_path + depth);
|
||||||
|
ret = ext4_ext_remove_idx(icb, handle, inode, right_path, depth - 1);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
ret = ext4_ext_correct_indexes(icb, handle,
|
||||||
|
inode, right_path, depth);
|
||||||
|
out:
|
||||||
|
if (right_path) {
|
||||||
|
ext4_ext_drop_refs(right_path);
|
||||||
|
kfree(right_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ext4_ext_balance(void *icb,
|
||||||
|
handle_t *handle,
|
||||||
|
struct inode *inode,
|
||||||
|
struct ext4_ext_path **path,
|
||||||
|
int at)
|
||||||
|
{
|
||||||
|
int ret, shrinked = 0;
|
||||||
|
int depth = at;
|
||||||
|
|
||||||
|
while (depth > 0) {
|
||||||
|
ret = ext4_ext_amalgamate(icb, handle,
|
||||||
|
inode, *path, depth);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
ret = ext4_ext_shrink_indepth(icb, handle,
|
||||||
|
inode, 0, &shrinked);
|
||||||
|
} while (!ret && shrinked);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: After removal, path should not be reused.
|
||||||
|
*/
|
||||||
|
int ext4_ext_remove_extent(void *icb,
|
||||||
|
handle_t *handle,
|
||||||
|
struct inode *inode, struct ext4_ext_path **path)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
int err = 0;
|
||||||
|
ext4_lblk_t start;
|
||||||
|
uint16_t new_entries;
|
||||||
|
int depth = ext_depth(inode);
|
||||||
|
struct ext4_extent *ex = (*path)[depth].p_ext,
|
||||||
|
*ex2 = ex + 1;
|
||||||
|
struct ext4_extent_header *eh = (*path)[depth].p_hdr;
|
||||||
|
if (!ex)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
start = le32_to_cpu(ex->ee_block);
|
||||||
|
len = ext4_ext_get_actual_len(ex);
|
||||||
|
new_entries = le16_to_cpu(eh->eh_entries) - 1;
|
||||||
|
|
||||||
|
ext4_ext_remove_blocks(icb, handle,
|
||||||
|
inode, ex, start, start + len - 1);
|
||||||
|
if (ex2 <= EXT_LAST_EXTENT(eh))
|
||||||
|
memmove(ex, ex2,
|
||||||
|
(EXT_LAST_EXTENT(eh) - ex2 + 1) * sizeof(struct ext4_extent));
|
||||||
|
eh->eh_entries = cpu_to_le16(new_entries);
|
||||||
|
|
||||||
|
ext4_ext_dirty(icb, handle, inode, (*path) + depth);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the node is free, then we should
|
||||||
|
* remove it from index block above.
|
||||||
|
*/
|
||||||
|
while (depth > 0) {
|
||||||
|
eh = (*path)[depth].p_hdr;
|
||||||
|
if (eh->eh_entries == 0 && (*path)[depth].p_bh != NULL) {
|
||||||
|
ext4_ext_drop_refs((*path) + depth);
|
||||||
|
err = ext4_ext_remove_idx(icb, handle,
|
||||||
|
inode, *path, depth - 1);
|
||||||
|
if (err)
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
err = ext4_ext_correct_indexes(icb, handle,
|
||||||
|
inode, *path, depth);
|
||||||
|
|
||||||
|
if ((*path)->p_hdr->eh_entries == 0) {
|
||||||
|
/*
|
||||||
|
* truncate to zero freed all the tree,
|
||||||
|
* so we need to correct eh_depth
|
||||||
|
*/
|
||||||
|
ext_inode_hdr(inode)->eh_depth = 0;
|
||||||
|
ext_inode_hdr(inode)->eh_max =
|
||||||
|
cpu_to_le16(ext4_ext_space_root(inode, 0));
|
||||||
|
err = ext4_ext_dirty(icb, handle, inode, *path);
|
||||||
|
}
|
||||||
|
err = ext4_ext_balance(icb, handle, inode, path, depth);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int __ext4_ext_truncate(void *icb,
|
||||||
|
handle_t *handle,
|
||||||
|
struct inode *inode,
|
||||||
|
ext4_lblk_t from, ext4_lblk_t to)
|
||||||
|
{
|
||||||
|
int depth = ext_depth(inode), ret = -EIO;
|
||||||
|
struct ext4_extent *ex;
|
||||||
|
struct ext4_ext_path *path = NULL, *npath;
|
||||||
|
ext4_lblk_t now = from;
|
||||||
|
|
||||||
|
if (to < from)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
npath = ext4_find_extent(inode, from, &path, 0);
|
||||||
|
if (IS_ERR(npath))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
path = npath;
|
||||||
|
ex = path[depth].p_ext;
|
||||||
|
if (!ex)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (from < le32_to_cpu(ex->ee_block) &&
|
||||||
|
to < le32_to_cpu(ex->ee_block)) {
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* If we do remove_space inside the range of an extent */
|
||||||
|
if ((le32_to_cpu(ex->ee_block) < from) &&
|
||||||
|
(to < le32_to_cpu(ex->ee_block) +
|
||||||
|
ext4_ext_get_actual_len(ex) - 1)) {
|
||||||
|
|
||||||
|
struct ext4_extent newex;
|
||||||
|
int unwritten = ext4_ext_is_unwritten(ex);
|
||||||
|
ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block);
|
||||||
|
int len = ext4_ext_get_actual_len(ex);
|
||||||
|
ext4_fsblk_t newblock =
|
||||||
|
to + 1 - ee_block + ext4_ext_pblock(ex);
|
||||||
|
|
||||||
|
ex->ee_len = cpu_to_le16(from - ee_block);
|
||||||
|
if (unwritten)
|
||||||
|
ext4_ext_mark_unwritten(ex);
|
||||||
|
|
||||||
|
ext4_ext_dirty(icb, handle, inode, path + depth);
|
||||||
|
|
||||||
|
ext4_ext_remove_blocks(icb, handle,
|
||||||
|
inode,
|
||||||
|
ex, from, to);
|
||||||
|
|
||||||
|
newex.ee_block = cpu_to_le32(to + 1);
|
||||||
|
newex.ee_len = cpu_to_le16(ee_block + len - 1 - to);
|
||||||
|
ext4_ext_store_pblock(&newex, newblock);
|
||||||
|
if (unwritten)
|
||||||
|
ext4_ext_mark_unwritten(&newex);
|
||||||
|
|
||||||
|
ret = ext4_ext_insert_extent(icb, handle,
|
||||||
|
inode, &path, &newex, 0);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - 1 < from) {
|
||||||
|
now = ext4_ext_next_allocated_block(path, depth);
|
||||||
|
npath = ext4_find_extent(inode, now, &path, 0);
|
||||||
|
if (IS_ERR(npath))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
path = npath;
|
||||||
|
ex = path[depth].p_ext;
|
||||||
|
}
|
||||||
|
while (ex &&
|
||||||
|
le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex) - 1 >= now &&
|
||||||
|
le32_to_cpu(ex->ee_block) <= to) {
|
||||||
|
int len, new_len = 0;
|
||||||
|
int unwritten;
|
||||||
|
ext4_lblk_t start, new_start;
|
||||||
|
ext4_fsblk_t newblock;
|
||||||
|
|
||||||
|
new_start = start = le32_to_cpu(ex->ee_block);
|
||||||
|
len = ext4_ext_get_actual_len(ex);
|
||||||
|
newblock = ext4_ext_pblock(ex);
|
||||||
|
if (start < from) {
|
||||||
|
len -= from - start;
|
||||||
|
new_len = from - start;
|
||||||
|
start = from;
|
||||||
|
} else {
|
||||||
|
if (start + len - 1 > to) {
|
||||||
|
new_len = start + len - 1 - to;
|
||||||
|
len -= new_len;
|
||||||
|
new_start = to + 1;
|
||||||
|
newblock += to + 1 - start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
now = ext4_ext_next_allocated_block(path, depth);
|
||||||
|
if (!new_len) {
|
||||||
|
ret = ext4_ext_remove_extent(icb, handle,
|
||||||
|
inode, &path);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ext4_ext_remove_blocks(icb, handle,
|
||||||
|
inode,
|
||||||
|
ex, start, start + len - 1);
|
||||||
|
ex->ee_block = cpu_to_le32(new_start);
|
||||||
|
unwritten = ext4_ext_is_unwritten(ex);
|
||||||
|
ex->ee_len = cpu_to_le16(new_len);
|
||||||
|
ext4_ext_store_pblock(ex, newblock);
|
||||||
|
if (unwritten)
|
||||||
|
ext4_ext_mark_unwritten(ex);
|
||||||
|
|
||||||
|
ext4_ext_dirty(icb, handle,
|
||||||
|
inode, path + depth);
|
||||||
|
}
|
||||||
|
npath = ext4_find_extent(inode, now, &path, 0);
|
||||||
|
if (IS_ERR(npath))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
path = npath;
|
||||||
|
depth = ext_depth(inode);
|
||||||
|
ex = path[depth].p_ext;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
if (path) {
|
||||||
|
ext4_ext_drop_refs(path);
|
||||||
|
kfree(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ERR(npath))
|
||||||
|
ret = PTR_ERR(npath);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ext4_split_extent_at() splits an extent at given block.
|
* ext4_split_extent_at() splits an extent at given block.
|
||||||
*
|
*
|
||||||
|
@ -2171,138 +2438,6 @@ fix_extent_len:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* returns 1 if current index have to be freed (even partial)
|
|
||||||
*/
|
|
||||||
static inline int
|
|
||||||
ext4_ext_more_to_rm(struct ext4_ext_path *path)
|
|
||||||
{
|
|
||||||
BUG_ON(path->p_idx == NULL);
|
|
||||||
|
|
||||||
if (path->p_idx < EXT_FIRST_INDEX(path->p_hdr))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* if truncate on deeper level happened it it wasn't partial
|
|
||||||
* so we have to consider current index for truncation
|
|
||||||
*/
|
|
||||||
if (le16_to_cpu(path->p_hdr->eh_entries) == path->p_block)
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ext4_ext_remove_space(void *icb, struct inode *inode, unsigned long start)
|
|
||||||
{
|
|
||||||
#ifndef __REACTOS__
|
|
||||||
struct super_block *sb = inode->i_sb;
|
|
||||||
#endif
|
|
||||||
int depth = ext_depth(inode);
|
|
||||||
struct ext4_ext_path *path;
|
|
||||||
handle_t *handle = NULL;
|
|
||||||
int i = 0, err = 0;
|
|
||||||
|
|
||||||
/* probably first extent we're gonna free will be last in block */
|
|
||||||
/*handle = ext4_journal_start(inode, depth + 1);*/
|
|
||||||
/*if (IS_ERR(icb, handle))*/
|
|
||||||
/*return PTR_ERR(icb, handle);*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* we start scanning from right side freeing all the blocks
|
|
||||||
* after i_size and walking into the deep
|
|
||||||
*/
|
|
||||||
path = kmalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_KERNEL);
|
|
||||||
if (path == NULL) {
|
|
||||||
ext4_journal_stop(icb, handle);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
memset(path, 0, sizeof(struct ext4_ext_path) * (depth + 1));
|
|
||||||
path[0].p_hdr = ext_inode_hdr(inode);
|
|
||||||
if (ext4_ext_check_inode(inode)) {
|
|
||||||
err = -EIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
path[0].p_depth = depth;
|
|
||||||
|
|
||||||
while (i >= 0 && err == 0) {
|
|
||||||
if (i == depth) {
|
|
||||||
/* this is leaf block */
|
|
||||||
err = ext4_ext_rm_leaf(icb, handle, inode, path, start);
|
|
||||||
/* root level have p_bh == NULL, extents_brelse() eats this */
|
|
||||||
extents_brelse(path[i].p_bh);
|
|
||||||
path[i].p_bh = NULL;
|
|
||||||
i--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this is index block */
|
|
||||||
if (!path[i].p_hdr) {
|
|
||||||
path[i].p_hdr = ext_block_hdr(path[i].p_bh);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!path[i].p_idx) {
|
|
||||||
/* this level hasn't touched yet */
|
|
||||||
path[i].p_idx = EXT_LAST_INDEX(path[i].p_hdr);
|
|
||||||
path[i].p_block = le16_to_cpu(path[i].p_hdr->eh_entries)+1;
|
|
||||||
} else {
|
|
||||||
/* we've already was here, see at next index */
|
|
||||||
path[i].p_idx--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ext4_ext_more_to_rm(path + i)) {
|
|
||||||
struct buffer_head *bh;
|
|
||||||
/* go to the next level */
|
|
||||||
memset(path + i + 1, 0, sizeof(*path));
|
|
||||||
bh = read_extent_tree_block(inode, ext4_idx_pblock(path[i].p_idx), path[0].p_depth - (i + 1), 0);
|
|
||||||
if (IS_ERR(bh)) {
|
|
||||||
/* should we reset i_size? */
|
|
||||||
err = -EIO;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
path[i+1].p_bh = bh;
|
|
||||||
|
|
||||||
/* put actual number of indexes to know is this
|
|
||||||
* number got changed at the next iteration */
|
|
||||||
path[i].p_block = le16_to_cpu(path[i].p_hdr->eh_entries);
|
|
||||||
i++;
|
|
||||||
} else {
|
|
||||||
/* we finish processing this index, go up */
|
|
||||||
if (path[i].p_hdr->eh_entries == 0 && i > 0) {
|
|
||||||
/* index is empty, remove it
|
|
||||||
* handle must be already prepared by the
|
|
||||||
* truncatei_leaf() */
|
|
||||||
err = ext4_ext_rm_idx(icb, handle, inode, path + i);
|
|
||||||
}
|
|
||||||
/* root level have p_bh == NULL, extents_brelse() eats this */
|
|
||||||
extents_brelse(path[i].p_bh);
|
|
||||||
path[i].p_bh = NULL;
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: flexible tree reduction should be here */
|
|
||||||
if (path->p_hdr->eh_entries == 0) {
|
|
||||||
/*
|
|
||||||
* truncate to zero freed all the tree
|
|
||||||
* so, we need to correct eh_depth
|
|
||||||
*/
|
|
||||||
err = ext4_ext_get_access(icb, handle, inode, path);
|
|
||||||
if (err == 0) {
|
|
||||||
ext_inode_hdr(inode)->eh_depth = 0;
|
|
||||||
ext_inode_hdr(inode)->eh_max =
|
|
||||||
cpu_to_le16(ext4_ext_space_root(inode, 0));
|
|
||||||
err = ext4_ext_dirty(icb, handle, inode, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
if (path) {
|
|
||||||
ext4_ext_drop_refs(path);
|
|
||||||
kfree(path);
|
|
||||||
}
|
|
||||||
ext4_journal_stop(icb, handle);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
struct ext4_extent_header *eh;
|
struct ext4_extent_header *eh;
|
||||||
|
@ -2441,7 +2576,7 @@ int ext4_ext_get_blocks(void *icb, handle_t *handle, struct inode *inode, ext4_f
|
||||||
|
|
||||||
/* find next allocated block so that we know how many
|
/* find next allocated block so that we know how many
|
||||||
* blocks we can allocate without ovelapping next extent */
|
* blocks we can allocate without ovelapping next extent */
|
||||||
next = ext4_ext_next_allocated_block(path);
|
next = ext4_ext_next_allocated_block(path, depth);
|
||||||
BUG_ON(next <= iblock);
|
BUG_ON(next <= iblock);
|
||||||
allocated = next - iblock;
|
allocated = next - iblock;
|
||||||
if (flags & EXT4_GET_BLOCKS_PRE_IO && max_blocks > EXT_UNWRITTEN_MAX_LEN)
|
if (flags & EXT4_GET_BLOCKS_PRE_IO && max_blocks > EXT_UNWRITTEN_MAX_LEN)
|
||||||
|
@ -2504,7 +2639,8 @@ out2:
|
||||||
|
|
||||||
int ext4_ext_truncate(void *icb, struct inode *inode, unsigned long start)
|
int ext4_ext_truncate(void *icb, struct inode *inode, unsigned long start)
|
||||||
{
|
{
|
||||||
int ret = ext4_ext_remove_space(icb, inode, start);
|
int ret = __ext4_ext_truncate(icb, NULL, inode,
|
||||||
|
start, EXT_MAX_BLOCKS);
|
||||||
|
|
||||||
/* Save modifications on i_blocks field of the inode. */
|
/* Save modifications on i_blocks field of the inode. */
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
|
|
@ -17,6 +17,9 @@ extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
/* DEFINITIONS *************************************************************/
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
|
#define FASTIO_DEBUG_LEVEL DL_NVR
|
||||||
|
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
|
|
||||||
#pragma alloc_text(PAGE, Ext2FastIoRead)
|
#pragma alloc_text(PAGE, Ext2FastIoRead)
|
||||||
|
@ -213,30 +216,34 @@ Ext2FastIoWrite (
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ExAcquireResourceExclusiveLite(&Fcb->MainResource, Wait))
|
if (!ExAcquireResourceSharedLite(Fcb->Header.Resource, Wait)) {
|
||||||
Locked = TRUE;
|
|
||||||
else
|
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
Locked = TRUE;
|
||||||
|
|
||||||
if (IsWritingToEof(*FileOffset) ||
|
if (IsWritingToEof(*FileOffset) ||
|
||||||
|
Fcb->Header.ValidDataLength.QuadPart < FileOffset->QuadPart + Length ||
|
||||||
Fcb->Header.FileSize.QuadPart < FileOffset->QuadPart + Length ) {
|
Fcb->Header.FileSize.QuadPart < FileOffset->QuadPart + Length ) {
|
||||||
Status = FALSE;
|
Status = FALSE;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Locked) {
|
||||||
|
ExReleaseResourceLite(Fcb->Header.Resource);
|
||||||
|
Locked = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
Status = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait,
|
Status = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait,
|
||||||
LockKey, Buffer, IoStatus, DeviceObject);
|
LockKey, Buffer, IoStatus, DeviceObject);
|
||||||
if (Status) {
|
if (Status) {
|
||||||
if (IoStatus)
|
if (IoStatus)
|
||||||
Length = (ULONG)IoStatus->Information;
|
Length = (ULONG)IoStatus->Information;
|
||||||
if (Fcb->Header.ValidDataLength.QuadPart < FileOffset->QuadPart + Length)
|
|
||||||
Fcb->Header.ValidDataLength.QuadPart = FileOffset->QuadPart + Length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} _SEH2_FINALLY {
|
} _SEH2_FINALLY {
|
||||||
|
|
||||||
if (Locked) {
|
if (Locked) {
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
ExReleaseResourceLite(Fcb->Header.Resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
FsRtlExitFileSystem();
|
FsRtlExitFileSystem();
|
||||||
|
@ -981,3 +988,137 @@ Ext2FastIoQueryNetworkOpenInfo (
|
||||||
|
|
||||||
return bResult;
|
return bResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
Ext2AcquireForCreateSection (
|
||||||
|
IN PFILE_OBJECT FileObject
|
||||||
|
)
|
||||||
|
|
||||||
|
{
|
||||||
|
PEXT2_FCB Fcb = FileObject->FsContext;
|
||||||
|
|
||||||
|
if (Fcb->Header.Resource != NULL) {
|
||||||
|
ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2AcquireForCreateSection: Fcb=%p\n", Fcb));
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
Ext2ReleaseForCreateSection (
|
||||||
|
IN PFILE_OBJECT FileObject
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PEXT2_FCB Fcb = FileObject->FsContext;
|
||||||
|
|
||||||
|
DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2ReleaseForCreateSection: Fcb=%p\n", Fcb));
|
||||||
|
|
||||||
|
if (Fcb->Header.Resource != NULL) {
|
||||||
|
ExReleaseResourceLite(Fcb->Header.Resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
Ext2AcquireFileForModWrite (
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN PLARGE_INTEGER EndingOffset,
|
||||||
|
OUT PERESOURCE *ResourceToRelease,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
)
|
||||||
|
|
||||||
|
{
|
||||||
|
BOOLEAN ResourceAcquired = FALSE;
|
||||||
|
|
||||||
|
PEXT2_FCB Fcb = FileObject->FsContext;
|
||||||
|
|
||||||
|
*ResourceToRelease = Fcb->Header.Resource;
|
||||||
|
ResourceAcquired = ExAcquireResourceExclusiveLite(*ResourceToRelease, FALSE);
|
||||||
|
if (!ResourceAcquired) {
|
||||||
|
*ResourceToRelease = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2AcquireFileForModWrite: Fcb=%p Acquired=%d\n",
|
||||||
|
Fcb, ResourceAcquired));
|
||||||
|
|
||||||
|
return (ResourceAcquired ? STATUS_SUCCESS : STATUS_CANT_WAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
Ext2ReleaseFileForModWrite (
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN PERESOURCE ResourceToRelease,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PEXT2_FCB Fcb = FileObject->FsContext;
|
||||||
|
|
||||||
|
DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2ReleaseFileForModWrite: Fcb=%p\n", Fcb));
|
||||||
|
|
||||||
|
if (ResourceToRelease != NULL) {
|
||||||
|
ASSERT(ResourceToRelease == Fcb->Header.Resource);
|
||||||
|
ExReleaseResourceLite(ResourceToRelease);
|
||||||
|
} else {
|
||||||
|
DbgBreak();
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
Ext2AcquireFileForCcFlush (
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PEXT2_FCB Fcb = FileObject->FsContext;
|
||||||
|
|
||||||
|
if (Fcb->Header.Resource != NULL) {
|
||||||
|
ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2AcquireFileForCcFlush: Fcb=%p\n", Fcb));
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
Ext2ReleaseFileForCcFlush (
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PEXT2_FCB Fcb = FileObject->FsContext;
|
||||||
|
|
||||||
|
DEBUG(FASTIO_DEBUG_LEVEL, ("Ext2ReleaseFileForCcFlush: Fcb=%p\n", Fcb));
|
||||||
|
|
||||||
|
if (Fcb->Header.Resource != NULL) {
|
||||||
|
ExReleaseResourceLite(Fcb->Header.Resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS NTAPI
|
||||||
|
Ext2PreAcquireForCreateSection(
|
||||||
|
IN PFS_FILTER_CALLBACK_DATA cd,
|
||||||
|
OUT PVOID *cc
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PEXT2_FCB Fcb = (PEXT2_FCB)cd->FileObject->FsContext;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
ASSERT(cd->Operation == FS_FILTER_ACQUIRE_FOR_SECTION_SYNCHRONIZATION);
|
||||||
|
ExAcquireResourceExclusiveLite(Fcb->Header.Resource, TRUE);
|
||||||
|
if (cd->Parameters.AcquireForSectionSynchronization.SyncType != SyncTypeCreateSection) {
|
||||||
|
status = STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY;
|
||||||
|
} else if (Fcb->ShareAccess.Writers == 0) {
|
||||||
|
status = STATUS_FILE_LOCKED_WITH_ONLY_READERS;
|
||||||
|
} else {
|
||||||
|
status = STATUS_FILE_LOCKED_WITH_WRITERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
|
@ -554,13 +554,6 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
VcbMainResourceAcquired = TRUE;
|
VcbMainResourceAcquired = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsVcbReadOnly(Vcb)) {
|
|
||||||
if (FileInformationClass != FilePositionInformation) {
|
|
||||||
Status = STATUS_MEDIA_WRITE_PROTECTED;
|
|
||||||
_SEH2_LEAVE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
|
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
|
||||||
Status = STATUS_ACCESS_DENIED;
|
Status = STATUS_ACCESS_DENIED;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
|
@ -596,6 +589,17 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
Mcb = Fcb->Mcb;
|
Mcb = Fcb->Mcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FileInformationClass != FilePositionInformation) {
|
||||||
|
if (IsVcbReadOnly(Vcb)) {
|
||||||
|
Status = STATUS_MEDIA_WRITE_PROTECTED;
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
if (!Ext2CheckFileAccess(Vcb, Mcb, Ext2FileCanWrite)) {
|
||||||
|
Status = STATUS_ACCESS_DENIED;
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( !IsDirectory(Fcb) && !FlagOn(Fcb->Flags, FCB_PAGE_FILE) &&
|
if ( !IsDirectory(Fcb) && !FlagOn(Fcb->Flags, FCB_PAGE_FILE) &&
|
||||||
((FileInformationClass == FileEndOfFileInformation) ||
|
((FileInformationClass == FileEndOfFileInformation) ||
|
||||||
(FileInformationClass == FileValidDataLengthInformation) ||
|
(FileInformationClass == FileValidDataLengthInformation) ||
|
||||||
|
@ -1289,8 +1293,9 @@ Ext2SetDispositionInfo(
|
||||||
DEBUG(DL_INF, ( "Ext2SetDispositionInformation: Removing %wZ.\n",
|
DEBUG(DL_INF, ( "Ext2SetDispositionInformation: Removing %wZ.\n",
|
||||||
&Mcb->FullName));
|
&Mcb->FullName));
|
||||||
|
|
||||||
/* always allow deleting on symlinks */
|
if (Ccb->SymLink || IsInodeSymLink(&Mcb->Inode)) {
|
||||||
if (Ccb->SymLink == NULL) {
|
/* always allow deleting on symlinks */
|
||||||
|
} else {
|
||||||
status = Ext2IsFileRemovable(IrpContext, Vcb, Fcb, Ccb);
|
status = Ext2IsFileRemovable(IrpContext, Vcb, Fcb, Ccb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,9 @@ Ext2FlushVolume (
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
|
DEBUG(DL_INF, ( "Ext2FlushVolume: Flushing Vcb ...\n"));
|
||||||
|
|
||||||
|
/* discard buffer_headers for group_desc */
|
||||||
|
Ext2DropGroup(Vcb);
|
||||||
|
|
||||||
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
|
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
|
||||||
ExReleaseResourceLite(&Vcb->PagingIoResource);
|
ExReleaseResourceLite(&Vcb->PagingIoResource);
|
||||||
|
|
||||||
|
|
|
@ -1422,7 +1422,8 @@ Ext2GetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
if (!Mcb || !IsInodeSymLink(&Mcb->Inode)) {
|
if (!Mcb || !IsInodeSymLink(&Mcb->Inode) ||
|
||||||
|
!IsFlagOn(Ccb->Flags, CCB_OPEN_REPARSE_POINT)) {
|
||||||
Status = STATUS_NOT_A_REPARSE_POINT;
|
Status = STATUS_NOT_A_REPARSE_POINT;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
@ -1567,7 +1568,6 @@ out:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
|
@ -1673,15 +1673,31 @@ Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* free all data blocks of the inode (to be set as symlink) */
|
||||||
|
{
|
||||||
|
LARGE_INTEGER zero = {0};
|
||||||
|
Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* decrease dir count of group desc and vcb stat */
|
||||||
|
if (S_ISDIR(Mcb->Inode.i_mode)) {
|
||||||
|
|
||||||
|
ULONG group = (Mcb->Inode.i_ino - 1) / INODES_PER_GROUP;
|
||||||
|
Ext2UpdateGroupDirStat(IrpContext, Vcb, group);
|
||||||
|
|
||||||
|
/* drop extra reference for dir inode */
|
||||||
|
ext3_dec_count(&Mcb->Inode);
|
||||||
|
}
|
||||||
|
|
||||||
/* overwrite inode mode as type SYMLINK */
|
/* overwrite inode mode as type SYMLINK */
|
||||||
Mcb->Inode.i_mode = S_IFLNK | S_IRWXUGO;
|
|
||||||
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
|
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
|
||||||
SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_REPARSE_POINT);
|
SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_REPARSE_POINT);
|
||||||
|
|
||||||
Status = Ext2WriteSymlink(IrpContext, Vcb, Mcb, OemNameBuffer,
|
Status = Ext2WriteSymlink(IrpContext, Vcb, Mcb, OemNameBuffer,
|
||||||
OemNameLength, &BytesWritten);
|
OemNameLength, &BytesWritten);
|
||||||
if (NT_SUCCESS(Status)) {
|
if (NT_SUCCESS(Status)) {
|
||||||
Status = Ext2SetFileType(IrpContext, Vcb, ParentDcb, Mcb);
|
Ext2SetFileType(IrpContext, Vcb, ParentDcb, Mcb,
|
||||||
|
S_IFLNK | S_IRWXUGO);
|
||||||
}
|
}
|
||||||
|
|
||||||
} _SEH2_FINALLY {
|
} _SEH2_FINALLY {
|
||||||
|
@ -1799,7 +1815,8 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Mcb) {
|
if (!Mcb || !IsInodeSymLink(&Mcb->Inode) ||
|
||||||
|
!IsFlagOn(Ccb->Flags, CCB_OPEN_REPARSE_POINT)) {
|
||||||
Status = STATUS_NOT_A_REPARSE_POINT;
|
Status = STATUS_NOT_A_REPARSE_POINT;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
@ -1825,15 +1842,9 @@ Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
|
|
||||||
SetFlag(Mcb->Inode.i_flags, EXT4_EXTENTS_FL);
|
/* inode is to be removed */
|
||||||
}
|
SetFlag(Ccb->Flags, CCB_DELETE_ON_CLOSE);
|
||||||
ClearFlag(Mcb->FileAttr, FILE_ATTRIBUTE_REPARSE_POINT);
|
|
||||||
ClearFlag(Mcb->Inode.i_flags, S_IFLNK);
|
|
||||||
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
|
|
||||||
if (NT_SUCCESS(Status)) {
|
|
||||||
Status = Ext2SetFileType(IrpContext, Vcb, ParentDcb, Mcb);
|
|
||||||
}
|
|
||||||
|
|
||||||
} _SEH2_FINALLY {
|
} _SEH2_FINALLY {
|
||||||
|
|
||||||
|
@ -2702,6 +2713,9 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb,
|
||||||
FlushBeforePurge = FALSE;
|
FlushBeforePurge = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* discard buffer_headers for group_desc */
|
||||||
|
Ext2DropGroup(Vcb);
|
||||||
|
|
||||||
FcbListEntry= NULL;
|
FcbListEntry= NULL;
|
||||||
InitializeListHead(&FcbList);
|
InitializeListHead(&FcbList);
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ DriverEntry(
|
||||||
|
|
||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(INIT, Ext2QueryGlobalParameters)
|
#pragma alloc_text(INIT, Ext2QueryGlobalParameters)
|
||||||
|
#pragma alloc_text(INIT, Ext2QueryRegistrySettings)
|
||||||
#pragma alloc_text(INIT, DriverEntry)
|
#pragma alloc_text(INIT, DriverEntry)
|
||||||
#if EXT2_UNLOAD
|
#if EXT2_UNLOAD
|
||||||
#pragma alloc_text(PAGE, DriverUnload)
|
#pragma alloc_text(PAGE, DriverUnload)
|
||||||
|
@ -99,36 +100,222 @@ DriverUnload (IN PDRIVER_OBJECT DriverObject)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BOOLEAN
|
NTSTATUS NTAPI
|
||||||
Ext2QueryGlobalParameters( IN PUNICODE_STRING RegistryPath)
|
Ext2RegistryQueryCallback(
|
||||||
|
IN PWSTR ValueName,
|
||||||
|
IN ULONG ValueType,
|
||||||
|
IN PVOID ValueData,
|
||||||
|
IN ULONG ValueLength,
|
||||||
|
IN PVOID Context,
|
||||||
|
IN PVOID EntryContext
|
||||||
|
)
|
||||||
{
|
{
|
||||||
|
ULONG i = 0;
|
||||||
|
BYTE *s, *t;
|
||||||
|
|
||||||
|
if (NULL == ValueName || NULL == ValueData)
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(WRITING_SUPPORT) &&
|
||||||
|
_wcsnicmp(ValueName, WRITING_SUPPORT, wcslen(WRITING_SUPPORT)) == 0) {
|
||||||
|
|
||||||
|
if (ValueData && ValueLength == sizeof(DWORD)) {
|
||||||
|
if (*((PULONG)ValueData)) {
|
||||||
|
SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
|
||||||
|
} else {
|
||||||
|
ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(CHECKING_BITMAP) &&
|
||||||
|
_wcsnicmp(ValueName, CHECKING_BITMAP, wcslen(CHECKING_BITMAP)) == 0) {
|
||||||
|
|
||||||
|
if (ValueData && ValueLength == sizeof(DWORD)) {
|
||||||
|
if (*((PULONG)ValueData)) {
|
||||||
|
SetLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP);
|
||||||
|
} else {
|
||||||
|
ClearLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(EXT3_FORCEWRITING) &&
|
||||||
|
_wcsnicmp(ValueName, EXT3_FORCEWRITING, wcslen(EXT3_FORCEWRITING)) == 0) {
|
||||||
|
|
||||||
|
if (ValueData && ValueLength == sizeof(DWORD)) {
|
||||||
|
if (*((PULONG)ValueData)) {
|
||||||
|
SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
|
||||||
|
SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
|
||||||
|
} else {
|
||||||
|
ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(AUTO_MOUNT) &&
|
||||||
|
_wcsnicmp(ValueName, AUTO_MOUNT, wcslen(AUTO_MOUNT)) == 0) {
|
||||||
|
|
||||||
|
if (ValueData && ValueLength == sizeof(DWORD)) {
|
||||||
|
if (*((PULONG)ValueData)) {
|
||||||
|
SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
|
||||||
|
} else {
|
||||||
|
ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(CODEPAGE_NAME) &&
|
||||||
|
_wcsnicmp(ValueName, CODEPAGE_NAME, wcslen(CODEPAGE_NAME)) == 0) {
|
||||||
|
|
||||||
|
if (ValueData && ValueLength <= sizeof(WCHAR) * CODEPAGE_MAXLEN) {
|
||||||
|
RtlCopyMemory(&Ext2Global->Codepage.PageName[0],
|
||||||
|
ValueData, ValueLength);
|
||||||
|
}
|
||||||
|
} else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(HIDING_PREFIX) &&
|
||||||
|
_wcsnicmp(ValueName, HIDING_PREFIX, wcslen(HIDING_PREFIX)) == 0) {
|
||||||
|
|
||||||
|
if (ValueData && ValueLength <= sizeof(WCHAR) * HIDINGPAT_LEN) {
|
||||||
|
RtlCopyMemory(&Ext2Global->wHidingPrefix[0],
|
||||||
|
ValueData, ValueLength);
|
||||||
|
}
|
||||||
|
} else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(HIDING_SUFFIX) &&
|
||||||
|
_wcsnicmp(ValueName, HIDING_SUFFIX, wcslen(HIDING_SUFFIX)) == 0) {
|
||||||
|
|
||||||
|
if (ValueData && ValueLength <= sizeof(WCHAR) * HIDINGPAT_LEN) {
|
||||||
|
RtlCopyMemory(&Ext2Global->wHidingSuffix[0],
|
||||||
|
ValueData, ValueLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
Ext2QueryGlobalParameters(IN PUNICODE_STRING RegistryPath)
|
||||||
|
{
|
||||||
|
RTL_QUERY_REGISTRY_TABLE QueryTable[8];
|
||||||
|
int i = 0;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 8);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1 writing support
|
||||||
|
*/
|
||||||
|
QueryTable[i].Flags = 0;
|
||||||
|
QueryTable[0].Name = WRITING_SUPPORT;
|
||||||
|
QueryTable[i].DefaultType = REG_NONE;
|
||||||
|
QueryTable[i].DefaultLength = 0;
|
||||||
|
QueryTable[i].DefaultData = NULL;
|
||||||
|
QueryTable[i].EntryContext = NULL;
|
||||||
|
QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 2 checking bitmap
|
||||||
|
*/
|
||||||
|
QueryTable[i].Flags = 0;
|
||||||
|
QueryTable[i].Name = CHECKING_BITMAP;
|
||||||
|
QueryTable[i].DefaultType = REG_NONE;
|
||||||
|
QueryTable[i].DefaultLength = 0;
|
||||||
|
QueryTable[i].DefaultData = NULL;
|
||||||
|
QueryTable[i].EntryContext = NULL;
|
||||||
|
QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 3 force writing
|
||||||
|
*/
|
||||||
|
QueryTable[i].Flags = 0;
|
||||||
|
QueryTable[i].Name = EXT3_FORCEWRITING;
|
||||||
|
QueryTable[i].DefaultType = REG_NONE;
|
||||||
|
QueryTable[i].DefaultLength = 0;
|
||||||
|
QueryTable[i].DefaultData = NULL;
|
||||||
|
QueryTable[i].EntryContext = NULL;
|
||||||
|
QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 4 automount
|
||||||
|
*/
|
||||||
|
QueryTable[i].Flags = 0;
|
||||||
|
QueryTable[i].Name = AUTO_MOUNT;
|
||||||
|
QueryTable[i].DefaultType = REG_NONE;
|
||||||
|
QueryTable[i].DefaultLength = 0;
|
||||||
|
QueryTable[i].DefaultData = NULL;
|
||||||
|
QueryTable[i].EntryContext = NULL;
|
||||||
|
QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 5 codepage
|
||||||
|
*/
|
||||||
|
QueryTable[i].Flags = 0;
|
||||||
|
QueryTable[i].Name = CODEPAGE_NAME;
|
||||||
|
QueryTable[i].DefaultType = REG_NONE;
|
||||||
|
QueryTable[i].DefaultLength = 0;
|
||||||
|
QueryTable[i].DefaultData = NULL;
|
||||||
|
QueryTable[i].EntryContext = NULL;
|
||||||
|
QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 6 hidden prefix
|
||||||
|
*/
|
||||||
|
QueryTable[i].Flags = 0;
|
||||||
|
QueryTable[i].Name = HIDING_PREFIX;
|
||||||
|
QueryTable[i].DefaultType = REG_NONE;
|
||||||
|
QueryTable[i].DefaultLength = 0;
|
||||||
|
QueryTable[i].DefaultData = NULL;
|
||||||
|
QueryTable[i].EntryContext = NULL;
|
||||||
|
QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 7 hidden suffix
|
||||||
|
*/
|
||||||
|
QueryTable[i].Flags = 0;
|
||||||
|
QueryTable[i].Name = HIDING_SUFFIX;
|
||||||
|
QueryTable[i].DefaultType = REG_NONE;
|
||||||
|
QueryTable[i].DefaultLength = 0;
|
||||||
|
QueryTable[i].DefaultData = NULL;
|
||||||
|
QueryTable[i].EntryContext = NULL;
|
||||||
|
QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
Status = RtlQueryRegistryValues(
|
||||||
|
RTL_REGISTRY_ABSOLUTE,
|
||||||
|
RegistryPath->Buffer,
|
||||||
|
&QueryTable[0],
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
return NT_SUCCESS(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
Ext2QueryRegistrySettings(IN PUNICODE_STRING RegistryPath)
|
||||||
|
{
|
||||||
UNICODE_STRING ParameterPath;
|
UNICODE_STRING ParameterPath;
|
||||||
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
UNICODE_STRING UniName;
|
||||||
|
ANSI_STRING AnsiName;
|
||||||
|
|
||||||
ULONG WritingSupport = 0;
|
ULONG WritingSupport = 0;
|
||||||
ULONG CheckingBitmap = 0;
|
ULONG CheckingBitmap = 0;
|
||||||
ULONG Ext3ForceWriting = 0;
|
ULONG Ext3ForceWriting = 0;
|
||||||
ULONG AutoMount = 0;
|
ULONG AutoMount = 0;
|
||||||
|
|
||||||
UNICODE_STRING UniName;
|
|
||||||
ANSI_STRING AnsiName;
|
|
||||||
|
|
||||||
WCHAR UniBuffer[CODEPAGE_MAXLEN];
|
WCHAR UniBuffer[CODEPAGE_MAXLEN];
|
||||||
USHORT Buffer[HIDINGPAT_LEN];
|
USHORT Buffer[HIDINGPAT_LEN];
|
||||||
|
|
||||||
ParameterPath.Length = 0;
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
ParameterPath.Length = 0;
|
||||||
ParameterPath.MaximumLength =
|
ParameterPath.MaximumLength =
|
||||||
RegistryPath->Length + sizeof(PARAMETERS_KEY) + sizeof(WCHAR);
|
RegistryPath->Length + sizeof(PARAMETERS_KEY) + sizeof(WCHAR);
|
||||||
|
|
||||||
ParameterPath.Buffer =
|
ParameterPath.Buffer =
|
||||||
(PWSTR) Ext2AllocatePool(
|
(PWSTR) Ext2AllocatePool(
|
||||||
PagedPool,
|
PagedPool,
|
||||||
ParameterPath.MaximumLength,
|
ParameterPath.MaximumLength,
|
||||||
'LG2E'
|
'LG2E'
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!ParameterPath.Buffer) {
|
if (!ParameterPath.Buffer) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
DEBUG(DL_ERR, ( "Ex2QueryParameters: failed to allocate Parameters...\n"));
|
DEBUG(DL_ERR, ( "Ex2QueryParameters: failed to allocate Parameters...\n"));
|
||||||
|
@ -138,101 +325,24 @@ Ext2QueryGlobalParameters( IN PUNICODE_STRING RegistryPath)
|
||||||
RtlCopyUnicodeString(&ParameterPath, RegistryPath);
|
RtlCopyUnicodeString(&ParameterPath, RegistryPath);
|
||||||
RtlAppendUnicodeToString(&ParameterPath, PARAMETERS_KEY);
|
RtlAppendUnicodeToString(&ParameterPath, PARAMETERS_KEY);
|
||||||
|
|
||||||
/* querying value of WritingSupport */
|
/* enable automount of ext2/3/4 volumes */
|
||||||
RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
|
|
||||||
|
|
||||||
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
|
||||||
QueryTable[0].Name = WRITING_SUPPORT;
|
|
||||||
QueryTable[0].EntryContext = &WritingSupport;
|
|
||||||
|
|
||||||
Status = RtlQueryRegistryValues(
|
|
||||||
RTL_REGISTRY_ABSOLUTE,
|
|
||||||
ParameterPath.Buffer,
|
|
||||||
&QueryTable[0],
|
|
||||||
NULL,
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
DEBUG(DL_ERR, ( "Ext2QueryParameters: WritingSupport=%xh\n", WritingSupport));
|
|
||||||
|
|
||||||
/* querying value of CheckingBitmap */
|
|
||||||
RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
|
|
||||||
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
|
||||||
QueryTable[0].Name = CHECKING_BITMAP;
|
|
||||||
QueryTable[0].EntryContext = &CheckingBitmap;
|
|
||||||
|
|
||||||
Status = RtlQueryRegistryValues(
|
|
||||||
RTL_REGISTRY_ABSOLUTE,
|
|
||||||
ParameterPath.Buffer,
|
|
||||||
&QueryTable[0],
|
|
||||||
NULL,
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
DEBUG(DL_ERR, ( "Ext2QueryParameters: CheckingBitmap=%xh\n", CheckingBitmap));
|
|
||||||
|
|
||||||
/* querying value of Ext3ForceWriting */
|
|
||||||
RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
|
|
||||||
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
|
||||||
QueryTable[0].Name = EXT3_FORCEWRITING;
|
|
||||||
QueryTable[0].EntryContext = &Ext3ForceWriting;
|
|
||||||
|
|
||||||
Status = RtlQueryRegistryValues(
|
|
||||||
RTL_REGISTRY_ABSOLUTE,
|
|
||||||
ParameterPath.Buffer,
|
|
||||||
&QueryTable[0],
|
|
||||||
NULL,
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
DEBUG(DL_ERR, ( "Ext2QueryParameters: Ext3ForceWriting=%xh\n", Ext3ForceWriting));
|
|
||||||
|
|
||||||
|
|
||||||
/* querying value of AutoMount */
|
|
||||||
RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
|
|
||||||
|
|
||||||
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
|
||||||
QueryTable[0].Name = AUTO_MOUNT;
|
|
||||||
QueryTable[0].EntryContext = &AutoMount;
|
|
||||||
|
|
||||||
Status = RtlQueryRegistryValues(
|
|
||||||
RTL_REGISTRY_ABSOLUTE,
|
|
||||||
ParameterPath.Buffer,
|
|
||||||
&QueryTable[0],
|
|
||||||
NULL,
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
|
SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
|
||||||
if (NT_SUCCESS(Status) && AutoMount == 0) {
|
|
||||||
ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(DL_ERR, ( "Ext2QueryParameters: AutoMount=%xh\n", AutoMount));
|
/* query parameter settings from registry */
|
||||||
|
Ext2QueryGlobalParameters(&ParameterPath);
|
||||||
|
|
||||||
/* querying codepage */
|
/* set global codepage settings */
|
||||||
RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
|
if (wcslen(&Ext2Global->Codepage.PageName[0])) {
|
||||||
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->Codepage.PageName[0]);
|
||||||
QueryTable[0].Name = CODEPAGE_NAME;
|
UniName.MaximumLength = CODEPAGE_MAXLEN * sizeof(WCHAR);
|
||||||
QueryTable[0].EntryContext = &(UniName);
|
UniName.Buffer = &Ext2Global->Codepage.PageName[0];
|
||||||
UniName.MaximumLength = CODEPAGE_MAXLEN * sizeof(WCHAR);
|
|
||||||
UniName.Length = 0;
|
|
||||||
UniName.Buffer = (PWSTR)UniBuffer;
|
|
||||||
|
|
||||||
Status = RtlQueryRegistryValues(
|
|
||||||
RTL_REGISTRY_ABSOLUTE,
|
|
||||||
ParameterPath.Buffer,
|
|
||||||
&QueryTable[0],
|
|
||||||
NULL,
|
|
||||||
NULL );
|
|
||||||
|
|
||||||
if (NT_SUCCESS(Status)) {
|
|
||||||
DEBUG(DL_ERR, ( "Ext2QueryParameters: Ext2CodePage=%wZ\n", &UniName));
|
|
||||||
AnsiName.MaximumLength = CODEPAGE_MAXLEN;
|
AnsiName.MaximumLength = CODEPAGE_MAXLEN;
|
||||||
AnsiName.Length = 0;
|
AnsiName.Length = 0;
|
||||||
AnsiName.Buffer = &(Ext2Global->Codepage.AnsiName[0]);
|
AnsiName.Buffer = &Ext2Global->Codepage.AnsiName[0];
|
||||||
|
|
||||||
Status = RtlUnicodeStringToAnsiString(
|
Status = RtlUnicodeStringToAnsiString(
|
||||||
&AnsiName,
|
&AnsiName,
|
||||||
&UniName,
|
&UniName,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong CodePage %wZ ...\n", &UniName));
|
DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong CodePage %wZ ...\n", &UniName));
|
||||||
RtlCopyMemory(&(Ext2Global->Codepage.AnsiName[0]),"default\0", 8);
|
RtlCopyMemory(&(Ext2Global->Codepage.AnsiName[0]),"default\0", 8);
|
||||||
|
@ -243,25 +353,13 @@ Ext2QueryGlobalParameters( IN PUNICODE_STRING RegistryPath)
|
||||||
}
|
}
|
||||||
Ext2Global->Codepage.AnsiName[CODEPAGE_MAXLEN - 1] = 0;
|
Ext2Global->Codepage.AnsiName[CODEPAGE_MAXLEN - 1] = 0;
|
||||||
|
|
||||||
/* querying name hiding patterns: prefix*/
|
|
||||||
RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
|
|
||||||
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
|
||||||
QueryTable[0].Name = HIDING_PREFIX;
|
|
||||||
QueryTable[0].EntryContext = &(UniName);
|
|
||||||
UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR);
|
|
||||||
UniName.Length = 0;
|
|
||||||
UniName.Buffer = Buffer;
|
|
||||||
|
|
||||||
Status = RtlQueryRegistryValues(
|
/* set global hidden prefix pattern */
|
||||||
RTL_REGISTRY_ABSOLUTE,
|
if (wcslen(&Ext2Global->wHidingPrefix[0])) {
|
||||||
ParameterPath.Buffer,
|
UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->wHidingPrefix[0]);
|
||||||
&QueryTable[0],
|
UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR);
|
||||||
NULL,
|
UniName.Buffer = &Ext2Global->wHidingPrefix[0];
|
||||||
NULL );
|
AnsiName.MaximumLength = HIDINGPAT_LEN;
|
||||||
|
|
||||||
if (NT_SUCCESS(Status)) {
|
|
||||||
DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingPrefix=%wZ\n", &UniName));
|
|
||||||
AnsiName.MaximumLength =HIDINGPAT_LEN;
|
|
||||||
AnsiName.Length = 0;
|
AnsiName.Length = 0;
|
||||||
AnsiName.Buffer = &(Ext2Global->sHidingPrefix[0]);
|
AnsiName.Buffer = &(Ext2Global->sHidingPrefix[0]);
|
||||||
|
|
||||||
|
@ -279,26 +377,12 @@ Ext2QueryGlobalParameters( IN PUNICODE_STRING RegistryPath)
|
||||||
}
|
}
|
||||||
Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0;
|
Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0;
|
||||||
|
|
||||||
/* querying name hiding patterns: suffix */
|
|
||||||
RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
|
|
||||||
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
|
||||||
QueryTable[0].Name = HIDING_SUFFIX;
|
|
||||||
QueryTable[0].EntryContext = &(UniName);
|
|
||||||
UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR);
|
|
||||||
UniName.Length = 0;
|
|
||||||
UniName.Buffer = Buffer;
|
|
||||||
|
|
||||||
Status = RtlQueryRegistryValues(
|
/* set global hidden suffix pattern */
|
||||||
RTL_REGISTRY_ABSOLUTE,
|
if (wcslen(&Ext2Global->wHidingSuffix[0])) {
|
||||||
ParameterPath.Buffer,
|
UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->wHidingSuffix[0]);
|
||||||
&QueryTable[0],
|
UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR);
|
||||||
NULL,
|
UniName.Buffer = &Ext2Global->wHidingSuffix[0];
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
if (NT_SUCCESS(Status)) {
|
|
||||||
|
|
||||||
DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingSuffix=%wZ\n", &UniName));
|
|
||||||
AnsiName.MaximumLength = HIDINGPAT_LEN;
|
AnsiName.MaximumLength = HIDINGPAT_LEN;
|
||||||
AnsiName.Length = 0;
|
AnsiName.Length = 0;
|
||||||
AnsiName.Buffer = &(Ext2Global->sHidingSuffix[0]);
|
AnsiName.Buffer = &(Ext2Global->sHidingSuffix[0]);
|
||||||
|
@ -317,29 +401,6 @@ Ext2QueryGlobalParameters( IN PUNICODE_STRING RegistryPath)
|
||||||
}
|
}
|
||||||
Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0;
|
Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0;
|
||||||
|
|
||||||
{
|
|
||||||
if (WritingSupport) {
|
|
||||||
SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
|
|
||||||
} else {
|
|
||||||
ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckingBitmap) {
|
|
||||||
SetLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP);
|
|
||||||
} else {
|
|
||||||
ClearLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Ext3ForceWriting) {
|
|
||||||
DEBUG(DL_WRN, ("Ext2Fsd -- Warning: Ext3ForceWriting enabled !!!\n"));
|
|
||||||
|
|
||||||
SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
|
|
||||||
SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
|
|
||||||
} else {
|
|
||||||
ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ext2Global->RegistryPath.Buffer = ParameterPath.Buffer;
|
Ext2Global->RegistryPath.Buffer = ParameterPath.Buffer;
|
||||||
Ext2Global->RegistryPath.Length = 0;
|
Ext2Global->RegistryPath.Length = 0;
|
||||||
Ext2Global->RegistryPath.MaximumLength = ParameterPath.MaximumLength;
|
Ext2Global->RegistryPath.MaximumLength = ParameterPath.MaximumLength;
|
||||||
|
@ -360,6 +421,23 @@ Ext2QueryGlobalParameters( IN PUNICODE_STRING RegistryPath)
|
||||||
)
|
)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
VOID
|
||||||
|
Ext2EresourceAlignmentChecking()
|
||||||
|
{
|
||||||
|
/* Verify ERESOURCE alignment in structures */
|
||||||
|
CL_ASSERT((FIELD_OFFSET(EXT2_GLOBAL, Resource) & 7) == 0);
|
||||||
|
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MainResource) & 7) == 0);
|
||||||
|
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, PagingIoResource) & 7) == 0);
|
||||||
|
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaInode) & 7) == 0);
|
||||||
|
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaBlock) & 7) == 0);
|
||||||
|
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, McbLock) & 7) == 0);
|
||||||
|
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, bd.bd_bh_lock) & 7) == 0);
|
||||||
|
CL_ASSERT((FIELD_OFFSET(EXT2_VCB, sbi.s_gd_lock) & 7) == 0);
|
||||||
|
CL_ASSERT((FIELD_OFFSET(EXT2_FCBVCB, MainResource) & 7) == 0);
|
||||||
|
CL_ASSERT((FIELD_OFFSET(EXT2_FCBVCB, PagingIoResource) & 7) == 0);
|
||||||
|
CL_ASSERT((FIELD_OFFSET(EXT2_FCB, MainResource) & 7) == 0);
|
||||||
|
CL_ASSERT((FIELD_OFFSET(EXT2_FCB, PagingIoResource) & 7) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NAME: DriverEntry
|
* NAME: DriverEntry
|
||||||
|
@ -384,24 +462,12 @@ DriverEntry (
|
||||||
PFAST_IO_DISPATCH FastIoDispatch;
|
PFAST_IO_DISPATCH FastIoDispatch;
|
||||||
PCACHE_MANAGER_CALLBACKS CacheManagerCallbacks;
|
PCACHE_MANAGER_CALLBACKS CacheManagerCallbacks;
|
||||||
|
|
||||||
LARGE_INTEGER Timeout;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
BOOLEAN linux_lib_inited = FALSE;
|
BOOLEAN linux_lib_inited = FALSE;
|
||||||
BOOLEAN journal_module_inited = FALSE;
|
BOOLEAN journal_module_inited = FALSE;
|
||||||
|
|
||||||
/* Verify ERESOURCE alignment in structures */
|
|
||||||
ASSERT((FIELD_OFFSET(EXT2_GLOBAL, Resource) & 7) == 0);
|
|
||||||
ASSERT((FIELD_OFFSET(EXT2_VCB, MainResource) & 7) == 0);
|
|
||||||
ASSERT((FIELD_OFFSET(EXT2_VCB, PagingIoResource) & 7) == 0);
|
|
||||||
ASSERT((FIELD_OFFSET(EXT2_VCB, MetaLock) & 7) == 0);
|
|
||||||
ASSERT((FIELD_OFFSET(EXT2_VCB, McbLock) & 7) == 0);
|
|
||||||
ASSERT((FIELD_OFFSET(EXT2_FCBVCB, MainResource) & 7) == 0);
|
|
||||||
ASSERT((FIELD_OFFSET(EXT2_FCBVCB, PagingIoResource) & 7) == 0);
|
|
||||||
ASSERT((FIELD_OFFSET(EXT2_FCB, MainResource) & 7) == 0);
|
|
||||||
ASSERT((FIELD_OFFSET(EXT2_FCB, PagingIoResource) & 7) == 0);
|
|
||||||
|
|
||||||
/* Verity super block ... */
|
/* Verity super block ... */
|
||||||
ASSERT(sizeof(EXT2_SUPER_BLOCK) == 1024);
|
ASSERT(sizeof(EXT2_SUPER_BLOCK) == 1024);
|
||||||
ASSERT(FIELD_OFFSET(EXT2_SUPER_BLOCK, s_magic) == 56);
|
ASSERT(FIELD_OFFSET(EXT2_SUPER_BLOCK, s_magic) == 56);
|
||||||
|
@ -454,12 +520,8 @@ DriverEntry (
|
||||||
InitializeListHead(&(Ext2Global->VcbList));
|
InitializeListHead(&(Ext2Global->VcbList));
|
||||||
ExInitializeResourceLite(&(Ext2Global->Resource));
|
ExInitializeResourceLite(&(Ext2Global->Resource));
|
||||||
|
|
||||||
/* Reaper thread engine event */
|
|
||||||
KeInitializeEvent(&Ext2Global->Reaper.Engine,
|
|
||||||
SynchronizationEvent, FALSE);
|
|
||||||
|
|
||||||
/* query registry settings */
|
/* query registry settings */
|
||||||
Ext2QueryGlobalParameters(RegistryPath);
|
Ext2QueryRegistrySettings(RegistryPath);
|
||||||
|
|
||||||
/* create Ext2Fsd cdrom fs deivce */
|
/* create Ext2Fsd cdrom fs deivce */
|
||||||
RtlInitUnicodeString(&DeviceName, CDROM_NAME);
|
RtlInitUnicodeString(&DeviceName, CDROM_NAME);
|
||||||
|
@ -494,21 +556,18 @@ DriverEntry (
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start resource reaper thread */
|
/* start resource reaper thread */
|
||||||
Status= Ext2StartReaperThread();
|
Status= Ext2StartReaper(
|
||||||
|
&Ext2Global->McbReaper,
|
||||||
|
Ext2McbReaperThread);
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
/* make sure Reaperthread is started */
|
|
||||||
Timeout.QuadPart = (LONGLONG)-10*1000*1000*10; /* 10 seconds */
|
Status= Ext2StartReaper(
|
||||||
Status = KeWaitForSingleObject(
|
&Ext2Global->bhReaper,
|
||||||
&(Ext2Global->Reaper.Engine),
|
Ext2bhReaperThread);
|
||||||
Executive,
|
if (!NT_SUCCESS(Status)) {
|
||||||
KernelMode,
|
Ext2StopReaper(&Ext2Global->McbReaper);
|
||||||
FALSE,
|
|
||||||
&Timeout
|
|
||||||
);
|
|
||||||
if (Status != STATUS_SUCCESS) {
|
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,12 +623,16 @@ DriverEntry (
|
||||||
FastIoDispatch->FastIoUnlockAll = Ext2FastIoUnlockAll;
|
FastIoDispatch->FastIoUnlockAll = Ext2FastIoUnlockAll;
|
||||||
FastIoDispatch->FastIoUnlockAllByKey = Ext2FastIoUnlockAllByKey;
|
FastIoDispatch->FastIoUnlockAllByKey = Ext2FastIoUnlockAllByKey;
|
||||||
FastIoDispatch->FastIoQueryNetworkOpenInfo = Ext2FastIoQueryNetworkOpenInfo;
|
FastIoDispatch->FastIoQueryNetworkOpenInfo = Ext2FastIoQueryNetworkOpenInfo;
|
||||||
|
|
||||||
|
FastIoDispatch->AcquireForModWrite = Ext2AcquireFileForModWrite;
|
||||||
|
FastIoDispatch->ReleaseForModWrite = Ext2ReleaseFileForModWrite;
|
||||||
FastIoDispatch->AcquireForModWrite = Ext2AcquireFileForModWrite;
|
FastIoDispatch->AcquireForModWrite = Ext2AcquireFileForModWrite;
|
||||||
FastIoDispatch->ReleaseForModWrite = Ext2ReleaseFileForModWrite;
|
FastIoDispatch->ReleaseForModWrite = Ext2ReleaseFileForModWrite;
|
||||||
FastIoDispatch->AcquireForCcFlush = Ext2AcquireFileForCcFlush;
|
FastIoDispatch->AcquireForCcFlush = Ext2AcquireFileForCcFlush;
|
||||||
FastIoDispatch->ReleaseForCcFlush = Ext2ReleaseFileForCcFlush;
|
FastIoDispatch->ReleaseForCcFlush = Ext2ReleaseFileForCcFlush;
|
||||||
FastIoDispatch->AcquireFileForNtCreateSection = Ext2AcquireForCreateSection;
|
FastIoDispatch->AcquireFileForNtCreateSection = Ext2AcquireForCreateSection;
|
||||||
FastIoDispatch->ReleaseFileForNtCreateSection = Ext2ReleaseForCreateSection;
|
FastIoDispatch->ReleaseFileForNtCreateSection = Ext2ReleaseForCreateSection;
|
||||||
|
|
||||||
DriverObject->FastIoDispatch = FastIoDispatch;
|
DriverObject->FastIoDispatch = FastIoDispatch;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -633,6 +696,19 @@ DriverEntry (
|
||||||
Ext2Global->CacheManagerNoOpCallbacks.AcquireForReadAhead = Ext2NoOpAcquire;
|
Ext2Global->CacheManagerNoOpCallbacks.AcquireForReadAhead = Ext2NoOpAcquire;
|
||||||
Ext2Global->CacheManagerNoOpCallbacks.ReleaseFromReadAhead = Ext2NoOpRelease;
|
Ext2Global->CacheManagerNoOpCallbacks.ReleaseFromReadAhead = Ext2NoOpRelease;
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _WIN2K_TARGET_
|
||||||
|
//
|
||||||
|
// Initialize FS Filter callbacks
|
||||||
|
//
|
||||||
|
|
||||||
|
RtlZeroMemory(&Ext2Global->FilterCallbacks, sizeof(FS_FILTER_CALLBACKS));
|
||||||
|
Ext2Global->FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);
|
||||||
|
Ext2Global->FilterCallbacks.PreAcquireForSectionSynchronization = Ext2PreAcquireForCreateSection;
|
||||||
|
FsRtlRegisterFileSystemFilterCallbacks(DriverObject, &Ext2Global->FilterCallbacks );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize the global data
|
// Initialize the global data
|
||||||
//
|
//
|
||||||
|
|
|
@ -329,10 +329,16 @@ new_buffer_head()
|
||||||
struct buffer_head * bh = NULL;
|
struct buffer_head * bh = NULL;
|
||||||
bh = kmem_cache_alloc(g_jbh.bh_cache, GFP_NOFS);
|
bh = kmem_cache_alloc(g_jbh.bh_cache, GFP_NOFS);
|
||||||
if (bh) {
|
if (bh) {
|
||||||
|
atomic_inc(&g_jbh.bh_count);
|
||||||
|
atomic_inc(&g_jbh.bh_acount);
|
||||||
|
|
||||||
memset(bh, 0, sizeof(struct buffer_head));
|
memset(bh, 0, sizeof(struct buffer_head));
|
||||||
|
InitializeListHead(&bh->b_link);
|
||||||
|
KeQuerySystemTime(&bh->b_ts_creat);
|
||||||
DEBUG(DL_BH, ("bh=%p allocated.\n", bh));
|
DEBUG(DL_BH, ("bh=%p allocated.\n", bh));
|
||||||
INC_MEM_COUNT(PS_BUFF_HEAD, bh, sizeof(struct buffer_head));
|
INC_MEM_COUNT(PS_BUFF_HEAD, bh, sizeof(struct buffer_head));
|
||||||
}
|
}
|
||||||
|
|
||||||
return bh;
|
return bh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,13 +350,9 @@ free_buffer_head(struct buffer_head * bh)
|
||||||
|
|
||||||
DEBUG(DL_BH, ("bh=%p mdl=%p (Flags:%xh VA:%p) released.\n", bh, bh->b_mdl,
|
DEBUG(DL_BH, ("bh=%p mdl=%p (Flags:%xh VA:%p) released.\n", bh, bh->b_mdl,
|
||||||
bh->b_mdl->MdlFlags, bh->b_mdl->MappedSystemVa));
|
bh->b_mdl->MdlFlags, bh->b_mdl->MappedSystemVa));
|
||||||
if (IsFlagOn(bh->b_mdl->MdlFlags, MDL_PAGES_LOCKED)) {
|
if (IsFlagOn(bh->b_mdl->MdlFlags, MDL_MAPPED_TO_SYSTEM_VA)) {
|
||||||
/* MmUnlockPages will release it's VA */
|
|
||||||
MmUnlockPages(bh->b_mdl);
|
|
||||||
} else if (IsFlagOn(bh->b_mdl->MdlFlags, MDL_MAPPED_TO_SYSTEM_VA)) {
|
|
||||||
MmUnmapLockedPages(bh->b_mdl->MappedSystemVa, bh->b_mdl);
|
MmUnmapLockedPages(bh->b_mdl->MappedSystemVa, bh->b_mdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ext2DestroyMdl(bh->b_mdl);
|
Ext2DestroyMdl(bh->b_mdl);
|
||||||
}
|
}
|
||||||
if (bh->b_bcb) {
|
if (bh->b_bcb) {
|
||||||
|
@ -360,6 +362,7 @@ free_buffer_head(struct buffer_head * bh)
|
||||||
DEBUG(DL_BH, ("bh=%p freed.\n", bh));
|
DEBUG(DL_BH, ("bh=%p freed.\n", bh));
|
||||||
DEC_MEM_COUNT(PS_BUFF_HEAD, bh, sizeof(struct buffer_head));
|
DEC_MEM_COUNT(PS_BUFF_HEAD, bh, sizeof(struct buffer_head));
|
||||||
kmem_cache_free(g_jbh.bh_cache, bh);
|
kmem_cache_free(g_jbh.bh_cache, bh);
|
||||||
|
atomic_dec(&g_jbh.bh_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,7 +439,6 @@ get_block_bh_mdl(
|
||||||
PVOID bcb = NULL;
|
PVOID bcb = NULL;
|
||||||
PVOID ptr = NULL;
|
PVOID ptr = NULL;
|
||||||
|
|
||||||
KIRQL irql = 0;
|
|
||||||
struct list_head *entry;
|
struct list_head *entry;
|
||||||
|
|
||||||
/* allocate buffer_head and initialize it */
|
/* allocate buffer_head and initialize it */
|
||||||
|
@ -449,15 +451,15 @@ get_block_bh_mdl(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* search the bdev bh list */
|
/* search the bdev bh list */
|
||||||
spin_lock_irqsave(&bdev->bd_bh_lock, irql);
|
ExAcquireSharedStarveExclusive(&bdev->bd_bh_lock, TRUE);
|
||||||
tbh = buffer_head_search(bdev, block);
|
tbh = buffer_head_search(bdev, block);
|
||||||
if (tbh) {
|
if (tbh) {
|
||||||
bh = tbh;
|
bh = tbh;
|
||||||
get_bh(bh);
|
get_bh(bh);
|
||||||
spin_unlock_irqrestore(&bdev->bd_bh_lock, irql);
|
ExReleaseResourceLite(&bdev->bd_bh_lock);
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&bdev->bd_bh_lock, irql);
|
ExReleaseResourceLite(&bdev->bd_bh_lock);
|
||||||
|
|
||||||
bh = new_buffer_head();
|
bh = new_buffer_head();
|
||||||
if (!bh) {
|
if (!bh) {
|
||||||
|
@ -467,8 +469,6 @@ get_block_bh_mdl(
|
||||||
bh->b_blocknr = block;
|
bh->b_blocknr = block;
|
||||||
bh->b_size = size;
|
bh->b_size = size;
|
||||||
bh->b_data = NULL;
|
bh->b_data = NULL;
|
||||||
atomic_inc(&g_jbh.bh_count);
|
|
||||||
atomic_inc(&g_jbh.bh_acount);
|
|
||||||
|
|
||||||
again:
|
again:
|
||||||
|
|
||||||
|
@ -499,13 +499,14 @@ again:
|
||||||
set_buffer_uptodate(bh);
|
set_buffer_uptodate(bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
bh->b_mdl = Ext2CreateMdl(ptr, TRUE, bh->b_size, IoModifyAccess);
|
bh->b_mdl = Ext2CreateMdl(ptr, bh->b_size, IoModifyAccess);
|
||||||
if (bh->b_mdl) {
|
if (bh->b_mdl) {
|
||||||
/* muse map the PTE to NonCached zone. journal recovery will
|
/* muse map the PTE to NonCached zone. journal recovery will
|
||||||
access the PTE under spinlock: DISPATCH_LEVEL IRQL */
|
access the PTE under spinlock: DISPATCH_LEVEL IRQL */
|
||||||
bh->b_data = MmMapLockedPagesSpecifyCache(
|
bh->b_data = MmMapLockedPagesSpecifyCache(
|
||||||
bh->b_mdl, KernelMode, MmNonCached,
|
bh->b_mdl, KernelMode, MmNonCached,
|
||||||
NULL,FALSE, HighPagePriority);
|
NULL,FALSE, HighPagePriority);
|
||||||
|
/* bh->b_data = MmMapLockedPages(bh->b_mdl, KernelMode); */
|
||||||
}
|
}
|
||||||
if (!bh->b_mdl || !bh->b_data) {
|
if (!bh->b_mdl || !bh->b_data) {
|
||||||
free_buffer_head(bh);
|
free_buffer_head(bh);
|
||||||
|
@ -518,20 +519,21 @@ again:
|
||||||
DEBUG(DL_BH, ("getblk: Vcb=%p bhcount=%u block=%u bh=%p mdl=%p (Flags:%xh VA:%p)\n",
|
DEBUG(DL_BH, ("getblk: Vcb=%p bhcount=%u block=%u bh=%p mdl=%p (Flags:%xh VA:%p)\n",
|
||||||
Vcb, atomic_read(&g_jbh.bh_count), block, bh, bh->b_mdl, bh->b_mdl->MdlFlags, bh->b_data));
|
Vcb, atomic_read(&g_jbh.bh_count), block, bh, bh->b_mdl, bh->b_mdl->MdlFlags, bh->b_data));
|
||||||
|
|
||||||
spin_lock_irqsave(&bdev->bd_bh_lock, irql);
|
ExAcquireResourceExclusiveLite(&bdev->bd_bh_lock, TRUE);
|
||||||
|
|
||||||
/* do search again here */
|
/* do search again here */
|
||||||
tbh = buffer_head_search(bdev, block);
|
tbh = buffer_head_search(bdev, block);
|
||||||
if (tbh) {
|
if (tbh) {
|
||||||
free_buffer_head(bh);
|
free_buffer_head(bh);
|
||||||
bh = tbh;
|
bh = tbh;
|
||||||
get_bh(bh);
|
get_bh(bh);
|
||||||
spin_unlock_irqrestore(&bdev->bd_bh_lock, irql);
|
RemoveEntryList(&bh->b_link);
|
||||||
|
InitializeListHead(&bh->b_link);
|
||||||
|
ExReleaseResourceLite(&bdev->bd_bh_lock);
|
||||||
goto errorout;
|
goto errorout;
|
||||||
} else
|
} else {
|
||||||
buffer_head_insert(bdev, bh);
|
buffer_head_insert(bdev, bh);
|
||||||
|
}
|
||||||
spin_unlock_irqrestore(&bdev->bd_bh_lock, irql);
|
ExReleaseResourceLite(&bdev->bd_bh_lock);
|
||||||
|
|
||||||
/* we get it */
|
/* we get it */
|
||||||
errorout:
|
errorout:
|
||||||
|
@ -602,7 +604,7 @@ errorout:
|
||||||
}
|
}
|
||||||
|
|
||||||
struct buffer_head *
|
struct buffer_head *
|
||||||
get_block_bh(
|
get_block_bh_pin(
|
||||||
struct block_device * bdev,
|
struct block_device * bdev,
|
||||||
sector_t block,
|
sector_t block,
|
||||||
unsigned long size,
|
unsigned long size,
|
||||||
|
@ -612,7 +614,6 @@ get_block_bh(
|
||||||
PEXT2_VCB Vcb = bdev->bd_priv;
|
PEXT2_VCB Vcb = bdev->bd_priv;
|
||||||
LARGE_INTEGER offset;
|
LARGE_INTEGER offset;
|
||||||
|
|
||||||
KIRQL irql = 0;
|
|
||||||
struct list_head *entry;
|
struct list_head *entry;
|
||||||
|
|
||||||
/* allocate buffer_head and initialize it */
|
/* allocate buffer_head and initialize it */
|
||||||
|
@ -625,15 +626,15 @@ get_block_bh(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* search the bdev bh list */
|
/* search the bdev bh list */
|
||||||
spin_lock_irqsave(&bdev->bd_bh_lock, irql);
|
ExAcquireSharedStarveExclusive(&bdev->bd_bh_lock, TRUE);
|
||||||
tbh = buffer_head_search(bdev, block);
|
tbh = buffer_head_search(bdev, block);
|
||||||
if (tbh) {
|
if (tbh) {
|
||||||
bh = tbh;
|
bh = tbh;
|
||||||
get_bh(bh);
|
get_bh(bh);
|
||||||
spin_unlock_irqrestore(&bdev->bd_bh_lock, irql);
|
ExReleaseResourceLite(&bdev->bd_bh_lock);
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&bdev->bd_bh_lock, irql);
|
ExReleaseResourceLite(&bdev->bd_bh_lock);
|
||||||
|
|
||||||
bh = new_buffer_head();
|
bh = new_buffer_head();
|
||||||
if (!bh) {
|
if (!bh) {
|
||||||
|
@ -643,8 +644,6 @@ get_block_bh(
|
||||||
bh->b_blocknr = block;
|
bh->b_blocknr = block;
|
||||||
bh->b_size = size;
|
bh->b_size = size;
|
||||||
bh->b_data = NULL;
|
bh->b_data = NULL;
|
||||||
atomic_inc(&g_jbh.bh_count);
|
|
||||||
atomic_inc(&g_jbh.bh_acount);
|
|
||||||
|
|
||||||
again:
|
again:
|
||||||
|
|
||||||
|
@ -656,7 +655,7 @@ again:
|
||||||
&offset,
|
&offset,
|
||||||
bh->b_size,
|
bh->b_size,
|
||||||
FALSE,
|
FALSE,
|
||||||
PIN_WAIT | PIN_EXCLUSIVE,
|
PIN_WAIT,
|
||||||
&bh->b_bcb,
|
&bh->b_bcb,
|
||||||
(PVOID *)&bh->b_data)) {
|
(PVOID *)&bh->b_data)) {
|
||||||
Ext2Sleep(100);
|
Ext2Sleep(100);
|
||||||
|
@ -675,33 +674,34 @@ again:
|
||||||
set_buffer_uptodate(bh);
|
set_buffer_uptodate(bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bh->b_bcb)
|
||||||
|
CcSetBcbOwnerPointer(bh->b_bcb, (PVOID)((ERESOURCE_THREAD)bh | 0x3));
|
||||||
|
|
||||||
if (!bh->b_data) {
|
if (!bh->b_data) {
|
||||||
free_buffer_head(bh);
|
free_buffer_head(bh);
|
||||||
bh = NULL;
|
bh = NULL;
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_bh(bh);
|
get_bh(bh);
|
||||||
CcSetBcbOwnerPointer(bh->b_bcb, (PVOID)((ERESOURCE_THREAD)bh | 0x3));
|
|
||||||
|
|
||||||
DEBUG(DL_BH, ("getblk: Vcb=%p bhcount=%u block=%u bh=%p ptr=%p.\n",
|
DEBUG(DL_BH, ("getblk: Vcb=%p bhcount=%u block=%u bh=%p ptr=%p.\n",
|
||||||
Vcb, atomic_read(&g_jbh.bh_count), block, bh, bh->b_data));
|
Vcb, atomic_read(&g_jbh.bh_count), block, bh, bh->b_data));
|
||||||
|
|
||||||
spin_lock_irqsave(&bdev->bd_bh_lock, irql);
|
ExAcquireResourceExclusiveLite(&bdev->bd_bh_lock, TRUE);
|
||||||
|
|
||||||
/* do search again here */
|
/* do search again here */
|
||||||
tbh = buffer_head_search(bdev, block);
|
tbh = buffer_head_search(bdev, block);
|
||||||
if (tbh) {
|
if (tbh) {
|
||||||
get_bh(tbh);
|
get_bh(tbh);
|
||||||
spin_unlock_irqrestore(&bdev->bd_bh_lock, irql);
|
ExReleaseResourceLite(&bdev->bd_bh_lock);
|
||||||
free_buffer_head(bh);
|
free_buffer_head(bh);
|
||||||
bh = tbh;
|
bh = tbh;
|
||||||
|
RemoveEntryList(&bh->b_link);
|
||||||
|
InitializeListHead(&bh->b_link);
|
||||||
goto errorout;
|
goto errorout;
|
||||||
} else {
|
} else {
|
||||||
buffer_head_insert(bdev, bh);
|
buffer_head_insert(bdev, bh);
|
||||||
}
|
}
|
||||||
|
ExReleaseResourceLite(&bdev->bd_bh_lock);
|
||||||
spin_unlock_irqrestore(&bdev->bd_bh_lock, irql);
|
|
||||||
|
|
||||||
/* we get it */
|
/* we get it */
|
||||||
errorout:
|
errorout:
|
||||||
|
@ -709,7 +709,7 @@ errorout:
|
||||||
return bh;
|
return bh;
|
||||||
}
|
}
|
||||||
|
|
||||||
int submit_bh(int rw, struct buffer_head *bh)
|
int submit_bh_pin(int rw, struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
struct block_device *bdev = bh->b_bdev;
|
struct block_device *bdev = bh->b_bdev;
|
||||||
PEXT2_VCB Vcb = bdev->bd_priv;
|
PEXT2_VCB Vcb = bdev->bd_priv;
|
||||||
|
@ -744,6 +744,43 @@ errorout:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
struct buffer_head *
|
||||||
|
get_block_bh(
|
||||||
|
struct block_device * bdev,
|
||||||
|
sector_t block,
|
||||||
|
unsigned long size,
|
||||||
|
int zero
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return get_block_bh_mdl(bdev, block, size, zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
int submit_bh(int rw, struct buffer_head *bh)
|
||||||
|
{
|
||||||
|
return submit_bh_mdl(rw, bh);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
struct buffer_head *
|
||||||
|
get_block_bh(
|
||||||
|
struct block_device * bdev,
|
||||||
|
sector_t block,
|
||||||
|
unsigned long size,
|
||||||
|
int zero
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return get_block_bh_pin(bdev, block, size, zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
int submit_bh(int rw, struct buffer_head *bh)
|
||||||
|
{
|
||||||
|
return submit_bh_pin(rw, bh);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct buffer_head *
|
struct buffer_head *
|
||||||
__getblk(
|
__getblk(
|
||||||
struct block_device * bdev,
|
struct block_device * bdev,
|
||||||
|
@ -758,7 +795,6 @@ void __brelse(struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
struct block_device *bdev = bh->b_bdev;
|
struct block_device *bdev = bh->b_bdev;
|
||||||
PEXT2_VCB Vcb = (PEXT2_VCB)bdev->bd_priv;
|
PEXT2_VCB Vcb = (PEXT2_VCB)bdev->bd_priv;
|
||||||
KIRQL irql = 0;
|
|
||||||
|
|
||||||
ASSERT(Vcb->Identifier.Type == EXT2VCB);
|
ASSERT(Vcb->Identifier.Type == EXT2VCB);
|
||||||
|
|
||||||
|
@ -767,20 +803,30 @@ void __brelse(struct buffer_head *bh)
|
||||||
ll_rw_block(WRITE, 1, &bh);
|
ll_rw_block(WRITE, 1, &bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&bdev->bd_bh_lock, irql);
|
if (1 == atomic_read(&bh->b_count)) {
|
||||||
if (!atomic_dec_and_test(&bh->b_count)) {
|
} else if (atomic_dec_and_test(&bh->b_count)) {
|
||||||
spin_unlock_irqrestore(&bdev->bd_bh_lock, irql);
|
atomic_inc(&bh->b_count);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExAcquireResourceExclusiveLite(&bdev->bd_bh_lock, TRUE);
|
||||||
|
if (atomic_dec_and_test(&bh->b_count)) {
|
||||||
|
ASSERT(0 == atomic_read(&bh->b_count));
|
||||||
|
} else {
|
||||||
|
ExReleaseResourceLite(&bdev->bd_bh_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
buffer_head_remove(bdev, bh);
|
buffer_head_remove(bdev, bh);
|
||||||
spin_unlock_irqrestore(&bdev->bd_bh_lock, irql);
|
KeQuerySystemTime(&bh->b_ts_drop);
|
||||||
|
InsertTailList(&Vcb->bd.bd_bh_free, &bh->b_link);
|
||||||
|
KeClearEvent(&Vcb->bd.bd_bh_notify);
|
||||||
|
ExReleaseResourceLite(&bdev->bd_bh_lock);
|
||||||
|
KeSetEvent(&Ext2Global->bhReaper.Wait, 0, FALSE);
|
||||||
|
|
||||||
DEBUG(DL_BH, ("brelse: cnt=%u size=%u blk=%10.10xh bh=%p ptr=%p\n",
|
DEBUG(DL_BH, ("brelse: cnt=%u size=%u blk=%10.10xh bh=%p ptr=%p\n",
|
||||||
atomic_read(&g_jbh.bh_count) - 1, bh->b_size,
|
atomic_read(&g_jbh.bh_count) - 1, bh->b_size,
|
||||||
bh->b_blocknr, bh, bh->b_data ));
|
bh->b_blocknr, bh, bh->b_data ));
|
||||||
|
|
||||||
free_buffer_head(bh);
|
|
||||||
atomic_dec(&g_jbh.bh_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -863,10 +909,7 @@ void mark_buffer_dirty(struct buffer_head *bh)
|
||||||
int sync_blockdev(struct block_device *bdev)
|
int sync_blockdev(struct block_device *bdev)
|
||||||
{
|
{
|
||||||
PEXT2_VCB Vcb = (PEXT2_VCB) bdev->bd_priv;
|
PEXT2_VCB Vcb = (PEXT2_VCB) bdev->bd_priv;
|
||||||
|
Ext2FlushVolume(NULL, Vcb, FALSE);
|
||||||
if (0 == atomic_read(&g_jbh.bh_count)) {
|
|
||||||
Ext2FlushVolume(NULL, Vcb, FALSE);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,8 @@ extern PEXT2_GLOBAL Ext2Global;
|
||||||
#pragma alloc_text(PAGE, Ext2DestroyVcb)
|
#pragma alloc_text(PAGE, Ext2DestroyVcb)
|
||||||
#pragma alloc_text(PAGE, Ext2SyncUninitializeCacheMap)
|
#pragma alloc_text(PAGE, Ext2SyncUninitializeCacheMap)
|
||||||
#pragma alloc_text(PAGE, Ext2ReaperThread)
|
#pragma alloc_text(PAGE, Ext2ReaperThread)
|
||||||
#pragma alloc_text(PAGE, Ext2StartReaperThread)
|
#pragma alloc_text(PAGE, Ext2StartReaper)
|
||||||
|
#pragma alloc_text(PAGE, Ext2StopReaper)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PEXT2_IRP_CONTEXT
|
PEXT2_IRP_CONTEXT
|
||||||
|
@ -1404,7 +1405,7 @@ Ext2AllocateMcb (
|
||||||
|
|
||||||
/* need wake the reaper thread if there are many Mcb allocated */
|
/* need wake the reaper thread if there are many Mcb allocated */
|
||||||
if (Ext2Global->PerfStat.Current.Mcb > (((ULONG)Ext2Global->MaxDepth) * 4)) {
|
if (Ext2Global->PerfStat.Current.Mcb > (((ULONG)Ext2Global->MaxDepth) * 4)) {
|
||||||
KeSetEvent(&Ext2Global->Reaper.Wait, 0, FALSE);
|
KeSetEvent(&Ext2Global->McbReaper.Wait, 0, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate Mcb from LookasideList */
|
/* allocate Mcb from LookasideList */
|
||||||
|
@ -1505,6 +1506,7 @@ Ext2FreeMcb (IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb)
|
||||||
#ifndef __REACTOS__
|
#ifndef __REACTOS__
|
||||||
PEXT2_MCB Parent = Mcb->Parent;
|
PEXT2_MCB Parent = Mcb->Parent;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ASSERT(Mcb != NULL);
|
ASSERT(Mcb != NULL);
|
||||||
|
|
||||||
ASSERT((Mcb->Identifier.Type == EXT2MCB) &&
|
ASSERT((Mcb->Identifier.Type == EXT2MCB) &&
|
||||||
|
@ -1839,6 +1841,7 @@ Ext2CheckSetBlock(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, LONGLONG Block)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RtlInitializeBitMap(&bitmap, (PULONG)bh->b_data, Length);
|
RtlInitializeBitMap(&bitmap, (PULONG)bh->b_data, Length);
|
||||||
|
|
||||||
if (RtlCheckBit(&bitmap, dwBlk) == 0) {
|
if (RtlCheckBit(&bitmap, dwBlk) == 0) {
|
||||||
|
@ -1982,7 +1985,7 @@ errorout:
|
||||||
VOID
|
VOID
|
||||||
Ext2ParseRegistryVolumeParams(
|
Ext2ParseRegistryVolumeParams(
|
||||||
IN PUNICODE_STRING Params,
|
IN PUNICODE_STRING Params,
|
||||||
OUT PEXT2_VOLUME_PROPERTY2 Property
|
OUT PEXT2_VOLUME_PROPERTY3 Property
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
WCHAR Codepage[CODEPAGE_MAXLEN];
|
WCHAR Codepage[CODEPAGE_MAXLEN];
|
||||||
|
@ -1990,11 +1993,15 @@ Ext2ParseRegistryVolumeParams(
|
||||||
WCHAR Suffix[HIDINGPAT_LEN];
|
WCHAR Suffix[HIDINGPAT_LEN];
|
||||||
USHORT MountPoint[4];
|
USHORT MountPoint[4];
|
||||||
UCHAR DrvLetter[4];
|
UCHAR DrvLetter[4];
|
||||||
|
WCHAR wUID[8], wGID[8], wEUID[8], wEGID[8];
|
||||||
|
CHAR sUID[8], sGID[8], sEUID[8], sEGID[8];
|
||||||
|
|
||||||
BOOLEAN bWriteSupport = FALSE,
|
BOOLEAN bWriteSupport = FALSE,
|
||||||
bCheckBitmap = FALSE,
|
bCheckBitmap = FALSE,
|
||||||
bCodeName = FALSE,
|
bCodeName = FALSE,
|
||||||
bMountPoint = FALSE;
|
bMountPoint = FALSE;
|
||||||
|
BOOLEAN bUID = 0, bGID = 0, bEUID = 0, bEGID = 0;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
PWCHAR Name; /* parameters name */
|
PWCHAR Name; /* parameters name */
|
||||||
PBOOLEAN bExist; /* is it contained in params */
|
PBOOLEAN bExist; /* is it contained in params */
|
||||||
|
@ -2020,6 +2027,11 @@ Ext2ParseRegistryVolumeParams(
|
||||||
{MOUNT_POINT, &bMountPoint, 4,
|
{MOUNT_POINT, &bMountPoint, 4,
|
||||||
&MountPoint[0], &DrvLetter[0]},
|
&MountPoint[0], &DrvLetter[0]},
|
||||||
|
|
||||||
|
{UID, &bUID, 8, &wUID[0], &sUID[0],},
|
||||||
|
{GID, &bGID, 8, &wGID[0], &sGID[0]},
|
||||||
|
{EUID, &bEUID, 8, &wEUID[0], &sEUID[0]},
|
||||||
|
{EGID, &bEGID, 8, &wEGID[0], &sEGID[0]},
|
||||||
|
|
||||||
/* end */
|
/* end */
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
@ -2032,9 +2044,9 @@ Ext2ParseRegistryVolumeParams(
|
||||||
RtlZeroMemory(MountPoint, sizeof(USHORT) * 4);
|
RtlZeroMemory(MountPoint, sizeof(USHORT) * 4);
|
||||||
RtlZeroMemory(DrvLetter, sizeof(CHAR) * 4);
|
RtlZeroMemory(DrvLetter, sizeof(CHAR) * 4);
|
||||||
|
|
||||||
RtlZeroMemory(Property, sizeof(EXT2_VOLUME_PROPERTY2));
|
RtlZeroMemory(Property, sizeof(EXT2_VOLUME_PROPERTY3));
|
||||||
Property->Magic = EXT2_VOLUME_PROPERTY_MAGIC;
|
Property->Magic = EXT2_VOLUME_PROPERTY_MAGIC;
|
||||||
Property->Command = APP_CMD_SET_PROPERTY2;
|
Property->Command = APP_CMD_SET_PROPERTY3;
|
||||||
|
|
||||||
for (i=0; ParamPattern[i].Name != NULL; i++) {
|
for (i=0; ParamPattern[i].Name != NULL; i++) {
|
||||||
|
|
||||||
|
@ -2095,6 +2107,22 @@ Ext2ParseRegistryVolumeParams(
|
||||||
Property->DrvLetter = DrvLetter[0];
|
Property->DrvLetter = DrvLetter[0];
|
||||||
Property->DrvLetter |= 0x80;
|
Property->DrvLetter |= 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bUID && bGID) {
|
||||||
|
SetFlag(Property->Flags2, EXT2_VPROP3_USERIDS);
|
||||||
|
sUID[7] = sGID[7] = sEUID[7] = sEGID[7] = 0;
|
||||||
|
Property->uid = (USHORT)atoi(sUID);
|
||||||
|
Property->gid = (USHORT)atoi(sGID);
|
||||||
|
if (bEUID) {
|
||||||
|
Property->euid = (USHORT)atoi(sEUID);
|
||||||
|
Property->egid = (USHORT)atoi(sEGID);
|
||||||
|
Property->EIDS = TRUE;
|
||||||
|
} else {
|
||||||
|
Property->EIDS = FALSE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ClearFlag(Property->Flags2, EXT2_VPROP3_USERIDS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -2107,7 +2135,7 @@ Ext2PerformRegistryVolumeParams(IN PEXT2_VCB Vcb)
|
||||||
if (NT_SUCCESS(Status)) {
|
if (NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
/* set Vcb settings from registery */
|
/* set Vcb settings from registery */
|
||||||
EXT2_VOLUME_PROPERTY2 Property;
|
EXT2_VOLUME_PROPERTY3 Property;
|
||||||
Ext2ParseRegistryVolumeParams(&VolumeParams, &Property);
|
Ext2ParseRegistryVolumeParams(&VolumeParams, &Property);
|
||||||
Ext2ProcessVolumeProperty(Vcb, &Property, sizeof(Property));
|
Ext2ProcessVolumeProperty(Vcb, &Property, sizeof(Property));
|
||||||
|
|
||||||
|
@ -2141,7 +2169,7 @@ Ext2PerformRegistryVolumeParams(IN PEXT2_VCB Vcb)
|
||||||
memcpy(Vcb->Codepage.AnsiName, Ext2Global->Codepage.AnsiName, CODEPAGE_MAXLEN);
|
memcpy(Vcb->Codepage.AnsiName, Ext2Global->Codepage.AnsiName, CODEPAGE_MAXLEN);
|
||||||
Vcb->Codepage.PageTable = Ext2Global->Codepage.PageTable;
|
Vcb->Codepage.PageTable = Ext2Global->Codepage.PageTable;
|
||||||
|
|
||||||
if ((Vcb->bHidingPrefix = Ext2Global->bHidingPrefix) != 0) {
|
if (Vcb->bHidingPrefix == Ext2Global->bHidingPrefix) {
|
||||||
RtlCopyMemory( Vcb->sHidingPrefix,
|
RtlCopyMemory( Vcb->sHidingPrefix,
|
||||||
Ext2Global->sHidingPrefix,
|
Ext2Global->sHidingPrefix,
|
||||||
HIDINGPAT_LEN);
|
HIDINGPAT_LEN);
|
||||||
|
@ -2150,7 +2178,7 @@ Ext2PerformRegistryVolumeParams(IN PEXT2_VCB Vcb)
|
||||||
HIDINGPAT_LEN);
|
HIDINGPAT_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Vcb->bHidingSuffix = Ext2Global->bHidingSuffix) != 0) {
|
if (Vcb->bHidingSuffix == Ext2Global->bHidingSuffix) {
|
||||||
RtlCopyMemory( Vcb->sHidingSuffix,
|
RtlCopyMemory( Vcb->sHidingSuffix,
|
||||||
Ext2Global->sHidingSuffix,
|
Ext2Global->sHidingSuffix,
|
||||||
HIDINGPAT_LEN);
|
HIDINGPAT_LEN);
|
||||||
|
@ -2247,6 +2275,7 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
BOOLEAN NotifySyncInitialized = FALSE;
|
BOOLEAN NotifySyncInitialized = FALSE;
|
||||||
BOOLEAN ExtentsInitialized = FALSE;
|
BOOLEAN ExtentsInitialized = FALSE;
|
||||||
BOOLEAN InodeLookasideInitialized = FALSE;
|
BOOLEAN InodeLookasideInitialized = FALSE;
|
||||||
|
BOOLEAN GroupLoaded = FALSE;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
|
@ -2293,8 +2322,10 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
/* initialize eresources */
|
/* initialize eresources */
|
||||||
ExInitializeResourceLite(&Vcb->MainResource);
|
ExInitializeResourceLite(&Vcb->MainResource);
|
||||||
ExInitializeResourceLite(&Vcb->PagingIoResource);
|
ExInitializeResourceLite(&Vcb->PagingIoResource);
|
||||||
ExInitializeResourceLite(&Vcb->MetaLock);
|
ExInitializeResourceLite(&Vcb->MetaInode);
|
||||||
|
ExInitializeResourceLite(&Vcb->MetaBlock);
|
||||||
ExInitializeResourceLite(&Vcb->McbLock);
|
ExInitializeResourceLite(&Vcb->McbLock);
|
||||||
|
ExInitializeResourceLite(&Vcb->sbi.s_gd_lock);
|
||||||
#ifndef _WIN2K_TARGET_
|
#ifndef _WIN2K_TARGET_
|
||||||
ExInitializeFastMutex(&Vcb->Mutex);
|
ExInitializeFastMutex(&Vcb->Mutex);
|
||||||
FsRtlSetupAdvancedHeader(&Vcb->Header, &Vcb->Mutex);
|
FsRtlSetupAdvancedHeader(&Vcb->Header, &Vcb->Mutex);
|
||||||
|
@ -2367,15 +2398,7 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
/* initialize UUID and serial number */
|
/* initialize UUID and serial number */
|
||||||
if (Ext2IsNullUuid(sb->s_uuid)) {
|
if (Ext2IsNullUuid(sb->s_uuid)) {
|
||||||
ExUuidCreate((UUID *)sb->s_uuid);
|
ExUuidCreate((UUID *)sb->s_uuid);
|
||||||
} else {
|
|
||||||
/* query parameters from registry */
|
|
||||||
if (!NT_SUCCESS(Ext2PerformRegistryVolumeParams(Vcb))) {
|
|
||||||
/* don't mount this volume */
|
|
||||||
Status = STATUS_UNRECOGNIZED_VOLUME;
|
|
||||||
_SEH2_LEAVE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vpb->SerialNumber = ((ULONG*)sb->s_uuid)[0] +
|
Vpb->SerialNumber = ((ULONG*)sb->s_uuid)[0] +
|
||||||
((ULONG*)sb->s_uuid)[1] +
|
((ULONG*)sb->s_uuid)[1] +
|
||||||
((ULONG*)sb->s_uuid)[2] +
|
((ULONG*)sb->s_uuid)[2] +
|
||||||
|
@ -2471,7 +2494,10 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
Vcb->bd.bd_volume = Vcb->Volume;
|
Vcb->bd.bd_volume = Vcb->Volume;
|
||||||
Vcb->bd.bd_priv = (void *) Vcb;
|
Vcb->bd.bd_priv = (void *) Vcb;
|
||||||
memset(&Vcb->bd.bd_bh_root, 0, sizeof(struct rb_root));
|
memset(&Vcb->bd.bd_bh_root, 0, sizeof(struct rb_root));
|
||||||
spin_lock_init(&Vcb->bd.bd_bh_lock);
|
InitializeListHead(&Vcb->bd.bd_bh_free);
|
||||||
|
ExInitializeResourceLite(&Vcb->bd.bd_bh_lock);
|
||||||
|
KeInitializeEvent(&Vcb->bd.bd_bh_notify,
|
||||||
|
NotificationEvent, TRUE);
|
||||||
Vcb->bd.bd_bh_cache = kmem_cache_create("bd_bh_buffer",
|
Vcb->bd.bd_bh_cache = kmem_cache_create("bd_bh_buffer",
|
||||||
Vcb->BlockSize, 0, 0, NULL);
|
Vcb->BlockSize, 0, 0, NULL);
|
||||||
if (!Vcb->bd.bd_bh_cache) {
|
if (!Vcb->bd.bd_bh_cache) {
|
||||||
|
@ -2600,6 +2626,7 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
Status = STATUS_UNSUCCESSFUL;
|
Status = STATUS_UNSUCCESSFUL;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
GroupLoaded = TRUE;
|
||||||
|
|
||||||
/* recovery journal since it's ext3 */
|
/* recovery journal since it's ext3 */
|
||||||
if (Vcb->IsExt3fs) {
|
if (Vcb->IsExt3fs) {
|
||||||
|
@ -2656,6 +2683,10 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
|
|
||||||
/* get anything doen, then refer target device */
|
/* get anything doen, then refer target device */
|
||||||
ObReferenceObject(Vcb->TargetDeviceObject);
|
ObReferenceObject(Vcb->TargetDeviceObject);
|
||||||
|
|
||||||
|
/* query parameters from registry */
|
||||||
|
Ext2PerformRegistryVolumeParams(Vcb);
|
||||||
|
|
||||||
SetLongFlag(Vcb->Flags, VCB_INITIALIZED);
|
SetLongFlag(Vcb->Flags, VCB_INITIALIZED);
|
||||||
|
|
||||||
} _SEH2_FINALLY {
|
} _SEH2_FINALLY {
|
||||||
|
@ -2671,9 +2702,11 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ExtentsInitialized) {
|
if (ExtentsInitialized) {
|
||||||
Ext2DropGroup(Vcb);
|
if (Vcb->bd.bd_bh_cache) {
|
||||||
if (Vcb->bd.bd_bh_cache)
|
if (GroupLoaded)
|
||||||
|
Ext2PutGroup(Vcb);
|
||||||
kmem_cache_destroy(Vcb->bd.bd_bh_cache);
|
kmem_cache_destroy(Vcb->bd.bd_bh_cache);
|
||||||
|
}
|
||||||
FsRtlUninitializeLargeMcb(&(Vcb->Extents));
|
FsRtlUninitializeLargeMcb(&(Vcb->Extents));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2690,7 +2723,9 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
|
|
||||||
if (VcbResourceInitialized) {
|
if (VcbResourceInitialized) {
|
||||||
ExDeleteResourceLite(&Vcb->McbLock);
|
ExDeleteResourceLite(&Vcb->McbLock);
|
||||||
ExDeleteResourceLite(&Vcb->MetaLock);
|
ExDeleteResourceLite(&Vcb->MetaInode);
|
||||||
|
ExDeleteResourceLite(&Vcb->MetaBlock);
|
||||||
|
ExDeleteResourceLite(&Vcb->sbi.s_gd_lock);
|
||||||
ExDeleteResourceLite(&Vcb->MainResource);
|
ExDeleteResourceLite(&Vcb->MainResource);
|
||||||
ExDeleteResourceLite(&Vcb->PagingIoResource);
|
ExDeleteResourceLite(&Vcb->PagingIoResource);
|
||||||
}
|
}
|
||||||
|
@ -2752,6 +2787,7 @@ Ext2DestroyVcb (IN PEXT2_VCB Vcb)
|
||||||
|
|
||||||
if (Vcb->bd.bd_bh_cache)
|
if (Vcb->bd.bd_bh_cache)
|
||||||
kmem_cache_destroy(Vcb->bd.bd_bh_cache);
|
kmem_cache_destroy(Vcb->bd.bd_bh_cache);
|
||||||
|
ExDeleteResourceLite(&Vcb->bd.bd_bh_lock);
|
||||||
|
|
||||||
if (Vcb->SuperBlock) {
|
if (Vcb->SuperBlock) {
|
||||||
Ext2FreePool(Vcb->SuperBlock, EXT2_SB_MAGIC);
|
Ext2FreePool(Vcb->SuperBlock, EXT2_SB_MAGIC);
|
||||||
|
@ -2770,7 +2806,9 @@ Ext2DestroyVcb (IN PEXT2_VCB Vcb)
|
||||||
|
|
||||||
ExDeleteNPagedLookasideList(&(Vcb->InodeLookasideList));
|
ExDeleteNPagedLookasideList(&(Vcb->InodeLookasideList));
|
||||||
ExDeleteResourceLite(&Vcb->McbLock);
|
ExDeleteResourceLite(&Vcb->McbLock);
|
||||||
ExDeleteResourceLite(&Vcb->MetaLock);
|
ExDeleteResourceLite(&Vcb->MetaInode);
|
||||||
|
ExDeleteResourceLite(&Vcb->MetaBlock);
|
||||||
|
ExDeleteResourceLite(&Vcb->sbi.s_gd_lock);
|
||||||
ExDeleteResourceLite(&Vcb->PagingIoResource);
|
ExDeleteResourceLite(&Vcb->PagingIoResource);
|
||||||
ExDeleteResourceLite(&Vcb->MainResource);
|
ExDeleteResourceLite(&Vcb->MainResource);
|
||||||
|
|
||||||
|
@ -2935,16 +2973,11 @@ Ext2FirstUnusedMcb(PEXT2_VCB Vcb, BOOLEAN Wait, ULONG Number)
|
||||||
|
|
||||||
/* Reaper thread to release unused Mcb blocks */
|
/* Reaper thread to release unused Mcb blocks */
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
Ext2ReaperThread(
|
Ext2McbReaperThread(
|
||||||
PVOID Context
|
PVOID Context
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
BOOLEAN GlobalAcquired = FALSE;
|
PEXT2_REAPER Reaper = Context;
|
||||||
|
|
||||||
BOOLEAN DidNothing = TRUE;
|
|
||||||
BOOLEAN LastState = TRUE;
|
|
||||||
BOOLEAN WaitLock;
|
|
||||||
|
|
||||||
PLIST_ENTRY List = NULL;
|
PLIST_ENTRY List = NULL;
|
||||||
LARGE_INTEGER Timeout;
|
LARGE_INTEGER Timeout;
|
||||||
|
|
||||||
|
@ -2953,13 +2986,19 @@ Ext2ReaperThread(
|
||||||
|
|
||||||
ULONG i, NumOfMcbs;
|
ULONG i, NumOfMcbs;
|
||||||
|
|
||||||
|
BOOLEAN GlobalAcquired = FALSE;
|
||||||
|
|
||||||
|
BOOLEAN DidNothing = TRUE;
|
||||||
|
BOOLEAN LastState = TRUE;
|
||||||
|
BOOLEAN WaitLock;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
/* wake up DirverEntry */
|
/* wake up DirverEntry */
|
||||||
KeSetEvent(&Ext2Global->Reaper.Engine, 0, FALSE);
|
KeSetEvent(&Reaper->Engine, 0, FALSE);
|
||||||
|
|
||||||
/* now process looping */
|
/* now process looping */
|
||||||
while (TRUE) {
|
while (!IsFlagOn(Reaper->Flags, EXT2_REAPER_FLAG_STOP)) {
|
||||||
|
|
||||||
WaitLock = FALSE;
|
WaitLock = FALSE;
|
||||||
|
|
||||||
|
@ -3002,13 +3041,16 @@ Ext2ReaperThread(
|
||||||
|
|
||||||
/* wait until it is waken or it times out */
|
/* wait until it is waken or it times out */
|
||||||
KeWaitForSingleObject(
|
KeWaitForSingleObject(
|
||||||
&(Ext2Global->Reaper.Wait),
|
&Reaper->Wait,
|
||||||
Executive,
|
Executive,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
&Timeout
|
&Timeout
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (IsFlagOn(Reaper->Flags, EXT2_REAPER_FLAG_STOP))
|
||||||
|
break;
|
||||||
|
|
||||||
DidNothing = TRUE;
|
DidNothing = TRUE;
|
||||||
|
|
||||||
/* acquire global exclusive lock */
|
/* acquire global exclusive lock */
|
||||||
|
@ -3047,22 +3089,157 @@ Ext2ReaperThread(
|
||||||
if (GlobalAcquired) {
|
if (GlobalAcquired) {
|
||||||
ExReleaseResourceLite(&Ext2Global->Resource);
|
ExReleaseResourceLite(&Ext2Global->Resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeSetEvent(&Reaper->Engine, 0, FALSE);
|
||||||
} _SEH2_END;
|
} _SEH2_END;
|
||||||
|
|
||||||
PsTerminateSystemThread(STATUS_SUCCESS);
|
PsTerminateSystemThread(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* get the first Mcb record in Vcb->McbList */
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
Ext2QueryUnusedBH(PEXT2_VCB Vcb, PLIST_ENTRY head)
|
||||||
|
{
|
||||||
|
struct buffer_head *bh = NULL;
|
||||||
|
PLIST_ENTRY list = NULL;
|
||||||
|
LARGE_INTEGER now;
|
||||||
|
BOOLEAN wake = FALSE;
|
||||||
|
|
||||||
|
KeQuerySystemTime(&now);
|
||||||
|
|
||||||
|
ExAcquireResourceExclusiveLite(&Vcb->bd.bd_bh_lock, TRUE);
|
||||||
|
while (!IsListEmpty(&Vcb->bd.bd_bh_free)) {
|
||||||
|
list = RemoveHeadList(&Vcb->bd.bd_bh_free);
|
||||||
|
bh = CONTAINING_RECORD(list, struct buffer_head, b_link);
|
||||||
|
if (atomic_read(&bh->b_count)) {
|
||||||
|
InitializeListHead(&bh->b_link);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( IsFlagOn(Vcb->Flags, VCB_BEING_DROPPED) ||
|
||||||
|
(bh->b_ts_drop.QuadPart + (LONGLONG)10*1000*1000*15) > now.QuadPart ||
|
||||||
|
(bh->b_ts_creat.QuadPart + (LONGLONG)10*1000*1000*180) > now.QuadPart) {
|
||||||
|
InsertTailList(head, &bh->b_link);
|
||||||
|
} else {
|
||||||
|
InsertHeadList(&Vcb->bd.bd_bh_free, &bh->b_link);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wake = IsListEmpty(&Vcb->bd.bd_bh_free);
|
||||||
|
ExReleaseResourceLite(&Vcb->bd.bd_bh_lock);
|
||||||
|
|
||||||
|
if (wake)
|
||||||
|
KeSetEvent(&Vcb->bd.bd_bh_notify, 0, FALSE);
|
||||||
|
|
||||||
|
return IsFlagOn(Vcb->Flags, VCB_BEING_DROPPED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Reaper thread to release unused buffer heads */
|
||||||
|
VOID NTAPI
|
||||||
|
Ext2bhReaperThread(
|
||||||
|
PVOID Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PEXT2_REAPER Reaper = Context;
|
||||||
|
PEXT2_VCB Vcb = NULL;
|
||||||
|
LIST_ENTRY List, *Link;
|
||||||
|
LARGE_INTEGER Timeout;
|
||||||
|
|
||||||
|
BOOLEAN GlobalAcquired = FALSE;
|
||||||
|
BOOLEAN DidNothing = FALSE;
|
||||||
|
BOOLEAN NonWait = FALSE;
|
||||||
|
|
||||||
|
_SEH2_TRY {
|
||||||
|
|
||||||
|
/* wake up DirverEntry */
|
||||||
|
KeSetEvent(&Reaper->Engine, 0, FALSE);
|
||||||
|
|
||||||
|
/* now process looping */
|
||||||
|
while (!IsFlagOn(Reaper->Flags, EXT2_REAPER_FLAG_STOP)) {
|
||||||
|
|
||||||
|
/* wait until it is waken or it times out */
|
||||||
|
if (NonWait) {
|
||||||
|
Timeout.QuadPart = (LONGLONG)-10*1000*10;
|
||||||
|
NonWait = FALSE;
|
||||||
|
} else if (DidNothing) {
|
||||||
|
Timeout.QuadPart = Timeout.QuadPart * 2;
|
||||||
|
} else {
|
||||||
|
Timeout.QuadPart = (LONGLONG)-10*1000*1000*10; /* 10 seconds */
|
||||||
|
}
|
||||||
|
KeWaitForSingleObject(
|
||||||
|
&Reaper->Wait,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
&Timeout
|
||||||
|
);
|
||||||
|
|
||||||
|
if (IsFlagOn(Reaper->Flags, EXT2_REAPER_FLAG_STOP))
|
||||||
|
break;
|
||||||
|
|
||||||
|
InitializeListHead(&List);
|
||||||
|
|
||||||
|
/* acquire global exclusive lock */
|
||||||
|
ExAcquireResourceSharedLite(&Ext2Global->Resource, TRUE);
|
||||||
|
GlobalAcquired = TRUE;
|
||||||
|
/* search all Vcb to get unused resources freed to system */
|
||||||
|
for (Link = Ext2Global->VcbList.Flink;
|
||||||
|
Link != &(Ext2Global->VcbList);
|
||||||
|
Link = Link->Flink ) {
|
||||||
|
|
||||||
|
Vcb = CONTAINING_RECORD(Link, EXT2_VCB, Next);
|
||||||
|
if (Ext2QueryUnusedBH(Vcb, &List))
|
||||||
|
NonWait = TRUE;
|
||||||
|
}
|
||||||
|
if (GlobalAcquired) {
|
||||||
|
ExReleaseResourceLite(&Ext2Global->Resource);
|
||||||
|
GlobalAcquired = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DidNothing = IsListEmpty(&List);
|
||||||
|
while (!IsListEmpty(&List)) {
|
||||||
|
struct buffer_head *bh;
|
||||||
|
Link = RemoveHeadList(&List);
|
||||||
|
bh = CONTAINING_RECORD(Link, struct buffer_head, b_link);
|
||||||
|
ASSERT(0 == atomic_read(&bh->b_count));
|
||||||
|
free_buffer_head(bh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} _SEH2_FINALLY {
|
||||||
|
|
||||||
|
if (GlobalAcquired) {
|
||||||
|
ExReleaseResourceLite(&Ext2Global->Resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeSetEvent(&Reaper->Engine, 0, FALSE);
|
||||||
|
} _SEH2_END;
|
||||||
|
|
||||||
|
PsTerminateSystemThread(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2StartReaperThread()
|
Ext2StartReaper(PEXT2_REAPER Reaper, EXT2_REAPER_RELEASE Free)
|
||||||
{
|
{
|
||||||
NTSTATUS status = STATUS_SUCCESS;
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
OBJECT_ATTRIBUTES oa;
|
OBJECT_ATTRIBUTES oa;
|
||||||
HANDLE handle = 0;
|
HANDLE handle = 0;
|
||||||
|
LARGE_INTEGER timeout;
|
||||||
|
|
||||||
|
Reaper->Free = Free;
|
||||||
|
|
||||||
/* initialize wait event */
|
/* initialize wait event */
|
||||||
KeInitializeEvent(
|
KeInitializeEvent(
|
||||||
&Ext2Global->Reaper.Wait,
|
&Reaper->Wait,
|
||||||
|
SynchronizationEvent, FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Reaper thread engine event */
|
||||||
|
KeInitializeEvent(
|
||||||
|
&Reaper->Engine,
|
||||||
SynchronizationEvent, FALSE
|
SynchronizationEvent, FALSE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -3083,13 +3260,45 @@ Ext2StartReaperThread()
|
||||||
&oa,
|
&oa,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
Ext2ReaperThread,
|
Free,
|
||||||
NULL
|
(PVOID)Reaper
|
||||||
);
|
);
|
||||||
|
|
||||||
if (NT_SUCCESS(status)) {
|
if (NT_SUCCESS(status)) {
|
||||||
ZwClose(handle);
|
ZwClose(handle);
|
||||||
|
|
||||||
|
/* make sure Reaperthread is started */
|
||||||
|
timeout.QuadPart = (LONGLONG)-10*1000*1000*2; /* 2 seconds */
|
||||||
|
status = KeWaitForSingleObject(
|
||||||
|
&Reaper->Engine,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
&timeout
|
||||||
|
);
|
||||||
|
if (status != STATUS_SUCCESS) {
|
||||||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
Ext2StopReaper(PEXT2_REAPER Reaper)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER timeout;
|
||||||
|
|
||||||
|
Reaper->Flags |= EXT2_REAPER_FLAG_STOP;
|
||||||
|
KeSetEvent(&Reaper->Wait, 0, FALSE);
|
||||||
|
|
||||||
|
/* make sure Reaperthread is started */
|
||||||
|
timeout.QuadPart = (LONGLONG)-10*1000*1000*2; /* 2 seconds */
|
||||||
|
KeWaitForSingleObject(
|
||||||
|
&Reaper->Engine,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
&timeout);
|
||||||
|
}
|
||||||
|
|
|
@ -582,7 +582,7 @@ Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (Nocache) {
|
if (Nocache && Ccb != NULL && Fcb->SectionObject.DataSectionObject) {
|
||||||
|
|
||||||
if (!ExAcquireResourceExclusiveLite(
|
if (!ExAcquireResourceExclusiveLite(
|
||||||
&Fcb->MainResource,
|
&Fcb->MainResource,
|
||||||
|
@ -592,14 +592,23 @@ Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
}
|
}
|
||||||
MainResourceAcquired = TRUE;
|
MainResourceAcquired = TRUE;
|
||||||
|
|
||||||
if (FileObject->SectionObjectPointer->DataSectionObject != NULL) {
|
CcFlushCache(&Fcb->SectionObject,
|
||||||
CcFlushCache( FileObject->SectionObjectPointer,
|
&ByteOffset,
|
||||||
&ByteOffset,
|
Length,
|
||||||
Length,
|
&Irp->IoStatus );
|
||||||
&Irp->IoStatus );
|
if (!NT_SUCCESS(Irp->IoStatus.Status))
|
||||||
if (!NT_SUCCESS(Irp->IoStatus.Status))
|
_SEH2_LEAVE;
|
||||||
_SEH2_LEAVE;
|
ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
|
||||||
|
|
||||||
|
if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
|
||||||
|
ExReleaseResourceLite(&(Fcb->PagingIoResource));
|
||||||
}
|
}
|
||||||
|
CcPurgeCacheSection( &Fcb->SectionObject,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
FALSE );
|
||||||
|
|
||||||
|
ExConvertExclusiveToShared(&Fcb->MainResource);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
|
@ -936,6 +936,11 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
if (!Ext2CheckFileAccess(Vcb, Fcb->Mcb, Ext2FileCanWrite)) {
|
||||||
|
Status = STATUS_ACCESS_DENIED;
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
|
||||||
if (IsDirectory(Fcb)) {
|
if (IsDirectory(Fcb)) {
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue