From a15c1b7b674008b2f3ef4cdb6514edcee9956764 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Sun, 20 Mar 2016 18:36:38 +0000 Subject: [PATCH] [EXT2] Update the driver to release 0.63. One notable change is support for ExtX links (hard/sym). They work out of the box due to all the previous work that was done for supporting reparse points on NTFS. Full changelog available at: http://www.ext2fsd.com/?p=195 CORE-10996 #resolve #comment Commited in r71031 svn path=/trunk/; revision=71031 --- .../drivers/filesystems/ext2/CMakeLists.txt | 1 + reactos/drivers/filesystems/ext2/inc/ext2fs.h | 107 ++- .../filesystems/ext2/inc/linux/ext3_fs_sb.h | 2 +- .../filesystems/ext2/inc/linux/ext4_ext.h | 2 +- .../drivers/filesystems/ext2/inc/linux/fs.h | 25 +- .../drivers/filesystems/ext2/inc/linux/jbd.h | 38 +- .../filesystems/ext2/inc/linux/module.h | 14 +- .../filesystems/ext2/inc/linux/rbtree.h | 2 - reactos/drivers/filesystems/ext2/src/access.c | 54 ++ .../drivers/filesystems/ext2/src/cleanup.c | 45 +- reactos/drivers/filesystems/ext2/src/close.c | 12 +- reactos/drivers/filesystems/ext2/src/create.c | 92 ++- reactos/drivers/filesystems/ext2/src/debug.c | 2 + reactos/drivers/filesystems/ext2/src/dirctl.c | 56 +- .../filesystems/ext2/src/ext3/generic.c | 439 +++++++----- .../drivers/filesystems/ext2/src/ext3/htree.c | 16 +- .../filesystems/ext2/src/ext3/recover.c | 2 +- .../filesystems/ext2/src/ext4/ext4_bh.c | 14 + .../filesystems/ext2/src/ext4/ext4_extents.c | 27 +- .../filesystems/ext2/src/ext4/extents.c | 17 +- reactos/drivers/filesystems/ext2/src/fastio.c | 73 +- .../drivers/filesystems/ext2/src/fileinfo.c | 307 ++++++++- reactos/drivers/filesystems/ext2/src/flush.c | 49 +- reactos/drivers/filesystems/ext2/src/fsctl.c | 649 +++++++++++++++++- reactos/drivers/filesystems/ext2/src/init.c | 6 +- .../drivers/filesystems/ext2/src/jbd/replay.c | 64 +- .../drivers/filesystems/ext2/src/jbd/revoke.c | 16 +- reactos/drivers/filesystems/ext2/src/linux.c | 172 ++++- reactos/drivers/filesystems/ext2/src/lock.c | 8 +- reactos/drivers/filesystems/ext2/src/memory.c | 103 ++- reactos/drivers/filesystems/ext2/src/misc.c | 9 +- reactos/drivers/filesystems/ext2/src/pnp.c | 4 +- reactos/drivers/filesystems/ext2/src/read.c | 65 +- .../drivers/filesystems/ext2/src/volinfo.c | 19 +- reactos/drivers/filesystems/ext2/src/write.c | 112 +-- 35 files changed, 2049 insertions(+), 574 deletions(-) create mode 100644 reactos/drivers/filesystems/ext2/src/access.c diff --git a/reactos/drivers/filesystems/ext2/CMakeLists.txt b/reactos/drivers/filesystems/ext2/CMakeLists.txt index ec64b1aa4bf..63bf2defa09 100644 --- a/reactos/drivers/filesystems/ext2/CMakeLists.txt +++ b/reactos/drivers/filesystems/ext2/CMakeLists.txt @@ -56,6 +56,7 @@ list(APPEND SOURCE src/nls/nls_koi8-ru.c src/nls/nls_koi8-u.c src/nls/nls_utf8.c + src/access.c src/block.c src/cleanup.c src/close.c diff --git a/reactos/drivers/filesystems/ext2/inc/ext2fs.h b/reactos/drivers/filesystems/ext2/inc/ext2fs.h index c695df22a56..eb806f3368c 100644 --- a/reactos/drivers/filesystems/ext2/inc/ext2fs.h +++ b/reactos/drivers/filesystems/ext2/inc/ext2fs.h @@ -4,7 +4,7 @@ * FILE: Ext2fs.h * PURPOSE: Header file: ext2 structures * PROGRAMMER: Matt Wu - * HOMEPAGE: http://ext2.yeah.net + * HOMEPAGE: http://www.ext2fsd.com * UPDATE HISTORY: */ @@ -18,7 +18,8 @@ #include #include #endif -#include "stdio.h" +#include +#include #include #include #include @@ -46,9 +47,14 @@ /* STRUCTS & CONSTS******************************************************/ -#define EXT2FSD_VERSION "0.62" +#define EXT2FSD_VERSION "0.63" +/* WDK DEFINITIONS ******************************************************/ + + +/* COMPILER SWITCH / OPTIONS ********************************************/ + // // Ext2Fsd build options // @@ -378,10 +384,25 @@ Ext2ClearFlag(PULONG Flags, ULONG FlagBit) #define Ext2SetOwnerReadOnly(m) do {(m) &= ~S_IWUSR;} while(0) #define Ext2IsOwnerWritable(m) (((m) & S_IWUSR) == S_IWUSR) -#define Ext2IsOwnerReadOnly(m) (!(Ext2IsOwnerWritable(m))) +#define Ext2IsOwnerReadable(m) (((m) & S_IRUSR) == S_IRUSR) +#define Ext2IsOwnerReadOnly(m) (!(Ext2IsOwnerWritable(m)) && Ext2IsOwnerReadable(m)) + +#define Ext2IsGroupWritable(m) (((m) & S_IWGRP) == S_IWGRP) +#define Ext2IsGroupReadable(m) (((m) & S_IRGRP) == S_IRGRP) +#define Ext2IsGroupReadOnly(m) (!(Ext2IsGroupWritable(m)) && Ext2IsGroupReadable(m)) + +#define Ext2IsOtherWritable(m) (((m) & S_IWOTH) == S_IWOTH) +#define Ext2IsOtherReadable(m) (((m) & S_IROTH) == S_IROTH) +#define Ext2IsOtherReadOnly(m) (!(Ext2IsOtherWritable(m)) && Ext2IsOtherReadable(m)) #define Ext2SetReadOnly(m) do {(m) &= ~(S_IWUSR | S_IWGRP | S_IWOTH);} while(0) + +#define Ext2FileCanRead (0x1) +#define Ext2FileCanWrite (0x2) +#define Ext2FileCanExecute (0x4) + + /* * We need 8-bytes aligned for all the sturctures * It's a must for all ERESOURCE allocations @@ -690,6 +711,14 @@ typedef struct _EXT2_VCB { BOOLEAN bHidingSuffix; CHAR sHidingSuffix[HIDINGPAT_LEN]; + /* User to impersanate */ + uid_t uid; + gid_t gid; + + /* User to act as */ + uid_t euid; + gid_t egid; + /* mountpoint: symlink to DesDevices */ UCHAR DrvLetter; @@ -713,6 +742,8 @@ typedef struct _EXT2_VCB { #define VCB_DISMOUNT_PENDING 0x00000008 #define VCB_NEW_VPB 0x00000010 #define VCB_BEING_CLOSED 0x00000020 +#define VCB_USER_IDS 0x00000040 /* uid/gid specified by user */ +#define VCB_USER_EIDS 0x00000080 /* euid/egid specified by user */ #define VCB_FORCE_WRITING 0x00004000 #define VCB_DEVICE_REMOVED 0x00008000 @@ -816,7 +847,7 @@ struct _EXT2_MCB { // Link List Info PEXT2_MCB Parent; // Parent - PEXT2_MCB Next; // Brothers + PEXT2_MCB Next; // Siblings union { PEXT2_MCB Child; // Children Mcb nodes @@ -943,7 +974,7 @@ typedef struct _EXT2_CCB { #define CCB_FROM_POOL 0x00000001 #define CCB_VOLUME_DASD_PURGE 0x00000002 #define CCB_LAST_WRITE_UPDATED 0x00000004 - +#define CCB_OPEN_REPARSE_POINT 0x00000008 #define CCB_DELETE_ON_CLOSE 0x00000010 #define CCB_ALLOW_EXTENDED_DASD_IO 0x80000000 @@ -1102,6 +1133,14 @@ typedef struct _EXT2_FILLDIR_CONTEXT { BOOLEAN efc_single; } EXT2_FILLDIR_CONTEXT, *PEXT2_FILLDIR_CONTEXT; +// +// Access.c +// + + +int Ext2CheckInodeAccess(PEXT2_VCB Vcb, struct inode *in, int attempt); +int Ext2CheckFileAccess (PEXT2_VCB Vcb, PEXT2_MCB Mcb, int attempt); + // // Block.c // @@ -1268,7 +1307,7 @@ Ext2FollowLink ( IN PEXT2_VCB Vcb, IN PEXT2_MCB Parent, IN PEXT2_MCB Mcb, - IN USHORT Linkdep + IN ULONG Linkdep ); NTSTATUS @@ -1287,6 +1326,9 @@ Ext2IsSpecialSystemFile( IN BOOLEAN bDirectory ); +#define EXT2_LOOKUP_FLAG_MASK (0xFF00000) +#define EXT2_LOOKUP_NOT_FOLLOW (0x8000000) + NTSTATUS Ext2LookupFile ( IN PEXT2_IRP_CONTEXT IrpContext, @@ -1294,7 +1336,7 @@ Ext2LookupFile ( IN PUNICODE_STRING FullName, IN PEXT2_MCB Parent, OUT PEXT2_MCB * Ext2Mcb, - IN USHORT Linkdep + IN ULONG Linkdep ); NTSTATUS @@ -1733,6 +1775,9 @@ Ext2LoadGroup(IN PEXT2_VCB Vcb); VOID Ext2PutGroup(IN PEXT2_VCB Vcb); +VOID +Ext2DropGroup(IN PEXT2_VCB Vcb); + BOOLEAN Ext2SaveGroup( IN PEXT2_IRP_CONTEXT IrpContext, @@ -1884,6 +1929,14 @@ Ext2AddEntry ( OUT struct dentry **dentry ); +NTSTATUS +Ext2SetFileType ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_FCB Dcb, + IN PEXT2_MCB Mcb +); + NTSTATUS Ext2RemoveEntry ( IN PEXT2_IRP_CONTEXT IrpContext, @@ -2116,6 +2169,14 @@ Ext2SetRenameInfo( PEXT2_CCB Ccb ); +NTSTATUS +Ext2SetLinkInfo( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_FCB Fcb, + PEXT2_CCB Ccb +); + ULONG Ext2InodeType(PEXT2_MCB Mcb); @@ -2161,6 +2222,34 @@ Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext); // Fsctl.c // +NTSTATUS +Ext2ReadSymlink ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN PVOID Buffer, + IN ULONG Size, + OUT PULONG BytesRead + ); + +NTSTATUS +Ext2WriteSymlink ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN PVOID Buffer, + IN ULONG Size, + OUT PULONG BytesWritten +); + +NTSTATUS +Ext2TruncateSymlink( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb, + ULONG Size +); + // // MountPoint process workitem // @@ -2400,7 +2489,7 @@ VOID Ext2RemoveFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb); PEXT2_CCB -Ext2AllocateCcb (PEXT2_MCB SymLink); +Ext2AllocateCcb (ULONG Flags, PEXT2_MCB SymLink); VOID Ext2FreeMcb ( diff --git a/reactos/drivers/filesystems/ext2/inc/linux/ext3_fs_sb.h b/reactos/drivers/filesystems/ext2/inc/linux/ext3_fs_sb.h index 201607ecd39..8aaeace04b3 100644 --- a/reactos/drivers/filesystems/ext2/inc/linux/ext3_fs_sb.h +++ b/reactos/drivers/filesystems/ext2/inc/linux/ext3_fs_sb.h @@ -36,7 +36,7 @@ struct ext3_sb_info { int s_addr_per_block_bits; int s_desc_per_block_bits; - struct buffer_head **s_group_desc; + ext3_fsblk_t *s_group_desc; #if 0 unsigned long s_frag_size; /* Size of a fragment in bytes */ diff --git a/reactos/drivers/filesystems/ext2/inc/linux/ext4_ext.h b/reactos/drivers/filesystems/ext2/inc/linux/ext4_ext.h index a4f063805a1..fedf4914142 100644 --- a/reactos/drivers/filesystems/ext2/inc/linux/ext4_ext.h +++ b/reactos/drivers/filesystems/ext2/inc/linux/ext4_ext.h @@ -252,6 +252,6 @@ int ext4_ext_get_blocks(void *icb, handle_t *handle, struct inode *inode, ext4_f unsigned long max_blocks, struct buffer_head *bh_result, int create, int flags); int ext4_ext_tree_init(void *icb, handle_t *handle, struct inode *inode); -int ext4_ext_remove_space(void *icb, struct inode *inode, unsigned long start); +int ext4_ext_truncate(void *icb, struct inode *inode, unsigned long start); #endif /* _LINUX_EXT4_EXT */ diff --git a/reactos/drivers/filesystems/ext2/inc/linux/fs.h b/reactos/drivers/filesystems/ext2/inc/linux/fs.h index 69aecbd4735..52a8b3dc904 100644 --- a/reactos/drivers/filesystems/ext2/inc/linux/fs.h +++ b/reactos/drivers/filesystems/ext2/inc/linux/fs.h @@ -3,6 +3,7 @@ #include #include +#include // // kdev @@ -74,6 +75,25 @@ struct super_block { void *s_fs_info; }; +struct xattr_entry { + char xe_name_index; + char *xe_name; + char xe_name_len; + char *xe_value; + int xe_value_size; + int xe_value_buf_size; + struct rb_node xe_node; +}; + +#define XATTR_FLAG_DIRTY 0x1 +#define XATTR_FLAG_LOADED 0x2 + +struct xattr_handle { + int xh_flags; + int xh_total_size; + struct rb_root xh_root; +}; + struct inode { __u32 i_ino; /* inode number */ loff_t i_size; /* size */ @@ -94,6 +114,9 @@ struct inode { struct super_block *i_sb; /* super_block */ void *i_priv; /* EXT2_MCB */ + + __u16 i_extra_isize; /* extra fields' size */ + __u64 i_file_acl; }; // @@ -153,4 +176,4 @@ void iget(struct inode *inode); void iput(struct inode *inode); ULONGLONG bmap(struct inode *i, ULONGLONG b); -#endif /*_LINUX_FS_INCLUDE_*/ \ No newline at end of file +#endif /*_LINUX_FS_INCLUDE_*/ diff --git a/reactos/drivers/filesystems/ext2/inc/linux/jbd.h b/reactos/drivers/filesystems/ext2/inc/linux/jbd.h index 60badad7252..f61263bd288 100644 --- a/reactos/drivers/filesystems/ext2/inc/linux/jbd.h +++ b/reactos/drivers/filesystems/ext2/inc/linux/jbd.h @@ -36,6 +36,36 @@ #define journal_oom_retry 1 +#define jbdlock_t FAST_MUTEX + +static inline void jbd_lock_init(jbdlock_t *lock) +{ + ExInitializeFastMutex(lock); +} + +static inline void jbd_lock(jbdlock_t *lock) +{ + ExAcquireFastMutex(lock); +} + +static inline void jbd_unlock(jbdlock_t *lock) +{ + ExReleaseFastMutex(lock); +} + +static inline int assert_jbd_locked(jbdlock_t *lock) +{ + int rc = 1; + + if (ExTryToAcquireFastMutex(lock)) { + ExReleaseFastMutex(lock); + rc = 0; + } + + return rc; +} + + /* * Define JBD_PARANIOD_IOFAIL to cause a kernel BUG() if ext3 finds * certain classes of error which can occur due to failed IOs. Under @@ -539,7 +569,7 @@ struct transaction_s /* * Protects info related to handles */ - spinlock_t t_handle_lock; + jbdlock_t t_handle_lock; /* * Number of outstanding updates running on this transaction @@ -657,7 +687,7 @@ struct journal_s /* * Protect the various scalars in the journal */ - spinlock_t j_state_lock; + jbdlock_t j_state_lock; /* * Number of processes waiting to create a barrier lock [j_state_lock] @@ -754,7 +784,7 @@ struct journal_s /* * Protects the buffer lists and internal buffer state. */ - spinlock_t j_list_lock; + jbdlock_t j_list_lock; /* Optional inode where we store the journal. If present, all */ /* journal block numbers are mapped into this inode via */ @@ -812,7 +842,7 @@ struct journal_s * The revoke table: maintains the list of revoked blocks in the * current transaction. [j_revoke_lock] */ - spinlock_t j_revoke_lock; + jbdlock_t j_revoke_lock; struct jbd_revoke_table_s *j_revoke; struct jbd_revoke_table_s *j_revoke_table[2]; diff --git a/reactos/drivers/filesystems/ext2/inc/linux/module.h b/reactos/drivers/filesystems/ext2/inc/linux/module.h index c0f0d65a46e..ac35b5af5d8 100644 --- a/reactos/drivers/filesystems/ext2/inc/linux/module.h +++ b/reactos/drivers/filesystems/ext2/inc/linux/module.h @@ -4,7 +4,7 @@ * FILE: Modules.h * PURPOSE: Header file: nls structures & linux kernel ... * PROGRAMMER: Matt Wu - * HOMEPAGE: http://ext2.yeah.net + * HOMEPAGE: http://www.ext2fsd.com * UPDATE HISTORY: */ @@ -15,9 +15,9 @@ #include #include +#include #include #include -#include #if _WIN32_WINNT <= 0x500 #define _WIN2K_TARGET_ 1 @@ -712,7 +712,7 @@ struct buffer_head { unsigned long b_state; /* buffer state bitmap (see above) */ struct page *b_page; /* the page this bh is mapped to */ PMDL b_mdl; /* MDL of the locked buffer */ - void *b_bcb; /* BCB of the buffer */ + void *b_bcb; /* BCB of the buffer */ // kdev_t b_dev; /* device (B_FREE = free) */ struct block_device *b_bdev; /* block device object */ @@ -940,6 +940,14 @@ static inline void brelse(struct buffer_head *bh) __brelse(bh); } +static inline void fini_bh(struct buffer_head **bh) +{ + if (bh && *bh) { + brelse(*bh); + *bh = NULL; + } +} + static inline void bforget(struct buffer_head *bh) { if (bh) diff --git a/reactos/drivers/filesystems/ext2/inc/linux/rbtree.h b/reactos/drivers/filesystems/ext2/inc/linux/rbtree.h index 0822acc2f9b..39b9039109f 100644 --- a/reactos/drivers/filesystems/ext2/inc/linux/rbtree.h +++ b/reactos/drivers/filesystems/ext2/inc/linux/rbtree.h @@ -94,8 +94,6 @@ static inline struct page * rb_insert_page_cache(struct inode * inode, #ifndef _LINUX_RBTREE_H #define _LINUX_RBTREE_H -#include - struct rb_node { ULONG_PTR rb_parent_color; diff --git a/reactos/drivers/filesystems/ext2/src/access.c b/reactos/drivers/filesystems/ext2/src/access.c new file mode 100644 index 00000000000..03ec4043be7 --- /dev/null +++ b/reactos/drivers/filesystems/ext2/src/access.c @@ -0,0 +1,54 @@ +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: access.c + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include "ext2fs.h" + +/* GLOBALS ***************************************************************/ + +extern PEXT2_GLOBAL Ext2Global; + +/* DEFINITIONS *************************************************************/ + +int Ext2CheckInodeAccess(PEXT2_VCB Vcb, struct inode *in, int attempt) +{ + int granted = 0; + + uid_t uid = Vcb->uid; + gid_t gid = Vcb->gid; + + if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) { + uid = Vcb->euid; + gid = Vcb->egid; + } + + if (!uid || uid == in->i_uid) { + /* grant all access for inode owner or root */ + granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute; + } else if (gid == in->i_gid) { + if (Ext2IsGroupReadOnly(in->i_mode)) + granted = Ext2FileCanRead | Ext2FileCanExecute; + else if (Ext2IsGroupWritable(in->i_mode)) + granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute; + } else { + if (Ext2IsOtherReadOnly(in->i_mode)) + granted = Ext2FileCanRead | Ext2FileCanExecute; + else if (Ext2IsOtherWritable(in->i_mode)) + granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute; + + } + + return IsFlagOn(granted, attempt); +} + +int Ext2CheckFileAccess(PEXT2_VCB Vcb, PEXT2_MCB Mcb, int attempt) +{ + return Ext2CheckInodeAccess(Vcb, &Mcb->Inode, attempt); +} diff --git a/reactos/drivers/filesystems/ext2/src/cleanup.c b/reactos/drivers/filesystems/ext2/src/cleanup.c index 2c04b8d75e0..bc20461ad59 100644 --- a/reactos/drivers/filesystems/ext2/src/cleanup.c +++ b/reactos/drivers/filesystems/ext2/src/cleanup.c @@ -22,12 +22,12 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_SUCCESS; - PEXT2_VCB Vcb; + PEXT2_VCB Vcb = NULL; PFILE_OBJECT FileObject; - PEXT2_FCB Fcb; - PEXT2_CCB Ccb; - PIRP Irp; - PEXT2_MCB Mcb; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PIRP Irp = NULL; + PEXT2_MCB Mcb = NULL; BOOLEAN VcbResourceAcquired = FALSE; @@ -75,7 +75,7 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) VcbResourceAcquired = ExAcquireResourceExclusiveLite( &Vcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) + TRUE ); if (Fcb->Identifier.Type == EXT2VCB) { @@ -143,7 +143,7 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) FcbResourceAcquired = ExAcquireResourceExclusiveLite( &Fcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) + TRUE ); ASSERT((Ccb->Identifier.Type == EXT2CCB) && @@ -237,8 +237,14 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) if (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart) { if (!INODE_HAS_EXTENT(Fcb->Inode)) { #if EXT2_PRE_ALLOCATION_SUPPORT - CcZeroData(FileObject, &Fcb->Header.ValidDataLength, - &Fcb->Header.AllocationSize, TRUE); + _SEH2_TRY { + CcZeroData( FileObject, + &Fcb->Header.ValidDataLength, + &Fcb->Header.AllocationSize, + TRUE); + } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { + DbgBreak(); + } _SEH2_END; #endif } } @@ -315,7 +321,7 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) FcbResourceAcquired = ExAcquireResourceExclusiveLite( &Fcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) + TRUE ); SetFlag(FileObject->Flags, FO_FILE_MODIFIED); @@ -329,7 +335,7 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) if (!IsDirectory(Fcb)) { if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) && - (Fcb->NonCachedOpenCount + 1 == Fcb->ReferenceCount) && + (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) && (Fcb->SectionObject.DataSectionObject != NULL)) { if (!IsVcbReadOnly(Vcb)) { @@ -337,14 +343,17 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); } - if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) { - ExReleaseResourceLite(&(Fcb->PagingIoResource)); - } + /* purge cache if all remaining openings are non-cached */ + if (Fcb->NonCachedOpenCount > 0) { + if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) { + ExReleaseResourceLite(&(Fcb->PagingIoResource)); + } - CcPurgeCacheSection( &Fcb->SectionObject, - NULL, - 0, - FALSE ); + CcPurgeCacheSection( &Fcb->SectionObject, + NULL, + 0, + FALSE ); + } } CcUninitializeCacheMap(FileObject, NULL, NULL); diff --git a/reactos/drivers/filesystems/ext2/src/close.c b/reactos/drivers/filesystems/ext2/src/close.c index de2d6875744..6403b5cdc21 100644 --- a/reactos/drivers/filesystems/ext2/src/close.c +++ b/reactos/drivers/filesystems/ext2/src/close.c @@ -28,11 +28,11 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext) PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_SUCCESS; PEXT2_VCB Vcb = NULL; - BOOLEAN VcbResourceAcquired = FALSE; PFILE_OBJECT FileObject; - PEXT2_FCB Fcb; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN FcbResourceAcquired = FALSE; - PEXT2_CCB Ccb; BOOLEAN bDeleteVcb = FALSE; BOOLEAN bBeingClosed = FALSE; BOOLEAN bSkipLeave = FALSE; @@ -57,7 +57,7 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext) if (!ExAcquireResourceExclusiveLite( &Vcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { + TRUE )) { DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n", Vcb->OpenHandleCount, Vcb->ReferenceCount)); @@ -118,7 +118,7 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext) if (!ExAcquireResourceExclusiveLite( &Fcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { + TRUE )) { Status = STATUS_PENDING; _SEH2_LEAVE; } @@ -178,7 +178,7 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext) if (NT_SUCCESS(Status) && Vcb != NULL && IsVcbInited(Vcb)) { /* for Ext2Fsd driver open/close, Vcb is NULL */ - if ((!bBeingClosed) && (Vcb->ReferenceCount == 0)&& + if ((!bBeingClosed) && (Vcb->ReferenceCount == 0) && (!IsMounted(Vcb) || IsDispending(Vcb))) { bDeleteVcb = TRUE; } diff --git a/reactos/drivers/filesystems/ext2/src/create.c b/reactos/drivers/filesystems/ext2/src/create.c index 43703eaae89..6ef28f7173c 100644 --- a/reactos/drivers/filesystems/ext2/src/create.c +++ b/reactos/drivers/filesystems/ext2/src/create.c @@ -68,7 +68,7 @@ Ext2FollowLink ( IN PEXT2_VCB Vcb, IN PEXT2_MCB Parent, IN PEXT2_MCB Mcb, - IN USHORT Linkdep + IN ULONG Linkdep ) { NTSTATUS Status = STATUS_LINK_FAILED; @@ -88,7 +88,7 @@ Ext2FollowLink ( /* exit if we jump into a possible symlink forever loop */ if ((Linkdep + 1) > EXT2_MAX_NESTED_LINKS || - IoGetRemainingStackSize() < 1024) { + IoGetRemainingStackSize() < 1024) { _SEH2_LEAVE; } @@ -113,14 +113,12 @@ Ext2FollowLink ( bOemBuffer = TRUE; RtlZeroMemory(OemName.Buffer, OemName.MaximumLength); - Status = Ext2ReadInode( + Status = Ext2ReadSymlink( IrpContext, Vcb, Mcb, - (ULONGLONG)0, OemName.Buffer, (ULONG)(Mcb->Inode.i_size), - FALSE, NULL); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; @@ -170,9 +168,9 @@ Ext2FollowLink ( } if (Target == NULL /* link target doesn't exist */ || - Target == Mcb /* symlink points to itself */ || - IsMcbSpecialFile(Target) /* target not resolved*/ || - IsFileDeleted(Target) /* target deleted */ ) { + Target == Mcb /* symlink points to itself */ || + IsMcbSpecialFile(Target) /* target not resolved*/ || + IsFileDeleted(Target) /* target deleted */ ) { if (Target) { ASSERT(Target->Refercount > 0); @@ -180,7 +178,6 @@ Ext2FollowLink ( } ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK); SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL); - Mcb->FileAttr = FILE_ATTRIBUTE_NORMAL; Mcb->Target = NULL; } else if (IsMcbSymLink(Target)) { @@ -194,15 +191,18 @@ Ext2FollowLink ( SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK); ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL); ASSERT(Mcb->Target->Refercount > 0); - Mcb->FileAttr = Target->FileAttr; - + } else { Mcb->Target = Target; SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK); ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL); ASSERT(Mcb->Target->Refercount > 0); - Mcb->FileAttr = Target->FileAttr; + } + + /* add directory flag to file attribute */ + if (Mcb->Target && IsMcbDirectory(Mcb->Target)) { + Mcb->FileAttr |= FILE_ATTRIBUTE_DIRECTORY; } } _SEH2_FINALLY { @@ -275,7 +275,7 @@ Ext2LookupFile ( IN PUNICODE_STRING FullName, IN PEXT2_MCB Parent, OUT PEXT2_MCB * Ext2Mcb, - IN USHORT Linkdep + IN ULONG Linkdep ) { NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND; @@ -289,12 +289,20 @@ Ext2LookupFile ( BOOLEAN bParent = FALSE; BOOLEAN bDirectory = FALSE; BOOLEAN LockAcquired = FALSE; + BOOLEAN bNotFollow = FALSE; _SEH2_TRY { ExAcquireResourceExclusiveLite(&Vcb->McbLock, TRUE); LockAcquired = TRUE; + bNotFollow = IsFlagOn(Linkdep, EXT2_LOOKUP_NOT_FOLLOW); +#ifndef __REACTOS__ + Linkdep = ClearFlag(Linkdep, EXT2_LOOKUP_FLAG_MASK); +#else + ClearFlag(Linkdep, EXT2_LOOKUP_FLAG_MASK); +#endif + *Ext2Mcb = NULL; DEBUG(DL_RES, ("Ext2LookupFile: %wZ\n", FullName)); @@ -394,7 +402,7 @@ Ext2LookupFile ( Parent = Mcb; if (IsMcbSymLink(Mcb) && IsFileDeleted(Mcb->Target) && - (Mcb->Refercount == 1)) { + Mcb->Refercount == 1) { ASSERT(Mcb->Target); ASSERT(Mcb->Target->Refercount > 0); @@ -453,16 +461,18 @@ Ext2LookupFile ( } /* set inode attribute */ - if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(Mcb->Inode.i_mode)) { + if (!Ext2CheckFileAccess(Vcb, Mcb, Ext2FileCanWrite)) { SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_READONLY); } if (S_ISDIR(Mcb->Inode.i_mode)) { SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY); } else { - SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_NORMAL); - if (!S_ISREG(Mcb->Inode.i_mode) && - !S_ISLNK(Mcb->Inode.i_mode)) { + if (S_ISREG(Mcb->Inode.i_mode)) { + SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_NORMAL); + } else if (S_ISLNK(Mcb->Inode.i_mode)) { + SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_REPARSE_POINT); + } else { SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL); } } @@ -484,7 +494,7 @@ Ext2LookupFile ( Mcb->ChangeTime = Ext2NtTime(Mcb->Inode.i_mtime); /* process symlink */ - if (S_ISLNK(Mcb->Inode.i_mode)) { + if (S_ISLNK(Mcb->Inode.i_mode) && !bNotFollow) { Ext2FollowLink( IrpContext, Vcb, Parent, @@ -616,7 +626,7 @@ Ext2ScanDir ( Ext2DerefMcb(Parent); if (bh) - brelse(bh); + __brelse(bh); if (!NT_SUCCESS(Status)) { if (de) @@ -659,7 +669,7 @@ NTSTATUS Ext2AddDotEntries(struct ext2_icb *icb, struct inode *dir, errorout: if (bh) - brelse (bh); + __brelse (bh); return Ext2WinntError(rc); } @@ -708,9 +718,11 @@ Ext2CreateFile( BOOLEAN DeleteOnClose; BOOLEAN TemporaryFile; BOOLEAN CaseSensitive; + BOOLEAN OpenReparsePoint; ACCESS_MASK DesiredAccess; ULONG ShareAccess; + ULONG CcbFlags = 0; RtlZeroMemory(&FileName, sizeof(UNICODE_STRING)); @@ -728,6 +740,9 @@ Ext2CreateFile( NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE); DeleteOnClose = IsFlagOn(Options, FILE_DELETE_ON_CLOSE); + /* Try to open reparse point (symlink) itself ? */ + OpenReparsePoint = IsFlagOn(Options, FILE_OPEN_REPARSE_POINT); + CaseSensitive = IsFlagOn(IrpSp->Flags, SL_CASE_SENSITIVE); TemporaryFile = IsFlagOn(IrpSp->Parameters.Create.FileAttributes, @@ -843,7 +858,8 @@ Ext2CreateFile( &FileName, ParentMcb, &Mcb, - 0 ); + 0 /* always follow link */ + ); McbExisting: if (!NT_SUCCESS(Status)) { @@ -964,7 +980,7 @@ Dissecting: _SEH2_LEAVE; } - if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(ParentFcb->Mcb->Inode.i_mode)) { + if (!Ext2CheckFileAccess(Vcb, ParentMcb, Ext2FileCanWrite)) { Status = STATUS_ACCESS_DENIED; _SEH2_LEAVE; } @@ -1104,7 +1120,7 @@ Dissecting: if (IsMcbDirectory(Mcb)) { if ((CreateDisposition != FILE_OPEN) && - (CreateDisposition != FILE_OPEN_IF)) { + (CreateDisposition != FILE_OPEN_IF)) { Status = STATUS_OBJECT_NAME_COLLISION; Ext2DerefMcb(Mcb); @@ -1147,7 +1163,11 @@ Openit: /* refer it's target if it's a symlink, so both refered */ if (IsMcbSymLink(Mcb)) { - if (IsFileDeleted(Mcb->Target)) { + + if (OpenReparsePoint) { + /* set Ccb flag */ + CcbFlags = CCB_OPEN_REPARSE_POINT; + } else if (IsFileDeleted(Mcb->Target)) { DbgBreak(); SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL); ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK); @@ -1162,7 +1182,12 @@ Openit: } // Check readonly flag - if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(Mcb->Inode.i_mode)) { + if (BooleanFlagOn(DesiredAccess, FILE_GENERIC_READ) && + !Ext2CheckFileAccess(Vcb, Mcb, Ext2FileCanRead)) { + Status = STATUS_ACCESS_DENIED; + _SEH2_LEAVE; + } + if (!Ext2CheckFileAccess(Vcb, Mcb, Ext2FileCanWrite)) { if (BooleanFlagOn(DesiredAccess, FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD)) { Status = STATUS_ACCESS_DENIED; @@ -1398,7 +1423,7 @@ Openit: &(Fcb->ShareAccess) ); } - Ccb = Ext2AllocateCcb(SymLink); + Ccb = Ext2AllocateCcb(CcbFlags, SymLink); if (!Ccb) { Status = STATUS_INSUFFICIENT_RESOURCES; DbgBreak(); @@ -1684,7 +1709,7 @@ Ext2CreateVolume(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb) return STATUS_SHARING_VIOLATION; } - Ccb = Ext2AllocateCcb(NULL); + Ccb = Ext2AllocateCcb(0, NULL); if (Ccb == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto errorout; @@ -1869,9 +1894,9 @@ Ext2CreateInode( Inode.i_sb = &Vcb->sb; Inode.i_ino = iNo; Inode.i_ctime = Inode.i_mtime = - Inode.i_atime = Ext2LinuxTime(SysTime); - Inode.i_uid = Parent->Inode->i_uid; - Inode.i_gid = Parent->Inode->i_gid; + Inode.i_atime = Ext2LinuxTime(SysTime); + Inode.i_uid = Vcb->uid; + Inode.i_gid = Vcb->gid; Inode.i_generation = Parent->Inode->i_generation; Inode.i_mode = S_IPERMISSION_MASK & Parent->Inode->i_mode; @@ -1887,6 +1912,11 @@ Ext2CreateInode( /* Force using extent */ if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) { Inode.i_flags |= EXT2_EXTENTS_FL; + ext4_ext_tree_init(IrpContext, NULL, &Inode); + /* ext4_ext_tree_init will save inode body */ + } else { + /* save inode body to cache */ + Ext2SaveInode(IrpContext, Vcb, &Inode); } /* add new entry to its parent */ diff --git a/reactos/drivers/filesystems/ext2/src/debug.c b/reactos/drivers/filesystems/ext2/src/debug.c index 881a632554e..f15b415b5c6 100644 --- a/reactos/drivers/filesystems/ext2/src/debug.c +++ b/reactos/drivers/filesystems/ext2/src/debug.c @@ -2654,6 +2654,7 @@ Ext2FreePool( NumberOfBytes = Data[0]; if (Data[1] != NumberOfBytes + 0x20) { DbgBreak(); + return; } for (i=0x08; i < 0x10; i++) { if (Buffer[i] != 'S') { @@ -2664,6 +2665,7 @@ Ext2FreePool( for (i=0; i < 0x10; i++) { if (Buffer[i + NumberOfBytes + 0x10] != 'E') { DbgBreak(); + return; } Buffer[i + NumberOfBytes + 0x10] = '-'; } diff --git a/reactos/drivers/filesystems/ext2/src/dirctl.c b/reactos/drivers/filesystems/ext2/src/dirctl.c index 1950649d9bb..b76385d0734 100644 --- a/reactos/drivers/filesystems/ext2/src/dirctl.c +++ b/reactos/drivers/filesystems/ext2/src/dirctl.c @@ -96,6 +96,8 @@ Ext2ProcessEntry( LONGLONG AllocationSize; ULONG FileAttributes = 0; + BOOLEAN IsEntrySymlink = FALSE; + *EntrySize = 0; NameLength = pName->Length; ASSERT((UsedLength & 7) == 0); @@ -120,7 +122,12 @@ Ext2ProcessEntry( DEBUG(DL_CP, ("Ext2ProcessDirEntry: %wZ in %wZ\n", pName, &Dcb->Mcb->FullName )); Mcb = Ext2SearchMcb(Vcb, Dcb->Mcb, pName); - if (NULL == Mcb) { + if (NULL != Mcb) { + if (S_ISLNK(Mcb->Inode.i_mode) && NULL == Mcb->Target) { + Ext2FollowLink( IrpContext, Vcb, Dcb->Mcb, Mcb, 0); + } + + } else { Inode.i_ino = in; Inode.i_sb = &Vcb->sb; @@ -136,7 +143,7 @@ Ext2ProcessEntry( } else if (S_ISLNK(Inode.i_mode)) { DEBUG(DL_RES, ("Ext2ProcessDirEntry: SymLink: %wZ\\%wZ\n", &Dcb->Mcb->FullName, pName)); - Ext2LookupFile(IrpContext, Vcb, pName, Dcb->Mcb, &Mcb, 0); + Ext2LookupFile(IrpContext, Vcb, pName, Dcb->Mcb, &Mcb,0); if (Mcb && IsMcbSpecialFile(Mcb)) { Ext2DerefMcb(Mcb); @@ -156,6 +163,7 @@ Ext2ProcessEntry( ASSERT(!IsMcbSymLink(Target)); if (IsMcbDirectory(Target)) { FileSize = 0; + FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; } else { FileSize = Target->Inode.i_size; } @@ -171,6 +179,10 @@ Ext2ProcessEntry( } } + if (IsInodeSymLink(&Mcb->Inode)) { + IsEntrySymlink = TRUE; + } + } else { if (S_ISDIR(Inode.i_mode)) { @@ -181,11 +193,14 @@ Ext2ProcessEntry( if (S_ISDIR(Inode.i_mode)) { FileAttributes = FILE_ATTRIBUTE_DIRECTORY; + } else if (S_ISLNK(Inode.i_mode)) { + FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT; + IsEntrySymlink = TRUE; } else { FileAttributes = FILE_ATTRIBUTE_NORMAL; } - if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(Inode.i_mode)) { + if (!Ext2CheckInodeAccess(Vcb, &Inode, Ext2FileCanWrite)) { SetFlag(FileAttributes, FILE_ATTRIBUTE_READONLY); } } @@ -254,8 +269,14 @@ Ext2ProcessEntry( if (FIF) { FIF->FileId.QuadPart = (LONGLONG) in; + if (IsEntrySymlink) { + FIF->EaSize = IO_REPARSE_TAG_SYMLINK; + } RtlCopyMemory(&FIF->FileName[0], &pName->Buffer[0], NameLength); } else if (FFI) { + if (IsEntrySymlink) { + FFI->EaSize = IO_REPARSE_TAG_SYMLINK; + } RtlCopyMemory(&FFI->FileName[0], &pName->Buffer[0], NameLength); } else { RtlCopyMemory(&FDI->FileName[0], &pName->Buffer[0], NameLength); @@ -302,6 +323,9 @@ Ext2ProcessEntry( if (FIB) { FIB->FileId.QuadPart = (LONGLONG)in; + if (IsEntrySymlink) { + FIB->EaSize = IO_REPARSE_TAG_SYMLINK; + } RtlCopyMemory(&FIB->FileName[0], &pName->Buffer[0], NameLength); } else { RtlCopyMemory(&FBI->FileName[0], &pName->Buffer[0], NameLength); @@ -502,13 +526,13 @@ Ext2QueryDirectory (IN PEXT2_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; - PEXT2_VCB Vcb; - PFILE_OBJECT FileObject; - PEXT2_FCB Fcb; - PEXT2_MCB Mcb; - PEXT2_CCB Ccb; - PIRP Irp; - PIO_STACK_LOCATION IoStackLocation; + PEXT2_VCB Vcb = NULL; + PFILE_OBJECT FileObject = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_MCB Mcb = NULL; + PEXT2_CCB Ccb = NULL; + PIRP Irp = NULL; + PIO_STACK_LOCATION IoStackLocation = NULL; ULONG Length; ULONG FileIndex; @@ -1009,12 +1033,12 @@ Ext2NotifyChangeDirectory ( PDEVICE_OBJECT DeviceObject; BOOLEAN CompleteRequest = TRUE; NTSTATUS Status = STATUS_UNSUCCESSFUL; - PEXT2_VCB Vcb; - PFILE_OBJECT FileObject; - PEXT2_FCB Fcb; - PEXT2_CCB Ccb; - PIRP Irp; + PEXT2_VCB Vcb = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PIRP Irp = NULL; PIO_STACK_LOCATION IrpSp; + PFILE_OBJECT FileObject; ULONG CompletionFilter; BOOLEAN WatchTree; @@ -1243,4 +1267,4 @@ Ext2IsDirectoryEmpty ( } return !!ext3_is_dir_empty(IrpContext, &Mcb->Inode); -} \ No newline at end of file +} diff --git a/reactos/drivers/filesystems/ext2/src/ext3/generic.c b/reactos/drivers/filesystems/ext2/src/ext3/generic.c index 55221e6c83a..2ae5b0f5e0e 100644 --- a/reactos/drivers/filesystems/ext2/src/ext3/generic.c +++ b/reactos/drivers/filesystems/ext2/src/ext3/generic.c @@ -3,7 +3,7 @@ * PROJECT: Ext2 File System Driver for WinNT/2K/XP * FILE: generic.c * PROGRAMMER: Matt Wu - * HOMEPAGE: http://ext2.yeah.net + * HOMEPAGE: http://www.ext2fsd.com * UPDATE HISTORY: */ @@ -132,15 +132,15 @@ Ext2LoadGroup(IN PEXT2_VCB Vcb) { struct super_block *sb = &Vcb->sb; struct ext3_sb_info *sbi = &Vcb->sbi; + ext3_fsblk_t sb_block = 1; unsigned long i; - ext3_fsblk_t block, sb_block = 1; if (BLOCK_SIZE != EXT3_MIN_BLOCK_SIZE) { sb_block = EXT4_MIN_BLOCK_SIZE / BLOCK_SIZE; } if (NULL == sbi->s_group_desc) { - sbi->s_group_desc = kzalloc(sbi->s_gdb_count * sizeof(void *), + sbi->s_group_desc = kzalloc(sbi->s_gdb_count * sizeof(ext3_fsblk_t), GFP_KERNEL); } if (sbi->s_group_desc == NULL) { @@ -149,10 +149,7 @@ Ext2LoadGroup(IN PEXT2_VCB Vcb) } for (i = 0; i < sbi->s_gdb_count; i++) { - block = descriptor_loc(sb, sb_block, i); - if (sbi->s_group_desc[i]) - continue; - sbi->s_group_desc[i] = sb_bread(sb, block); + sbi->s_group_desc[i] = descriptor_loc(sb, sb_block, i); if (!sbi->s_group_desc[i]) { DEBUG(DL_ERR, ("Ext2LoadGroup: can't read group descriptor %d\n", i)); return FALSE; @@ -167,28 +164,19 @@ Ext2LoadGroup(IN PEXT2_VCB Vcb) return TRUE; } + VOID -Ext2PutGroup(IN PEXT2_VCB Vcb) +Ext2DropGroup(IN PEXT2_VCB Vcb) { struct ext3_sb_info *sbi = &Vcb->sbi; unsigned long i; - ExAcquireResourceExclusiveLite(&Vcb->MetaLock, TRUE); if (NULL == sbi->s_group_desc) { - ExReleaseResourceLite(&Vcb->MetaLock); return; } - for (i = 0; i < sbi->s_gdb_count; i++) { - if (sbi->s_group_desc[i]) { - brelse(sbi->s_group_desc[i]); - sbi->s_group_desc[i] = NULL; - } - } - kfree(sbi->s_group_desc); sbi->s_group_desc = NULL; - ExReleaseResourceLite(&Vcb->MetaLock); } BOOLEAN @@ -198,22 +186,17 @@ Ext2SaveGroup( IN ULONG Group ) { - struct ext4_group_desc *desc; - struct buffer_head *bh = NULL; + struct ext4_group_desc *gd; + struct buffer_head *gb = NULL; unsigned long i; - ExAcquireResourceExclusiveLite(&Vcb->MetaLock, TRUE); - desc = ext4_get_group_desc(&Vcb->sb, Group, &bh); - if (bh) - get_bh(bh); - ExReleaseResourceLite(&Vcb->MetaLock); - - if (!bh) + gd = ext4_get_group_desc(&Vcb->sb, Group, &gb); + if (!gd) return 0; - desc->bg_checksum = ext4_group_desc_csum(&Vcb->sbi, Group, desc); - mark_buffer_dirty(bh); - __brelse(bh); + gd->bg_checksum = ext4_group_desc_csum(&Vcb->sbi, Group, gd); + mark_buffer_dirty(gb); + fini_bh(&gb); return TRUE; } @@ -236,6 +219,7 @@ Ext2GetInodeLba ( ) { PEXT2_GROUP_DESC gd; + struct buffer_head *bh = NULL; ext4_fsblk_t loc; int group; @@ -246,8 +230,8 @@ Ext2GetInodeLba ( } group = (inode - 1) / INODES_PER_GROUP ; - gd = ext4_get_group_desc(&Vcb->sb, group, NULL); - if (!gd) { + gd = ext4_get_group_desc(&Vcb->sb, group, &bh); + if (!bh) { *offset = 0; DbgBreak(); return FALSE; @@ -257,6 +241,7 @@ Ext2GetInodeLba ( loc = loc + ((inode - 1) % INODES_PER_GROUP) * Vcb->InodeSize; *offset = loc; + __brelse(bh); return TRUE; } @@ -273,11 +258,14 @@ void Ext2DecodeInode(struct inode *dst, struct ext3_inode *src) if (S_ISREG(src->i_mode)) { dst->i_size |= (loff_t)src->i_size_high << 32; } + dst->i_file_acl = src->i_file_acl_lo; + dst->i_file_acl |= (ext4_fsblk_t)src->osd2.linux2.l_i_file_acl_high << 32; dst->i_atime = src->i_atime; dst->i_ctime = src->i_ctime; dst->i_mtime = src->i_mtime; dst->i_dtime = src->i_dtime; dst->i_blocks = ext3_inode_blocks(src, dst); + dst->i_extra_isize = src->i_extra_isize; memcpy(&dst->i_block[0], &src->i_block[0], sizeof(__u32) * 15); } @@ -293,10 +281,13 @@ void Ext2EncodeInode(struct ext3_inode *dst, struct inode *src) if (S_ISREG(src->i_mode)) { dst->i_size_high = (__u32)(src->i_size >> 32); } + dst->i_file_acl_lo = (__u32)src->i_file_acl; + dst->osd2.linux2.l_i_file_acl_high |= (__u16)(src->i_file_acl >> 32); dst->i_atime = src->i_atime; dst->i_ctime = src->i_ctime; dst->i_mtime = src->i_mtime; dst->i_dtime = src->i_dtime; + dst->i_extra_isize = src->i_extra_isize; ASSERT(src->i_sb); ext3_inode_blocks_set(dst, src); memcpy(&dst->i_block[0], &src->i_block[0], sizeof(__u32) * 15); @@ -584,8 +575,9 @@ Ext2NewBlock( ) { struct super_block *sb = &Vcb->sb; - PEXT2_GROUP_DESC group_desc; - struct buffer_head* bh = NULL; + PEXT2_GROUP_DESC gd; + struct buffer_head *gb = NULL; + struct buffer_head *bh = NULL; ext4_fsblk_t bitmap_blk; RTL_BITMAP BlockBitmap; @@ -617,31 +609,32 @@ Ext2NewBlock( Again: - if (bh) { - __brelse(bh); - bh = NULL; - } + if (bh) + fini_bh(&bh); + + if (gb) + fini_bh(&gb); - group_desc = ext4_get_group_desc(sb, Group, NULL); - if (!group_desc) { + gd = ext4_get_group_desc(sb, Group, &gb); + if (!gd) { DbgBreak(); Status = STATUS_INSUFFICIENT_RESOURCES; goto errorout; } - bitmap_blk = ext4_block_bitmap(sb, group_desc); + bitmap_blk = ext4_block_bitmap(sb, gd); - if (group_desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { + if (gd->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { bh = sb_getblk_zero(sb, bitmap_blk); if (!bh) { DbgBreak(); Status = STATUS_INSUFFICIENT_RESOURCES; goto errorout; } - group_desc->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, group_desc); - ext4_init_block_bitmap(sb, bh, Group, group_desc); + gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd); + ext4_init_block_bitmap(sb, bh, Group, gd); set_buffer_uptodate(bh); - group_desc->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); + gd->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); Ext2SaveGroup(IrpContext, Vcb, Group); } else { bh = sb_getblk(sb, bitmap_blk); @@ -661,7 +654,7 @@ Again: } } - if (ext4_free_blks_count(sb, group_desc)) { + if (ext4_free_blks_count(sb, gd)) { if (Group == Vcb->sbi.s_groups_count - 1) { @@ -696,7 +689,7 @@ Again: RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP)); /* no blocks found: set bg_free_blocks_count to 0 */ - ext4_free_blks_set(sb, group_desc, 0); + ext4_free_blks_set(sb, gd, 0); Ext2SaveGroup(IrpContext, Vcb, Group); /* will try next group */ @@ -732,7 +725,7 @@ Again: mark_buffer_dirty(bh); /* update group description */ - ext4_free_blks_set(sb, group_desc, RtlNumberOfClearBits(&BlockBitmap)); + ext4_free_blks_set(sb, gd, RtlNumberOfClearBits(&BlockBitmap)); Ext2SaveGroup(IrpContext, Vcb, Group); /* update Vcb free blocks */ @@ -746,9 +739,9 @@ Again: goto Again; } - if (ext4_block_bitmap(sb, group_desc) == *Block || - ext4_inode_bitmap(sb, group_desc) == *Block || - ext4_inode_table(sb, group_desc) == *Block ) { + if (ext4_block_bitmap(sb, gd) == *Block || + ext4_inode_bitmap(sb, gd) == *Block || + ext4_inode_table(sb, gd) == *Block ) { DbgBreak(); dwHint = 0; goto Again; @@ -772,7 +765,10 @@ errorout: ExReleaseResourceLite(&Vcb->MetaLock); if (bh) - __brelse(bh); + fini_bh(&bh); + + if (gb) + fini_bh(&gb); return Status; } @@ -786,7 +782,8 @@ Ext2FreeBlock( ) { struct super_block *sb = &Vcb->sb; - PEXT2_GROUP_DESC group_desc; + PEXT2_GROUP_DESC gd; + struct buffer_head *gb = NULL; ext4_fsblk_t bitmap_blk; RTL_BITMAP BlockBitmap; @@ -812,6 +809,9 @@ Ext2FreeBlock( Again: + if (gb) + fini_bh(&gb); + if ( Block < EXT2_FIRST_DATA_BLOCK || Block >= TOTAL_BLOCKS || Group >= Vcb->sbi.s_groups_count) { @@ -821,13 +821,13 @@ Again: } else { - group_desc = ext4_get_group_desc(sb, Group, NULL); - if (!group_desc) { + gd = ext4_get_group_desc(sb, Group, &gb); + if (!gd) { DbgBreak(); Status = STATUS_INSUFFICIENT_RESOURCES; goto errorout; } - bitmap_blk = ext4_block_bitmap(sb, group_desc); + bitmap_blk = ext4_block_bitmap(sb, gd); /* check the block is valid or not */ if (bitmap_blk >= TOTAL_BLOCKS) { @@ -874,7 +874,7 @@ Again: RtlClearBits(&BlockBitmap, Index, Count); /* update group description table */ - ext4_free_blks_set(sb, group_desc, RtlNumberOfClearBits(&BlockBitmap)); + ext4_free_blks_set(sb, gd, RtlNumberOfClearBits(&BlockBitmap)); /* indict the cache range is dirty */ CcSetDirtyPinnedData(BitmapBcb, NULL ); @@ -913,6 +913,9 @@ Again: errorout: + if (gb) + fini_bh(&gb); + ExReleaseResourceLite(&Vcb->MetaLock); return Status; @@ -929,7 +932,8 @@ Ext2NewInode( ) { struct super_block *sb = &Vcb->sb; - PEXT2_GROUP_DESC group_desc; + PEXT2_GROUP_DESC gd; + struct buffer_head *gb = NULL; struct buffer_head *bh = NULL; ext4_fsblk_t bitmap_blk; @@ -951,13 +955,14 @@ Ext2NewInode( repeat: - if (bh) { - __brelse(bh); - bh = NULL; - } + if (bh) + fini_bh(&bh); + + if (gb) + fini_bh(&gb); Group = i = 0; - group_desc = NULL; + gd = NULL; if (Type == EXT2_FT_DIR) { @@ -966,31 +971,33 @@ repeat: for (j = 0; j < Vcb->sbi.s_groups_count; j++) { i = (j + GroupHint) % (Vcb->sbi.s_groups_count); - group_desc = ext4_get_group_desc(sb, i, NULL); - if (!group_desc) { - DbgBreak(); + gd = ext4_get_group_desc(sb, i, &gb); + if (!gd) { + DbgBreak(); Status = STATUS_INSUFFICIENT_RESOURCES; goto errorout; } - if ((group_desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) || - (ext4_used_dirs_count(sb, group_desc) << 8 < - ext4_free_inodes_count(sb, group_desc)) ) { + if ((gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) || + (ext4_used_dirs_count(sb, gd) << 8 < + ext4_free_inodes_count(sb, gd)) ) { Group = i + 1; break; } + fini_bh(&gb); } if (!Group) { PEXT2_GROUP_DESC desc = NULL; - group_desc = NULL; + gd = NULL; /* get the group with the biggest vacancy */ for (j = 0; j < Vcb->sbi.s_groups_count; j++) { - desc = ext4_get_group_desc(sb, j, NULL); + struct buffer_head *gt = NULL; + desc = ext4_get_group_desc(sb, j, >); if (!desc) { DbgBreak(); Status = STATUS_INSUFFICIENT_RESOURCES; @@ -1000,23 +1007,38 @@ repeat: /* return the group if it's not initialized yet */ if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { Group = j + 1; - group_desc = desc; + gd = desc; + + if (gb) + fini_bh(&gb); + gb = gt; + gt = NULL; break; } - if (!group_desc) { + if (!gd) { if (ext4_free_inodes_count(sb, desc) > 0) { Group = j + 1; - group_desc = desc; + gd = desc; + if (gb) + fini_bh(&gb); + gb = gt; + gt = NULL; } } else { if (ext4_free_inodes_count(sb, desc) > - ext4_free_inodes_count(sb, group_desc)) { + ext4_free_inodes_count(sb, gd)) { Group = j + 1; - group_desc = desc; + gd = desc; + if (gb) + fini_bh(&gb); + gb = gt; + gt = NULL; break; } } + if (gt) + fini_bh(>); } } @@ -1026,20 +1048,23 @@ repeat: * Try to place the inode in its parent directory (GroupHint) */ - group_desc = ext4_get_group_desc(sb, GroupHint, NULL); - if (!group_desc) { + gd = ext4_get_group_desc(sb, GroupHint, &gb); + if (!gb) { DbgBreak(); Status = STATUS_INSUFFICIENT_RESOURCES; goto errorout; } - if (group_desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT) || - ext4_free_inodes_count(sb, group_desc)) { + if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT) || + ext4_free_inodes_count(sb, gd)) { Group = GroupHint + 1; } else { + /* this group is 100% cocucpied */ + fini_bh(&gb); + i = GroupHint; /* @@ -1048,19 +1073,22 @@ repeat: for (j = 1; j < Vcb->sbi.s_groups_count; j <<= 1) { + i = (i + j) % Vcb->sbi.s_groups_count; - group_desc = ext4_get_group_desc(sb, i, NULL); - if (!group_desc) { + gd = ext4_get_group_desc(sb, i, &gb); + if (!gd) { DbgBreak(); Status = STATUS_INSUFFICIENT_RESOURCES; goto errorout; } - if (group_desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT) || - ext4_free_inodes_count(sb, group_desc)) { + if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT) || + ext4_free_inodes_count(sb, gd)) { Group = i + 1; break; } + + fini_bh(&gb); } } @@ -1072,23 +1100,25 @@ repeat: for (j = 2; j < Vcb->sbi.s_groups_count; j++) { i = (i + 1) % Vcb->sbi.s_groups_count; - group_desc = ext4_get_group_desc(sb, i, NULL); - if (!group_desc) { + gd = ext4_get_group_desc(sb, i, &gb); + if (!gd) { DbgBreak(); Status = STATUS_INSUFFICIENT_RESOURCES; goto errorout; } - if (group_desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT) || - ext4_free_inodes_count(sb, group_desc)) { + if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT) || + ext4_free_inodes_count(sb, gd)) { Group = i + 1; break; } + + fini_bh(&gb); } } } - if (group_desc == NULL || Group == 0) { + if (gd == NULL || Group == 0) { goto errorout; } @@ -1101,8 +1131,8 @@ repeat: /* valid group number starts from 1, not 0 */ Group -= 1; - ASSERT(group_desc); - bitmap_blk = ext4_inode_bitmap(sb, group_desc); + ASSERT(gd); + bitmap_blk = ext4_inode_bitmap(sb, gd); /* check the block is valid or not */ if (bitmap_blk == 0 || bitmap_blk >= TOTAL_BLOCKS) { DbgBreak(); @@ -1110,17 +1140,17 @@ repeat: goto errorout; } - if (group_desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { + if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { bh = sb_getblk_zero(sb, bitmap_blk); if (!bh) { DbgBreak(); Status = STATUS_INSUFFICIENT_RESOURCES; goto errorout; } - group_desc->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, group_desc); - ext4_init_inode_bitmap(sb, bh, Group, group_desc); + gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd); + ext4_init_inode_bitmap(sb, bh, Group, gd); set_buffer_uptodate(bh); - group_desc->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT); + gd->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT); Ext2SaveGroup(IrpContext, Vcb, Group); } else { bh = sb_getblk(sb, bitmap_blk); @@ -1160,8 +1190,8 @@ repeat: if (dwInode == 0xFFFFFFFF || dwInode >= Length) { RtlZeroMemory(&InodeBitmap, sizeof(RTL_BITMAP)); - if (ext4_free_inodes_count(sb, group_desc) > 0) { - ext4_free_inodes_set(sb, group_desc, 0); + if (ext4_free_inodes_count(sb, gd) > 0) { + ext4_free_inodes_set(sb, gd, 0); Ext2SaveGroup(IrpContext, Vcb, Group); } goto repeat; @@ -1171,8 +1201,8 @@ repeat: __u32 count = 0; /* update unused inodes count */ - count = ext4_free_inodes_count(sb, group_desc) - 1; - ext4_free_inodes_set(sb, group_desc, count); + count = ext4_free_inodes_count(sb, gd) - 1; + ext4_free_inodes_set(sb, gd, count); RtlSetBits(&InodeBitmap, dwInode, 1); @@ -1185,8 +1215,8 @@ repeat: __u32 free; - if (group_desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { - group_desc->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT); + if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { + gd->bg_flags &= cpu_to_le16(~EXT4_BG_INODE_UNINIT); /* When marking the block group with * ~EXT4_BG_INODE_UNINIT we don't want to depend * on the value of bg_itable_unused even though @@ -1196,7 +1226,7 @@ repeat: free = 0; } else { - free = EXT3_INODES_PER_GROUP(sb) - ext4_itable_unused_count(sb, group_desc); + free = EXT3_INODES_PER_GROUP(sb) - ext4_itable_unused_count(sb, gd); } /* @@ -1206,24 +1236,24 @@ repeat: * */ if (dwInode + 1 > free) { - ext4_itable_unused_set(sb, group_desc, + ext4_itable_unused_set(sb, gd, (EXT3_INODES_PER_GROUP(sb) - 1 - dwInode)); } /* We may have to initialize the block bitmap if it isn't already */ - if (group_desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { + if (gd->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { struct buffer_head *block_bitmap_bh = NULL; /* recheck and clear flag under lock if we still need to */ - block_bitmap_bh = sb_getblk_zero(sb, ext4_block_bitmap(sb, group_desc)); + block_bitmap_bh = sb_getblk_zero(sb, ext4_block_bitmap(sb, gd)); if (block_bitmap_bh) { - group_desc->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, group_desc); - free = ext4_init_block_bitmap(sb, block_bitmap_bh, Group, group_desc); + gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd); + free = ext4_init_block_bitmap(sb, block_bitmap_bh, Group, gd); set_buffer_uptodate(block_bitmap_bh); brelse(block_bitmap_bh); - group_desc->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); - ext4_free_blks_set(sb, group_desc, free); + gd->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); + ext4_free_blks_set(sb, gd, free); Ext2SaveGroup(IrpContext, Vcb, Group); } } @@ -1233,7 +1263,7 @@ repeat: /* update group_desc / super_block */ if (Type == EXT2_FT_DIR) { - ext4_used_dirs_set(sb, group_desc, ext4_used_dirs_count(sb, group_desc) + 1); + ext4_used_dirs_set(sb, gd, ext4_used_dirs_count(sb, gd) + 1); } Ext2SaveGroup(IrpContext, Vcb, Group); Ext2UpdateVcbStat(IrpContext, Vcb); @@ -1244,9 +1274,12 @@ errorout: ExReleaseResourceLite(&Vcb->MetaLock); - if (bh) { - brelse(bh); - } + if (bh) + fini_bh(&bh); + + if (gb) + fini_bh(&gb); + return Status; } @@ -1260,7 +1293,8 @@ Ext2FreeInode( ) { struct super_block *sb = &Vcb->sb; - PEXT2_GROUP_DESC group_desc; + PEXT2_GROUP_DESC gd; + struct buffer_head *gb = NULL; struct buffer_head *bh = NULL; ext4_fsblk_t bitmap_blk; @@ -1287,14 +1321,14 @@ Ext2FreeInode( goto errorout; } - group_desc = ext4_get_group_desc(sb, Group, NULL); - if (!group_desc) { + gd = ext4_get_group_desc(sb, Group, &gb); + if (!gd) { DbgBreak(); Status = STATUS_INSUFFICIENT_RESOURCES; goto errorout; } - bitmap_blk = ext4_inode_bitmap(sb, group_desc); + bitmap_blk = ext4_inode_bitmap(sb, gd); bh = sb_getblk(sb, bitmap_blk); if (!bh) { DbgBreak(); @@ -1333,7 +1367,7 @@ Ext2FreeInode( if (bModified) { /* update group free inodes */ - ext4_free_inodes_set(sb, group_desc, + ext4_free_inodes_set(sb, gd, RtlNumberOfClearBits(&InodeBitmap)); /* set inode block dirty and add to vcb dirty range */ @@ -1341,8 +1375,8 @@ Ext2FreeInode( /* update group_desc and super_block */ if (Type == EXT2_FT_DIR) { - ext4_used_dirs_set(sb, group_desc, - ext4_used_dirs_count(sb, group_desc) - 1); + ext4_used_dirs_set(sb, gd, + ext4_used_dirs_count(sb, gd) - 1); } Ext2SaveGroup(IrpContext, Vcb, Group); Ext2UpdateVcbStat(IrpContext, Vcb); @@ -1353,9 +1387,12 @@ errorout: ExReleaseResourceLite(&Vcb->MetaLock); - if (bh) { - brelse(bh); - } + if (bh) + fini_bh(&bh); + + if (gb) + fini_bh(&gb); + return Status; } @@ -1410,8 +1447,10 @@ Ext2AddEntry ( ext3_inc_count(Inode); ext3_mark_inode_dirty(IrpContext, Inode); - *Dentry = de; - de = NULL; + if (Dentry) { + *Dentry = de; + de = NULL; + } } } _SEH2_FINALLY { @@ -1430,6 +1469,69 @@ Ext2AddEntry ( } +NTSTATUS +Ext2SetFileType ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_FCB Dcb, + IN PEXT2_MCB Mcb + ) +{ + struct inode *dir = Dcb->Inode; + struct buffer_head *bh = NULL; + struct ext3_dir_entry_2 *de; + struct inode *inode; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + BOOLEAN MainResourceAcquired = FALSE; + + if (!EXT3_HAS_INCOMPAT_FEATURE(dir->i_sb, EXT3_FEATURE_INCOMPAT_FILETYPE)) { + return STATUS_SUCCESS; + } + + if (!IsDirectory(Dcb)) { + return STATUS_NOT_A_DIRECTORY; + } + + ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE); + MainResourceAcquired = TRUE; + + _SEH2_TRY { + + Ext2ReferXcb(&Dcb->ReferenceCount); + + bh = ext3_find_entry(IrpContext, Mcb->de, &de); + if (!bh) + _SEH2_LEAVE; + + inode = &Mcb->Inode; + if (le32_to_cpu(de->inode) != inode->i_ino) + _SEH2_LEAVE; + + ext3_set_de_type(inode->i_sb, de, inode->i_mode); + mark_buffer_dirty(bh); + + //if (!inode->i_nlink) + // ext3_orphan_add(handle, inode); + + dir->i_ctime = dir->i_mtime = ext3_current_time(dir); + ext3_mark_inode_dirty(IrpContext, dir); + + Status = STATUS_SUCCESS; + + } _SEH2_FINALLY { + + Ext2DerefXcb(&Dcb->ReferenceCount); + + if (MainResourceAcquired) + ExReleaseResourceLite(&Dcb->MainResource); + + if (bh) + brelse(bh); + } _SEH2_END; + + return Status; +} + NTSTATUS Ext2RemoveEntry ( IN PEXT2_IRP_CONTEXT IrpContext, @@ -2259,7 +2361,7 @@ static int ext4_group_used_meta_blocks(struct super_block *sb, if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { struct ext4_group_desc *gdp; - struct buffer_head *bh; + struct buffer_head *bh = NULL; gdp = ext4_get_group_desc(sb, block_group, &bh); if (!ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp), @@ -2276,6 +2378,8 @@ static int ext4_group_used_meta_blocks(struct super_block *sb, if (!ext4_block_in_group(sb, tmp, block_group)) used_blocks -= 1; } + if (bh) + fini_bh(&bh); } return used_blocks; } @@ -2384,12 +2488,17 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, ext4_group_t block_group, struct buffer_head **bh) { - unsigned int group_desc; - unsigned int offset; struct ext4_group_desc *desc = NULL; + struct buffer_head *gb = NULL; struct ext3_sb_info *sbi = EXT3_SB(sb); PEXT2_VCB vcb = sb->s_priv; + unsigned int group; + unsigned int offset; + + if (bh) + *bh = NULL; + if (block_group >= sbi->s_groups_count) { ext4_error(sb, "ext4_get_group_desc", "block_group >= groups_count - " @@ -2400,40 +2509,39 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, } smp_rmb(); - group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb); + group = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb); offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1); - ExAcquireResourceExclusiveLite(&vcb->MetaLock, TRUE); - - if (!sbi->s_group_desc || !sbi->s_group_desc[group_desc]) { - if (!Ext2LoadGroup(vcb)) { - ext4_error(sb, "ext4_get_group_desc", - "failed to load group desc: " - "block_group >= groups_count - " - "block_group = %u, groups_count = %u", - block_group, sbi->s_groups_count); - goto errorout; - } + if (!sbi->s_group_desc || !sbi->s_group_desc[group]) { + Ext2LoadGroup(vcb); } - if (!sbi->s_group_desc[group_desc]) { + if (!sbi->s_group_desc[group]) { ext4_error(sb, "ext4_get_group_desc", "Group descriptor not loaded - " - "block_group = %u, group_desc = %u, desc = %u", - block_group, group_desc, offset); + "block_group = %u, group = %u, desc = %u", + block_group, group, offset); goto errorout; } - desc = (struct ext4_group_desc *)( - (__u8 *)sbi->s_group_desc[group_desc]->b_data + - offset * EXT4_DESC_SIZE(sb)); + gb = sb_getblk(sb, sbi->s_group_desc[group]); + if (!gb) { + ext4_error(sb, "ext4_get_group_desc", + "failed to load group - " + "block_group = %u, group = %u, desc = %u", + block_group, group, offset); + goto errorout; + } + + desc = (struct ext4_group_desc *)(gb->b_data + + offset * EXT4_DESC_SIZE(sb)); if (bh) - *bh = sbi->s_group_desc[group_desc]; + *bh = gb; + else + fini_bh(&gb); errorout: - ExReleaseResourceLite(&vcb->MetaLock); - return desc; } @@ -2447,16 +2555,18 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb) { ext4_fsblk_t desc_count; struct ext4_group_desc *gdp; + struct buffer_head *bh = NULL; ext4_group_t i; ext4_group_t ngroups = EXT3_SB(sb)->s_groups_count; desc_count = 0; smp_rmb(); for (i = 0; i < ngroups; i++) { - gdp = ext4_get_group_desc(sb, i, NULL); - if (!gdp) + gdp = ext4_get_group_desc(sb, i, &bh); + if (!bh) continue; desc_count += ext4_free_blks_count(sb, gdp); + fini_bh(&bh); } return desc_count; @@ -2466,15 +2576,16 @@ unsigned long ext4_count_free_inodes(struct super_block *sb) { unsigned long desc_count; struct ext4_group_desc *gdp; + struct buffer_head *bh = NULL; ext4_group_t i; desc_count = 0; for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) { - gdp = ext4_get_group_desc(sb, i, NULL); - if (!gdp) + gdp = ext4_get_group_desc(sb, i, &bh); + if (!bh) continue; desc_count += ext4_free_inodes_count(sb, gdp); - cond_resched(); + fini_bh(&bh); } return desc_count; } @@ -2482,14 +2593,17 @@ unsigned long ext4_count_free_inodes(struct super_block *sb) /* Called at mount-time, super-block is locked */ unsigned long ext4_count_dirs(struct super_block * sb) { + struct ext4_group_desc *gdp; + struct buffer_head *bh = NULL; unsigned long count = 0; ext4_group_t i; for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) { - struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL); - if (!gdp) + gdp = ext4_get_group_desc(sb, i, &bh); + if (!bh) continue; count += ext4_used_dirs_count(sb, gdp); + fini_bh(&bh); } return count; } @@ -2513,7 +2627,12 @@ int ext4_check_descriptors(struct super_block *sb) DEBUG(DL_INF, ("Checking group descriptors")); for (i = 0; i < sbi->s_groups_count; i++) { - struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL); + + struct buffer_head *bh = NULL; + struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, &bh); + + if (!bh) + continue; if (i == sbi->s_groups_count - 1 || flexbg_flag) last_block = ext3_blocks_count(sbi->s_es) - 1; @@ -2526,6 +2645,7 @@ int ext4_check_descriptors(struct super_block *sb) printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: " "Block bitmap for group %u not in group " "(block %llu)!\n", i, block_bitmap); + __brelse(bh); return 0; } inode_bitmap = ext4_inode_bitmap(sb, gdp); @@ -2533,6 +2653,7 @@ int ext4_check_descriptors(struct super_block *sb) printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: " "Inode bitmap for group %u not in group " "(block %llu)!\n", i, inode_bitmap); + __brelse(bh); return 0; } inode_table = ext4_inode_table(sb, gdp); @@ -2541,6 +2662,7 @@ int ext4_check_descriptors(struct super_block *sb) printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: " "Inode table for group %u not in group " "(block %llu)!\n", i, inode_table); + __brelse(bh); return 0; } @@ -2550,12 +2672,15 @@ int ext4_check_descriptors(struct super_block *sb) i, le16_to_cpu(ext4_group_desc_csum(sbi, i, gdp)), le16_to_cpu(gdp->bg_checksum)); if (!IsVcbReadOnly(Vcb)) { + __brelse(bh); return 0; } } if (!flexbg_flag) first_block += EXT4_BLOCKS_PER_GROUP(sb); + + __brelse(bh); } ext3_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb)); diff --git a/reactos/drivers/filesystems/ext2/src/ext3/htree.c b/reactos/drivers/filesystems/ext2/src/ext3/htree.c index 186942b3e86..8d5bd4dab42 100644 --- a/reactos/drivers/filesystems/ext2/src/ext3/htree.c +++ b/reactos/drivers/filesystems/ext2/src/ext3/htree.c @@ -270,7 +270,7 @@ struct buffer_head *ext3_bread(struct ext2_icb *icb, struct inode *inode, *err = bh_submit_read(bh); if (*err) { - brelse(bh); + __brelse(bh); return NULL; } return bh; @@ -402,11 +402,11 @@ int add_dirent_to_buf(struct ext2_icb *icb, struct dentry *dentry, while ((char *) de <= top) { if (!ext3_check_dir_entry("ext3_add_entry", dir, de, bh, offset)) { - brelse(bh); + __brelse(bh); return -EIO; } if (ext3_match(namelen, name, de)) { - brelse(bh); + __brelse(bh); return -EEXIST; } nlen = EXT3_DIR_REC_LEN(de->name_len); @@ -454,7 +454,7 @@ int add_dirent_to_buf(struct ext2_icb *icb, struct dentry *dentry, dir->i_version++; ext3_mark_inode_dirty(icb, dir); set_buffer_dirty(bh); - brelse(bh); + __brelse(bh); return 0; } @@ -971,7 +971,7 @@ struct stats dx_show_entries(struct ext2_icb *icb, struct dx_hash_info *hinfo, names += stats.names; space += stats.space; bcount += stats.bcount; - brelse (bh); + __brelse (bh); } if (bcount) printk("%snames %u, fullness %u (%u%%)\n", levels?"":" ", @@ -1023,7 +1023,7 @@ static struct dx_frame * ext3_warning(dir->i_sb, __FUNCTION__, "Unrecognised inode hash code %d", root->info.hash_version); - brelse(bh); + __brelse(bh); *err = ERR_BAD_DX_DIR; goto fail; } @@ -2181,7 +2181,7 @@ struct buffer_head * ext3_find_entry (struct ext2_icb *icb, return NULL; #ifdef EXT2_HTREE_INDEX - if (is_dx(dir)) { + if (icb->MajorFunction != IRP_MJ_CREATE && is_dx(dir)) { bh = ext3_dx_find_entry(icb, dentry, res_dir, &err); /* * On success, or if the error was file not found, @@ -2264,4 +2264,4 @@ cleanup_and_exit: for (; ra_ptr < ra_max; ra_ptr++) brelse(bh_use[ra_ptr]); return ret; -} \ No newline at end of file +} diff --git a/reactos/drivers/filesystems/ext2/src/ext3/recover.c b/reactos/drivers/filesystems/ext2/src/ext3/recover.c index 2c5401c5683..4270c15e603 100644 --- a/reactos/drivers/filesystems/ext2/src/ext3/recover.c +++ b/reactos/drivers/filesystems/ext2/src/ext3/recover.c @@ -3,7 +3,7 @@ * PROJECT: Ext2 File System Driver for WinNT/2K/XP * FILE: recover.c * PROGRAMMER: Matt Wu - * HOMEPAGE: http://ext2.yeah.net + * HOMEPAGE: http://www.ext2fsd.com * UPDATE HISTORY: */ diff --git a/reactos/drivers/filesystems/ext2/src/ext4/ext4_bh.c b/reactos/drivers/filesystems/ext2/src/ext4/ext4_bh.c index 9becba0d7ed..a874bbdd8e0 100644 --- a/reactos/drivers/filesystems/ext2/src/ext4/ext4_bh.c +++ b/reactos/drivers/filesystems/ext2/src/ext4/ext4_bh.c @@ -52,3 +52,17 @@ void extents_brelse(struct buffer_head *bh) { brelse(bh); } + +/* + * extents_bforget: Release the corresponding buffer header. + * NOTE: The page owned by @bh will be marked invalidated. + * + * @bh: The corresponding buffer header that is going to be freed. + * + * The pages underlying the buffer header will be unlocked. + */ +void extents_bforget(struct buffer_head *bh) +{ + clear_buffer_uptodate(bh); + bforget(bh); +} diff --git a/reactos/drivers/filesystems/ext2/src/ext4/ext4_extents.c b/reactos/drivers/filesystems/ext2/src/ext4/ext4_extents.c index 80ce39e6069..a135b4a48f5 100644 --- a/reactos/drivers/filesystems/ext2/src/ext4/ext4_extents.c +++ b/reactos/drivers/filesystems/ext2/src/ext4/ext4_extents.c @@ -878,7 +878,7 @@ static int ext4_ext_split(void *icb, handle_t *handle, struct inode *inode, neh = ext_block_hdr(bh); neh->eh_entries = 0; neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0)); - neh->eh_magic = EXT4_EXT_MAGIC; + neh->eh_magic = cpu_to_le16(EXT4_EXT_MAGIC); neh->eh_depth = 0; /* move remainder of path[depth] to the new leaf */ @@ -948,7 +948,7 @@ static int ext4_ext_split(void *icb, handle_t *handle, struct inode *inode, neh = ext_block_hdr(bh); neh->eh_entries = cpu_to_le16(1); - neh->eh_magic = EXT4_EXT_MAGIC; + neh->eh_magic = cpu_to_le16(EXT4_EXT_MAGIC); neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode, 0)); neh->eh_depth = cpu_to_le16(depth - i); fidx = EXT_FIRST_INDEX(neh); @@ -1064,10 +1064,10 @@ static int ext4_ext_grow_indepth(void *icb, handle_t *handle, struct inode *inod /* old root could have indexes or leaves * so calculate e_max right way */ if (ext_depth(inode)) - neh->eh_max = (ext4_ext_space_block_idx(inode, 0)); + neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode, 0)); else - neh->eh_max = (ext4_ext_space_block(inode, 0)); - neh->eh_magic = EXT4_EXT_MAGIC; + neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0)); + neh->eh_magic = cpu_to_le16(EXT4_EXT_MAGIC); ext4_extent_block_csum_set(inode, neh); set_buffer_uptodate(bh); @@ -1077,11 +1077,11 @@ static int ext4_ext_grow_indepth(void *icb, handle_t *handle, struct inode *inod /* Update top-level index: num,max,pointer */ neh = ext_inode_hdr(inode); - neh->eh_entries = (1); + neh->eh_entries = cpu_to_le16(1); ext4_idx_store_pblock(EXT_FIRST_INDEX(neh), newblock); if (neh->eh_depth == 0) { /* Root extent block becomes index block */ - neh->eh_max = (ext4_ext_space_root_idx(inode, 0)); + neh->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode, 0)); EXT_FIRST_INDEX(neh)->ei_block = EXT_FIRST_EXTENT(neh)->ee_block; } @@ -2310,7 +2310,7 @@ int ext4_ext_tree_init(void *icb, handle_t *handle, struct inode *inode) eh = ext_inode_hdr(inode); eh->eh_depth = 0; eh->eh_entries = 0; - eh->eh_magic = EXT4_EXT_MAGIC; + eh->eh_magic = cpu_to_le16(EXT4_EXT_MAGIC); eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode, 0)); ext4_mark_inode_dirty(icb, handle, inode); return 0; @@ -2502,6 +2502,17 @@ out2: return err ? err : allocated; } +int ext4_ext_truncate(void *icb, struct inode *inode, unsigned long start) +{ + int ret = ext4_ext_remove_space(icb, inode, start); + + /* Save modifications on i_blocks field of the inode. */ + if (!ret) + ret = ext4_mark_inode_dirty(icb, NULL, inode); + + return ret; +} + #ifdef _MSC_VER #pragma warning(pop) #endif diff --git a/reactos/drivers/filesystems/ext2/src/ext4/extents.c b/reactos/drivers/filesystems/ext2/src/ext4/extents.c index d823ea130fd..c132911e855 100644 --- a/reactos/drivers/filesystems/ext2/src/ext4/extents.c +++ b/reactos/drivers/filesystems/ext2/src/ext4/extents.c @@ -33,7 +33,7 @@ Ext2MapExtent( ) { EXT4_EXTENT_HEADER *eh; - struct buffer_head bh_got; + struct buffer_head bh_got = {0}; int flags, rc; ULONG max_blocks = 0; @@ -67,6 +67,16 @@ Ext2MapExtent( flags = EXT4_GET_BLOCKS_IO_CREATE_EXT; max_blocks = EXT_UNWRITTEN_MAX_LEN; } + + if (Alloc) { + if (Number && !*Number) { + if (max_blocks > *Number) { + max_blocks = *Number; + } + } else { + max_blocks = 1; + } + } if ((rc = ext4_ext_get_blocks( IrpContext, @@ -209,7 +219,7 @@ Ext2TruncateExtent( /* calculate blocks to be freed */ Extra = End - Wanted; - err = ext4_ext_remove_space(IrpContext, &Mcb->Inode, Wanted); + err = ext4_ext_truncate(IrpContext, &Mcb->Inode, Wanted); if (err == 0) { if (!Ext2RemoveBlockExtent(Vcb, Mcb, Wanted, Extra)) { ClearFlag(Mcb->Flags, MCB_ZONE_INITED); @@ -224,9 +234,10 @@ Ext2TruncateExtent( Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS); } - /* save inode */ if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart)) Mcb->Inode.i_size = (loff_t)(Size->QuadPart); + + /* Save modifications on i_blocks field and i_size field of the inode. */ Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); return Status; diff --git a/reactos/drivers/filesystems/ext2/src/fastio.c b/reactos/drivers/filesystems/ext2/src/fastio.c index 7885b08861a..56e7ae641f6 100644 --- a/reactos/drivers/filesystems/ext2/src/fastio.c +++ b/reactos/drivers/filesystems/ext2/src/fastio.c @@ -213,18 +213,24 @@ Ext2FastIoWrite ( _SEH2_LEAVE; } - ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE); - Locked = TRUE; + if (ExAcquireResourceExclusiveLite(&Fcb->MainResource, Wait)) + Locked = TRUE; + else + _SEH2_LEAVE; if (IsWritingToEof(*FileOffset) || - Fcb->Header.ValidDataLength.QuadPart < FileOffset->QuadPart || Fcb->Header.FileSize.QuadPart < FileOffset->QuadPart + Length ) { Status = FALSE; - } else { - ExReleaseResourceLite(&Fcb->MainResource); - Locked = FALSE; - Status = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, - LockKey, Buffer, IoStatus, DeviceObject); + _SEH2_LEAVE; + } + + Status = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, + LockKey, Buffer, IoStatus, DeviceObject); + if (Status) { + if (IoStatus) + Length = (ULONG)IoStatus->Information; + if (Fcb->Header.ValidDataLength.QuadPart < FileOffset->QuadPart + Length) + Fcb->Header.ValidDataLength.QuadPart = FileOffset->QuadPart + Length; } } _SEH2_FINALLY { @@ -251,6 +257,8 @@ Ext2FastIoQueryBasicInfo ( IN PDEVICE_OBJECT DeviceObject) { PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_MCB Mcb = NULL; BOOLEAN Status = FALSE; BOOLEAN FcbMainResourceAcquired = FALSE; @@ -270,7 +278,8 @@ Ext2FastIoQueryBasicInfo ( IoStatus->Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } - + Ccb = (PEXT2_CCB) FileObject->FsContext2; + Mcb = Fcb->Mcb; ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); #if EXT2_DEBUG @@ -302,17 +311,11 @@ Ext2FastIoQueryBasicInfo ( } FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; */ - if (IsRoot(Fcb)) { - Buffer->CreationTime = Buffer->LastAccessTime = - Buffer->LastWriteTime = Buffer->ChangeTime = Ext2NtTime(0); - } else { - Buffer->CreationTime = Fcb->Mcb->CreationTime; - Buffer->LastAccessTime = Fcb->Mcb->LastAccessTime; - Buffer->LastWriteTime = Fcb->Mcb->LastWriteTime; - Buffer->ChangeTime = Fcb->Mcb->ChangeTime; - } - - Buffer->FileAttributes = Fcb->Mcb->FileAttr; + Buffer->CreationTime = Mcb->CreationTime; + Buffer->LastAccessTime = Mcb->LastAccessTime; + Buffer->LastWriteTime = Mcb->LastWriteTime; + Buffer->ChangeTime = Mcb->ChangeTime; + Buffer->FileAttributes = Mcb->FileAttr; if (Buffer->FileAttributes == 0) { Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL; } @@ -368,8 +371,8 @@ Ext2FastIoQueryStandardInfo ( { BOOLEAN Status = FALSE; - PEXT2_VCB Vcb; - PEXT2_FCB Fcb; + PEXT2_VCB Vcb = NULL; + PEXT2_FCB Fcb = NULL; BOOLEAN FcbMainResourceAcquired = FALSE; _SEH2_TRY { @@ -892,10 +895,11 @@ Ext2FastIoQueryNetworkOpenInfo ( IN PDEVICE_OBJECT DeviceObject ) { - BOOLEAN bResult = FALSE; - PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_MCB Mcb = NULL; + BOOLEAN bResult = FALSE; BOOLEAN FcbResourceAcquired = FALSE; _SEH2_TRY { @@ -916,6 +920,8 @@ Ext2FastIoQueryNetworkOpenInfo ( ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); + Ccb = (PEXT2_CCB) FileObject->FsContext2; + Mcb = Fcb->Mcb; #if EXT2_DEBUG DEBUG(DL_INF, ( @@ -925,7 +931,7 @@ Ext2FastIoQueryNetworkOpenInfo ( )); #endif - if (FileObject->FsContext2) { + if (!Ccb) { _SEH2_LEAVE; } @@ -949,22 +955,15 @@ Ext2FastIoQueryNetworkOpenInfo ( PFNOI->EndOfFile = Fcb->Header.FileSize; } - PFNOI->FileAttributes = Fcb->Mcb->FileAttr; + PFNOI->FileAttributes = Mcb->FileAttr; if (PFNOI->FileAttributes == 0) { PFNOI->FileAttributes = FILE_ATTRIBUTE_NORMAL; } - if (IsRoot(Fcb)) { - PFNOI->CreationTime = - PFNOI->LastAccessTime = - PFNOI->LastWriteTime = - PFNOI->ChangeTime = Ext2NtTime(0); - } else { - PFNOI->CreationTime = Fcb->Mcb->CreationTime; - PFNOI->LastAccessTime = Fcb->Mcb->LastAccessTime; - PFNOI->LastWriteTime = Fcb->Mcb->LastWriteTime; - PFNOI->ChangeTime = Fcb->Mcb->ChangeTime; - } + PFNOI->CreationTime = Mcb->CreationTime; + PFNOI->LastAccessTime = Mcb->LastAccessTime; + PFNOI->LastWriteTime = Mcb->LastWriteTime; + PFNOI->ChangeTime = Mcb->ChangeTime; bResult = TRUE; diff --git a/reactos/drivers/filesystems/ext2/src/fileinfo.c b/reactos/drivers/filesystems/ext2/src/fileinfo.c index 3588b47b20a..f00035d4d25 100644 --- a/reactos/drivers/filesystems/ext2/src/fileinfo.c +++ b/reactos/drivers/filesystems/ext2/src/fileinfo.c @@ -25,6 +25,7 @@ extern PEXT2_GLOBAL Ext2Global; #pragma alloc_text(PAGE, Ext2TruncateFile) #pragma alloc_text(PAGE, Ext2SetDispositionInfo) #pragma alloc_text(PAGE, Ext2SetRenameInfo) +#pragma alloc_text(PAGE, Ext2SetLinkInfo) #pragma alloc_text(PAGE, Ext2DeleteFile) #endif @@ -34,11 +35,11 @@ Ext2QueryFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; PFILE_OBJECT FileObject; - PEXT2_VCB Vcb; - PEXT2_FCB Fcb; - PEXT2_MCB Mcb; - PEXT2_CCB Ccb; - PIRP Irp; + PEXT2_VCB Vcb = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_MCB Mcb = NULL; + PEXT2_CCB Ccb = NULL; + PIRP Irp = NULL; PIO_STACK_LOCATION IoStackLocation; FILE_INFORMATION_CLASS FileInformationClass; ULONG Length; @@ -489,13 +490,13 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; - PEXT2_VCB Vcb; - PFILE_OBJECT FileObject; - PEXT2_FCB Fcb; - PEXT2_CCB Ccb; - PEXT2_MCB Mcb; - PIRP Irp; - PIO_STACK_LOCATION IoStackLocation; + PEXT2_VCB Vcb = NULL; + PFILE_OBJECT FileObject = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_MCB Mcb = NULL; + PIRP Irp = NULL; + PIO_STACK_LOCATION IoStackLocation = NULL; FILE_INFORMATION_CLASS FileInformationClass; ULONG NotifyFilter = 0; @@ -541,8 +542,9 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) _SEH2_LEAVE; } - /* we need grab Vcb in case it's a rename operation */ - if (FileInformationClass == FileRenameInformation) { + /* we need grab Vcb in case it's rename or sethardlink */ + if (FileInformationClass == FileRenameInformation || + FileInformationClass == FileLinkInformation) { if (!ExAcquireResourceExclusiveLite( &Vcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { @@ -616,10 +618,11 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); } - /* for renaming, we must not get any Fcb locks here, function - Ext2SetRenameInfo will get Dcb resource exclusively. */ + /* for renaming or set link, we must not grab any Fcb locks, + and later we will get Dcb or Fcb resources exclusively. */ if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE) && - FileInformationClass != FileRenameInformation) { + FileInformationClass != FileRenameInformation && + FileInformationClass != FileLinkInformation) { if (!ExAcquireResourceExclusiveLite( &Fcb->MainResource, @@ -975,6 +978,14 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) break; + + case FileLinkInformation: + { + Status = Ext2SetLinkInfo(IrpContext, Vcb, Fcb, Ccb); + } + + break; + // // This is the only set file information request supported on read // only file systems @@ -1006,11 +1017,6 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext) break; - case FileLinkInformation: - - Status = STATUS_INVALID_DEVICE_REQUEST; - break; - default: DEBUG(DL_WRN, ( "Ext2SetInformation: invalid class: %d\n", FileInformationClass)); @@ -1656,6 +1662,262 @@ errorout: return Status; } +NTSTATUS +Ext2SetLinkInfo( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_FCB Fcb, + PEXT2_CCB Ccb +) +{ + PEXT2_MCB Mcb = Fcb->Mcb; + + PEXT2_FCB TargetDcb = NULL; /* Dcb of target directory */ + PEXT2_MCB TargetMcb = NULL; + PEXT2_FCB ParentDcb = NULL; /* Dcb of it's current parent */ + PEXT2_MCB ParentMcb = NULL; + + PEXT2_FCB ExistingFcb = NULL; /* Target file Fcb if it exists*/ + PEXT2_MCB ExistingMcb = NULL; + PEXT2_MCB LinkMcb = NULL; /* Mcb for new hardlink */ + + UNICODE_STRING FileName; + + NTSTATUS Status; + + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + + PFILE_OBJECT FileObject; + PFILE_OBJECT TargetObject; + + BOOLEAN ReplaceIfExists; + BOOLEAN bTargetRemoved = FALSE; + BOOLEAN bNewTargetDcb = FALSE; + BOOLEAN bNewParentDcb = FALSE; + + PFILE_LINK_INFORMATION FLI; + + if (Ccb->SymLink) { + Mcb = Ccb->SymLink; + } + + if (IsMcbDirectory(Mcb)) { + Status = STATUS_INVALID_PARAMETER; + goto errorout; + } + + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + FileObject = IrpSp->FileObject; + TargetObject = IrpSp->Parameters.SetFile.FileObject; + ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists; + + FLI = (PFILE_LINK_INFORMATION)Irp->AssociatedIrp.SystemBuffer; + + if (TargetObject == NULL) { + + UNICODE_STRING NewName; + + NewName.Buffer = FLI->FileName; + NewName.MaximumLength = NewName.Length = (USHORT)FLI->FileNameLength; + + while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] == L'\\') { + NewName.Buffer[NewName.Length/2 - 1] = 0; + NewName.Length -= 2; + } + + while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] != L'\\') { + NewName.Length -= 2; + } + + NewName.Buffer = (USHORT *)((UCHAR *)NewName.Buffer + NewName.Length); + NewName.Length = (USHORT)(FLI->FileNameLength - NewName.Length); + + FileName = NewName; + + TargetMcb = Mcb->Parent; + if (IsMcbSymLink(TargetMcb)) { + TargetMcb = TargetMcb->Target; + ASSERT(!IsMcbSymLink(TargetMcb)); + } + + if (TargetMcb == NULL || FileName.Length >= EXT2_NAME_LEN*2) { + Status = STATUS_OBJECT_NAME_INVALID; + goto errorout; + } + + } else { + + TargetDcb = (PEXT2_FCB)(TargetObject->FsContext); + if (!TargetDcb || TargetDcb->Vcb != Vcb) { + DbgBreak(); + Status = STATUS_INVALID_PARAMETER; + goto errorout; + } + + TargetMcb = TargetDcb->Mcb; + FileName = TargetObject->FileName; + } + + if (FsRtlDoesNameContainWildCards(&FileName)) { + Status = STATUS_OBJECT_NAME_INVALID; + goto errorout; + } + + if (TargetMcb->Inode.i_ino == Mcb->Parent->Inode.i_ino) { + if (FsRtlAreNamesEqual( &FileName, + &(Mcb->ShortName), + FALSE, + NULL )) { + Status = STATUS_SUCCESS; + goto errorout; + } + } + + TargetDcb = TargetMcb->Fcb; + if (TargetDcb == NULL) { + TargetDcb = Ext2AllocateFcb(Vcb, TargetMcb); + if (TargetDcb) { + Ext2ReferXcb(&TargetDcb->ReferenceCount); + bNewTargetDcb = TRUE; + } + } + + if (TargetDcb) { + SetLongFlag(TargetDcb->Flags, FCB_STATE_BUSY); + } + + ParentMcb = Mcb->Parent; + ParentDcb = ParentMcb->Fcb; + + if ((TargetMcb->Inode.i_ino != ParentMcb->Inode.i_ino)) { + + if (ParentDcb == NULL) { + ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb); + if (ParentDcb) { + Ext2ReferXcb(&ParentDcb->ReferenceCount); + bNewParentDcb = TRUE; + } + } + if (ParentDcb) { + SetLongFlag(ParentDcb->Flags, FCB_STATE_BUSY); + } + } + + if (!TargetDcb || !ParentDcb) { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto errorout; + } + + DEBUG(DL_RES, ("Ext2SetLinkInfo: %wZ\\%wZ -> %wZ\n", + &TargetMcb->FullName, &FileName, &Mcb->FullName)); + + Status = Ext2LookupFile(IrpContext, Vcb, &FileName, + TargetMcb, &ExistingMcb, 0); + if (NT_SUCCESS(Status) && ExistingMcb != Mcb) { + + if (!ReplaceIfExists) { + + Status = STATUS_OBJECT_NAME_COLLISION; + DEBUG(DL_RES, ("Ext2SetRenameInfo: Target file %wZ exists\n", + &ExistingMcb->FullName)); + goto errorout; + + } else { + + if ( (ExistingFcb = ExistingMcb->Fcb) && !IsMcbSymLink(ExistingMcb) ) { + Status = Ext2IsFileRemovable(IrpContext, Vcb, ExistingFcb, Ccb); + if (!NT_SUCCESS(Status)) { + DEBUG(DL_REN, ("Ext2SetRenameInfo: Target file %wZ cannot be removed.\n", + &ExistingMcb->FullName)); + goto errorout; + } + } + + Status = Ext2DeleteFile(IrpContext, Vcb, ExistingFcb, ExistingMcb); + if (!NT_SUCCESS(Status)) { + DEBUG(DL_REN, ("Ext2SetRenameInfo: Failed to delete %wZ with status: %xh.\n", + &FileName, Status)); + + goto errorout; + } + bTargetRemoved = TRUE; + } + } + + /* add new entry for new target name */ + Status = Ext2AddEntry(IrpContext, Vcb, TargetDcb, &Mcb->Inode, &FileName, NULL); + if (!NT_SUCCESS(Status)) { + DEBUG(DL_REN, ("Ext2SetLinkInfo: Failed to add entry for %wZ with status: %xh.\n", + &FileName, Status)); + goto errorout; + } + + if (bTargetRemoved) { + Ext2NotifyReportChange( + IrpContext, + Vcb, + ExistingMcb, + (IsMcbDirectory(ExistingMcb) ? + FILE_NOTIFY_CHANGE_DIR_NAME : + FILE_NOTIFY_CHANGE_FILE_NAME ), + FILE_ACTION_REMOVED); + } + + if (NT_SUCCESS(Status)) { + + Ext2LookupFile(IrpContext, Vcb, &FileName, TargetMcb, &LinkMcb, 0); + if (!LinkMcb) + goto errorout; + + Ext2NotifyReportChange( + IrpContext, + Vcb, + LinkMcb, + FILE_NOTIFY_CHANGE_FILE_NAME, + FILE_ACTION_ADDED); + } + +errorout: + + if (TargetDcb) { + if (ParentDcb && ParentDcb->Inode->i_ino != TargetDcb->Inode->i_ino) { + ClearLongFlag(ParentDcb->Flags, FCB_STATE_BUSY); + } + ClearLongFlag(TargetDcb->Flags, FCB_STATE_BUSY); + } + + if (bNewTargetDcb) { + ASSERT(TargetDcb != NULL); + if (Ext2DerefXcb(&TargetDcb->ReferenceCount) == 0) { + Ext2FreeFcb(TargetDcb); + TargetDcb = NULL; + } else { + DEBUG(DL_RES, ( "Ext2SetLinkInfo: TargetDcb is resued by other threads.\n")); + } + } + + if (bNewParentDcb) { + ASSERT(ParentDcb != NULL); + if (Ext2DerefXcb(&ParentDcb->ReferenceCount) == 0) { + Ext2FreeFcb(ParentDcb); + ParentDcb = NULL; + } else { + DEBUG(DL_RES, ( "Ext2SeLinkInfo: ParentDcb is resued by other threads.\n")); + } + } + + if (ExistingMcb) + Ext2DerefMcb(ExistingMcb); + + if (LinkMcb) + Ext2DerefMcb(LinkMcb); + + return Status; +} + ULONG Ext2InodeType(PEXT2_MCB Mcb) { @@ -1705,7 +1967,6 @@ Ext2DeleteFile( } } - _SEH2_TRY { Ext2ReferMcb(Mcb); diff --git a/reactos/drivers/filesystems/ext2/src/flush.c b/reactos/drivers/filesystems/ext2/src/flush.c index 136cf26974d..dba95f55f35 100644 --- a/reactos/drivers/filesystems/ext2/src/flush.c +++ b/reactos/drivers/filesystems/ext2/src/flush.c @@ -96,39 +96,48 @@ Ext2FlushFile ( IN PEXT2_CCB Ccb ) { - IO_STATUS_BLOCK IoStatus; + IO_STATUS_BLOCK IoStatus; ASSERT(Fcb != NULL); ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); - /* update timestamp and achieve attribute */ - if (Ccb != NULL) { + _SEH2_TRY { + + /* update timestamp and achieve attribute */ + if (Ccb != NULL) { - if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) { + if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) { - LARGE_INTEGER SysTime; - KeQuerySystemTime(&SysTime); + LARGE_INTEGER SysTime; + KeQuerySystemTime(&SysTime); - Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime); - Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime); - Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode); + Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime); + Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime); + Ext2SaveInode(IrpContext, Fcb->Vcb, Fcb->Inode); + } } - } - if (IsDirectory(Fcb)) { - return STATUS_SUCCESS; - } + if (IsDirectory(Fcb)) { + IoStatus.Status = STATUS_SUCCESS; + _SEH2_LEAVE; + } + + DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n", + Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer)); - DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n", - Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer)); + CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus); + ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED); + + } _SEH2_FINALLY { - CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus); - ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED); + /* do cleanup here */ + } _SEH2_END; return IoStatus.Status; } + NTSTATUS Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext) { @@ -189,9 +198,7 @@ Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext) } MainResourceAcquired = - ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, - IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)); - + ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, TRUE); ASSERT(MainResourceAcquired); DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n", FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents))); @@ -265,4 +272,4 @@ Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext) } _SEH2_END; return Status; -} \ No newline at end of file +} diff --git a/reactos/drivers/filesystems/ext2/src/fsctl.c b/reactos/drivers/filesystems/ext2/src/fsctl.c index 124b73930d3..5ff4264e2ba 100644 --- a/reactos/drivers/filesystems/ext2/src/fsctl.c +++ b/reactos/drivers/filesystems/ext2/src/fsctl.c @@ -137,7 +137,7 @@ Ext2LockVolume (IN PEXT2_IRP_CONTEXT IrpContext) { PIO_STACK_LOCATION IrpSp; PDEVICE_OBJECT DeviceObject; - PEXT2_VCB Vcb; + PEXT2_VCB Vcb = NULL; NTSTATUS Status; BOOLEAN VcbResourceAcquired = FALSE; @@ -242,10 +242,10 @@ Ext2UnlockVolume ( IN PEXT2_IRP_CONTEXT IrpContext ) { - PIO_STACK_LOCATION IrpSp; - PDEVICE_OBJECT DeviceObject; + PIO_STACK_LOCATION IrpSp = NULL; + PDEVICE_OBJECT DeviceObject = NULL; + PEXT2_VCB Vcb = NULL; NTSTATUS Status; - PEXT2_VCB Vcb; BOOLEAN VcbResourceAcquired = FALSE; _SEH2_TRY { @@ -1289,6 +1289,595 @@ Ext2GetRetrievalPointerBase ( return Status; } +NTSTATUS +Ext2InspectReparseData( + IN PREPARSE_DATA_BUFFER RDB, + IN ULONG InputBufferLength +) +{ + NTSTATUS Status = STATUS_SUCCESS; + + if (!RDB) { + Status = STATUS_INVALID_PARAMETER; + goto out; + } + + if (InputBufferLength < sizeof(REPARSE_DATA_BUFFER)) { + Status = STATUS_BUFFER_OVERFLOW; + goto out; + } + + if (InputBufferLength < RDB->ReparseDataLength) { + Status = STATUS_BUFFER_OVERFLOW; + goto out; + } + + if (RDB->ReparseTag != IO_REPARSE_TAG_SYMLINK) { + Status = STATUS_NOT_IMPLEMENTED; + goto out; + } + + if ((PUCHAR)RDB->SymbolicLinkReparseBuffer.PathBuffer + + RDB->SymbolicLinkReparseBuffer.SubstituteNameOffset + + RDB->SymbolicLinkReparseBuffer.SubstituteNameLength + > (PUCHAR)RDB + InputBufferLength ) { + Status = STATUS_BUFFER_OVERFLOW; + goto out; + } + + if ((PUCHAR)RDB->SymbolicLinkReparseBuffer.PathBuffer + + RDB->SymbolicLinkReparseBuffer.PrintNameOffset + + RDB->SymbolicLinkReparseBuffer.PrintNameLength + > (PUCHAR)RDB + InputBufferLength) { + Status = STATUS_BUFFER_OVERFLOW; + goto out; + } + + if (RDB->SymbolicLinkReparseBuffer.Flags != SYMLINK_FLAG_RELATIVE) { + Status = STATUS_NOT_IMPLEMENTED; + goto out; + } + +out: + return Status; +} + +VOID +Ext2InitializeReparseData(IN PREPARSE_DATA_BUFFER RDB, USHORT PathBufferLength) +{ + ASSERT(FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.SubstituteNameOffset) == + REPARSE_DATA_BUFFER_HEADER_SIZE); + RDB->ReparseTag = IO_REPARSE_TAG_SYMLINK; + RDB->ReparseDataLength = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - + FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + + PathBufferLength * sizeof(WCHAR); + RDB->Reserved = 0; + RDB->SymbolicLinkReparseBuffer.SubstituteNameOffset = PathBufferLength; + RDB->SymbolicLinkReparseBuffer.SubstituteNameLength = PathBufferLength; + RDB->SymbolicLinkReparseBuffer.PrintNameOffset = 0; + RDB->SymbolicLinkReparseBuffer.PrintNameLength = PathBufferLength; + RDB->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE; + RtlZeroMemory(&RDB->SymbolicLinkReparseBuffer.PathBuffer, PathBufferLength * 2); +} + +NTSTATUS +Ext2ReadSymlink ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN PVOID Buffer, + IN ULONG Size, + OUT PULONG BytesRead + ) +{ + return Ext2ReadInode ( IrpContext, + Vcb, + Mcb, + 0, + Buffer, + Size, + FALSE, + BytesRead); +} + + + +NTSTATUS +Ext2GetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) +{ + PIRP Irp = NULL; + PIO_STACK_LOCATION IrpSp; + PEXTENDED_IO_STACK_LOCATION EIrpSp; + + PDEVICE_OBJECT DeviceObject; + + PEXT2_VCB Vcb = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_MCB Mcb = NULL; + + NTSTATUS Status = STATUS_UNSUCCESSFUL; + BOOLEAN MainResourceAcquired = FALSE; + + PVOID OutputBuffer; + ULONG OutputBufferLength; + ULONG BytesRead = 0; + + PREPARSE_DATA_BUFFER RDB; + + UNICODE_STRING UniName; + OEM_STRING OemName; + + PCHAR OemNameBuffer = NULL; + int OemNameLength = 0, i; + + Ccb = IrpContext->Ccb; + ASSERT(Ccb != NULL); + ASSERT((Ccb->Identifier.Type == EXT2CCB) && + (Ccb->Identifier.Size == sizeof(EXT2_CCB))); + DeviceObject = IrpContext->DeviceObject; + Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; + Mcb = IrpContext->Fcb->Mcb; + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + _SEH2_TRY { + + if (!Mcb || !IsInodeSymLink(&Mcb->Inode)) { + Status = STATUS_NOT_A_REPARSE_POINT; + _SEH2_LEAVE; + } + + OutputBuffer = (PVOID)Irp->AssociatedIrp.SystemBuffer; + OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; + + RDB = (PREPARSE_DATA_BUFFER)OutputBuffer; + if (!RDB) { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + if (OutputBufferLength < sizeof(REPARSE_DATA_BUFFER)) { + Status = STATUS_BUFFER_OVERFLOW; + _SEH2_LEAVE; + } + + OemNameLength = (ULONG)Mcb->Inode.i_size; + if (OemNameLength > USHRT_MAX) { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + OemName.Length = (USHORT)OemNameLength; + OemName.MaximumLength = OemNameLength + 1; + OemNameBuffer = OemName.Buffer = Ext2AllocatePool(NonPagedPool, + OemName.MaximumLength, + 'NL2E'); + if (!OemNameBuffer) { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + Status = Ext2ReadSymlink(IrpContext, + Vcb, + Mcb, + OemNameBuffer, + OemNameLength, + &BytesRead + ); + OemName.Buffer[OemName.Length] = '\0'; + for (i = 0;i < OemName.Length;i++) { + if (OemName.Buffer[i] == '/') { + OemName.Buffer[i] = '\\'; + } + } + + if (OutputBufferLength - FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) > USHRT_MAX) { + UniName.Length = USHRT_MAX; + } else { + UniName.Length = (USHORT)OutputBufferLength - FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer); + } + UniName.MaximumLength = UniName.Length; + UniName.Length = (USHORT)Ext2OEMToUnicodeSize(Vcb, &OemName); + Irp->IoStatus.Information = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + 2 * UniName.Length; + if (UniName.MaximumLength < 2*UniName.Length) { + Status = STATUS_BUFFER_TOO_SMALL; + _SEH2_LEAVE; + } + + Ext2InitializeReparseData(RDB, UniName.Length); + UniName.Buffer = RDB->SymbolicLinkReparseBuffer.PathBuffer; + /* + (PWCHAR)((PUCHAR)& + + RDB->SymbolicLinkReparseBuffer.SubstituteNameOffset); + */ + Ext2OEMToUnicode(Vcb, &UniName, &OemName); + RtlMoveMemory( (PUCHAR)RDB->SymbolicLinkReparseBuffer.PathBuffer + + RDB->SymbolicLinkReparseBuffer.SubstituteNameOffset, + UniName.Buffer, UniName.Length); + + Status = STATUS_SUCCESS; + + } _SEH2_FINALLY { + + if (OemNameBuffer) { + Ext2FreePool(OemNameBuffer, 'NL2E'); + } + + if (!_SEH2_AbnormalTermination()) { + if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { + Status = Ext2QueueRequest(IrpContext); + } else { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + } _SEH2_END; + + return Status; +} + + +NTSTATUS +Ext2WriteSymlink ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN PVOID Buffer, + IN ULONG Size, + OUT PULONG BytesWritten +) +{ + NTSTATUS Status = STATUS_SUCCESS; + PUCHAR Data = (PUCHAR)(&Mcb->Inode.i_block[0]); + + if (Size >= EXT2_LINKLEN_IN_INODE) { + + /* initialize inode i_block[] */ + if (0 == Mcb->Inode.i_blocks) { + memset(Data, 0, EXT2_LINKLEN_IN_INODE); + ClearFlag(Mcb->Inode.i_flags, EXT4_EXTENTS_FL); + Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); + } + + Status = Ext2WriteInode(IrpContext, Vcb, Mcb, + 0, Buffer, Size, + FALSE, BytesWritten); + if (!NT_SUCCESS(Status)) { + goto out; + } + + } else { + + /* free inode blocks before writing in line */ + if (Mcb->Inode.i_blocks) { + LARGE_INTEGER Zero = {0, 0}; + Ext2TruncateFile(IrpContext, Vcb, Mcb, &Zero); + } + + ClearFlag(Mcb->Inode.i_flags, EXT4_EXTENTS_FL); + memset(Data, 0, EXT2_LINKLEN_IN_INODE); + RtlCopyMemory(Data, Buffer, Size); + } + + Mcb->Inode.i_size = Size; + Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); + + if (BytesWritten) { + *BytesWritten = Size; + } + +out: + return Status; +} + + +NTSTATUS +Ext2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) +{ + PIRP Irp = NULL; + PIO_STACK_LOCATION IrpSp; + + PDEVICE_OBJECT DeviceObject; + + PEXT2_VCB Vcb = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_MCB Mcb = NULL; + + NTSTATUS Status = STATUS_UNSUCCESSFUL; + BOOLEAN bNewParentDcb = FALSE; + BOOLEAN MainResourceAcquired = FALSE; + + PVOID InputBuffer; + ULONG InputBufferLength; + ULONG BytesWritten = 0; + + PEXT2_FCB ParentDcb = NULL; /* Dcb of it's current parent */ + PEXT2_MCB ParentMcb = NULL; + + PREPARSE_DATA_BUFFER RDB; + + UNICODE_STRING UniName; + OEM_STRING OemName; + + PCHAR OemNameBuffer = NULL; + int OemNameLength = 0, i; + + + _SEH2_TRY { + + Ccb = IrpContext->Ccb; + ASSERT(Ccb != NULL); + ASSERT((Ccb->Identifier.Type == EXT2CCB) && + (Ccb->Identifier.Size == sizeof(EXT2_CCB))); + DeviceObject = IrpContext->DeviceObject; + Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; + Fcb = IrpContext->Fcb; + Mcb = Fcb->Mcb; + Irp = IrpContext->Irp; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + ParentMcb = Mcb->Parent; + ParentDcb = ParentMcb->Fcb; + if (ParentDcb == NULL) { + ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb); + if (ParentDcb) { + Ext2ReferXcb(&ParentDcb->ReferenceCount); + bNewParentDcb = TRUE; + } + } + + if (!Mcb) + _SEH2_LEAVE; + + if (!ExAcquireResourceSharedLite( + &Fcb->MainResource, + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + MainResourceAcquired = TRUE; + + InputBuffer = Irp->AssociatedIrp.SystemBuffer; + InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; + + RDB = (PREPARSE_DATA_BUFFER)InputBuffer; + Status = Ext2InspectReparseData(RDB, InputBufferLength); + if (!NT_SUCCESS(Status)) { + _SEH2_LEAVE; + } + + UniName.Length = RDB->SymbolicLinkReparseBuffer.SubstituteNameLength; + UniName.MaximumLength = UniName.Length; + UniName.Buffer = + (PWCHAR)((PUCHAR)&RDB->SymbolicLinkReparseBuffer.PathBuffer + + RDB->SymbolicLinkReparseBuffer.SubstituteNameOffset); + + OemNameLength = Ext2UnicodeToOEMSize(Vcb, &UniName); + if (OemNameLength > USHRT_MAX) { + Status = STATUS_INVALID_PARAMETER; + _SEH2_LEAVE; + } + OemName.Length = (USHORT)OemNameLength; + OemName.MaximumLength = OemNameLength + 1; + OemNameBuffer = OemName.Buffer = Ext2AllocatePool(PagedPool, + OemName.MaximumLength, + 'NL2E'); + if (!OemNameBuffer) { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + + Ext2UnicodeToOEM(Vcb, &OemName, &UniName); + OemName.Buffer[OemName.Length] = '\0'; + for (i = 0;i < OemName.Length;i++) { + if (OemName.Buffer[i] == '\\') { + OemName.Buffer[i] = '/'; + } + } + + /* overwrite inode mode as type SYMLINK */ + Mcb->Inode.i_mode = S_IFLNK | S_IRWXUGO; + Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); + SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_REPARSE_POINT); + + Status = Ext2WriteSymlink(IrpContext, Vcb, Mcb, OemNameBuffer, + OemNameLength, &BytesWritten); + if (NT_SUCCESS(Status)) { + Status = Ext2SetFileType(IrpContext, Vcb, ParentDcb, Mcb); + } + + } _SEH2_FINALLY { + + if (MainResourceAcquired) { + ExReleaseResourceLite(&Fcb->MainResource); + } + + if (OemNameBuffer) { + Ext2FreePool(OemNameBuffer, 'NL2E'); + } + + if (NT_SUCCESS(Status)) { + Ext2NotifyReportChange( + IrpContext, + Vcb, + Mcb, + FILE_NOTIFY_CHANGE_ATTRIBUTES, + FILE_ACTION_MODIFIED ); + } + + if (bNewParentDcb) { + ASSERT(ParentDcb != NULL); + if (Ext2DerefXcb(&ParentDcb->ReferenceCount) == 0) { + Ext2FreeFcb(ParentDcb); + ParentDcb = NULL; + } else { + DEBUG(DL_RES, ( "Ext2SetRenameInfo: ParentDcb is resued by other threads.\n")); + } + } + + if (!_SEH2_AbnormalTermination()) { + if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { + Status = Ext2QueueRequest(IrpContext); + } else { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + } _SEH2_END; + + return Status; +} + +NTSTATUS +Ext2TruncateSymlink( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb, + ULONG Size + ) +{ + NTSTATUS status = STATUS_SUCCESS; + PUCHAR data = (PUCHAR)&Mcb->Inode.i_block; + ULONG len = (ULONG)Mcb->Inode.i_size; + LARGE_INTEGER NewSize; + + if (len < EXT2_LINKLEN_IN_INODE && !Mcb->Inode.i_blocks) { + + RtlZeroMemory(data + Size, EXT2_LINKLEN_IN_INODE - Size); + Mcb->Inode.i_size = Size; + Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); + + } else { + NewSize.QuadPart = Size; + status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &NewSize); + if (!NT_SUCCESS(status)) { + goto out; + } + } + +out: + return status; +} + + +/* FIXME: We can only handle one reparse point right now. */ +NTSTATUS +Ext2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext) +{ + PIRP Irp = NULL; + + PDEVICE_OBJECT DeviceObject; + + PEXT2_VCB Vcb = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_MCB Mcb = NULL; + + NTSTATUS Status = STATUS_UNSUCCESSFUL; + BOOLEAN bNewParentDcb = FALSE; + BOOLEAN bFcbAllocated = FALSE; + BOOLEAN MainResourceAcquired = FALSE; + + PEXT2_FCB ParentDcb = NULL; /* Dcb of it's current parent */ + PEXT2_MCB ParentMcb = NULL; + + _SEH2_TRY { + + Ccb = IrpContext->Ccb; + ASSERT(Ccb != NULL); + ASSERT((Ccb->Identifier.Type == EXT2CCB) && + (Ccb->Identifier.Size == sizeof(EXT2_CCB))); + DeviceObject = IrpContext->DeviceObject; + Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; + Mcb = IrpContext->Fcb->Mcb; + Irp = IrpContext->Irp; + + ParentMcb = Mcb->Parent; + ParentDcb = ParentMcb->Fcb; + if (ParentDcb == NULL) { + ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb); + if (ParentDcb) { + Ext2ReferXcb(&ParentDcb->ReferenceCount); + bNewParentDcb = TRUE; + } + } + + if (!Mcb) { + Status = STATUS_NOT_A_REPARSE_POINT; + _SEH2_LEAVE; + } + + Fcb = Ext2AllocateFcb (Vcb, Mcb); + if (Fcb) { + bFcbAllocated = TRUE; + } else { + Status = STATUS_INSUFFICIENT_RESOURCES; + _SEH2_LEAVE; + } + Ext2ReferXcb(&Fcb->ReferenceCount); + + if (!ExAcquireResourceSharedLite( + &Fcb->MainResource, + IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { + Status = STATUS_PENDING; + _SEH2_LEAVE; + } + MainResourceAcquired = TRUE; + + Status = Ext2TruncateSymlink(IrpContext, Vcb, Mcb, 0); + if (!NT_SUCCESS(Status)) { + _SEH2_LEAVE; + } + if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) { + SetFlag(Mcb->Inode.i_flags, EXT4_EXTENTS_FL); + } + 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 { + + if (MainResourceAcquired) { + ExReleaseResourceLite(&Fcb->MainResource); + } + + if (NT_SUCCESS(Status)) { + Ext2NotifyReportChange( + IrpContext, + Vcb, + Mcb, + FILE_NOTIFY_CHANGE_ATTRIBUTES, + FILE_ACTION_MODIFIED ); + + } + + if (bNewParentDcb) { + ASSERT(ParentDcb != NULL); + if (Ext2DerefXcb(&ParentDcb->ReferenceCount) == 0) { + Ext2FreeFcb(ParentDcb); + ParentDcb = NULL; + } else { + DEBUG(DL_RES, ( "Ext2DeleteReparsePoint: ParentDcb is resued.\n")); + } + } + + if (!_SEH2_AbnormalTermination()) { + if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { + Status = Ext2QueueRequest(IrpContext); + } else { + Ext2CompleteIrpContext(IrpContext, Status); + } + } + + if (bFcbAllocated) { + if (Ext2DerefXcb(&Fcb->ReferenceCount) == 0) { + Ext2FreeFcb(Fcb); + } + } + } _SEH2_END; + + return Status; +} NTSTATUS Ext2UserFsRequest (IN PEXT2_IRP_CONTEXT IrpContext) @@ -1304,7 +1893,6 @@ Ext2UserFsRequest (IN PEXT2_IRP_CONTEXT IrpContext) (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); Irp = IrpContext->Irp; - IoStackLocation = IoGetCurrentIrpStackLocation(Irp); #ifndef _GNU_NTIFS_ @@ -1317,6 +1905,18 @@ Ext2UserFsRequest (IN PEXT2_IRP_CONTEXT IrpContext) switch (FsControlCode) { + case FSCTL_GET_REPARSE_POINT: + Status = Ext2GetReparsePoint(IrpContext); + break; + + case FSCTL_SET_REPARSE_POINT: + Status = Ext2SetReparsePoint(IrpContext); + break; + + case FSCTL_DELETE_REPARSE_POINT: + Status = Ext2DeleteReparsePoint(IrpContext); + break; + case FSCTL_LOCK_VOLUME: Status = Ext2LockVolume(IrpContext); break; @@ -1513,6 +2113,10 @@ Ext2MountVolume (IN PEXT2_IRP_CONTEXT IrpContext) VolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1); ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING); +/* + These are for buffer-address alignment requirements. + Never do this check, unless you want fail user requests :) + if (TargetDeviceObject->AlignmentRequirement > VolumeDeviceObject->AlignmentRequirement) { @@ -1520,6 +2124,14 @@ Ext2MountVolume (IN PEXT2_IRP_CONTEXT IrpContext) TargetDeviceObject->AlignmentRequirement; } + if (DiskGeometry.BytesPerSector - 1 > + VolumeDeviceObject->AlignmentRequirement) { + VolumeDeviceObject->AlignmentRequirement = + DiskGeometry.BytesPerSector - 1; + TargetDeviceObject->AlignmentRequirement = + DiskGeometry.BytesPerSector - 1; + } +*/ (IoStackLocation->Parameters.MountVolume.Vpb)->DeviceObject = VolumeDeviceObject; Vpb = IoStackLocation->Parameters.MountVolume.Vpb; @@ -1891,7 +2503,7 @@ Ext2DismountVolume (IN PEXT2_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; - PEXT2_VCB Vcb; + PEXT2_VCB Vcb = NULL; BOOLEAN VcbResourceAcquired = FALSE; _SEH2_TRY { @@ -1968,11 +2580,12 @@ Ext2CheckDismount ( BOOLEAN bDeleted = FALSE, bTearDown = FALSE; ULONG UnCleanCount = 0; - NewVpb = Ext2AllocatePool(NonPagedPool, VPB_SIZE, TAG_VPB); + NewVpb = ExAllocatePoolWithTag(NonPagedPool, VPB_SIZE, TAG_VPB); if (NewVpb == NULL) { DEBUG(DL_ERR, ( "Ex2CheckDismount: failed to allocate NewVpb.\n")); return FALSE; } + DEBUG(DL_DBG, ("Ext2CheckDismount: NewVpb allocated: %p\n", NewVpb)); INC_MEM_COUNT(PS_VPB, NewVpb, sizeof(VPB)); memset(NewVpb, '_', VPB_SIZE); RtlZeroMemory(NewVpb, sizeof(VPB)); @@ -1985,15 +2598,16 @@ Ext2CheckDismount ( if ((IrpContext->MajorFunction == IRP_MJ_CREATE) && (IrpContext->RealDevice == Vcb->RealDevice)) { - UnCleanCount = 3; - } else { UnCleanCount = 2; + } else { + UnCleanCount = 1; } IoAcquireVpbSpinLock (&Irql); DEBUG(DL_DBG, ("Ext2CheckDismount: Vpb %p ioctl=%d Device %p\n", Vpb, Vpb->ReferenceCount, Vpb->RealDevice)); + if (Vpb->ReferenceCount <= UnCleanCount) { if (!IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { @@ -2018,10 +2632,17 @@ Ext2CheckDismount ( Vpb->DeviceObject = NULL; } + DEBUG(DL_DBG, ("Ext2CheckDismount: Vpb: %p bDeleted=%d bTearDown=%d\n", + Vpb, bDeleted, bTearDown)); + + } else if (bForce) { - DEBUG(DL_DBG, ( "Ext2CheckDismount: NewVpb %p Realdevice = %p\n", - NewVpb, Vpb->RealDevice)); + DEBUG(DL_DBG, ( "Ext2CheckDismount: New/Old Vpb %p/%p Realdevice = %p\n", + NewVpb, Vcb->Vpb, Vpb->RealDevice)); + + /* keep vpb president and later we'll free it */ + SetFlag(Vpb->Flags, VPB_PERSISTENT); Vcb->Vpb2 = Vcb->Vpb; NewVpb->Type = IO_TYPE_VPB; @@ -2051,8 +2672,8 @@ Ext2CheckDismount ( } if (NewVpb != NULL) { - DEBUG(DL_DBG, ( "Ext2CheckDismount: freeing Vpb %p\n", NewVpb)); - Ext2FreePool(NewVpb, TAG_VPB); + DEBUG(DL_DBG, ( "Ext2CheckDismount: freeing new Vpb %p\n", NewVpb)); + ExFreePoolWithTag(NewVpb, TAG_VPB); DEC_MEM_COUNT(PS_VPB, NewVpb, sizeof(VPB)); } @@ -2081,8 +2702,6 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb, FlushBeforePurge = FALSE; } - Ext2PutGroup(Vcb); - FcbListEntry= NULL; InitializeListHead(&FcbList); diff --git a/reactos/drivers/filesystems/ext2/src/init.c b/reactos/drivers/filesystems/ext2/src/init.c index 4a40e2dd5cc..470811a273b 100644 --- a/reactos/drivers/filesystems/ext2/src/init.c +++ b/reactos/drivers/filesystems/ext2/src/init.c @@ -18,10 +18,12 @@ PEXT2_GLOBAL Ext2Global = NULL; /* * Ext2Fsd version, building date/time */ + CHAR gVersion[] = EXT2FSD_VERSION; CHAR gTime[] = __TIME__; CHAR gDate[] = __DATE__; + /* DEFINITIONS ***********************************************************/ NTSTATUS NTAPI @@ -417,8 +419,8 @@ DriverEntry ( " Free" #endif " -- " - __DATE__" " - __TIME__".\n"); + __DATE__ " " + __TIME__ ".\n"); DEBUG(DL_FUN, ( "Ext2 DriverEntry ...\n")); diff --git a/reactos/drivers/filesystems/ext2/src/jbd/replay.c b/reactos/drivers/filesystems/ext2/src/jbd/replay.c index f0df57784fe..2835ed246bb 100644 --- a/reactos/drivers/filesystems/ext2/src/jbd/replay.c +++ b/reactos/drivers/filesystems/ext2/src/jbd/replay.c @@ -43,9 +43,9 @@ int log_start_commit(journal_t *journal, tid_t tid) { int ret; - spin_lock(&journal->j_state_lock); + jbd_lock(&journal->j_state_lock); ret = __log_start_commit(journal, tid); - spin_unlock(&journal->j_state_lock); + jbd_unlock(&journal->j_state_lock); return ret; } @@ -69,12 +69,12 @@ static void __journal_abort_hard(journal_t *journal) if (journal->j_flags & JFS_ABORT) return; - spin_lock(&journal->j_state_lock); + jbd_lock(&journal->j_state_lock); journal->j_flags |= JFS_ABORT; transaction = journal->j_running_transaction; if (transaction) __log_start_commit(journal, transaction->t_tid); - spin_unlock(&journal->j_state_lock); + jbd_unlock(&journal->j_state_lock); } /* Soft abort: record the abort error status in the journal superblock, @@ -160,12 +160,12 @@ int journal_errno(journal_t *journal) { int err; - spin_lock(&journal->j_state_lock); + jbd_lock(&journal->j_state_lock); if (journal->j_flags & JFS_ABORT) err = -EROFS; else err = journal->j_errno; - spin_unlock(&journal->j_state_lock); + jbd_unlock(&journal->j_state_lock); return err; } @@ -180,12 +180,12 @@ int journal_clear_err(journal_t *journal) { int err = 0; - spin_lock(&journal->j_state_lock); + jbd_lock(&journal->j_state_lock); if (journal->j_flags & JFS_ABORT) err = -EROFS; else journal->j_errno = 0; - spin_unlock(&journal->j_state_lock); + jbd_unlock(&journal->j_state_lock); return err; } @@ -198,10 +198,10 @@ int journal_clear_err(journal_t *journal) */ void journal_ack_err(journal_t *journal) { - spin_lock(&journal->j_state_lock); + jbd_lock(&journal->j_state_lock); if (journal->j_errno) journal->j_flags |= JFS_ACK_ERR; - spin_unlock(&journal->j_state_lock); + jbd_unlock(&journal->j_state_lock); } int journal_blocks_per_page(struct inode *inode) @@ -462,7 +462,7 @@ int journal_next_log_block(journal_t *journal, unsigned long *retp) { unsigned long blocknr; - spin_lock(&journal->j_state_lock); + jbd_lock(&journal->j_state_lock); J_ASSERT(journal->j_free > 1); blocknr = journal->j_head; @@ -470,7 +470,7 @@ int journal_next_log_block(journal_t *journal, unsigned long *retp) journal->j_free--; if (journal->j_head == journal->j_last) journal->j_head = journal->j_first; - spin_unlock(&journal->j_state_lock); + jbd_unlock(&journal->j_state_lock); return journal_bmap(journal, blocknr, retp); } @@ -561,9 +561,9 @@ static journal_t * journal_init_common (void) init_waitqueue_head(&journal->j_wait_updates); mutex_init(&journal->j_barrier); mutex_init(&journal->j_checkpoint_mutex); - spin_lock_init(&journal->j_revoke_lock); - spin_lock_init(&journal->j_list_lock); - spin_lock_init(&journal->j_state_lock); + jbd_lock_init(&journal->j_revoke_lock); + jbd_lock_init(&journal->j_list_lock); + jbd_lock_init(&journal->j_state_lock); journal->j_commit_interval = (HZ * JBD_DEFAULT_MAX_COMMIT_AGE); @@ -688,17 +688,17 @@ void journal_destroy(journal_t *journal) /* Force any old transactions to disk */ /* Totally anal locking here... */ - spin_lock(&journal->j_list_lock); + jbd_lock(&journal->j_list_lock); while (journal->j_checkpoint_transactions != NULL) { - spin_unlock(&journal->j_list_lock); + jbd_unlock(&journal->j_list_lock); log_do_checkpoint(journal); - spin_lock(&journal->j_list_lock); + jbd_lock(&journal->j_list_lock); } J_ASSERT(journal->j_running_transaction == NULL); J_ASSERT(journal->j_committing_transaction == NULL); J_ASSERT(journal->j_checkpoint_transactions == NULL); - spin_unlock(&journal->j_list_lock); + jbd_unlock(&journal->j_list_lock); /* We can now mark the journal as empty. */ journal->j_tail = 0; @@ -1048,14 +1048,14 @@ void journal_update_superblock(journal_t *journal, int wait) goto out; } - spin_lock(&journal->j_state_lock); + jbd_lock(&journal->j_state_lock); jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n", journal->j_tail, journal->j_tail_sequence, journal->j_errno); sb->s_sequence = cpu_to_be32(journal->j_tail_sequence); sb->s_start = cpu_to_be32(journal->j_tail); sb->s_errno = cpu_to_be32(journal->j_errno); - spin_unlock(&journal->j_state_lock); + jbd_unlock(&journal->j_state_lock); BUFFER_TRACE(bh, "marking dirty"); mark_buffer_dirty(bh); @@ -1069,12 +1069,12 @@ out: * any future commit will have to be careful to update the * superblock again to re-record the true start of the log. */ - spin_lock(&journal->j_state_lock); + jbd_lock(&journal->j_state_lock); if (sb->s_start) journal->j_flags &= ~JFS_FLUSHED; else journal->j_flags |= JFS_FLUSHED; - spin_unlock(&journal->j_state_lock); + jbd_unlock(&journal->j_state_lock); } /* @@ -1240,7 +1240,7 @@ static void __journal_temp_unlink_buffer(struct journal_head *jh) J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh)); transaction = jh->b_transaction; if (transaction) - assert_spin_locked(&transaction->t_journal->j_list_lock); + assert_jbd_locked(&transaction->t_journal->j_list_lock); J_ASSERT_JH(jh, jh->b_jlist < BJ_Types); if (jh->b_jlist != BJ_None) @@ -1292,9 +1292,9 @@ void __journal_unfile_buffer(struct journal_head *jh) void journal_unfile_buffer(journal_t *journal, struct journal_head *jh) { jbd_lock_bh_state(jh2bh(jh)); - spin_lock(&journal->j_list_lock); + jbd_lock(&journal->j_list_lock); __journal_unfile_buffer(jh); - spin_unlock(&journal->j_list_lock); + jbd_unlock(&journal->j_list_lock); jbd_unlock_bh_state(jh2bh(jh)); } @@ -1342,7 +1342,7 @@ void __journal_file_buffer(struct journal_head *jh, struct buffer_head *bh = jh2bh(jh); J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh)); - assert_spin_locked(&transaction->t_journal->j_list_lock); + assert_jbd_locked(&transaction->t_journal->j_list_lock); J_ASSERT_JH(jh, jh->b_jlist < BJ_Types); J_ASSERT_JH(jh, jh->b_transaction == transaction || @@ -1409,9 +1409,9 @@ void journal_file_buffer(struct journal_head *jh, transaction_t *transaction, int jlist) { jbd_lock_bh_state(jh2bh(jh)); - spin_lock(&transaction->t_journal->j_list_lock); + jbd_lock(&transaction->t_journal->j_list_lock); __journal_file_buffer(jh, transaction, jlist); - spin_unlock(&transaction->t_journal->j_list_lock); + jbd_unlock(&transaction->t_journal->j_list_lock); jbd_unlock_bh_state(jh2bh(jh)); } @@ -1455,7 +1455,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh) BUFFER_TRACE(bh, "entry"); jbd_lock_bh_state(bh); - spin_lock(&journal->j_list_lock); + jbd_lock(&journal->j_list_lock); if (!buffer_jbd(bh)) goto not_jbd; @@ -1508,7 +1508,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh) journal_remove_journal_head(bh); __brelse(bh); if (!buffer_jbd(bh)) { - spin_unlock(&journal->j_list_lock); + jbd_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); __bforget(bh); goto drop; @@ -1531,7 +1531,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh) } not_jbd: - spin_unlock(&journal->j_list_lock); + jbd_unlock(&journal->j_list_lock); jbd_unlock_bh_state(bh); __brelse(bh); drop: diff --git a/reactos/drivers/filesystems/ext2/src/jbd/revoke.c b/reactos/drivers/filesystems/ext2/src/jbd/revoke.c index 26892836cd2..0ba861a6073 100644 --- a/reactos/drivers/filesystems/ext2/src/jbd/revoke.c +++ b/reactos/drivers/filesystems/ext2/src/jbd/revoke.c @@ -131,9 +131,9 @@ repeat: record->sequence = seq; record->blocknr = blocknr; hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)]; - spin_lock(&journal->j_revoke_lock); + jbd_lock(&journal->j_revoke_lock); list_add(&record->hash, hash_list); - spin_unlock(&journal->j_revoke_lock); + jbd_unlock(&journal->j_revoke_lock); return 0; oom: @@ -154,16 +154,16 @@ static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal, hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)]; - spin_lock(&journal->j_revoke_lock); + jbd_lock(&journal->j_revoke_lock); record = (struct jbd_revoke_record_s *) hash_list->next; while (&(record->hash) != hash_list) { if (record->blocknr == blocknr) { - spin_unlock(&journal->j_revoke_lock); + jbd_unlock(&journal->j_revoke_lock); return record; } record = (struct jbd_revoke_record_s *) record->hash.next; } - spin_unlock(&journal->j_revoke_lock); + jbd_unlock(&journal->j_revoke_lock); return NULL; } @@ -261,7 +261,7 @@ int journal_init_revoke(journal_t *journal, int hash_size) for (tmp = 0; tmp < hash_size; tmp++) INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]); - spin_lock_init(&journal->j_revoke_lock); + jbd_lock_init(&journal->j_revoke_lock); return 0; } @@ -447,9 +447,9 @@ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh) if (record) { jbd_debug(4, "cancelled existing revoke on " "blocknr %llu\n", (u64)bh->b_blocknr); - spin_lock(&journal->j_revoke_lock); + jbd_lock(&journal->j_revoke_lock); list_del(&record->hash); - spin_unlock(&journal->j_revoke_lock); + jbd_unlock(&journal->j_revoke_lock); kmem_cache_free(revoke_record_cache, record); did_revoke = 1; } diff --git a/reactos/drivers/filesystems/ext2/src/linux.c b/reactos/drivers/filesystems/ext2/src/linux.c index 889bf0948e6..289c0c7bfb1 100644 --- a/reactos/drivers/filesystems/ext2/src/linux.c +++ b/reactos/drivers/filesystems/ext2/src/linux.c @@ -353,6 +353,10 @@ free_buffer_head(struct buffer_head * bh) Ext2DestroyMdl(bh->b_mdl); } + if (bh->b_bcb) { + CcUnpinDataForThread(bh->b_bcb, (ERESOURCE_THREAD)bh | 0x3); + } + DEBUG(DL_BH, ("bh=%p freed.\n", bh)); DEC_MEM_COUNT(PS_BUFF_HEAD, bh, sizeof(struct buffer_head)); kmem_cache_free(g_jbh.bh_cache, bh); @@ -420,7 +424,7 @@ static void buffer_head_remove(struct block_device *bdev, struct buffer_head *bh } struct buffer_head * -get_block_bh( +get_block_bh_mdl( struct block_device * bdev, sector_t block, unsigned long size, @@ -538,17 +542,7 @@ errorout: return bh; } -struct buffer_head * -__getblk( - struct block_device * bdev, - sector_t block, - unsigned long size -) -{ - return get_block_bh(bdev, block, size, 0); -} - -int submit_bh(int rw, struct buffer_head *bh) +int submit_bh_mdl(int rw, struct buffer_head *bh) { struct block_device *bdev = bh->b_bdev; PEXT2_VCB Vcb = bdev->bd_priv; @@ -607,6 +601,159 @@ errorout: return 0; } +struct buffer_head * +get_block_bh( + struct block_device * bdev, + sector_t block, + unsigned long size, + int zero +) +{ + PEXT2_VCB Vcb = bdev->bd_priv; + LARGE_INTEGER offset; + + KIRQL irql = 0; + struct list_head *entry; + + /* allocate buffer_head and initialize it */ + struct buffer_head *bh = NULL, *tbh = NULL; + + /* check the block is valid or not */ + if (block >= TOTAL_BLOCKS) { + DbgBreak(); + goto errorout; + } + + /* search the bdev bh list */ + spin_lock_irqsave(&bdev->bd_bh_lock, irql); + tbh = buffer_head_search(bdev, block); + if (tbh) { + bh = tbh; + get_bh(bh); + spin_unlock_irqrestore(&bdev->bd_bh_lock, irql); + goto errorout; + } + spin_unlock_irqrestore(&bdev->bd_bh_lock, irql); + + bh = new_buffer_head(); + if (!bh) { + goto errorout; + } + bh->b_bdev = bdev; + bh->b_blocknr = block; + bh->b_size = size; + bh->b_data = NULL; + atomic_inc(&g_jbh.bh_count); + atomic_inc(&g_jbh.bh_acount); + +again: + + offset.QuadPart = (s64) bh->b_blocknr; + offset.QuadPart <<= BLOCK_BITS; + + if (zero) { + if (!CcPreparePinWrite(Vcb->Volume, + &offset, + bh->b_size, + FALSE, + PIN_WAIT | PIN_EXCLUSIVE, + &bh->b_bcb, + (PVOID *)&bh->b_data)) { + Ext2Sleep(100); + goto again; + } + } else { + if (!CcPinRead( Vcb->Volume, + &offset, + bh->b_size, + PIN_WAIT, + &bh->b_bcb, + (PVOID *)&bh->b_data)) { + Ext2Sleep(100); + goto again; + } + set_buffer_uptodate(bh); + } + + if (!bh->b_data) { + free_buffer_head(bh); + bh = NULL; + goto errorout; + } + + 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", + Vcb, atomic_read(&g_jbh.bh_count), block, bh, bh->b_data)); + + spin_lock_irqsave(&bdev->bd_bh_lock, irql); + + /* do search again here */ + tbh = buffer_head_search(bdev, block); + if (tbh) { + get_bh(tbh); + spin_unlock_irqrestore(&bdev->bd_bh_lock, irql); + free_buffer_head(bh); + bh = tbh; + goto errorout; + } else { + buffer_head_insert(bdev, bh); + } + + spin_unlock_irqrestore(&bdev->bd_bh_lock, irql); + + /* we get it */ +errorout: + + return bh; +} + +int submit_bh(int rw, struct buffer_head *bh) +{ + struct block_device *bdev = bh->b_bdev; + PEXT2_VCB Vcb = bdev->bd_priv; + PVOID Buffer; + LARGE_INTEGER Offset; + + ASSERT(Vcb->Identifier.Type == EXT2VCB); + ASSERT(bh->b_data && bh->b_bcb); + + if (rw == WRITE) { + + if (IsVcbReadOnly(Vcb)) { + goto errorout; + } + + SetFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED); + Offset.QuadPart = ((LONGLONG)bh->b_blocknr) << BLOCK_BITS; + + CcSetDirtyPinnedData(bh->b_bcb, NULL); + Ext2AddBlockExtent( Vcb, NULL, + (ULONG)bh->b_blocknr, + (ULONG)bh->b_blocknr, + (bh->b_size >> BLOCK_BITS)); + } else { + DbgBreak(); + } + +errorout: + + unlock_buffer(bh); + put_bh(bh); + return 0; +} + +struct buffer_head * +__getblk( + struct block_device * bdev, + sector_t block, + unsigned long size +) +{ + return get_block_bh(bdev, block, size, 0); +} + void __brelse(struct buffer_head *bh) { struct block_device *bdev = bh->b_bdev; @@ -636,6 +783,7 @@ void __brelse(struct buffer_head *bh) atomic_dec(&g_jbh.bh_count); } + void __bforget(struct buffer_head *bh) { clear_buffer_dirty(bh); diff --git a/reactos/drivers/filesystems/ext2/src/lock.c b/reactos/drivers/filesystems/ext2/src/lock.c index 82d15a89ddc..640162aeed5 100644 --- a/reactos/drivers/filesystems/ext2/src/lock.c +++ b/reactos/drivers/filesystems/ext2/src/lock.c @@ -24,10 +24,10 @@ extern PEXT2_GLOBAL Ext2Global; NTSTATUS Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext) { - PDEVICE_OBJECT DeviceObject; - PFILE_OBJECT FileObject; - PEXT2_FCB Fcb; - PIRP Irp; + PDEVICE_OBJECT DeviceObject = NULL; + PFILE_OBJECT FileObject = NULL; + PEXT2_FCB Fcb = NULL; + PIRP Irp = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; BOOLEAN CompleteContext = TRUE; diff --git a/reactos/drivers/filesystems/ext2/src/memory.c b/reactos/drivers/filesystems/ext2/src/memory.c index 37129c2d313..da91dc12a88 100644 --- a/reactos/drivers/filesystems/ext2/src/memory.c +++ b/reactos/drivers/filesystems/ext2/src/memory.c @@ -138,8 +138,6 @@ Ext2AllocateFcb ( { PEXT2_FCB Fcb; - ASSERT(!IsMcbSymLink(Mcb)); - Fcb = (PEXT2_FCB) ExAllocateFromNPagedLookasideList( &(Ext2Global->Ext2FcbLookasideList)); @@ -216,7 +214,7 @@ Ext2FreeFcb (IN PEXT2_FCB Fcb) #endif if ((Fcb->Mcb->Identifier.Type == EXT2MCB) && - (Fcb->Mcb->Identifier.Size == sizeof(EXT2_MCB))) { + (Fcb->Mcb->Identifier.Size == sizeof(EXT2_MCB))) { ASSERT (Fcb->Mcb->Fcb == Fcb); if (IsMcbSpecialFile(Fcb->Mcb) || IsFileDeleted(Fcb->Mcb)) { @@ -283,7 +281,7 @@ Ext2RemoveFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb) } PEXT2_CCB -Ext2AllocateCcb (PEXT2_MCB SymLink) +Ext2AllocateCcb (ULONG Flags, PEXT2_MCB SymLink) { PEXT2_CCB Ccb; @@ -299,6 +297,7 @@ Ext2AllocateCcb (PEXT2_MCB SymLink) Ccb->Identifier.Type = EXT2CCB; Ccb->Identifier.Size = sizeof(EXT2_CCB); + Ccb->Flags = Flags; Ccb->SymLink = SymLink; if (SymLink) { @@ -1187,7 +1186,7 @@ Ext2BuildExtents( NTSTATUS Status = STATUS_SUCCESS; PEXT2_EXTENT Extent = NULL; - PEXT2_EXTENT List = *Chain; + PEXT2_EXTENT List = *Chain = NULL; if (!IsZoneInited(Mcb)) { Status = Ext2InitializeZone(IrpContext, Vcb, Mcb); @@ -1246,7 +1245,7 @@ Ext2BuildExtents( &Mapped ); if (!NT_SUCCESS(Status)) { - goto errorout; + break; } /* skip wrong blocks, in case wrongly treating symlink @@ -1272,6 +1271,11 @@ Ext2BuildExtents( Length = Size; } + if (0 == Length) { + DbgBreak(); + break; + } + Start += Mapped; Offset = (ULONGLONG)Start << BLOCK_BITS; @@ -1288,7 +1292,8 @@ Ext2BuildExtents( Extent = Ext2AllocateExtent(); if (!Extent) { Status = STATUS_INSUFFICIENT_RESOURCES; - goto errorout; + DbgBreak(); + break; } Extent->Lba = Lba; @@ -1303,14 +1308,16 @@ Ext2BuildExtents( *Chain = List = Extent; } } + } else { + if (bAlloc) { + DbgBreak(); + } } Total += Length; Size -= Length; } -errorout: - return Status; } @@ -1800,29 +1807,23 @@ Ext2CleanupAllMcbs(PEXT2_VCB Vcb) BOOLEAN Ext2CheckSetBlock(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, LONGLONG Block) { - PEXT2_GROUP_DESC gd; - ULONG Group, dwBlk, Length; - - RTL_BITMAP BlockBitmap; - PVOID BitmapCache; - PBCB BitmapBcb; - - LARGE_INTEGER Offset; - - BOOLEAN bModified = FALSE; - - - Group = (ULONG)(Block - EXT2_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP; + PEXT2_GROUP_DESC gd; + struct buffer_head *gb = NULL; + struct buffer_head *bh = NULL; + ULONG group, dwBlk, Length; + RTL_BITMAP bitmap; + BOOLEAN bModified = FALSE; + + group = (ULONG)(Block - EXT2_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP; dwBlk = (ULONG)(Block - EXT2_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP; - gd = ext4_get_group_desc(&Vcb->sb, Group, NULL); + gd = ext4_get_group_desc(&Vcb->sb, group, &gb); if (!gd) { return FALSE; } - Offset.QuadPart = ext4_block_bitmap(&Vcb->sb, gd); - Offset.QuadPart <<= BLOCK_BITS; + bh = sb_getblk(&Vcb->sb, ext4_block_bitmap(&Vcb->sb, gd)); - if (Group == Vcb->sbi.s_groups_count - 1) { + if (group == Vcb->sbi.s_groups_count - 1) { Length = (ULONG)(TOTAL_BLOCKS % BLOCKS_PER_GROUP); /* s_blocks_count is integer multiple of s_blocks_per_group */ @@ -1832,43 +1833,23 @@ Ext2CheckSetBlock(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, LONGLONG Block) Length = BLOCKS_PER_GROUP; } - if (dwBlk >= Length) - return FALSE; - - if (!CcPinRead( Vcb->Volume, - &Offset, - Vcb->BlockSize, - PIN_WAIT, - &BitmapBcb, - &BitmapCache ) ) { - - DEBUG(DL_ERR, ( "Ext2CheckSetBlock: Failed to PinLock block %xh ...\n", - ext4_block_bitmap(&Vcb->sb, gd))); + if (dwBlk >= Length) { + fini_bh(&gb); + fini_bh(&bh); return FALSE; } - RtlInitializeBitMap( &BlockBitmap, - BitmapCache, - Length ); + RtlInitializeBitMap(&bitmap, (PULONG)bh->b_data, Length); - if (RtlCheckBit(&BlockBitmap, dwBlk) == 0) { + if (RtlCheckBit(&bitmap, dwBlk) == 0) { DbgBreak(); - RtlSetBits(&BlockBitmap, dwBlk, 1); + RtlSetBits(&bitmap, dwBlk, 1); bModified = TRUE; + mark_buffer_dirty(bh); } - if (bModified) { - CcSetDirtyPinnedData(BitmapBcb, NULL ); - Ext2AddVcbExtent(Vcb, Offset.QuadPart, (LONGLONG)BLOCK_SIZE); - } - - { - CcUnpinData(BitmapBcb); - BitmapBcb = NULL; - BitmapCache = NULL; - - RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP)); - } + fini_bh(&gb); + fini_bh(&bh); return (!bModified); } @@ -1881,8 +1862,9 @@ Ext2CheckBitmapConsistency(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb) for (i = 0; i < Vcb->sbi.s_groups_count; i++) { PEXT2_GROUP_DESC gd; + struct buffer_head *bh = NULL; - gd = ext4_get_group_desc(&Vcb->sb, i, NULL); + gd = ext4_get_group_desc(&Vcb->sb, i, &bh); if (!gd) continue; Ext2CheckSetBlock(IrpContext, Vcb, ext4_block_bitmap(&Vcb->sb, gd)); @@ -1900,6 +1882,8 @@ Ext2CheckBitmapConsistency(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb) for (j = 0; j < InodeBlocks; j++ ) Ext2CheckSetBlock(IrpContext, Vcb, ext4_inode_table(&Vcb->sb, gd) + j); + + fini_bh(&bh); } return TRUE; @@ -2687,7 +2671,7 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext, } if (ExtentsInitialized) { - Ext2PutGroup(Vcb); + Ext2DropGroup(Vcb); if (Vcb->bd.bd_bh_cache) kmem_cache_destroy(Vcb->bd.bd_bh_cache); FsRtlUninitializeLargeMcb(&(Vcb->Extents)); @@ -2764,7 +2748,7 @@ Ext2DestroyVcb (IN PEXT2_VCB Vcb) Ext2CleanupAllMcbs(Vcb); - Ext2PutGroup(Vcb); + Ext2DropGroup(Vcb); if (Vcb->bd.bd_bh_cache) kmem_cache_destroy(Vcb->bd.bd_bh_cache); @@ -2776,7 +2760,8 @@ Ext2DestroyVcb (IN PEXT2_VCB Vcb) if (IsFlagOn(Vcb->Flags, VCB_NEW_VPB)) { ASSERT(Vcb->Vpb2 != NULL); - Ext2FreePool(Vcb->Vpb2, TAG_VPB); + DEBUG(DL_DBG, ("Ext2DestroyVcb: Vpb2 to be freed: %p\n", Vcb->Vpb2)); + ExFreePoolWithTag(Vcb->Vpb2, TAG_VPB); DEC_MEM_COUNT(PS_VPB, Vcb->Vpb2, sizeof(VPB)); Vcb->Vpb2 = NULL; } diff --git a/reactos/drivers/filesystems/ext2/src/misc.c b/reactos/drivers/filesystems/ext2/src/misc.c index 1fbbc34cb59..8f26a340ea2 100644 --- a/reactos/drivers/filesystems/ext2/src/misc.c +++ b/reactos/drivers/filesystems/ext2/src/misc.c @@ -382,10 +382,13 @@ int Ext2LinuxError (NTSTATUS Status) case STATUS_HOST_UNREACHABLE: return (-EHOSTUNREACH); + case STATUS_CANT_WAIT: case STATUS_PENDING: - case STATUS_DEVICE_NOT_READY: return (-EAGAIN); + case STATUS_DEVICE_NOT_READY: + return (-EIO); + case STATUS_CANCELLED: case STATUS_REQUEST_ABORTED: return (-EINTR); @@ -503,7 +506,7 @@ NTSTATUS Ext2WinntError(int rc) return STATUS_HOST_UNREACHABLE; case -EAGAIN: - return STATUS_DEVICE_NOT_READY; + return STATUS_CANT_WAIT; case -EINTR: return STATUS_CANCELLED; @@ -527,4 +530,4 @@ BOOLEAN Ext2IsDotDot(PUNICODE_STRING name) { return (name->Length == 4 && name->Buffer[0] == L'.' && name->Buffer[1] == L'.'); -} \ No newline at end of file +} diff --git a/reactos/drivers/filesystems/ext2/src/pnp.c b/reactos/drivers/filesystems/ext2/src/pnp.c index 82c26ad94c1..1afb9f9b1e9 100644 --- a/reactos/drivers/filesystems/ext2/src/pnp.c +++ b/reactos/drivers/filesystems/ext2/src/pnp.c @@ -63,7 +63,7 @@ Ext2Pnp (IN PEXT2_IRP_CONTEXT IrpContext) PIRP Irp; PIO_STACK_LOCATION IrpSp; - PEXT2_VCB Vcb; + PEXT2_VCB Vcb = NULL; PDEVICE_OBJECT DeviceObject; _SEH2_TRY { @@ -394,4 +394,4 @@ Ext2PnpCancelRemove ( return Status; } -#endif //(_WIN32_WINNT >= 0x0500) \ No newline at end of file +#endif //(_WIN32_WINNT >= 0x0500) diff --git a/reactos/drivers/filesystems/ext2/src/read.c b/reactos/drivers/filesystems/ext2/src/read.c index b78c754b16a..660fd5d72f9 100644 --- a/reactos/drivers/filesystems/ext2/src/read.c +++ b/reactos/drivers/filesystems/ext2/src/read.c @@ -65,15 +65,15 @@ Ext2ReadVolume (IN PEXT2_IRP_CONTEXT IrpContext) { NTSTATUS Status = STATUS_UNSUCCESSFUL; - PEXT2_VCB Vcb; - PEXT2_CCB Ccb; - PEXT2_FCBVCB FcbOrVcb; - PFILE_OBJECT FileObject; + PEXT2_VCB Vcb = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_FCBVCB FcbOrVcb = NULL; + PFILE_OBJECT FileObject = NULL; - PDEVICE_OBJECT DeviceObject; + PDEVICE_OBJECT DeviceObject = NULL; PIRP Irp = NULL; - PIO_STACK_LOCATION IoStackLocation; + PIO_STACK_LOCATION IoStackLocation = NULL; ULONG Length; LARGE_INTEGER ByteOffset; @@ -347,11 +347,9 @@ Ext2ReadInode ( /* handle fast symlinks */ - if (S_ISLNK(Mcb->Inode.i_mode) && - Mcb->Inode.i_size < EXT2_LINKLEN_IN_INODE) { + if (S_ISLNK(Mcb->Inode.i_mode) && 0 == Mcb->Inode.i_blocks) { PUCHAR Data = (PUCHAR) (&Mcb->Inode.i_block[0]); - if (!Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; @@ -474,15 +472,15 @@ Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext) { NTSTATUS Status = STATUS_UNSUCCESSFUL; - PEXT2_VCB Vcb; - PEXT2_FCB Fcb; - PEXT2_CCB Ccb; - PFILE_OBJECT FileObject; + PEXT2_VCB Vcb = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PFILE_OBJECT FileObject = NULL; - PDEVICE_OBJECT DeviceObject; + PDEVICE_OBJECT DeviceObject = NULL; - PIRP Irp; - PIO_STACK_LOCATION IoStackLocation; + PIRP Irp = NULL; + PIO_STACK_LOCATION IoStackLocation = NULL; ULONG Length; ULONG ReturnedLength = 0; @@ -534,6 +532,11 @@ Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext) DEBUG(DL_INF, ("Ext2ReadFile: reading %wZ Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n", &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache)); + if (IsSpecialFile(Fcb) || IsInodeSymLink(Fcb->Inode) ) { + Status = STATUS_INVALID_DEVICE_REQUEST; + _SEH2_LEAVE; + } + if ((IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) || IsFileDeleted(Fcb->Mcb)) { Status = STATUS_FILE_DELETED; @@ -546,9 +549,13 @@ Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext) _SEH2_LEAVE; } - if (Nocache && - (ByteOffset.LowPart & (SECTOR_SIZE - 1) || - Length & (SECTOR_SIZE - 1))) { + if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION && + ByteOffset.HighPart == -1) { + ByteOffset = FileObject->CurrentByteOffset; + } + + if (Nocache && (ByteOffset.LowPart & (SECTOR_SIZE - 1) || + Length & (SECTOR_SIZE - 1))) { Status = STATUS_INVALID_PARAMETER; DbgBreak(); _SEH2_LEAVE; @@ -561,17 +568,6 @@ Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext) _SEH2_LEAVE; } - if (!PagingIo && Nocache && (FileObject->SectionObjectPointer->DataSectionObject != NULL)) { - CcFlushCache( FileObject->SectionObjectPointer, - &ByteOffset, - Length, - &Irp->IoStatus ); - - if (!NT_SUCCESS(Irp->IoStatus.Status)) { - _SEH2_LEAVE; - } - } - ReturnedLength = Length; if (PagingIo) { @@ -596,6 +592,15 @@ Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext) } MainResourceAcquired = TRUE; + if (FileObject->SectionObjectPointer->DataSectionObject != NULL) { + CcFlushCache( FileObject->SectionObjectPointer, + &ByteOffset, + Length, + &Irp->IoStatus ); + if (!NT_SUCCESS(Irp->IoStatus.Status)) + _SEH2_LEAVE; + } + } else { if (!ExAcquireResourceSharedLite( diff --git a/reactos/drivers/filesystems/ext2/src/volinfo.c b/reactos/drivers/filesystems/ext2/src/volinfo.c index 895da8fc4c8..8840482787d 100644 --- a/reactos/drivers/filesystems/ext2/src/volinfo.c +++ b/reactos/drivers/filesystems/ext2/src/volinfo.c @@ -27,13 +27,13 @@ NTSTATUS Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; + PEXT2_VCB Vcb = NULL; + PIRP Irp = NULL; + PIO_STACK_LOCATION IoStackLocation = NULL; + PVOID Buffer; + ULONG Length; NTSTATUS Status = STATUS_UNSUCCESSFUL; - PEXT2_VCB Vcb; - PIRP Irp; - PIO_STACK_LOCATION IoStackLocation; FS_INFORMATION_CLASS FsInformationClass; - ULONG Length; - PVOID Buffer; BOOLEAN VcbResourceAcquired = FALSE; _SEH2_TRY { @@ -186,8 +186,9 @@ Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext) FsAttrInfo = (PFILE_FS_ATTRIBUTE_INFORMATION) Buffer; - FsAttrInfo->FileSystemAttributes = - FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES; + FsAttrInfo->FileSystemAttributes = FILE_SUPPORTS_HARD_LINKS | + FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | + FILE_SUPPORTS_REPARSE_POINTS; if (IsVcbReadOnly(Vcb)) { FsAttrInfo->FileSystemAttributes |= FILE_READ_ONLY_VOLUME; } @@ -292,7 +293,7 @@ Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; - PEXT2_VCB Vcb; + PEXT2_VCB Vcb = NULL; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; FS_INFORMATION_CLASS FsInformationClass; @@ -405,4 +406,4 @@ Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext) } _SEH2_END; return Status; -} \ No newline at end of file +} diff --git a/reactos/drivers/filesystems/ext2/src/write.c b/reactos/drivers/filesystems/ext2/src/write.c index fe50d349486..a3ddcbc5771 100644 --- a/reactos/drivers/filesystems/ext2/src/write.c +++ b/reactos/drivers/filesystems/ext2/src/write.c @@ -175,9 +175,8 @@ Ext2ZeroData ( PBCB Bcb; PVOID Ptr; ULONG Size; -#ifndef __REACTOS__ BOOLEAN rc = TRUE; -#endif + ASSERT (End && Start && End->QuadPart > Start->QuadPart); Fcb = (PEXT2_FCB) FileObject->FsContext; @@ -195,7 +194,13 @@ Ext2ZeroData ( } /* clear data in range [Start, End) */ - return CcZeroData(FileObject, Start, End, Ext2CanIWait()); + _SEH2_TRY { + rc = CcZeroData(FileObject, Start, End, Ext2CanIWait()); + } _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { + DbgBreak(); + } _SEH2_END; + + return rc; } VOID @@ -212,15 +217,15 @@ Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext) { NTSTATUS Status = STATUS_UNSUCCESSFUL; - PEXT2_VCB Vcb; - PEXT2_CCB Ccb; - PEXT2_FCBVCB FcbOrVcb; - PFILE_OBJECT FileObject; + PEXT2_VCB Vcb = NULL; + PEXT2_CCB Ccb = NULL; + PEXT2_FCBVCB FcbOrVcb = NULL; + PFILE_OBJECT FileObject = NULL; - PDEVICE_OBJECT DeviceObject; + PDEVICE_OBJECT DeviceObject = NULL; PIRP Irp = NULL; - PIO_STACK_LOCATION IoStackLocation; + PIO_STACK_LOCATION IoStackLocation = NULL; ULONG Length; LARGE_INTEGER ByteOffset; @@ -646,7 +651,7 @@ Ext2WriteInode ( IN ULONG Size, IN BOOLEAN bDirectIo, OUT PULONG BytesWritten -) + ) { PEXT2_EXTENT Chain = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; @@ -663,7 +668,7 @@ Ext2WriteInode ( Mcb, Offset, Size, - IsMcbDirectory(Mcb) ? FALSE : TRUE, + S_ISDIR(Mcb->Inode.i_mode) ? FALSE : TRUE, &Chain ); @@ -730,19 +735,20 @@ Ext2WriteInode ( return Status; } + NTSTATUS Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext) { - PEXT2_VCB Vcb; - PEXT2_FCB Fcb; - PEXT2_CCB Ccb; - PFILE_OBJECT FileObject; + PEXT2_VCB Vcb = NULL; + PEXT2_FCB Fcb = NULL; + PEXT2_CCB Ccb = NULL; + PFILE_OBJECT FileObject = NULL; - PDEVICE_OBJECT DeviceObject; + PDEVICE_OBJECT DeviceObject = NULL; - PIRP Irp; - PIO_STACK_LOCATION IoStackLocation; - PUCHAR Buffer; + PIRP Irp = NULL; + PIO_STACK_LOCATION IoStackLocation = NULL; + PUCHAR Buffer = NULL; LARGE_INTEGER ByteOffset; ULONG ReturnedLength = 0; @@ -803,7 +809,7 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext) DEBUG(DL_INF, ("Ext2WriteFile: %wZ Offset=%I64xh Length=%xh Paging=%xh Nocache=%xh\n", &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache)); - if (IsSpecialFile(Fcb)) { + if (IsSpecialFile(Fcb) || IsInodeSymLink(Fcb->Inode) ) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; } @@ -820,8 +826,16 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext) _SEH2_LEAVE; } - if (Nocache && ( (ByteOffset.LowPart & (SECTOR_SIZE - 1)) || - (Length & (SECTOR_SIZE - 1))) ) { + if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION && + ByteOffset.HighPart == -1) { + ByteOffset = FileObject->CurrentByteOffset; + } else if (IsWritingToEof(ByteOffset)) { + ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart; + } + + if (Nocache && !PagingIo && + ( (ByteOffset.LowPart & (SECTOR_SIZE - 1)) || + (Length & (SECTOR_SIZE - 1))) ) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } @@ -864,10 +878,6 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext) } } - if (IsWritingToEof(ByteOffset)) { - ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart; - } - if (IsDirectory(Fcb) && !PagingIo) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; @@ -904,18 +914,24 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext) } PagingIoResourceAcquired = TRUE; - if ( (ByteOffset.QuadPart + Length) > Fcb->Header.AllocationSize.QuadPart) { + if ( (ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) { - if ( ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) { + if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) { - Status = STATUS_END_OF_FILE; + Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; _SEH2_LEAVE; } else { - Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart); + ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); + if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart) + Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart); } + + } else { + + ReturnedLength = Length; } } else { @@ -1049,9 +1065,9 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext) &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart, Fcb->Header.AllocationSize.QuadPart)); } - } - ReturnedLength = Length; + ReturnedLength = Length; + } if (!Nocache) { @@ -1138,19 +1154,17 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext) } else { if (!PagingIo && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) { - if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) { - if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) { - - /* let this irp wait, since it has to be synchronous */ - SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); - rc = Ext2ZeroData(IrpContext, Vcb, FileObject, - &Fcb->Header.ValidDataLength, - &ByteOffset); - if (!rc) { - Status = STATUS_PENDING; - DbgBreak(); - _SEH2_LEAVE; - } + if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) { + + /* let this irp wait, since it has to be synchronous */ + SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); + rc = Ext2ZeroData(IrpContext, Vcb, FileObject, + &Fcb->Header.ValidDataLength, + &ByteOffset); + if (!rc) { + Status = STATUS_PENDING; + DbgBreak(); + _SEH2_LEAVE; } } } @@ -1180,20 +1194,22 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext) Irp = IrpContext->Irp; - if (NT_SUCCESS(Status) && !PagingIo && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) { + if (NT_SUCCESS(Status) && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) { if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) { FileSizesChanged = TRUE; if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) { + if (!PagingIo) + Fcb->Header.FileSize.QuadPart = ByteOffset.QuadPart + Length; Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart; } else { if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length) Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length; } - if (CcIsFileCached(FileObject)) { + if (!PagingIo && CcIsFileCached(FileObject)) { CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); } @@ -1215,7 +1231,7 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext) /* * in case we got excpetions, we need revert MajorFunction - * back to IRP_MJ_WRITE. The reason we do this, if to tell + * back to IRP_MJ_WRITE. The reason we do this, is to tell * Ext2ExpandFile to allocate unwritten extent or don't add * new blocks for indirect files. */ -- 2.17.1