mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 19:52:56 +00:00
[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
This commit is contained in:
parent
0a5da2af17
commit
a15c1b7b67
35 changed files with 2048 additions and 573 deletions
|
@ -56,6 +56,7 @@ list(APPEND SOURCE
|
||||||
src/nls/nls_koi8-ru.c
|
src/nls/nls_koi8-ru.c
|
||||||
src/nls/nls_koi8-u.c
|
src/nls/nls_koi8-u.c
|
||||||
src/nls/nls_utf8.c
|
src/nls/nls_utf8.c
|
||||||
|
src/access.c
|
||||||
src/block.c
|
src/block.c
|
||||||
src/cleanup.c
|
src/cleanup.c
|
||||||
src/close.c
|
src/close.c
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* FILE: Ext2fs.h
|
* FILE: Ext2fs.h
|
||||||
* PURPOSE: Header file: ext2 structures
|
* PURPOSE: Header file: ext2 structures
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://ext2.yeah.net
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -18,7 +18,8 @@
|
||||||
#include <ndk/rtlfuncs.h>
|
#include <ndk/rtlfuncs.h>
|
||||||
#include <pseh/pseh2.h>
|
#include <pseh/pseh2.h>
|
||||||
#endif
|
#endif
|
||||||
#include "stdio.h"
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <linux/ext2_fs.h>
|
#include <linux/ext2_fs.h>
|
||||||
#include <linux/ext3_fs.h>
|
#include <linux/ext3_fs.h>
|
||||||
|
@ -46,9 +47,14 @@
|
||||||
|
|
||||||
/* STRUCTS & CONSTS******************************************************/
|
/* STRUCTS & CONSTS******************************************************/
|
||||||
|
|
||||||
#define EXT2FSD_VERSION "0.62"
|
#define EXT2FSD_VERSION "0.63"
|
||||||
|
|
||||||
|
|
||||||
|
/* WDK DEFINITIONS ******************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/* COMPILER SWITCH / OPTIONS ********************************************/
|
||||||
|
|
||||||
//
|
//
|
||||||
// Ext2Fsd build options
|
// Ext2Fsd build options
|
||||||
//
|
//
|
||||||
|
@ -378,10 +384,25 @@ Ext2ClearFlag(PULONG Flags, ULONG FlagBit)
|
||||||
#define Ext2SetOwnerReadOnly(m) do {(m) &= ~S_IWUSR;} while(0)
|
#define Ext2SetOwnerReadOnly(m) do {(m) &= ~S_IWUSR;} while(0)
|
||||||
|
|
||||||
#define Ext2IsOwnerWritable(m) (((m) & S_IWUSR) == S_IWUSR)
|
#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 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
|
* We need 8-bytes aligned for all the sturctures
|
||||||
* It's a must for all ERESOURCE allocations
|
* It's a must for all ERESOURCE allocations
|
||||||
|
@ -690,6 +711,14 @@ typedef struct _EXT2_VCB {
|
||||||
BOOLEAN bHidingSuffix;
|
BOOLEAN bHidingSuffix;
|
||||||
CHAR sHidingSuffix[HIDINGPAT_LEN];
|
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 */
|
/* mountpoint: symlink to DesDevices */
|
||||||
UCHAR DrvLetter;
|
UCHAR DrvLetter;
|
||||||
|
|
||||||
|
@ -713,6 +742,8 @@ typedef struct _EXT2_VCB {
|
||||||
#define VCB_DISMOUNT_PENDING 0x00000008
|
#define VCB_DISMOUNT_PENDING 0x00000008
|
||||||
#define VCB_NEW_VPB 0x00000010
|
#define VCB_NEW_VPB 0x00000010
|
||||||
#define VCB_BEING_CLOSED 0x00000020
|
#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_FORCE_WRITING 0x00004000
|
||||||
#define VCB_DEVICE_REMOVED 0x00008000
|
#define VCB_DEVICE_REMOVED 0x00008000
|
||||||
|
@ -816,7 +847,7 @@ struct _EXT2_MCB {
|
||||||
|
|
||||||
// Link List Info
|
// Link List Info
|
||||||
PEXT2_MCB Parent; // Parent
|
PEXT2_MCB Parent; // Parent
|
||||||
PEXT2_MCB Next; // Brothers
|
PEXT2_MCB Next; // Siblings
|
||||||
|
|
||||||
union {
|
union {
|
||||||
PEXT2_MCB Child; // Children Mcb nodes
|
PEXT2_MCB Child; // Children Mcb nodes
|
||||||
|
@ -943,7 +974,7 @@ typedef struct _EXT2_CCB {
|
||||||
#define CCB_FROM_POOL 0x00000001
|
#define CCB_FROM_POOL 0x00000001
|
||||||
#define CCB_VOLUME_DASD_PURGE 0x00000002
|
#define CCB_VOLUME_DASD_PURGE 0x00000002
|
||||||
#define CCB_LAST_WRITE_UPDATED 0x00000004
|
#define CCB_LAST_WRITE_UPDATED 0x00000004
|
||||||
|
#define CCB_OPEN_REPARSE_POINT 0x00000008
|
||||||
#define CCB_DELETE_ON_CLOSE 0x00000010
|
#define CCB_DELETE_ON_CLOSE 0x00000010
|
||||||
|
|
||||||
#define CCB_ALLOW_EXTENDED_DASD_IO 0x80000000
|
#define CCB_ALLOW_EXTENDED_DASD_IO 0x80000000
|
||||||
|
@ -1102,6 +1133,14 @@ typedef struct _EXT2_FILLDIR_CONTEXT {
|
||||||
BOOLEAN efc_single;
|
BOOLEAN efc_single;
|
||||||
} EXT2_FILLDIR_CONTEXT, *PEXT2_FILLDIR_CONTEXT;
|
} 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
|
// Block.c
|
||||||
//
|
//
|
||||||
|
@ -1268,7 +1307,7 @@ Ext2FollowLink (
|
||||||
IN PEXT2_VCB Vcb,
|
IN PEXT2_VCB Vcb,
|
||||||
IN PEXT2_MCB Parent,
|
IN PEXT2_MCB Parent,
|
||||||
IN PEXT2_MCB Mcb,
|
IN PEXT2_MCB Mcb,
|
||||||
IN USHORT Linkdep
|
IN ULONG Linkdep
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -1287,6 +1326,9 @@ Ext2IsSpecialSystemFile(
|
||||||
IN BOOLEAN bDirectory
|
IN BOOLEAN bDirectory
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#define EXT2_LOOKUP_FLAG_MASK (0xFF00000)
|
||||||
|
#define EXT2_LOOKUP_NOT_FOLLOW (0x8000000)
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2LookupFile (
|
Ext2LookupFile (
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
|
@ -1294,7 +1336,7 @@ Ext2LookupFile (
|
||||||
IN PUNICODE_STRING FullName,
|
IN PUNICODE_STRING FullName,
|
||||||
IN PEXT2_MCB Parent,
|
IN PEXT2_MCB Parent,
|
||||||
OUT PEXT2_MCB * Ext2Mcb,
|
OUT PEXT2_MCB * Ext2Mcb,
|
||||||
IN USHORT Linkdep
|
IN ULONG Linkdep
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -1733,6 +1775,9 @@ Ext2LoadGroup(IN PEXT2_VCB Vcb);
|
||||||
VOID
|
VOID
|
||||||
Ext2PutGroup(IN PEXT2_VCB Vcb);
|
Ext2PutGroup(IN PEXT2_VCB Vcb);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
Ext2DropGroup(IN PEXT2_VCB Vcb);
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
Ext2SaveGroup(
|
Ext2SaveGroup(
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
|
@ -1884,6 +1929,14 @@ Ext2AddEntry (
|
||||||
OUT struct dentry **dentry
|
OUT struct dentry **dentry
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
Ext2SetFileType (
|
||||||
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
|
IN PEXT2_VCB Vcb,
|
||||||
|
IN PEXT2_FCB Dcb,
|
||||||
|
IN PEXT2_MCB Mcb
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2RemoveEntry (
|
Ext2RemoveEntry (
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
|
@ -2116,6 +2169,14 @@ Ext2SetRenameInfo(
|
||||||
PEXT2_CCB Ccb
|
PEXT2_CCB Ccb
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
Ext2SetLinkInfo(
|
||||||
|
PEXT2_IRP_CONTEXT IrpContext,
|
||||||
|
PEXT2_VCB Vcb,
|
||||||
|
PEXT2_FCB Fcb,
|
||||||
|
PEXT2_CCB Ccb
|
||||||
|
);
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
Ext2InodeType(PEXT2_MCB Mcb);
|
Ext2InodeType(PEXT2_MCB Mcb);
|
||||||
|
|
||||||
|
@ -2161,6 +2222,34 @@ Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext);
|
||||||
// Fsctl.c
|
// 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
|
// MountPoint process workitem
|
||||||
//
|
//
|
||||||
|
@ -2400,7 +2489,7 @@ VOID
|
||||||
Ext2RemoveFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb);
|
Ext2RemoveFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb);
|
||||||
|
|
||||||
PEXT2_CCB
|
PEXT2_CCB
|
||||||
Ext2AllocateCcb (PEXT2_MCB SymLink);
|
Ext2AllocateCcb (ULONG Flags, PEXT2_MCB SymLink);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2FreeMcb (
|
Ext2FreeMcb (
|
||||||
|
|
|
@ -36,7 +36,7 @@ struct ext3_sb_info {
|
||||||
int s_addr_per_block_bits;
|
int s_addr_per_block_bits;
|
||||||
int s_desc_per_block_bits;
|
int s_desc_per_block_bits;
|
||||||
|
|
||||||
struct buffer_head **s_group_desc;
|
ext3_fsblk_t *s_group_desc;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
unsigned long s_frag_size; /* Size of a fragment in bytes */
|
unsigned long s_frag_size; /* Size of a fragment in bytes */
|
||||||
|
|
|
@ -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,
|
unsigned long max_blocks, struct buffer_head *bh_result,
|
||||||
int create, int flags);
|
int create, int flags);
|
||||||
int ext4_ext_tree_init(void *icb, handle_t *handle, struct inode *inode);
|
int ext4_ext_tree_init(void *icb, handle_t *handle, struct inode *inode);
|
||||||
int ext4_ext_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 */
|
#endif /* _LINUX_EXT4_EXT */
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
|
#include <linux/rbtree.h>
|
||||||
|
|
||||||
//
|
//
|
||||||
// kdev
|
// kdev
|
||||||
|
@ -74,6 +75,25 @@ struct super_block {
|
||||||
void *s_fs_info;
|
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 {
|
struct inode {
|
||||||
__u32 i_ino; /* inode number */
|
__u32 i_ino; /* inode number */
|
||||||
loff_t i_size; /* size */
|
loff_t i_size; /* size */
|
||||||
|
@ -94,6 +114,9 @@ struct inode {
|
||||||
|
|
||||||
struct super_block *i_sb; /* super_block */
|
struct super_block *i_sb; /* super_block */
|
||||||
void *i_priv; /* EXT2_MCB */
|
void *i_priv; /* EXT2_MCB */
|
||||||
|
|
||||||
|
__u16 i_extra_isize; /* extra fields' size */
|
||||||
|
__u64 i_file_acl;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -153,4 +176,4 @@ void iget(struct inode *inode);
|
||||||
void iput(struct inode *inode);
|
void iput(struct inode *inode);
|
||||||
ULONGLONG bmap(struct inode *i, ULONGLONG b);
|
ULONGLONG bmap(struct inode *i, ULONGLONG b);
|
||||||
|
|
||||||
#endif /*_LINUX_FS_INCLUDE_*/
|
#endif /*_LINUX_FS_INCLUDE_*/
|
||||||
|
|
|
@ -36,6 +36,36 @@
|
||||||
|
|
||||||
#define journal_oom_retry 1
|
#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
|
* Define JBD_PARANIOD_IOFAIL to cause a kernel BUG() if ext3 finds
|
||||||
* certain classes of error which can occur due to failed IOs. Under
|
* certain classes of error which can occur due to failed IOs. Under
|
||||||
|
@ -539,7 +569,7 @@ struct transaction_s
|
||||||
/*
|
/*
|
||||||
* Protects info related to handles
|
* Protects info related to handles
|
||||||
*/
|
*/
|
||||||
spinlock_t t_handle_lock;
|
jbdlock_t t_handle_lock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Number of outstanding updates running on this transaction
|
* Number of outstanding updates running on this transaction
|
||||||
|
@ -657,7 +687,7 @@ struct journal_s
|
||||||
/*
|
/*
|
||||||
* Protect the various scalars in the journal
|
* 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]
|
* 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.
|
* 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 */
|
/* Optional inode where we store the journal. If present, all */
|
||||||
/* journal block numbers are mapped into this inode via */
|
/* 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
|
* The revoke table: maintains the list of revoked blocks in the
|
||||||
* current transaction. [j_revoke_lock]
|
* 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;
|
||||||
struct jbd_revoke_table_s *j_revoke_table[2];
|
struct jbd_revoke_table_s *j_revoke_table[2];
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* FILE: Modules.h
|
* FILE: Modules.h
|
||||||
* PURPOSE: Header file: nls structures & linux kernel ...
|
* PURPOSE: Header file: nls structures & linux kernel ...
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://ext2.yeah.net
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -15,9 +15,9 @@
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
#include <linux/rbtree.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/log2.h>
|
#include <linux/log2.h>
|
||||||
#include <linux/rbtree.h>
|
|
||||||
|
|
||||||
#if _WIN32_WINNT <= 0x500
|
#if _WIN32_WINNT <= 0x500
|
||||||
#define _WIN2K_TARGET_ 1
|
#define _WIN2K_TARGET_ 1
|
||||||
|
@ -712,7 +712,7 @@ struct buffer_head {
|
||||||
unsigned long b_state; /* buffer state bitmap (see above) */
|
unsigned long b_state; /* buffer state bitmap (see above) */
|
||||||
struct page *b_page; /* the page this bh is mapped to */
|
struct page *b_page; /* the page this bh is mapped to */
|
||||||
PMDL b_mdl; /* MDL of the locked buffer */
|
PMDL b_mdl; /* MDL of the locked buffer */
|
||||||
void *b_bcb; /* BCB of the buffer */
|
void *b_bcb; /* BCB of the buffer */
|
||||||
|
|
||||||
// kdev_t b_dev; /* device (B_FREE = free) */
|
// kdev_t b_dev; /* device (B_FREE = free) */
|
||||||
struct block_device *b_bdev; /* block device object */
|
struct block_device *b_bdev; /* block device object */
|
||||||
|
@ -940,6 +940,14 @@ static inline void brelse(struct buffer_head *bh)
|
||||||
__brelse(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)
|
static inline void bforget(struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
if (bh)
|
if (bh)
|
||||||
|
|
|
@ -94,8 +94,6 @@ static inline struct page * rb_insert_page_cache(struct inode * inode,
|
||||||
#ifndef _LINUX_RBTREE_H
|
#ifndef _LINUX_RBTREE_H
|
||||||
#define _LINUX_RBTREE_H
|
#define _LINUX_RBTREE_H
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
|
|
||||||
struct rb_node
|
struct rb_node
|
||||||
{
|
{
|
||||||
ULONG_PTR rb_parent_color;
|
ULONG_PTR rb_parent_color;
|
||||||
|
|
54
reactos/drivers/filesystems/ext2/src/access.c
Normal file
54
reactos/drivers/filesystems/ext2/src/access.c
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYRIGHT.TXT
|
||||||
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
|
* FILE: access.c
|
||||||
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include "ext2fs.h"
|
||||||
|
|
||||||
|
/* GLOBALS ***************************************************************/
|
||||||
|
|
||||||
|
extern PEXT2_GLOBAL Ext2Global;
|
||||||
|
|
||||||
|
/* DEFINITIONS *************************************************************/
|
||||||
|
|
||||||
|
int Ext2CheckInodeAccess(PEXT2_VCB Vcb, struct inode *in, int attempt)
|
||||||
|
{
|
||||||
|
int granted = 0;
|
||||||
|
|
||||||
|
uid_t uid = Vcb->uid;
|
||||||
|
gid_t gid = Vcb->gid;
|
||||||
|
|
||||||
|
if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) {
|
||||||
|
uid = Vcb->euid;
|
||||||
|
gid = Vcb->egid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uid || uid == in->i_uid) {
|
||||||
|
/* grant all access for inode owner or root */
|
||||||
|
granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute;
|
||||||
|
} else if (gid == in->i_gid) {
|
||||||
|
if (Ext2IsGroupReadOnly(in->i_mode))
|
||||||
|
granted = Ext2FileCanRead | Ext2FileCanExecute;
|
||||||
|
else if (Ext2IsGroupWritable(in->i_mode))
|
||||||
|
granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute;
|
||||||
|
} else {
|
||||||
|
if (Ext2IsOtherReadOnly(in->i_mode))
|
||||||
|
granted = Ext2FileCanRead | Ext2FileCanExecute;
|
||||||
|
else if (Ext2IsOtherWritable(in->i_mode))
|
||||||
|
granted = Ext2FileCanRead | Ext2FileCanWrite | Ext2FileCanExecute;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return IsFlagOn(granted, attempt);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Ext2CheckFileAccess(PEXT2_VCB Vcb, PEXT2_MCB Mcb, int attempt)
|
||||||
|
{
|
||||||
|
return Ext2CheckInodeAccess(Vcb, &Mcb->Inode, attempt);
|
||||||
|
}
|
|
@ -22,12 +22,12 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb = NULL;
|
||||||
PEXT2_CCB Ccb;
|
PEXT2_CCB Ccb = NULL;
|
||||||
PIRP Irp;
|
PIRP Irp = NULL;
|
||||||
PEXT2_MCB Mcb;
|
PEXT2_MCB Mcb = NULL;
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
|
@ -75,7 +75,7 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
VcbResourceAcquired =
|
VcbResourceAcquired =
|
||||||
ExAcquireResourceExclusiveLite(
|
ExAcquireResourceExclusiveLite(
|
||||||
&Vcb->MainResource,
|
&Vcb->MainResource,
|
||||||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
|
TRUE
|
||||||
);
|
);
|
||||||
|
|
||||||
if (Fcb->Identifier.Type == EXT2VCB) {
|
if (Fcb->Identifier.Type == EXT2VCB) {
|
||||||
|
@ -143,7 +143,7 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
FcbResourceAcquired =
|
FcbResourceAcquired =
|
||||||
ExAcquireResourceExclusiveLite(
|
ExAcquireResourceExclusiveLite(
|
||||||
&Fcb->MainResource,
|
&Fcb->MainResource,
|
||||||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
|
TRUE
|
||||||
);
|
);
|
||||||
|
|
||||||
ASSERT((Ccb->Identifier.Type == EXT2CCB) &&
|
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 (Fcb->Header.ValidDataLength.QuadPart < Fcb->Header.FileSize.QuadPart) {
|
||||||
if (!INODE_HAS_EXTENT(Fcb->Inode)) {
|
if (!INODE_HAS_EXTENT(Fcb->Inode)) {
|
||||||
#if EXT2_PRE_ALLOCATION_SUPPORT
|
#if EXT2_PRE_ALLOCATION_SUPPORT
|
||||||
CcZeroData(FileObject, &Fcb->Header.ValidDataLength,
|
_SEH2_TRY {
|
||||||
&Fcb->Header.AllocationSize, TRUE);
|
CcZeroData( FileObject,
|
||||||
|
&Fcb->Header.ValidDataLength,
|
||||||
|
&Fcb->Header.AllocationSize,
|
||||||
|
TRUE);
|
||||||
|
} _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
|
||||||
|
DbgBreak();
|
||||||
|
} _SEH2_END;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,7 +321,7 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
FcbResourceAcquired =
|
FcbResourceAcquired =
|
||||||
ExAcquireResourceExclusiveLite(
|
ExAcquireResourceExclusiveLite(
|
||||||
&Fcb->MainResource,
|
&Fcb->MainResource,
|
||||||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
|
TRUE
|
||||||
);
|
);
|
||||||
|
|
||||||
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
|
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
|
||||||
|
@ -329,7 +335,7 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
if (!IsDirectory(Fcb)) {
|
if (!IsDirectory(Fcb)) {
|
||||||
|
|
||||||
if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
|
if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
|
||||||
(Fcb->NonCachedOpenCount + 1 == Fcb->ReferenceCount) &&
|
(Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) &&
|
||||||
(Fcb->SectionObject.DataSectionObject != NULL)) {
|
(Fcb->SectionObject.DataSectionObject != NULL)) {
|
||||||
|
|
||||||
if (!IsVcbReadOnly(Vcb)) {
|
if (!IsVcbReadOnly(Vcb)) {
|
||||||
|
@ -337,14 +343,17 @@ Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
|
ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
|
/* purge cache if all remaining openings are non-cached */
|
||||||
ExReleaseResourceLite(&(Fcb->PagingIoResource));
|
if (Fcb->NonCachedOpenCount > 0) {
|
||||||
}
|
if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) {
|
||||||
|
ExReleaseResourceLite(&(Fcb->PagingIoResource));
|
||||||
|
}
|
||||||
|
|
||||||
CcPurgeCacheSection( &Fcb->SectionObject,
|
CcPurgeCacheSection( &Fcb->SectionObject,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
FALSE );
|
FALSE );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CcUninitializeCacheMap(FileObject, NULL, NULL);
|
CcUninitializeCacheMap(FileObject, NULL, NULL);
|
||||||
|
|
|
@ -28,11 +28,11 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PEXT2_VCB Vcb = NULL;
|
PEXT2_VCB Vcb = NULL;
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb = NULL;
|
||||||
|
PEXT2_CCB Ccb = NULL;
|
||||||
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
BOOLEAN FcbResourceAcquired = FALSE;
|
BOOLEAN FcbResourceAcquired = FALSE;
|
||||||
PEXT2_CCB Ccb;
|
|
||||||
BOOLEAN bDeleteVcb = FALSE;
|
BOOLEAN bDeleteVcb = FALSE;
|
||||||
BOOLEAN bBeingClosed = FALSE;
|
BOOLEAN bBeingClosed = FALSE;
|
||||||
BOOLEAN bSkipLeave = FALSE;
|
BOOLEAN bSkipLeave = FALSE;
|
||||||
|
@ -57,7 +57,7 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
if (!ExAcquireResourceExclusiveLite(
|
if (!ExAcquireResourceExclusiveLite(
|
||||||
&Vcb->MainResource,
|
&Vcb->MainResource,
|
||||||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
|
TRUE )) {
|
||||||
DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n",
|
DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n",
|
||||||
Vcb->OpenHandleCount, Vcb->ReferenceCount));
|
Vcb->OpenHandleCount, Vcb->ReferenceCount));
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
if (!ExAcquireResourceExclusiveLite(
|
if (!ExAcquireResourceExclusiveLite(
|
||||||
&Fcb->MainResource,
|
&Fcb->MainResource,
|
||||||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
|
TRUE )) {
|
||||||
Status = STATUS_PENDING;
|
Status = STATUS_PENDING;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
if (NT_SUCCESS(Status) && Vcb != NULL && IsVcbInited(Vcb)) {
|
if (NT_SUCCESS(Status) && Vcb != NULL && IsVcbInited(Vcb)) {
|
||||||
/* for Ext2Fsd driver open/close, Vcb is NULL */
|
/* for Ext2Fsd driver open/close, Vcb is NULL */
|
||||||
if ((!bBeingClosed) && (Vcb->ReferenceCount == 0)&&
|
if ((!bBeingClosed) && (Vcb->ReferenceCount == 0) &&
|
||||||
(!IsMounted(Vcb) || IsDispending(Vcb))) {
|
(!IsMounted(Vcb) || IsDispending(Vcb))) {
|
||||||
bDeleteVcb = TRUE;
|
bDeleteVcb = TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ Ext2FollowLink (
|
||||||
IN PEXT2_VCB Vcb,
|
IN PEXT2_VCB Vcb,
|
||||||
IN PEXT2_MCB Parent,
|
IN PEXT2_MCB Parent,
|
||||||
IN PEXT2_MCB Mcb,
|
IN PEXT2_MCB Mcb,
|
||||||
IN USHORT Linkdep
|
IN ULONG Linkdep
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_LINK_FAILED;
|
NTSTATUS Status = STATUS_LINK_FAILED;
|
||||||
|
@ -88,7 +88,7 @@ Ext2FollowLink (
|
||||||
|
|
||||||
/* exit if we jump into a possible symlink forever loop */
|
/* exit if we jump into a possible symlink forever loop */
|
||||||
if ((Linkdep + 1) > EXT2_MAX_NESTED_LINKS ||
|
if ((Linkdep + 1) > EXT2_MAX_NESTED_LINKS ||
|
||||||
IoGetRemainingStackSize() < 1024) {
|
IoGetRemainingStackSize() < 1024) {
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,14 +113,12 @@ Ext2FollowLink (
|
||||||
bOemBuffer = TRUE;
|
bOemBuffer = TRUE;
|
||||||
RtlZeroMemory(OemName.Buffer, OemName.MaximumLength);
|
RtlZeroMemory(OemName.Buffer, OemName.MaximumLength);
|
||||||
|
|
||||||
Status = Ext2ReadInode(
|
Status = Ext2ReadSymlink(
|
||||||
IrpContext,
|
IrpContext,
|
||||||
Vcb,
|
Vcb,
|
||||||
Mcb,
|
Mcb,
|
||||||
(ULONGLONG)0,
|
|
||||||
OemName.Buffer,
|
OemName.Buffer,
|
||||||
(ULONG)(Mcb->Inode.i_size),
|
(ULONG)(Mcb->Inode.i_size),
|
||||||
FALSE,
|
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
|
@ -170,9 +168,9 @@ Ext2FollowLink (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Target == NULL /* link target doesn't exist */ ||
|
if (Target == NULL /* link target doesn't exist */ ||
|
||||||
Target == Mcb /* symlink points to itself */ ||
|
Target == Mcb /* symlink points to itself */ ||
|
||||||
IsMcbSpecialFile(Target) /* target not resolved*/ ||
|
IsMcbSpecialFile(Target) /* target not resolved*/ ||
|
||||||
IsFileDeleted(Target) /* target deleted */ ) {
|
IsFileDeleted(Target) /* target deleted */ ) {
|
||||||
|
|
||||||
if (Target) {
|
if (Target) {
|
||||||
ASSERT(Target->Refercount > 0);
|
ASSERT(Target->Refercount > 0);
|
||||||
|
@ -180,7 +178,6 @@ Ext2FollowLink (
|
||||||
}
|
}
|
||||||
ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
|
ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
|
||||||
SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
|
SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
|
||||||
Mcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
|
|
||||||
Mcb->Target = NULL;
|
Mcb->Target = NULL;
|
||||||
|
|
||||||
} else if (IsMcbSymLink(Target)) {
|
} else if (IsMcbSymLink(Target)) {
|
||||||
|
@ -194,15 +191,18 @@ Ext2FollowLink (
|
||||||
SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
|
SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
|
||||||
ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
|
ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
|
||||||
ASSERT(Mcb->Target->Refercount > 0);
|
ASSERT(Mcb->Target->Refercount > 0);
|
||||||
Mcb->FileAttr = Target->FileAttr;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
Mcb->Target = Target;
|
Mcb->Target = Target;
|
||||||
SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
|
SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
|
||||||
ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
|
ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
|
||||||
ASSERT(Mcb->Target->Refercount > 0);
|
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 {
|
} _SEH2_FINALLY {
|
||||||
|
@ -275,7 +275,7 @@ Ext2LookupFile (
|
||||||
IN PUNICODE_STRING FullName,
|
IN PUNICODE_STRING FullName,
|
||||||
IN PEXT2_MCB Parent,
|
IN PEXT2_MCB Parent,
|
||||||
OUT PEXT2_MCB * Ext2Mcb,
|
OUT PEXT2_MCB * Ext2Mcb,
|
||||||
IN USHORT Linkdep
|
IN ULONG Linkdep
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
@ -289,12 +289,20 @@ Ext2LookupFile (
|
||||||
BOOLEAN bParent = FALSE;
|
BOOLEAN bParent = FALSE;
|
||||||
BOOLEAN bDirectory = FALSE;
|
BOOLEAN bDirectory = FALSE;
|
||||||
BOOLEAN LockAcquired = FALSE;
|
BOOLEAN LockAcquired = FALSE;
|
||||||
|
BOOLEAN bNotFollow = FALSE;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&Vcb->McbLock, TRUE);
|
ExAcquireResourceExclusiveLite(&Vcb->McbLock, TRUE);
|
||||||
LockAcquired = 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;
|
*Ext2Mcb = NULL;
|
||||||
|
|
||||||
DEBUG(DL_RES, ("Ext2LookupFile: %wZ\n", FullName));
|
DEBUG(DL_RES, ("Ext2LookupFile: %wZ\n", FullName));
|
||||||
|
@ -394,7 +402,7 @@ Ext2LookupFile (
|
||||||
Parent = Mcb;
|
Parent = Mcb;
|
||||||
|
|
||||||
if (IsMcbSymLink(Mcb) && IsFileDeleted(Mcb->Target) &&
|
if (IsMcbSymLink(Mcb) && IsFileDeleted(Mcb->Target) &&
|
||||||
(Mcb->Refercount == 1)) {
|
Mcb->Refercount == 1) {
|
||||||
|
|
||||||
ASSERT(Mcb->Target);
|
ASSERT(Mcb->Target);
|
||||||
ASSERT(Mcb->Target->Refercount > 0);
|
ASSERT(Mcb->Target->Refercount > 0);
|
||||||
|
@ -453,16 +461,18 @@ Ext2LookupFile (
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set inode attribute */
|
/* set inode attribute */
|
||||||
if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(Mcb->Inode.i_mode)) {
|
if (!Ext2CheckFileAccess(Vcb, Mcb, Ext2FileCanWrite)) {
|
||||||
SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_READONLY);
|
SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_READONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (S_ISDIR(Mcb->Inode.i_mode)) {
|
if (S_ISDIR(Mcb->Inode.i_mode)) {
|
||||||
SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
|
SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
|
||||||
} else {
|
} else {
|
||||||
SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_NORMAL);
|
if (S_ISREG(Mcb->Inode.i_mode)) {
|
||||||
if (!S_ISREG(Mcb->Inode.i_mode) &&
|
SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_NORMAL);
|
||||||
!S_ISLNK(Mcb->Inode.i_mode)) {
|
} else if (S_ISLNK(Mcb->Inode.i_mode)) {
|
||||||
|
SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_REPARSE_POINT);
|
||||||
|
} else {
|
||||||
SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
|
SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -484,7 +494,7 @@ Ext2LookupFile (
|
||||||
Mcb->ChangeTime = Ext2NtTime(Mcb->Inode.i_mtime);
|
Mcb->ChangeTime = Ext2NtTime(Mcb->Inode.i_mtime);
|
||||||
|
|
||||||
/* process symlink */
|
/* process symlink */
|
||||||
if (S_ISLNK(Mcb->Inode.i_mode)) {
|
if (S_ISLNK(Mcb->Inode.i_mode) && !bNotFollow) {
|
||||||
Ext2FollowLink( IrpContext,
|
Ext2FollowLink( IrpContext,
|
||||||
Vcb,
|
Vcb,
|
||||||
Parent,
|
Parent,
|
||||||
|
@ -616,7 +626,7 @@ Ext2ScanDir (
|
||||||
Ext2DerefMcb(Parent);
|
Ext2DerefMcb(Parent);
|
||||||
|
|
||||||
if (bh)
|
if (bh)
|
||||||
brelse(bh);
|
__brelse(bh);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
if (de)
|
if (de)
|
||||||
|
@ -659,7 +669,7 @@ NTSTATUS Ext2AddDotEntries(struct ext2_icb *icb, struct inode *dir,
|
||||||
|
|
||||||
errorout:
|
errorout:
|
||||||
if (bh)
|
if (bh)
|
||||||
brelse (bh);
|
__brelse (bh);
|
||||||
|
|
||||||
return Ext2WinntError(rc);
|
return Ext2WinntError(rc);
|
||||||
}
|
}
|
||||||
|
@ -708,9 +718,11 @@ Ext2CreateFile(
|
||||||
BOOLEAN DeleteOnClose;
|
BOOLEAN DeleteOnClose;
|
||||||
BOOLEAN TemporaryFile;
|
BOOLEAN TemporaryFile;
|
||||||
BOOLEAN CaseSensitive;
|
BOOLEAN CaseSensitive;
|
||||||
|
BOOLEAN OpenReparsePoint;
|
||||||
|
|
||||||
ACCESS_MASK DesiredAccess;
|
ACCESS_MASK DesiredAccess;
|
||||||
ULONG ShareAccess;
|
ULONG ShareAccess;
|
||||||
|
ULONG CcbFlags = 0;
|
||||||
|
|
||||||
RtlZeroMemory(&FileName, sizeof(UNICODE_STRING));
|
RtlZeroMemory(&FileName, sizeof(UNICODE_STRING));
|
||||||
|
|
||||||
|
@ -728,6 +740,9 @@ Ext2CreateFile(
|
||||||
NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
|
NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
|
||||||
DeleteOnClose = IsFlagOn(Options, FILE_DELETE_ON_CLOSE);
|
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);
|
CaseSensitive = IsFlagOn(IrpSp->Flags, SL_CASE_SENSITIVE);
|
||||||
|
|
||||||
TemporaryFile = IsFlagOn(IrpSp->Parameters.Create.FileAttributes,
|
TemporaryFile = IsFlagOn(IrpSp->Parameters.Create.FileAttributes,
|
||||||
|
@ -843,7 +858,8 @@ Ext2CreateFile(
|
||||||
&FileName,
|
&FileName,
|
||||||
ParentMcb,
|
ParentMcb,
|
||||||
&Mcb,
|
&Mcb,
|
||||||
0 );
|
0 /* always follow link */
|
||||||
|
);
|
||||||
McbExisting:
|
McbExisting:
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
@ -964,7 +980,7 @@ Dissecting:
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(ParentFcb->Mcb->Inode.i_mode)) {
|
if (!Ext2CheckFileAccess(Vcb, ParentMcb, Ext2FileCanWrite)) {
|
||||||
Status = STATUS_ACCESS_DENIED;
|
Status = STATUS_ACCESS_DENIED;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
@ -1104,7 +1120,7 @@ Dissecting:
|
||||||
if (IsMcbDirectory(Mcb)) {
|
if (IsMcbDirectory(Mcb)) {
|
||||||
|
|
||||||
if ((CreateDisposition != FILE_OPEN) &&
|
if ((CreateDisposition != FILE_OPEN) &&
|
||||||
(CreateDisposition != FILE_OPEN_IF)) {
|
(CreateDisposition != FILE_OPEN_IF)) {
|
||||||
|
|
||||||
Status = STATUS_OBJECT_NAME_COLLISION;
|
Status = STATUS_OBJECT_NAME_COLLISION;
|
||||||
Ext2DerefMcb(Mcb);
|
Ext2DerefMcb(Mcb);
|
||||||
|
@ -1147,7 +1163,11 @@ Openit:
|
||||||
|
|
||||||
/* refer it's target if it's a symlink, so both refered */
|
/* refer it's target if it's a symlink, so both refered */
|
||||||
if (IsMcbSymLink(Mcb)) {
|
if (IsMcbSymLink(Mcb)) {
|
||||||
if (IsFileDeleted(Mcb->Target)) {
|
|
||||||
|
if (OpenReparsePoint) {
|
||||||
|
/* set Ccb flag */
|
||||||
|
CcbFlags = CCB_OPEN_REPARSE_POINT;
|
||||||
|
} else if (IsFileDeleted(Mcb->Target)) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
|
SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
|
||||||
ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
|
ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
|
||||||
|
@ -1162,7 +1182,12 @@ Openit:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check readonly flag
|
// 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 |
|
if (BooleanFlagOn(DesiredAccess, FILE_WRITE_DATA | FILE_APPEND_DATA |
|
||||||
FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD)) {
|
FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD)) {
|
||||||
Status = STATUS_ACCESS_DENIED;
|
Status = STATUS_ACCESS_DENIED;
|
||||||
|
@ -1398,7 +1423,7 @@ Openit:
|
||||||
&(Fcb->ShareAccess) );
|
&(Fcb->ShareAccess) );
|
||||||
}
|
}
|
||||||
|
|
||||||
Ccb = Ext2AllocateCcb(SymLink);
|
Ccb = Ext2AllocateCcb(CcbFlags, SymLink);
|
||||||
if (!Ccb) {
|
if (!Ccb) {
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
|
@ -1684,7 +1709,7 @@ Ext2CreateVolume(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb)
|
||||||
return STATUS_SHARING_VIOLATION;
|
return STATUS_SHARING_VIOLATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ccb = Ext2AllocateCcb(NULL);
|
Ccb = Ext2AllocateCcb(0, NULL);
|
||||||
if (Ccb == NULL) {
|
if (Ccb == NULL) {
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto errorout;
|
goto errorout;
|
||||||
|
@ -1869,9 +1894,9 @@ Ext2CreateInode(
|
||||||
Inode.i_sb = &Vcb->sb;
|
Inode.i_sb = &Vcb->sb;
|
||||||
Inode.i_ino = iNo;
|
Inode.i_ino = iNo;
|
||||||
Inode.i_ctime = Inode.i_mtime =
|
Inode.i_ctime = Inode.i_mtime =
|
||||||
Inode.i_atime = Ext2LinuxTime(SysTime);
|
Inode.i_atime = Ext2LinuxTime(SysTime);
|
||||||
Inode.i_uid = Parent->Inode->i_uid;
|
Inode.i_uid = Vcb->uid;
|
||||||
Inode.i_gid = Parent->Inode->i_gid;
|
Inode.i_gid = Vcb->gid;
|
||||||
Inode.i_generation = Parent->Inode->i_generation;
|
Inode.i_generation = Parent->Inode->i_generation;
|
||||||
Inode.i_mode = S_IPERMISSION_MASK &
|
Inode.i_mode = S_IPERMISSION_MASK &
|
||||||
Parent->Inode->i_mode;
|
Parent->Inode->i_mode;
|
||||||
|
@ -1887,6 +1912,11 @@ Ext2CreateInode(
|
||||||
/* Force using extent */
|
/* Force using extent */
|
||||||
if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
|
if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
|
||||||
Inode.i_flags |= EXT2_EXTENTS_FL;
|
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 */
|
/* add new entry to its parent */
|
||||||
|
|
|
@ -2654,6 +2654,7 @@ Ext2FreePool(
|
||||||
NumberOfBytes = Data[0];
|
NumberOfBytes = Data[0];
|
||||||
if (Data[1] != NumberOfBytes + 0x20) {
|
if (Data[1] != NumberOfBytes + 0x20) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
for (i=0x08; i < 0x10; i++) {
|
for (i=0x08; i < 0x10; i++) {
|
||||||
if (Buffer[i] != 'S') {
|
if (Buffer[i] != 'S') {
|
||||||
|
@ -2664,6 +2665,7 @@ Ext2FreePool(
|
||||||
for (i=0; i < 0x10; i++) {
|
for (i=0; i < 0x10; i++) {
|
||||||
if (Buffer[i + NumberOfBytes + 0x10] != 'E') {
|
if (Buffer[i + NumberOfBytes + 0x10] != 'E') {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Buffer[i + NumberOfBytes + 0x10] = '-';
|
Buffer[i + NumberOfBytes + 0x10] = '-';
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,8 @@ Ext2ProcessEntry(
|
||||||
LONGLONG AllocationSize;
|
LONGLONG AllocationSize;
|
||||||
ULONG FileAttributes = 0;
|
ULONG FileAttributes = 0;
|
||||||
|
|
||||||
|
BOOLEAN IsEntrySymlink = FALSE;
|
||||||
|
|
||||||
*EntrySize = 0;
|
*EntrySize = 0;
|
||||||
NameLength = pName->Length;
|
NameLength = pName->Length;
|
||||||
ASSERT((UsedLength & 7) == 0);
|
ASSERT((UsedLength & 7) == 0);
|
||||||
|
@ -120,7 +122,12 @@ Ext2ProcessEntry(
|
||||||
DEBUG(DL_CP, ("Ext2ProcessDirEntry: %wZ in %wZ\n", pName, &Dcb->Mcb->FullName ));
|
DEBUG(DL_CP, ("Ext2ProcessDirEntry: %wZ in %wZ\n", pName, &Dcb->Mcb->FullName ));
|
||||||
|
|
||||||
Mcb = Ext2SearchMcb(Vcb, Dcb->Mcb, pName);
|
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_ino = in;
|
||||||
Inode.i_sb = &Vcb->sb;
|
Inode.i_sb = &Vcb->sb;
|
||||||
|
@ -136,7 +143,7 @@ Ext2ProcessEntry(
|
||||||
} else if (S_ISLNK(Inode.i_mode)) {
|
} else if (S_ISLNK(Inode.i_mode)) {
|
||||||
DEBUG(DL_RES, ("Ext2ProcessDirEntry: SymLink: %wZ\\%wZ\n",
|
DEBUG(DL_RES, ("Ext2ProcessDirEntry: SymLink: %wZ\\%wZ\n",
|
||||||
&Dcb->Mcb->FullName, pName));
|
&Dcb->Mcb->FullName, pName));
|
||||||
Ext2LookupFile(IrpContext, Vcb, pName, Dcb->Mcb, &Mcb, 0);
|
Ext2LookupFile(IrpContext, Vcb, pName, Dcb->Mcb, &Mcb,0);
|
||||||
|
|
||||||
if (Mcb && IsMcbSpecialFile(Mcb)) {
|
if (Mcb && IsMcbSpecialFile(Mcb)) {
|
||||||
Ext2DerefMcb(Mcb);
|
Ext2DerefMcb(Mcb);
|
||||||
|
@ -156,6 +163,7 @@ Ext2ProcessEntry(
|
||||||
ASSERT(!IsMcbSymLink(Target));
|
ASSERT(!IsMcbSymLink(Target));
|
||||||
if (IsMcbDirectory(Target)) {
|
if (IsMcbDirectory(Target)) {
|
||||||
FileSize = 0;
|
FileSize = 0;
|
||||||
|
FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
|
||||||
} else {
|
} else {
|
||||||
FileSize = Target->Inode.i_size;
|
FileSize = Target->Inode.i_size;
|
||||||
}
|
}
|
||||||
|
@ -171,6 +179,10 @@ Ext2ProcessEntry(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsInodeSymLink(&Mcb->Inode)) {
|
||||||
|
IsEntrySymlink = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (S_ISDIR(Inode.i_mode)) {
|
if (S_ISDIR(Inode.i_mode)) {
|
||||||
|
@ -181,11 +193,14 @@ Ext2ProcessEntry(
|
||||||
|
|
||||||
if (S_ISDIR(Inode.i_mode)) {
|
if (S_ISDIR(Inode.i_mode)) {
|
||||||
FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
} else if (S_ISLNK(Inode.i_mode)) {
|
||||||
|
FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
|
||||||
|
IsEntrySymlink = TRUE;
|
||||||
} else {
|
} else {
|
||||||
FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CanIWrite(Vcb) && Ext2IsOwnerReadOnly(Inode.i_mode)) {
|
if (!Ext2CheckInodeAccess(Vcb, &Inode, Ext2FileCanWrite)) {
|
||||||
SetFlag(FileAttributes, FILE_ATTRIBUTE_READONLY);
|
SetFlag(FileAttributes, FILE_ATTRIBUTE_READONLY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,8 +269,14 @@ Ext2ProcessEntry(
|
||||||
|
|
||||||
if (FIF) {
|
if (FIF) {
|
||||||
FIF->FileId.QuadPart = (LONGLONG) in;
|
FIF->FileId.QuadPart = (LONGLONG) in;
|
||||||
|
if (IsEntrySymlink) {
|
||||||
|
FIF->EaSize = IO_REPARSE_TAG_SYMLINK;
|
||||||
|
}
|
||||||
RtlCopyMemory(&FIF->FileName[0], &pName->Buffer[0], NameLength);
|
RtlCopyMemory(&FIF->FileName[0], &pName->Buffer[0], NameLength);
|
||||||
} else if (FFI) {
|
} else if (FFI) {
|
||||||
|
if (IsEntrySymlink) {
|
||||||
|
FFI->EaSize = IO_REPARSE_TAG_SYMLINK;
|
||||||
|
}
|
||||||
RtlCopyMemory(&FFI->FileName[0], &pName->Buffer[0], NameLength);
|
RtlCopyMemory(&FFI->FileName[0], &pName->Buffer[0], NameLength);
|
||||||
} else {
|
} else {
|
||||||
RtlCopyMemory(&FDI->FileName[0], &pName->Buffer[0], NameLength);
|
RtlCopyMemory(&FDI->FileName[0], &pName->Buffer[0], NameLength);
|
||||||
|
@ -302,6 +323,9 @@ Ext2ProcessEntry(
|
||||||
|
|
||||||
if (FIB) {
|
if (FIB) {
|
||||||
FIB->FileId.QuadPart = (LONGLONG)in;
|
FIB->FileId.QuadPart = (LONGLONG)in;
|
||||||
|
if (IsEntrySymlink) {
|
||||||
|
FIB->EaSize = IO_REPARSE_TAG_SYMLINK;
|
||||||
|
}
|
||||||
RtlCopyMemory(&FIB->FileName[0], &pName->Buffer[0], NameLength);
|
RtlCopyMemory(&FIB->FileName[0], &pName->Buffer[0], NameLength);
|
||||||
} else {
|
} else {
|
||||||
RtlCopyMemory(&FBI->FileName[0], &pName->Buffer[0], NameLength);
|
RtlCopyMemory(&FBI->FileName[0], &pName->Buffer[0], NameLength);
|
||||||
|
@ -502,13 +526,13 @@ Ext2QueryDirectory (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject = NULL;
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb = NULL;
|
||||||
PEXT2_MCB Mcb;
|
PEXT2_MCB Mcb = NULL;
|
||||||
PEXT2_CCB Ccb;
|
PEXT2_CCB Ccb = NULL;
|
||||||
PIRP Irp;
|
PIRP Irp = NULL;
|
||||||
PIO_STACK_LOCATION IoStackLocation;
|
PIO_STACK_LOCATION IoStackLocation = NULL;
|
||||||
|
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
ULONG FileIndex;
|
ULONG FileIndex;
|
||||||
|
@ -1009,12 +1033,12 @@ Ext2NotifyChangeDirectory (
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
BOOLEAN CompleteRequest = TRUE;
|
BOOLEAN CompleteRequest = TRUE;
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PFILE_OBJECT FileObject;
|
PEXT2_FCB Fcb = NULL;
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_CCB Ccb = NULL;
|
||||||
PEXT2_CCB Ccb;
|
PIRP Irp = NULL;
|
||||||
PIRP Irp;
|
|
||||||
PIO_STACK_LOCATION IrpSp;
|
PIO_STACK_LOCATION IrpSp;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
ULONG CompletionFilter;
|
ULONG CompletionFilter;
|
||||||
BOOLEAN WatchTree;
|
BOOLEAN WatchTree;
|
||||||
|
|
||||||
|
@ -1243,4 +1267,4 @@ Ext2IsDirectoryEmpty (
|
||||||
}
|
}
|
||||||
|
|
||||||
return !!ext3_is_dir_empty(IrpContext, &Mcb->Inode);
|
return !!ext3_is_dir_empty(IrpContext, &Mcb->Inode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: generic.c
|
* FILE: generic.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://ext2.yeah.net
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -132,15 +132,15 @@ Ext2LoadGroup(IN PEXT2_VCB Vcb)
|
||||||
{
|
{
|
||||||
struct super_block *sb = &Vcb->sb;
|
struct super_block *sb = &Vcb->sb;
|
||||||
struct ext3_sb_info *sbi = &Vcb->sbi;
|
struct ext3_sb_info *sbi = &Vcb->sbi;
|
||||||
|
ext3_fsblk_t sb_block = 1;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
ext3_fsblk_t block, sb_block = 1;
|
|
||||||
|
|
||||||
if (BLOCK_SIZE != EXT3_MIN_BLOCK_SIZE) {
|
if (BLOCK_SIZE != EXT3_MIN_BLOCK_SIZE) {
|
||||||
sb_block = EXT4_MIN_BLOCK_SIZE / BLOCK_SIZE;
|
sb_block = EXT4_MIN_BLOCK_SIZE / BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL == sbi->s_group_desc) {
|
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);
|
GFP_KERNEL);
|
||||||
}
|
}
|
||||||
if (sbi->s_group_desc == NULL) {
|
if (sbi->s_group_desc == NULL) {
|
||||||
|
@ -149,10 +149,7 @@ Ext2LoadGroup(IN PEXT2_VCB Vcb)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < sbi->s_gdb_count; i++) {
|
for (i = 0; i < sbi->s_gdb_count; i++) {
|
||||||
block = descriptor_loc(sb, sb_block, i);
|
sbi->s_group_desc[i] = descriptor_loc(sb, sb_block, i);
|
||||||
if (sbi->s_group_desc[i])
|
|
||||||
continue;
|
|
||||||
sbi->s_group_desc[i] = sb_bread(sb, block);
|
|
||||||
if (!sbi->s_group_desc[i]) {
|
if (!sbi->s_group_desc[i]) {
|
||||||
DEBUG(DL_ERR, ("Ext2LoadGroup: can't read group descriptor %d\n", i));
|
DEBUG(DL_ERR, ("Ext2LoadGroup: can't read group descriptor %d\n", i));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -167,28 +164,19 @@ Ext2LoadGroup(IN PEXT2_VCB Vcb)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
Ext2PutGroup(IN PEXT2_VCB Vcb)
|
Ext2DropGroup(IN PEXT2_VCB Vcb)
|
||||||
{
|
{
|
||||||
struct ext3_sb_info *sbi = &Vcb->sbi;
|
struct ext3_sb_info *sbi = &Vcb->sbi;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&Vcb->MetaLock, TRUE);
|
|
||||||
if (NULL == sbi->s_group_desc) {
|
if (NULL == sbi->s_group_desc) {
|
||||||
ExReleaseResourceLite(&Vcb->MetaLock);
|
|
||||||
return;
|
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);
|
kfree(sbi->s_group_desc);
|
||||||
sbi->s_group_desc = NULL;
|
sbi->s_group_desc = NULL;
|
||||||
ExReleaseResourceLite(&Vcb->MetaLock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
|
@ -198,22 +186,17 @@ Ext2SaveGroup(
|
||||||
IN ULONG Group
|
IN ULONG Group
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
struct ext4_group_desc *desc;
|
struct ext4_group_desc *gd;
|
||||||
struct buffer_head *bh = NULL;
|
struct buffer_head *gb = NULL;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&Vcb->MetaLock, TRUE);
|
gd = ext4_get_group_desc(&Vcb->sb, Group, &gb);
|
||||||
desc = ext4_get_group_desc(&Vcb->sb, Group, &bh);
|
if (!gd)
|
||||||
if (bh)
|
|
||||||
get_bh(bh);
|
|
||||||
ExReleaseResourceLite(&Vcb->MetaLock);
|
|
||||||
|
|
||||||
if (!bh)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
desc->bg_checksum = ext4_group_desc_csum(&Vcb->sbi, Group, desc);
|
gd->bg_checksum = ext4_group_desc_csum(&Vcb->sbi, Group, gd);
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(gb);
|
||||||
__brelse(bh);
|
fini_bh(&gb);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -236,6 +219,7 @@ Ext2GetInodeLba (
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
PEXT2_GROUP_DESC gd;
|
PEXT2_GROUP_DESC gd;
|
||||||
|
struct buffer_head *bh = NULL;
|
||||||
ext4_fsblk_t loc;
|
ext4_fsblk_t loc;
|
||||||
int group;
|
int group;
|
||||||
|
|
||||||
|
@ -246,8 +230,8 @@ Ext2GetInodeLba (
|
||||||
}
|
}
|
||||||
|
|
||||||
group = (inode - 1) / INODES_PER_GROUP ;
|
group = (inode - 1) / INODES_PER_GROUP ;
|
||||||
gd = ext4_get_group_desc(&Vcb->sb, group, NULL);
|
gd = ext4_get_group_desc(&Vcb->sb, group, &bh);
|
||||||
if (!gd) {
|
if (!bh) {
|
||||||
*offset = 0;
|
*offset = 0;
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -257,6 +241,7 @@ Ext2GetInodeLba (
|
||||||
loc = loc + ((inode - 1) % INODES_PER_GROUP) * Vcb->InodeSize;
|
loc = loc + ((inode - 1) % INODES_PER_GROUP) * Vcb->InodeSize;
|
||||||
|
|
||||||
*offset = loc;
|
*offset = loc;
|
||||||
|
__brelse(bh);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -273,11 +258,14 @@ void Ext2DecodeInode(struct inode *dst, struct ext3_inode *src)
|
||||||
if (S_ISREG(src->i_mode)) {
|
if (S_ISREG(src->i_mode)) {
|
||||||
dst->i_size |= (loff_t)src->i_size_high << 32;
|
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_atime = src->i_atime;
|
||||||
dst->i_ctime = src->i_ctime;
|
dst->i_ctime = src->i_ctime;
|
||||||
dst->i_mtime = src->i_mtime;
|
dst->i_mtime = src->i_mtime;
|
||||||
dst->i_dtime = src->i_dtime;
|
dst->i_dtime = src->i_dtime;
|
||||||
dst->i_blocks = ext3_inode_blocks(src, dst);
|
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);
|
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)) {
|
if (S_ISREG(src->i_mode)) {
|
||||||
dst->i_size_high = (__u32)(src->i_size >> 32);
|
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_atime = src->i_atime;
|
||||||
dst->i_ctime = src->i_ctime;
|
dst->i_ctime = src->i_ctime;
|
||||||
dst->i_mtime = src->i_mtime;
|
dst->i_mtime = src->i_mtime;
|
||||||
dst->i_dtime = src->i_dtime;
|
dst->i_dtime = src->i_dtime;
|
||||||
|
dst->i_extra_isize = src->i_extra_isize;
|
||||||
ASSERT(src->i_sb);
|
ASSERT(src->i_sb);
|
||||||
ext3_inode_blocks_set(dst, src);
|
ext3_inode_blocks_set(dst, src);
|
||||||
memcpy(&dst->i_block[0], &src->i_block[0], sizeof(__u32) * 15);
|
memcpy(&dst->i_block[0], &src->i_block[0], sizeof(__u32) * 15);
|
||||||
|
@ -584,8 +575,9 @@ Ext2NewBlock(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
struct super_block *sb = &Vcb->sb;
|
struct super_block *sb = &Vcb->sb;
|
||||||
PEXT2_GROUP_DESC group_desc;
|
PEXT2_GROUP_DESC gd;
|
||||||
struct buffer_head* bh = NULL;
|
struct buffer_head *gb = NULL;
|
||||||
|
struct buffer_head *bh = NULL;
|
||||||
ext4_fsblk_t bitmap_blk;
|
ext4_fsblk_t bitmap_blk;
|
||||||
|
|
||||||
RTL_BITMAP BlockBitmap;
|
RTL_BITMAP BlockBitmap;
|
||||||
|
@ -617,31 +609,32 @@ Ext2NewBlock(
|
||||||
|
|
||||||
Again:
|
Again:
|
||||||
|
|
||||||
if (bh) {
|
if (bh)
|
||||||
__brelse(bh);
|
fini_bh(&bh);
|
||||||
bh = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
group_desc = ext4_get_group_desc(sb, Group, NULL);
|
if (gb)
|
||||||
if (!group_desc) {
|
fini_bh(&gb);
|
||||||
|
|
||||||
|
gd = ext4_get_group_desc(sb, Group, &gb);
|
||||||
|
if (!gd) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto errorout;
|
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);
|
bh = sb_getblk_zero(sb, bitmap_blk);
|
||||||
if (!bh) {
|
if (!bh) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
group_desc->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, group_desc);
|
gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd);
|
||||||
ext4_init_block_bitmap(sb, bh, Group, group_desc);
|
ext4_init_block_bitmap(sb, bh, Group, gd);
|
||||||
set_buffer_uptodate(bh);
|
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);
|
Ext2SaveGroup(IrpContext, Vcb, Group);
|
||||||
} else {
|
} else {
|
||||||
bh = sb_getblk(sb, bitmap_blk);
|
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) {
|
if (Group == Vcb->sbi.s_groups_count - 1) {
|
||||||
|
|
||||||
|
@ -696,7 +689,7 @@ Again:
|
||||||
RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
|
RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
|
||||||
|
|
||||||
/* no blocks found: set bg_free_blocks_count to 0 */
|
/* 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);
|
Ext2SaveGroup(IrpContext, Vcb, Group);
|
||||||
|
|
||||||
/* will try next group */
|
/* will try next group */
|
||||||
|
@ -732,7 +725,7 @@ Again:
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
|
|
||||||
/* update group description */
|
/* update group description */
|
||||||
ext4_free_blks_set(sb, group_desc, RtlNumberOfClearBits(&BlockBitmap));
|
ext4_free_blks_set(sb, gd, RtlNumberOfClearBits(&BlockBitmap));
|
||||||
Ext2SaveGroup(IrpContext, Vcb, Group);
|
Ext2SaveGroup(IrpContext, Vcb, Group);
|
||||||
|
|
||||||
/* update Vcb free blocks */
|
/* update Vcb free blocks */
|
||||||
|
@ -746,9 +739,9 @@ Again:
|
||||||
goto Again;
|
goto Again;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ext4_block_bitmap(sb, group_desc) == *Block ||
|
if (ext4_block_bitmap(sb, gd) == *Block ||
|
||||||
ext4_inode_bitmap(sb, group_desc) == *Block ||
|
ext4_inode_bitmap(sb, gd) == *Block ||
|
||||||
ext4_inode_table(sb, group_desc) == *Block ) {
|
ext4_inode_table(sb, gd) == *Block ) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
dwHint = 0;
|
dwHint = 0;
|
||||||
goto Again;
|
goto Again;
|
||||||
|
@ -772,7 +765,10 @@ errorout:
|
||||||
ExReleaseResourceLite(&Vcb->MetaLock);
|
ExReleaseResourceLite(&Vcb->MetaLock);
|
||||||
|
|
||||||
if (bh)
|
if (bh)
|
||||||
__brelse(bh);
|
fini_bh(&bh);
|
||||||
|
|
||||||
|
if (gb)
|
||||||
|
fini_bh(&gb);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -786,7 +782,8 @@ Ext2FreeBlock(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
struct super_block *sb = &Vcb->sb;
|
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;
|
ext4_fsblk_t bitmap_blk;
|
||||||
|
|
||||||
RTL_BITMAP BlockBitmap;
|
RTL_BITMAP BlockBitmap;
|
||||||
|
@ -812,6 +809,9 @@ Ext2FreeBlock(
|
||||||
|
|
||||||
Again:
|
Again:
|
||||||
|
|
||||||
|
if (gb)
|
||||||
|
fini_bh(&gb);
|
||||||
|
|
||||||
if ( Block < EXT2_FIRST_DATA_BLOCK ||
|
if ( Block < EXT2_FIRST_DATA_BLOCK ||
|
||||||
Block >= TOTAL_BLOCKS ||
|
Block >= TOTAL_BLOCKS ||
|
||||||
Group >= Vcb->sbi.s_groups_count) {
|
Group >= Vcb->sbi.s_groups_count) {
|
||||||
|
@ -821,13 +821,13 @@ Again:
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
group_desc = ext4_get_group_desc(sb, Group, NULL);
|
gd = ext4_get_group_desc(sb, Group, &gb);
|
||||||
if (!group_desc) {
|
if (!gd) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
bitmap_blk = ext4_block_bitmap(sb, group_desc);
|
bitmap_blk = ext4_block_bitmap(sb, gd);
|
||||||
|
|
||||||
/* check the block is valid or not */
|
/* check the block is valid or not */
|
||||||
if (bitmap_blk >= TOTAL_BLOCKS) {
|
if (bitmap_blk >= TOTAL_BLOCKS) {
|
||||||
|
@ -874,7 +874,7 @@ Again:
|
||||||
RtlClearBits(&BlockBitmap, Index, Count);
|
RtlClearBits(&BlockBitmap, Index, Count);
|
||||||
|
|
||||||
/* update group description table */
|
/* 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 */
|
/* indict the cache range is dirty */
|
||||||
CcSetDirtyPinnedData(BitmapBcb, NULL );
|
CcSetDirtyPinnedData(BitmapBcb, NULL );
|
||||||
|
@ -913,6 +913,9 @@ Again:
|
||||||
|
|
||||||
errorout:
|
errorout:
|
||||||
|
|
||||||
|
if (gb)
|
||||||
|
fini_bh(&gb);
|
||||||
|
|
||||||
ExReleaseResourceLite(&Vcb->MetaLock);
|
ExReleaseResourceLite(&Vcb->MetaLock);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -929,7 +932,8 @@ Ext2NewInode(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
struct super_block *sb = &Vcb->sb;
|
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;
|
struct buffer_head *bh = NULL;
|
||||||
ext4_fsblk_t bitmap_blk;
|
ext4_fsblk_t bitmap_blk;
|
||||||
|
|
||||||
|
@ -951,13 +955,14 @@ Ext2NewInode(
|
||||||
|
|
||||||
repeat:
|
repeat:
|
||||||
|
|
||||||
if (bh) {
|
if (bh)
|
||||||
__brelse(bh);
|
fini_bh(&bh);
|
||||||
bh = NULL;
|
|
||||||
}
|
if (gb)
|
||||||
|
fini_bh(&gb);
|
||||||
|
|
||||||
Group = i = 0;
|
Group = i = 0;
|
||||||
group_desc = NULL;
|
gd = NULL;
|
||||||
|
|
||||||
if (Type == EXT2_FT_DIR) {
|
if (Type == EXT2_FT_DIR) {
|
||||||
|
|
||||||
|
@ -966,31 +971,33 @@ repeat:
|
||||||
for (j = 0; j < Vcb->sbi.s_groups_count; j++) {
|
for (j = 0; j < Vcb->sbi.s_groups_count; j++) {
|
||||||
|
|
||||||
i = (j + GroupHint) % (Vcb->sbi.s_groups_count);
|
i = (j + GroupHint) % (Vcb->sbi.s_groups_count);
|
||||||
group_desc = ext4_get_group_desc(sb, i, NULL);
|
gd = ext4_get_group_desc(sb, i, &gb);
|
||||||
if (!group_desc) {
|
if (!gd) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto errorout;
|
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)) ||
|
||||||
(ext4_used_dirs_count(sb, group_desc) << 8 <
|
(ext4_used_dirs_count(sb, gd) << 8 <
|
||||||
ext4_free_inodes_count(sb, group_desc)) ) {
|
ext4_free_inodes_count(sb, gd)) ) {
|
||||||
Group = i + 1;
|
Group = i + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
fini_bh(&gb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Group) {
|
if (!Group) {
|
||||||
|
|
||||||
PEXT2_GROUP_DESC desc = NULL;
|
PEXT2_GROUP_DESC desc = NULL;
|
||||||
|
|
||||||
group_desc = NULL;
|
gd = NULL;
|
||||||
|
|
||||||
/* get the group with the biggest vacancy */
|
/* get the group with the biggest vacancy */
|
||||||
for (j = 0; j < Vcb->sbi.s_groups_count; j++) {
|
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) {
|
if (!desc) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
@ -1000,23 +1007,38 @@ repeat:
|
||||||
/* return the group if it's not initialized yet */
|
/* return the group if it's not initialized yet */
|
||||||
if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
|
if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
|
||||||
Group = j + 1;
|
Group = j + 1;
|
||||||
group_desc = desc;
|
gd = desc;
|
||||||
|
|
||||||
|
if (gb)
|
||||||
|
fini_bh(&gb);
|
||||||
|
gb = gt;
|
||||||
|
gt = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!group_desc) {
|
if (!gd) {
|
||||||
if (ext4_free_inodes_count(sb, desc) > 0) {
|
if (ext4_free_inodes_count(sb, desc) > 0) {
|
||||||
Group = j + 1;
|
Group = j + 1;
|
||||||
group_desc = desc;
|
gd = desc;
|
||||||
|
if (gb)
|
||||||
|
fini_bh(&gb);
|
||||||
|
gb = gt;
|
||||||
|
gt = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ext4_free_inodes_count(sb, desc) >
|
if (ext4_free_inodes_count(sb, desc) >
|
||||||
ext4_free_inodes_count(sb, group_desc)) {
|
ext4_free_inodes_count(sb, gd)) {
|
||||||
Group = j + 1;
|
Group = j + 1;
|
||||||
group_desc = desc;
|
gd = desc;
|
||||||
|
if (gb)
|
||||||
|
fini_bh(&gb);
|
||||||
|
gb = gt;
|
||||||
|
gt = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (gt)
|
||||||
|
fini_bh(>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1026,20 +1048,23 @@ repeat:
|
||||||
* Try to place the inode in its parent directory (GroupHint)
|
* Try to place the inode in its parent directory (GroupHint)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
group_desc = ext4_get_group_desc(sb, GroupHint, NULL);
|
gd = ext4_get_group_desc(sb, GroupHint, &gb);
|
||||||
if (!group_desc) {
|
if (!gb) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto errorout;
|
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) ||
|
||||||
ext4_free_inodes_count(sb, group_desc)) {
|
ext4_free_inodes_count(sb, gd)) {
|
||||||
|
|
||||||
Group = GroupHint + 1;
|
Group = GroupHint + 1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
/* this group is 100% cocucpied */
|
||||||
|
fini_bh(&gb);
|
||||||
|
|
||||||
i = GroupHint;
|
i = GroupHint;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1048,19 +1073,22 @@ repeat:
|
||||||
|
|
||||||
for (j = 1; j < Vcb->sbi.s_groups_count; j <<= 1) {
|
for (j = 1; j < Vcb->sbi.s_groups_count; j <<= 1) {
|
||||||
|
|
||||||
|
|
||||||
i = (i + j) % Vcb->sbi.s_groups_count;
|
i = (i + j) % Vcb->sbi.s_groups_count;
|
||||||
group_desc = ext4_get_group_desc(sb, i, NULL);
|
gd = ext4_get_group_desc(sb, i, &gb);
|
||||||
if (!group_desc) {
|
if (!gd) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto errorout;
|
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) ||
|
||||||
ext4_free_inodes_count(sb, group_desc)) {
|
ext4_free_inodes_count(sb, gd)) {
|
||||||
Group = i + 1;
|
Group = i + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fini_bh(&gb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1072,23 +1100,25 @@ repeat:
|
||||||
for (j = 2; j < Vcb->sbi.s_groups_count; j++) {
|
for (j = 2; j < Vcb->sbi.s_groups_count; j++) {
|
||||||
|
|
||||||
i = (i + 1) % Vcb->sbi.s_groups_count;
|
i = (i + 1) % Vcb->sbi.s_groups_count;
|
||||||
group_desc = ext4_get_group_desc(sb, i, NULL);
|
gd = ext4_get_group_desc(sb, i, &gb);
|
||||||
if (!group_desc) {
|
if (!gd) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto errorout;
|
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) ||
|
||||||
ext4_free_inodes_count(sb, group_desc)) {
|
ext4_free_inodes_count(sb, gd)) {
|
||||||
Group = i + 1;
|
Group = i + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fini_bh(&gb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (group_desc == NULL || Group == 0) {
|
if (gd == NULL || Group == 0) {
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1101,8 +1131,8 @@ repeat:
|
||||||
/* valid group number starts from 1, not 0 */
|
/* valid group number starts from 1, not 0 */
|
||||||
Group -= 1;
|
Group -= 1;
|
||||||
|
|
||||||
ASSERT(group_desc);
|
ASSERT(gd);
|
||||||
bitmap_blk = ext4_inode_bitmap(sb, group_desc);
|
bitmap_blk = ext4_inode_bitmap(sb, gd);
|
||||||
/* check the block is valid or not */
|
/* check the block is valid or not */
|
||||||
if (bitmap_blk == 0 || bitmap_blk >= TOTAL_BLOCKS) {
|
if (bitmap_blk == 0 || bitmap_blk >= TOTAL_BLOCKS) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
|
@ -1110,17 +1140,17 @@ repeat:
|
||||||
goto errorout;
|
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);
|
bh = sb_getblk_zero(sb, bitmap_blk);
|
||||||
if (!bh) {
|
if (!bh) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
group_desc->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, group_desc);
|
gd->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), Group, gd);
|
||||||
ext4_init_inode_bitmap(sb, bh, Group, group_desc);
|
ext4_init_inode_bitmap(sb, bh, Group, gd);
|
||||||
set_buffer_uptodate(bh);
|
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);
|
Ext2SaveGroup(IrpContext, Vcb, Group);
|
||||||
} else {
|
} else {
|
||||||
bh = sb_getblk(sb, bitmap_blk);
|
bh = sb_getblk(sb, bitmap_blk);
|
||||||
|
@ -1160,8 +1190,8 @@ repeat:
|
||||||
if (dwInode == 0xFFFFFFFF || dwInode >= Length) {
|
if (dwInode == 0xFFFFFFFF || dwInode >= Length) {
|
||||||
|
|
||||||
RtlZeroMemory(&InodeBitmap, sizeof(RTL_BITMAP));
|
RtlZeroMemory(&InodeBitmap, sizeof(RTL_BITMAP));
|
||||||
if (ext4_free_inodes_count(sb, group_desc) > 0) {
|
if (ext4_free_inodes_count(sb, gd) > 0) {
|
||||||
ext4_free_inodes_set(sb, group_desc, 0);
|
ext4_free_inodes_set(sb, gd, 0);
|
||||||
Ext2SaveGroup(IrpContext, Vcb, Group);
|
Ext2SaveGroup(IrpContext, Vcb, Group);
|
||||||
}
|
}
|
||||||
goto repeat;
|
goto repeat;
|
||||||
|
@ -1171,8 +1201,8 @@ repeat:
|
||||||
__u32 count = 0;
|
__u32 count = 0;
|
||||||
|
|
||||||
/* update unused inodes count */
|
/* update unused inodes count */
|
||||||
count = ext4_free_inodes_count(sb, group_desc) - 1;
|
count = ext4_free_inodes_count(sb, gd) - 1;
|
||||||
ext4_free_inodes_set(sb, group_desc, count);
|
ext4_free_inodes_set(sb, gd, count);
|
||||||
|
|
||||||
RtlSetBits(&InodeBitmap, dwInode, 1);
|
RtlSetBits(&InodeBitmap, dwInode, 1);
|
||||||
|
|
||||||
|
@ -1185,8 +1215,8 @@ repeat:
|
||||||
|
|
||||||
__u32 free;
|
__u32 free;
|
||||||
|
|
||||||
if (group_desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
|
if (gd->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
|
||||||
group_desc->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
|
/* When marking the block group with
|
||||||
* ~EXT4_BG_INODE_UNINIT we don't want to depend
|
* ~EXT4_BG_INODE_UNINIT we don't want to depend
|
||||||
* on the value of bg_itable_unused even though
|
* on the value of bg_itable_unused even though
|
||||||
|
@ -1196,7 +1226,7 @@ repeat:
|
||||||
|
|
||||||
free = 0;
|
free = 0;
|
||||||
} else {
|
} 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) {
|
if (dwInode + 1 > free) {
|
||||||
ext4_itable_unused_set(sb, group_desc,
|
ext4_itable_unused_set(sb, gd,
|
||||||
(EXT3_INODES_PER_GROUP(sb) - 1 - dwInode));
|
(EXT3_INODES_PER_GROUP(sb) - 1 - dwInode));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We may have to initialize the block bitmap if it isn't already */
|
/* 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;
|
struct buffer_head *block_bitmap_bh = NULL;
|
||||||
|
|
||||||
/* recheck and clear flag under lock if we still need to */
|
/* 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) {
|
if (block_bitmap_bh) {
|
||||||
group_desc->bg_checksum = ext4_group_desc_csum(EXT3_SB(sb), 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, group_desc);
|
free = ext4_init_block_bitmap(sb, block_bitmap_bh, Group, gd);
|
||||||
set_buffer_uptodate(block_bitmap_bh);
|
set_buffer_uptodate(block_bitmap_bh);
|
||||||
brelse(block_bitmap_bh);
|
brelse(block_bitmap_bh);
|
||||||
group_desc->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
|
gd->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
|
||||||
ext4_free_blks_set(sb, group_desc, free);
|
ext4_free_blks_set(sb, gd, free);
|
||||||
Ext2SaveGroup(IrpContext, Vcb, Group);
|
Ext2SaveGroup(IrpContext, Vcb, Group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1233,7 +1263,7 @@ repeat:
|
||||||
|
|
||||||
/* update group_desc / super_block */
|
/* update group_desc / super_block */
|
||||||
if (Type == EXT2_FT_DIR) {
|
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);
|
Ext2SaveGroup(IrpContext, Vcb, Group);
|
||||||
Ext2UpdateVcbStat(IrpContext, Vcb);
|
Ext2UpdateVcbStat(IrpContext, Vcb);
|
||||||
|
@ -1244,9 +1274,12 @@ errorout:
|
||||||
|
|
||||||
ExReleaseResourceLite(&Vcb->MetaLock);
|
ExReleaseResourceLite(&Vcb->MetaLock);
|
||||||
|
|
||||||
if (bh) {
|
if (bh)
|
||||||
brelse(bh);
|
fini_bh(&bh);
|
||||||
}
|
|
||||||
|
if (gb)
|
||||||
|
fini_bh(&gb);
|
||||||
|
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -1260,7 +1293,8 @@ Ext2FreeInode(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
struct super_block *sb = &Vcb->sb;
|
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;
|
struct buffer_head *bh = NULL;
|
||||||
ext4_fsblk_t bitmap_blk;
|
ext4_fsblk_t bitmap_blk;
|
||||||
|
|
||||||
|
@ -1287,14 +1321,14 @@ Ext2FreeInode(
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
|
|
||||||
group_desc = ext4_get_group_desc(sb, Group, NULL);
|
gd = ext4_get_group_desc(sb, Group, &gb);
|
||||||
if (!group_desc) {
|
if (!gd) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmap_blk = ext4_inode_bitmap(sb, group_desc);
|
bitmap_blk = ext4_inode_bitmap(sb, gd);
|
||||||
bh = sb_getblk(sb, bitmap_blk);
|
bh = sb_getblk(sb, bitmap_blk);
|
||||||
if (!bh) {
|
if (!bh) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
|
@ -1333,7 +1367,7 @@ Ext2FreeInode(
|
||||||
|
|
||||||
if (bModified) {
|
if (bModified) {
|
||||||
/* update group free inodes */
|
/* update group free inodes */
|
||||||
ext4_free_inodes_set(sb, group_desc,
|
ext4_free_inodes_set(sb, gd,
|
||||||
RtlNumberOfClearBits(&InodeBitmap));
|
RtlNumberOfClearBits(&InodeBitmap));
|
||||||
|
|
||||||
/* set inode block dirty and add to vcb dirty range */
|
/* set inode block dirty and add to vcb dirty range */
|
||||||
|
@ -1341,8 +1375,8 @@ Ext2FreeInode(
|
||||||
|
|
||||||
/* update group_desc and super_block */
|
/* update group_desc and super_block */
|
||||||
if (Type == EXT2_FT_DIR) {
|
if (Type == EXT2_FT_DIR) {
|
||||||
ext4_used_dirs_set(sb, group_desc,
|
ext4_used_dirs_set(sb, gd,
|
||||||
ext4_used_dirs_count(sb, group_desc) - 1);
|
ext4_used_dirs_count(sb, gd) - 1);
|
||||||
}
|
}
|
||||||
Ext2SaveGroup(IrpContext, Vcb, Group);
|
Ext2SaveGroup(IrpContext, Vcb, Group);
|
||||||
Ext2UpdateVcbStat(IrpContext, Vcb);
|
Ext2UpdateVcbStat(IrpContext, Vcb);
|
||||||
|
@ -1353,9 +1387,12 @@ errorout:
|
||||||
|
|
||||||
ExReleaseResourceLite(&Vcb->MetaLock);
|
ExReleaseResourceLite(&Vcb->MetaLock);
|
||||||
|
|
||||||
if (bh) {
|
if (bh)
|
||||||
brelse(bh);
|
fini_bh(&bh);
|
||||||
}
|
|
||||||
|
if (gb)
|
||||||
|
fini_bh(&gb);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1410,8 +1447,10 @@ Ext2AddEntry (
|
||||||
ext3_inc_count(Inode);
|
ext3_inc_count(Inode);
|
||||||
ext3_mark_inode_dirty(IrpContext, Inode);
|
ext3_mark_inode_dirty(IrpContext, Inode);
|
||||||
|
|
||||||
*Dentry = de;
|
if (Dentry) {
|
||||||
de = NULL;
|
*Dentry = de;
|
||||||
|
de = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} _SEH2_FINALLY {
|
} _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
|
NTSTATUS
|
||||||
Ext2RemoveEntry (
|
Ext2RemoveEntry (
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext,
|
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)) {
|
if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
|
||||||
struct ext4_group_desc *gdp;
|
struct ext4_group_desc *gdp;
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh = NULL;
|
||||||
|
|
||||||
gdp = ext4_get_group_desc(sb, block_group, &bh);
|
gdp = ext4_get_group_desc(sb, block_group, &bh);
|
||||||
if (!ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp),
|
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))
|
if (!ext4_block_in_group(sb, tmp, block_group))
|
||||||
used_blocks -= 1;
|
used_blocks -= 1;
|
||||||
}
|
}
|
||||||
|
if (bh)
|
||||||
|
fini_bh(&bh);
|
||||||
}
|
}
|
||||||
return used_blocks;
|
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,
|
struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
|
||||||
ext4_group_t block_group, struct buffer_head **bh)
|
ext4_group_t block_group, struct buffer_head **bh)
|
||||||
{
|
{
|
||||||
unsigned int group_desc;
|
|
||||||
unsigned int offset;
|
|
||||||
struct ext4_group_desc *desc = NULL;
|
struct ext4_group_desc *desc = NULL;
|
||||||
|
struct buffer_head *gb = NULL;
|
||||||
struct ext3_sb_info *sbi = EXT3_SB(sb);
|
struct ext3_sb_info *sbi = EXT3_SB(sb);
|
||||||
PEXT2_VCB vcb = sb->s_priv;
|
PEXT2_VCB vcb = sb->s_priv;
|
||||||
|
|
||||||
|
unsigned int group;
|
||||||
|
unsigned int offset;
|
||||||
|
|
||||||
|
if (bh)
|
||||||
|
*bh = NULL;
|
||||||
|
|
||||||
if (block_group >= sbi->s_groups_count) {
|
if (block_group >= sbi->s_groups_count) {
|
||||||
ext4_error(sb, "ext4_get_group_desc",
|
ext4_error(sb, "ext4_get_group_desc",
|
||||||
"block_group >= groups_count - "
|
"block_group >= groups_count - "
|
||||||
|
@ -2400,40 +2509,39 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
|
||||||
}
|
}
|
||||||
smp_rmb();
|
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);
|
offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
|
||||||
|
|
||||||
ExAcquireResourceExclusiveLite(&vcb->MetaLock, TRUE);
|
if (!sbi->s_group_desc || !sbi->s_group_desc[group]) {
|
||||||
|
Ext2LoadGroup(vcb);
|
||||||
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[group_desc]) {
|
if (!sbi->s_group_desc[group]) {
|
||||||
ext4_error(sb, "ext4_get_group_desc",
|
ext4_error(sb, "ext4_get_group_desc",
|
||||||
"Group descriptor not loaded - "
|
"Group descriptor not loaded - "
|
||||||
"block_group = %u, group_desc = %u, desc = %u",
|
"block_group = %u, group = %u, desc = %u",
|
||||||
block_group, group_desc, offset);
|
block_group, group, offset);
|
||||||
goto errorout;
|
goto errorout;
|
||||||
}
|
}
|
||||||
|
|
||||||
desc = (struct ext4_group_desc *)(
|
gb = sb_getblk(sb, sbi->s_group_desc[group]);
|
||||||
(__u8 *)sbi->s_group_desc[group_desc]->b_data +
|
if (!gb) {
|
||||||
offset * EXT4_DESC_SIZE(sb));
|
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)
|
if (bh)
|
||||||
*bh = sbi->s_group_desc[group_desc];
|
*bh = gb;
|
||||||
|
else
|
||||||
|
fini_bh(&gb);
|
||||||
|
|
||||||
errorout:
|
errorout:
|
||||||
|
|
||||||
ExReleaseResourceLite(&vcb->MetaLock);
|
|
||||||
|
|
||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2447,16 +2555,18 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
|
||||||
{
|
{
|
||||||
ext4_fsblk_t desc_count;
|
ext4_fsblk_t desc_count;
|
||||||
struct ext4_group_desc *gdp;
|
struct ext4_group_desc *gdp;
|
||||||
|
struct buffer_head *bh = NULL;
|
||||||
ext4_group_t i;
|
ext4_group_t i;
|
||||||
ext4_group_t ngroups = EXT3_SB(sb)->s_groups_count;
|
ext4_group_t ngroups = EXT3_SB(sb)->s_groups_count;
|
||||||
|
|
||||||
desc_count = 0;
|
desc_count = 0;
|
||||||
smp_rmb();
|
smp_rmb();
|
||||||
for (i = 0; i < ngroups; i++) {
|
for (i = 0; i < ngroups; i++) {
|
||||||
gdp = ext4_get_group_desc(sb, i, NULL);
|
gdp = ext4_get_group_desc(sb, i, &bh);
|
||||||
if (!gdp)
|
if (!bh)
|
||||||
continue;
|
continue;
|
||||||
desc_count += ext4_free_blks_count(sb, gdp);
|
desc_count += ext4_free_blks_count(sb, gdp);
|
||||||
|
fini_bh(&bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
return desc_count;
|
return desc_count;
|
||||||
|
@ -2466,15 +2576,16 @@ unsigned long ext4_count_free_inodes(struct super_block *sb)
|
||||||
{
|
{
|
||||||
unsigned long desc_count;
|
unsigned long desc_count;
|
||||||
struct ext4_group_desc *gdp;
|
struct ext4_group_desc *gdp;
|
||||||
|
struct buffer_head *bh = NULL;
|
||||||
ext4_group_t i;
|
ext4_group_t i;
|
||||||
|
|
||||||
desc_count = 0;
|
desc_count = 0;
|
||||||
for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
|
for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
|
||||||
gdp = ext4_get_group_desc(sb, i, NULL);
|
gdp = ext4_get_group_desc(sb, i, &bh);
|
||||||
if (!gdp)
|
if (!bh)
|
||||||
continue;
|
continue;
|
||||||
desc_count += ext4_free_inodes_count(sb, gdp);
|
desc_count += ext4_free_inodes_count(sb, gdp);
|
||||||
cond_resched();
|
fini_bh(&bh);
|
||||||
}
|
}
|
||||||
return desc_count;
|
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 */
|
/* Called at mount-time, super-block is locked */
|
||||||
unsigned long ext4_count_dirs(struct super_block * sb)
|
unsigned long ext4_count_dirs(struct super_block * sb)
|
||||||
{
|
{
|
||||||
|
struct ext4_group_desc *gdp;
|
||||||
|
struct buffer_head *bh = NULL;
|
||||||
unsigned long count = 0;
|
unsigned long count = 0;
|
||||||
ext4_group_t i;
|
ext4_group_t i;
|
||||||
|
|
||||||
for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
|
for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
|
||||||
struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL);
|
gdp = ext4_get_group_desc(sb, i, &bh);
|
||||||
if (!gdp)
|
if (!bh)
|
||||||
continue;
|
continue;
|
||||||
count += ext4_used_dirs_count(sb, gdp);
|
count += ext4_used_dirs_count(sb, gdp);
|
||||||
|
fini_bh(&bh);
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -2513,7 +2627,12 @@ int ext4_check_descriptors(struct super_block *sb)
|
||||||
DEBUG(DL_INF, ("Checking group descriptors"));
|
DEBUG(DL_INF, ("Checking group descriptors"));
|
||||||
|
|
||||||
for (i = 0; i < sbi->s_groups_count; i++) {
|
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)
|
if (i == sbi->s_groups_count - 1 || flexbg_flag)
|
||||||
last_block = ext3_blocks_count(sbi->s_es) - 1;
|
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: "
|
printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
|
||||||
"Block bitmap for group %u not in group "
|
"Block bitmap for group %u not in group "
|
||||||
"(block %llu)!\n", i, block_bitmap);
|
"(block %llu)!\n", i, block_bitmap);
|
||||||
|
__brelse(bh);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
inode_bitmap = ext4_inode_bitmap(sb, gdp);
|
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: "
|
printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
|
||||||
"Inode bitmap for group %u not in group "
|
"Inode bitmap for group %u not in group "
|
||||||
"(block %llu)!\n", i, inode_bitmap);
|
"(block %llu)!\n", i, inode_bitmap);
|
||||||
|
__brelse(bh);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
inode_table = ext4_inode_table(sb, gdp);
|
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: "
|
printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
|
||||||
"Inode table for group %u not in group "
|
"Inode table for group %u not in group "
|
||||||
"(block %llu)!\n", i, inode_table);
|
"(block %llu)!\n", i, inode_table);
|
||||||
|
__brelse(bh);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2550,12 +2672,15 @@ int ext4_check_descriptors(struct super_block *sb)
|
||||||
i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
|
i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
|
||||||
gdp)), le16_to_cpu(gdp->bg_checksum));
|
gdp)), le16_to_cpu(gdp->bg_checksum));
|
||||||
if (!IsVcbReadOnly(Vcb)) {
|
if (!IsVcbReadOnly(Vcb)) {
|
||||||
|
__brelse(bh);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!flexbg_flag)
|
if (!flexbg_flag)
|
||||||
first_block += EXT4_BLOCKS_PER_GROUP(sb);
|
first_block += EXT4_BLOCKS_PER_GROUP(sb);
|
||||||
|
|
||||||
|
__brelse(bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
ext3_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
|
ext3_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
|
||||||
|
|
|
@ -270,7 +270,7 @@ struct buffer_head *ext3_bread(struct ext2_icb *icb, struct inode *inode,
|
||||||
|
|
||||||
*err = bh_submit_read(bh);
|
*err = bh_submit_read(bh);
|
||||||
if (*err) {
|
if (*err) {
|
||||||
brelse(bh);
|
__brelse(bh);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return bh;
|
return bh;
|
||||||
|
@ -402,11 +402,11 @@ int add_dirent_to_buf(struct ext2_icb *icb, struct dentry *dentry,
|
||||||
while ((char *) de <= top) {
|
while ((char *) de <= top) {
|
||||||
if (!ext3_check_dir_entry("ext3_add_entry", dir, de,
|
if (!ext3_check_dir_entry("ext3_add_entry", dir, de,
|
||||||
bh, offset)) {
|
bh, offset)) {
|
||||||
brelse(bh);
|
__brelse(bh);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
if (ext3_match(namelen, name, de)) {
|
if (ext3_match(namelen, name, de)) {
|
||||||
brelse(bh);
|
__brelse(bh);
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
nlen = EXT3_DIR_REC_LEN(de->name_len);
|
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++;
|
dir->i_version++;
|
||||||
ext3_mark_inode_dirty(icb, dir);
|
ext3_mark_inode_dirty(icb, dir);
|
||||||
set_buffer_dirty(bh);
|
set_buffer_dirty(bh);
|
||||||
brelse(bh);
|
__brelse(bh);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -971,7 +971,7 @@ struct stats dx_show_entries(struct ext2_icb *icb, struct dx_hash_info *hinfo,
|
||||||
names += stats.names;
|
names += stats.names;
|
||||||
space += stats.space;
|
space += stats.space;
|
||||||
bcount += stats.bcount;
|
bcount += stats.bcount;
|
||||||
brelse (bh);
|
__brelse (bh);
|
||||||
}
|
}
|
||||||
if (bcount)
|
if (bcount)
|
||||||
printk("%snames %u, fullness %u (%u%%)\n", levels?"":" ",
|
printk("%snames %u, fullness %u (%u%%)\n", levels?"":" ",
|
||||||
|
@ -1023,7 +1023,7 @@ static struct dx_frame *
|
||||||
ext3_warning(dir->i_sb, __FUNCTION__,
|
ext3_warning(dir->i_sb, __FUNCTION__,
|
||||||
"Unrecognised inode hash code %d",
|
"Unrecognised inode hash code %d",
|
||||||
root->info.hash_version);
|
root->info.hash_version);
|
||||||
brelse(bh);
|
__brelse(bh);
|
||||||
*err = ERR_BAD_DX_DIR;
|
*err = ERR_BAD_DX_DIR;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -2181,7 +2181,7 @@ struct buffer_head * ext3_find_entry (struct ext2_icb *icb,
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#ifdef EXT2_HTREE_INDEX
|
#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);
|
bh = ext3_dx_find_entry(icb, dentry, res_dir, &err);
|
||||||
/*
|
/*
|
||||||
* On success, or if the error was file not found,
|
* On success, or if the error was file not found,
|
||||||
|
@ -2264,4 +2264,4 @@ cleanup_and_exit:
|
||||||
for (; ra_ptr < ra_max; ra_ptr++)
|
for (; ra_ptr < ra_max; ra_ptr++)
|
||||||
brelse(bh_use[ra_ptr]);
|
brelse(bh_use[ra_ptr]);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
|
||||||
* FILE: recover.c
|
* FILE: recover.c
|
||||||
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
* PROGRAMMER: Matt Wu <mattwu@163.com>
|
||||||
* HOMEPAGE: http://ext2.yeah.net
|
* HOMEPAGE: http://www.ext2fsd.com
|
||||||
* UPDATE HISTORY:
|
* UPDATE HISTORY:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -52,3 +52,17 @@ void extents_brelse(struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
brelse(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);
|
||||||
|
}
|
||||||
|
|
|
@ -878,7 +878,7 @@ static int ext4_ext_split(void *icb, handle_t *handle, struct inode *inode,
|
||||||
neh = ext_block_hdr(bh);
|
neh = ext_block_hdr(bh);
|
||||||
neh->eh_entries = 0;
|
neh->eh_entries = 0;
|
||||||
neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 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;
|
neh->eh_depth = 0;
|
||||||
|
|
||||||
/* move remainder of path[depth] to the new leaf */
|
/* 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 = ext_block_hdr(bh);
|
||||||
neh->eh_entries = cpu_to_le16(1);
|
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_max = cpu_to_le16(ext4_ext_space_block_idx(inode, 0));
|
||||||
neh->eh_depth = cpu_to_le16(depth - i);
|
neh->eh_depth = cpu_to_le16(depth - i);
|
||||||
fidx = EXT_FIRST_INDEX(neh);
|
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
|
/* old root could have indexes or leaves
|
||||||
* so calculate e_max right way */
|
* so calculate e_max right way */
|
||||||
if (ext_depth(inode))
|
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
|
else
|
||||||
neh->eh_max = (ext4_ext_space_block(inode, 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);
|
||||||
ext4_extent_block_csum_set(inode, neh);
|
ext4_extent_block_csum_set(inode, neh);
|
||||||
set_buffer_uptodate(bh);
|
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 */
|
/* Update top-level index: num,max,pointer */
|
||||||
neh = ext_inode_hdr(inode);
|
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);
|
ext4_idx_store_pblock(EXT_FIRST_INDEX(neh), newblock);
|
||||||
if (neh->eh_depth == 0) {
|
if (neh->eh_depth == 0) {
|
||||||
/* Root extent block becomes index block */
|
/* 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_INDEX(neh)->ei_block =
|
||||||
EXT_FIRST_EXTENT(neh)->ee_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 = ext_inode_hdr(inode);
|
||||||
eh->eh_depth = 0;
|
eh->eh_depth = 0;
|
||||||
eh->eh_entries = 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));
|
eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode, 0));
|
||||||
ext4_mark_inode_dirty(icb, handle, inode);
|
ext4_mark_inode_dirty(icb, handle, inode);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2502,6 +2502,17 @@ out2:
|
||||||
return err ? err : allocated;
|
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
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,7 +33,7 @@ Ext2MapExtent(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EXT4_EXTENT_HEADER *eh;
|
EXT4_EXTENT_HEADER *eh;
|
||||||
struct buffer_head bh_got;
|
struct buffer_head bh_got = {0};
|
||||||
int flags, rc;
|
int flags, rc;
|
||||||
ULONG max_blocks = 0;
|
ULONG max_blocks = 0;
|
||||||
|
|
||||||
|
@ -67,6 +67,16 @@ Ext2MapExtent(
|
||||||
flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
|
flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
|
||||||
max_blocks = EXT_UNWRITTEN_MAX_LEN;
|
max_blocks = EXT_UNWRITTEN_MAX_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Alloc) {
|
||||||
|
if (Number && !*Number) {
|
||||||
|
if (max_blocks > *Number) {
|
||||||
|
max_blocks = *Number;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
max_blocks = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((rc = ext4_ext_get_blocks(
|
if ((rc = ext4_ext_get_blocks(
|
||||||
IrpContext,
|
IrpContext,
|
||||||
|
@ -209,7 +219,7 @@ Ext2TruncateExtent(
|
||||||
/* calculate blocks to be freed */
|
/* calculate blocks to be freed */
|
||||||
Extra = End - Wanted;
|
Extra = End - Wanted;
|
||||||
|
|
||||||
err = ext4_ext_remove_space(IrpContext, &Mcb->Inode, Wanted);
|
err = ext4_ext_truncate(IrpContext, &Mcb->Inode, Wanted);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
if (!Ext2RemoveBlockExtent(Vcb, Mcb, Wanted, Extra)) {
|
if (!Ext2RemoveBlockExtent(Vcb, Mcb, Wanted, Extra)) {
|
||||||
ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
|
ClearFlag(Mcb->Flags, MCB_ZONE_INITED);
|
||||||
|
@ -224,9 +234,10 @@ Ext2TruncateExtent(
|
||||||
Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS);
|
Size->QuadPart += ((ULONGLONG)Extra << BLOCK_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* save inode */
|
|
||||||
if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart))
|
if (Mcb->Inode.i_size > (loff_t)(Size->QuadPart))
|
||||||
Mcb->Inode.i_size = (loff_t)(Size->QuadPart);
|
Mcb->Inode.i_size = (loff_t)(Size->QuadPart);
|
||||||
|
|
||||||
|
/* Save modifications on i_blocks field and i_size field of the inode. */
|
||||||
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
|
Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
|
|
@ -213,18 +213,24 @@ Ext2FastIoWrite (
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE);
|
if (ExAcquireResourceExclusiveLite(&Fcb->MainResource, Wait))
|
||||||
Locked = TRUE;
|
Locked = TRUE;
|
||||||
|
else
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
|
||||||
if (IsWritingToEof(*FileOffset) ||
|
if (IsWritingToEof(*FileOffset) ||
|
||||||
Fcb->Header.ValidDataLength.QuadPart < FileOffset->QuadPart ||
|
|
||||||
Fcb->Header.FileSize.QuadPart < FileOffset->QuadPart + Length ) {
|
Fcb->Header.FileSize.QuadPart < FileOffset->QuadPart + Length ) {
|
||||||
Status = FALSE;
|
Status = FALSE;
|
||||||
} else {
|
_SEH2_LEAVE;
|
||||||
ExReleaseResourceLite(&Fcb->MainResource);
|
}
|
||||||
Locked = FALSE;
|
|
||||||
Status = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait,
|
Status = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait,
|
||||||
LockKey, Buffer, IoStatus, DeviceObject);
|
LockKey, Buffer, IoStatus, DeviceObject);
|
||||||
|
if (Status) {
|
||||||
|
if (IoStatus)
|
||||||
|
Length = (ULONG)IoStatus->Information;
|
||||||
|
if (Fcb->Header.ValidDataLength.QuadPart < FileOffset->QuadPart + Length)
|
||||||
|
Fcb->Header.ValidDataLength.QuadPart = FileOffset->QuadPart + Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
} _SEH2_FINALLY {
|
} _SEH2_FINALLY {
|
||||||
|
@ -251,6 +257,8 @@ Ext2FastIoQueryBasicInfo (
|
||||||
IN PDEVICE_OBJECT DeviceObject)
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
PEXT2_FCB Fcb = NULL;
|
PEXT2_FCB Fcb = NULL;
|
||||||
|
PEXT2_CCB Ccb = NULL;
|
||||||
|
PEXT2_MCB Mcb = NULL;
|
||||||
BOOLEAN Status = FALSE;
|
BOOLEAN Status = FALSE;
|
||||||
BOOLEAN FcbMainResourceAcquired = FALSE;
|
BOOLEAN FcbMainResourceAcquired = FALSE;
|
||||||
|
|
||||||
|
@ -270,7 +278,8 @@ Ext2FastIoQueryBasicInfo (
|
||||||
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
Ccb = (PEXT2_CCB) FileObject->FsContext2;
|
||||||
|
Mcb = Fcb->Mcb;
|
||||||
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
||||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||||
#if EXT2_DEBUG
|
#if EXT2_DEBUG
|
||||||
|
@ -302,17 +311,11 @@ Ext2FastIoQueryBasicInfo (
|
||||||
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
|
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (IsRoot(Fcb)) {
|
Buffer->CreationTime = Mcb->CreationTime;
|
||||||
Buffer->CreationTime = Buffer->LastAccessTime =
|
Buffer->LastAccessTime = Mcb->LastAccessTime;
|
||||||
Buffer->LastWriteTime = Buffer->ChangeTime = Ext2NtTime(0);
|
Buffer->LastWriteTime = Mcb->LastWriteTime;
|
||||||
} else {
|
Buffer->ChangeTime = Mcb->ChangeTime;
|
||||||
Buffer->CreationTime = Fcb->Mcb->CreationTime;
|
Buffer->FileAttributes = Mcb->FileAttr;
|
||||||
Buffer->LastAccessTime = Fcb->Mcb->LastAccessTime;
|
|
||||||
Buffer->LastWriteTime = Fcb->Mcb->LastWriteTime;
|
|
||||||
Buffer->ChangeTime = Fcb->Mcb->ChangeTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
Buffer->FileAttributes = Fcb->Mcb->FileAttr;
|
|
||||||
if (Buffer->FileAttributes == 0) {
|
if (Buffer->FileAttributes == 0) {
|
||||||
Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||||
}
|
}
|
||||||
|
@ -368,8 +371,8 @@ Ext2FastIoQueryStandardInfo (
|
||||||
{
|
{
|
||||||
|
|
||||||
BOOLEAN Status = FALSE;
|
BOOLEAN Status = FALSE;
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb = NULL;
|
||||||
BOOLEAN FcbMainResourceAcquired = FALSE;
|
BOOLEAN FcbMainResourceAcquired = FALSE;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
@ -892,10 +895,11 @@ Ext2FastIoQueryNetworkOpenInfo (
|
||||||
IN PDEVICE_OBJECT DeviceObject
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
BOOLEAN bResult = FALSE;
|
|
||||||
|
|
||||||
PEXT2_FCB Fcb = NULL;
|
PEXT2_FCB Fcb = NULL;
|
||||||
|
PEXT2_CCB Ccb = NULL;
|
||||||
|
PEXT2_MCB Mcb = NULL;
|
||||||
|
|
||||||
|
BOOLEAN bResult = FALSE;
|
||||||
BOOLEAN FcbResourceAcquired = FALSE;
|
BOOLEAN FcbResourceAcquired = FALSE;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
@ -916,6 +920,8 @@ Ext2FastIoQueryNetworkOpenInfo (
|
||||||
|
|
||||||
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
||||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||||
|
Ccb = (PEXT2_CCB) FileObject->FsContext2;
|
||||||
|
Mcb = Fcb->Mcb;
|
||||||
|
|
||||||
#if EXT2_DEBUG
|
#if EXT2_DEBUG
|
||||||
DEBUG(DL_INF, (
|
DEBUG(DL_INF, (
|
||||||
|
@ -925,7 +931,7 @@ Ext2FastIoQueryNetworkOpenInfo (
|
||||||
));
|
));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (FileObject->FsContext2) {
|
if (!Ccb) {
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -949,22 +955,15 @@ Ext2FastIoQueryNetworkOpenInfo (
|
||||||
PFNOI->EndOfFile = Fcb->Header.FileSize;
|
PFNOI->EndOfFile = Fcb->Header.FileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
PFNOI->FileAttributes = Fcb->Mcb->FileAttr;
|
PFNOI->FileAttributes = Mcb->FileAttr;
|
||||||
if (PFNOI->FileAttributes == 0) {
|
if (PFNOI->FileAttributes == 0) {
|
||||||
PFNOI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
PFNOI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsRoot(Fcb)) {
|
PFNOI->CreationTime = Mcb->CreationTime;
|
||||||
PFNOI->CreationTime =
|
PFNOI->LastAccessTime = Mcb->LastAccessTime;
|
||||||
PFNOI->LastAccessTime =
|
PFNOI->LastWriteTime = Mcb->LastWriteTime;
|
||||||
PFNOI->LastWriteTime =
|
PFNOI->ChangeTime = Mcb->ChangeTime;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bResult = TRUE;
|
bResult = TRUE;
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ extern PEXT2_GLOBAL Ext2Global;
|
||||||
#pragma alloc_text(PAGE, Ext2TruncateFile)
|
#pragma alloc_text(PAGE, Ext2TruncateFile)
|
||||||
#pragma alloc_text(PAGE, Ext2SetDispositionInfo)
|
#pragma alloc_text(PAGE, Ext2SetDispositionInfo)
|
||||||
#pragma alloc_text(PAGE, Ext2SetRenameInfo)
|
#pragma alloc_text(PAGE, Ext2SetRenameInfo)
|
||||||
|
#pragma alloc_text(PAGE, Ext2SetLinkInfo)
|
||||||
#pragma alloc_text(PAGE, Ext2DeleteFile)
|
#pragma alloc_text(PAGE, Ext2DeleteFile)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -34,11 +35,11 @@ Ext2QueryFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject;
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb = NULL;
|
||||||
PEXT2_MCB Mcb;
|
PEXT2_MCB Mcb = NULL;
|
||||||
PEXT2_CCB Ccb;
|
PEXT2_CCB Ccb = NULL;
|
||||||
PIRP Irp;
|
PIRP Irp = NULL;
|
||||||
PIO_STACK_LOCATION IoStackLocation;
|
PIO_STACK_LOCATION IoStackLocation;
|
||||||
FILE_INFORMATION_CLASS FileInformationClass;
|
FILE_INFORMATION_CLASS FileInformationClass;
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
|
@ -489,13 +490,13 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject = NULL;
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb = NULL;
|
||||||
PEXT2_CCB Ccb;
|
PEXT2_CCB Ccb = NULL;
|
||||||
PEXT2_MCB Mcb;
|
PEXT2_MCB Mcb = NULL;
|
||||||
PIRP Irp;
|
PIRP Irp = NULL;
|
||||||
PIO_STACK_LOCATION IoStackLocation;
|
PIO_STACK_LOCATION IoStackLocation = NULL;
|
||||||
FILE_INFORMATION_CLASS FileInformationClass;
|
FILE_INFORMATION_CLASS FileInformationClass;
|
||||||
|
|
||||||
ULONG NotifyFilter = 0;
|
ULONG NotifyFilter = 0;
|
||||||
|
@ -541,8 +542,9 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we need grab Vcb in case it's a rename operation */
|
/* we need grab Vcb in case it's rename or sethardlink */
|
||||||
if (FileInformationClass == FileRenameInformation) {
|
if (FileInformationClass == FileRenameInformation ||
|
||||||
|
FileInformationClass == FileLinkInformation) {
|
||||||
if (!ExAcquireResourceExclusiveLite(
|
if (!ExAcquireResourceExclusiveLite(
|
||||||
&Vcb->MainResource,
|
&Vcb->MainResource,
|
||||||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
|
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
|
||||||
|
@ -616,10 +618,11 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
|
Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for renaming, we must not get any Fcb locks here, function
|
/* for renaming or set link, we must not grab any Fcb locks,
|
||||||
Ext2SetRenameInfo will get Dcb resource exclusively. */
|
and later we will get Dcb or Fcb resources exclusively. */
|
||||||
if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE) &&
|
if (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE) &&
|
||||||
FileInformationClass != FileRenameInformation) {
|
FileInformationClass != FileRenameInformation &&
|
||||||
|
FileInformationClass != FileLinkInformation) {
|
||||||
|
|
||||||
if (!ExAcquireResourceExclusiveLite(
|
if (!ExAcquireResourceExclusiveLite(
|
||||||
&Fcb->MainResource,
|
&Fcb->MainResource,
|
||||||
|
@ -975,6 +978,14 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case FileLinkInformation:
|
||||||
|
{
|
||||||
|
Status = Ext2SetLinkInfo(IrpContext, Vcb, Fcb, Ccb);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
//
|
//
|
||||||
// This is the only set file information request supported on read
|
// This is the only set file information request supported on read
|
||||||
// only file systems
|
// only file systems
|
||||||
|
@ -1006,11 +1017,6 @@ Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileLinkInformation:
|
|
||||||
|
|
||||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG(DL_WRN, ( "Ext2SetInformation: invalid class: %d\n",
|
DEBUG(DL_WRN, ( "Ext2SetInformation: invalid class: %d\n",
|
||||||
FileInformationClass));
|
FileInformationClass));
|
||||||
|
@ -1656,6 +1662,262 @@ errorout:
|
||||||
return Status;
|
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
|
ULONG
|
||||||
Ext2InodeType(PEXT2_MCB Mcb)
|
Ext2InodeType(PEXT2_MCB Mcb)
|
||||||
{
|
{
|
||||||
|
@ -1705,7 +1967,6 @@ Ext2DeleteFile(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
|
||||||
Ext2ReferMcb(Mcb);
|
Ext2ReferMcb(Mcb);
|
||||||
|
|
|
@ -96,39 +96,48 @@ Ext2FlushFile (
|
||||||
IN PEXT2_CCB Ccb
|
IN PEXT2_CCB Ccb
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
IO_STATUS_BLOCK IoStatus;
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
|
||||||
ASSERT(Fcb != NULL);
|
ASSERT(Fcb != NULL);
|
||||||
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
|
||||||
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
|
||||||
|
|
||||||
/* update timestamp and achieve attribute */
|
_SEH2_TRY {
|
||||||
if (Ccb != NULL) {
|
|
||||||
|
|
||||||
if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
|
/* update timestamp and achieve attribute */
|
||||||
|
if (Ccb != NULL) {
|
||||||
|
|
||||||
LARGE_INTEGER SysTime;
|
if (!IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) {
|
||||||
KeQuerySystemTime(&SysTime);
|
|
||||||
|
|
||||||
Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime);
|
LARGE_INTEGER SysTime;
|
||||||
Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_mtime);
|
KeQuerySystemTime(&SysTime);
|
||||||
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)) {
|
if (IsDirectory(Fcb)) {
|
||||||
return STATUS_SUCCESS;
|
IoStatus.Status = STATUS_SUCCESS;
|
||||||
}
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n",
|
DEBUG(DL_INF, ( "Ext2FlushFile: Flushing File Inode=%xh %S ...\n",
|
||||||
Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer));
|
Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer));
|
||||||
|
|
||||||
CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
|
CcFlushCache(&(Fcb->SectionObject), NULL, 0, &IoStatus);
|
||||||
ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
|
ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
|
||||||
|
|
||||||
|
} _SEH2_FINALLY {
|
||||||
|
|
||||||
|
/* do cleanup here */
|
||||||
|
} _SEH2_END;
|
||||||
|
|
||||||
return IoStatus.Status;
|
return IoStatus.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
|
@ -189,9 +198,7 @@ Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
MainResourceAcquired =
|
MainResourceAcquired =
|
||||||
ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource,
|
ExAcquireResourceExclusiveLite(&FcbOrVcb->MainResource, TRUE);
|
||||||
IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
|
|
||||||
|
|
||||||
ASSERT(MainResourceAcquired);
|
ASSERT(MainResourceAcquired);
|
||||||
DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n",
|
DEBUG(DL_INF, ("Ext2Flush-pre: total mcb records=%u\n",
|
||||||
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
|
FsRtlNumberOfRunsInLargeMcb(&Vcb->Extents)));
|
||||||
|
@ -265,4 +272,4 @@ Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
} _SEH2_END;
|
} _SEH2_END;
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@ Ext2LockVolume (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IrpSp;
|
PIO_STACK_LOCATION IrpSp;
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
|
|
||||||
|
@ -242,10 +242,10 @@ Ext2UnlockVolume (
|
||||||
IN PEXT2_IRP_CONTEXT IrpContext
|
IN PEXT2_IRP_CONTEXT IrpContext
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IrpSp;
|
PIO_STACK_LOCATION IrpSp = NULL;
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject = NULL;
|
||||||
|
PEXT2_VCB Vcb = NULL;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PEXT2_VCB Vcb;
|
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
@ -1289,6 +1289,595 @@ Ext2GetRetrievalPointerBase (
|
||||||
return Status;
|
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
|
NTSTATUS
|
||||||
Ext2UserFsRequest (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2UserFsRequest (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
@ -1304,7 +1893,6 @@ Ext2UserFsRequest (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
|
||||||
|
|
||||||
Irp = IrpContext->Irp;
|
Irp = IrpContext->Irp;
|
||||||
|
|
||||||
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
#ifndef _GNU_NTIFS_
|
#ifndef _GNU_NTIFS_
|
||||||
|
@ -1317,6 +1905,18 @@ Ext2UserFsRequest (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
switch (FsControlCode) {
|
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:
|
case FSCTL_LOCK_VOLUME:
|
||||||
Status = Ext2LockVolume(IrpContext);
|
Status = Ext2LockVolume(IrpContext);
|
||||||
break;
|
break;
|
||||||
|
@ -1513,6 +2113,10 @@ Ext2MountVolume (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
VolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1);
|
VolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1);
|
||||||
ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING);
|
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 >
|
if (TargetDeviceObject->AlignmentRequirement >
|
||||||
VolumeDeviceObject->AlignmentRequirement) {
|
VolumeDeviceObject->AlignmentRequirement) {
|
||||||
|
|
||||||
|
@ -1520,6 +2124,14 @@ Ext2MountVolume (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
TargetDeviceObject->AlignmentRequirement;
|
TargetDeviceObject->AlignmentRequirement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DiskGeometry.BytesPerSector - 1 >
|
||||||
|
VolumeDeviceObject->AlignmentRequirement) {
|
||||||
|
VolumeDeviceObject->AlignmentRequirement =
|
||||||
|
DiskGeometry.BytesPerSector - 1;
|
||||||
|
TargetDeviceObject->AlignmentRequirement =
|
||||||
|
DiskGeometry.BytesPerSector - 1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
(IoStackLocation->Parameters.MountVolume.Vpb)->DeviceObject =
|
(IoStackLocation->Parameters.MountVolume.Vpb)->DeviceObject =
|
||||||
VolumeDeviceObject;
|
VolumeDeviceObject;
|
||||||
Vpb = IoStackLocation->Parameters.MountVolume.Vpb;
|
Vpb = IoStackLocation->Parameters.MountVolume.Vpb;
|
||||||
|
@ -1891,7 +2503,7 @@ Ext2DismountVolume (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
@ -1968,11 +2580,12 @@ Ext2CheckDismount (
|
||||||
BOOLEAN bDeleted = FALSE, bTearDown = FALSE;
|
BOOLEAN bDeleted = FALSE, bTearDown = FALSE;
|
||||||
ULONG UnCleanCount = 0;
|
ULONG UnCleanCount = 0;
|
||||||
|
|
||||||
NewVpb = Ext2AllocatePool(NonPagedPool, VPB_SIZE, TAG_VPB);
|
NewVpb = ExAllocatePoolWithTag(NonPagedPool, VPB_SIZE, TAG_VPB);
|
||||||
if (NewVpb == NULL) {
|
if (NewVpb == NULL) {
|
||||||
DEBUG(DL_ERR, ( "Ex2CheckDismount: failed to allocate NewVpb.\n"));
|
DEBUG(DL_ERR, ( "Ex2CheckDismount: failed to allocate NewVpb.\n"));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
DEBUG(DL_DBG, ("Ext2CheckDismount: NewVpb allocated: %p\n", NewVpb));
|
||||||
INC_MEM_COUNT(PS_VPB, NewVpb, sizeof(VPB));
|
INC_MEM_COUNT(PS_VPB, NewVpb, sizeof(VPB));
|
||||||
memset(NewVpb, '_', VPB_SIZE);
|
memset(NewVpb, '_', VPB_SIZE);
|
||||||
RtlZeroMemory(NewVpb, sizeof(VPB));
|
RtlZeroMemory(NewVpb, sizeof(VPB));
|
||||||
|
@ -1985,15 +2598,16 @@ Ext2CheckDismount (
|
||||||
|
|
||||||
if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
|
if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
|
||||||
(IrpContext->RealDevice == Vcb->RealDevice)) {
|
(IrpContext->RealDevice == Vcb->RealDevice)) {
|
||||||
UnCleanCount = 3;
|
|
||||||
} else {
|
|
||||||
UnCleanCount = 2;
|
UnCleanCount = 2;
|
||||||
|
} else {
|
||||||
|
UnCleanCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
IoAcquireVpbSpinLock (&Irql);
|
IoAcquireVpbSpinLock (&Irql);
|
||||||
|
|
||||||
DEBUG(DL_DBG, ("Ext2CheckDismount: Vpb %p ioctl=%d Device %p\n",
|
DEBUG(DL_DBG, ("Ext2CheckDismount: Vpb %p ioctl=%d Device %p\n",
|
||||||
Vpb, Vpb->ReferenceCount, Vpb->RealDevice));
|
Vpb, Vpb->ReferenceCount, Vpb->RealDevice));
|
||||||
|
|
||||||
if (Vpb->ReferenceCount <= UnCleanCount) {
|
if (Vpb->ReferenceCount <= UnCleanCount) {
|
||||||
|
|
||||||
if (!IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
|
if (!IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
|
||||||
|
@ -2018,10 +2632,17 @@ Ext2CheckDismount (
|
||||||
Vpb->DeviceObject = NULL;
|
Vpb->DeviceObject = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG(DL_DBG, ("Ext2CheckDismount: Vpb: %p bDeleted=%d bTearDown=%d\n",
|
||||||
|
Vpb, bDeleted, bTearDown));
|
||||||
|
|
||||||
|
|
||||||
} else if (bForce) {
|
} else if (bForce) {
|
||||||
|
|
||||||
DEBUG(DL_DBG, ( "Ext2CheckDismount: NewVpb %p Realdevice = %p\n",
|
DEBUG(DL_DBG, ( "Ext2CheckDismount: New/Old Vpb %p/%p Realdevice = %p\n",
|
||||||
NewVpb, Vpb->RealDevice));
|
NewVpb, Vcb->Vpb, Vpb->RealDevice));
|
||||||
|
|
||||||
|
/* keep vpb president and later we'll free it */
|
||||||
|
SetFlag(Vpb->Flags, VPB_PERSISTENT);
|
||||||
|
|
||||||
Vcb->Vpb2 = Vcb->Vpb;
|
Vcb->Vpb2 = Vcb->Vpb;
|
||||||
NewVpb->Type = IO_TYPE_VPB;
|
NewVpb->Type = IO_TYPE_VPB;
|
||||||
|
@ -2051,8 +2672,8 @@ Ext2CheckDismount (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NewVpb != NULL) {
|
if (NewVpb != NULL) {
|
||||||
DEBUG(DL_DBG, ( "Ext2CheckDismount: freeing Vpb %p\n", NewVpb));
|
DEBUG(DL_DBG, ( "Ext2CheckDismount: freeing new Vpb %p\n", NewVpb));
|
||||||
Ext2FreePool(NewVpb, TAG_VPB);
|
ExFreePoolWithTag(NewVpb, TAG_VPB);
|
||||||
DEC_MEM_COUNT(PS_VPB, NewVpb, sizeof(VPB));
|
DEC_MEM_COUNT(PS_VPB, NewVpb, sizeof(VPB));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2081,8 +2702,6 @@ Ext2PurgeVolume (IN PEXT2_VCB Vcb,
|
||||||
FlushBeforePurge = FALSE;
|
FlushBeforePurge = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ext2PutGroup(Vcb);
|
|
||||||
|
|
||||||
FcbListEntry= NULL;
|
FcbListEntry= NULL;
|
||||||
InitializeListHead(&FcbList);
|
InitializeListHead(&FcbList);
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,12 @@ PEXT2_GLOBAL Ext2Global = NULL;
|
||||||
/*
|
/*
|
||||||
* Ext2Fsd version, building date/time
|
* Ext2Fsd version, building date/time
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CHAR gVersion[] = EXT2FSD_VERSION;
|
CHAR gVersion[] = EXT2FSD_VERSION;
|
||||||
CHAR gTime[] = __TIME__;
|
CHAR gTime[] = __TIME__;
|
||||||
CHAR gDate[] = __DATE__;
|
CHAR gDate[] = __DATE__;
|
||||||
|
|
||||||
|
|
||||||
/* DEFINITIONS ***********************************************************/
|
/* DEFINITIONS ***********************************************************/
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
|
@ -417,8 +419,8 @@ DriverEntry (
|
||||||
" Free"
|
" Free"
|
||||||
#endif
|
#endif
|
||||||
" -- "
|
" -- "
|
||||||
__DATE__" "
|
__DATE__ " "
|
||||||
__TIME__".\n");
|
__TIME__ ".\n");
|
||||||
|
|
||||||
DEBUG(DL_FUN, ( "Ext2 DriverEntry ...\n"));
|
DEBUG(DL_FUN, ( "Ext2 DriverEntry ...\n"));
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,9 @@ int log_start_commit(journal_t *journal, tid_t tid)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
spin_lock(&journal->j_state_lock);
|
jbd_lock(&journal->j_state_lock);
|
||||||
ret = __log_start_commit(journal, tid);
|
ret = __log_start_commit(journal, tid);
|
||||||
spin_unlock(&journal->j_state_lock);
|
jbd_unlock(&journal->j_state_lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,12 +69,12 @@ static void __journal_abort_hard(journal_t *journal)
|
||||||
if (journal->j_flags & JFS_ABORT)
|
if (journal->j_flags & JFS_ABORT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock(&journal->j_state_lock);
|
jbd_lock(&journal->j_state_lock);
|
||||||
journal->j_flags |= JFS_ABORT;
|
journal->j_flags |= JFS_ABORT;
|
||||||
transaction = journal->j_running_transaction;
|
transaction = journal->j_running_transaction;
|
||||||
if (transaction)
|
if (transaction)
|
||||||
__log_start_commit(journal, transaction->t_tid);
|
__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,
|
/* Soft abort: record the abort error status in the journal superblock,
|
||||||
|
@ -160,12 +160,12 @@ int journal_errno(journal_t *journal)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
spin_lock(&journal->j_state_lock);
|
jbd_lock(&journal->j_state_lock);
|
||||||
if (journal->j_flags & JFS_ABORT)
|
if (journal->j_flags & JFS_ABORT)
|
||||||
err = -EROFS;
|
err = -EROFS;
|
||||||
else
|
else
|
||||||
err = journal->j_errno;
|
err = journal->j_errno;
|
||||||
spin_unlock(&journal->j_state_lock);
|
jbd_unlock(&journal->j_state_lock);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,12 +180,12 @@ int journal_clear_err(journal_t *journal)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
spin_lock(&journal->j_state_lock);
|
jbd_lock(&journal->j_state_lock);
|
||||||
if (journal->j_flags & JFS_ABORT)
|
if (journal->j_flags & JFS_ABORT)
|
||||||
err = -EROFS;
|
err = -EROFS;
|
||||||
else
|
else
|
||||||
journal->j_errno = 0;
|
journal->j_errno = 0;
|
||||||
spin_unlock(&journal->j_state_lock);
|
jbd_unlock(&journal->j_state_lock);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,10 +198,10 @@ int journal_clear_err(journal_t *journal)
|
||||||
*/
|
*/
|
||||||
void journal_ack_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)
|
if (journal->j_errno)
|
||||||
journal->j_flags |= JFS_ACK_ERR;
|
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)
|
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;
|
unsigned long blocknr;
|
||||||
|
|
||||||
spin_lock(&journal->j_state_lock);
|
jbd_lock(&journal->j_state_lock);
|
||||||
J_ASSERT(journal->j_free > 1);
|
J_ASSERT(journal->j_free > 1);
|
||||||
|
|
||||||
blocknr = journal->j_head;
|
blocknr = journal->j_head;
|
||||||
|
@ -470,7 +470,7 @@ int journal_next_log_block(journal_t *journal, unsigned long *retp)
|
||||||
journal->j_free--;
|
journal->j_free--;
|
||||||
if (journal->j_head == journal->j_last)
|
if (journal->j_head == journal->j_last)
|
||||||
journal->j_head = journal->j_first;
|
journal->j_head = journal->j_first;
|
||||||
spin_unlock(&journal->j_state_lock);
|
jbd_unlock(&journal->j_state_lock);
|
||||||
return journal_bmap(journal, blocknr, retp);
|
return journal_bmap(journal, blocknr, retp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,9 +561,9 @@ static journal_t * journal_init_common (void)
|
||||||
init_waitqueue_head(&journal->j_wait_updates);
|
init_waitqueue_head(&journal->j_wait_updates);
|
||||||
mutex_init(&journal->j_barrier);
|
mutex_init(&journal->j_barrier);
|
||||||
mutex_init(&journal->j_checkpoint_mutex);
|
mutex_init(&journal->j_checkpoint_mutex);
|
||||||
spin_lock_init(&journal->j_revoke_lock);
|
jbd_lock_init(&journal->j_revoke_lock);
|
||||||
spin_lock_init(&journal->j_list_lock);
|
jbd_lock_init(&journal->j_list_lock);
|
||||||
spin_lock_init(&journal->j_state_lock);
|
jbd_lock_init(&journal->j_state_lock);
|
||||||
|
|
||||||
journal->j_commit_interval = (HZ * JBD_DEFAULT_MAX_COMMIT_AGE);
|
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 */
|
/* Force any old transactions to disk */
|
||||||
|
|
||||||
/* Totally anal locking here... */
|
/* Totally anal locking here... */
|
||||||
spin_lock(&journal->j_list_lock);
|
jbd_lock(&journal->j_list_lock);
|
||||||
while (journal->j_checkpoint_transactions != NULL) {
|
while (journal->j_checkpoint_transactions != NULL) {
|
||||||
spin_unlock(&journal->j_list_lock);
|
jbd_unlock(&journal->j_list_lock);
|
||||||
log_do_checkpoint(journal);
|
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_running_transaction == NULL);
|
||||||
J_ASSERT(journal->j_committing_transaction == NULL);
|
J_ASSERT(journal->j_committing_transaction == NULL);
|
||||||
J_ASSERT(journal->j_checkpoint_transactions == 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. */
|
/* We can now mark the journal as empty. */
|
||||||
journal->j_tail = 0;
|
journal->j_tail = 0;
|
||||||
|
@ -1048,14 +1048,14 @@ void journal_update_superblock(journal_t *journal, int wait)
|
||||||
goto out;
|
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",
|
jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n",
|
||||||
journal->j_tail, journal->j_tail_sequence, journal->j_errno);
|
journal->j_tail, journal->j_tail_sequence, journal->j_errno);
|
||||||
|
|
||||||
sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
|
sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
|
||||||
sb->s_start = cpu_to_be32(journal->j_tail);
|
sb->s_start = cpu_to_be32(journal->j_tail);
|
||||||
sb->s_errno = cpu_to_be32(journal->j_errno);
|
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");
|
BUFFER_TRACE(bh, "marking dirty");
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
|
@ -1069,12 +1069,12 @@ out:
|
||||||
* any future commit will have to be careful to update the
|
* any future commit will have to be careful to update the
|
||||||
* superblock again to re-record the true start of the log. */
|
* 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)
|
if (sb->s_start)
|
||||||
journal->j_flags &= ~JFS_FLUSHED;
|
journal->j_flags &= ~JFS_FLUSHED;
|
||||||
else
|
else
|
||||||
journal->j_flags |= JFS_FLUSHED;
|
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));
|
J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh));
|
||||||
transaction = jh->b_transaction;
|
transaction = jh->b_transaction;
|
||||||
if (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);
|
J_ASSERT_JH(jh, jh->b_jlist < BJ_Types);
|
||||||
if (jh->b_jlist != BJ_None)
|
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)
|
void journal_unfile_buffer(journal_t *journal, struct journal_head *jh)
|
||||||
{
|
{
|
||||||
jbd_lock_bh_state(jh2bh(jh));
|
jbd_lock_bh_state(jh2bh(jh));
|
||||||
spin_lock(&journal->j_list_lock);
|
jbd_lock(&journal->j_list_lock);
|
||||||
__journal_unfile_buffer(jh);
|
__journal_unfile_buffer(jh);
|
||||||
spin_unlock(&journal->j_list_lock);
|
jbd_unlock(&journal->j_list_lock);
|
||||||
jbd_unlock_bh_state(jh2bh(jh));
|
jbd_unlock_bh_state(jh2bh(jh));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1342,7 +1342,7 @@ void __journal_file_buffer(struct journal_head *jh,
|
||||||
struct buffer_head *bh = jh2bh(jh);
|
struct buffer_head *bh = jh2bh(jh);
|
||||||
|
|
||||||
J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh));
|
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_jlist < BJ_Types);
|
||||||
J_ASSERT_JH(jh, jh->b_transaction == transaction ||
|
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)
|
transaction_t *transaction, int jlist)
|
||||||
{
|
{
|
||||||
jbd_lock_bh_state(jh2bh(jh));
|
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);
|
__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));
|
jbd_unlock_bh_state(jh2bh(jh));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1455,7 +1455,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
|
||||||
BUFFER_TRACE(bh, "entry");
|
BUFFER_TRACE(bh, "entry");
|
||||||
|
|
||||||
jbd_lock_bh_state(bh);
|
jbd_lock_bh_state(bh);
|
||||||
spin_lock(&journal->j_list_lock);
|
jbd_lock(&journal->j_list_lock);
|
||||||
|
|
||||||
if (!buffer_jbd(bh))
|
if (!buffer_jbd(bh))
|
||||||
goto not_jbd;
|
goto not_jbd;
|
||||||
|
@ -1508,7 +1508,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
|
||||||
journal_remove_journal_head(bh);
|
journal_remove_journal_head(bh);
|
||||||
__brelse(bh);
|
__brelse(bh);
|
||||||
if (!buffer_jbd(bh)) {
|
if (!buffer_jbd(bh)) {
|
||||||
spin_unlock(&journal->j_list_lock);
|
jbd_unlock(&journal->j_list_lock);
|
||||||
jbd_unlock_bh_state(bh);
|
jbd_unlock_bh_state(bh);
|
||||||
__bforget(bh);
|
__bforget(bh);
|
||||||
goto drop;
|
goto drop;
|
||||||
|
@ -1531,7 +1531,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
|
||||||
}
|
}
|
||||||
|
|
||||||
not_jbd:
|
not_jbd:
|
||||||
spin_unlock(&journal->j_list_lock);
|
jbd_unlock(&journal->j_list_lock);
|
||||||
jbd_unlock_bh_state(bh);
|
jbd_unlock_bh_state(bh);
|
||||||
__brelse(bh);
|
__brelse(bh);
|
||||||
drop:
|
drop:
|
||||||
|
|
|
@ -131,9 +131,9 @@ repeat:
|
||||||
record->sequence = seq;
|
record->sequence = seq;
|
||||||
record->blocknr = blocknr;
|
record->blocknr = blocknr;
|
||||||
hash_list = &journal->j_revoke->hash_table[hash(journal, 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);
|
list_add(&record->hash, hash_list);
|
||||||
spin_unlock(&journal->j_revoke_lock);
|
jbd_unlock(&journal->j_revoke_lock);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
oom:
|
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)];
|
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;
|
record = (struct jbd_revoke_record_s *) hash_list->next;
|
||||||
while (&(record->hash) != hash_list) {
|
while (&(record->hash) != hash_list) {
|
||||||
if (record->blocknr == blocknr) {
|
if (record->blocknr == blocknr) {
|
||||||
spin_unlock(&journal->j_revoke_lock);
|
jbd_unlock(&journal->j_revoke_lock);
|
||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
record = (struct jbd_revoke_record_s *) record->hash.next;
|
record = (struct jbd_revoke_record_s *) record->hash.next;
|
||||||
}
|
}
|
||||||
spin_unlock(&journal->j_revoke_lock);
|
jbd_unlock(&journal->j_revoke_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@ int journal_init_revoke(journal_t *journal, int hash_size)
|
||||||
for (tmp = 0; tmp < hash_size; tmp++)
|
for (tmp = 0; tmp < hash_size; tmp++)
|
||||||
INIT_LIST_HEAD(&journal->j_revoke->hash_table[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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -447,9 +447,9 @@ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
|
||||||
if (record) {
|
if (record) {
|
||||||
jbd_debug(4, "cancelled existing revoke on "
|
jbd_debug(4, "cancelled existing revoke on "
|
||||||
"blocknr %llu\n", (u64)bh->b_blocknr);
|
"blocknr %llu\n", (u64)bh->b_blocknr);
|
||||||
spin_lock(&journal->j_revoke_lock);
|
jbd_lock(&journal->j_revoke_lock);
|
||||||
list_del(&record->hash);
|
list_del(&record->hash);
|
||||||
spin_unlock(&journal->j_revoke_lock);
|
jbd_unlock(&journal->j_revoke_lock);
|
||||||
kmem_cache_free(revoke_record_cache, record);
|
kmem_cache_free(revoke_record_cache, record);
|
||||||
did_revoke = 1;
|
did_revoke = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -353,6 +353,10 @@ free_buffer_head(struct buffer_head * bh)
|
||||||
|
|
||||||
Ext2DestroyMdl(bh->b_mdl);
|
Ext2DestroyMdl(bh->b_mdl);
|
||||||
}
|
}
|
||||||
|
if (bh->b_bcb) {
|
||||||
|
CcUnpinDataForThread(bh->b_bcb, (ERESOURCE_THREAD)bh | 0x3);
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG(DL_BH, ("bh=%p freed.\n", bh));
|
DEBUG(DL_BH, ("bh=%p freed.\n", bh));
|
||||||
DEC_MEM_COUNT(PS_BUFF_HEAD, bh, sizeof(struct buffer_head));
|
DEC_MEM_COUNT(PS_BUFF_HEAD, bh, sizeof(struct buffer_head));
|
||||||
kmem_cache_free(g_jbh.bh_cache, bh);
|
kmem_cache_free(g_jbh.bh_cache, bh);
|
||||||
|
@ -420,7 +424,7 @@ static void buffer_head_remove(struct block_device *bdev, struct buffer_head *bh
|
||||||
}
|
}
|
||||||
|
|
||||||
struct buffer_head *
|
struct buffer_head *
|
||||||
get_block_bh(
|
get_block_bh_mdl(
|
||||||
struct block_device * bdev,
|
struct block_device * bdev,
|
||||||
sector_t block,
|
sector_t block,
|
||||||
unsigned long size,
|
unsigned long size,
|
||||||
|
@ -538,17 +542,7 @@ errorout:
|
||||||
return bh;
|
return bh;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct buffer_head *
|
int submit_bh_mdl(int rw, struct buffer_head *bh)
|
||||||
__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)
|
|
||||||
{
|
{
|
||||||
struct block_device *bdev = bh->b_bdev;
|
struct block_device *bdev = bh->b_bdev;
|
||||||
PEXT2_VCB Vcb = bdev->bd_priv;
|
PEXT2_VCB Vcb = bdev->bd_priv;
|
||||||
|
@ -607,6 +601,159 @@ errorout:
|
||||||
return 0;
|
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)
|
void __brelse(struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
struct block_device *bdev = bh->b_bdev;
|
struct block_device *bdev = bh->b_bdev;
|
||||||
|
@ -636,6 +783,7 @@ void __brelse(struct buffer_head *bh)
|
||||||
atomic_dec(&g_jbh.bh_count);
|
atomic_dec(&g_jbh.bh_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void __bforget(struct buffer_head *bh)
|
void __bforget(struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
clear_buffer_dirty(bh);
|
clear_buffer_dirty(bh);
|
||||||
|
|
|
@ -24,10 +24,10 @@ extern PEXT2_GLOBAL Ext2Global;
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject = NULL;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject = NULL;
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb = NULL;
|
||||||
PIRP Irp;
|
PIRP Irp = NULL;
|
||||||
|
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
BOOLEAN CompleteContext = TRUE;
|
BOOLEAN CompleteContext = TRUE;
|
||||||
|
|
|
@ -138,8 +138,6 @@ Ext2AllocateFcb (
|
||||||
{
|
{
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb;
|
||||||
|
|
||||||
ASSERT(!IsMcbSymLink(Mcb));
|
|
||||||
|
|
||||||
Fcb = (PEXT2_FCB) ExAllocateFromNPagedLookasideList(
|
Fcb = (PEXT2_FCB) ExAllocateFromNPagedLookasideList(
|
||||||
&(Ext2Global->Ext2FcbLookasideList));
|
&(Ext2Global->Ext2FcbLookasideList));
|
||||||
|
|
||||||
|
@ -216,7 +214,7 @@ Ext2FreeFcb (IN PEXT2_FCB Fcb)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((Fcb->Mcb->Identifier.Type == EXT2MCB) &&
|
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);
|
ASSERT (Fcb->Mcb->Fcb == Fcb);
|
||||||
if (IsMcbSpecialFile(Fcb->Mcb) || IsFileDeleted(Fcb->Mcb)) {
|
if (IsMcbSpecialFile(Fcb->Mcb) || IsFileDeleted(Fcb->Mcb)) {
|
||||||
|
@ -283,7 +281,7 @@ Ext2RemoveFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb)
|
||||||
}
|
}
|
||||||
|
|
||||||
PEXT2_CCB
|
PEXT2_CCB
|
||||||
Ext2AllocateCcb (PEXT2_MCB SymLink)
|
Ext2AllocateCcb (ULONG Flags, PEXT2_MCB SymLink)
|
||||||
{
|
{
|
||||||
PEXT2_CCB Ccb;
|
PEXT2_CCB Ccb;
|
||||||
|
|
||||||
|
@ -299,6 +297,7 @@ Ext2AllocateCcb (PEXT2_MCB SymLink)
|
||||||
|
|
||||||
Ccb->Identifier.Type = EXT2CCB;
|
Ccb->Identifier.Type = EXT2CCB;
|
||||||
Ccb->Identifier.Size = sizeof(EXT2_CCB);
|
Ccb->Identifier.Size = sizeof(EXT2_CCB);
|
||||||
|
Ccb->Flags = Flags;
|
||||||
|
|
||||||
Ccb->SymLink = SymLink;
|
Ccb->SymLink = SymLink;
|
||||||
if (SymLink) {
|
if (SymLink) {
|
||||||
|
@ -1187,7 +1186,7 @@ Ext2BuildExtents(
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
PEXT2_EXTENT Extent = NULL;
|
PEXT2_EXTENT Extent = NULL;
|
||||||
PEXT2_EXTENT List = *Chain;
|
PEXT2_EXTENT List = *Chain = NULL;
|
||||||
|
|
||||||
if (!IsZoneInited(Mcb)) {
|
if (!IsZoneInited(Mcb)) {
|
||||||
Status = Ext2InitializeZone(IrpContext, Vcb, Mcb);
|
Status = Ext2InitializeZone(IrpContext, Vcb, Mcb);
|
||||||
|
@ -1246,7 +1245,7 @@ Ext2BuildExtents(
|
||||||
&Mapped
|
&Mapped
|
||||||
);
|
);
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
goto errorout;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* skip wrong blocks, in case wrongly treating symlink
|
/* skip wrong blocks, in case wrongly treating symlink
|
||||||
|
@ -1272,6 +1271,11 @@ Ext2BuildExtents(
|
||||||
Length = Size;
|
Length = Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 == Length) {
|
||||||
|
DbgBreak();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
Start += Mapped;
|
Start += Mapped;
|
||||||
Offset = (ULONGLONG)Start << BLOCK_BITS;
|
Offset = (ULONGLONG)Start << BLOCK_BITS;
|
||||||
|
|
||||||
|
@ -1288,7 +1292,8 @@ Ext2BuildExtents(
|
||||||
Extent = Ext2AllocateExtent();
|
Extent = Ext2AllocateExtent();
|
||||||
if (!Extent) {
|
if (!Extent) {
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto errorout;
|
DbgBreak();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Extent->Lba = Lba;
|
Extent->Lba = Lba;
|
||||||
|
@ -1303,14 +1308,16 @@ Ext2BuildExtents(
|
||||||
*Chain = List = Extent;
|
*Chain = List = Extent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (bAlloc) {
|
||||||
|
DbgBreak();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Total += Length;
|
Total += Length;
|
||||||
Size -= Length;
|
Size -= Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
errorout:
|
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1800,29 +1807,23 @@ Ext2CleanupAllMcbs(PEXT2_VCB Vcb)
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
Ext2CheckSetBlock(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, LONGLONG Block)
|
Ext2CheckSetBlock(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, LONGLONG Block)
|
||||||
{
|
{
|
||||||
PEXT2_GROUP_DESC gd;
|
PEXT2_GROUP_DESC gd;
|
||||||
ULONG Group, dwBlk, Length;
|
struct buffer_head *gb = NULL;
|
||||||
|
struct buffer_head *bh = NULL;
|
||||||
|
ULONG group, dwBlk, Length;
|
||||||
|
RTL_BITMAP bitmap;
|
||||||
|
BOOLEAN bModified = FALSE;
|
||||||
|
|
||||||
RTL_BITMAP BlockBitmap;
|
group = (ULONG)(Block - EXT2_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
|
||||||
PVOID BitmapCache;
|
|
||||||
PBCB BitmapBcb;
|
|
||||||
|
|
||||||
LARGE_INTEGER Offset;
|
|
||||||
|
|
||||||
BOOLEAN bModified = FALSE;
|
|
||||||
|
|
||||||
|
|
||||||
Group = (ULONG)(Block - EXT2_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
|
|
||||||
dwBlk = (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) {
|
if (!gd) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
Offset.QuadPart = ext4_block_bitmap(&Vcb->sb, gd);
|
bh = sb_getblk(&Vcb->sb, ext4_block_bitmap(&Vcb->sb, gd));
|
||||||
Offset.QuadPart <<= BLOCK_BITS;
|
|
||||||
|
|
||||||
if (Group == Vcb->sbi.s_groups_count - 1) {
|
if (group == Vcb->sbi.s_groups_count - 1) {
|
||||||
Length = (ULONG)(TOTAL_BLOCKS % BLOCKS_PER_GROUP);
|
Length = (ULONG)(TOTAL_BLOCKS % BLOCKS_PER_GROUP);
|
||||||
|
|
||||||
/* s_blocks_count is integer multiple of s_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;
|
Length = BLOCKS_PER_GROUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwBlk >= Length)
|
if (dwBlk >= Length) {
|
||||||
return FALSE;
|
fini_bh(&gb);
|
||||||
|
fini_bh(&bh);
|
||||||
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)));
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlInitializeBitMap( &BlockBitmap,
|
RtlInitializeBitMap(&bitmap, (PULONG)bh->b_data, Length);
|
||||||
BitmapCache,
|
|
||||||
Length );
|
|
||||||
|
|
||||||
if (RtlCheckBit(&BlockBitmap, dwBlk) == 0) {
|
if (RtlCheckBit(&bitmap, dwBlk) == 0) {
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
RtlSetBits(&BlockBitmap, dwBlk, 1);
|
RtlSetBits(&bitmap, dwBlk, 1);
|
||||||
bModified = TRUE;
|
bModified = TRUE;
|
||||||
|
mark_buffer_dirty(bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bModified) {
|
fini_bh(&gb);
|
||||||
CcSetDirtyPinnedData(BitmapBcb, NULL );
|
fini_bh(&bh);
|
||||||
Ext2AddVcbExtent(Vcb, Offset.QuadPart, (LONGLONG)BLOCK_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
CcUnpinData(BitmapBcb);
|
|
||||||
BitmapBcb = NULL;
|
|
||||||
BitmapCache = NULL;
|
|
||||||
|
|
||||||
RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (!bModified);
|
return (!bModified);
|
||||||
}
|
}
|
||||||
|
@ -1881,8 +1862,9 @@ Ext2CheckBitmapConsistency(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb)
|
||||||
for (i = 0; i < Vcb->sbi.s_groups_count; i++) {
|
for (i = 0; i < Vcb->sbi.s_groups_count; i++) {
|
||||||
|
|
||||||
PEXT2_GROUP_DESC gd;
|
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)
|
if (!gd)
|
||||||
continue;
|
continue;
|
||||||
Ext2CheckSetBlock(IrpContext, Vcb, ext4_block_bitmap(&Vcb->sb, gd));
|
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++ )
|
for (j = 0; j < InodeBlocks; j++ )
|
||||||
Ext2CheckSetBlock(IrpContext, Vcb, ext4_inode_table(&Vcb->sb, gd) + j);
|
Ext2CheckSetBlock(IrpContext, Vcb, ext4_inode_table(&Vcb->sb, gd) + j);
|
||||||
|
|
||||||
|
fini_bh(&bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -2687,7 +2671,7 @@ Ext2InitializeVcb( IN PEXT2_IRP_CONTEXT IrpContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ExtentsInitialized) {
|
if (ExtentsInitialized) {
|
||||||
Ext2PutGroup(Vcb);
|
Ext2DropGroup(Vcb);
|
||||||
if (Vcb->bd.bd_bh_cache)
|
if (Vcb->bd.bd_bh_cache)
|
||||||
kmem_cache_destroy(Vcb->bd.bd_bh_cache);
|
kmem_cache_destroy(Vcb->bd.bd_bh_cache);
|
||||||
FsRtlUninitializeLargeMcb(&(Vcb->Extents));
|
FsRtlUninitializeLargeMcb(&(Vcb->Extents));
|
||||||
|
@ -2764,7 +2748,7 @@ Ext2DestroyVcb (IN PEXT2_VCB Vcb)
|
||||||
|
|
||||||
Ext2CleanupAllMcbs(Vcb);
|
Ext2CleanupAllMcbs(Vcb);
|
||||||
|
|
||||||
Ext2PutGroup(Vcb);
|
Ext2DropGroup(Vcb);
|
||||||
|
|
||||||
if (Vcb->bd.bd_bh_cache)
|
if (Vcb->bd.bd_bh_cache)
|
||||||
kmem_cache_destroy(Vcb->bd.bd_bh_cache);
|
kmem_cache_destroy(Vcb->bd.bd_bh_cache);
|
||||||
|
@ -2776,7 +2760,8 @@ Ext2DestroyVcb (IN PEXT2_VCB Vcb)
|
||||||
|
|
||||||
if (IsFlagOn(Vcb->Flags, VCB_NEW_VPB)) {
|
if (IsFlagOn(Vcb->Flags, VCB_NEW_VPB)) {
|
||||||
ASSERT(Vcb->Vpb2 != NULL);
|
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));
|
DEC_MEM_COUNT(PS_VPB, Vcb->Vpb2, sizeof(VPB));
|
||||||
Vcb->Vpb2 = NULL;
|
Vcb->Vpb2 = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -382,10 +382,13 @@ int Ext2LinuxError (NTSTATUS Status)
|
||||||
case STATUS_HOST_UNREACHABLE:
|
case STATUS_HOST_UNREACHABLE:
|
||||||
return (-EHOSTUNREACH);
|
return (-EHOSTUNREACH);
|
||||||
|
|
||||||
|
case STATUS_CANT_WAIT:
|
||||||
case STATUS_PENDING:
|
case STATUS_PENDING:
|
||||||
case STATUS_DEVICE_NOT_READY:
|
|
||||||
return (-EAGAIN);
|
return (-EAGAIN);
|
||||||
|
|
||||||
|
case STATUS_DEVICE_NOT_READY:
|
||||||
|
return (-EIO);
|
||||||
|
|
||||||
case STATUS_CANCELLED:
|
case STATUS_CANCELLED:
|
||||||
case STATUS_REQUEST_ABORTED:
|
case STATUS_REQUEST_ABORTED:
|
||||||
return (-EINTR);
|
return (-EINTR);
|
||||||
|
@ -503,7 +506,7 @@ NTSTATUS Ext2WinntError(int rc)
|
||||||
return STATUS_HOST_UNREACHABLE;
|
return STATUS_HOST_UNREACHABLE;
|
||||||
|
|
||||||
case -EAGAIN:
|
case -EAGAIN:
|
||||||
return STATUS_DEVICE_NOT_READY;
|
return STATUS_CANT_WAIT;
|
||||||
|
|
||||||
case -EINTR:
|
case -EINTR:
|
||||||
return STATUS_CANCELLED;
|
return STATUS_CANCELLED;
|
||||||
|
@ -527,4 +530,4 @@ BOOLEAN Ext2IsDotDot(PUNICODE_STRING name)
|
||||||
{
|
{
|
||||||
return (name->Length == 4 && name->Buffer[0] == L'.' &&
|
return (name->Length == 4 && name->Buffer[0] == L'.' &&
|
||||||
name->Buffer[1] == L'.');
|
name->Buffer[1] == L'.');
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ Ext2Pnp (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
PIO_STACK_LOCATION IrpSp;
|
PIO_STACK_LOCATION IrpSp;
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
@ -394,4 +394,4 @@ Ext2PnpCancelRemove (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //(_WIN32_WINNT >= 0x0500)
|
#endif //(_WIN32_WINNT >= 0x0500)
|
||||||
|
|
|
@ -65,15 +65,15 @@ Ext2ReadVolume (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PEXT2_CCB Ccb;
|
PEXT2_CCB Ccb = NULL;
|
||||||
PEXT2_FCBVCB FcbOrVcb;
|
PEXT2_FCBVCB FcbOrVcb = NULL;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject = NULL;
|
||||||
|
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject = NULL;
|
||||||
|
|
||||||
PIRP Irp = NULL;
|
PIRP Irp = NULL;
|
||||||
PIO_STACK_LOCATION IoStackLocation;
|
PIO_STACK_LOCATION IoStackLocation = NULL;
|
||||||
|
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
LARGE_INTEGER ByteOffset;
|
LARGE_INTEGER ByteOffset;
|
||||||
|
@ -347,11 +347,9 @@ Ext2ReadInode (
|
||||||
|
|
||||||
|
|
||||||
/* handle fast symlinks */
|
/* handle fast symlinks */
|
||||||
if (S_ISLNK(Mcb->Inode.i_mode) &&
|
if (S_ISLNK(Mcb->Inode.i_mode) && 0 == Mcb->Inode.i_blocks) {
|
||||||
Mcb->Inode.i_size < EXT2_LINKLEN_IN_INODE) {
|
|
||||||
|
|
||||||
PUCHAR Data = (PUCHAR) (&Mcb->Inode.i_block[0]);
|
PUCHAR Data = (PUCHAR) (&Mcb->Inode.i_block[0]);
|
||||||
|
|
||||||
if (!Buffer) {
|
if (!Buffer) {
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
|
@ -474,15 +472,15 @@ Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb = NULL;
|
||||||
PEXT2_CCB Ccb;
|
PEXT2_CCB Ccb = NULL;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject = NULL;
|
||||||
|
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject = NULL;
|
||||||
|
|
||||||
PIRP Irp;
|
PIRP Irp = NULL;
|
||||||
PIO_STACK_LOCATION IoStackLocation;
|
PIO_STACK_LOCATION IoStackLocation = NULL;
|
||||||
|
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
ULONG ReturnedLength = 0;
|
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",
|
DEBUG(DL_INF, ("Ext2ReadFile: reading %wZ Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
|
||||||
&Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache));
|
&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)) ||
|
if ((IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ||
|
||||||
IsFileDeleted(Fcb->Mcb)) {
|
IsFileDeleted(Fcb->Mcb)) {
|
||||||
Status = STATUS_FILE_DELETED;
|
Status = STATUS_FILE_DELETED;
|
||||||
|
@ -546,9 +549,13 @@ Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Nocache &&
|
if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION &&
|
||||||
(ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
|
ByteOffset.HighPart == -1) {
|
||||||
Length & (SECTOR_SIZE - 1))) {
|
ByteOffset = FileObject->CurrentByteOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Nocache && (ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
|
||||||
|
Length & (SECTOR_SIZE - 1))) {
|
||||||
Status = STATUS_INVALID_PARAMETER;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
|
@ -561,17 +568,6 @@ Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
_SEH2_LEAVE;
|
_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;
|
ReturnedLength = Length;
|
||||||
|
|
||||||
if (PagingIo) {
|
if (PagingIo) {
|
||||||
|
@ -596,6 +592,15 @@ Ext2ReadFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
}
|
}
|
||||||
MainResourceAcquired = TRUE;
|
MainResourceAcquired = TRUE;
|
||||||
|
|
||||||
|
if (FileObject->SectionObjectPointer->DataSectionObject != NULL) {
|
||||||
|
CcFlushCache( FileObject->SectionObjectPointer,
|
||||||
|
&ByteOffset,
|
||||||
|
Length,
|
||||||
|
&Irp->IoStatus );
|
||||||
|
if (!NT_SUCCESS(Irp->IoStatus.Status))
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (!ExAcquireResourceSharedLite(
|
if (!ExAcquireResourceSharedLite(
|
||||||
|
|
|
@ -27,13 +27,13 @@ NTSTATUS
|
||||||
Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PEXT2_VCB Vcb;
|
PIRP Irp = NULL;
|
||||||
PIRP Irp;
|
PIO_STACK_LOCATION IoStackLocation = NULL;
|
||||||
PIO_STACK_LOCATION IoStackLocation;
|
|
||||||
FS_INFORMATION_CLASS FsInformationClass;
|
|
||||||
ULONG Length;
|
|
||||||
PVOID Buffer;
|
PVOID Buffer;
|
||||||
|
ULONG Length;
|
||||||
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
|
FS_INFORMATION_CLASS FsInformationClass;
|
||||||
BOOLEAN VcbResourceAcquired = FALSE;
|
BOOLEAN VcbResourceAcquired = FALSE;
|
||||||
|
|
||||||
_SEH2_TRY {
|
_SEH2_TRY {
|
||||||
|
@ -186,8 +186,9 @@ Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
FsAttrInfo =
|
FsAttrInfo =
|
||||||
(PFILE_FS_ATTRIBUTE_INFORMATION) Buffer;
|
(PFILE_FS_ATTRIBUTE_INFORMATION) Buffer;
|
||||||
FsAttrInfo->FileSystemAttributes =
|
FsAttrInfo->FileSystemAttributes = FILE_SUPPORTS_HARD_LINKS |
|
||||||
FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
|
FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
|
||||||
|
FILE_SUPPORTS_REPARSE_POINTS;
|
||||||
if (IsVcbReadOnly(Vcb)) {
|
if (IsVcbReadOnly(Vcb)) {
|
||||||
FsAttrInfo->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
|
FsAttrInfo->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
|
||||||
}
|
}
|
||||||
|
@ -292,7 +293,7 @@ Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
PIO_STACK_LOCATION IoStackLocation;
|
PIO_STACK_LOCATION IoStackLocation;
|
||||||
FS_INFORMATION_CLASS FsInformationClass;
|
FS_INFORMATION_CLASS FsInformationClass;
|
||||||
|
@ -405,4 +406,4 @@ Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
} _SEH2_END;
|
} _SEH2_END;
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,9 +175,8 @@ Ext2ZeroData (
|
||||||
PBCB Bcb;
|
PBCB Bcb;
|
||||||
PVOID Ptr;
|
PVOID Ptr;
|
||||||
ULONG Size;
|
ULONG Size;
|
||||||
#ifndef __REACTOS__
|
|
||||||
BOOLEAN rc = TRUE;
|
BOOLEAN rc = TRUE;
|
||||||
#endif
|
|
||||||
ASSERT (End && Start && End->QuadPart > Start->QuadPart);
|
ASSERT (End && Start && End->QuadPart > Start->QuadPart);
|
||||||
Fcb = (PEXT2_FCB) FileObject->FsContext;
|
Fcb = (PEXT2_FCB) FileObject->FsContext;
|
||||||
|
|
||||||
|
@ -195,7 +194,13 @@ Ext2ZeroData (
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clear data in range [Start, End) */
|
/* 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
|
VOID
|
||||||
|
@ -212,15 +217,15 @@ Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PEXT2_CCB Ccb;
|
PEXT2_CCB Ccb = NULL;
|
||||||
PEXT2_FCBVCB FcbOrVcb;
|
PEXT2_FCBVCB FcbOrVcb = NULL;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject = NULL;
|
||||||
|
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject = NULL;
|
||||||
|
|
||||||
PIRP Irp = NULL;
|
PIRP Irp = NULL;
|
||||||
PIO_STACK_LOCATION IoStackLocation;
|
PIO_STACK_LOCATION IoStackLocation = NULL;
|
||||||
|
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
LARGE_INTEGER ByteOffset;
|
LARGE_INTEGER ByteOffset;
|
||||||
|
@ -646,7 +651,7 @@ Ext2WriteInode (
|
||||||
IN ULONG Size,
|
IN ULONG Size,
|
||||||
IN BOOLEAN bDirectIo,
|
IN BOOLEAN bDirectIo,
|
||||||
OUT PULONG BytesWritten
|
OUT PULONG BytesWritten
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
PEXT2_EXTENT Chain = NULL;
|
PEXT2_EXTENT Chain = NULL;
|
||||||
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
||||||
|
@ -663,7 +668,7 @@ Ext2WriteInode (
|
||||||
Mcb,
|
Mcb,
|
||||||
Offset,
|
Offset,
|
||||||
Size,
|
Size,
|
||||||
IsMcbDirectory(Mcb) ? FALSE : TRUE,
|
S_ISDIR(Mcb->Inode.i_mode) ? FALSE : TRUE,
|
||||||
&Chain
|
&Chain
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -730,19 +735,20 @@ Ext2WriteInode (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
{
|
{
|
||||||
PEXT2_VCB Vcb;
|
PEXT2_VCB Vcb = NULL;
|
||||||
PEXT2_FCB Fcb;
|
PEXT2_FCB Fcb = NULL;
|
||||||
PEXT2_CCB Ccb;
|
PEXT2_CCB Ccb = NULL;
|
||||||
PFILE_OBJECT FileObject;
|
PFILE_OBJECT FileObject = NULL;
|
||||||
|
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject = NULL;
|
||||||
|
|
||||||
PIRP Irp;
|
PIRP Irp = NULL;
|
||||||
PIO_STACK_LOCATION IoStackLocation;
|
PIO_STACK_LOCATION IoStackLocation = NULL;
|
||||||
PUCHAR Buffer;
|
PUCHAR Buffer = NULL;
|
||||||
|
|
||||||
LARGE_INTEGER ByteOffset;
|
LARGE_INTEGER ByteOffset;
|
||||||
ULONG ReturnedLength = 0;
|
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",
|
DEBUG(DL_INF, ("Ext2WriteFile: %wZ Offset=%I64xh Length=%xh Paging=%xh Nocache=%xh\n",
|
||||||
&Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache));
|
&Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache));
|
||||||
|
|
||||||
if (IsSpecialFile(Fcb)) {
|
if (IsSpecialFile(Fcb) || IsInodeSymLink(Fcb->Inode) ) {
|
||||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
@ -820,8 +826,16 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Nocache && ( (ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
|
if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION &&
|
||||||
(Length & (SECTOR_SIZE - 1))) ) {
|
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;
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
_SEH2_LEAVE;
|
_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) {
|
if (IsDirectory(Fcb) && !PagingIo) {
|
||||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
|
@ -904,18 +914,24 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
}
|
}
|
||||||
PagingIoResourceAcquired = TRUE;
|
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;
|
Irp->IoStatus.Information = 0;
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
|
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
|
@ -1049,9 +1065,9 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
&Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart,
|
&Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart,
|
||||||
Fcb->Header.AllocationSize.QuadPart));
|
Fcb->Header.AllocationSize.QuadPart));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ReturnedLength = Length;
|
ReturnedLength = Length;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Nocache) {
|
if (!Nocache) {
|
||||||
|
|
||||||
|
@ -1138,19 +1154,17 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (!PagingIo && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) {
|
if (!PagingIo && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) {
|
||||||
if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {
|
if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {
|
||||||
if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) {
|
|
||||||
|
|
||||||
/* let this irp wait, since it has to be synchronous */
|
/* let this irp wait, since it has to be synchronous */
|
||||||
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
|
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
|
||||||
rc = Ext2ZeroData(IrpContext, Vcb, FileObject,
|
rc = Ext2ZeroData(IrpContext, Vcb, FileObject,
|
||||||
&Fcb->Header.ValidDataLength,
|
&Fcb->Header.ValidDataLength,
|
||||||
&ByteOffset);
|
&ByteOffset);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
Status = STATUS_PENDING;
|
Status = STATUS_PENDING;
|
||||||
DbgBreak();
|
DbgBreak();
|
||||||
_SEH2_LEAVE;
|
_SEH2_LEAVE;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1180,20 +1194,22 @@ Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
|
||||||
|
|
||||||
Irp = IrpContext->Irp;
|
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 ) {
|
if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) {
|
||||||
|
|
||||||
FileSizesChanged = TRUE;
|
FileSizesChanged = TRUE;
|
||||||
|
|
||||||
if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) {
|
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;
|
Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart;
|
||||||
} else {
|
} else {
|
||||||
if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length)
|
if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length)
|
||||||
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)));
|
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
|
* 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
|
* Ext2ExpandFile to allocate unwritten extent or don't add
|
||||||
* new blocks for indirect files.
|
* new blocks for indirect files.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue