diff --git a/Ext4Fsd/include/ext2fs.h b/Ext4Fsd/include/ext2fs.h index 546b45a..69a7e51 100644 --- a/Ext4Fsd/include/ext2fs.h +++ b/Ext4Fsd/include/ext2fs.h @@ -1,3072 +1,3066 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: Ext2fs.h - * PURPOSE: Header file: ext2 structures - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -#ifndef _EXT2_HEADER_ -#define _EXT2_HEADER_ - -/* INCLUDES *************************************************************/ -#include -#include -#include -#include -#include -#include - -/* DEBUG ****************************************************************/ -#if DBG -# define EXT2_DEBUG 1 -#else -# define EXT2_DEBUG 0 -#endif - -#if EXT2_DEBUG -#if _X86_ -#define DbgBreak() __asm int 3 -#else -#define DbgBreak() KdBreakPoint() -#endif -#else -#define DbgBreak() -#endif - -/* STRUCTS & CONSTS******************************************************/ - -#define EXT2FSD_VERSION "0.70" - - -/* WDK DEFINITIONS ******************************************************/ - - -/* COMPILER SWITCH / OPTIONS ********************************************/ - -// -// Ext2Fsd build options -// - -// To support driver dynamics unload - -#define EXT2_UNLOAD FALSE - -// To support inode size expansion (fallocate) - -#define EXT2_PRE_ALLOCATION_SUPPORT TRUE - -// -// Constants -// - -#define EXT2_MAX_NESTED_LINKS (8) -#define EXT2_LINKLEN_IN_INODE (60) -#define EXT2_BLOCK_TYPES (0x04) - -#define MAXIMUM_RECORD_LENGTH (0x10000) - -#define SECTOR_BITS (Vcb->SectorBits) -#define SECTOR_SIZE (Vcb->DiskGeometry.BytesPerSector) -#define DEFAULT_SECTOR_SIZE (0x200) - -#define SUPER_BLOCK_OFFSET (0x400) -#define SUPER_BLOCK_SIZE (0x400) - -#define READ_AHEAD_GRANULARITY (0x10000) - -#define SUPER_BLOCK (Vcb->SuperBlock) - -#define INODE_SIZE (Vcb->InodeSize) -#define BLOCK_SIZE (Vcb->BlockSize) -#define BLOCK_BITS (SUPER_BLOCK->s_log_block_size + 10) -#define GROUP_DESC_SIZE (Vcb->sbi.s_desc_size) - -#define INODES_COUNT (Vcb->SuperBlock->s_inodes_count) - -#define INODES_PER_GROUP (SUPER_BLOCK->s_inodes_per_group) -#define BLOCKS_PER_GROUP (SUPER_BLOCK->s_blocks_per_group) -#define TOTAL_BLOCKS (ext3_blocks_count(SUPER_BLOCK)) - -#define EXT2_FIRST_DATA_BLOCK (SUPER_BLOCK->s_first_data_block) - -typedef struct ext3_super_block EXT2_SUPER_BLOCK, *PEXT2_SUPER_BLOCK; -typedef struct ext3_inode EXT2_INODE, *PEXT2_INODE; -typedef struct ext4_group_desc EXT2_GROUP_DESC, *PEXT2_GROUP_DESC; -typedef struct ext3_dir_entry EXT2_DIR_ENTRY, *PEXT2_DIR_ENTRY; -typedef struct ext3_dir_entry_2 EXT2_DIR_ENTRY2, *PEXT2_DIR_ENTRY2; - -#define CEILING_ALIGNED(T, A, B) (((A) + (B) - 1) & (~((T)(B) - 1))) -#define COCKLOFT_ALIGNED(T, A, B) (((A) + (B)) & (~((T)(B) - 1))) - - - -/* - * Compile-time assertion: (Lustre version) - * - * Check an invariant described by a constant expression at compile time by - * forcing a compiler error if it does not hold. \a cond must be a constant - * expression as defined by the ISO C Standard: - * - * 6.8.4.2 The switch statement - * .... - * [#3] The expression of each case label shall be an integer - * constant expression and no two of the case constant - * expressions in the same switch statement shall have the same - * value after conversion... - * - */ - -#define CL_ASSERT(cond) do {switch('x') {case (cond): case 0: break;}} while (0) - -/* File System Releated *************************************************/ - -#define DRIVER_NAME "Ext2Fsd" -#define DEVICE_NAME L"\\Ext2Fsd" -#define CDROM_NAME L"\\Ext2CdFsd" - -// Registry - -#define PARAMETERS_KEY L"\\Parameters" -#define VOLUMES_KEY L"\\Volumes" - -#define READING_ONLY L"Readonly" -#define WRITING_SUPPORT L"WritingSupport" -#define CHECKING_BITMAP L"CheckingBitmap" -#define EXT3_FORCEWRITING L"Ext3ForceWriting" -#define CODEPAGE_NAME L"CodePage" -#define HIDING_PREFIX L"HidingPrefix" -#define HIDING_SUFFIX L"HidingSuffix" -#define AUTO_MOUNT L"AutoMount" -#define MOUNT_POINT L"MountPoint" -#define UID L"uid" -#define GID L"gid" -#define EUID L"euid" -#define EGID L"egid" - -#define DOS_DEVICE_NAME L"\\DosDevices\\Ext2Fsd" - -// To support ext2fsd unload routine -#if EXT2_UNLOAD -// -// Private IOCTL to make the driver ready to unload -// -#define IOCTL_PREPARE_TO_UNLOAD \ -CTL_CODE(FILE_DEVICE_UNKNOWN, 2048, METHOD_NEITHER, FILE_WRITE_ACCESS) - -#endif // EXT2_UNLOAD - -#include "common.h" - -#ifndef _GNU_NTIFS_ -typedef IO_STACK_LOCATION EXTENDED_IO_STACK_LOCATION, *PEXTENDED_IO_STACK_LOCATION; -#endif - -#define IsFlagOn(a,b) ((BOOLEAN)(FlagOn(a,b) == b)) -#ifndef FlagOn -#define FlagOn(_F,_SF) ((_F) & (_SF)) -#endif - -#ifndef BooleanFlagOn -#define BooleanFlagOn(F,SF) ((BOOLEAN)(((F) & (SF)) != 0)) -#endif - -#ifndef SetFlag -#define SetFlag(_F,_SF) ((_F) |= (_SF)) -#endif - -#ifndef ClearFlag -#define ClearFlag(_F,_SF) ((_F) &= ~(_SF)) -#endif - -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifdef _WIN2K_TARGET_ -#define InterlockedOr _InterlockedOr -LONG -_InterlockedAnd ( - IN OUT LONG volatile *Target, - IN LONG Set -); - -#pragma intrinsic (_InterlockedAnd) -#define InterlockedAnd _InterlockedAnd - -LONG -_InterlockedXor ( - IN OUT LONG volatile *Target, - IN LONG Set -); - -#pragma intrinsic (_InterlockedXor) -#define InterlockedXor _InterlockedXor - -#endif /* only for win2k */ - -#if EXT2_DEBUG - -#define SetLongFlag(_F,_SF) Ext2SetFlag(&(_F), (ULONG)(_SF)) -#define ClearLongFlag(_F,_SF) Ext2ClearFlag(&(_F), (ULONG)(_SF)) - -__inline -VOID -Ext2SetFlag(PULONG Flags, ULONG FlagBit) -{ - ULONG _ret = InterlockedOr(Flags, FlagBit); - ASSERT(*Flags == (_ret | FlagBit)); -} - -__inline -VOID -Ext2ClearFlag(PULONG Flags, ULONG FlagBit) -{ - ULONG _ret = InterlockedAnd(Flags, ~FlagBit); - ASSERT(*Flags == (_ret & (~FlagBit))); -} - -#else - -#define SetLongFlag(_F,_SF) InterlockedOr(&(_F), (ULONG)(_SF)) -#define ClearLongFlag(_F,_SF) InterlockedAnd(&(_F), ~((ULONG)(_SF))) - -#endif /* release */ - -#define Ext2RaiseStatus(IRPCONTEXT,STATUS) { \ - (IRPCONTEXT)->ExceptionCode = (STATUS); \ - ExRaiseStatus((STATUS)); \ -} - -#define Ext2NormalizeAndRaiseStatus(IRPCONTEXT,STATUS) { \ - (IRPCONTEXT)->ExceptionCode = STATUS; \ - if ((STATUS) == STATUS_VERIFY_REQUIRED) { ExRaiseStatus((STATUS)); } \ - ExRaiseStatus(FsRtlNormalizeNtstatus((STATUS),STATUS_UNEXPECTED_IO_ERROR)); \ -} - -// -// Define IsWritingToEof for write (append) operations -// - -#define FILE_WRITE_TO_END_OF_FILE 0xffffffff - -#define IsWritingToEof(Pos) (((Pos).LowPart == FILE_WRITE_TO_END_OF_FILE) && \ - ((Pos).HighPart == -1 )) - -#define IsDirectory(Fcb) IsMcbDirectory((Fcb)->Mcb) -#define IsSpecialFile(Fcb) IsMcbSpecialFile((Fcb)->Mcb) -#define IsSymLink(Fcb) IsMcbSymLink((Fcb)->Mcb) -#define IsInodeSymLink(I) S_ISLNK((I)->i_mode) -#define IsRoot(Fcb) IsMcbRoot((Fcb)->Mcb) - -// -// Pool Tags -// - -#define TAG_VPB ' bpV' -#define VPB_SIZE sizeof(VPB) - -#define EXT2_DATA_MAGIC 'BD2E' -#define EXT2_INAME_MAGIC 'NI2E' -#define EXT2_FNAME_MAGIC 'NF2E' -#define EXT2_VNAME_MAGIC 'NV2E' -#define EXT2_DENTRY_MAGIC 'ED2E' -#define EXT2_DIRSP_MAGIC 'SD2E' -#define EXT2_SB_MAGIC 'BS2E' -#define EXT2_GD_MAGIC 'DG2E' -#define EXT2_FLIST_MAGIC 'LF2E' -#define EXT2_PARAM_MAGIC 'PP2E' -#define EXT2_RWC_MAGIC 'WR2E' - -// -// Bug Check Codes Definitions -// - -#define EXT2_FILE_SYSTEM (FILE_SYSTEM) - -#define EXT2_BUGCHK_BLOCK (0x00010000) -#define EXT2_BUGCHK_CLEANUP (0x00020000) -#define EXT2_BUGCHK_CLOSE (0x00030000) -#define EXT2_BUGCHK_CMCB (0x00040000) -#define EXT2_BUGCHK_CREATE (0x00050000) -#define EXT2_BUGCHK_DEBUG (0x00060000) -#define EXT2_BUGCHK_DEVCTL (0x00070000) -#define EXT2_BUGCHK_DIRCTL (0x00080000) -#define EXT2_BUGCHK_DISPATCH (0x00090000) -#define EXT2_BUGCHK_EXCEPT (0x000A0000) -#define EXT2_BUGCHK_EXT2 (0x000B0000) -#define EXT2_BUGCHK_FASTIO (0x000C0000) -#define EXT2_BUGCHK_FILEINFO (0x000D0000) -#define EXT2_BUGCHK_FLUSH (0x000E0000) -#define EXT2_BUGCHK_FSCTL (0x000F0000) -#define EXT2_BUGCHK_INIT (0x00100000) -#define EXT2_BUGCHK_LOCK (0x0011000) -#define EXT2_BUGCHK_MEMORY (0x0012000) -#define EXT2_BUGCHK_MISC (0x0013000) -#define EXT2_BUGCHK_READ (0x00140000) -#define EXT2_BUGCHK_SHUTDOWN (0x00150000) -#define EXT2_BUGCHK_VOLINFO (0x00160000) -#define EXT2_BUGCHK_WRITE (0x00170000) - -#define EXT2_BUGCHK_LAST (0x00170000) - -#define Ext2BugCheck(A,B,C,D) { KeBugCheckEx(EXT2_FILE_SYSTEM, A | __LINE__, B, C, D ); } - - -/* Ext2 file system definions *******************************************/ - -// -// The second extended file system magic number -// - -#define EXT2_SUPER_MAGIC 0xEF53 - -#define EXT2_MIN_BLOCK 1024 -#define EXT2_MIN_FRAG 1024 -#define EXT2_MAX_USER_BLKSIZE 65536 -// -// Inode flags (Linux uses octad number, but why ? strange!!!) -// - -#define S_IFMT 0x0F000 /* 017 0000 */ -#define S_IFSOCK 0x0C000 /* 014 0000 */ -#define S_IFLNK 0x0A000 /* 012 0000 */ -#define S_IFREG 0x08000 /* 010 0000 */ -#define S_IFBLK 0x06000 /* 006 0000 */ -#define S_IFDIR 0x04000 /* 004 0000 */ -#define S_IFCHR 0x02000 /* 002 0000 */ -#define S_IFIFO 0x01000 /* 001 0000 */ - -#define S_ISUID 0x00800 /* 000 4000 */ -#define S_ISGID 0x00400 /* 000 2000 */ -#define S_ISVTX 0x00200 /* 000 1000 */ - -#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) -#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) -#define S_ISFIL(m) (((m) & S_IFMT) == S_IFFIL) -#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) -#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) -#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) - -#define S_IPERMISSION_MASK 0x1FF /* */ - -#define S_IRWXU 0x1C0 /* 0 0700 */ -#define S_IRWNU 0x180 /* 0 0600 */ -#define S_IRUSR 0x100 /* 0 0400 */ -#define S_IWUSR 0x080 /* 0 0200 */ -#define S_IXUSR 0x040 /* 0 0100 */ - -#define S_IRWXG 0x038 /* 0 0070 */ -#define S_IRWNG 0x030 /* 0 0060 */ -#define S_IRGRP 0x020 /* 0 0040 */ -#define S_IWGRP 0x010 /* 0 0020 */ -#define S_IXGRP 0x008 /* 0 0010 */ - -#define S_IRWXO 0x007 /* 0 0007 */ -#define S_IRWNO 0x006 /* 0 0006 */ -#define S_IROTH 0x004 /* 0 0004 */ -#define S_IWOTH 0x002 /* 0 0002 */ -#define S_IXOTH 0x001 /* 0 0001 */ - -#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO) -#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO) -#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) -#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) -#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) -#define S_IFATTR (S_IRWNU|S_IRWNG|S_IRWNO) - -#define S_ISREADABLE(m) (((m) & S_IPERMISSION_MASK) == (S_IRUSR | S_IRGRP | S_IROTH)) -#define S_ISWRITABLE(m) (((m) & S_IPERMISSION_MASK) == (S_IWUSR | S_IWGRP | S_IWOTH)) - -#define Ext2SetReadable(m) do {(m) = (m) | (S_IRUSR | S_IRGRP | S_IROTH);} while(0) -#define Ext2SetWritable(m) do {(m) = (m) | (S_IWUSR | S_IWGRP | S_IWOTH);} while(0) - -#define Ext2SetOwnerWritable(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 Ext2IsOwnerReadable(m) (((m) & S_IRUSR) == S_IRUSR) -#define Ext2IsOwnerReadOnly(m) (!(Ext2IsOwnerWritable(m)) && Ext2IsOwnerReadable(m)) - -#define Ext2IsGroupWritable(m) (((m) & S_IWGRP) == S_IWGRP) -#define Ext2IsGroupReadable(m) (((m) & S_IRGRP) == S_IRGRP) -#define Ext2IsGroupReadOnly(m) (!(Ext2IsGroupWritable(m)) && Ext2IsGroupReadable(m)) - -#define Ext2IsOtherWritable(m) (((m) & S_IWOTH) == S_IWOTH) -#define Ext2IsOtherReadable(m) (((m) & S_IROTH) == S_IROTH) -#define Ext2IsOtherReadOnly(m) (!(Ext2IsOtherWritable(m)) && Ext2IsOtherReadable(m)) - -#define Ext2SetReadOnly(m) do {(m) &= ~(S_IWUSR | S_IWGRP | S_IWOTH);} while(0) - - -#define Ext2FileCanRead (0x1) -#define Ext2FileCanWrite (0x2) -#define Ext2FileCanExecute (0x4) - - -/* - * We need 8-bytes aligned for all the sturctures - * It's a must for all ERESOURCE allocations - */ - -// -// Ext2Fsd Driver Definitions -// - -// -// EXT2_IDENTIFIER_TYPE -// -// Identifiers used to mark the structures -// - -typedef enum _EXT2_IDENTIFIER_TYPE { -#ifdef _MSC_VER - EXT2FGD = ':DGF', - EXT2VCB = ':BCV', - EXT2FCB = ':BCF', - EXT2CCB = ':BCC', - EXT2ICX = ':XCI', - EXT2FSD = ':DSF', - EXT2MCB = ':BCM' -#else - EXT2FGD = 0xE2FD0001, - EXT2VCB = 0xE2FD0002, - EXT2FCB = 0xE2FD0003, - EXT2CCB = 0xE2FD0004, - EXT2ICX = 0xE2FD0005, - EXT2FSD = 0xE2FD0006, - EXT2MCB = 0xE2FD0007 -#endif -} EXT2_IDENTIFIER_TYPE; - -// -// EXT2_IDENTIFIER -// -// Header used to mark the structures -// -typedef struct _EXT2_IDENTIFIER { - EXT2_IDENTIFIER_TYPE Type; - ULONG Size; -} EXT2_IDENTIFIER, *PEXT2_IDENTIFIER; - - -#define NodeType(Ptr) (*((EXT2_IDENTIFIER_TYPE *)(Ptr))) - -typedef struct _EXT2_MCB EXT2_MCB, *PEXT2_MCB; - - -typedef PVOID PBCB; - -// - -// -// EXT2_GLOBAL_DATA -// -// Data that is not specific to a mounted volume -// - -typedef VOID (*EXT2_REAPER_RELEASE)(PVOID); - -typedef struct _EXT2_REAPER { - PETHREAD Thread; - KEVENT Engine; - KEVENT Wait; - EXT2_REAPER_RELEASE Free; - ULONG Flags; -} EXT2_REAPER, *PEXT2_REAPER; - -#define EXT2_REAPER_FLAG_STOP (1 << 0) - -typedef struct _EXT2_GLOBAL { - - /* Identifier for this structure */ - EXT2_IDENTIFIER Identifier; - - /* Syncronization primitive for this structure */ - ERESOURCE Resource; - - /* Global flags for the driver: I put it since - FastIoDispatch isn't 8bytes aligned. */ - ULONG Flags; - - /* Table of pointers to the fast I/O entry points */ - FAST_IO_DISPATCH FastIoDispatch; - - /* Filter callbacks */ - FS_FILTER_CALLBACKS FilterCallbacks; - - /* Table of pointers to the Cache Manager callbacks */ - CACHE_MANAGER_CALLBACKS CacheManagerCallbacks; - CACHE_MANAGER_CALLBACKS CacheManagerNoOpCallbacks; - - /* Pointer to the driver object */ - PDRIVER_OBJECT DriverObject; - - /* Pointer to the disk device object */ - PDEVICE_OBJECT DiskdevObject; - - /* Pointer to the cdrom device object */ - PDEVICE_OBJECT CdromdevObject; - - /* List of mounted volumes */ - LIST_ENTRY VcbList; - - /* Cleaning thread related: resource cleaner */ - EXT2_REAPER FcbReaper; - EXT2_REAPER McbReaper; - EXT2_REAPER bhReaper; - - /* Look Aside table of IRP_CONTEXT, FCB, MCB, CCB */ - NPAGED_LOOKASIDE_LIST Ext2IrpContextLookasideList; - NPAGED_LOOKASIDE_LIST Ext2FcbLookasideList; - NPAGED_LOOKASIDE_LIST Ext2CcbLookasideList; - NPAGED_LOOKASIDE_LIST Ext2McbLookasideList; - NPAGED_LOOKASIDE_LIST Ext2ExtLookasideList; - NPAGED_LOOKASIDE_LIST Ext2DentryLookasideList; - USHORT MaxDepth; - - /* User specified global codepage name */ - struct { - WCHAR PageName[CODEPAGE_MAXLEN]; - UCHAR AnsiName[CODEPAGE_MAXLEN]; - struct nls_table * PageTable; - } Codepage; - - /* global hiding patterns */ - WCHAR wHidingPrefix[HIDINGPAT_LEN]; - WCHAR wHidingSuffix[HIDINGPAT_LEN]; - BOOLEAN bHidingPrefix; - CHAR sHidingPrefix[HIDINGPAT_LEN]; - BOOLEAN bHidingSuffix; - CHAR sHidingSuffix[HIDINGPAT_LEN]; - - /* Registery path */ - UNICODE_STRING RegistryPath; - - /* global memory and i/o statistics and memory allocations - of various sturctures */ - - EXT2_PERF_STATISTICS_V2 PerfStat; - -} EXT2_GLOBAL, *PEXT2_GLOBAL; - -// -// Flags for EXT2_GLOBAL_DATA -// - -#define EXT2_UNLOAD_PENDING 0x00000001 -#define EXT2_SUPPORT_WRITING 0x00000002 -#define EXT3_FORCE_WRITING 0x00000004 -#define EXT2_CHECKING_BITMAP 0x00000008 -#define EXT2_AUTO_MOUNT 0x00000010 - -// -// Glboal Ext2Fsd Memory Block -// - -extern PEXT2_GLOBAL Ext2Global; - -// -// memory allocation statistics -// - - -#define INC_MEM_COUNT(_i, _p, _s) do { ASSERT(_p); Ext2TraceMemory(TRUE, (int) (_i), (PVOID)(_p), (LONG)(_s)); } while(0) -#define DEC_MEM_COUNT(_i, _p, _s) do { ASSERT(_p); Ext2TraceMemory(FALSE, (int) (_i), (PVOID)(_p), (LONG)(_s)); } while(0) -#define INC_IRP_COUNT(IrpContext) Ext2TraceIrpContext(TRUE, (IrpContext)) -#define DEC_IRP_COUNT(IrpContext) Ext2TraceIrpContext(FALSE, (IrpContext)) - -// -// Driver Extension define -// - -#define IsExt2FsDevice(DO) ((DO == Ext2Global->DiskdevObject) || \ - (DO == Ext2Global->CdromdevObject) ) - -#ifdef _WIN2K_TARGET_ -#define FSRTL_ADVANCED_FCB_HEADER FSRTL_COMMON_FCB_HEADER -#endif - -typedef struct _EXT2_FCBVCB { - - // Command header for Vcb and Fcb - FSRTL_ADVANCED_FCB_HEADER Header; - -#ifndef _WIN2K_TARGET_ - FAST_MUTEX Mutex; -#endif - - // Ext2Fsd identifier - EXT2_IDENTIFIER Identifier; - - - // Locking resources - ERESOURCE MainResource; - ERESOURCE PagingIoResource; - -} EXT2_FCBVCB, *PEXT2_FCBVCB; - -// -// EXT2_VCB Volume Control Block -// -// Data that represents a mounted logical volume -// It is allocated as the device extension of the volume device object -// -typedef struct _EXT2_VCB { - - /* Common header */ - EXT2_FCBVCB; - - // Resource for metadata (inode) - ERESOURCE MetaInode; - - // Resource for metadata (block) - ERESOURCE MetaBlock; - - // Resource for Mcb (Meta data control block) - ERESOURCE McbLock; - - // List of FCBs for open files on this volume - ERESOURCE FcbLock; - LIST_ENTRY FcbList; - ULONG FcbCount; - - // Mcb list - ULONG NumOfMcb; - LIST_ENTRY McbList; - - // Entry of Mcb Tree (Root Node) - PEXT2_MCB McbTree; - - // Link list to Global - LIST_ENTRY Next; - - // Section objects - SECTION_OBJECT_POINTERS SectionObject; - - // Dirty Mcbs of modifications for volume stream - LARGE_MCB Extents; - - - // Share Access for the file object - SHARE_ACCESS ShareAccess; - - // Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLOSE - // for both files on this volume and open instances of the - // volume itself. - ULONG ReferenceCount; /* total ref count */ - ULONG OpenHandleCount; /* all handles */ - - ULONG OpenVolumeCount; /* volume handle */ - - // Disk change count - ULONG ChangeCount; - - // Pointer to the VPB in the target device object - PVPB Vpb; - PVPB Vpb2; - - // The FileObject of Volume used to lock the volume - PFILE_OBJECT LockFile; - - // List of IRPs pending on directory change notify requests - LIST_ENTRY NotifyList; - - // Pointer to syncronization primitive for this list - PNOTIFY_SYNC NotifySync; - - // This volumes device object - PDEVICE_OBJECT DeviceObject; - - // The physical device object (the disk) - PDEVICE_OBJECT TargetDeviceObject; - - // The physical device object (the disk) - PDEVICE_OBJECT RealDevice; - - // Information about the physical device object - DISK_GEOMETRY DiskGeometry; - PARTITION_INFORMATION PartitionInformation; - - BOOLEAN IsExt3fs; - PEXT2_SUPER_BLOCK SuperBlock; - - // Block / Cluster size - ULONG BlockSize; - - // Sector size in bits - ULONG SectorBits; - - // Minimal i/o size: min(PageSize, BlockSize) - ULONGLONG IoUnitSize; - - // Bits of aligned size - ULONG IoUnitBits; - - // Inode size - ULONG InodeSize; - - // Inode lookaside list - NPAGED_LOOKASIDE_LIST InodeLookasideList; - - // Flags for the volume - ULONG Flags; - - // Streaming File Object - PFILE_OBJECT Volume; - - // User specified codepage name per volume - struct { - UCHAR AnsiName[CODEPAGE_MAXLEN]; - struct nls_table * PageTable; - } Codepage; - - /* patterns to hiding files */ - BOOLEAN bHidingPrefix; - CHAR sHidingPrefix[HIDINGPAT_LEN]; - BOOLEAN bHidingSuffix; - CHAR sHidingSuffix[HIDINGPAT_LEN]; - - /* User to impersanate */ - uid_t uid; - gid_t gid; - - /* User to act as */ - uid_t euid; - gid_t egid; - - /* mountpoint: symlink to DesDevices */ - UCHAR DrvLetter; - - struct block_device bd; - struct super_block sb; - struct ext3_sb_info sbi; - - /* Maximum file size in blocks ... */ - ULONG max_blocks_per_layer[EXT2_BLOCK_TYPES]; - ULONG max_data_blocks; - loff_t max_bitmap_bytes; - loff_t max_bytes; -} EXT2_VCB, *PEXT2_VCB; - -// -// Flags for EXT2_VCB -// -#define VCB_INITIALIZED 0x00000001 -#define VCB_VOLUME_LOCKED 0x00000002 -#define VCB_MOUNTED 0x00000004 -#define VCB_DISMOUNT_PENDING 0x00000008 -#define VCB_NEW_VPB 0x00000010 -#define VCB_BEING_CLOSED 0x00000020 -#define VCB_USER_IDS 0x00000040 /* uid/gid specified by user */ -#define VCB_USER_EIDS 0x00000080 /* euid/egid specified by user */ -#define VCB_GD_LOADED 0x00000100 /* group desc loaded */ - -#define VCB_BEING_DROPPED 0x00002000 -#define VCB_FORCE_WRITING 0x00004000 -#define VCB_DEVICE_REMOVED 0x00008000 -#define VCB_JOURNAL_RECOVER 0x00080000 -#define VCB_ARRIVAL_NOTIFIED 0x00800000 -#define VCB_RO_COMPAT_READ_ONLY 0x01000000 -#define VCB_READ_ONLY 0x08000000 -#define VCB_WRITE_PROTECTED 0x10000000 -#define VCB_FLOPPY_DISK 0x20000000 -#define VCB_REMOVAL_PREVENTED 0x40000000 -#define VCB_REMOVABLE_MEDIA 0x80000000 - - -#define IsVcbInited(Vcb) (IsFlagOn((Vcb)->Flags, VCB_INITIALIZED)) -#define IsMounted(Vcb) (IsFlagOn((Vcb)->Flags, VCB_MOUNTED)) -#define IsDispending(Vcb) (IsFlagOn((Vcb)->Flags, VCB_DISMOUNT_PENDING)) -#define IsVcbReadOnly(Vcb) (IsFlagOn((Vcb)->Flags, VCB_READ_ONLY) || \ - IsFlagOn((Vcb)->Flags, VCB_RO_COMPAT_READ_ONLY) || \ - IsFlagOn((Vcb)->Flags, VCB_WRITE_PROTECTED)) - - -#define IsExt3ForceWrite() (IsFlagOn(Ext2Global->Flags, EXT3_FORCE_WRITING)) -#define IsVcbForceWrite(Vcb) (IsFlagOn((Vcb)->Flags, VCB_FORCE_WRITING)) -#define CanIWrite(Vcb) (IsExt3ForceWrite() || (!IsVcbReadOnly(Vcb) && IsVcbForceWrite(Vcb))) -#define IsLazyWriter(Fcb) ((Fcb)->LazyWriterThread == PsGetCurrentThread()) -// -// EXT2_FCB File Control Block -// -// Data that represents an open file -// There is a single instance of the FCB for every open file -// -typedef struct _EXT2_FCB { - - /* Common header */ - EXT2_FCBVCB; - - // List of FCBs for this volume - LIST_ENTRY Next; - LARGE_INTEGER TsDrop; /* drop time */ - - SECTION_OBJECT_POINTERS SectionObject; - - // Share Access for the file object - SHARE_ACCESS ShareAccess; - - // List of byte-range locks for this file - FILE_LOCK FileLockAnchor; - - // oplock information management structure - OPLOCK Oplock; - - // Lazy writer thread context - PETHREAD LazyWriterThread; - - // Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP - ULONG OpenHandleCount; - - // Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLOSE - ULONG ReferenceCount; - - // Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP - // But only for Files with FO_NO_INTERMEDIATE_BUFFERING flag - ULONG NonCachedOpenCount; - - // Flags for the FCB - ULONG Flags; - - // Pointer to the inode - struct inode *Inode; - - // Vcb - PEXT2_VCB Vcb; - - // Mcb Node ... - PEXT2_MCB Mcb; - -} EXT2_FCB, *PEXT2_FCB; - -// -// Flags for EXT2_FCB -// - -#define FCB_FROM_POOL 0x00000001 -#define FCB_PAGE_FILE 0x00000002 -#define FCB_FILE_MODIFIED 0x00000020 - -#define FCB_ALLOC_IN_CREATE 0x00000080 -#define FCB_ALLOC_IN_WRITE 0x00000100 -#define FCB_ALLOC_IN_SETINFO 0x00000200 - -#define FCB_DELETE_PENDING 0x80000000 - -// -// Mcb Node -// - -struct _EXT2_MCB { - - // Identifier for this structure - EXT2_IDENTIFIER Identifier; - - // Flags - ULONG Flags; - - // Link List Info - PEXT2_MCB Parent; // Parent - PEXT2_MCB Next; // Siblings - - union { - PEXT2_MCB Child; // Children Mcb nodes - PEXT2_MCB Target; // Target Mcb of symlink - }; - - // Mcb Node Info - - // -> Fcb - PEXT2_FCB Fcb; - - // Short name - UNICODE_STRING ShortName; - - // Full name with path - UNICODE_STRING FullName; - - // File attribute - ULONG FileAttr; - - // reference count - ULONG Refercount; - - // Extents zone - LARGE_MCB Extents; - - // Metablocks - LARGE_MCB MetaExts; - - // Time stamps - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - LARGE_INTEGER LastAccessTime; - - // List Link to Vcb->McbList - LIST_ENTRY Link; - - - - struct inode Inode; - struct dentry *de; -}; - -// -// Flags for MCB -// -#define MCB_FROM_POOL 0x00000001 -#define MCB_VCB_LINK 0x00000002 -#define MCB_ENTRY_TREE 0x00000004 -#define MCB_FILE_DELETED 0x00000008 - -#define MCB_ZONE_INITED 0x20000000 -#define MCB_TYPE_SPECIAL 0x40000000 /* unresolved symlink + device node */ -#define MCB_TYPE_SYMLINK 0x80000000 - -#define IsMcbUsed(Mcb) ((Mcb)->Refercount > 0) -#define IsMcbSymLink(Mcb) IsFlagOn((Mcb)->Flags, MCB_TYPE_SYMLINK) -#define IsZoneInited(Mcb) IsFlagOn((Mcb)->Flags, MCB_ZONE_INITED) -#define IsMcbSpecialFile(Mcb) IsFlagOn((Mcb)->Flags, MCB_TYPE_SPECIAL) -#define IsMcbRoot(Mcb) ((Mcb)->Inode.i_ino == EXT2_ROOT_INO) -#define IsMcbReadonly(Mcb) IsFlagOn((Mcb)->FileAttr, FILE_ATTRIBUTE_READONLY) -#define IsMcbDirectory(Mcb) IsFlagOn((Mcb)->FileAttr, FILE_ATTRIBUTE_DIRECTORY) -#define IsFileDeleted(Mcb) IsFlagOn((Mcb)->Flags, MCB_FILE_DELETED) - -#define IsLinkInvalid(Mcb) (IsMcbSymLink(Mcb) && IsFileDeleted(Mcb->Target)) - -/* - * routines for reference count management - */ - -#define Ext2ReferXcb(_C) InterlockedIncrement(_C) -#define Ext2DerefXcb(_C) DEC_OBJ_CNT(_C) - -__inline ULONG DEC_OBJ_CNT(PULONG _C) { - if (*_C <= 0) { - DbgBreak(); - } - return InterlockedDecrement(_C); -} - -#if EXT2_DEBUG -VOID -Ext2TraceMcb(PCHAR fn, USHORT lc, USHORT add, PEXT2_MCB Mcb); -#define Ext2ReferMcb(Mcb) Ext2TraceMcb(__FUNCTION__, __LINE__, TRUE, Mcb) -#define Ext2DerefMcb(Mcb) Ext2TraceMcb(__FUNCTION__, __LINE__, FALSE, Mcb) -#else -#define Ext2ReferMcb(Mcb) Ext2ReferXcb(&Mcb->Refercount) -#define Ext2DerefMcb(Mcb) Ext2DerefXcb(&Mcb->Refercount) -#endif - -// -// EXT2_CCB Context Control Block -// -// Data that represents one instance of an open file -// There is one instance of the CCB for every instance of an open file -// -typedef struct _EXT2_CCB { - - // Identifier for this structure - EXT2_IDENTIFIER Identifier; - - // Flags - ULONG Flags; - - // Mcb of it's symbol link - PEXT2_MCB SymLink; - - // State that may need to be maintained - UNICODE_STRING DirectorySearchPattern; - - /* Open handle control block */ - struct file filp; - - /* The EA index we are on */ - ULONG EaIndex; - -} EXT2_CCB, *PEXT2_CCB; - -// -// Flags for CCB -// - -#define CCB_FROM_POOL 0x00000001 -#define CCB_VOLUME_DASD_PURGE 0x00000002 -#define CCB_LAST_WRITE_UPDATED 0x00000004 -#define CCB_OPEN_REPARSE_POINT 0x00000008 -#define CCB_DELETE_ON_CLOSE 0x00000010 - -#define CCB_ALLOW_EXTENDED_DASD_IO 0x80000000 - -// -// EXT2_IRP_CONTEXT -// -// Used to pass information about a request between the drivers functions -// -typedef struct ext2_icb { - - // Identifier for this structure - EXT2_IDENTIFIER Identifier; - - // Pointer to the IRP this request describes - PIRP Irp; - - // Flags - ULONG Flags; - - // The major and minor function code for the request - UCHAR MajorFunction; - UCHAR MinorFunction; - - // The device object - PDEVICE_OBJECT DeviceObject; - - // The real device object - PDEVICE_OBJECT RealDevice; - - // The file object - PFILE_OBJECT FileObject; - - PEXT2_FCB Fcb; - PEXT2_CCB Ccb; - - // If the request is top level - BOOLEAN IsTopLevel; - - // Used if the request needs to be queued for later processing - WORK_QUEUE_ITEM WorkQueueItem; - - // If an exception is currently in progress - BOOLEAN ExceptionInProgress; - - // The exception code when an exception is in progress - NTSTATUS ExceptionCode; - -} EXT2_IRP_CONTEXT, *PEXT2_IRP_CONTEXT; - - -#define IRP_CONTEXT_FLAG_FROM_POOL (0x00000001) -#define IRP_CONTEXT_FLAG_WAIT (0x00000002) -#define IRP_CONTEXT_FLAG_WRITE_THROUGH (0x00000004) -#define IRP_CONTEXT_FLAG_FLOPPY (0x00000008) -#define IRP_CONTEXT_FLAG_DISABLE_POPUPS (0x00000020) -#define IRP_CONTEXT_FLAG_DEFERRED (0x00000040) -#define IRP_CONTEXT_FLAG_VERIFY_READ (0x00000080) -#define IRP_CONTEXT_STACK_IO_CONTEXT (0x00000100) -#define IRP_CONTEXT_FLAG_REQUEUED (0x00000200) -#define IRP_CONTEXT_FLAG_USER_IO (0x00000400) -#define IRP_CONTEXT_FLAG_DELAY_CLOSE (0x00000800) -#define IRP_CONTEXT_FLAG_FILE_BUSY (0x00001000) - - -#define Ext2CanIWait() (!IrpContext || IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) - -// -// EXT2_ALLOC_HEADER -// -// In the checked version of the driver this header is put in the beginning of -// every memory allocation -// -typedef struct _EXT2_ALLOC_HEADER { - EXT2_IDENTIFIER Identifier; -} EXT2_ALLOC_HEADER, *PEXT2_ALLOC_HEADER; - -typedef struct _FCB_LIST_ENTRY { - PEXT2_FCB Fcb; - LIST_ENTRY Next; -} FCB_LIST_ENTRY, *PFCB_LIST_ENTRY; - - -// Block Description List -typedef struct _EXT2_EXTENT { - LONGLONG Lba; - ULONG Offset; - ULONG Length; - PIRP Irp; - struct _EXT2_EXTENT * Next; -} EXT2_EXTENT, *PEXT2_EXTENT; - - -/* FUNCTIONS DECLARATION *****************************************************/ - -// Include this so we don't need the latest WDK to build the driver. -#ifndef FSCTL_GET_RETRIEVAL_POINTER_BASE -#define FSCTL_GET_RETRIEVAL_POINTER_BASE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 141, METHOD_BUFFERED, FILE_ANY_ACCESS) // RETRIEVAL_POINTER_BASE -#endif - -#ifndef FILE_SUPPORTS_EXTENDED_ATTRIBUTES -#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000 -#endif - -// -// The following macro is used to determine if an FSD thread can block -// for I/O or wait for a resource. It returns TRUE if the thread can -// block and FALSE otherwise. This attribute can then be used to call -// the FSD & FSP common work routine with the proper wait value. -// - -#define CanExt2Wait(IRP) IoIsOperationSynchronous(Irp) - -// -// memory allocation statistics -// - -__inline -VOID -Ext2TraceMemory(BOOLEAN _n, int _i, PVOID _p, LONG _s) -{ - if (_n) { - InterlockedIncrement(&Ext2Global->PerfStat.Current.Slot[_i]); - InterlockedIncrement(&Ext2Global->PerfStat.Total.Slot[_i]); - InterlockedExchangeAdd(&Ext2Global->PerfStat.Size.Slot[_i], _s); - } else { - InterlockedDecrement(&Ext2Global->PerfStat.Current.Slot[_i]); - InterlockedExchangeAdd(&Ext2Global->PerfStat.Size.Slot[_i], -1 * _s); - } -} - -__inline -VOID -Ext2TraceIrpContext(BOOLEAN _n, PEXT2_IRP_CONTEXT IrpContext) -{ - if (_n) { - INC_MEM_COUNT(PS_IRP_CONTEXT, IrpContext, sizeof(EXT2_IRP_CONTEXT)); - InterlockedIncrement(&(Ext2Global->PerfStat.Irps[IrpContext->MajorFunction].Current)); - } else { - DEC_MEM_COUNT(PS_IRP_CONTEXT, IrpContext, sizeof(EXT2_IRP_CONTEXT)); - InterlockedIncrement(&Ext2Global->PerfStat.Irps[IrpContext->MajorFunction].Processed); - InterlockedDecrement(&Ext2Global->PerfStat.Irps[IrpContext->MajorFunction].Current); - } -} - -typedef struct _EXT2_FILLDIR_CONTEXT { - PEXT2_IRP_CONTEXT efc_irp; - PUCHAR efc_buf; - ULONG efc_size; - ULONG efc_start; - ULONG efc_prev; - NTSTATUS efc_status; - FILE_INFORMATION_CLASS efc_fi; - BOOLEAN efc_single; -} EXT2_FILLDIR_CONTEXT, *PEXT2_FILLDIR_CONTEXT; - -// -// Access.c -// - - -int Ext2CheckInodeAccess(PEXT2_VCB Vcb, struct inode *in, int attempt); -int Ext2CheckFileAccess (PEXT2_VCB Vcb, PEXT2_MCB Mcb, int attempt); - -// -// Block.c -// - -PMDL -Ext2CreateMdl ( - IN PVOID Buffer, - IN ULONG Length, - IN LOCK_OPERATION Operation -); - -VOID -Ext2DestroyMdl (IN PMDL Mdl); - -NTSTATUS -Ext2LockUserBuffer ( - IN PIRP Irp, - IN ULONG Length, - IN LOCK_OPERATION Operation); -PVOID -Ext2GetUserBuffer (IN PIRP Irp); - - -NTSTATUS -Ext2ReadWriteBlocks( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_EXTENT Extent, - IN ULONG Length - ); - -NTSTATUS -Ext2ReadSync( - IN PEXT2_VCB Vcb, - IN ULONGLONG Offset, - IN ULONG Length, - OUT PVOID Buffer, - IN BOOLEAN bVerify ); - -NTSTATUS -Ext2ReadDisk( - IN PEXT2_VCB Vcb, - IN ULONGLONG Offset, - IN ULONG Size, - IN PVOID Buffer, - IN BOOLEAN bVerify ); - -NTSTATUS -Ext2DiskIoControl ( - IN PDEVICE_OBJECT DeviceOjbect, - IN ULONG IoctlCode, - IN PVOID InputBuffer, - IN ULONG InputBufferSize, - IN OUT PVOID OutputBuffer, - IN OUT PULONG OutputBufferSize ); - -VOID -Ext2MediaEjectControl ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN BOOLEAN bPrevent ); - -NTSTATUS -Ext2DiskShutDown(PEXT2_VCB Vcb); - - -// -// Cleanup.c -// - -NTSTATUS -Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext); - -// -// Close.c -// - -NTSTATUS -Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext); - -VOID -Ext2QueueCloseRequest (IN PEXT2_IRP_CONTEXT IrpContext); - -VOID -Ext2DeQueueCloseRequest (IN PVOID Context); - -// -// Cmcb.c -// - -BOOLEAN -Ext2AcquireForLazyWrite ( - IN PVOID Context, - IN BOOLEAN Wait ); -VOID -Ext2ReleaseFromLazyWrite (IN PVOID Context); - -BOOLEAN -Ext2AcquireForReadAhead ( - IN PVOID Context, - IN BOOLEAN Wait ); - -VOID -Ext2ReleaseFromReadAhead (IN PVOID Context); - -BOOLEAN -Ext2NoOpAcquire ( - IN PVOID Fcb, - IN BOOLEAN Wait ); - -VOID -Ext2NoOpRelease (IN PVOID Fcb); - - -// -// Create.c -// - - -BOOLEAN -Ext2IsNameValid(PUNICODE_STRING FileName); - -NTSTATUS -Ext2FollowLink ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Parent, - IN PEXT2_MCB Mcb, - IN ULONG Linkdep -); - -NTSTATUS -Ext2ScanDir ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Parent, - IN PUNICODE_STRING FileName, - OUT PULONG Inode, - struct dentry **dentry -); - -BOOLEAN -Ext2IsSpecialSystemFile( - IN PUNICODE_STRING FileName, - IN BOOLEAN bDirectory -); - -#define EXT2_LOOKUP_FLAG_MASK (0xFF00000) -#define EXT2_LOOKUP_NOT_FOLLOW (0x8000000) - -NTSTATUS -Ext2LookupFile ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PUNICODE_STRING FullName, - IN PEXT2_MCB Parent, - OUT PEXT2_MCB * Ext2Mcb, - IN ULONG Linkdep -); - -NTSTATUS -Ext2CreateFile( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - OUT PBOOLEAN OpPostIrp -); - -NTSTATUS -Ext2CreateVolume( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb ); - -NTSTATUS -Ext2Create (IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2CreateInode( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_FCB pParentFcb, - IN ULONG Type, - IN ULONG FileAttr, - IN PUNICODE_STRING FileName); - - -NTSTATUS -Ext2SupersedeOrOverWriteFile( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PFILE_OBJECT FileObject, - IN PEXT2_VCB Vcb, - IN PEXT2_FCB Fcb, - IN PLARGE_INTEGER AllocationSize, - IN ULONG Disposition -); - -// -// Debug.c -// - -/* debug levels */ -#define DL_NVR 0 -#define DL_VIT 0x00000001 -#define DL_ERR 0x00000002 -#define DL_DBG 0x00000004 -#define DL_INF 0x00000008 -#define DL_FUN 0x00000010 -#define DL_LOW 0x00000020 -#define DL_REN 0x00000040 /* renaming operation */ -#define DL_RES 0x00000080 /* entry reference managment */ -#define DL_BLK 0x00000100 /* data block allocation / free */ -#define DL_CP 0x00000200 /* code pages (create, querydir) */ -#define DL_EXT 0x00000400 /* mcb extents */ -#define DL_MAP 0x00000800 /* retrieval points */ -#define DL_JNL 0x00001000 /* dump journal operations */ -#define DL_HTI 0x00002000 /* htree index */ -#define DL_WRN 0x00004000 /* warning */ -#define DL_BH 0x00008000 /* buffer head */ -#define DL_PNP 0x00010000 /* pnp */ -#define DL_IO 0x00020000 /* file i/o */ - -#define DL_DEFAULT (DL_ERR|DL_VIT) - -#if EXT2_DEBUG -extern ULONG DebugFilter; - -VOID -__cdecl -Ext2NiPrintf( - PCHAR DebugMessage, - ... -); - -#define DEBUG(_DL, arg) do {if ((_DL) & DebugFilter) Ext2Printf arg;} while(0) -#define DEBUGNI(_DL, arg) do {if ((_DL) & DebugFilter) Ext2NiPrintf arg;} while(0) - -#define Ext2CompleteRequest(Irp, bPrint, PriorityBoost) \ - Ext2DbgPrintComplete(Irp, bPrint); \ - IoCompleteRequest(Irp, PriorityBoost) - -#else - -#define DEBUG(_DL, arg) do {if ((_DL) & DL_ERR) DbgPrint arg;} while(0) - -#define Ext2CompleteRequest(Irp, bPrint, PriorityBoost) \ - IoCompleteRequest(Irp, PriorityBoost) - -#endif // EXT2_DEBUG - -VOID -__cdecl -Ext2Printf( - PCHAR DebugMessage, - ... -); - -extern ULONG ProcessNameOffset; - -#define Ext2GetCurrentProcessName() ( \ - (PUCHAR) PsGetCurrentProcess() + ProcessNameOffset \ -) - -ULONG -Ext2GetProcessNameOffset (VOID); - -VOID -Ext2DbgPrintCall ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp ); - -VOID -Ext2DbgPrintComplete ( - IN PIRP Irp, - IN BOOLEAN bPrint -); - -PUCHAR -Ext2NtStatusToString (IN NTSTATUS Status ); - -PVOID Ext2AllocatePool( - IN POOL_TYPE PoolType, - IN SIZE_T NumberOfBytes, - IN ULONG Tag -); - -VOID -Ext2FreePool( - IN PVOID P, - IN ULONG Tag -); - -// -// Devctl.c -// - -NTSTATUS -Ext2ProcessGlobalProperty( - IN PDEVICE_OBJECT DeviceObject, - IN PEXT2_VOLUME_PROPERTY3 Property, - IN ULONG Length -); - -NTSTATUS -Ext2ProcessVolumeProperty( - IN PEXT2_VCB Vcb, - IN PEXT2_VOLUME_PROPERTY3 Property, - IN ULONG Length -); - -NTSTATUS -Ext2ProcessUserProperty( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VOLUME_PROPERTY3 Property, - IN ULONG Length -); - -NTSTATUS -Ex2ProcessUserPerfStat( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_QUERY_PERFSTAT QueryPerf, - IN ULONG Length -); - -NTSTATUS -Ex2ProcessMountPoint( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_MOUNT_POINT MountPoint, - IN ULONG Length -); - -NTSTATUS -Ext2DeviceControlNormal (IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2PrepareToUnload (IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2DeviceControl (IN PEXT2_IRP_CONTEXT IrpContext); - -// -// Dirctl.c -// - -ULONG -Ext2GetInfoLength(IN FILE_INFORMATION_CLASS FileInformationClass); - -NTSTATUS -Ext2ProcessEntry( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_FCB Dcb, - IN FILE_INFORMATION_CLASS FileInformationClass, - IN ULONG in, - IN PVOID Buffer, - IN ULONG UsedLength, - IN ULONG Length, - IN ULONG FileIndex, - IN PUNICODE_STRING pName, - OUT PULONG EntrySize, - IN BOOLEAN Single -); - -BOOLEAN -Ext2IsWearingCloak( - IN PEXT2_VCB Vcb, - IN POEM_STRING OeName -); - -NTSTATUS Ext2QueryDirectory (IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2NotifyChangeDirectory ( - IN PEXT2_IRP_CONTEXT IrpContext -); - -VOID -Ext2NotifyReportChange ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Filter, - IN ULONG Action -); - -NTSTATUS -Ext2DirectoryControl (IN PEXT2_IRP_CONTEXT IrpContext); - -BOOLEAN -Ext2IsDirectoryEmpty ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb -); - -// -// Dispatch.c -// - -VOID -Ext2OplockComplete ( - IN PVOID Context, - IN PIRP Irp -); - -VOID -Ext2LockIrp ( - IN PVOID Context, - IN PIRP Irp -); - -NTSTATUS -Ext2QueueRequest (IN PEXT2_IRP_CONTEXT IrpContext); - -VOID -Ext2DeQueueRequest (IN PVOID Context); - -NTSTATUS -Ext2DispatchRequest (IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2BuildRequest ( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp -); - -// -// ea.c -// - -NTSTATUS -Ext2QueryEa( - IN PEXT2_IRP_CONTEXT IrpContext -); - -BOOLEAN -Ext2IsEaNameValid( - IN OEM_STRING Name -); - -NTSTATUS -Ext2SetEa( - IN PEXT2_IRP_CONTEXT IrpContext -); - - -// -// Except.c -// - -NTSTATUS -Ext2ExceptionFilter ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXCEPTION_POINTERS ExceptionPointer -); - -NTSTATUS -Ext2ExceptionHandler (IN PEXT2_IRP_CONTEXT IrpContext); - - -// -// Extents.c -// - - -NTSTATUS -Ext2MapExtent( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Index, - IN BOOLEAN Alloc, - OUT PULONG Block, - OUT PULONG Number - ); - -NTSTATUS -Ext2ExpandExtent( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_MCB Mcb, - ULONG Start, - ULONG End, - PLARGE_INTEGER Size - ); - -NTSTATUS -Ext2TruncateExtent( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_MCB Mcb, - PLARGE_INTEGER Size - ); - - -// -// generic.c -// - -static inline ext3_fsblk_t ext3_blocks_count(struct ext3_super_block *es) -{ - return ((ext3_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) | - le32_to_cpu(es->s_blocks_count); -} - -static inline ext3_fsblk_t ext3_r_blocks_count(struct ext3_super_block *es) -{ - return ((ext3_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) | - le32_to_cpu(es->s_r_blocks_count); -} - -static inline ext3_fsblk_t ext3_free_blocks_count(struct ext3_super_block *es) -{ - return ((ext3_fsblk_t)le32_to_cpu(es->s_free_blocks_count_hi) << 32) | - le32_to_cpu(es->s_free_blocks_count); -} - -static inline void ext3_blocks_count_set(struct ext3_super_block *es, - ext3_fsblk_t blk) -{ - es->s_blocks_count = cpu_to_le32((u32)blk); - es->s_blocks_count_hi = cpu_to_le32(blk >> 32); -} - -static inline void ext3_free_blocks_count_set(struct ext3_super_block *es, - ext3_fsblk_t blk) -{ - es->s_free_blocks_count = cpu_to_le32((u32)blk); - es->s_free_blocks_count_hi = cpu_to_le32(blk >> 32); -} - -static inline void ext3_r_blocks_count_set(struct ext3_super_block *es, - ext3_fsblk_t blk) -{ - es->s_r_blocks_count = cpu_to_le32((u32)blk); - es->s_r_blocks_count_hi = cpu_to_le32(blk >> 32); -} - -blkcnt_t ext3_inode_blocks(struct ext3_inode *raw_inode, - struct inode *inode); - -int ext3_inode_blocks_set(struct ext3_inode *raw_inode, - struct inode * inode); -ext4_fsblk_t ext4_block_bitmap(struct super_block *sb, - struct ext4_group_desc *bg); - -ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb, - struct ext4_group_desc *bg); -ext4_fsblk_t ext4_inode_table(struct super_block *sb, - struct ext4_group_desc *bg); -__u32 ext4_free_blks_count(struct super_block *sb, - struct ext4_group_desc *bg); -__u32 ext4_free_inodes_count(struct super_block *sb, - struct ext4_group_desc *bg); -__u32 ext4_used_dirs_count(struct super_block *sb, - struct ext4_group_desc *bg); -__u32 ext4_itable_unused_count(struct super_block *sb, - struct ext4_group_desc *bg); -void ext4_block_bitmap_set(struct super_block *sb, - struct ext4_group_desc *bg, ext4_fsblk_t blk); -void ext4_inode_bitmap_set(struct super_block *sb, - struct ext4_group_desc *bg, ext4_fsblk_t blk); -void ext4_inode_table_set(struct super_block *sb, - struct ext4_group_desc *bg, ext4_fsblk_t blk); -void ext4_free_blks_set(struct super_block *sb, - struct ext4_group_desc *bg, __u32 count); -void ext4_free_inodes_set(struct super_block *sb, - struct ext4_group_desc *bg, __u32 count); -void ext4_used_dirs_set(struct super_block *sb, - struct ext4_group_desc *bg, __u32 count); -void ext4_itable_unused_set(struct super_block *sb, - struct ext4_group_desc *bg, __u32 count); - -int ext3_bg_has_super(struct super_block *sb, ext3_group_t group); -unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group); -unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh, - ext4_group_t block_group, - struct ext4_group_desc *gdp); -unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, - ext4_group_t block_group, struct ext4_group_desc *gdp); -struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, - ext4_group_t block_group, struct buffer_head **bh); -ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb); -unsigned long ext4_count_free_inodes(struct super_block *sb); -int ext4_check_descriptors(struct super_block *sb); - -NTSTATUS -Ext2LoadSuper( - IN PEXT2_VCB Vcb, - IN BOOLEAN bVerify, - OUT PEXT2_SUPER_BLOCK * Sb -); - - -BOOLEAN -Ext2SaveSuper( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb -); - -BOOLEAN -Ext2RefreshSuper( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb -); - -BOOLEAN -Ext2LoadGroupBH(IN PEXT2_VCB Vcb); - -BOOLEAN -Ext2LoadGroup(IN PEXT2_VCB Vcb); - -VOID -Ext2DropGroupBH(IN PEXT2_VCB Vcb); - -VOID -Ext2PutGroup(IN PEXT2_VCB Vcb); - -VOID -Ext2DropBH(IN PEXT2_VCB Vcb); - -NTSTATUS -Ext2FlushVcb(IN PEXT2_VCB Vcb); - -BOOLEAN -Ext2SaveGroup( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN ULONG Group -); - -BOOLEAN -Ext2RefreshGroup( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb -); - -BOOLEAN -Ext2GetInodeLba ( - IN PEXT2_VCB Vcb, - IN ULONG inode, - OUT PLONGLONG offset -); - -BOOLEAN -Ext2LoadInode ( - IN PEXT2_VCB Vcb, - IN struct inode *Inode -); - -BOOLEAN -Ext2ClearInode ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN ULONG inode -); - -BOOLEAN -Ext2SaveInode ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN struct inode *Inode -); - -BOOLEAN -Ext2LoadInodeXattr(IN PEXT2_VCB Vcb, - IN struct inode *Inode, - IN PEXT2_INODE InodeXattr); - -BOOLEAN -Ext2SaveInodeXattr(IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN struct inode *Inode, - IN PEXT2_INODE InodeXattr); - -BOOLEAN -Ext2LoadBlock ( - IN PEXT2_VCB Vcb, - IN ULONG dwBlk, - IN PVOID Buffer -); - -BOOLEAN -Ext2SaveBlock ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN ULONG dwBlk, - IN PVOID Buf -); - -BOOLEAN -Ext2LoadBuffer( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN LONGLONG Offset, - IN ULONG Size, - IN PVOID Buf -); - -BOOLEAN -Ext2ZeroBuffer( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN LONGLONG Offset, - IN ULONG Size -); - -BOOLEAN -Ext2SaveBuffer( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN LONGLONG Offset, - IN ULONG Size, - IN PVOID Buf -); - -NTSTATUS -Ext2GetBlock( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Base, - IN ULONG Layer, - IN ULONG Start, - IN ULONG SizeArray, - IN PULONG BlockArray, - IN BOOLEAN bAlloc, - IN OUT PULONG Hint, - OUT PULONG Block, - OUT PULONG Number -); - -NTSTATUS -Ext2BlockMap( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Index, - IN BOOLEAN bAlloc, - OUT PULONG pBlock, - OUT PULONG Number -); - -VOID -Ext2UpdateVcbStat( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb -); - -NTSTATUS -Ext2NewBlock( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN ULONG GroupHint, - IN ULONG BlockHint, - OUT PULONG Block, - IN OUT PULONG Number -); - -NTSTATUS -Ext2FreeBlock( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN ULONG Block, - IN ULONG Number -); - - -NTSTATUS -Ext2NewInode( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN ULONG GroupHint, - IN ULONG Type, - OUT PULONG Inode -); - -NTSTATUS -Ext2UpdateGroupDirStat( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN ULONG Group -); - -NTSTATUS -Ext2FreeInode( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN ULONG Inode, - IN ULONG Type -); - -NTSTATUS -Ext2AddEntry ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_FCB Dcb, - IN struct inode *Inode, - IN PUNICODE_STRING FileName, - OUT struct dentry **dentry -); - -NTSTATUS -Ext2SetFileType ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_FCB Dcb, - IN PEXT2_MCB Mcb, - IN umode_t mode -); - -NTSTATUS -Ext2RemoveEntry ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_FCB Dcb, - IN PEXT2_MCB Mcb -); - -NTSTATUS -Ext2SetParentEntry ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_FCB Dcb, - IN ULONG OldParent, - IN ULONG NewParent ); - - -NTSTATUS -Ext2TruncateBlock( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Base, - IN ULONG Start, - IN ULONG Layer, - IN ULONG SizeArray, - IN PULONG BlockArray, - IN PULONG Extra -); - -struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p); - -int ext3_check_dir_entry (const char * function, struct inode * dir, - struct ext3_dir_entry_2 * de, - struct buffer_head * bh, - unsigned long offset); - -loff_t ext3_max_size(int blkbits, int has_huge_files); -loff_t ext3_max_bitmap_size(int bits, int has_huge_files); - - -/*__le16 ext4_group_desc_csum(struct ext3_sb_info *sbi, __u32 block_group, - struct ext4_group_desc *gdp); -int ext4_group_desc_csum_verify(struct ext3_sb_info *sbi, __u32 block_group, - struct ext4_group_desc *gdp);*/ - -ext3_fsblk_t descriptor_loc(struct super_block *sb, - ext3_fsblk_t logical_sb_block, unsigned int nr); -struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, - ext4_group_t block_group, struct buffer_head **bh); -int ext4_check_descriptors(struct super_block *sb); - -// -// Fastio.c -// - -FAST_IO_POSSIBLE -Ext2IsFastIoPossible( - IN PEXT2_FCB Fcb -); - -BOOLEAN -Ext2FastIoCheckIfPossible ( - IN PFILE_OBJECT FileObject, - IN PLARGE_INTEGER FileOffset, - IN ULONG Length, - IN BOOLEAN Wait, - IN ULONG LockKey, - IN BOOLEAN CheckForReadOperation, - OUT PIO_STATUS_BLOCK IoStatus, - IN PDEVICE_OBJECT DeviceObject -); - - -BOOLEAN -Ext2FastIoRead (IN PFILE_OBJECT FileObject, - IN PLARGE_INTEGER FileOffset, - IN ULONG Length, - IN BOOLEAN Wait, - IN ULONG LockKey, - OUT PVOID Buffer, - OUT PIO_STATUS_BLOCK IoStatus, - IN PDEVICE_OBJECT DeviceObject); - -BOOLEAN -Ext2FastIoWrite ( - IN PFILE_OBJECT FileObject, - IN PLARGE_INTEGER FileOffset, - IN ULONG Length, - IN BOOLEAN Wait, - IN ULONG LockKey, - OUT PVOID Buffer, - OUT PIO_STATUS_BLOCK IoStatus, - IN PDEVICE_OBJECT DeviceObject); - -BOOLEAN -Ext2FastIoQueryBasicInfo ( - IN PFILE_OBJECT FileObject, - IN BOOLEAN Wait, - OUT PFILE_BASIC_INFORMATION Buffer, - OUT PIO_STATUS_BLOCK IoStatus, - IN PDEVICE_OBJECT DeviceObject); - -BOOLEAN -Ext2FastIoQueryStandardInfo ( - IN PFILE_OBJECT FileObject, - IN BOOLEAN Wait, - OUT PFILE_STANDARD_INFORMATION Buffer, - OUT PIO_STATUS_BLOCK IoStatus, - IN PDEVICE_OBJECT DeviceObject); - -BOOLEAN -Ext2FastIoLock ( - IN PFILE_OBJECT FileObject, - IN PLARGE_INTEGER FileOffset, - IN PLARGE_INTEGER Length, - IN PEPROCESS Process, - IN ULONG Key, - IN BOOLEAN FailImmediately, - IN BOOLEAN ExclusiveLock, - OUT PIO_STATUS_BLOCK IoStatus, - IN PDEVICE_OBJECT DeviceObject -); - -BOOLEAN -Ext2FastIoUnlockSingle ( - IN PFILE_OBJECT FileObject, - IN PLARGE_INTEGER FileOffset, - IN PLARGE_INTEGER Length, - IN PEPROCESS Process, - IN ULONG Key, - OUT PIO_STATUS_BLOCK IoStatus, - IN PDEVICE_OBJECT DeviceObject -); - -BOOLEAN -Ext2FastIoUnlockAll ( - IN PFILE_OBJECT FileObject, - IN PEPROCESS Process, - OUT PIO_STATUS_BLOCK IoStatus, - IN PDEVICE_OBJECT DeviceObject -); - -BOOLEAN -Ext2FastIoUnlockAllByKey ( - IN PFILE_OBJECT FileObject, - IN PEPROCESS Process, - IN ULONG Key, - OUT PIO_STATUS_BLOCK IoStatus, - IN PDEVICE_OBJECT DeviceObject -); - - -BOOLEAN -Ext2FastIoQueryNetworkOpenInfo ( - IN PFILE_OBJECT FileObject, - IN BOOLEAN Wait, - OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, - OUT PIO_STATUS_BLOCK IoStatus, - IN PDEVICE_OBJECT DeviceObject ); - -BOOLEAN -Ext2FastIoQueryNetworkOpenInfo ( - IN PFILE_OBJECT FileObject, - IN BOOLEAN Wait, - OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, - OUT PIO_STATUS_BLOCK IoStatus, - IN PDEVICE_OBJECT DeviceObject); - -VOID -Ext2AcquireForCreateSection ( - IN PFILE_OBJECT FileObject -); - -VOID -Ext2ReleaseForCreateSection ( - IN PFILE_OBJECT FileObject -); - -NTSTATUS -Ext2AcquireFileForModWrite ( - IN PFILE_OBJECT FileObject, - IN PLARGE_INTEGER EndingOffset, - OUT PERESOURCE *ResourceToRelease, - IN PDEVICE_OBJECT DeviceObject -); - -NTSTATUS -Ext2ReleaseFileForModWrite ( - IN PFILE_OBJECT FileObject, - IN PERESOURCE ResourceToRelease, - IN PDEVICE_OBJECT DeviceObject -); - -NTSTATUS -Ext2AcquireFileForCcFlush ( - IN PFILE_OBJECT FileObject, - IN PDEVICE_OBJECT DeviceObject -); - -NTSTATUS -Ext2ReleaseFileForCcFlush ( - IN PFILE_OBJECT FileObject, - IN PDEVICE_OBJECT DeviceObject -); - - -NTSTATUS -Ext2PreAcquireForCreateSection( - IN PFS_FILTER_CALLBACK_DATA cd, - OUT PVOID *cc - ); - -// -// FileInfo.c -// - - -NTSTATUS -Ext2QueryFileInformation (IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext); - -ULONG -Ext2TotalBlocks( - PEXT2_VCB Vcb, - PLARGE_INTEGER Size, - PULONG pMeta -); - -NTSTATUS -Ext2ExpandFile( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_MCB Mcb, - PLARGE_INTEGER Size -); - -NTSTATUS -Ext2TruncateFile ( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_MCB Mcb, - PLARGE_INTEGER AllocationSize ); - -NTSTATUS -Ext2IsFileRemovable( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_FCB Fcb, - IN PEXT2_CCB Ccb -); - -NTSTATUS -Ext2SetDispositionInfo( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_FCB Fcb, - PEXT2_CCB Ccb, - BOOLEAN bDelete -); - -NTSTATUS -Ext2SetRenameInfo( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_FCB Fcb, - PEXT2_CCB Ccb -); - -NTSTATUS -Ext2SetLinkInfo( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_FCB Fcb, - PEXT2_CCB Ccb -); - -ULONG -Ext2InodeType(PEXT2_MCB Mcb); - -NTSTATUS -Ext2DeleteFile( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_FCB Fcb, - PEXT2_MCB Mcb -); - - -// -// Flush.c -// - -NTSTATUS -Ext2FlushFiles( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN BOOLEAN bShutDown -); - -NTSTATUS -Ext2FlushVolume ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN BOOLEAN bShutDown -); - -NTSTATUS -Ext2FlushFile ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_FCB Fcb, - IN PEXT2_CCB Ccb -); - -NTSTATUS -Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext); - - -// -// Fsctl.c -// - -NTSTATUS -Ext2ReadSymlink ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN PVOID Buffer, - IN ULONG Size, - OUT PULONG BytesRead - ); - -NTSTATUS -Ext2WriteSymlink ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN PVOID Buffer, - IN ULONG Size, - OUT PULONG BytesWritten -); - -NTSTATUS -Ext2TruncateSymlink( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_MCB Mcb, - ULONG Size -); - -// -// MountPoint process workitem -// - -VOID -Ext2SetVpbFlag (IN PVPB Vpb, - IN USHORT Flag ); - -VOID -Ext2ClearVpbFlag (IN PVPB Vpb, - IN USHORT Flag ); - -BOOLEAN -Ext2CheckDismount ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN BOOLEAN bForce ); - -NTSTATUS -Ext2PurgeVolume (IN PEXT2_VCB Vcb, - IN BOOLEAN FlushBeforePurge); - -NTSTATUS -Ext2PurgeFile (IN PEXT2_FCB Fcb, - IN BOOLEAN FlushBeforePurge); - -BOOLEAN -Ext2IsHandleCountZero(IN PEXT2_VCB Vcb); - -NTSTATUS -Ext2LockVcb (IN PEXT2_VCB Vcb, - IN PFILE_OBJECT FileObject); - -NTSTATUS -Ext2LockVolume (IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2UnlockVcb (IN PEXT2_VCB Vcb, - IN PFILE_OBJECT FileObject); - -NTSTATUS -Ext2UnlockVolume (IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2AllowExtendedDasdIo(IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2OplockRequest (IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2QueryExtentMappings( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_FCB Fcb, - IN PLARGE_INTEGER RequestVbn, - OUT PLARGE_INTEGER * pMappedRuns -); - -NTSTATUS -Ext2QueryRetrievalPointers(IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2GetRetrievalPointers(IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2GetRetrievalPointerBase(IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2UserFsRequest (IN PEXT2_IRP_CONTEXT IrpContext); - -BOOLEAN -Ext2IsMediaWriteProtected ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PDEVICE_OBJECT TargetDevice -); - -NTSTATUS -Ext2MountVolume (IN PEXT2_IRP_CONTEXT IrpContext); - -VOID -Ext2VerifyVcb (IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb ); -NTSTATUS -Ext2VerifyVolume (IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2IsVolumeMounted (IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2DismountVolume (IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2FileSystemControl (IN PEXT2_IRP_CONTEXT IrpContext); - -// -// HTree.c -// - -struct buffer_head *ext3_append(struct ext2_icb *icb, struct inode *inode, - ext3_lblk_t *block, int *err); - -void ext3_set_de_type(struct super_block *sb, - struct ext3_dir_entry_2 *de, - umode_t mode); - -__u32 ext3_current_time(struct inode *in); -void ext3_warning (struct super_block * sb, const char * function, - char * fmt, ...); -#define ext3_error ext3_warning -#define ext4_error ext3_error - -void ext3_update_dx_flag(struct inode *inode); -int ext3_mark_inode_dirty(struct ext2_icb *icb, struct inode *in); - -void ext3_inc_count(struct inode *inode); -void ext3_dec_count(struct inode *inode); - -struct buffer_head * - ext3_find_entry (struct ext2_icb *icb, struct dentry *dentry, - struct ext3_dir_entry_2 ** res_dir); -struct buffer_head * - ext3_dx_find_entry(struct ext2_icb *, struct dentry *dentry, - struct ext3_dir_entry_2 **res_dir, int *err); - -typedef int (*filldir_t)(void *, const char *, int, unsigned long, __u32, unsigned); -int ext3_dx_readdir(struct file *filp, filldir_t filldir, void * context); - -struct buffer_head *ext3_bread(struct ext2_icb *icb, struct inode *inode, - unsigned long block, int *err); -int add_dirent_to_buf(struct ext2_icb *icb, struct dentry *dentry, - struct inode *inode, struct ext3_dir_entry_2 *de, - struct buffer_head *bh); -struct ext3_dir_entry_2 * - do_split(struct ext2_icb *icb, struct inode *dir, - struct buffer_head **bh,struct dx_frame *frame, - struct dx_hash_info *hinfo, int *error); - -int ext3_add_entry(struct ext2_icb *icb, struct dentry *dentry, struct inode *inode); - -int ext3_delete_entry(struct ext2_icb *icb, struct inode *dir, - struct ext3_dir_entry_2 *de_del, - struct buffer_head *bh); - -int ext3_is_dir_empty(struct ext2_icb *icb, struct inode *inode); - -// -// Init.c -// - -NTSTATUS -Ext2QueryGlobalParameters(IN PUNICODE_STRING RegistryPath); -BOOLEAN -Ext2QueryRegistrySettings(IN PUNICODE_STRING RegistryPath); - -VOID -DriverUnload (IN PDRIVER_OBJECT DriverObject); - -// -// Indirect.c -// - -NTSTATUS -Ext2MapIndirect( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Index, - IN BOOLEAN bAlloc, - OUT PULONG pBlock, - OUT PULONG Number -); - -NTSTATUS -Ext2ExpandIndirect( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_MCB Mcb, - ULONG Start, - ULONG End, - PLARGE_INTEGER Size -); - -NTSTATUS -Ext2TruncateIndirect( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_MCB Mcb, - PLARGE_INTEGER Size -); - - -// -// linux.c: linux lib implemenation -// - -#if _MSC_VER > 1900 -int strncmp(const char* str1, const char* str2, size_t count); -char* strncpy(char* dest, const char* src, size_t count); -#endif - -int -ext2_init_linux(); - -void -ext2_destroy_linux(); - - -// -// Lock.c -// - -NTSTATUS -Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext); - - -// -// Memory.c -// - -VOID -Ext2FcbReaperThread( - PVOID Context -); - -VOID -Ext2McbReaperThread( - PVOID Context -); - -VOID -Ext2bhReaperThread( - PVOID Context -); - - -PEXT2_IRP_CONTEXT -Ext2AllocateIrpContext (IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp ); - -VOID -Ext2FreeIrpContext (IN PEXT2_IRP_CONTEXT IrpContext); - - -PEXT2_FCB -Ext2AllocateFcb ( - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb -); - -VOID -Ext2UnlinkFcb(IN PEXT2_FCB Fcb); - -VOID -Ext2FreeFcb (IN PEXT2_FCB Fcb); -VOID -Ext2ReleaseFcb (IN PEXT2_FCB Fcb); - -VOID -Ext2InsertFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb); - -PEXT2_CCB -Ext2AllocateCcb (ULONG Flags, PEXT2_MCB SymLink); - -VOID -Ext2FreeMcb ( - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb -); - -VOID -Ext2FreeCcb (IN PEXT2_VCB Vcb, IN PEXT2_CCB Ccb); - -PEXT2_INODE -Ext2AllocateInode (PEXT2_VCB Vcb); - -VOID -Ext2DestroyInode (IN PEXT2_VCB Vcb, IN PEXT2_INODE inode); - -struct dentry * Ext2AllocateEntry(); -VOID Ext2FreeEntry (IN struct dentry *de); -struct dentry *Ext2BuildEntry(PEXT2_VCB Vcb, PEXT2_MCB Dcb, PUNICODE_STRING FileName); - -PEXT2_EXTENT -Ext2AllocateExtent(); - -VOID -Ext2FreeExtent (IN PEXT2_EXTENT Extent); - -ULONG -Ext2CountExtents(IN PEXT2_EXTENT Chain); - -VOID -Ext2JointExtents( - IN PEXT2_EXTENT Chain, - IN PEXT2_EXTENT Extent -); - -VOID -Ext2DestroyExtentChain(IN PEXT2_EXTENT Chain); - -NTSTATUS -Ext2BuildExtents( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONGLONG Offset, - IN ULONG Size, - IN BOOLEAN bAlloc, - OUT PEXT2_EXTENT * Chain -); - -BOOLEAN -Ext2ListExtents(PLARGE_MCB Extents); - -VOID -Ext2CheckExtent( - PLARGE_MCB Zone, - LONGLONG Vbn, - LONGLONG Lbn, - LONGLONG Length, - BOOLEAN bAdded -); - -VOID -Ext2ClearAllExtents(PLARGE_MCB Zone); - -BOOLEAN -Ext2AddVcbExtent ( - IN PEXT2_VCB Vcb, - IN LONGLONG Vbn, - IN LONGLONG Length -); - -BOOLEAN -Ext2RemoveVcbExtent ( - IN PEXT2_VCB Vcb, - IN LONGLONG Vbn, - IN LONGLONG Length -); - -BOOLEAN -Ext2LookupVcbExtent ( - IN PEXT2_VCB Vcb, - IN LONGLONG Vbn, - OUT PLONGLONG Lbn, - OUT PLONGLONG Length -); - -BOOLEAN -Ext2AddMcbExtent ( - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN LONGLONG Vbn, - IN LONGLONG Lbn, - IN LONGLONG Length -); - -BOOLEAN -Ext2RemoveMcbExtent ( - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN LONGLONG Vbn, - IN LONGLONG Length -); - -BOOLEAN -Ext2LookupMcbExtent ( - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN LONGLONG Vbn, - OUT PLONGLONG Lbn, - OUT PLONGLONG Length -); - -BOOLEAN -Ext2AddMcbMetaExts ( - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Block, - IN ULONG Length -); - -BOOLEAN -Ext2RemoveMcbMetaExts ( - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Block, - IN ULONG Length -); - -BOOLEAN -Ext2AddBlockExtent( - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Start, - IN ULONG Block, - IN ULONG Number -); - -BOOLEAN -Ext2LookupBlockExtent( - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Start, - IN PULONG Block, - IN PULONG Mapped -); - -BOOLEAN -Ext2RemoveBlockExtent( - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONG Start, - IN ULONG Number -); - -NTSTATUS -Ext2InitializeZone( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb -); - -BOOLEAN -Ext2BuildName( - IN OUT PUNICODE_STRING Target, - IN PUNICODE_STRING File, - IN PUNICODE_STRING Parent -); - - -PEXT2_MCB -Ext2AllocateMcb ( - IN PEXT2_VCB Vcb, - IN PUNICODE_STRING FileName, - IN PUNICODE_STRING Parent, - IN ULONG FileAttr -); - -PEXT2_MCB -Ext2SearchMcb( - PEXT2_VCB Vcb, - PEXT2_MCB Parent, - PUNICODE_STRING FileName -); - -PEXT2_MCB -Ext2SearchMcbWithoutLock( - PEXT2_MCB Parent, - PUNICODE_STRING FileName -); - -VOID -Ext2InsertMcb( - PEXT2_VCB Vcb, - PEXT2_MCB Parent, - PEXT2_MCB Child -); - -BOOLEAN -Ext2RemoveMcb( - PEXT2_VCB Vcb, - PEXT2_MCB Mcb -); - -VOID -Ext2CleanupAllMcbs( - PEXT2_VCB Vcb -); - -BOOLEAN -Ext2CheckSetBlock( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, LONGLONG Block -); - -BOOLEAN -Ext2CheckBitmapConsistency( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb -); - -VOID -Ext2InsertVcb(PEXT2_VCB Vcb); - -VOID -Ext2RemoveVcb(PEXT2_VCB Vcb); - -NTSTATUS -Ext2InitializeLabel( - IN PEXT2_VCB Vcb, - IN PEXT2_SUPER_BLOCK Sb -); - -NTSTATUS -Ext2InitializeVcb( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb, - PEXT2_SUPER_BLOCK Ext2Sb, - PDEVICE_OBJECT TargetDevice, - PDEVICE_OBJECT VolumeDevice, - PVPB Vpb ); - -VOID -Ext2TearDownStream (IN PEXT2_VCB Vcb); - -VOID -Ext2DestroyVcb (IN PEXT2_VCB Vcb); - -NTSTATUS -Ext2CompleteIrpContext ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN NTSTATUS Status ); - -VOID -Ext2SyncUninitializeCacheMap ( - IN PFILE_OBJECT FileObject ); - -VOID -Ext2LinkTailMcb(PEXT2_VCB Vcb, PEXT2_MCB Mcb); - - -VOID -Ext2LinkHeadMcb(PEXT2_VCB Vcb, PEXT2_MCB Mcb); - -VOID -Ext2UnlinkMcb(PEXT2_VCB Vcb, PEXT2_MCB Mcb); - -PEXT2_MCB -Ext2FirstUnusedMcb( - PEXT2_VCB Vcb, - BOOLEAN Wait, - ULONG Number -); - -VOID -Ext2ReaperThread( - PVOID Context -); - -NTSTATUS -Ext2StartReaper(PEXT2_REAPER, EXT2_REAPER_RELEASE); -VOID -Ext2StopReaper(PEXT2_REAPER Reaper); - -// -// Misc.c -// - -ULONG -Ext2Log2(ULONG Value); - -LARGE_INTEGER -Ext2NtTime (IN ULONG i_time); - -ULONG -Ext2LinuxTime (IN LARGE_INTEGER SysTime); - -ULONG -Ext2OEMToUnicodeSize( - IN PEXT2_VCB Vcb, - IN PANSI_STRING Oem -); - -NTSTATUS -Ext2OEMToUnicode( - IN PEXT2_VCB Vcb, - IN OUT PUNICODE_STRING Oem, - IN POEM_STRING Unicode -); - -ULONG -Ext2UnicodeToOEMSize( - IN PEXT2_VCB Vcb, - IN PUNICODE_STRING Unicode -); - -NTSTATUS -Ext2UnicodeToOEM ( - IN PEXT2_VCB Vcb, - IN OUT POEM_STRING Oem, - IN PUNICODE_STRING Unicode -); - -VOID -Ext2Sleep(ULONG ms); - -int Ext2LinuxError (NTSTATUS Status); -NTSTATUS Ext2WinntError(int rc); - -BOOLEAN Ext2IsDot(PUNICODE_STRING name); -BOOLEAN Ext2IsDotDot(PUNICODE_STRING name); -// -// nls/nls_rtl.c -// - -int -Ext2LoadAllNls(); - -VOID -Ext2UnloadAllNls(); - -// -// Pnp.c -// - -NTSTATUS -Ext2Pnp(IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2PnpQueryRemove( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb ); - -NTSTATUS -Ext2PnpRemove( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb ); - -NTSTATUS -Ext2PnpCancelRemove( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb ); - -NTSTATUS -Ext2PnpSurpriseRemove( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb ); - - -// -// Read.c -// - -NTSTATUS -Ext2ReadInode ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONGLONG Offset, - IN PVOID Buffer, - IN ULONG Size, - IN BOOLEAN bDirectIo, - OUT PULONG dwReturn -); - -NTSTATUS -Ext2Read (IN PEXT2_IRP_CONTEXT IrpContext); - - -// -// ext3\recover.c -// - -PEXT2_MCB -Ext2LoadInternalJournal( - PEXT2_VCB Vcb, - ULONG jNo -); - -INT -Ext2CheckJournal( - PEXT2_VCB Vcb, - PULONG jNo -); - -INT -Ext2RecoverJournal( - PEXT2_IRP_CONTEXT IrpContext, - PEXT2_VCB Vcb -); - -// -// Shutdown.c -// - - -NTSTATUS -Ext2ShutDown (IN PEXT2_IRP_CONTEXT IrpContext); - - -// -// Volinfo.c -// - -NTSTATUS -Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext); - -NTSTATUS -Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext); - -// -// Write.c -// - -typedef struct _EXT2_RW_CONTEXT { - PIRP MasterIrp; - KEVENT Event; - ULONG Blocks; - ULONG Length; - PERESOURCE Resource; - ERESOURCE_THREAD ThreadId; - PFILE_OBJECT FileObject; - ULONG Flags; - BOOLEAN Wait; - -} EXT2_RW_CONTEXT, *PEXT2_RW_CONTEXT; - -#define EXT2_RW_CONTEXT_WRITE 1 - -NTSTATUS -Ext2WriteInode ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PEXT2_MCB Mcb, - IN ULONGLONG Offset, - IN PVOID Buffer, - IN ULONG Size, - IN BOOLEAN bDirectIo, - OUT PULONG dwReturn -); - - -VOID -Ext2StartFloppyFlushDpc ( - PEXT2_VCB Vcb, - PEXT2_FCB Fcb, - PFILE_OBJECT FileObject ); - -BOOLEAN -Ext2ZeroData ( - IN PEXT2_IRP_CONTEXT IrpContext, - IN PEXT2_VCB Vcb, - IN PFILE_OBJECT FileObject, - IN PLARGE_INTEGER Start, - IN PLARGE_INTEGER End ); - -NTSTATUS -Ext2Write (IN PEXT2_IRP_CONTEXT IrpContext); - -#endif /* _EXT2_HEADER_ */ +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: Ext2fs.h + * PURPOSE: Header file: ext2 structures + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +#ifndef _EXT2_HEADER_ +#define _EXT2_HEADER_ + +/* INCLUDES *************************************************************/ +#include +#include +#include +#include +#include +#include + +/* DEBUG ****************************************************************/ +#if DBG +# define EXT2_DEBUG 1 +#else +# define EXT2_DEBUG 0 +#endif + +#if EXT2_DEBUG +#if _X86_ +#define DbgBreak() __asm int 3 +#else +#define DbgBreak() KdBreakPoint() +#endif +#else +#define DbgBreak() +#endif + +/* STRUCTS & CONSTS******************************************************/ + +#define EXT2FSD_VERSION "0.70" + + +/* WDK DEFINITIONS ******************************************************/ + + +/* COMPILER SWITCH / OPTIONS ********************************************/ + +// +// Ext2Fsd build options +// + +// To support driver dynamics unload + +#define EXT2_UNLOAD FALSE + +// To support inode size expansion (fallocate) + +#define EXT2_PRE_ALLOCATION_SUPPORT TRUE + +// +// Constants +// + +#define EXT2_MAX_NESTED_LINKS (8) +#define EXT2_LINKLEN_IN_INODE (60) +#define EXT2_BLOCK_TYPES (0x04) + +#define MAXIMUM_RECORD_LENGTH (0x10000) + +#define SECTOR_BITS (Vcb->SectorBits) +#define SECTOR_SIZE (Vcb->DiskGeometry.BytesPerSector) +#define DEFAULT_SECTOR_SIZE (0x200) + +#define SUPER_BLOCK_OFFSET (0x400) +#define SUPER_BLOCK_SIZE (0x400) + +#define READ_AHEAD_GRANULARITY (0x10000) + +#define SUPER_BLOCK (Vcb->SuperBlock) + +#define INODE_SIZE (Vcb->InodeSize) +#define BLOCK_SIZE (Vcb->BlockSize) +#define BLOCK_BITS (SUPER_BLOCK->s_log_block_size + 10) +#define GROUP_DESC_SIZE (Vcb->sbi.s_desc_size) + +#define INODES_COUNT (Vcb->SuperBlock->s_inodes_count) + +#define INODES_PER_GROUP (SUPER_BLOCK->s_inodes_per_group) +#define BLOCKS_PER_GROUP (SUPER_BLOCK->s_blocks_per_group) +#define TOTAL_BLOCKS (ext3_blocks_count(SUPER_BLOCK)) + +#define EXT2_FIRST_DATA_BLOCK (SUPER_BLOCK->s_first_data_block) + +typedef struct ext3_super_block EXT2_SUPER_BLOCK, *PEXT2_SUPER_BLOCK; +typedef struct ext3_inode EXT2_INODE, *PEXT2_INODE; +typedef struct ext4_group_desc EXT2_GROUP_DESC, *PEXT2_GROUP_DESC; +typedef struct ext3_dir_entry EXT2_DIR_ENTRY, *PEXT2_DIR_ENTRY; +typedef struct ext3_dir_entry_2 EXT2_DIR_ENTRY2, *PEXT2_DIR_ENTRY2; + +#define CEILING_ALIGNED(T, A, B) (((A) + (B) - 1) & (~((T)(B) - 1))) +#define COCKLOFT_ALIGNED(T, A, B) (((A) + (B)) & (~((T)(B) - 1))) + + + +/* + * Compile-time assertion: (Lustre version) + * + * Check an invariant described by a constant expression at compile time by + * forcing a compiler error if it does not hold. \a cond must be a constant + * expression as defined by the ISO C Standard: + * + * 6.8.4.2 The switch statement + * .... + * [#3] The expression of each case label shall be an integer + * constant expression and no two of the case constant + * expressions in the same switch statement shall have the same + * value after conversion... + * + */ + +#define CL_ASSERT(cond) do {switch('x') {case (cond): case 0: break;}} while (0) + +/* File System Releated *************************************************/ + +#define DRIVER_NAME "Ext2Fsd" +#define DEVICE_NAME L"\\Ext2Fsd" +#define CDROM_NAME L"\\Ext2CdFsd" + +// Registry + +#define PARAMETERS_KEY L"\\Parameters" +#define VOLUMES_KEY L"\\Volumes" + +#define READING_ONLY L"Readonly" +#define WRITING_SUPPORT L"WritingSupport" +#define CHECKING_BITMAP L"CheckingBitmap" +#define EXT3_FORCEWRITING L"Ext3ForceWriting" +#define CODEPAGE_NAME L"CodePage" +#define HIDING_PREFIX L"HidingPrefix" +#define HIDING_SUFFIX L"HidingSuffix" +#define AUTO_MOUNT L"AutoMount" +#define MOUNT_POINT L"MountPoint" +#define UID L"uid" +#define GID L"gid" +#define EUID L"euid" +#define EGID L"egid" + +#define DOS_DEVICE_NAME L"\\DosDevices\\Ext2Fsd" + +// To support ext2fsd unload routine +#if EXT2_UNLOAD +// +// Private IOCTL to make the driver ready to unload +// +#define IOCTL_PREPARE_TO_UNLOAD \ +CTL_CODE(FILE_DEVICE_UNKNOWN, 2048, METHOD_NEITHER, FILE_WRITE_ACCESS) + +#endif // EXT2_UNLOAD + +#include "common.h" + +#ifndef _GNU_NTIFS_ +typedef IO_STACK_LOCATION EXTENDED_IO_STACK_LOCATION, *PEXTENDED_IO_STACK_LOCATION; +#endif + +#define IsFlagOn(a,b) ((BOOLEAN)(FlagOn(a,b) == b)) +#ifndef FlagOn +#define FlagOn(_F,_SF) ((_F) & (_SF)) +#endif + +#ifndef BooleanFlagOn +#define BooleanFlagOn(F,SF) ((BOOLEAN)(((F) & (SF)) != 0)) +#endif + +#ifndef SetFlag +#define SetFlag(_F,_SF) ((_F) |= (_SF)) +#endif + +#ifndef ClearFlag +#define ClearFlag(_F,_SF) ((_F) &= ~(_SF)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifdef _WIN2K_TARGET_ +#define InterlockedOr _InterlockedOr +LONG +_InterlockedAnd ( + IN OUT LONG volatile *Target, + IN LONG Set +); + +#pragma intrinsic (_InterlockedAnd) +#define InterlockedAnd _InterlockedAnd + +LONG +_InterlockedXor ( + IN OUT LONG volatile *Target, + IN LONG Set +); + +#pragma intrinsic (_InterlockedXor) +#define InterlockedXor _InterlockedXor + +#endif /* only for win2k */ + +#if EXT2_DEBUG + +#define SetLongFlag(_F,_SF) Ext2SetFlag(&(_F), (ULONG)(_SF)) +#define ClearLongFlag(_F,_SF) Ext2ClearFlag(&(_F), (ULONG)(_SF)) + +__inline +VOID +Ext2SetFlag(PULONG Flags, ULONG FlagBit) +{ + ULONG _ret = InterlockedOr(Flags, FlagBit); + ASSERT(*Flags == (_ret | FlagBit)); +} + +__inline +VOID +Ext2ClearFlag(PULONG Flags, ULONG FlagBit) +{ + ULONG _ret = InterlockedAnd(Flags, ~FlagBit); + ASSERT(*Flags == (_ret & (~FlagBit))); +} + +#else + +#define SetLongFlag(_F,_SF) InterlockedOr(&(_F), (ULONG)(_SF)) +#define ClearLongFlag(_F,_SF) InterlockedAnd(&(_F), ~((ULONG)(_SF))) + +#endif /* release */ + +#define Ext2RaiseStatus(IRPCONTEXT,STATUS) { \ + (IRPCONTEXT)->ExceptionCode = (STATUS); \ + ExRaiseStatus((STATUS)); \ +} + +#define Ext2NormalizeAndRaiseStatus(IRPCONTEXT,STATUS) { \ + (IRPCONTEXT)->ExceptionCode = STATUS; \ + if ((STATUS) == STATUS_VERIFY_REQUIRED) { ExRaiseStatus((STATUS)); } \ + ExRaiseStatus(FsRtlNormalizeNtstatus((STATUS),STATUS_UNEXPECTED_IO_ERROR)); \ +} + +// +// Define IsWritingToEof for write (append) operations +// + +#define FILE_WRITE_TO_END_OF_FILE 0xffffffff + +#define IsWritingToEof(Pos) (((Pos).LowPart == FILE_WRITE_TO_END_OF_FILE) && \ + ((Pos).HighPart == -1 )) + +#define IsDirectory(Fcb) IsMcbDirectory((Fcb)->Mcb) +#define IsSpecialFile(Fcb) IsMcbSpecialFile((Fcb)->Mcb) +#define IsSymLink(Fcb) IsMcbSymLink((Fcb)->Mcb) +#define IsInodeSymLink(I) S_ISLNK((I)->i_mode) +#define IsRoot(Fcb) IsMcbRoot((Fcb)->Mcb) + +// +// Pool Tags +// + +#define TAG_VPB ' bpV' +#define VPB_SIZE sizeof(VPB) + +#define EXT2_DATA_MAGIC 'BD2E' +#define EXT2_INAME_MAGIC 'NI2E' +#define EXT2_FNAME_MAGIC 'NF2E' +#define EXT2_VNAME_MAGIC 'NV2E' +#define EXT2_DENTRY_MAGIC 'ED2E' +#define EXT2_DIRSP_MAGIC 'SD2E' +#define EXT2_SB_MAGIC 'BS2E' +#define EXT2_GD_MAGIC 'DG2E' +#define EXT2_FLIST_MAGIC 'LF2E' +#define EXT2_PARAM_MAGIC 'PP2E' +#define EXT2_RWC_MAGIC 'WR2E' + +// +// Bug Check Codes Definitions +// + +#define EXT2_FILE_SYSTEM (FILE_SYSTEM) + +#define EXT2_BUGCHK_BLOCK (0x00010000) +#define EXT2_BUGCHK_CLEANUP (0x00020000) +#define EXT2_BUGCHK_CLOSE (0x00030000) +#define EXT2_BUGCHK_CMCB (0x00040000) +#define EXT2_BUGCHK_CREATE (0x00050000) +#define EXT2_BUGCHK_DEBUG (0x00060000) +#define EXT2_BUGCHK_DEVCTL (0x00070000) +#define EXT2_BUGCHK_DIRCTL (0x00080000) +#define EXT2_BUGCHK_DISPATCH (0x00090000) +#define EXT2_BUGCHK_EXCEPT (0x000A0000) +#define EXT2_BUGCHK_EXT2 (0x000B0000) +#define EXT2_BUGCHK_FASTIO (0x000C0000) +#define EXT2_BUGCHK_FILEINFO (0x000D0000) +#define EXT2_BUGCHK_FLUSH (0x000E0000) +#define EXT2_BUGCHK_FSCTL (0x000F0000) +#define EXT2_BUGCHK_INIT (0x00100000) +#define EXT2_BUGCHK_LOCK (0x0011000) +#define EXT2_BUGCHK_MEMORY (0x0012000) +#define EXT2_BUGCHK_MISC (0x0013000) +#define EXT2_BUGCHK_READ (0x00140000) +#define EXT2_BUGCHK_SHUTDOWN (0x00150000) +#define EXT2_BUGCHK_VOLINFO (0x00160000) +#define EXT2_BUGCHK_WRITE (0x00170000) + +#define EXT2_BUGCHK_LAST (0x00170000) + +#define Ext2BugCheck(A,B,C,D) { KeBugCheckEx(EXT2_FILE_SYSTEM, A | __LINE__, B, C, D ); } + + +/* Ext2 file system definions *******************************************/ + +// +// The second extended file system magic number +// + +#define EXT2_SUPER_MAGIC 0xEF53 + +#define EXT2_MIN_BLOCK 1024 +#define EXT2_MIN_FRAG 1024 +#define EXT2_MAX_USER_BLKSIZE 65536 +// +// Inode flags (Linux uses octad number, but why ? strange!!!) +// + +#define S_IFMT 0x0F000 /* 017 0000 */ +#define S_IFSOCK 0x0C000 /* 014 0000 */ +#define S_IFLNK 0x0A000 /* 012 0000 */ +#define S_IFREG 0x08000 /* 010 0000 */ +#define S_IFBLK 0x06000 /* 006 0000 */ +#define S_IFDIR 0x04000 /* 004 0000 */ +#define S_IFCHR 0x02000 /* 002 0000 */ +#define S_IFIFO 0x01000 /* 001 0000 */ + +#define S_ISUID 0x00800 /* 000 4000 */ +#define S_ISGID 0x00400 /* 000 2000 */ +#define S_ISVTX 0x00200 /* 000 1000 */ + +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#define S_ISFIL(m) (((m) & S_IFMT) == S_IFFIL) +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) + +#define S_IPERMISSION_MASK 0x1FF /* */ + +#define S_IRWXU 0x1C0 /* 0 0700 */ +#define S_IRWNU 0x180 /* 0 0600 */ +#define S_IRUSR 0x100 /* 0 0400 */ +#define S_IWUSR 0x080 /* 0 0200 */ +#define S_IXUSR 0x040 /* 0 0100 */ + +#define S_IRWXG 0x038 /* 0 0070 */ +#define S_IRWNG 0x030 /* 0 0060 */ +#define S_IRGRP 0x020 /* 0 0040 */ +#define S_IWGRP 0x010 /* 0 0020 */ +#define S_IXGRP 0x008 /* 0 0010 */ + +#define S_IRWXO 0x007 /* 0 0007 */ +#define S_IRWNO 0x006 /* 0 0006 */ +#define S_IROTH 0x004 /* 0 0004 */ +#define S_IWOTH 0x002 /* 0 0002 */ +#define S_IXOTH 0x001 /* 0 0001 */ + +#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO) +#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO) +#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) +#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) +#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) +#define S_IFATTR (S_IRWNU|S_IRWNG|S_IRWNO) + +#define S_ISREADABLE(m) (((m) & S_IPERMISSION_MASK) == (S_IRUSR | S_IRGRP | S_IROTH)) +#define S_ISWRITABLE(m) (((m) & S_IPERMISSION_MASK) == (S_IWUSR | S_IWGRP | S_IWOTH)) + +#define Ext2SetReadable(m) do {(m) = (m) | (S_IRUSR | S_IRGRP | S_IROTH);} while(0) +#define Ext2SetWritable(m) do {(m) = (m) | (S_IWUSR | S_IWGRP | S_IWOTH);} while(0) + +#define Ext2SetOwnerWritable(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 Ext2IsOwnerReadable(m) (((m) & S_IRUSR) == S_IRUSR) +#define Ext2IsOwnerReadOnly(m) (!(Ext2IsOwnerWritable(m)) && Ext2IsOwnerReadable(m)) + +#define Ext2IsGroupWritable(m) (((m) & S_IWGRP) == S_IWGRP) +#define Ext2IsGroupReadable(m) (((m) & S_IRGRP) == S_IRGRP) +#define Ext2IsGroupReadOnly(m) (!(Ext2IsGroupWritable(m)) && Ext2IsGroupReadable(m)) + +#define Ext2IsOtherWritable(m) (((m) & S_IWOTH) == S_IWOTH) +#define Ext2IsOtherReadable(m) (((m) & S_IROTH) == S_IROTH) +#define Ext2IsOtherReadOnly(m) (!(Ext2IsOtherWritable(m)) && Ext2IsOtherReadable(m)) + +#define Ext2SetReadOnly(m) do {(m) &= ~(S_IWUSR | S_IWGRP | S_IWOTH);} while(0) + + +#define Ext2FileCanRead (0x1) +#define Ext2FileCanWrite (0x2) +#define Ext2FileCanExecute (0x4) + + +/* + * We need 8-bytes aligned for all the sturctures + * It's a must for all ERESOURCE allocations + */ + +// +// Ext2Fsd Driver Definitions +// + +// +// EXT2_IDENTIFIER_TYPE +// +// Identifiers used to mark the structures +// + +typedef enum _EXT2_IDENTIFIER_TYPE { +#ifdef _MSC_VER + EXT2FGD = ':DGF', + EXT2VCB = ':BCV', + EXT2FCB = ':BCF', + EXT2CCB = ':BCC', + EXT2ICX = ':XCI', + EXT2FSD = ':DSF', + EXT2MCB = ':BCM' +#else + EXT2FGD = 0xE2FD0001, + EXT2VCB = 0xE2FD0002, + EXT2FCB = 0xE2FD0003, + EXT2CCB = 0xE2FD0004, + EXT2ICX = 0xE2FD0005, + EXT2FSD = 0xE2FD0006, + EXT2MCB = 0xE2FD0007 +#endif +} EXT2_IDENTIFIER_TYPE; + +// +// EXT2_IDENTIFIER +// +// Header used to mark the structures +// +typedef struct _EXT2_IDENTIFIER { + EXT2_IDENTIFIER_TYPE Type; + ULONG Size; +} EXT2_IDENTIFIER, *PEXT2_IDENTIFIER; + + +#define NodeType(Ptr) (*((EXT2_IDENTIFIER_TYPE *)(Ptr))) + +typedef struct _EXT2_MCB EXT2_MCB, *PEXT2_MCB; + + +typedef PVOID PBCB; + +// + +// +// EXT2_GLOBAL_DATA +// +// Data that is not specific to a mounted volume +// + +typedef VOID (*EXT2_REAPER_RELEASE)(PVOID); + +typedef struct _EXT2_REAPER { + PETHREAD Thread; + KEVENT Engine; + KEVENT Wait; + EXT2_REAPER_RELEASE Free; + ULONG Flags; +} EXT2_REAPER, *PEXT2_REAPER; + +#define EXT2_REAPER_FLAG_STOP (1 << 0) + +typedef struct _EXT2_GLOBAL { + + /* Identifier for this structure */ + EXT2_IDENTIFIER Identifier; + + /* Syncronization primitive for this structure */ + ERESOURCE Resource; + + /* Global flags for the driver: I put it since + FastIoDispatch isn't 8bytes aligned. */ + ULONG Flags; + + /* Table of pointers to the fast I/O entry points */ + FAST_IO_DISPATCH FastIoDispatch; + + /* Filter callbacks */ + FS_FILTER_CALLBACKS FilterCallbacks; + + /* Table of pointers to the Cache Manager callbacks */ + CACHE_MANAGER_CALLBACKS CacheManagerCallbacks; + CACHE_MANAGER_CALLBACKS CacheManagerNoOpCallbacks; + + /* Pointer to the driver object */ + PDRIVER_OBJECT DriverObject; + + /* Pointer to the disk device object */ + PDEVICE_OBJECT DiskdevObject; + + /* Pointer to the cdrom device object */ + PDEVICE_OBJECT CdromdevObject; + + /* List of mounted volumes */ + LIST_ENTRY VcbList; + + /* Cleaning thread related: resource cleaner */ + EXT2_REAPER FcbReaper; + EXT2_REAPER McbReaper; + EXT2_REAPER bhReaper; + + /* Look Aside table of IRP_CONTEXT, FCB, MCB, CCB */ + NPAGED_LOOKASIDE_LIST Ext2IrpContextLookasideList; + NPAGED_LOOKASIDE_LIST Ext2FcbLookasideList; + NPAGED_LOOKASIDE_LIST Ext2CcbLookasideList; + NPAGED_LOOKASIDE_LIST Ext2McbLookasideList; + NPAGED_LOOKASIDE_LIST Ext2ExtLookasideList; + NPAGED_LOOKASIDE_LIST Ext2DentryLookasideList; + USHORT MaxDepth; + + /* User specified global codepage name */ + struct { + WCHAR PageName[CODEPAGE_MAXLEN]; + UCHAR AnsiName[CODEPAGE_MAXLEN]; + struct nls_table * PageTable; + } Codepage; + + /* global hiding patterns */ + WCHAR wHidingPrefix[HIDINGPAT_LEN]; + WCHAR wHidingSuffix[HIDINGPAT_LEN]; + BOOLEAN bHidingPrefix; + CHAR sHidingPrefix[HIDINGPAT_LEN]; + BOOLEAN bHidingSuffix; + CHAR sHidingSuffix[HIDINGPAT_LEN]; + + /* Registery path */ + UNICODE_STRING RegistryPath; + + /* global memory and i/o statistics and memory allocations + of various sturctures */ + + EXT2_PERF_STATISTICS_V2 PerfStat; + +} EXT2_GLOBAL, *PEXT2_GLOBAL; + +// +// Flags for EXT2_GLOBAL_DATA +// + +#define EXT2_UNLOAD_PENDING 0x00000001 +#define EXT2_SUPPORT_WRITING 0x00000002 +#define EXT3_FORCE_WRITING 0x00000004 +#define EXT2_CHECKING_BITMAP 0x00000008 +#define EXT2_AUTO_MOUNT 0x00000010 + +// +// Glboal Ext2Fsd Memory Block +// + +extern PEXT2_GLOBAL Ext2Global; + +// +// memory allocation statistics +// + + +#define INC_MEM_COUNT(_i, _p, _s) do { ASSERT(_p); Ext2TraceMemory(TRUE, (int) (_i), (PVOID)(_p), (LONG)(_s)); } while(0) +#define DEC_MEM_COUNT(_i, _p, _s) do { ASSERT(_p); Ext2TraceMemory(FALSE, (int) (_i), (PVOID)(_p), (LONG)(_s)); } while(0) +#define INC_IRP_COUNT(IrpContext) Ext2TraceIrpContext(TRUE, (IrpContext)) +#define DEC_IRP_COUNT(IrpContext) Ext2TraceIrpContext(FALSE, (IrpContext)) + +// +// Driver Extension define +// + +#define IsExt2FsDevice(DO) ((DO == Ext2Global->DiskdevObject) || \ + (DO == Ext2Global->CdromdevObject) ) + +#ifdef _WIN2K_TARGET_ +#define FSRTL_ADVANCED_FCB_HEADER FSRTL_COMMON_FCB_HEADER +#endif + +typedef struct _EXT2_FCBVCB { + + // Command header for Vcb and Fcb + FSRTL_ADVANCED_FCB_HEADER Header; + +#ifndef _WIN2K_TARGET_ + FAST_MUTEX Mutex; +#endif + + // Ext2Fsd identifier + EXT2_IDENTIFIER Identifier; + + + // Locking resources + ERESOURCE MainResource; + ERESOURCE PagingIoResource; + +} EXT2_FCBVCB, *PEXT2_FCBVCB; + +// +// EXT2_VCB Volume Control Block +// +// Data that represents a mounted logical volume +// It is allocated as the device extension of the volume device object +// +typedef struct _EXT2_VCB { + + /* Common header */ + EXT2_FCBVCB; + + // Resource for metadata (inode) + ERESOURCE MetaInode; + + // Resource for metadata (block) + ERESOURCE MetaBlock; + + // Resource for Mcb (Meta data control block) + ERESOURCE McbLock; + + // List of FCBs for open files on this volume + ERESOURCE FcbLock; + LIST_ENTRY FcbList; + ULONG FcbCount; + + // Mcb list + ULONG NumOfMcb; + LIST_ENTRY McbList; + + // Entry of Mcb Tree (Root Node) + PEXT2_MCB McbTree; + + // Link list to Global + LIST_ENTRY Next; + + // Section objects + SECTION_OBJECT_POINTERS SectionObject; + + // Dirty Mcbs of modifications for volume stream + LARGE_MCB Extents; + + + // Share Access for the file object + SHARE_ACCESS ShareAccess; + + // Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLOSE + // for both files on this volume and open instances of the + // volume itself. + ULONG ReferenceCount; /* total ref count */ + ULONG OpenHandleCount; /* all handles */ + + ULONG OpenVolumeCount; /* volume handle */ + + // Disk change count + ULONG ChangeCount; + + // Pointer to the VPB in the target device object + PVPB Vpb; + PVPB Vpb2; + + // The FileObject of Volume used to lock the volume + PFILE_OBJECT LockFile; + + // List of IRPs pending on directory change notify requests + LIST_ENTRY NotifyList; + + // Pointer to syncronization primitive for this list + PNOTIFY_SYNC NotifySync; + + // This volumes device object + PDEVICE_OBJECT DeviceObject; + + // The physical device object (the disk) + PDEVICE_OBJECT TargetDeviceObject; + + // The physical device object (the disk) + PDEVICE_OBJECT RealDevice; + + // Information about the physical device object + DISK_GEOMETRY DiskGeometry; + PARTITION_INFORMATION PartitionInformation; + + BOOLEAN IsExt3fs; + PEXT2_SUPER_BLOCK SuperBlock; + + // Block / Cluster size + ULONG BlockSize; + + // Sector size in bits + ULONG SectorBits; + + // Minimal i/o size: min(PageSize, BlockSize) + ULONGLONG IoUnitSize; + + // Bits of aligned size + ULONG IoUnitBits; + + // Inode size + ULONG InodeSize; + + // Inode lookaside list + NPAGED_LOOKASIDE_LIST InodeLookasideList; + + // Flags for the volume + ULONG Flags; + + // Streaming File Object + PFILE_OBJECT Volume; + + // User specified codepage name per volume + struct { + UCHAR AnsiName[CODEPAGE_MAXLEN]; + struct nls_table * PageTable; + } Codepage; + + /* patterns to hiding files */ + BOOLEAN bHidingPrefix; + CHAR sHidingPrefix[HIDINGPAT_LEN]; + BOOLEAN bHidingSuffix; + CHAR sHidingSuffix[HIDINGPAT_LEN]; + + /* User to impersanate */ + uid_t uid; + gid_t gid; + + /* User to act as */ + uid_t euid; + gid_t egid; + + /* mountpoint: symlink to DesDevices */ + UCHAR DrvLetter; + + struct block_device bd; + struct super_block sb; + struct ext3_sb_info sbi; + + /* Maximum file size in blocks ... */ + ULONG max_blocks_per_layer[EXT2_BLOCK_TYPES]; + ULONG max_data_blocks; + loff_t max_bitmap_bytes; + loff_t max_bytes; +} EXT2_VCB, *PEXT2_VCB; + +// +// Flags for EXT2_VCB +// +#define VCB_INITIALIZED 0x00000001 +#define VCB_VOLUME_LOCKED 0x00000002 +#define VCB_MOUNTED 0x00000004 +#define VCB_DISMOUNT_PENDING 0x00000008 +#define VCB_NEW_VPB 0x00000010 +#define VCB_BEING_CLOSED 0x00000020 +#define VCB_USER_IDS 0x00000040 /* uid/gid specified by user */ +#define VCB_USER_EIDS 0x00000080 /* euid/egid specified by user */ +#define VCB_GD_LOADED 0x00000100 /* group desc loaded */ + +#define VCB_BEING_DROPPED 0x00002000 +#define VCB_FORCE_WRITING 0x00004000 +#define VCB_DEVICE_REMOVED 0x00008000 +#define VCB_JOURNAL_RECOVER 0x00080000 +#define VCB_ARRIVAL_NOTIFIED 0x00800000 +#define VCB_RO_COMPAT_READ_ONLY 0x01000000 +#define VCB_READ_ONLY 0x08000000 +#define VCB_WRITE_PROTECTED 0x10000000 +#define VCB_FLOPPY_DISK 0x20000000 +#define VCB_REMOVAL_PREVENTED 0x40000000 +#define VCB_REMOVABLE_MEDIA 0x80000000 + + +#define IsVcbInited(Vcb) (IsFlagOn((Vcb)->Flags, VCB_INITIALIZED)) +#define IsMounted(Vcb) (IsFlagOn((Vcb)->Flags, VCB_MOUNTED)) +#define IsDispending(Vcb) (IsFlagOn((Vcb)->Flags, VCB_DISMOUNT_PENDING)) +#define IsVcbReadOnly(Vcb) (IsFlagOn((Vcb)->Flags, VCB_READ_ONLY) || \ + IsFlagOn((Vcb)->Flags, VCB_RO_COMPAT_READ_ONLY) || \ + IsFlagOn((Vcb)->Flags, VCB_WRITE_PROTECTED)) + + +#define IsExt3ForceWrite() (IsFlagOn(Ext2Global->Flags, EXT3_FORCE_WRITING)) +#define IsVcbForceWrite(Vcb) (IsFlagOn((Vcb)->Flags, VCB_FORCE_WRITING)) +#define CanIWrite(Vcb) (IsExt3ForceWrite() || (!IsVcbReadOnly(Vcb) && IsVcbForceWrite(Vcb))) +#define IsLazyWriter(Fcb) ((Fcb)->LazyWriterThread == PsGetCurrentThread()) +// +// EXT2_FCB File Control Block +// +// Data that represents an open file +// There is a single instance of the FCB for every open file +// +typedef struct _EXT2_FCB { + + /* Common header */ + EXT2_FCBVCB; + + // List of FCBs for this volume + LIST_ENTRY Next; + LARGE_INTEGER TsDrop; /* drop time */ + + SECTION_OBJECT_POINTERS SectionObject; + + // Share Access for the file object + SHARE_ACCESS ShareAccess; + + // List of byte-range locks for this file + FILE_LOCK FileLockAnchor; + + // oplock information management structure + OPLOCK Oplock; + + // Lazy writer thread context + PETHREAD LazyWriterThread; + + // Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP + ULONG OpenHandleCount; + + // Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLOSE + ULONG ReferenceCount; + + // Incremented on IRP_MJ_CREATE, decremented on IRP_MJ_CLEANUP + // But only for Files with FO_NO_INTERMEDIATE_BUFFERING flag + ULONG NonCachedOpenCount; + + // Flags for the FCB + ULONG Flags; + + // Pointer to the inode + struct inode *Inode; + + // Vcb + PEXT2_VCB Vcb; + + // Mcb Node ... + PEXT2_MCB Mcb; + +} EXT2_FCB, *PEXT2_FCB; + +// +// Flags for EXT2_FCB +// + +#define FCB_FROM_POOL 0x00000001 +#define FCB_PAGE_FILE 0x00000002 +#define FCB_FILE_MODIFIED 0x00000020 + +#define FCB_ALLOC_IN_CREATE 0x00000080 +#define FCB_ALLOC_IN_WRITE 0x00000100 +#define FCB_ALLOC_IN_SETINFO 0x00000200 + +#define FCB_DELETE_PENDING 0x80000000 + +// +// Mcb Node +// + +struct _EXT2_MCB { + + // Identifier for this structure + EXT2_IDENTIFIER Identifier; + + // Flags + ULONG Flags; + + // Link List Info + PEXT2_MCB Parent; // Parent + PEXT2_MCB Next; // Siblings + + union { + PEXT2_MCB Child; // Children Mcb nodes + PEXT2_MCB Target; // Target Mcb of symlink + }; + + // Mcb Node Info + + // -> Fcb + PEXT2_FCB Fcb; + + // Short name + UNICODE_STRING ShortName; + + // Full name with path + UNICODE_STRING FullName; + + // File attribute + ULONG FileAttr; + + // reference count + ULONG Refercount; + + // Extents zone + LARGE_MCB Extents; + + // Metablocks + LARGE_MCB MetaExts; + + // Time stamps + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER LastAccessTime; + + // List Link to Vcb->McbList + LIST_ENTRY Link; + + + + struct inode Inode; + struct dentry *de; +}; + +// +// Flags for MCB +// +#define MCB_FROM_POOL 0x00000001 +#define MCB_VCB_LINK 0x00000002 +#define MCB_ENTRY_TREE 0x00000004 +#define MCB_FILE_DELETED 0x00000008 + +#define MCB_ZONE_INITED 0x20000000 +#define MCB_TYPE_SPECIAL 0x40000000 /* unresolved symlink + device node */ +#define MCB_TYPE_SYMLINK 0x80000000 + +#define IsMcbUsed(Mcb) ((Mcb)->Refercount > 0) +#define IsMcbSymLink(Mcb) IsFlagOn((Mcb)->Flags, MCB_TYPE_SYMLINK) +#define IsZoneInited(Mcb) IsFlagOn((Mcb)->Flags, MCB_ZONE_INITED) +#define IsMcbSpecialFile(Mcb) IsFlagOn((Mcb)->Flags, MCB_TYPE_SPECIAL) +#define IsMcbRoot(Mcb) ((Mcb)->Inode.i_ino == EXT2_ROOT_INO) +#define IsMcbReadonly(Mcb) IsFlagOn((Mcb)->FileAttr, FILE_ATTRIBUTE_READONLY) +#define IsMcbDirectory(Mcb) IsFlagOn((Mcb)->FileAttr, FILE_ATTRIBUTE_DIRECTORY) +#define IsFileDeleted(Mcb) IsFlagOn((Mcb)->Flags, MCB_FILE_DELETED) + +#define IsLinkInvalid(Mcb) (IsMcbSymLink(Mcb) && IsFileDeleted(Mcb->Target)) + +/* + * routines for reference count management + */ + +#define Ext2ReferXcb(_C) InterlockedIncrement(_C) +#define Ext2DerefXcb(_C) DEC_OBJ_CNT(_C) + +__inline ULONG DEC_OBJ_CNT(PULONG _C) { + if (*_C <= 0) { + DbgBreak(); + } + return InterlockedDecrement(_C); +} + +#if EXT2_DEBUG +VOID +Ext2TraceMcb(PCHAR fn, USHORT lc, USHORT add, PEXT2_MCB Mcb); +#define Ext2ReferMcb(Mcb) Ext2TraceMcb(__FUNCTION__, __LINE__, TRUE, Mcb) +#define Ext2DerefMcb(Mcb) Ext2TraceMcb(__FUNCTION__, __LINE__, FALSE, Mcb) +#else +#define Ext2ReferMcb(Mcb) Ext2ReferXcb(&Mcb->Refercount) +#define Ext2DerefMcb(Mcb) Ext2DerefXcb(&Mcb->Refercount) +#endif + +// +// EXT2_CCB Context Control Block +// +// Data that represents one instance of an open file +// There is one instance of the CCB for every instance of an open file +// +typedef struct _EXT2_CCB { + + // Identifier for this structure + EXT2_IDENTIFIER Identifier; + + // Flags + ULONG Flags; + + // Mcb of it's symbol link + PEXT2_MCB SymLink; + + // State that may need to be maintained + UNICODE_STRING DirectorySearchPattern; + + /* Open handle control block */ + struct file filp; + + /* The EA index we are on */ + ULONG EaIndex; + +} EXT2_CCB, *PEXT2_CCB; + +// +// Flags for CCB +// + +#define CCB_FROM_POOL 0x00000001 +#define CCB_VOLUME_DASD_PURGE 0x00000002 +#define CCB_LAST_WRITE_UPDATED 0x00000004 +#define CCB_OPEN_REPARSE_POINT 0x00000008 +#define CCB_DELETE_ON_CLOSE 0x00000010 + +#define CCB_ALLOW_EXTENDED_DASD_IO 0x80000000 + +// +// EXT2_IRP_CONTEXT +// +// Used to pass information about a request between the drivers functions +// +typedef struct ext2_icb { + + // Identifier for this structure + EXT2_IDENTIFIER Identifier; + + // Pointer to the IRP this request describes + PIRP Irp; + + // Flags + ULONG Flags; + + // The major and minor function code for the request + UCHAR MajorFunction; + UCHAR MinorFunction; + + // The device object + PDEVICE_OBJECT DeviceObject; + + // The real device object + PDEVICE_OBJECT RealDevice; + + // The file object + PFILE_OBJECT FileObject; + + PEXT2_FCB Fcb; + PEXT2_CCB Ccb; + + // If the request is top level + BOOLEAN IsTopLevel; + + // Used if the request needs to be queued for later processing + WORK_QUEUE_ITEM WorkQueueItem; + + // If an exception is currently in progress + BOOLEAN ExceptionInProgress; + + // The exception code when an exception is in progress + NTSTATUS ExceptionCode; + +} EXT2_IRP_CONTEXT, *PEXT2_IRP_CONTEXT; + + +#define IRP_CONTEXT_FLAG_FROM_POOL (0x00000001) +#define IRP_CONTEXT_FLAG_WAIT (0x00000002) +#define IRP_CONTEXT_FLAG_WRITE_THROUGH (0x00000004) +#define IRP_CONTEXT_FLAG_FLOPPY (0x00000008) +#define IRP_CONTEXT_FLAG_DISABLE_POPUPS (0x00000020) +#define IRP_CONTEXT_FLAG_DEFERRED (0x00000040) +#define IRP_CONTEXT_FLAG_VERIFY_READ (0x00000080) +#define IRP_CONTEXT_STACK_IO_CONTEXT (0x00000100) +#define IRP_CONTEXT_FLAG_REQUEUED (0x00000200) +#define IRP_CONTEXT_FLAG_USER_IO (0x00000400) +#define IRP_CONTEXT_FLAG_DELAY_CLOSE (0x00000800) +#define IRP_CONTEXT_FLAG_FILE_BUSY (0x00001000) + + +#define Ext2CanIWait() (!IrpContext || IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) + +// +// EXT2_ALLOC_HEADER +// +// In the checked version of the driver this header is put in the beginning of +// every memory allocation +// +typedef struct _EXT2_ALLOC_HEADER { + EXT2_IDENTIFIER Identifier; +} EXT2_ALLOC_HEADER, *PEXT2_ALLOC_HEADER; + +typedef struct _FCB_LIST_ENTRY { + PEXT2_FCB Fcb; + LIST_ENTRY Next; +} FCB_LIST_ENTRY, *PFCB_LIST_ENTRY; + + +// Block Description List +typedef struct _EXT2_EXTENT { + LONGLONG Lba; + ULONG Offset; + ULONG Length; + PIRP Irp; + struct _EXT2_EXTENT * Next; +} EXT2_EXTENT, *PEXT2_EXTENT; + + +/* FUNCTIONS DECLARATION *****************************************************/ + +// Include this so we don't need the latest WDK to build the driver. +#ifndef FSCTL_GET_RETRIEVAL_POINTER_BASE +#define FSCTL_GET_RETRIEVAL_POINTER_BASE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 141, METHOD_BUFFERED, FILE_ANY_ACCESS) // RETRIEVAL_POINTER_BASE +#endif + +#ifndef FILE_SUPPORTS_EXTENDED_ATTRIBUTES +#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000 +#endif + +// +// The following macro is used to determine if an FSD thread can block +// for I/O or wait for a resource. It returns TRUE if the thread can +// block and FALSE otherwise. This attribute can then be used to call +// the FSD & FSP common work routine with the proper wait value. +// + +#define CanExt2Wait(IRP) IoIsOperationSynchronous(Irp) + +// +// memory allocation statistics +// + +__inline +VOID +Ext2TraceMemory(BOOLEAN _n, int _i, PVOID _p, LONG _s) +{ + if (_n) { + InterlockedIncrement(&Ext2Global->PerfStat.Current.Slot[_i]); + InterlockedIncrement(&Ext2Global->PerfStat.Total.Slot[_i]); + InterlockedExchangeAdd(&Ext2Global->PerfStat.Size.Slot[_i], _s); + } else { + InterlockedDecrement(&Ext2Global->PerfStat.Current.Slot[_i]); + InterlockedExchangeAdd(&Ext2Global->PerfStat.Size.Slot[_i], -1 * _s); + } +} + +__inline +VOID +Ext2TraceIrpContext(BOOLEAN _n, PEXT2_IRP_CONTEXT IrpContext) +{ + if (_n) { + INC_MEM_COUNT(PS_IRP_CONTEXT, IrpContext, sizeof(EXT2_IRP_CONTEXT)); + InterlockedIncrement(&(Ext2Global->PerfStat.Irps[IrpContext->MajorFunction].Current)); + } else { + DEC_MEM_COUNT(PS_IRP_CONTEXT, IrpContext, sizeof(EXT2_IRP_CONTEXT)); + InterlockedIncrement(&Ext2Global->PerfStat.Irps[IrpContext->MajorFunction].Processed); + InterlockedDecrement(&Ext2Global->PerfStat.Irps[IrpContext->MajorFunction].Current); + } +} + +typedef struct _EXT2_FILLDIR_CONTEXT { + PEXT2_IRP_CONTEXT efc_irp; + PUCHAR efc_buf; + ULONG efc_size; + ULONG efc_start; + ULONG efc_prev; + NTSTATUS efc_status; + FILE_INFORMATION_CLASS efc_fi; + BOOLEAN efc_single; +} EXT2_FILLDIR_CONTEXT, *PEXT2_FILLDIR_CONTEXT; + +// +// Access.c +// + + +int Ext2CheckInodeAccess(PEXT2_VCB Vcb, struct inode *in, int attempt); +int Ext2CheckFileAccess (PEXT2_VCB Vcb, PEXT2_MCB Mcb, int attempt); + +// +// Block.c +// + +PMDL +Ext2CreateMdl ( + IN PVOID Buffer, + IN ULONG Length, + IN LOCK_OPERATION Operation +); + +VOID +Ext2DestroyMdl (IN PMDL Mdl); + +NTSTATUS +Ext2LockUserBuffer ( + IN PIRP Irp, + IN ULONG Length, + IN LOCK_OPERATION Operation); +PVOID +Ext2GetUserBuffer (IN PIRP Irp); + + +NTSTATUS +Ext2ReadWriteBlocks( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_EXTENT Extent, + IN ULONG Length + ); + +NTSTATUS +Ext2ReadSync( + IN PEXT2_VCB Vcb, + IN ULONGLONG Offset, + IN ULONG Length, + OUT PVOID Buffer, + IN BOOLEAN bVerify ); + +NTSTATUS +Ext2ReadDisk( + IN PEXT2_VCB Vcb, + IN ULONGLONG Offset, + IN ULONG Size, + IN PVOID Buffer, + IN BOOLEAN bVerify ); + +NTSTATUS +Ext2DiskIoControl ( + IN PDEVICE_OBJECT DeviceOjbect, + IN ULONG IoctlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG OutputBufferSize ); + +VOID +Ext2MediaEjectControl ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN BOOLEAN bPrevent ); + +NTSTATUS +Ext2DiskShutDown(PEXT2_VCB Vcb); + + +// +// Cleanup.c +// + +NTSTATUS +Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext); + +// +// Close.c +// + +NTSTATUS +Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext); + +VOID +Ext2QueueCloseRequest (IN PEXT2_IRP_CONTEXT IrpContext); + +VOID +Ext2DeQueueCloseRequest (IN PVOID Context); + +// +// Cmcb.c +// + +BOOLEAN +Ext2AcquireForLazyWrite ( + IN PVOID Context, + IN BOOLEAN Wait ); +VOID +Ext2ReleaseFromLazyWrite (IN PVOID Context); + +BOOLEAN +Ext2AcquireForReadAhead ( + IN PVOID Context, + IN BOOLEAN Wait ); + +VOID +Ext2ReleaseFromReadAhead (IN PVOID Context); + +BOOLEAN +Ext2NoOpAcquire ( + IN PVOID Fcb, + IN BOOLEAN Wait ); + +VOID +Ext2NoOpRelease (IN PVOID Fcb); + + +// +// Create.c +// + + +BOOLEAN +Ext2IsNameValid(PUNICODE_STRING FileName); + +NTSTATUS +Ext2FollowLink ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Parent, + IN PEXT2_MCB Mcb, + IN ULONG Linkdep +); + +NTSTATUS +Ext2ScanDir ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Parent, + IN PUNICODE_STRING FileName, + OUT PULONG Inode, + struct dentry **dentry +); + +BOOLEAN +Ext2IsSpecialSystemFile( + IN PUNICODE_STRING FileName, + IN BOOLEAN bDirectory +); + +#define EXT2_LOOKUP_FLAG_MASK (0xFF00000) +#define EXT2_LOOKUP_NOT_FOLLOW (0x8000000) + +NTSTATUS +Ext2LookupFile ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PUNICODE_STRING FullName, + IN PEXT2_MCB Parent, + OUT PEXT2_MCB * Ext2Mcb, + IN ULONG Linkdep +); + +NTSTATUS +Ext2CreateFile( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + OUT PBOOLEAN OpPostIrp +); + +NTSTATUS +Ext2CreateVolume( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb ); + +NTSTATUS +Ext2Create (IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2CreateInode( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_FCB pParentFcb, + IN ULONG Type, + IN ULONG FileAttr, + IN PUNICODE_STRING FileName); + + +NTSTATUS +Ext2SupersedeOrOverWriteFile( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PFILE_OBJECT FileObject, + IN PEXT2_VCB Vcb, + IN PEXT2_FCB Fcb, + IN PLARGE_INTEGER AllocationSize, + IN ULONG Disposition +); + +// +// Debug.c +// + +/* debug levels */ +#define DL_NVR 0 +#define DL_VIT 0x00000001 +#define DL_ERR 0x00000002 +#define DL_DBG 0x00000004 +#define DL_INF 0x00000008 +#define DL_FUN 0x00000010 +#define DL_LOW 0x00000020 +#define DL_REN 0x00000040 /* renaming operation */ +#define DL_RES 0x00000080 /* entry reference managment */ +#define DL_BLK 0x00000100 /* data block allocation / free */ +#define DL_CP 0x00000200 /* code pages (create, querydir) */ +#define DL_EXT 0x00000400 /* mcb extents */ +#define DL_MAP 0x00000800 /* retrieval points */ +#define DL_JNL 0x00001000 /* dump journal operations */ +#define DL_HTI 0x00002000 /* htree index */ +#define DL_WRN 0x00004000 /* warning */ +#define DL_BH 0x00008000 /* buffer head */ +#define DL_PNP 0x00010000 /* pnp */ +#define DL_IO 0x00020000 /* file i/o */ + +#define DL_DEFAULT (DL_ERR|DL_VIT) + +#if EXT2_DEBUG +extern ULONG DebugFilter; + +VOID +__cdecl +Ext2NiPrintf( + PCHAR DebugMessage, + ... +); + +#define DEBUG(_DL, arg) do {if ((_DL) & DebugFilter) Ext2Printf arg;} while(0) +#define DEBUGNI(_DL, arg) do {if ((_DL) & DebugFilter) Ext2NiPrintf arg;} while(0) + +#define Ext2CompleteRequest(Irp, bPrint, PriorityBoost) \ + Ext2DbgPrintComplete(Irp, bPrint); \ + IoCompleteRequest(Irp, PriorityBoost) + +#else + +#define DEBUG(_DL, arg) do {if ((_DL) & DL_ERR) DbgPrint arg;} while(0) + +#define Ext2CompleteRequest(Irp, bPrint, PriorityBoost) \ + IoCompleteRequest(Irp, PriorityBoost) + +#endif // EXT2_DEBUG + +VOID +__cdecl +Ext2Printf( + PCHAR DebugMessage, + ... +); + +extern ULONG ProcessNameOffset; + +#define Ext2GetCurrentProcessName() ( \ + (PUCHAR) PsGetCurrentProcess() + ProcessNameOffset \ +) + +ULONG +Ext2GetProcessNameOffset (VOID); + +VOID +Ext2DbgPrintCall ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp ); + +VOID +Ext2DbgPrintComplete ( + IN PIRP Irp, + IN BOOLEAN bPrint +); + +PUCHAR +Ext2NtStatusToString (IN NTSTATUS Status ); + +PVOID Ext2AllocatePool( + IN POOL_TYPE PoolType, + IN SIZE_T NumberOfBytes, + IN ULONG Tag +); + +VOID +Ext2FreePool( + IN PVOID P, + IN ULONG Tag +); + +// +// Devctl.c +// + +NTSTATUS +Ext2ProcessGlobalProperty( + IN PDEVICE_OBJECT DeviceObject, + IN PEXT2_VOLUME_PROPERTY3 Property, + IN ULONG Length +); + +NTSTATUS +Ext2ProcessVolumeProperty( + IN PEXT2_VCB Vcb, + IN PEXT2_VOLUME_PROPERTY3 Property, + IN ULONG Length +); + +NTSTATUS +Ext2ProcessUserProperty( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VOLUME_PROPERTY3 Property, + IN ULONG Length +); + +NTSTATUS +Ex2ProcessUserPerfStat( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_QUERY_PERFSTAT QueryPerf, + IN ULONG Length +); + +NTSTATUS +Ex2ProcessMountPoint( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_MOUNT_POINT MountPoint, + IN ULONG Length +); + +NTSTATUS +Ext2DeviceControlNormal (IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2PrepareToUnload (IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2DeviceControl (IN PEXT2_IRP_CONTEXT IrpContext); + +// +// Dirctl.c +// + +ULONG +Ext2GetInfoLength(IN FILE_INFORMATION_CLASS FileInformationClass); + +NTSTATUS +Ext2ProcessEntry( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_FCB Dcb, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN ULONG in, + IN PVOID Buffer, + IN ULONG UsedLength, + IN ULONG Length, + IN ULONG FileIndex, + IN PUNICODE_STRING pName, + OUT PULONG EntrySize, + IN BOOLEAN Single +); + +BOOLEAN +Ext2IsWearingCloak( + IN PEXT2_VCB Vcb, + IN POEM_STRING OeName +); + +NTSTATUS Ext2QueryDirectory (IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2NotifyChangeDirectory ( + IN PEXT2_IRP_CONTEXT IrpContext +); + +VOID +Ext2NotifyReportChange ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Filter, + IN ULONG Action +); + +NTSTATUS +Ext2DirectoryControl (IN PEXT2_IRP_CONTEXT IrpContext); + +BOOLEAN +Ext2IsDirectoryEmpty ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb +); + +// +// Dispatch.c +// + +VOID +Ext2OplockComplete ( + IN PVOID Context, + IN PIRP Irp +); + +VOID +Ext2LockIrp ( + IN PVOID Context, + IN PIRP Irp +); + +NTSTATUS +Ext2QueueRequest (IN PEXT2_IRP_CONTEXT IrpContext); + +VOID +Ext2DeQueueRequest (IN PVOID Context); + +NTSTATUS +Ext2DispatchRequest (IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2BuildRequest ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp +); + +// +// ea.c +// + +NTSTATUS +Ext2QueryEa( + IN PEXT2_IRP_CONTEXT IrpContext +); + +BOOLEAN +Ext2IsEaNameValid( + IN OEM_STRING Name +); + +NTSTATUS +Ext2SetEa( + IN PEXT2_IRP_CONTEXT IrpContext +); + + +// +// Except.c +// + +NTSTATUS +Ext2ExceptionFilter ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXCEPTION_POINTERS ExceptionPointer +); + +NTSTATUS +Ext2ExceptionHandler (IN PEXT2_IRP_CONTEXT IrpContext); + + +// +// Extents.c +// + + +NTSTATUS +Ext2MapExtent( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Index, + IN BOOLEAN Alloc, + OUT PULONG Block, + OUT PULONG Number + ); + +NTSTATUS +Ext2ExpandExtent( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb, + ULONG Start, + ULONG End, + PLARGE_INTEGER Size + ); + +NTSTATUS +Ext2TruncateExtent( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb, + PLARGE_INTEGER Size + ); + + +// +// generic.c +// + +static inline ext3_fsblk_t ext3_blocks_count(struct ext3_super_block *es) +{ + return ((ext3_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) | + le32_to_cpu(es->s_blocks_count); +} + +static inline ext3_fsblk_t ext3_r_blocks_count(struct ext3_super_block *es) +{ + return ((ext3_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) | + le32_to_cpu(es->s_r_blocks_count); +} + +static inline ext3_fsblk_t ext3_free_blocks_count(struct ext3_super_block *es) +{ + return ((ext3_fsblk_t)le32_to_cpu(es->s_free_blocks_count_hi) << 32) | + le32_to_cpu(es->s_free_blocks_count); +} + +static inline void ext3_blocks_count_set(struct ext3_super_block *es, + ext3_fsblk_t blk) +{ + es->s_blocks_count = cpu_to_le32((u32)blk); + es->s_blocks_count_hi = cpu_to_le32(blk >> 32); +} + +static inline void ext3_free_blocks_count_set(struct ext3_super_block *es, + ext3_fsblk_t blk) +{ + es->s_free_blocks_count = cpu_to_le32((u32)blk); + es->s_free_blocks_count_hi = cpu_to_le32(blk >> 32); +} + +static inline void ext3_r_blocks_count_set(struct ext3_super_block *es, + ext3_fsblk_t blk) +{ + es->s_r_blocks_count = cpu_to_le32((u32)blk); + es->s_r_blocks_count_hi = cpu_to_le32(blk >> 32); +} + +blkcnt_t ext3_inode_blocks(struct ext3_inode *raw_inode, + struct inode *inode); + +int ext3_inode_blocks_set(struct ext3_inode *raw_inode, + struct inode * inode); +ext4_fsblk_t ext4_block_bitmap(struct super_block *sb, + struct ext4_group_desc *bg); + +ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb, + struct ext4_group_desc *bg); +ext4_fsblk_t ext4_inode_table(struct super_block *sb, + struct ext4_group_desc *bg); +__u32 ext4_free_blks_count(struct super_block *sb, + struct ext4_group_desc *bg); +__u32 ext4_free_inodes_count(struct super_block *sb, + struct ext4_group_desc *bg); +__u32 ext4_used_dirs_count(struct super_block *sb, + struct ext4_group_desc *bg); +__u32 ext4_itable_unused_count(struct super_block *sb, + struct ext4_group_desc *bg); +void ext4_block_bitmap_set(struct super_block *sb, + struct ext4_group_desc *bg, ext4_fsblk_t blk); +void ext4_inode_bitmap_set(struct super_block *sb, + struct ext4_group_desc *bg, ext4_fsblk_t blk); +void ext4_inode_table_set(struct super_block *sb, + struct ext4_group_desc *bg, ext4_fsblk_t blk); +void ext4_free_blks_set(struct super_block *sb, + struct ext4_group_desc *bg, __u32 count); +void ext4_free_inodes_set(struct super_block *sb, + struct ext4_group_desc *bg, __u32 count); +void ext4_used_dirs_set(struct super_block *sb, + struct ext4_group_desc *bg, __u32 count); +void ext4_itable_unused_set(struct super_block *sb, + struct ext4_group_desc *bg, __u32 count); + +int ext3_bg_has_super(struct super_block *sb, ext3_group_t group); +unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group); +unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh, + ext4_group_t block_group, + struct ext4_group_desc *gdp); +unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, + ext4_group_t block_group, struct ext4_group_desc *gdp); +struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, + ext4_group_t block_group, struct buffer_head **bh); +ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb); +unsigned long ext4_count_free_inodes(struct super_block *sb); +int ext4_check_descriptors(struct super_block *sb); + +NTSTATUS +Ext2LoadSuper( + IN PEXT2_VCB Vcb, + IN BOOLEAN bVerify, + OUT PEXT2_SUPER_BLOCK * Sb +); + + +BOOLEAN +Ext2SaveSuper( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb +); + +BOOLEAN +Ext2RefreshSuper( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb +); + +BOOLEAN +Ext2LoadGroupBH(IN PEXT2_VCB Vcb); + +BOOLEAN +Ext2LoadGroup(IN PEXT2_VCB Vcb); + +VOID +Ext2DropGroupBH(IN PEXT2_VCB Vcb); + +VOID +Ext2PutGroup(IN PEXT2_VCB Vcb); + +VOID +Ext2DropBH(IN PEXT2_VCB Vcb); + +NTSTATUS +Ext2FlushVcb(IN PEXT2_VCB Vcb); + +BOOLEAN +Ext2SaveGroup( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN ULONG Group +); + +BOOLEAN +Ext2RefreshGroup( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb +); + +BOOLEAN +Ext2GetInodeLba ( + IN PEXT2_VCB Vcb, + IN ULONG inode, + OUT PLONGLONG offset +); + +BOOLEAN +Ext2LoadInode ( + IN PEXT2_VCB Vcb, + IN struct inode *Inode +); + +BOOLEAN +Ext2ClearInode ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN ULONG inode +); + +BOOLEAN +Ext2SaveInode ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN struct inode *Inode +); + +BOOLEAN +Ext2LoadInodeXattr(IN PEXT2_VCB Vcb, + IN struct inode *Inode, + IN PEXT2_INODE InodeXattr); + +BOOLEAN +Ext2SaveInodeXattr(IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN struct inode *Inode, + IN PEXT2_INODE InodeXattr); + +BOOLEAN +Ext2LoadBlock ( + IN PEXT2_VCB Vcb, + IN ULONG dwBlk, + IN PVOID Buffer +); + +BOOLEAN +Ext2SaveBlock ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN ULONG dwBlk, + IN PVOID Buf +); + +BOOLEAN +Ext2LoadBuffer( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN LONGLONG Offset, + IN ULONG Size, + IN PVOID Buf +); + +BOOLEAN +Ext2ZeroBuffer( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN LONGLONG Offset, + IN ULONG Size +); + +BOOLEAN +Ext2SaveBuffer( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN LONGLONG Offset, + IN ULONG Size, + IN PVOID Buf +); + +NTSTATUS +Ext2GetBlock( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Base, + IN ULONG Layer, + IN ULONG Start, + IN ULONG SizeArray, + IN PULONG BlockArray, + IN BOOLEAN bAlloc, + IN OUT PULONG Hint, + OUT PULONG Block, + OUT PULONG Number +); + +NTSTATUS +Ext2BlockMap( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Index, + IN BOOLEAN bAlloc, + OUT PULONG pBlock, + OUT PULONG Number +); + +VOID +Ext2UpdateVcbStat( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb +); + +NTSTATUS +Ext2NewBlock( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN ULONG GroupHint, + IN ULONG BlockHint, + OUT PULONG Block, + IN OUT PULONG Number +); + +NTSTATUS +Ext2FreeBlock( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN ULONG Block, + IN ULONG Number +); + + +NTSTATUS +Ext2NewInode( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN ULONG GroupHint, + IN ULONG Type, + OUT PULONG Inode +); + +NTSTATUS +Ext2UpdateGroupDirStat( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN ULONG Group +); + +NTSTATUS +Ext2FreeInode( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN ULONG Inode, + IN ULONG Type +); + +NTSTATUS +Ext2AddEntry ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_FCB Dcb, + IN struct inode *Inode, + IN PUNICODE_STRING FileName, + OUT struct dentry **dentry +); + +NTSTATUS +Ext2SetFileType ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_FCB Dcb, + IN PEXT2_MCB Mcb, + IN umode_t mode +); + +NTSTATUS +Ext2RemoveEntry ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_FCB Dcb, + IN PEXT2_MCB Mcb +); + +NTSTATUS +Ext2SetParentEntry ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_FCB Dcb, + IN ULONG OldParent, + IN ULONG NewParent ); + + +NTSTATUS +Ext2TruncateBlock( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Base, + IN ULONG Start, + IN ULONG Layer, + IN ULONG SizeArray, + IN PULONG BlockArray, + IN PULONG Extra +); + +struct ext3_dir_entry_2 *ext3_next_entry(struct ext3_dir_entry_2 *p); + +int ext3_check_dir_entry (const char * function, struct inode * dir, + struct ext3_dir_entry_2 * de, + struct buffer_head * bh, + unsigned long offset); + +loff_t ext3_max_size(int blkbits, int has_huge_files); +loff_t ext3_max_bitmap_size(int bits, int has_huge_files); + +ext3_fsblk_t descriptor_loc(struct super_block *sb, + ext3_fsblk_t logical_sb_block, unsigned int nr); +struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb, + ext4_group_t block_group, struct buffer_head **bh); +int ext4_check_descriptors(struct super_block *sb); + +// +// Fastio.c +// + +FAST_IO_POSSIBLE +Ext2IsFastIoPossible( + IN PEXT2_FCB Fcb +); + +BOOLEAN +Ext2FastIoCheckIfPossible ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + IN BOOLEAN CheckForReadOperation, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject +); + + +BOOLEAN +Ext2FastIoRead (IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +BOOLEAN +Ext2FastIoWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +BOOLEAN +Ext2FastIoQueryBasicInfo ( + IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + OUT PFILE_BASIC_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +BOOLEAN +Ext2FastIoQueryStandardInfo ( + IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + OUT PFILE_STANDARD_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +BOOLEAN +Ext2FastIoLock ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS Process, + IN ULONG Key, + IN BOOLEAN FailImmediately, + IN BOOLEAN ExclusiveLock, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject +); + +BOOLEAN +Ext2FastIoUnlockSingle ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS Process, + IN ULONG Key, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject +); + +BOOLEAN +Ext2FastIoUnlockAll ( + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject +); + +BOOLEAN +Ext2FastIoUnlockAllByKey ( + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process, + IN ULONG Key, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject +); + + +BOOLEAN +Ext2FastIoQueryNetworkOpenInfo ( + IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject ); + +BOOLEAN +Ext2FastIoQueryNetworkOpenInfo ( + IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject); + +VOID +Ext2AcquireForCreateSection ( + IN PFILE_OBJECT FileObject +); + +VOID +Ext2ReleaseForCreateSection ( + IN PFILE_OBJECT FileObject +); + +NTSTATUS +Ext2AcquireFileForModWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER EndingOffset, + OUT PERESOURCE *ResourceToRelease, + IN PDEVICE_OBJECT DeviceObject +); + +NTSTATUS +Ext2ReleaseFileForModWrite ( + IN PFILE_OBJECT FileObject, + IN PERESOURCE ResourceToRelease, + IN PDEVICE_OBJECT DeviceObject +); + +NTSTATUS +Ext2AcquireFileForCcFlush ( + IN PFILE_OBJECT FileObject, + IN PDEVICE_OBJECT DeviceObject +); + +NTSTATUS +Ext2ReleaseFileForCcFlush ( + IN PFILE_OBJECT FileObject, + IN PDEVICE_OBJECT DeviceObject +); + + +NTSTATUS +Ext2PreAcquireForCreateSection( + IN PFS_FILTER_CALLBACK_DATA cd, + OUT PVOID *cc + ); + +// +// FileInfo.c +// + + +NTSTATUS +Ext2QueryFileInformation (IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2SetFileInformation (IN PEXT2_IRP_CONTEXT IrpContext); + +ULONG +Ext2TotalBlocks( + PEXT2_VCB Vcb, + PLARGE_INTEGER Size, + PULONG pMeta +); + +NTSTATUS +Ext2ExpandFile( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb, + PLARGE_INTEGER Size +); + +NTSTATUS +Ext2TruncateFile ( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb, + PLARGE_INTEGER AllocationSize ); + +NTSTATUS +Ext2IsFileRemovable( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_FCB Fcb, + IN PEXT2_CCB Ccb +); + +NTSTATUS +Ext2SetDispositionInfo( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_FCB Fcb, + PEXT2_CCB Ccb, + BOOLEAN bDelete +); + +NTSTATUS +Ext2SetRenameInfo( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_FCB Fcb, + PEXT2_CCB Ccb +); + +NTSTATUS +Ext2SetLinkInfo( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_FCB Fcb, + PEXT2_CCB Ccb +); + +ULONG +Ext2InodeType(PEXT2_MCB Mcb); + +NTSTATUS +Ext2DeleteFile( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_FCB Fcb, + PEXT2_MCB Mcb +); + + +// +// Flush.c +// + +NTSTATUS +Ext2FlushFiles( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN BOOLEAN bShutDown +); + +NTSTATUS +Ext2FlushVolume ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN BOOLEAN bShutDown +); + +NTSTATUS +Ext2FlushFile ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_FCB Fcb, + IN PEXT2_CCB Ccb +); + +NTSTATUS +Ext2Flush (IN PEXT2_IRP_CONTEXT IrpContext); + + +// +// Fsctl.c +// + +NTSTATUS +Ext2ReadSymlink ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN PVOID Buffer, + IN ULONG Size, + OUT PULONG BytesRead + ); + +NTSTATUS +Ext2WriteSymlink ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN PVOID Buffer, + IN ULONG Size, + OUT PULONG BytesWritten +); + +NTSTATUS +Ext2TruncateSymlink( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb, + ULONG Size +); + +// +// MountPoint process workitem +// + +VOID +Ext2SetVpbFlag (IN PVPB Vpb, + IN USHORT Flag ); + +VOID +Ext2ClearVpbFlag (IN PVPB Vpb, + IN USHORT Flag ); + +BOOLEAN +Ext2CheckDismount ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN BOOLEAN bForce ); + +NTSTATUS +Ext2PurgeVolume (IN PEXT2_VCB Vcb, + IN BOOLEAN FlushBeforePurge); + +NTSTATUS +Ext2PurgeFile (IN PEXT2_FCB Fcb, + IN BOOLEAN FlushBeforePurge); + +BOOLEAN +Ext2IsHandleCountZero(IN PEXT2_VCB Vcb); + +NTSTATUS +Ext2LockVcb (IN PEXT2_VCB Vcb, + IN PFILE_OBJECT FileObject); + +NTSTATUS +Ext2LockVolume (IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2UnlockVcb (IN PEXT2_VCB Vcb, + IN PFILE_OBJECT FileObject); + +NTSTATUS +Ext2UnlockVolume (IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2AllowExtendedDasdIo(IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2OplockRequest (IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2QueryExtentMappings( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_FCB Fcb, + IN PLARGE_INTEGER RequestVbn, + OUT PLARGE_INTEGER * pMappedRuns +); + +NTSTATUS +Ext2QueryRetrievalPointers(IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2GetRetrievalPointers(IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2GetRetrievalPointerBase(IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2UserFsRequest (IN PEXT2_IRP_CONTEXT IrpContext); + +BOOLEAN +Ext2IsMediaWriteProtected ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PDEVICE_OBJECT TargetDevice +); + +NTSTATUS +Ext2MountVolume (IN PEXT2_IRP_CONTEXT IrpContext); + +VOID +Ext2VerifyVcb (IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb ); +NTSTATUS +Ext2VerifyVolume (IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2IsVolumeMounted (IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2DismountVolume (IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2FileSystemControl (IN PEXT2_IRP_CONTEXT IrpContext); + +// +// HTree.c +// + +struct buffer_head *ext3_append(struct ext2_icb *icb, struct inode *inode, + ext3_lblk_t *block, int *err); + +void ext3_set_de_type(struct super_block *sb, + struct ext3_dir_entry_2 *de, + umode_t mode); + +__u32 ext3_current_time(struct inode *in); +void ext3_warning (struct super_block * sb, const char * function, + char * fmt, ...); +#define ext3_error ext3_warning +#define ext4_error ext3_error + +void ext3_update_dx_flag(struct inode *inode); +int ext3_mark_inode_dirty(struct ext2_icb *icb, struct inode *in); + +void ext3_inc_count(struct inode *inode); +void ext3_dec_count(struct inode *inode); + +struct buffer_head * + ext3_find_entry (struct ext2_icb *icb, struct dentry *dentry, + struct ext3_dir_entry_2 ** res_dir); +struct buffer_head * + ext3_dx_find_entry(struct ext2_icb *, struct dentry *dentry, + struct ext3_dir_entry_2 **res_dir, int *err); + +typedef int (*filldir_t)(void *, const char *, int, unsigned long, __u32, unsigned); +int ext3_dx_readdir(struct file *filp, filldir_t filldir, void * context); + +struct buffer_head *ext3_bread(struct ext2_icb *icb, struct inode *inode, + unsigned long block, int *err); +int add_dirent_to_buf(struct ext2_icb *icb, struct dentry *dentry, + struct inode *inode, struct ext3_dir_entry_2 *de, + struct buffer_head *bh); +struct ext3_dir_entry_2 * + do_split(struct ext2_icb *icb, struct inode *dir, + struct buffer_head **bh,struct dx_frame *frame, + struct dx_hash_info *hinfo, int *error); + +int ext3_add_entry(struct ext2_icb *icb, struct dentry *dentry, struct inode *inode); + +int ext3_delete_entry(struct ext2_icb *icb, struct inode *dir, + struct ext3_dir_entry_2 *de_del, + struct buffer_head *bh); + +int ext3_is_dir_empty(struct ext2_icb *icb, struct inode *inode); + +// +// Init.c +// + +NTSTATUS +Ext2QueryGlobalParameters(IN PUNICODE_STRING RegistryPath); +BOOLEAN +Ext2QueryRegistrySettings(IN PUNICODE_STRING RegistryPath); + +VOID +DriverUnload (IN PDRIVER_OBJECT DriverObject); + +// +// Indirect.c +// + +NTSTATUS +Ext2MapIndirect( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Index, + IN BOOLEAN bAlloc, + OUT PULONG pBlock, + OUT PULONG Number +); + +NTSTATUS +Ext2ExpandIndirect( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb, + ULONG Start, + ULONG End, + PLARGE_INTEGER Size +); + +NTSTATUS +Ext2TruncateIndirect( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_MCB Mcb, + PLARGE_INTEGER Size +); + + +// +// linux.c: linux lib implemenation +// + +#if _MSC_VER > 1900 +int strncmp(const char* str1, const char* str2, size_t count); +char* strncpy(char* dest, const char* src, size_t count); +#endif + +int +ext2_init_linux(); + +void +ext2_destroy_linux(); + + +// +// Lock.c +// + +NTSTATUS +Ext2LockControl (IN PEXT2_IRP_CONTEXT IrpContext); + + +// +// Memory.c +// + +VOID +Ext2FcbReaperThread( + PVOID Context +); + +VOID +Ext2McbReaperThread( + PVOID Context +); + +VOID +Ext2bhReaperThread( + PVOID Context +); + + +PEXT2_IRP_CONTEXT +Ext2AllocateIrpContext (IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp ); + +VOID +Ext2FreeIrpContext (IN PEXT2_IRP_CONTEXT IrpContext); + + +PEXT2_FCB +Ext2AllocateFcb ( + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb +); + +VOID +Ext2UnlinkFcb(IN PEXT2_FCB Fcb); + +VOID +Ext2FreeFcb (IN PEXT2_FCB Fcb); +VOID +Ext2ReleaseFcb (IN PEXT2_FCB Fcb); + +VOID +Ext2InsertFcb(PEXT2_VCB Vcb, PEXT2_FCB Fcb); + +PEXT2_CCB +Ext2AllocateCcb (ULONG Flags, PEXT2_MCB SymLink); + +VOID +Ext2FreeMcb ( + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb +); + +VOID +Ext2FreeCcb (IN PEXT2_VCB Vcb, IN PEXT2_CCB Ccb); + +PEXT2_INODE +Ext2AllocateInode (PEXT2_VCB Vcb); + +VOID +Ext2DestroyInode (IN PEXT2_VCB Vcb, IN PEXT2_INODE inode); + +struct dentry * Ext2AllocateEntry(); +VOID Ext2FreeEntry (IN struct dentry *de); +struct dentry *Ext2BuildEntry(PEXT2_VCB Vcb, PEXT2_MCB Dcb, PUNICODE_STRING FileName); + +PEXT2_EXTENT +Ext2AllocateExtent(); + +VOID +Ext2FreeExtent (IN PEXT2_EXTENT Extent); + +ULONG +Ext2CountExtents(IN PEXT2_EXTENT Chain); + +VOID +Ext2JointExtents( + IN PEXT2_EXTENT Chain, + IN PEXT2_EXTENT Extent +); + +VOID +Ext2DestroyExtentChain(IN PEXT2_EXTENT Chain); + +NTSTATUS +Ext2BuildExtents( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONGLONG Offset, + IN ULONG Size, + IN BOOLEAN bAlloc, + OUT PEXT2_EXTENT * Chain +); + +BOOLEAN +Ext2ListExtents(PLARGE_MCB Extents); + +VOID +Ext2CheckExtent( + PLARGE_MCB Zone, + LONGLONG Vbn, + LONGLONG Lbn, + LONGLONG Length, + BOOLEAN bAdded +); + +VOID +Ext2ClearAllExtents(PLARGE_MCB Zone); + +BOOLEAN +Ext2AddVcbExtent ( + IN PEXT2_VCB Vcb, + IN LONGLONG Vbn, + IN LONGLONG Length +); + +BOOLEAN +Ext2RemoveVcbExtent ( + IN PEXT2_VCB Vcb, + IN LONGLONG Vbn, + IN LONGLONG Length +); + +BOOLEAN +Ext2LookupVcbExtent ( + IN PEXT2_VCB Vcb, + IN LONGLONG Vbn, + OUT PLONGLONG Lbn, + OUT PLONGLONG Length +); + +BOOLEAN +Ext2AddMcbExtent ( + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG Lbn, + IN LONGLONG Length +); + +BOOLEAN +Ext2RemoveMcbExtent ( + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG Length +); + +BOOLEAN +Ext2LookupMcbExtent ( + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN LONGLONG Vbn, + OUT PLONGLONG Lbn, + OUT PLONGLONG Length +); + +BOOLEAN +Ext2AddMcbMetaExts ( + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Block, + IN ULONG Length +); + +BOOLEAN +Ext2RemoveMcbMetaExts ( + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Block, + IN ULONG Length +); + +BOOLEAN +Ext2AddBlockExtent( + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Start, + IN ULONG Block, + IN ULONG Number +); + +BOOLEAN +Ext2LookupBlockExtent( + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Start, + IN PULONG Block, + IN PULONG Mapped +); + +BOOLEAN +Ext2RemoveBlockExtent( + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONG Start, + IN ULONG Number +); + +NTSTATUS +Ext2InitializeZone( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb +); + +BOOLEAN +Ext2BuildName( + IN OUT PUNICODE_STRING Target, + IN PUNICODE_STRING File, + IN PUNICODE_STRING Parent +); + + +PEXT2_MCB +Ext2AllocateMcb ( + IN PEXT2_VCB Vcb, + IN PUNICODE_STRING FileName, + IN PUNICODE_STRING Parent, + IN ULONG FileAttr +); + +PEXT2_MCB +Ext2SearchMcb( + PEXT2_VCB Vcb, + PEXT2_MCB Parent, + PUNICODE_STRING FileName +); + +PEXT2_MCB +Ext2SearchMcbWithoutLock( + PEXT2_MCB Parent, + PUNICODE_STRING FileName +); + +VOID +Ext2InsertMcb( + PEXT2_VCB Vcb, + PEXT2_MCB Parent, + PEXT2_MCB Child +); + +BOOLEAN +Ext2RemoveMcb( + PEXT2_VCB Vcb, + PEXT2_MCB Mcb +); + +VOID +Ext2CleanupAllMcbs( + PEXT2_VCB Vcb +); + +BOOLEAN +Ext2CheckSetBlock( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, LONGLONG Block +); + +BOOLEAN +Ext2CheckBitmapConsistency( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb +); + +VOID +Ext2InsertVcb(PEXT2_VCB Vcb); + +VOID +Ext2RemoveVcb(PEXT2_VCB Vcb); + +NTSTATUS +Ext2InitializeLabel( + IN PEXT2_VCB Vcb, + IN PEXT2_SUPER_BLOCK Sb +); + +NTSTATUS +Ext2InitializeVcb( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb, + PEXT2_SUPER_BLOCK Ext2Sb, + PDEVICE_OBJECT TargetDevice, + PDEVICE_OBJECT VolumeDevice, + PVPB Vpb ); + +VOID +Ext2TearDownStream (IN PEXT2_VCB Vcb); + +VOID +Ext2DestroyVcb (IN PEXT2_VCB Vcb); + +NTSTATUS +Ext2CompleteIrpContext ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN NTSTATUS Status ); + +VOID +Ext2SyncUninitializeCacheMap ( + IN PFILE_OBJECT FileObject ); + +VOID +Ext2LinkTailMcb(PEXT2_VCB Vcb, PEXT2_MCB Mcb); + + +VOID +Ext2LinkHeadMcb(PEXT2_VCB Vcb, PEXT2_MCB Mcb); + +VOID +Ext2UnlinkMcb(PEXT2_VCB Vcb, PEXT2_MCB Mcb); + +PEXT2_MCB +Ext2FirstUnusedMcb( + PEXT2_VCB Vcb, + BOOLEAN Wait, + ULONG Number +); + +VOID +Ext2ReaperThread( + PVOID Context +); + +NTSTATUS +Ext2StartReaper(PEXT2_REAPER, EXT2_REAPER_RELEASE); +VOID +Ext2StopReaper(PEXT2_REAPER Reaper); + +// +// Misc.c +// + +ULONG +Ext2Log2(ULONG Value); + +LARGE_INTEGER +Ext2NtTime (IN ULONG i_time); + +ULONG +Ext2LinuxTime (IN LARGE_INTEGER SysTime); + +ULONG +Ext2OEMToUnicodeSize( + IN PEXT2_VCB Vcb, + IN PANSI_STRING Oem +); + +NTSTATUS +Ext2OEMToUnicode( + IN PEXT2_VCB Vcb, + IN OUT PUNICODE_STRING Oem, + IN POEM_STRING Unicode +); + +ULONG +Ext2UnicodeToOEMSize( + IN PEXT2_VCB Vcb, + IN PUNICODE_STRING Unicode +); + +NTSTATUS +Ext2UnicodeToOEM ( + IN PEXT2_VCB Vcb, + IN OUT POEM_STRING Oem, + IN PUNICODE_STRING Unicode +); + +VOID +Ext2Sleep(ULONG ms); + +int Ext2LinuxError (NTSTATUS Status); +NTSTATUS Ext2WinntError(int rc); + +BOOLEAN Ext2IsDot(PUNICODE_STRING name); +BOOLEAN Ext2IsDotDot(PUNICODE_STRING name); +// +// nls/nls_rtl.c +// + +int +Ext2LoadAllNls(); + +VOID +Ext2UnloadAllNls(); + +// +// Pnp.c +// + +NTSTATUS +Ext2Pnp(IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2PnpQueryRemove( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb ); + +NTSTATUS +Ext2PnpRemove( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb ); + +NTSTATUS +Ext2PnpCancelRemove( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb ); + +NTSTATUS +Ext2PnpSurpriseRemove( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb ); + + +// +// Read.c +// + +NTSTATUS +Ext2ReadInode ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONGLONG Offset, + IN PVOID Buffer, + IN ULONG Size, + IN BOOLEAN bDirectIo, + OUT PULONG dwReturn +); + +NTSTATUS +Ext2Read (IN PEXT2_IRP_CONTEXT IrpContext); + + +// +// ext3\recover.c +// + +PEXT2_MCB +Ext2LoadInternalJournal( + PEXT2_VCB Vcb, + ULONG jNo +); + +INT +Ext2CheckJournal( + PEXT2_VCB Vcb, + PULONG jNo +); + +INT +Ext2RecoverJournal( + PEXT2_IRP_CONTEXT IrpContext, + PEXT2_VCB Vcb +); + +// +// Shutdown.c +// + + +NTSTATUS +Ext2ShutDown (IN PEXT2_IRP_CONTEXT IrpContext); + + +// +// Volinfo.c +// + +NTSTATUS +Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext); + +NTSTATUS +Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext); + +// +// Write.c +// + +typedef struct _EXT2_RW_CONTEXT { + PIRP MasterIrp; + KEVENT Event; + ULONG Blocks; + ULONG Length; + PERESOURCE Resource; + ERESOURCE_THREAD ThreadId; + PFILE_OBJECT FileObject; + ULONG Flags; + BOOLEAN Wait; + +} EXT2_RW_CONTEXT, *PEXT2_RW_CONTEXT; + +#define EXT2_RW_CONTEXT_WRITE 1 + +NTSTATUS +Ext2WriteInode ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PEXT2_MCB Mcb, + IN ULONGLONG Offset, + IN PVOID Buffer, + IN ULONG Size, + IN BOOLEAN bDirectIo, + OUT PULONG dwReturn +); + + +VOID +Ext2StartFloppyFlushDpc ( + PEXT2_VCB Vcb, + PEXT2_FCB Fcb, + PFILE_OBJECT FileObject ); + +BOOLEAN +Ext2ZeroData ( + IN PEXT2_IRP_CONTEXT IrpContext, + IN PEXT2_VCB Vcb, + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER Start, + IN PLARGE_INTEGER End ); + +NTSTATUS +Ext2Write (IN PEXT2_IRP_CONTEXT IrpContext); + +#endif /* _EXT2_HEADER_ */ diff --git a/Ext4Fsd/include/linux/jbd.h b/Ext4Fsd/include/linux/jbd.h index 15c0a4d..1ecbdd3 100644 --- a/Ext4Fsd/include/linux/jbd.h +++ b/Ext4Fsd/include/linux/jbd.h @@ -1,1138 +1,1139 @@ -/* - * linux/include/linux/jbd.h - * - * Written by Stephen C. Tweedie - * - * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved - * - * This file is part of the Linux kernel and is made available under - * the terms of the GNU General Public License, version 2, or at your - * option, any later version, incorporated herein by reference. - * - * Definitions for transaction data structures for the buffer cache - * filesystem journaling support. - */ - -#ifndef _LINUX_JBD_H -#define _LINUX_JBD_H - -/* Allow this file to be included directly into e2fsprogs */ -#ifndef __KERNEL__ -#include "jfs_compat.h" -#define JFS_DEBUG -#define jfs_debug jbd_debug -#else - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define journal_oom_retry 1 - -#define jbdlock_t FAST_MUTEX - -static inline void jbd_lock_init(jbdlock_t *lock) -{ - ExInitializeFastMutex(lock); -} - -static inline void jbd_lock(jbdlock_t *lock) -{ - ExAcquireFastMutex(lock); -} - -static inline void jbd_unlock(jbdlock_t *lock) -{ - ExReleaseFastMutex(lock); -} - -static inline int assert_jbd_locked(jbdlock_t *lock) -{ - int rc = 1; - - if (ExTryToAcquireFastMutex(lock)) { - ExReleaseFastMutex(lock); - rc = 0; - } - - return rc; -} - - -/* - * Define JBD_PARANIOD_IOFAIL to cause a kernel BUG() if ext3 finds - * certain classes of error which can occur due to failed IOs. Under - * normal use we want ext3 to continue after such errors, because - * hardware _can_ fail, but for debugging purposes when running tests on - * known-good hardware we may want to trap these errors. - */ -#undef JBD_PARANOID_IOFAIL - -/* - * The default maximum commit age, in seconds. - */ -#define JBD_DEFAULT_MAX_COMMIT_AGE 5 - -#ifdef CONFIG_JBD_DEBUG -/* - * Define JBD_EXPENSIVE_CHECKING to enable more expensive internal - * consistency checks. By default we don't do this unless - * CONFIG_JBD_DEBUG is on. - */ -#define JBD_EXPENSIVE_CHECKING -extern u8 journal_enable_debug; - -#define jbd_debug(n, f, a...) \ - do { \ - if ((n) <= journal_enable_debug) { \ - printk (KERN_DEBUG "(%s, %d): %s: ", \ - __FILE__, __LINE__, __FUNCTION__); \ - printk (f, ## a); \ - } \ - } while (0) -#else -#define jbd_debug -#endif - -static inline void *jbd_alloc(size_t size, gfp_t flags) -{ - return kmalloc(size, flags); - /*__get_free_pages(flags, get_order(size));*/ -} - -static inline void jbd_free(void *ptr, size_t size) -{ - if (ptr) { - kfree(ptr); - } - /* free_pages((unsigned long)ptr, get_order(size)); */ -}; - -#define JFS_MIN_JOURNAL_BLOCKS 1024 - - -/** - * typedef handle_t - The handle_t type represents a single atomic update being performed by some process. - * - * All filesystem modifications made by the process go - * through this handle. Recursive operations (such as quota operations) - * are gathered into a single update. - * - * The buffer credits field is used to account for journaled buffers - * being modified by the running process. To ensure that there is - * enough log space for all outstanding operations, we need to limit the - * number of outstanding buffers possible at any time. When the - * operation completes, any buffer credits not used are credited back to - * the transaction, so that at all times we know how many buffers the - * outstanding updates on a transaction might possibly touch. - * - * This is an opaque datatype. - **/ -typedef struct handle_s handle_t; /* Atomic operation type */ - - -/** - * typedef journal_t - The journal_t maintains all of the journaling state information for a single filesystem. - * - * journal_t is linked to from the fs superblock structure. - * - * We use the journal_t to keep track of all outstanding transaction - * activity on the filesystem, and to manage the state of the log - * writing process. - * - * This is an opaque datatype. - **/ -typedef struct journal_s journal_t; /* Journal control structure */ -#endif - -/* - * Internal structures used by the logging mechanism: - */ - -#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */ - -/* - * On-disk structures - */ - -/* - * Descriptor block types: - */ - -#define JFS_DESCRIPTOR_BLOCK 1 -#define JFS_COMMIT_BLOCK 2 -#define JFS_SUPERBLOCK_V1 3 -#define JFS_SUPERBLOCK_V2 4 -#define JFS_REVOKE_BLOCK 5 - -/* - * Standard header for all descriptor blocks: - */ -typedef struct journal_header_s -{ - __be32 h_magic; - __be32 h_blocktype; - __be32 h_sequence; -} journal_header_t; - - -/* - * The block tag: used to describe a single buffer in the journal - */ -typedef struct journal_block_tag_s -{ - __be32 t_blocknr; /* The on-disk block number */ - __be32 t_flags; /* See below */ -} journal_block_tag_t; - -/* - * The revoke descriptor: used on disk to describe a series of blocks to - * be revoked from the log - */ -typedef struct journal_revoke_header_s -{ - journal_header_t r_header; - __be32 r_count; /* Count of bytes used in the block */ -} journal_revoke_header_t; - - -/* Definitions for the journal tag flags word: */ -#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */ -#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */ -#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */ -#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */ - - -/* - * The journal superblock. All fields are in big-endian byte order. - */ -typedef struct journal_superblock_s -{ - /* 0x0000 */ - journal_header_t s_header; - - /* 0x000C */ - /* Static information describing the journal */ - __be32 s_blocksize; /* journal device blocksize */ - __be32 s_maxlen; /* total blocks in journal file */ - __be32 s_first; /* first block of log information */ - - /* 0x0018 */ - /* Dynamic information describing the current state of the log */ - __be32 s_sequence; /* first commit ID expected in log */ - __be32 s_start; /* blocknr of start of log */ - - /* 0x0020 */ - /* Error value, as set by journal_abort(). */ - __be32 s_errno; - - /* 0x0024 */ - /* Remaining fields are only valid in a version-2 superblock */ - __be32 s_feature_compat; /* compatible feature set */ - __be32 s_feature_incompat; /* incompatible feature set */ - __be32 s_feature_ro_compat; /* readonly-compatible feature set */ - /* 0x0030 */ - __u8 s_uuid[16]; /* 128-bit uuid for journal */ - - /* 0x0040 */ - __be32 s_nr_users; /* Nr of filesystems sharing log */ - - __be32 s_dynsuper; /* Blocknr of dynamic superblock copy*/ - - /* 0x0048 */ - __be32 s_max_transaction; /* Limit of journal blocks per trans.*/ - __be32 s_max_trans_data; /* Limit of data blocks per trans. */ - - /* 0x0050 */ - __u32 s_padding[44]; - - /* 0x0100 */ - __u8 s_users[16*48]; /* ids of all fs'es sharing the log */ - /* 0x0400 */ -} journal_superblock_t; - -#define JFS_HAS_COMPAT_FEATURE(j,mask) \ - ((j)->j_format_version >= 2 && \ - ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask)))) -#define JFS_HAS_RO_COMPAT_FEATURE(j,mask) \ - ((j)->j_format_version >= 2 && \ - ((j)->j_superblock->s_feature_ro_compat & cpu_to_be32((mask)))) -#define JFS_HAS_INCOMPAT_FEATURE(j,mask) \ - ((j)->j_format_version >= 2 && \ - ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask)))) - -#define JFS_FEATURE_INCOMPAT_REVOKE 0x00000001 - -/* Features known to this kernel version: */ -#define JFS_KNOWN_COMPAT_FEATURES 0 -#define JFS_KNOWN_ROCOMPAT_FEATURES 0 -#define JFS_KNOWN_INCOMPAT_FEATURES JFS_FEATURE_INCOMPAT_REVOKE - -#ifdef __KERNEL__ - -#include -#include - -#define J_ASSERT ASSERT - -#if defined(CONFIG_BUFFER_DEBUG) -void buffer_assertion_failure(struct buffer_head *bh); -#define J_ASSERT_BH(bh, expr) \ - do { \ - if (!(expr)) \ - buffer_assertion_failure(bh); \ - J_ASSERT(expr); \ - } while (0) -#define J_ASSERT_JH(jh, expr) J_ASSERT_BH(jh2bh(jh), expr) -#else -#define J_ASSERT_BH(bh, expr) J_ASSERT(expr) -#define J_ASSERT_JH(jh, expr) J_ASSERT(expr) -#endif - -#if defined(JBD_PARANOID_IOFAIL) -#define J_EXPECT(expr, why...) J_ASSERT(expr) -#define J_EXPECT_BH(bh, expr, why...) J_ASSERT_BH(bh, expr) -#define J_EXPECT_JH(jh, expr, why...) J_ASSERT_JH(jh, expr) -#else -#if 0 -#define __journal_expect(expr, why...) \ - ({ \ - int val = (expr); \ - if (!val) { \ - printk(KERN_ERR \ - "EXT3-fs unexpected failure: %s;\n",# expr); \ - printk(KERN_ERR why "\n"); \ - } \ - val; \ - }) -#define J_EXPECT(expr, why...) __journal_expect(expr, ## why) -#define J_EXPECT_BH(bh, expr, why...) __journal_expect(expr, ## why) -#define J_EXPECT_JH(jh, expr, why...) __journal_expect(expr, ## why) -#endif -#define __journal_expect - -#define J_EXPECT -#define J_EXPECT_BH -#define J_EXPECT_JH - -#endif - -enum jbd_state_bits { - BH_JBD /* Has an attached ext3 journal_head */ - = BH_PrivateStart, - BH_JWrite, /* Being written to log (@@@ DEBUGGING) */ - BH_Freed, /* Has been freed (truncated) */ - BH_Revoked, /* Has been revoked from the log */ - BH_RevokeValid, /* Revoked flag is valid */ - BH_JBDDirty, /* Is dirty but journaled */ - BH_State, /* Pins most journal_head state */ - BH_JournalHead, /* Pins bh->b_private and jh->b_bh */ - BH_Unshadow, /* Dummy bit, for BJ_Shadow wakeup filtering */ -}; - -BUFFER_FNS(JBD, jbd) -BUFFER_FNS(JWrite, jwrite) -BUFFER_FNS(JBDDirty, jbddirty) -TAS_BUFFER_FNS(JBDDirty, jbddirty) -BUFFER_FNS(Revoked, revoked) -TAS_BUFFER_FNS(Revoked, revoked) -BUFFER_FNS(RevokeValid, revokevalid) -TAS_BUFFER_FNS(RevokeValid, revokevalid) -BUFFER_FNS(Freed, freed) - -static inline struct buffer_head *jh2bh(struct journal_head *jh) -{ - return jh->b_bh; -} - -static inline struct journal_head *bh2jh(struct buffer_head *bh) -{ - return bh->b_private; -} - -static inline void jbd_lock_bh_state(struct buffer_head *bh) -{ - bit_spin_lock(BH_State, &bh->b_state); -} - -static inline int jbd_trylock_bh_state(struct buffer_head *bh) -{ - return bit_spin_trylock(BH_State, &bh->b_state); -} - -static inline int jbd_is_locked_bh_state(struct buffer_head *bh) -{ - return bit_spin_is_locked(BH_State, &bh->b_state); -} - -static inline void jbd_unlock_bh_state(struct buffer_head *bh) -{ - bit_spin_unlock(BH_State, &bh->b_state); -} - -static inline void jbd_lock_bh_journal_head(struct buffer_head *bh) -{ - bit_spin_lock(BH_JournalHead, &bh->b_state); -} - -static inline void jbd_unlock_bh_journal_head(struct buffer_head *bh) -{ - bit_spin_unlock(BH_JournalHead, &bh->b_state); -} - -struct jbd_revoke_table_s; - -/** - * struct handle_s - The handle_s type is the concrete type associated with - * handle_t. - * @h_transaction: Which compound transaction is this update a part of? - * @h_buffer_credits: Number of remaining buffers we are allowed to dirty. - * @h_ref: Reference count on this handle - * @h_err: Field for caller's use to track errors through large fs operations - * @h_sync: flag for sync-on-close - * @h_jdata: flag to force data journaling - * @h_aborted: flag indicating fatal error on handle - * @h_lockdep_map: lockdep info for debugging lock problems - **/ - -/* Docbook can't yet cope with the bit fields, but will leave the documentation - * in so it can be fixed later. - */ - -struct handle_s -{ - /* Which compound transaction is this update a part of? */ - transaction_t *h_transaction; - - /* Number of remaining buffers we are allowed to dirty: */ - int h_buffer_credits; - - /* Reference count on this handle */ - int h_ref; - - /* Field for caller's use to track errors through large fs */ - /* operations */ - int h_err; - - /* Flags [no locking] */ -unsigned int h_sync: - 1; /* sync-on-close */ -unsigned int h_jdata: - 1; /* force data journaling */ -unsigned int h_aborted: - 1; /* fatal error on handle */ - -#ifdef CONFIG_DEBUG_LOCK_ALLOC - struct lockdep_map h_lockdep_map; -#endif -}; - - -/* The transaction_t type is the guts of the journaling mechanism. It - * tracks a compound transaction through its various states: - * - * RUNNING: accepting new updates - * LOCKED: Updates still running but we don't accept new ones - * RUNDOWN: Updates are tidying up but have finished requesting - * new buffers to modify (state not used for now) - * FLUSH: All updates complete, but we are still writing to disk - * COMMIT: All data on disk, writing commit record - * FINISHED: We still have to keep the transaction for checkpointing. - * - * The transaction keeps track of all of the buffers modified by a - * running transaction, and all of the buffers committed but not yet - * flushed to home for finished transactions. - */ - -/* - * Lock ranking: - * - * j_list_lock - * ->jbd_lock_bh_journal_head() (This is "innermost") - * - * j_state_lock - * ->jbd_lock_bh_state() - * - * jbd_lock_bh_state() - * ->j_list_lock - * - * j_state_lock - * ->t_handle_lock - * - * j_state_lock - * ->j_list_lock (journal_unmap_buffer) - * - */ - -struct transaction_s -{ - /* Pointer to the journal for this transaction. [no locking] */ - journal_t *t_journal; - - /* Sequence number for this transaction [no locking] */ - tid_t t_tid; - - /* - * Transaction's current state - * [no locking - only kjournald alters this] - * [j_list_lock] guards transition of a transaction into T_FINISHED - * state and subsequent call of __journal_drop_transaction() - * FIXME: needs barriers - * KLUDGE: [use j_state_lock] - */ - enum { - T_RUNNING, - T_LOCKED, - T_RUNDOWN, - T_FLUSH, - T_COMMIT, - T_FINISHED - } t_state; - - /* - * Where in the log does this transaction's commit start? [no locking] - */ - unsigned long t_log_start; - - /* Number of buffers on the t_buffers list [j_list_lock] */ - int t_nr_buffers; - - /* - * Doubly-linked circular list of all buffers reserved but not yet - * modified by this transaction [j_list_lock] - */ - struct journal_head *t_reserved_list; - - /* - * Doubly-linked circular list of all buffers under writeout during - * commit [j_list_lock] - */ - struct journal_head *t_locked_list; - - /* - * Doubly-linked circular list of all metadata buffers owned by this - * transaction [j_list_lock] - */ - struct journal_head *t_buffers; - - /* - * Doubly-linked circular list of all data buffers still to be - * flushed before this transaction can be committed [j_list_lock] - */ - struct journal_head *t_sync_datalist; - - /* - * Doubly-linked circular list of all forget buffers (superseded - * buffers which we can un-checkpoint once this transaction commits) - * [j_list_lock] - */ - struct journal_head *t_forget; - - /* - * Doubly-linked circular list of all buffers still to be flushed before - * this transaction can be checkpointed. [j_list_lock] - */ - struct journal_head *t_checkpoint_list; - - /* - * Doubly-linked circular list of all buffers submitted for IO while - * checkpointing. [j_list_lock] - */ - struct journal_head *t_checkpoint_io_list; - - /* - * Doubly-linked circular list of temporary buffers currently undergoing - * IO in the log [j_list_lock] - */ - struct journal_head *t_iobuf_list; - - /* - * Doubly-linked circular list of metadata buffers being shadowed by log - * IO. The IO buffers on the iobuf list and the shadow buffers on this - * list match each other one for one at all times. [j_list_lock] - */ - struct journal_head *t_shadow_list; - - /* - * Doubly-linked circular list of control buffers being written to the - * log. [j_list_lock] - */ - struct journal_head *t_log_list; - - /* - * Protects info related to handles - */ - jbdlock_t t_handle_lock; - - /* - * Number of outstanding updates running on this transaction - * [t_handle_lock] - */ - int t_updates; - - /* - * Number of buffers reserved for use by all handles in this transaction - * handle but not yet modified. [t_handle_lock] - */ - int t_outstanding_credits; - - /* - * Forward and backward links for the circular list of all transactions - * awaiting checkpoint. [j_list_lock] - */ - transaction_t *t_cpnext, *t_cpprev; - - /* - * When will the transaction expire (become due for commit), in jiffies? - * [no locking] - */ - unsigned long t_expires; - - /* - * How many handles used this transaction? [t_handle_lock] - */ - int t_handle_count; - -}; - -/** - * struct journal_s - The journal_s type is the concrete type associated with - * journal_t. - * @j_flags: General journaling state flags - * @j_errno: Is there an outstanding uncleared error on the journal (from a - * prior abort)? - * @j_sb_buffer: First part of superblock buffer - * @j_superblock: Second part of superblock buffer - * @j_format_version: Version of the superblock format - * @j_state_lock: Protect the various scalars in the journal - * @j_barrier_count: Number of processes waiting to create a barrier lock - * @j_barrier: The barrier lock itself - * @j_running_transaction: The current running transaction.. - * @j_committing_transaction: the transaction we are pushing to disk - * @j_checkpoint_transactions: a linked circular list of all transactions - * waiting for checkpointing - * @j_wait_transaction_locked: Wait queue for waiting for a locked transaction - * to start committing, or for a barrier lock to be released - * @j_wait_logspace: Wait queue for waiting for checkpointing to complete - * @j_wait_done_commit: Wait queue for waiting for commit to complete - * @j_wait_checkpoint: Wait queue to trigger checkpointing - * @j_wait_commit: Wait queue to trigger commit - * @j_wait_updates: Wait queue to wait for updates to complete - * @j_checkpoint_mutex: Mutex for locking against concurrent checkpoints - * @j_head: Journal head - identifies the first unused block in the journal - * @j_tail: Journal tail - identifies the oldest still-used block in the - * journal. - * @j_free: Journal free - how many free blocks are there in the journal? - * @j_first: The block number of the first usable block - * @j_last: The block number one beyond the last usable block - * @j_dev: Device where we store the journal - * @j_blocksize: blocksize for the location where we store the journal. - * @j_blk_offset: starting block offset for into the device where we store the - * journal - * @j_fs_dev: Device which holds the client fs. For internal journal this will - * be equal to j_dev - * @j_maxlen: Total maximum capacity of the journal region on disk. - * @j_list_lock: Protects the buffer lists and internal buffer state. - * @j_inode: Optional inode where we store the journal. If present, all journal - * block numbers are mapped into this inode via bmap(). - * @j_tail_sequence: Sequence number of the oldest transaction in the log - * @j_transaction_sequence: Sequence number of the next transaction to grant - * @j_commit_sequence: Sequence number of the most recently committed - * transaction - * @j_commit_request: Sequence number of the most recent transaction wanting - * commit - * @j_uuid: Uuid of client object. - * @j_task: Pointer to the current commit thread for this journal - * @j_max_transaction_buffers: Maximum number of metadata buffers to allow in a - * single compound commit transaction - * @j_commit_interval: What is the maximum transaction lifetime before we begin - * a commit? - * @j_commit_timer: The timer used to wakeup the commit thread - * @j_revoke_lock: Protect the revoke table - * @j_revoke: The revoke table - maintains the list of revoked blocks in the - * current transaction. - * @j_revoke_table: alternate revoke tables for j_revoke - * @j_wbuf: array of buffer_heads for journal_commit_transaction - * @j_wbufsize: maximum number of buffer_heads allowed in j_wbuf, the - * number that will fit in j_blocksize - * @j_last_sync_writer: most recent pid which did a synchronous write - * @j_private: An opaque pointer to fs-private information. - */ - -struct journal_s -{ - /* General journaling state flags [j_state_lock] */ - unsigned long j_flags; - - /* - * Is there an outstanding uncleared error on the journal (from a prior - * abort)? [j_state_lock] - */ - int j_errno; - - /* The superblock buffer */ - struct buffer_head *j_sb_buffer; - journal_superblock_t *j_superblock; - - /* Version of the superblock format */ - int j_format_version; - - /* - * Protect the various scalars in the journal - */ - jbdlock_t j_state_lock; - - /* - * Number of processes waiting to create a barrier lock [j_state_lock] - */ - int j_barrier_count; - - /* The barrier lock itself */ - struct mutex j_barrier; - - /* - * Transactions: The current running transaction... - * [j_state_lock] [caller holding open handle] - */ - transaction_t *j_running_transaction; - - /* - * the transaction we are pushing to disk - * [j_state_lock] [caller holding open handle] - */ - transaction_t *j_committing_transaction; - - /* - * ... and a linked circular list of all transactions waiting for - * checkpointing. [j_list_lock] - */ - transaction_t *j_checkpoint_transactions; - - /* - * Wait queue for waiting for a locked transaction to start committing, - * or for a barrier lock to be released - */ - wait_queue_head_t j_wait_transaction_locked; - - /* Wait queue for waiting for checkpointing to complete */ - wait_queue_head_t j_wait_logspace; - - /* Wait queue for waiting for commit to complete */ - wait_queue_head_t j_wait_done_commit; - - /* Wait queue to trigger checkpointing */ - wait_queue_head_t j_wait_checkpoint; - - /* Wait queue to trigger commit */ - wait_queue_head_t j_wait_commit; - - /* Wait queue to wait for updates to complete */ - wait_queue_head_t j_wait_updates; - - /* Semaphore for locking against concurrent checkpoints */ - struct mutex j_checkpoint_mutex; - - /* - * Journal head: identifies the first unused block in the journal. - * [j_state_lock] - */ - unsigned long j_head; - - /* - * Journal tail: identifies the oldest still-used block in the journal. - * [j_state_lock] - */ - unsigned long j_tail; - - /* - * Journal free: how many free blocks are there in the journal? - * [j_state_lock] - */ - unsigned long j_free; - - /* - * Journal start and end: the block numbers of the first usable block - * and one beyond the last usable block in the journal. [j_state_lock] - */ - unsigned long j_first; - unsigned long j_last; - - /* - * Device, blocksize and starting block offset for the location where we - * store the journal. - */ - struct block_device *j_dev; - int j_blocksize; - unsigned long j_blk_offset; - - /* - * Device which holds the client fs. For internal journal this will be - * equal to j_dev. - */ - struct block_device *j_fs_dev; - - /* Total maximum capacity of the journal region on disk. */ - unsigned int j_maxlen; - - /* - * Protects the buffer lists and internal buffer state. - */ - jbdlock_t j_list_lock; - - /* Optional inode where we store the journal. If present, all */ - /* journal block numbers are mapped into this inode via */ - /* bmap(). */ - struct inode *j_inode; - - /* - * Sequence number of the oldest transaction in the log [j_state_lock] - */ - tid_t j_tail_sequence; - - /* - * Sequence number of the next transaction to grant [j_state_lock] - */ - tid_t j_transaction_sequence; - - /* - * Sequence number of the most recently committed transaction - * [j_state_lock]. - */ - tid_t j_commit_sequence; - - /* - * Sequence number of the most recent transaction wanting commit - * [j_state_lock] - */ - tid_t j_commit_request; - - /* - * Journal uuid: identifies the object (filesystem, LVM volume etc) - * backed by this journal. This will eventually be replaced by an array - * of uuids, allowing us to index multiple devices within a single - * journal and to perform atomic updates across them. - */ - __u8 j_uuid[16]; - - /* Pointer to the current commit thread for this journal */ - struct task_struct *j_task; - - /* - * Maximum number of metadata buffers to allow in a single compound - * commit transaction - */ - int j_max_transaction_buffers; - - /* - * What is the maximum transaction lifetime before we begin a commit? - */ - unsigned long j_commit_interval; - - /* The timer used to wakeup the commit thread: */ - struct timer_list j_commit_timer; - - /* - * The revoke table: maintains the list of revoked blocks in the - * current transaction. [j_revoke_lock] - */ - jbdlock_t j_revoke_lock; - struct jbd_revoke_table_s *j_revoke; - struct jbd_revoke_table_s *j_revoke_table[2]; - - /* - * array of bhs for journal_commit_transaction - */ - struct buffer_head **j_wbuf; - int j_wbufsize; - - pid_t j_last_sync_writer; - - /* - * An opaque pointer to fs-private information. ext3 puts its - * superblock pointer here - */ - void *j_private; -}; - -/* - * Journal flag definitions - */ -#define JFS_UNMOUNT 0x001 /* Journal thread is being destroyed */ -#define JFS_ABORT 0x002 /* Journaling has been aborted for errors. */ -#define JFS_ACK_ERR 0x004 /* The errno in the sb has been acked */ -#define JFS_FLUSHED 0x008 /* The journal superblock has been flushed */ -#define JFS_LOADED 0x010 /* The journal superblock has been loaded */ -#define JFS_BARRIER 0x020 /* Use IDE barriers */ - -/* - * Function declarations for the journaling transaction and buffer - * management - */ - -/* Filing buffers */ -extern void journal_unfile_buffer(journal_t *, struct journal_head *); -extern void __journal_unfile_buffer(struct journal_head *); -extern void __journal_refile_buffer(struct journal_head *); -extern void journal_refile_buffer(journal_t *, struct journal_head *); -extern void __journal_file_buffer(struct journal_head *, transaction_t *, int); -extern void __journal_free_buffer(struct journal_head *bh); -extern void journal_file_buffer(struct journal_head *, transaction_t *, int); -extern void __journal_clean_data_list(transaction_t *transaction); - -/* Log buffer allocation */ -extern struct journal_head * journal_get_descriptor_buffer(journal_t *); -int journal_next_log_block(journal_t *, unsigned long *); - -/* Commit management */ -extern void journal_commit_transaction(journal_t *); - -/* Checkpoint list management */ -int __journal_clean_checkpoint_list(journal_t *journal); -int __journal_remove_checkpoint(struct journal_head *); -void __journal_insert_checkpoint(struct journal_head *, transaction_t *); - -/* Buffer IO */ -extern int - journal_write_metadata_buffer(transaction_t *transaction, - struct journal_head *jh_in, - struct journal_head **jh_out, - unsigned long blocknr); - -/* Transaction locking */ -extern void __wait_on_journal (journal_t *); - -/* - * Journal locking. - * - * We need to lock the journal during transaction state changes so that nobody - * ever tries to take a handle on the running transaction while we are in the - * middle of moving it to the commit phase. j_state_lock does this. - * - * Note that the locking is completely interrupt unsafe. We never touch - * journal structures from interrupts. - */ - -static inline handle_t *journal_current_handle(void) -{ - return NULL; - /* return current->journal_info; */ -} - -/* The journaling code user interface: - * - * Create and destroy handles - * Register buffer modifications against the current transaction. - */ - -extern handle_t *journal_start(journal_t *, int nblocks); -extern int journal_restart (handle_t *, int nblocks); -extern int journal_extend (handle_t *, int nblocks); -extern int journal_get_write_access(handle_t *, struct buffer_head *); -extern int journal_get_create_access (handle_t *, struct buffer_head *); -extern int journal_get_undo_access(handle_t *, struct buffer_head *); -extern int journal_dirty_data (handle_t *, struct buffer_head *); -extern int journal_dirty_metadata (handle_t *, struct buffer_head *); -extern void journal_release_buffer (handle_t *, struct buffer_head *); -extern int journal_forget (handle_t *, struct buffer_head *); -extern void journal_sync_buffer (struct buffer_head *); -extern void journal_invalidatepage(journal_t *, - struct page *, unsigned long); -extern int journal_try_to_free_buffers(journal_t *, struct page *, gfp_t); -extern int journal_stop(handle_t *); -extern int journal_flush (journal_t *); -extern void journal_lock_updates (journal_t *); -extern void journal_unlock_updates (journal_t *); - -extern journal_t * journal_init_dev(struct block_device *bdev, - struct block_device *fs_dev, - int start, int len, int bsize); -extern journal_t * journal_init_inode (struct inode *); -extern int journal_update_format (journal_t *); -extern int journal_check_used_features - (journal_t *, unsigned long, unsigned long, unsigned long); -extern int journal_check_available_features - (journal_t *, unsigned long, unsigned long, unsigned long); -extern int journal_set_features - (journal_t *, unsigned long, unsigned long, unsigned long); -extern int journal_create (journal_t *); -extern int journal_load (journal_t *journal); -extern void journal_destroy (journal_t *); -extern int journal_recover (journal_t *journal); -extern int journal_wipe (journal_t *, int); -extern int journal_skip_recovery (journal_t *); -extern void journal_update_superblock (journal_t *, int); -void journal_abort (journal_t *, int); -extern int journal_errno (journal_t *); -extern void journal_ack_err (journal_t *); -extern int journal_clear_err (journal_t *); -extern int journal_bmap(journal_t *, unsigned long, unsigned long *); -extern int journal_force_commit(journal_t *); - -/* added by matt */ -void journal_wipe_recovery(journal_t *journal); - -/* - * journal_head management - */ -struct journal_head *journal_add_journal_head(struct buffer_head *bh); -struct journal_head *journal_grab_journal_head(struct buffer_head *bh); -void journal_remove_journal_head(struct buffer_head *bh); -void journal_put_journal_head(struct journal_head *jh); - -/* - * handle management - */ -extern struct kmem_cache *jbd_handle_cache; - -static inline handle_t *jbd_alloc_handle(gfp_t gfp_flags) -{ - return (handle_t *)kmem_cache_alloc(jbd_handle_cache, gfp_flags); -} - -static inline void jbd_free_handle(handle_t *handle) -{ - kmem_cache_free(jbd_handle_cache, handle); -} - -/* Primary revoke support */ -#define JOURNAL_REVOKE_DEFAULT_HASH 256 -extern int journal_init_revoke(journal_t *, int); -extern void journal_destroy_revoke_caches(void); -extern int journal_init_revoke_caches(void); - -extern void journal_destroy_revoke(journal_t *); -extern int journal_revoke (handle_t *, - unsigned long, struct buffer_head *); -extern int journal_cancel_revoke(handle_t *, struct journal_head *); -extern void journal_write_revoke_records(journal_t *, transaction_t *); - -/* Recovery revoke support */ -extern int journal_set_revoke(journal_t *, unsigned long, tid_t); -extern int journal_test_revoke(journal_t *, unsigned long, tid_t); -extern void journal_clear_revoke(journal_t *); -extern void journal_switch_revoke_table(journal_t *journal); - -/* - * The log thread user interface: - * - * Request space in the current transaction, and force transaction commit - * transitions on demand. - */ - -int __log_space_left(journal_t *); /* Called with journal locked */ -int log_start_commit(journal_t *journal, tid_t tid); -int __log_start_commit(journal_t *journal, tid_t tid); -int journal_start_commit(journal_t *journal, tid_t *tid); -int journal_force_commit_nested(journal_t *journal); -int log_wait_commit(journal_t *journal, tid_t tid); -int log_do_checkpoint(journal_t *journal); - -void __log_wait_for_space(journal_t *journal); -extern void __journal_drop_transaction(journal_t *, transaction_t *); -extern int cleanup_journal_tail(journal_t *); - -/* Debugging code only: */ - -#define jbd_ENOSYS() \ -do { \ - printk (KERN_ERR "JBD unimplemented function %s\n", __FUNCTION__); \ - current->state = TASK_UNINTERRUPTIBLE; \ - schedule(); \ -} while (1) - -/* - * is_journal_abort - * - * Simple test wrapper function to test the JFS_ABORT state flag. This - * bit, when set, indicates that we have had a fatal error somewhere, - * either inside the journaling layer or indicated to us by the client - * (eg. ext3), and that we and should not commit any further - * transactions. - */ - -static inline int is_journal_aborted(journal_t *journal) -{ - return journal->j_flags & JFS_ABORT; -} - -static inline int is_handle_aborted(handle_t *handle) -{ - if (handle->h_aborted) - return 1; - return is_journal_aborted(handle->h_transaction->t_journal); -} - -static inline void journal_abort_handle(handle_t *handle) -{ - handle->h_aborted = 1; -} - -#endif /* __KERNEL__ */ - -/* Comparison functions for transaction IDs: perform comparisons using - * modulo arithmetic so that they work over sequence number wraps. */ - -static inline int tid_gt(tid_t x, tid_t y) -{ - int difference = (x - y); - return (difference > 0); -} - -static inline int tid_geq(tid_t x, tid_t y) -{ - int difference = (x - y); - return (difference >= 0); -} - -extern int journal_blocks_per_page(struct inode *inode); - -/* - * Return the minimum number of blocks which must be free in the journal - * before a new transaction may be started. Must be called under j_state_lock. - */ -static inline int jbd_space_needed(journal_t *journal) -{ - int nblocks = journal->j_max_transaction_buffers; - if (journal->j_committing_transaction) - nblocks += journal->j_committing_transaction-> - t_outstanding_credits; - return nblocks; -} - -/* - * Definitions which augment the buffer_head layer - */ - -/* journaling buffer types */ -#define BJ_None 0 /* Not journaled */ -#define BJ_SyncData 1 /* Normal data: flush before commit */ -#define BJ_Metadata 2 /* Normal journaled metadata */ -#define BJ_Forget 3 /* Buffer superseded by this transaction */ -#define BJ_IO 4 /* Buffer is for temporary IO use */ -#define BJ_Shadow 5 /* Buffer contents being shadowed to the log */ -#define BJ_LogCtl 6 /* Buffer contains log descriptors */ -#define BJ_Reserved 7 /* Buffer is reserved for access by journal */ -#define BJ_Locked 8 /* Locked for I/O during commit */ -#define BJ_Types 9 - -extern int jbd_blocks_per_page(struct inode *inode); - -#ifdef __KERNEL__ - -#define buffer_trace_init(bh) do {} while (0) -#define print_buffer_fields(bh) do {} while (0) -#define print_buffer_trace(bh) do {} while (0) -#define BUFFER_TRACE(bh, info) do {} while (0) -#define BUFFER_TRACE2(bh, bh2, info) do {} while (0) -#define JBUFFER_TRACE(jh, info) do {} while (0) - -#endif /* __KERNEL__ */ - -#endif /* _LINUX_JBD_H */ +/* + * linux/include/linux/jbd.h + * + * Written by Stephen C. Tweedie + * + * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * Definitions for transaction data structures for the buffer cache + * filesystem journaling support. + */ + +#ifndef _LINUX_JBD_H +#define _LINUX_JBD_H + +/* Allow this file to be included directly into e2fsprogs */ +#ifndef __KERNEL__ +#include "jfs_compat.h" +#define JFS_DEBUG +#define jfs_debug jbd_debug +#else + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define journal_oom_retry 1 + +#define jbdlock_t FAST_MUTEX + +static inline void jbd_lock_init(jbdlock_t *lock) +{ + ExInitializeFastMutex(lock); +} + +static inline void jbd_lock(jbdlock_t *lock) +{ + ExAcquireFastMutex(lock); +} + +static inline void jbd_unlock(jbdlock_t *lock) +{ + ExReleaseFastMutex(lock); +} + +static inline int assert_jbd_locked(jbdlock_t *lock) +{ + int rc = 1; + + if (ExTryToAcquireFastMutex(lock)) { + ExReleaseFastMutex(lock); + rc = 0; + } + + return rc; +} + + +/* + * Define JBD_PARANIOD_IOFAIL to cause a kernel BUG() if ext3 finds + * certain classes of error which can occur due to failed IOs. Under + * normal use we want ext3 to continue after such errors, because + * hardware _can_ fail, but for debugging purposes when running tests on + * known-good hardware we may want to trap these errors. + */ +#undef JBD_PARANOID_IOFAIL + +/* + * The default maximum commit age, in seconds. + */ +#define JBD_DEFAULT_MAX_COMMIT_AGE 5 + +#ifdef CONFIG_JBD_DEBUG +/* + * Define JBD_EXPENSIVE_CHECKING to enable more expensive internal + * consistency checks. By default we don't do this unless + * CONFIG_JBD_DEBUG is on. + */ +#define JBD_EXPENSIVE_CHECKING +extern u8 journal_enable_debug; + +#define jbd_debug(n, f, a...) \ + do { \ + if ((n) <= journal_enable_debug) { \ + printk (KERN_DEBUG "(%s, %d): %s: ", \ + __FILE__, __LINE__, __FUNCTION__); \ + printk (f, ## a); \ + } \ + } while (0) +#else +#define jbd_debug +#endif + +static inline void *jbd_alloc(size_t size, gfp_t flags) +{ + return kmalloc(size, flags); + /*__get_free_pages(flags, get_order(size));*/ +} + +static inline void jbd_free(void *ptr, size_t size) +{ + if (ptr) { + kfree(ptr); + } + /* free_pages((unsigned long)ptr, get_order(size)); */ +}; + +#define JFS_MIN_JOURNAL_BLOCKS 1024 + + +/** + * typedef handle_t - The handle_t type represents a single atomic update being performed by some process. + * + * All filesystem modifications made by the process go + * through this handle. Recursive operations (such as quota operations) + * are gathered into a single update. + * + * The buffer credits field is used to account for journaled buffers + * being modified by the running process. To ensure that there is + * enough log space for all outstanding operations, we need to limit the + * number of outstanding buffers possible at any time. When the + * operation completes, any buffer credits not used are credited back to + * the transaction, so that at all times we know how many buffers the + * outstanding updates on a transaction might possibly touch. + * + * This is an opaque datatype. + **/ +typedef struct handle_s handle_t; /* Atomic operation type */ + + +/** + * typedef journal_t - The journal_t maintains all of the journaling state information for a single filesystem. + * + * journal_t is linked to from the fs superblock structure. + * + * We use the journal_t to keep track of all outstanding transaction + * activity on the filesystem, and to manage the state of the log + * writing process. + * + * This is an opaque datatype. + **/ +typedef struct journal_s journal_t; /* Journal control structure */ +#endif + +/* + * Internal structures used by the logging mechanism: + */ + +#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */ + +/* + * On-disk structures + */ + +/* + * Descriptor block types: + */ + +#define JFS_DESCRIPTOR_BLOCK 1 +#define JFS_COMMIT_BLOCK 2 +#define JFS_SUPERBLOCK_V1 3 +#define JFS_SUPERBLOCK_V2 4 +#define JFS_REVOKE_BLOCK 5 + +/* + * Standard header for all descriptor blocks: + */ +typedef struct journal_header_s +{ + __be32 h_magic; + __be32 h_blocktype; + __be32 h_sequence; +} journal_header_t; + + +/* + * The block tag: used to describe a single buffer in the journal + */ +typedef struct journal_block_tag_s +{ + __be32 t_blocknr; /* The on-disk block number */ + __be32 t_flags; /* See below */ +} journal_block_tag_t; + +/* + * The revoke descriptor: used on disk to describe a series of blocks to + * be revoked from the log + */ +typedef struct journal_revoke_header_s +{ + journal_header_t r_header; + __be32 r_count; /* Count of bytes used in the block */ +} journal_revoke_header_t; + + +/* Definitions for the journal tag flags word: */ +#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */ +#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */ +#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */ +#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */ + + +/* + * The journal superblock. All fields are in big-endian byte order. + */ +typedef struct journal_superblock_s +{ + /* 0x0000 */ + journal_header_t s_header; + + /* 0x000C */ + /* Static information describing the journal */ + __be32 s_blocksize; /* journal device blocksize */ + __be32 s_maxlen; /* total blocks in journal file */ + __be32 s_first; /* first block of log information */ + + /* 0x0018 */ + /* Dynamic information describing the current state of the log */ + __be32 s_sequence; /* first commit ID expected in log */ + __be32 s_start; /* blocknr of start of log */ + + /* 0x0020 */ + /* Error value, as set by journal_abort(). */ + __be32 s_errno; + + /* 0x0024 */ + /* Remaining fields are only valid in a version-2 superblock */ + __be32 s_feature_compat; /* compatible feature set */ + __be32 s_feature_incompat; /* incompatible feature set */ + __be32 s_feature_ro_compat; /* readonly-compatible feature set */ + /* 0x0030 */ + __u8 s_uuid[16]; /* 128-bit uuid for journal */ + + /* 0x0040 */ + __be32 s_nr_users; /* Nr of filesystems sharing log */ + + __be32 s_dynsuper; /* Blocknr of dynamic superblock copy*/ + + /* 0x0048 */ + __be32 s_max_transaction; /* Limit of journal blocks per trans.*/ + __be32 s_max_trans_data; /* Limit of data blocks per trans. */ + + /* 0x0050 */ + __u32 s_padding[44]; + + /* 0x0100 */ + __u8 s_users[16*48]; /* ids of all fs'es sharing the log */ + /* 0x0400 */ +} journal_superblock_t; + +#define JFS_HAS_COMPAT_FEATURE(j,mask) \ + ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask)))) +#define JFS_HAS_RO_COMPAT_FEATURE(j,mask) \ + ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_ro_compat & cpu_to_be32((mask)))) +#define JFS_HAS_INCOMPAT_FEATURE(j,mask) \ + ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask)))) + +#define JFS_FEATURE_INCOMPAT_REVOKE 0x00000001 +#define JFS_FEATURE_INCOMPAT_64BIT 0x00000002 + +/* Features known to this kernel version: */ +#define JFS_KNOWN_COMPAT_FEATURES 0 +#define JFS_KNOWN_ROCOMPAT_FEATURES 0 +#define JFS_KNOWN_INCOMPAT_FEATURES (JFS_FEATURE_INCOMPAT_REVOKE | JFS_FEATURE_INCOMPAT_64BIT) + +#ifdef __KERNEL__ + +#include +#include + +#define J_ASSERT ASSERT + +#if defined(CONFIG_BUFFER_DEBUG) +void buffer_assertion_failure(struct buffer_head *bh); +#define J_ASSERT_BH(bh, expr) \ + do { \ + if (!(expr)) \ + buffer_assertion_failure(bh); \ + J_ASSERT(expr); \ + } while (0) +#define J_ASSERT_JH(jh, expr) J_ASSERT_BH(jh2bh(jh), expr) +#else +#define J_ASSERT_BH(bh, expr) J_ASSERT(expr) +#define J_ASSERT_JH(jh, expr) J_ASSERT(expr) +#endif + +#if defined(JBD_PARANOID_IOFAIL) +#define J_EXPECT(expr, why...) J_ASSERT(expr) +#define J_EXPECT_BH(bh, expr, why...) J_ASSERT_BH(bh, expr) +#define J_EXPECT_JH(jh, expr, why...) J_ASSERT_JH(jh, expr) +#else +#if 0 +#define __journal_expect(expr, why...) \ + ({ \ + int val = (expr); \ + if (!val) { \ + printk(KERN_ERR \ + "EXT3-fs unexpected failure: %s;\n",# expr); \ + printk(KERN_ERR why "\n"); \ + } \ + val; \ + }) +#define J_EXPECT(expr, why...) __journal_expect(expr, ## why) +#define J_EXPECT_BH(bh, expr, why...) __journal_expect(expr, ## why) +#define J_EXPECT_JH(jh, expr, why...) __journal_expect(expr, ## why) +#endif +#define __journal_expect + +#define J_EXPECT +#define J_EXPECT_BH +#define J_EXPECT_JH + +#endif + +enum jbd_state_bits { + BH_JBD /* Has an attached ext3 journal_head */ + = BH_PrivateStart, + BH_JWrite, /* Being written to log (@@@ DEBUGGING) */ + BH_Freed, /* Has been freed (truncated) */ + BH_Revoked, /* Has been revoked from the log */ + BH_RevokeValid, /* Revoked flag is valid */ + BH_JBDDirty, /* Is dirty but journaled */ + BH_State, /* Pins most journal_head state */ + BH_JournalHead, /* Pins bh->b_private and jh->b_bh */ + BH_Unshadow, /* Dummy bit, for BJ_Shadow wakeup filtering */ +}; + +BUFFER_FNS(JBD, jbd) +BUFFER_FNS(JWrite, jwrite) +BUFFER_FNS(JBDDirty, jbddirty) +TAS_BUFFER_FNS(JBDDirty, jbddirty) +BUFFER_FNS(Revoked, revoked) +TAS_BUFFER_FNS(Revoked, revoked) +BUFFER_FNS(RevokeValid, revokevalid) +TAS_BUFFER_FNS(RevokeValid, revokevalid) +BUFFER_FNS(Freed, freed) + +static inline struct buffer_head *jh2bh(struct journal_head *jh) +{ + return jh->b_bh; +} + +static inline struct journal_head *bh2jh(struct buffer_head *bh) +{ + return bh->b_private; +} + +static inline void jbd_lock_bh_state(struct buffer_head *bh) +{ + bit_spin_lock(BH_State, &bh->b_state); +} + +static inline int jbd_trylock_bh_state(struct buffer_head *bh) +{ + return bit_spin_trylock(BH_State, &bh->b_state); +} + +static inline int jbd_is_locked_bh_state(struct buffer_head *bh) +{ + return bit_spin_is_locked(BH_State, &bh->b_state); +} + +static inline void jbd_unlock_bh_state(struct buffer_head *bh) +{ + bit_spin_unlock(BH_State, &bh->b_state); +} + +static inline void jbd_lock_bh_journal_head(struct buffer_head *bh) +{ + bit_spin_lock(BH_JournalHead, &bh->b_state); +} + +static inline void jbd_unlock_bh_journal_head(struct buffer_head *bh) +{ + bit_spin_unlock(BH_JournalHead, &bh->b_state); +} + +struct jbd_revoke_table_s; + +/** + * struct handle_s - The handle_s type is the concrete type associated with + * handle_t. + * @h_transaction: Which compound transaction is this update a part of? + * @h_buffer_credits: Number of remaining buffers we are allowed to dirty. + * @h_ref: Reference count on this handle + * @h_err: Field for caller's use to track errors through large fs operations + * @h_sync: flag for sync-on-close + * @h_jdata: flag to force data journaling + * @h_aborted: flag indicating fatal error on handle + * @h_lockdep_map: lockdep info for debugging lock problems + **/ + +/* Docbook can't yet cope with the bit fields, but will leave the documentation + * in so it can be fixed later. + */ + +struct handle_s +{ + /* Which compound transaction is this update a part of? */ + transaction_t *h_transaction; + + /* Number of remaining buffers we are allowed to dirty: */ + int h_buffer_credits; + + /* Reference count on this handle */ + int h_ref; + + /* Field for caller's use to track errors through large fs */ + /* operations */ + int h_err; + + /* Flags [no locking] */ +unsigned int h_sync: + 1; /* sync-on-close */ +unsigned int h_jdata: + 1; /* force data journaling */ +unsigned int h_aborted: + 1; /* fatal error on handle */ + +#ifdef CONFIG_DEBUG_LOCK_ALLOC + struct lockdep_map h_lockdep_map; +#endif +}; + + +/* The transaction_t type is the guts of the journaling mechanism. It + * tracks a compound transaction through its various states: + * + * RUNNING: accepting new updates + * LOCKED: Updates still running but we don't accept new ones + * RUNDOWN: Updates are tidying up but have finished requesting + * new buffers to modify (state not used for now) + * FLUSH: All updates complete, but we are still writing to disk + * COMMIT: All data on disk, writing commit record + * FINISHED: We still have to keep the transaction for checkpointing. + * + * The transaction keeps track of all of the buffers modified by a + * running transaction, and all of the buffers committed but not yet + * flushed to home for finished transactions. + */ + +/* + * Lock ranking: + * + * j_list_lock + * ->jbd_lock_bh_journal_head() (This is "innermost") + * + * j_state_lock + * ->jbd_lock_bh_state() + * + * jbd_lock_bh_state() + * ->j_list_lock + * + * j_state_lock + * ->t_handle_lock + * + * j_state_lock + * ->j_list_lock (journal_unmap_buffer) + * + */ + +struct transaction_s +{ + /* Pointer to the journal for this transaction. [no locking] */ + journal_t *t_journal; + + /* Sequence number for this transaction [no locking] */ + tid_t t_tid; + + /* + * Transaction's current state + * [no locking - only kjournald alters this] + * [j_list_lock] guards transition of a transaction into T_FINISHED + * state and subsequent call of __journal_drop_transaction() + * FIXME: needs barriers + * KLUDGE: [use j_state_lock] + */ + enum { + T_RUNNING, + T_LOCKED, + T_RUNDOWN, + T_FLUSH, + T_COMMIT, + T_FINISHED + } t_state; + + /* + * Where in the log does this transaction's commit start? [no locking] + */ + unsigned long t_log_start; + + /* Number of buffers on the t_buffers list [j_list_lock] */ + int t_nr_buffers; + + /* + * Doubly-linked circular list of all buffers reserved but not yet + * modified by this transaction [j_list_lock] + */ + struct journal_head *t_reserved_list; + + /* + * Doubly-linked circular list of all buffers under writeout during + * commit [j_list_lock] + */ + struct journal_head *t_locked_list; + + /* + * Doubly-linked circular list of all metadata buffers owned by this + * transaction [j_list_lock] + */ + struct journal_head *t_buffers; + + /* + * Doubly-linked circular list of all data buffers still to be + * flushed before this transaction can be committed [j_list_lock] + */ + struct journal_head *t_sync_datalist; + + /* + * Doubly-linked circular list of all forget buffers (superseded + * buffers which we can un-checkpoint once this transaction commits) + * [j_list_lock] + */ + struct journal_head *t_forget; + + /* + * Doubly-linked circular list of all buffers still to be flushed before + * this transaction can be checkpointed. [j_list_lock] + */ + struct journal_head *t_checkpoint_list; + + /* + * Doubly-linked circular list of all buffers submitted for IO while + * checkpointing. [j_list_lock] + */ + struct journal_head *t_checkpoint_io_list; + + /* + * Doubly-linked circular list of temporary buffers currently undergoing + * IO in the log [j_list_lock] + */ + struct journal_head *t_iobuf_list; + + /* + * Doubly-linked circular list of metadata buffers being shadowed by log + * IO. The IO buffers on the iobuf list and the shadow buffers on this + * list match each other one for one at all times. [j_list_lock] + */ + struct journal_head *t_shadow_list; + + /* + * Doubly-linked circular list of control buffers being written to the + * log. [j_list_lock] + */ + struct journal_head *t_log_list; + + /* + * Protects info related to handles + */ + jbdlock_t t_handle_lock; + + /* + * Number of outstanding updates running on this transaction + * [t_handle_lock] + */ + int t_updates; + + /* + * Number of buffers reserved for use by all handles in this transaction + * handle but not yet modified. [t_handle_lock] + */ + int t_outstanding_credits; + + /* + * Forward and backward links for the circular list of all transactions + * awaiting checkpoint. [j_list_lock] + */ + transaction_t *t_cpnext, *t_cpprev; + + /* + * When will the transaction expire (become due for commit), in jiffies? + * [no locking] + */ + unsigned long t_expires; + + /* + * How many handles used this transaction? [t_handle_lock] + */ + int t_handle_count; + +}; + +/** + * struct journal_s - The journal_s type is the concrete type associated with + * journal_t. + * @j_flags: General journaling state flags + * @j_errno: Is there an outstanding uncleared error on the journal (from a + * prior abort)? + * @j_sb_buffer: First part of superblock buffer + * @j_superblock: Second part of superblock buffer + * @j_format_version: Version of the superblock format + * @j_state_lock: Protect the various scalars in the journal + * @j_barrier_count: Number of processes waiting to create a barrier lock + * @j_barrier: The barrier lock itself + * @j_running_transaction: The current running transaction.. + * @j_committing_transaction: the transaction we are pushing to disk + * @j_checkpoint_transactions: a linked circular list of all transactions + * waiting for checkpointing + * @j_wait_transaction_locked: Wait queue for waiting for a locked transaction + * to start committing, or for a barrier lock to be released + * @j_wait_logspace: Wait queue for waiting for checkpointing to complete + * @j_wait_done_commit: Wait queue for waiting for commit to complete + * @j_wait_checkpoint: Wait queue to trigger checkpointing + * @j_wait_commit: Wait queue to trigger commit + * @j_wait_updates: Wait queue to wait for updates to complete + * @j_checkpoint_mutex: Mutex for locking against concurrent checkpoints + * @j_head: Journal head - identifies the first unused block in the journal + * @j_tail: Journal tail - identifies the oldest still-used block in the + * journal. + * @j_free: Journal free - how many free blocks are there in the journal? + * @j_first: The block number of the first usable block + * @j_last: The block number one beyond the last usable block + * @j_dev: Device where we store the journal + * @j_blocksize: blocksize for the location where we store the journal. + * @j_blk_offset: starting block offset for into the device where we store the + * journal + * @j_fs_dev: Device which holds the client fs. For internal journal this will + * be equal to j_dev + * @j_maxlen: Total maximum capacity of the journal region on disk. + * @j_list_lock: Protects the buffer lists and internal buffer state. + * @j_inode: Optional inode where we store the journal. If present, all journal + * block numbers are mapped into this inode via bmap(). + * @j_tail_sequence: Sequence number of the oldest transaction in the log + * @j_transaction_sequence: Sequence number of the next transaction to grant + * @j_commit_sequence: Sequence number of the most recently committed + * transaction + * @j_commit_request: Sequence number of the most recent transaction wanting + * commit + * @j_uuid: Uuid of client object. + * @j_task: Pointer to the current commit thread for this journal + * @j_max_transaction_buffers: Maximum number of metadata buffers to allow in a + * single compound commit transaction + * @j_commit_interval: What is the maximum transaction lifetime before we begin + * a commit? + * @j_commit_timer: The timer used to wakeup the commit thread + * @j_revoke_lock: Protect the revoke table + * @j_revoke: The revoke table - maintains the list of revoked blocks in the + * current transaction. + * @j_revoke_table: alternate revoke tables for j_revoke + * @j_wbuf: array of buffer_heads for journal_commit_transaction + * @j_wbufsize: maximum number of buffer_heads allowed in j_wbuf, the + * number that will fit in j_blocksize + * @j_last_sync_writer: most recent pid which did a synchronous write + * @j_private: An opaque pointer to fs-private information. + */ + +struct journal_s +{ + /* General journaling state flags [j_state_lock] */ + unsigned long j_flags; + + /* + * Is there an outstanding uncleared error on the journal (from a prior + * abort)? [j_state_lock] + */ + int j_errno; + + /* The superblock buffer */ + struct buffer_head *j_sb_buffer; + journal_superblock_t *j_superblock; + + /* Version of the superblock format */ + int j_format_version; + + /* + * Protect the various scalars in the journal + */ + jbdlock_t j_state_lock; + + /* + * Number of processes waiting to create a barrier lock [j_state_lock] + */ + int j_barrier_count; + + /* The barrier lock itself */ + struct mutex j_barrier; + + /* + * Transactions: The current running transaction... + * [j_state_lock] [caller holding open handle] + */ + transaction_t *j_running_transaction; + + /* + * the transaction we are pushing to disk + * [j_state_lock] [caller holding open handle] + */ + transaction_t *j_committing_transaction; + + /* + * ... and a linked circular list of all transactions waiting for + * checkpointing. [j_list_lock] + */ + transaction_t *j_checkpoint_transactions; + + /* + * Wait queue for waiting for a locked transaction to start committing, + * or for a barrier lock to be released + */ + wait_queue_head_t j_wait_transaction_locked; + + /* Wait queue for waiting for checkpointing to complete */ + wait_queue_head_t j_wait_logspace; + + /* Wait queue for waiting for commit to complete */ + wait_queue_head_t j_wait_done_commit; + + /* Wait queue to trigger checkpointing */ + wait_queue_head_t j_wait_checkpoint; + + /* Wait queue to trigger commit */ + wait_queue_head_t j_wait_commit; + + /* Wait queue to wait for updates to complete */ + wait_queue_head_t j_wait_updates; + + /* Semaphore for locking against concurrent checkpoints */ + struct mutex j_checkpoint_mutex; + + /* + * Journal head: identifies the first unused block in the journal. + * [j_state_lock] + */ + unsigned long j_head; + + /* + * Journal tail: identifies the oldest still-used block in the journal. + * [j_state_lock] + */ + unsigned long j_tail; + + /* + * Journal free: how many free blocks are there in the journal? + * [j_state_lock] + */ + unsigned long j_free; + + /* + * Journal start and end: the block numbers of the first usable block + * and one beyond the last usable block in the journal. [j_state_lock] + */ + unsigned long j_first; + unsigned long j_last; + + /* + * Device, blocksize and starting block offset for the location where we + * store the journal. + */ + struct block_device *j_dev; + int j_blocksize; + unsigned long j_blk_offset; + + /* + * Device which holds the client fs. For internal journal this will be + * equal to j_dev. + */ + struct block_device *j_fs_dev; + + /* Total maximum capacity of the journal region on disk. */ + unsigned int j_maxlen; + + /* + * Protects the buffer lists and internal buffer state. + */ + jbdlock_t j_list_lock; + + /* Optional inode where we store the journal. If present, all */ + /* journal block numbers are mapped into this inode via */ + /* bmap(). */ + struct inode *j_inode; + + /* + * Sequence number of the oldest transaction in the log [j_state_lock] + */ + tid_t j_tail_sequence; + + /* + * Sequence number of the next transaction to grant [j_state_lock] + */ + tid_t j_transaction_sequence; + + /* + * Sequence number of the most recently committed transaction + * [j_state_lock]. + */ + tid_t j_commit_sequence; + + /* + * Sequence number of the most recent transaction wanting commit + * [j_state_lock] + */ + tid_t j_commit_request; + + /* + * Journal uuid: identifies the object (filesystem, LVM volume etc) + * backed by this journal. This will eventually be replaced by an array + * of uuids, allowing us to index multiple devices within a single + * journal and to perform atomic updates across them. + */ + __u8 j_uuid[16]; + + /* Pointer to the current commit thread for this journal */ + struct task_struct *j_task; + + /* + * Maximum number of metadata buffers to allow in a single compound + * commit transaction + */ + int j_max_transaction_buffers; + + /* + * What is the maximum transaction lifetime before we begin a commit? + */ + unsigned long j_commit_interval; + + /* The timer used to wakeup the commit thread: */ + struct timer_list j_commit_timer; + + /* + * The revoke table: maintains the list of revoked blocks in the + * current transaction. [j_revoke_lock] + */ + jbdlock_t j_revoke_lock; + struct jbd_revoke_table_s *j_revoke; + struct jbd_revoke_table_s *j_revoke_table[2]; + + /* + * array of bhs for journal_commit_transaction + */ + struct buffer_head **j_wbuf; + int j_wbufsize; + + pid_t j_last_sync_writer; + + /* + * An opaque pointer to fs-private information. ext3 puts its + * superblock pointer here + */ + void *j_private; +}; + +/* + * Journal flag definitions + */ +#define JFS_UNMOUNT 0x001 /* Journal thread is being destroyed */ +#define JFS_ABORT 0x002 /* Journaling has been aborted for errors. */ +#define JFS_ACK_ERR 0x004 /* The errno in the sb has been acked */ +#define JFS_FLUSHED 0x008 /* The journal superblock has been flushed */ +#define JFS_LOADED 0x010 /* The journal superblock has been loaded */ +#define JFS_BARRIER 0x020 /* Use IDE barriers */ + +/* + * Function declarations for the journaling transaction and buffer + * management + */ + +/* Filing buffers */ +extern void journal_unfile_buffer(journal_t *, struct journal_head *); +extern void __journal_unfile_buffer(struct journal_head *); +extern void __journal_refile_buffer(struct journal_head *); +extern void journal_refile_buffer(journal_t *, struct journal_head *); +extern void __journal_file_buffer(struct journal_head *, transaction_t *, int); +extern void __journal_free_buffer(struct journal_head *bh); +extern void journal_file_buffer(struct journal_head *, transaction_t *, int); +extern void __journal_clean_data_list(transaction_t *transaction); + +/* Log buffer allocation */ +extern struct journal_head * journal_get_descriptor_buffer(journal_t *); +int journal_next_log_block(journal_t *, unsigned long *); + +/* Commit management */ +extern void journal_commit_transaction(journal_t *); + +/* Checkpoint list management */ +int __journal_clean_checkpoint_list(journal_t *journal); +int __journal_remove_checkpoint(struct journal_head *); +void __journal_insert_checkpoint(struct journal_head *, transaction_t *); + +/* Buffer IO */ +extern int + journal_write_metadata_buffer(transaction_t *transaction, + struct journal_head *jh_in, + struct journal_head **jh_out, + unsigned long blocknr); + +/* Transaction locking */ +extern void __wait_on_journal (journal_t *); + +/* + * Journal locking. + * + * We need to lock the journal during transaction state changes so that nobody + * ever tries to take a handle on the running transaction while we are in the + * middle of moving it to the commit phase. j_state_lock does this. + * + * Note that the locking is completely interrupt unsafe. We never touch + * journal structures from interrupts. + */ + +static inline handle_t *journal_current_handle(void) +{ + return NULL; + /* return current->journal_info; */ +} + +/* The journaling code user interface: + * + * Create and destroy handles + * Register buffer modifications against the current transaction. + */ + +extern handle_t *journal_start(journal_t *, int nblocks); +extern int journal_restart (handle_t *, int nblocks); +extern int journal_extend (handle_t *, int nblocks); +extern int journal_get_write_access(handle_t *, struct buffer_head *); +extern int journal_get_create_access (handle_t *, struct buffer_head *); +extern int journal_get_undo_access(handle_t *, struct buffer_head *); +extern int journal_dirty_data (handle_t *, struct buffer_head *); +extern int journal_dirty_metadata (handle_t *, struct buffer_head *); +extern void journal_release_buffer (handle_t *, struct buffer_head *); +extern int journal_forget (handle_t *, struct buffer_head *); +extern void journal_sync_buffer (struct buffer_head *); +extern void journal_invalidatepage(journal_t *, + struct page *, unsigned long); +extern int journal_try_to_free_buffers(journal_t *, struct page *, gfp_t); +extern int journal_stop(handle_t *); +extern int journal_flush (journal_t *); +extern void journal_lock_updates (journal_t *); +extern void journal_unlock_updates (journal_t *); + +extern journal_t * journal_init_dev(struct block_device *bdev, + struct block_device *fs_dev, + int start, int len, int bsize); +extern journal_t * journal_init_inode (struct inode *); +extern int journal_update_format (journal_t *); +extern int journal_check_used_features + (journal_t *, unsigned long, unsigned long, unsigned long); +extern int journal_check_available_features + (journal_t *, unsigned long, unsigned long, unsigned long); +extern int journal_set_features + (journal_t *, unsigned long, unsigned long, unsigned long); +extern int journal_create (journal_t *); +extern int journal_load (journal_t *journal); +extern void journal_destroy (journal_t *); +extern int journal_recover (journal_t *journal); +extern int journal_wipe (journal_t *, int); +extern int journal_skip_recovery (journal_t *); +extern void journal_update_superblock (journal_t *, int); +void journal_abort (journal_t *, int); +extern int journal_errno (journal_t *); +extern void journal_ack_err (journal_t *); +extern int journal_clear_err (journal_t *); +extern int journal_bmap(journal_t *, unsigned long, unsigned long *); +extern int journal_force_commit(journal_t *); + +/* added by matt */ +void journal_wipe_recovery(journal_t *journal); + +/* + * journal_head management + */ +struct journal_head *journal_add_journal_head(struct buffer_head *bh); +struct journal_head *journal_grab_journal_head(struct buffer_head *bh); +void journal_remove_journal_head(struct buffer_head *bh); +void journal_put_journal_head(struct journal_head *jh); + +/* + * handle management + */ +extern struct kmem_cache *jbd_handle_cache; + +static inline handle_t *jbd_alloc_handle(gfp_t gfp_flags) +{ + return (handle_t *)kmem_cache_alloc(jbd_handle_cache, gfp_flags); +} + +static inline void jbd_free_handle(handle_t *handle) +{ + kmem_cache_free(jbd_handle_cache, handle); +} + +/* Primary revoke support */ +#define JOURNAL_REVOKE_DEFAULT_HASH 256 +extern int journal_init_revoke(journal_t *, int); +extern void journal_destroy_revoke_caches(void); +extern int journal_init_revoke_caches(void); + +extern void journal_destroy_revoke(journal_t *); +extern int journal_revoke (handle_t *, + unsigned long, struct buffer_head *); +extern int journal_cancel_revoke(handle_t *, struct journal_head *); +extern void journal_write_revoke_records(journal_t *, transaction_t *); + +/* Recovery revoke support */ +extern int journal_set_revoke(journal_t *, unsigned long, tid_t); +extern int journal_test_revoke(journal_t *, unsigned long, tid_t); +extern void journal_clear_revoke(journal_t *); +extern void journal_switch_revoke_table(journal_t *journal); + +/* + * The log thread user interface: + * + * Request space in the current transaction, and force transaction commit + * transitions on demand. + */ + +int __log_space_left(journal_t *); /* Called with journal locked */ +int log_start_commit(journal_t *journal, tid_t tid); +int __log_start_commit(journal_t *journal, tid_t tid); +int journal_start_commit(journal_t *journal, tid_t *tid); +int journal_force_commit_nested(journal_t *journal); +int log_wait_commit(journal_t *journal, tid_t tid); +int log_do_checkpoint(journal_t *journal); + +void __log_wait_for_space(journal_t *journal); +extern void __journal_drop_transaction(journal_t *, transaction_t *); +extern int cleanup_journal_tail(journal_t *); + +/* Debugging code only: */ + +#define jbd_ENOSYS() \ +do { \ + printk (KERN_ERR "JBD unimplemented function %s\n", __FUNCTION__); \ + current->state = TASK_UNINTERRUPTIBLE; \ + schedule(); \ +} while (1) + +/* + * is_journal_abort + * + * Simple test wrapper function to test the JFS_ABORT state flag. This + * bit, when set, indicates that we have had a fatal error somewhere, + * either inside the journaling layer or indicated to us by the client + * (eg. ext3), and that we and should not commit any further + * transactions. + */ + +static inline int is_journal_aborted(journal_t *journal) +{ + return journal->j_flags & JFS_ABORT; +} + +static inline int is_handle_aborted(handle_t *handle) +{ + if (handle->h_aborted) + return 1; + return is_journal_aborted(handle->h_transaction->t_journal); +} + +static inline void journal_abort_handle(handle_t *handle) +{ + handle->h_aborted = 1; +} + +#endif /* __KERNEL__ */ + +/* Comparison functions for transaction IDs: perform comparisons using + * modulo arithmetic so that they work over sequence number wraps. */ + +static inline int tid_gt(tid_t x, tid_t y) +{ + int difference = (x - y); + return (difference > 0); +} + +static inline int tid_geq(tid_t x, tid_t y) +{ + int difference = (x - y); + return (difference >= 0); +} + +extern int journal_blocks_per_page(struct inode *inode); + +/* + * Return the minimum number of blocks which must be free in the journal + * before a new transaction may be started. Must be called under j_state_lock. + */ +static inline int jbd_space_needed(journal_t *journal) +{ + int nblocks = journal->j_max_transaction_buffers; + if (journal->j_committing_transaction) + nblocks += journal->j_committing_transaction-> + t_outstanding_credits; + return nblocks; +} + +/* + * Definitions which augment the buffer_head layer + */ + +/* journaling buffer types */ +#define BJ_None 0 /* Not journaled */ +#define BJ_SyncData 1 /* Normal data: flush before commit */ +#define BJ_Metadata 2 /* Normal journaled metadata */ +#define BJ_Forget 3 /* Buffer superseded by this transaction */ +#define BJ_IO 4 /* Buffer is for temporary IO use */ +#define BJ_Shadow 5 /* Buffer contents being shadowed to the log */ +#define BJ_LogCtl 6 /* Buffer contains log descriptors */ +#define BJ_Reserved 7 /* Buffer is reserved for access by journal */ +#define BJ_Locked 8 /* Locked for I/O during commit */ +#define BJ_Types 9 + +extern int jbd_blocks_per_page(struct inode *inode); + +#ifdef __KERNEL__ + +#define buffer_trace_init(bh) do {} while (0) +#define print_buffer_fields(bh) do {} while (0) +#define print_buffer_trace(bh) do {} while (0) +#define BUFFER_TRACE(bh, info) do {} while (0) +#define BUFFER_TRACE2(bh, bh2, info) do {} while (0) +#define JBUFFER_TRACE(jh, info) do {} while (0) + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_JBD_H */ diff --git a/Ext4Fsd/include/linux/jbd2.h b/Ext4Fsd/include/linux/jbd2.h new file mode 100644 index 0000000..24a21bf --- /dev/null +++ b/Ext4Fsd/include/linux/jbd2.h @@ -0,0 +1,1653 @@ +/* + * linux/include/linux/jbd2.h + * + * Written by Stephen C. Tweedie + * + * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * Definitions for transaction data structures for the buffer cache + * filesystem journaling support. + */ + +#ifndef _LINUX_JBD2_H +#define _LINUX_JBD2_H + +/* Allow this file to be included directly into e2fsprogs */ +#ifndef __KERNEL__ +#include "jfs_compat.h" +#define JBD2_DEBUG +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#define journal_oom_retry 1 + +/* + * Define JBD2_PARANIOD_IOFAIL to cause a kernel BUG() if ext4 finds + * certain classes of error which can occur due to failed IOs. Under + * normal use we want ext4 to continue after such errors, because + * hardware _can_ fail, but for debugging purposes when running tests on + * known-good hardware we may want to trap these errors. + */ +#undef JBD2_PARANOID_IOFAIL + +/* + * The default maximum commit age, in seconds. + */ +#define JBD2_DEFAULT_MAX_COMMIT_AGE 5 + +#ifdef CONFIG_JBD2_DEBUG +/* + * Define JBD2_EXPENSIVE_CHECKING to enable more expensive internal + * consistency checks. By default we don't do this unless + * CONFIG_JBD2_DEBUG is on. + */ +#define JBD2_EXPENSIVE_CHECKING +extern ushort jbd2_journal_enable_debug; +void __jbd2_debug(int level, const char *file, const char *func, + unsigned int line, const char *fmt, ...); + +#define jbd_debug(n, fmt, a...) \ + __jbd2_debug((n), __FILE__, __func__, __LINE__, (fmt), ##a) +#else +#define jbd_debug(n, fmt, a) /**/ +#endif + +extern void *jbd2_alloc(size_t size, gfp_t flags); +extern void jbd2_free(void *ptr, size_t size); + +#define JBD2_MIN_JOURNAL_BLOCKS 1024 + +#ifdef __KERNEL__ + +/** + * typedef handle_t - The handle_t type represents a single atomic update being performed by some process. + * + * All filesystem modifications made by the process go + * through this handle. Recursive operations (such as quota operations) + * are gathered into a single update. + * + * The buffer credits field is used to account for journaled buffers + * being modified by the running process. To ensure that there is + * enough log space for all outstanding operations, we need to limit the + * number of outstanding buffers possible at any time. When the + * operation completes, any buffer credits not used are credited back to + * the transaction, so that at all times we know how many buffers the + * outstanding updates on a transaction might possibly touch. + * + * This is an opaque datatype. + **/ +typedef struct jbd2_journal_handle handle_t; /* Atomic operation type */ + + +/** + * typedef journal_t - The journal_t maintains all of the journaling state information for a single filesystem. + * + * journal_t is linked to from the fs superblock structure. + * + * We use the journal_t to keep track of all outstanding transaction + * activity on the filesystem, and to manage the state of the log + * writing process. + * + * This is an opaque datatype. + **/ +typedef struct journal_s journal_t; /* Journal control structure */ +#endif + +/* + * Internal structures used by the logging mechanism: + */ + +#define JBD2_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */ + +/* + * On-disk structures + */ + +/* + * Descriptor block types: + */ + +#define JBD2_DESCRIPTOR_BLOCK 1 +#define JBD2_COMMIT_BLOCK 2 +#define JBD2_SUPERBLOCK_V1 3 +#define JBD2_SUPERBLOCK_V2 4 +#define JBD2_REVOKE_BLOCK 5 + +/* + * Standard header for all descriptor blocks: + */ +typedef struct journal_header_s +{ + __be32 h_magic; + __be32 h_blocktype; + __be32 h_sequence; +} journal_header_t; + +/* + * Checksum types. + */ +#define JBD2_CRC32_CHKSUM 1 +#define JBD2_MD5_CHKSUM 2 +#define JBD2_SHA1_CHKSUM 3 +#define JBD2_CRC32C_CHKSUM 4 + +#define JBD2_CRC32_CHKSUM_SIZE 4 + +#define JBD2_CHECKSUM_BYTES (32 / sizeof(u32)) +/* + * Commit block header for storing transactional checksums: + * + * NOTE: If FEATURE_COMPAT_CHECKSUM (checksum v1) is set, the h_chksum* + * fields are used to store a checksum of the descriptor and data blocks. + * + * If FEATURE_INCOMPAT_CSUM_V2 (checksum v2) is set, then the h_chksum + * field is used to store crc32c(uuid+commit_block). Each journal metadata + * block gets its own checksum, and data block checksums are stored in + * journal_block_tag (in the descriptor). The other h_chksum* fields are + * not used. + * + * If FEATURE_INCOMPAT_CSUM_V3 is set, the descriptor block uses + * journal_block_tag3_t to store a full 32-bit checksum. Everything else + * is the same as v2. + * + * Checksum v1, v2, and v3 are mutually exclusive features. + */ +struct commit_header { + __be32 h_magic; + __be32 h_blocktype; + __be32 h_sequence; + unsigned char h_chksum_type; + unsigned char h_chksum_size; + unsigned char h_padding[2]; + __be32 h_chksum[JBD2_CHECKSUM_BYTES]; + __be64 h_commit_sec; + __be32 h_commit_nsec; +}; + +/* + * The block tag: used to describe a single buffer in the journal. + * t_blocknr_high is only used if INCOMPAT_64BIT is set, so this + * raw struct shouldn't be used for pointer math or sizeof() - use + * journal_tag_bytes(journal) instead to compute this. + */ +typedef struct journal_block_tag3_s +{ + __be32 t_blocknr; /* The on-disk block number */ + __be32 t_flags; /* See below */ + __be32 t_blocknr_high; /* most-significant high 32bits. */ + __be32 t_checksum; /* crc32c(uuid+seq+block) */ +} journal_block_tag3_t; + +typedef struct journal_block_tag_s +{ + __be32 t_blocknr; /* The on-disk block number */ + __be16 t_checksum; /* truncated crc32c(uuid+seq+block) */ + __be16 t_flags; /* See below */ + __be32 t_blocknr_high; /* most-significant high 32bits. */ +} journal_block_tag_t; + +/* Tail of descriptor or revoke block, for checksumming */ +struct jbd2_journal_block_tail { + __be32 t_checksum; /* crc32c(uuid+descr_block) */ +}; + +/* + * The revoke descriptor: used on disk to describe a series of blocks to + * be revoked from the log + */ +typedef struct jbd2_journal_revoke_header_s +{ + journal_header_t r_header; + __be32 r_count; /* Count of bytes used in the block */ +} jbd2_journal_revoke_header_t; + +/* Definitions for the journal tag flags word: */ +#define JBD2_FLAG_ESCAPE 1 /* on-disk block is escaped */ +#define JBD2_FLAG_SAME_UUID 2 /* block has same uuid as previous */ +#define JBD2_FLAG_DELETED 4 /* block deleted by this transaction */ +#define JBD2_FLAG_LAST_TAG 8 /* last tag in this descriptor block */ + + +/* + * The journal superblock. All fields are in big-endian byte order. + */ +typedef struct journal_superblock_s +{ +/* 0x0000 */ + journal_header_t s_header; + +/* 0x000C */ + /* Static information describing the journal */ + __be32 s_blocksize; /* journal device blocksize */ + __be32 s_maxlen; /* total blocks in journal file */ + __be32 s_first; /* first block of log information */ + +/* 0x0018 */ + /* Dynamic information describing the current state of the log */ + __be32 s_sequence; /* first commit ID expected in log */ + __be32 s_start; /* blocknr of start of log */ + +/* 0x0020 */ + /* Error value, as set by jbd2_journal_abort(). */ + __be32 s_errno; + +/* 0x0024 */ + /* Remaining fields are only valid in a version-2 superblock */ + __be32 s_feature_compat; /* compatible feature set */ + __be32 s_feature_incompat; /* incompatible feature set */ + __be32 s_feature_ro_compat; /* readonly-compatible feature set */ +/* 0x0030 */ + __u8 s_uuid[16]; /* 128-bit uuid for journal */ + +/* 0x0040 */ + __be32 s_nr_users; /* Nr of filesystems sharing log */ + + __be32 s_dynsuper; /* Blocknr of dynamic superblock copy*/ + +/* 0x0048 */ + __be32 s_max_transaction; /* Limit of journal blocks per trans.*/ + __be32 s_max_trans_data; /* Limit of data blocks per trans. */ + +/* 0x0050 */ + __u8 s_checksum_type; /* checksum type */ + __u8 s_padding2[3]; + __u32 s_padding[42]; + __be32 s_checksum; /* crc32c(superblock) */ + +/* 0x0100 */ + __u8 s_users[16*48]; /* ids of all fs'es sharing the log */ +/* 0x0400 */ +} journal_superblock_t; + +/* Use the jbd2_{has,set,clear}_feature_* helpers; these will be removed */ +#define JBD2_HAS_COMPAT_FEATURE(j,mask) \ + ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask)))) +#define JBD2_HAS_RO_COMPAT_FEATURE(j,mask) \ + ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_ro_compat & cpu_to_be32((mask)))) +#define JBD2_HAS_INCOMPAT_FEATURE(j,mask) \ + ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask)))) + +#define JBD2_FEATURE_COMPAT_CHECKSUM 0x00000001 + +#define JBD2_FEATURE_INCOMPAT_REVOKE 0x00000001 +#define JBD2_FEATURE_INCOMPAT_64BIT 0x00000002 +#define JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT 0x00000004 +#define JBD2_FEATURE_INCOMPAT_CSUM_V2 0x00000008 +#define JBD2_FEATURE_INCOMPAT_CSUM_V3 0x00000010 + +/* See "journal feature predicate functions" below */ + +/* Features known to this kernel version: */ +#define JBD2_KNOWN_COMPAT_FEATURES JBD2_FEATURE_COMPAT_CHECKSUM +#define JBD2_KNOWN_ROCOMPAT_FEATURES 0 +#define JBD2_KNOWN_INCOMPAT_FEATURES (JBD2_FEATURE_INCOMPAT_REVOKE | \ + JBD2_FEATURE_INCOMPAT_64BIT | \ + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT | \ + JBD2_FEATURE_INCOMPAT_CSUM_V2 | \ + JBD2_FEATURE_INCOMPAT_CSUM_V3) + +#ifdef __KERNEL__ + +#include +#include + +enum jbd_state_bits { + BH_JBD /* Has an attached ext3 journal_head */ + = BH_PrivateStart, + BH_JWrite, /* Being written to log (@@@ DEBUGGING) */ + BH_Freed, /* Has been freed (truncated) */ + BH_Revoked, /* Has been revoked from the log */ + BH_RevokeValid, /* Revoked flag is valid */ + BH_JBDDirty, /* Is dirty but journaled */ + BH_State, /* Pins most journal_head state */ + BH_JournalHead, /* Pins bh->b_private and jh->b_bh */ + BH_Shadow, /* IO on shadow buffer is running */ + //BH_Verified, /* Metadata block has been verified ok */ + BH_JBDPrivateStart, /* First bit available for private use by FS */ +}; + +BUFFER_FNS(JBD, jbd) +BUFFER_FNS(JWrite, jwrite) +BUFFER_FNS(JBDDirty, jbddirty) +TAS_BUFFER_FNS(JBDDirty, jbddirty) +BUFFER_FNS(Revoked, revoked) +TAS_BUFFER_FNS(Revoked, revoked) +BUFFER_FNS(RevokeValid, revokevalid) +TAS_BUFFER_FNS(RevokeValid, revokevalid) +BUFFER_FNS(Freed, freed) +BUFFER_FNS(Shadow, shadow) +//BUFFER_FNS(Verified, verified) + +static inline struct buffer_head *jh2bh(struct journal_head *jh) +{ + return jh->b_bh; +} + +static inline struct journal_head *bh2jh(struct buffer_head *bh) +{ + return bh->b_private; +} + +static inline void jbd_lock_bh_state(struct buffer_head *bh) +{ + bit_spin_lock(BH_State, &bh->b_state); +} + +static inline int jbd_trylock_bh_state(struct buffer_head *bh) +{ + return bit_spin_trylock(BH_State, &bh->b_state); +} + +static inline int jbd_is_locked_bh_state(struct buffer_head *bh) +{ + return bit_spin_is_locked(BH_State, &bh->b_state); +} + +static inline void jbd_unlock_bh_state(struct buffer_head *bh) +{ + bit_spin_unlock(BH_State, &bh->b_state); +} + +static inline void jbd_lock_bh_journal_head(struct buffer_head *bh) +{ + bit_spin_lock(BH_JournalHead, &bh->b_state); +} + +static inline void jbd_unlock_bh_journal_head(struct buffer_head *bh) +{ + bit_spin_unlock(BH_JournalHead, &bh->b_state); +} + +#define J_ASSERT(assert) BUG_ON(!(assert)) + +#define J_ASSERT_BH(bh, expr) J_ASSERT(expr) +#define J_ASSERT_JH(jh, expr) J_ASSERT(expr) + +#if 0 +#if defined(JBD2_PARANOID_IOFAIL) +#define J_EXPECT(expr, why...) J_ASSERT(expr) +#define J_EXPECT_BH(bh, expr, why...) J_ASSERT_BH(bh, expr) +#define J_EXPECT_JH(jh, expr, why...) J_ASSERT_JH(jh, expr) +#else +#define __journal_expect(expr, why...) \ + ({ \ + int val = (expr); \ + if (!val) { \ + printk(KERN_ERR \ + "JBD2 unexpected failure: %s: %s;\n", \ + __func__, #expr); \ + printk(KERN_ERR why "\n"); \ + } \ + val; \ + }) +#define J_EXPECT(expr, why...) __journal_expect(expr, ## why) +#define J_EXPECT_BH(bh, expr, why...) __journal_expect(expr, ## why) +#define J_EXPECT_JH(jh, expr, why...) __journal_expect(expr, ## why) +#endif +#endif + +/* Flags in jbd_inode->i_flags */ +#define __JI_COMMIT_RUNNING 0 +#define __JI_WRITE_DATA 1 +#define __JI_WAIT_DATA 2 + +/* + * Commit of the inode data in progress. We use this flag to protect us from + * concurrent deletion of inode. We cannot use reference to inode for this + * since we cannot afford doing last iput() on behalf of kjournald + */ +#define JI_COMMIT_RUNNING (1 << __JI_COMMIT_RUNNING) +/* Write allocated dirty buffers in this inode before commit */ +#define JI_WRITE_DATA (1 << __JI_WRITE_DATA) +/* Wait for outstanding data writes for this inode before commit */ +#define JI_WAIT_DATA (1 << __JI_WAIT_DATA) + +/** + * struct jbd_inode - The jbd_inode type is the structure linking inodes in + * ordered mode present in a transaction so that we can sync them during commit. + */ +struct jbd2_inode { + /** + * @i_transaction: + * + * Which transaction does this inode belong to? Either the running + * transaction or the committing one. [j_list_lock] + */ + transaction_t *i_transaction; + + /** + * @i_next_transaction: + * + * Pointer to the running transaction modifying inode's data in case + * there is already a committing transaction touching it. [j_list_lock] + */ + transaction_t *i_next_transaction; + + /** + * @i_list: List of inodes in the i_transaction [j_list_lock] + */ + struct list_head i_list; + + /** + * @i_vfs_inode: + * + * VFS inode this inode belongs to [constant for lifetime of structure] + */ + struct inode *i_vfs_inode; + + /** + * @i_flags: Flags of inode [j_list_lock] + */ + unsigned long i_flags; +}; + +struct jbd2_revoke_table_s; + +/** + * struct handle_s - The handle_s type is the concrete type associated with + * handle_t. + * @h_transaction: Which compound transaction is this update a part of? + * @h_journal: Which journal handle belongs to - used iff h_reserved set. + * @h_rsv_handle: Handle reserved for finishing the logical operation. + * @h_buffer_credits: Number of remaining buffers we are allowed to dirty. + * @h_ref: Reference count on this handle. + * @h_err: Field for caller's use to track errors through large fs operations. + * @h_sync: Flag for sync-on-close. + * @h_jdata: Flag to force data journaling. + * @h_reserved: Flag for handle for reserved credits. + * @h_aborted: Flag indicating fatal error on handle. + * @h_type: For handle statistics. + * @h_line_no: For handle statistics. + * @h_start_jiffies: Handle Start time. + * @h_requested_credits: Holds @h_buffer_credits after handle is started. + * @saved_alloc_context: Saved context while transaction is open. + **/ + +/* Docbook can't yet cope with the bit fields, but will leave the documentation + * in so it can be fixed later. + */ + +struct jbd2_journal_handle +{ + union { + transaction_t *h_transaction; + /* Which journal handle belongs to - used iff h_reserved set */ + journal_t *h_journal; + }; + + handle_t *h_rsv_handle; + int h_buffer_credits; + int h_ref; + int h_err; + + /* Flags [no locking] */ + unsigned int h_sync: 1; + unsigned int h_jdata: 1; + unsigned int h_reserved: 1; + unsigned int h_aborted: 1; + unsigned int h_type: 8; + unsigned int h_line_no: 16; + + unsigned long h_start_jiffies; + unsigned int h_requested_credits; + + unsigned int saved_alloc_context; +}; + + +/* + * Some stats for checkpoint phase + */ +struct transaction_chp_stats_s { + unsigned long cs_chp_time; + __u32 cs_forced_to_close; + __u32 cs_written; + __u32 cs_dropped; +}; + +/* The transaction_t type is the guts of the journaling mechanism. It + * tracks a compound transaction through its various states: + * + * RUNNING: accepting new updates + * LOCKED: Updates still running but we don't accept new ones + * RUNDOWN: Updates are tidying up but have finished requesting + * new buffers to modify (state not used for now) + * FLUSH: All updates complete, but we are still writing to disk + * COMMIT: All data on disk, writing commit record + * FINISHED: We still have to keep the transaction for checkpointing. + * + * The transaction keeps track of all of the buffers modified by a + * running transaction, and all of the buffers committed but not yet + * flushed to home for finished transactions. + */ + +/* + * Lock ranking: + * + * j_list_lock + * ->jbd_lock_bh_journal_head() (This is "innermost") + * + * j_state_lock + * ->jbd_lock_bh_state() + * + * jbd_lock_bh_state() + * ->j_list_lock + * + * j_state_lock + * ->t_handle_lock + * + * j_state_lock + * ->j_list_lock (journal_unmap_buffer) + * + */ + +struct transaction_s +{ + /* Pointer to the journal for this transaction. [no locking] */ + journal_t *t_journal; + + /* Sequence number for this transaction [no locking] */ + tid_t t_tid; + + /* + * Transaction's current state + * [no locking - only kjournald2 alters this] + * [j_list_lock] guards transition of a transaction into T_FINISHED + * state and subsequent call of __jbd2_journal_drop_transaction() + * FIXME: needs barriers + * KLUDGE: [use j_state_lock] + */ + enum { + T_RUNNING, + T_LOCKED, + T_SWITCH, + T_FLUSH, + T_COMMIT, + T_COMMIT_DFLUSH, + T_COMMIT_JFLUSH, + T_COMMIT_CALLBACK, + T_FINISHED + } t_state; + + /* + * Where in the log does this transaction's commit start? [no locking] + */ + unsigned long t_log_start; + + /* Number of buffers on the t_buffers list [j_list_lock] */ + int t_nr_buffers; + + /* + * Doubly-linked circular list of all buffers reserved but not yet + * modified by this transaction [j_list_lock] + */ + struct journal_head *t_reserved_list; + + /* + * Doubly-linked circular list of all metadata buffers owned by this + * transaction [j_list_lock] + */ + struct journal_head *t_buffers; + + /* + * Doubly-linked circular list of all forget buffers (superseded + * buffers which we can un-checkpoint once this transaction commits) + * [j_list_lock] + */ + struct journal_head *t_forget; + + /* + * Doubly-linked circular list of all buffers still to be flushed before + * this transaction can be checkpointed. [j_list_lock] + */ + struct journal_head *t_checkpoint_list; + + /* + * Doubly-linked circular list of all buffers submitted for IO while + * checkpointing. [j_list_lock] + */ + struct journal_head *t_checkpoint_io_list; + + /* + * Doubly-linked circular list of metadata buffers being shadowed by log + * IO. The IO buffers on the iobuf list and the shadow buffers on this + * list match each other one for one at all times. [j_list_lock] + */ + struct journal_head *t_shadow_list; + + /* + * List of inodes whose data we've modified in data=ordered mode. + * [j_list_lock] + */ + struct list_head t_inode_list; + + /* + * Protects info related to handles + */ + spinlock_t t_handle_lock; + + /* + * Longest time some handle had to wait for running transaction + */ + unsigned long t_max_wait; + + /* + * When transaction started + */ + unsigned long t_start; + + /* + * When commit was requested + */ + unsigned long t_requested; + + /* + * Checkpointing stats [j_checkpoint_sem] + */ + struct transaction_chp_stats_s t_chp_stats; + + /* + * Number of outstanding updates running on this transaction + * [none] + */ + atomic_t t_updates; + + /* + * Number of buffers reserved for use by all handles in this transaction + * handle but not yet modified. [none] + */ + atomic_t t_outstanding_credits; + + /* + * Forward and backward links for the circular list of all transactions + * awaiting checkpoint. [j_list_lock] + */ + transaction_t *t_cpnext, *t_cpprev; + + /* + * When will the transaction expire (become due for commit), in jiffies? + * [no locking] + */ + unsigned long t_expires; + + /* + * When this transaction started, in nanoseconds [no locking] + */ + //ktime_t t_start_time; + + /* + * How many handles used this transaction? [none] + */ + atomic_t t_handle_count; + + /* + * This transaction is being forced and some process is + * waiting for it to finish. + */ + unsigned int t_synchronous_commit:1; + + /* Disk flush needs to be sent to fs partition [no locking] */ + int t_need_data_flush; + + /* + * For use by the filesystem to store fs-specific data + * structures associated with the transaction + */ + struct list_head t_private_list; +}; + +struct transaction_run_stats_s { + unsigned long rs_wait; + unsigned long rs_request_delay; + unsigned long rs_running; + unsigned long rs_locked; + unsigned long rs_flushing; + unsigned long rs_logging; + + __u32 rs_handle_count; + __u32 rs_blocks; + __u32 rs_blocks_logged; +}; + +struct transaction_stats_s { + unsigned long ts_tid; + unsigned long ts_requested; + struct transaction_run_stats_s run; +}; + +#define MAX_JIFFY_OFFSET ((LONG_MAX >> 1)-1) +static inline unsigned long +jbd2_time_diff(unsigned long start, unsigned long end) +{ + if (end >= start) + return end - start; + + return end + (MAX_JIFFY_OFFSET - start); +} + +#define JBD2_NR_BATCH 64 + +/** + * struct journal_s - The journal_s type is the concrete type associated with + * journal_t. + */ +struct journal_s +{ + /** + * @j_flags: General journaling state flags [j_state_lock] + */ + unsigned long j_flags; + + /** + * @j_errno: + * + * Is there an outstanding uncleared error on the journal (from a prior + * abort)? [j_state_lock] + */ + int j_errno; + + /** + * @j_sb_buffer: The first part of the superblock buffer. + */ + struct buffer_head *j_sb_buffer; + + /** + * @j_superblock: The second part of the superblock buffer. + */ + journal_superblock_t *j_superblock; + + /** + * @j_format_version: Version of the superblock format. + */ + int j_format_version; + + /** + * @j_state_lock: Protect the various scalars in the journal. + */ + //rwlock_t j_state_lock; + + /** + * @j_barrier_count: + * + * Number of processes waiting to create a barrier lock [j_state_lock] + */ + int j_barrier_count; + + /** + * @j_barrier: The barrier lock itself. + */ + struct mutex j_barrier; + + /** + * @j_running_transaction: + * + * Transactions: The current running transaction... + * [j_state_lock] [caller holding open handle] + */ + transaction_t *j_running_transaction; + + /** + * @j_committing_transaction: + * + * the transaction we are pushing to disk + * [j_state_lock] [caller holding open handle] + */ + transaction_t *j_committing_transaction; + + /** + * @j_checkpoint_transactions: + * + * ... and a linked circular list of all transactions waiting for + * checkpointing. [j_list_lock] + */ + transaction_t *j_checkpoint_transactions; + + /** + * @j_wait_transaction_locked: + * + * Wait queue for waiting for a locked transaction to start committing, + * or for a barrier lock to be released. + */ + wait_queue_head_t j_wait_transaction_locked; + + /** + * @j_wait_done_commit: Wait queue for waiting for commit to complete. + */ + wait_queue_head_t j_wait_done_commit; + + /** + * @j_wait_commit: Wait queue to trigger commit. + */ + wait_queue_head_t j_wait_commit; + + /** + * @j_wait_updates: Wait queue to wait for updates to complete. + */ + wait_queue_head_t j_wait_updates; + + /** + * @j_wait_reserved: + * + * Wait queue to wait for reserved buffer credits to drop. + */ + wait_queue_head_t j_wait_reserved; + + /** + * @j_checkpoint_mutex: + * + * Semaphore for locking against concurrent checkpoints. + */ + struct mutex j_checkpoint_mutex; + + /** + * @j_chkpt_bhs: + * + * List of buffer heads used by the checkpoint routine. This + * was moved from jbd2_log_do_checkpoint() to reduce stack + * usage. Access to this array is controlled by the + * @j_checkpoint_mutex. [j_checkpoint_mutex] + */ + struct buffer_head *j_chkpt_bhs[JBD2_NR_BATCH]; + + /** + * @j_head: + * + * Journal head: identifies the first unused block in the journal. + * [j_state_lock] + */ + unsigned long j_head; + + /** + * @j_tail: + * + * Journal tail: identifies the oldest still-used block in the journal. + * [j_state_lock] + */ + unsigned long j_tail; + + /** + * @j_free: + * + * Journal free: how many free blocks are there in the journal? + * [j_state_lock] + */ + unsigned long j_free; + + /** + * @j_first: + * + * The block number of the first usable block in the journal + * [j_state_lock]. + */ + unsigned long j_first; + + /** + * @j_last: + * + * The block number one beyond the last usable block in the journal + * [j_state_lock]. + */ + unsigned long j_last; + + /** + * @j_dev: Device where we store the journal. + */ + struct block_device *j_dev; + + /** + * @j_blocksize: Block size for the location where we store the journal. + */ + int j_blocksize; + + /** + * @j_blk_offset: + * + * Starting block offset into the device where we store the journal. + */ + unsigned long long j_blk_offset; + + /** + * @j_devname: Journal device name. + */ + char j_devname[BDEVNAME_SIZE+24]; + + /** + * @j_fs_dev: + * + * Device which holds the client fs. For internal journal this will be + * equal to j_dev. + */ + struct block_device *j_fs_dev; + + /** + * @j_maxlen: Total maximum capacity of the journal region on disk. + */ + unsigned int j_maxlen; + + /** + * @j_reserved_credits: + * + * Number of buffers reserved from the running transaction. + */ + atomic_t j_reserved_credits; + + /** + * @j_list_lock: Protects the buffer lists and internal buffer state. + */ + spinlock_t j_list_lock; + + /** + * @j_inode: + * + * Optional inode where we store the journal. If present, all + * journal block numbers are mapped into this inode via bmap(). + */ + struct inode *j_inode; + + /** + * @j_tail_sequence: + * + * Sequence number of the oldest transaction in the log [j_state_lock] + */ + tid_t j_tail_sequence; + + /** + * @j_transaction_sequence: + * + * Sequence number of the next transaction to grant [j_state_lock] + */ + tid_t j_transaction_sequence; + + /** + * @j_commit_sequence: + * + * Sequence number of the most recently committed transaction + * [j_state_lock]. + */ + tid_t j_commit_sequence; + + /** + * @j_commit_request: + * + * Sequence number of the most recent transaction wanting commit + * [j_state_lock] + */ + tid_t j_commit_request; + + /** + * @j_uuid: + * + * Journal uuid: identifies the object (filesystem, LVM volume etc) + * backed by this journal. This will eventually be replaced by an array + * of uuids, allowing us to index multiple devices within a single + * journal and to perform atomic updates across them. + */ + __u8 j_uuid[16]; + + /** + * @j_task: Pointer to the current commit thread for this journal. + */ + struct task_struct *j_task; + + /** + * @j_max_transaction_buffers: + * + * Maximum number of metadata buffers to allow in a single compound + * commit transaction. + */ + int j_max_transaction_buffers; + + /** + * @j_commit_interval: + * + * What is the maximum transaction lifetime before we begin a commit? + */ + unsigned long j_commit_interval; + + /** + * @j_commit_timer: The timer used to wakeup the commit thread. + */ + struct timer_list j_commit_timer; + + /** + * @j_revoke_lock: Protect the revoke table. + */ + spinlock_t j_revoke_lock; + + /** + * @j_revoke: + * + * The revoke table - maintains the list of revoked blocks in the + * current transaction. + */ + struct jbd2_revoke_table_s *j_revoke; + + /** + * @j_revoke_table: Alternate revoke tables for j_revoke. + */ + struct jbd2_revoke_table_s *j_revoke_table[2]; + + /** + * @j_wbuf: Array of bhs for jbd2_journal_commit_transaction. + */ + struct buffer_head **j_wbuf; + + /** + * @j_wbufsize: + * + * Size of @j_wbuf array. + */ + int j_wbufsize; + + /** + * @j_last_sync_writer: + * + * The pid of the last person to run a synchronous operation + * through the journal. + */ + pid_t j_last_sync_writer; + + /** + * @j_average_commit_time: + * + * The average amount of time in nanoseconds it takes to commit a + * transaction to disk. [j_state_lock] + */ + u64 j_average_commit_time; + + /** + * @j_min_batch_time: + * + * Minimum time that we should wait for additional filesystem operations + * to get batched into a synchronous handle in microseconds. + */ + u32 j_min_batch_time; + + /** + * @j_max_batch_time: + * + * Maximum time that we should wait for additional filesystem operations + * to get batched into a synchronous handle in microseconds. + */ + u32 j_max_batch_time; + + /** + * @j_commit_callback: + * + * This function is called when a transaction is closed. + */ + void (*j_commit_callback)(journal_t *, + transaction_t *); + + /* + * Journal statistics + */ + + /** + * @j_history_lock: Protect the transactions statistics history. + */ + spinlock_t j_history_lock; + + /** + * @j_proc_entry: procfs entry for the jbd statistics directory. + */ + struct proc_dir_entry *j_proc_entry; + + /** + * @j_stats: Overall statistics. + */ + struct transaction_stats_s j_stats; + + /** + * @j_failed_commit: Failed journal commit ID. + */ + unsigned int j_failed_commit; + + /** + * @j_private: + * + * An opaque pointer to fs-private information. ext3 puts its + * superblock pointer here. + */ + void *j_private; + + /** + * @j_chksum_driver: + * + * Reference to checksum algorithm driver via cryptoapi. + */ + struct crypto_shash *j_chksum_driver; + + /** + * @j_csum_seed: + * + * Precomputed journal UUID checksum for seeding other checksums. + */ + __u32 j_csum_seed; + +#ifdef CONFIG_DEBUG_LOCK_ALLOC + /** + * @j_trans_commit_map: + * + * Lockdep entity to track transaction commit dependencies. Handles + * hold this "lock" for read, when we wait for commit, we acquire the + * "lock" for writing. This matches the properties of jbd2 journalling + * where the running transaction has to wait for all handles to be + * dropped to commit that transaction and also acquiring a handle may + * require transaction commit to finish. + */ + struct lockdep_map j_trans_commit_map; +#endif +}; + +#define jbd2_might_wait_for_commit(j) \ + do { \ + rwsem_acquire(&j->j_trans_commit_map, 0, 0, _THIS_IP_); \ + rwsem_release(&j->j_trans_commit_map, 1, _THIS_IP_); \ + } while (0) + +/* journal feature predicate functions */ +#define JBD2_FEATURE_COMPAT_FUNCS(name, flagname) \ +static inline bool jbd2_has_feature_##name(journal_t *j) \ +{ \ + return ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_compat & \ + cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname)) != 0); \ +} \ +static inline void jbd2_set_feature_##name(journal_t *j) \ +{ \ + (j)->j_superblock->s_feature_compat |= \ + cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname); \ +} \ +static inline void jbd2_clear_feature_##name(journal_t *j) \ +{ \ + (j)->j_superblock->s_feature_compat &= \ + ~cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname); \ +} + +#define JBD2_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ +static inline bool jbd2_has_feature_##name(journal_t *j) \ +{ \ + return ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_ro_compat & \ + cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname)) != 0); \ +} \ +static inline void jbd2_set_feature_##name(journal_t *j) \ +{ \ + (j)->j_superblock->s_feature_ro_compat |= \ + cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname); \ +} \ +static inline void jbd2_clear_feature_##name(journal_t *j) \ +{ \ + (j)->j_superblock->s_feature_ro_compat &= \ + ~cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname); \ +} + +#define JBD2_FEATURE_INCOMPAT_FUNCS(name, flagname) \ +static inline bool jbd2_has_feature_##name(journal_t *j) \ +{ \ + return ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_incompat & \ + cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname)) != 0); \ +} \ +static inline void jbd2_set_feature_##name(journal_t *j) \ +{ \ + (j)->j_superblock->s_feature_incompat |= \ + cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname); \ +} \ +static inline void jbd2_clear_feature_##name(journal_t *j) \ +{ \ + (j)->j_superblock->s_feature_incompat &= \ + ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname); \ +} + +JBD2_FEATURE_COMPAT_FUNCS(checksum, CHECKSUM) + +JBD2_FEATURE_INCOMPAT_FUNCS(revoke, REVOKE) +JBD2_FEATURE_INCOMPAT_FUNCS(64bit, 64BIT) +JBD2_FEATURE_INCOMPAT_FUNCS(async_commit, ASYNC_COMMIT) +JBD2_FEATURE_INCOMPAT_FUNCS(csum2, CSUM_V2) +JBD2_FEATURE_INCOMPAT_FUNCS(csum3, CSUM_V3) + +/* + * Journal flag definitions + */ +#define JBD2_UNMOUNT 0x001 /* Journal thread is being destroyed */ +#define JBD2_ABORT 0x002 /* Journaling has been aborted for errors. */ +#define JBD2_ACK_ERR 0x004 /* The errno in the sb has been acked */ +#define JBD2_FLUSHED 0x008 /* The journal superblock has been flushed */ +#define JBD2_LOADED 0x010 /* The journal superblock has been loaded */ +#define JBD2_BARRIER 0x020 /* Use IDE barriers */ +#define JBD2_ABORT_ON_SYNCDATA_ERR 0x040 /* Abort the journal on file + * data write error in ordered + * mode */ +#define JBD2_REC_ERR 0x080 /* The errno in the sb has been recorded */ + +/* + * Function declarations for the journaling transaction and buffer + * management + */ + +/* Filing buffers */ +extern void jbd2_journal_unfile_buffer(journal_t *, struct journal_head *); +extern void __jbd2_journal_refile_buffer(struct journal_head *); +extern void jbd2_journal_refile_buffer(journal_t *, struct journal_head *); +extern void __jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int); +extern void __journal_free_buffer(struct journal_head *bh); +extern void jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int); +extern void __journal_clean_data_list(transaction_t *transaction); + +#if 0 +static inline void jbd2_file_log_bh(struct list_head *head, struct buffer_head *bh) +{ + list_add_tail(&bh->b_assoc_buffers, head); +} +static inline void jbd2_unfile_log_bh(struct buffer_head *bh) +{ + list_del_init(&bh->b_assoc_buffers); +} +#endif + +/* Log buffer allocation */ +struct buffer_head *jbd2_journal_get_descriptor_buffer(transaction_t *, int); +void jbd2_descriptor_block_csum_set(journal_t *, struct buffer_head *); +int jbd2_journal_next_log_block(journal_t *, unsigned long long *); +int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid, + unsigned long *block); +int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); +void jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); + +/* Commit management */ +extern void jbd2_journal_commit_transaction(journal_t *); + +/* Checkpoint list management */ +void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy); +int __jbd2_journal_remove_checkpoint(struct journal_head *); +void jbd2_journal_destroy_checkpoint(journal_t *journal); +void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *); + + +/* + * Triggers + */ + +struct jbd2_buffer_trigger_type { + /* + * Fired a the moment data to write to the journal are known to be + * stable - so either at the moment b_frozen_data is created or just + * before a buffer is written to the journal. mapped_data is a mapped + * buffer that is the frozen data for commit. + */ + void (*t_frozen)(struct jbd2_buffer_trigger_type *type, + struct buffer_head *bh, void *mapped_data, + size_t size); + + /* + * Fired during journal abort for dirty buffers that will not be + * committed. + */ + void (*t_abort)(struct jbd2_buffer_trigger_type *type, + struct buffer_head *bh); +}; + +extern void jbd2_buffer_frozen_trigger(struct journal_head *jh, + void *mapped_data, + struct jbd2_buffer_trigger_type *triggers); +extern void jbd2_buffer_abort_trigger(struct journal_head *jh, + struct jbd2_buffer_trigger_type *triggers); + +/* Buffer IO */ +extern int jbd2_journal_write_metadata_buffer(transaction_t *transaction, + struct journal_head *jh_in, + struct buffer_head **bh_out, + sector_t blocknr); + +/* Transaction locking */ +extern void __wait_on_journal (journal_t *); + +/* Transaction cache support */ +extern void jbd2_journal_destroy_transaction_cache(void); +extern int jbd2_journal_init_transaction_cache(void); +extern void jbd2_journal_free_transaction(transaction_t *); + +/* + * Journal locking. + * + * We need to lock the journal during transaction state changes so that nobody + * ever tries to take a handle on the running transaction while we are in the + * middle of moving it to the commit phase. j_state_lock does this. + * + * Note that the locking is completely interrupt unsafe. We never touch + * journal structures from interrupts. + */ + +static inline handle_t *journal_current_handle(void) +{ + return current->journal_info; +} + +/* The journaling code user interface: + * + * Create and destroy handles + * Register buffer modifications against the current transaction. + */ + +extern handle_t *jbd2_journal_start(journal_t *, int nblocks); +extern handle_t *jbd2__journal_start(journal_t *, int blocks, int rsv_blocks, + gfp_t gfp_mask, unsigned int type, + unsigned int line_no); +extern int jbd2_journal_restart(handle_t *, int nblocks); +extern int jbd2__journal_restart(handle_t *, int nblocks, gfp_t gfp_mask); +extern int jbd2_journal_start_reserved(handle_t *handle, + unsigned int type, unsigned int line_no); +extern void jbd2_journal_free_reserved(handle_t *handle); +extern int jbd2_journal_extend (handle_t *, int nblocks); +extern int jbd2_journal_get_write_access(handle_t *, struct buffer_head *); +extern int jbd2_journal_get_create_access (handle_t *, struct buffer_head *); +extern int jbd2_journal_get_undo_access(handle_t *, struct buffer_head *); +void jbd2_journal_set_triggers(struct buffer_head *, + struct jbd2_buffer_trigger_type *type); +extern int jbd2_journal_dirty_metadata (handle_t *, struct buffer_head *); +extern int jbd2_journal_forget (handle_t *, struct buffer_head *); +extern void journal_sync_buffer (struct buffer_head *); +extern int jbd2_journal_invalidatepage(journal_t *, + struct page *, unsigned int, unsigned int); +extern int jbd2_journal_try_to_free_buffers(journal_t *, struct page *, gfp_t); +extern int jbd2_journal_stop(handle_t *); +extern int jbd2_journal_flush (journal_t *); +extern void jbd2_journal_lock_updates (journal_t *); +extern void jbd2_journal_unlock_updates (journal_t *); + +extern journal_t * jbd2_journal_init_dev(struct block_device *bdev, + struct block_device *fs_dev, + unsigned long long start, int len, int bsize); +extern journal_t * jbd2_journal_init_inode (struct inode *); +extern int jbd2_journal_update_format (journal_t *); +extern int jbd2_journal_check_used_features + (journal_t *, unsigned long, unsigned long, unsigned long); +extern int jbd2_journal_check_available_features + (journal_t *, unsigned long, unsigned long, unsigned long); +extern int jbd2_journal_set_features + (journal_t *, unsigned long, unsigned long, unsigned long); +extern void jbd2_journal_clear_features + (journal_t *, unsigned long, unsigned long, unsigned long); +extern int jbd2_journal_load (journal_t *journal); +extern int jbd2_journal_destroy (journal_t *); +extern int jbd2_journal_recover (journal_t *journal); +extern int jbd2_journal_wipe (journal_t *, int); +extern int jbd2_journal_skip_recovery (journal_t *); +extern void jbd2_journal_update_sb_errno(journal_t *); +extern int jbd2_journal_update_sb_log_tail (journal_t *, tid_t, + unsigned long, int); +extern void __jbd2_journal_abort_hard (journal_t *); +extern void jbd2_journal_abort (journal_t *, int); +extern int jbd2_journal_errno (journal_t *); +extern void jbd2_journal_ack_err (journal_t *); +extern int jbd2_journal_clear_err (journal_t *); +extern int jbd2_journal_bmap(journal_t *, unsigned long, unsigned long long *); +extern int jbd2_journal_force_commit(journal_t *); +extern int jbd2_journal_force_commit_nested(journal_t *); +extern int jbd2_journal_inode_add_write(handle_t *handle, struct jbd2_inode *inode); +extern int jbd2_journal_inode_add_wait(handle_t *handle, struct jbd2_inode *inode); +extern int jbd2_journal_begin_ordered_truncate(journal_t *journal, + struct jbd2_inode *inode, loff_t new_size); +extern void jbd2_journal_init_jbd_inode(struct jbd2_inode *jinode, struct inode *inode); +extern void jbd2_journal_release_jbd_inode(journal_t *journal, struct jbd2_inode *jinode); + +/* + * journal_head management + */ +struct journal_head *jbd2_journal_add_journal_head(struct buffer_head *bh); +struct journal_head *jbd2_journal_grab_journal_head(struct buffer_head *bh); +void jbd2_journal_put_journal_head(struct journal_head *jh); + +/* + * handle management + */ +extern struct kmem_cache *jbd2_handle_cache; + +static inline handle_t *jbd2_alloc_handle(gfp_t gfp_flags) +{ + return kmem_cache_alloc(jbd2_handle_cache, gfp_flags); +} + +static inline void jbd2_free_handle(handle_t *handle) +{ + kmem_cache_free(jbd2_handle_cache, handle); +} + +/* + * jbd2_inode management (optional, for those file systems that want to use + * dynamically allocated jbd2_inode structures) + */ +extern struct kmem_cache *jbd2_inode_cache; + +static inline struct jbd2_inode *jbd2_alloc_inode(gfp_t gfp_flags) +{ + return kmem_cache_alloc(jbd2_inode_cache, gfp_flags); +} + +static inline void jbd2_free_inode(struct jbd2_inode *jinode) +{ + kmem_cache_free(jbd2_inode_cache, jinode); +} + +/* Primary revoke support */ +#define JOURNAL_REVOKE_DEFAULT_HASH 256 +extern int jbd2_journal_init_revoke(journal_t *, int); +extern void jbd2_journal_destroy_revoke_caches(void); +extern int jbd2_journal_init_revoke_caches(void); + +extern void jbd2_journal_destroy_revoke(journal_t *); +extern int jbd2_journal_revoke (handle_t *, unsigned long long, struct buffer_head *); +extern int jbd2_journal_cancel_revoke(handle_t *, struct journal_head *); +extern void jbd2_journal_write_revoke_records(transaction_t *transaction, + struct list_head *log_bufs); + +/* Recovery revoke support */ +extern int jbd2_journal_set_revoke(journal_t *, unsigned long long, tid_t); +extern int jbd2_journal_test_revoke(journal_t *, unsigned long long, tid_t); +extern void jbd2_journal_clear_revoke(journal_t *); +extern void jbd2_journal_switch_revoke_table(journal_t *journal); +extern void jbd2_clear_buffer_revoked_flags(journal_t *journal); + +/* + * The log thread user interface: + * + * Request space in the current transaction, and force transaction commit + * transitions on demand. + */ + +int jbd2_log_start_commit(journal_t *journal, tid_t tid); +int __jbd2_log_start_commit(journal_t *journal, tid_t tid); +int jbd2_journal_start_commit(journal_t *journal, tid_t *tid); +int jbd2_log_wait_commit(journal_t *journal, tid_t tid); +int jbd2_transaction_committed(journal_t *journal, tid_t tid); +int jbd2_complete_transaction(journal_t *journal, tid_t tid); +int jbd2_log_do_checkpoint(journal_t *journal); +int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid); + +void __jbd2_log_wait_for_space(journal_t *journal); +extern void __jbd2_journal_drop_transaction(journal_t *, transaction_t *); +extern int jbd2_cleanup_journal_tail(journal_t *); + +/* + * is_journal_abort + * + * Simple test wrapper function to test the JBD2_ABORT state flag. This + * bit, when set, indicates that we have had a fatal error somewhere, + * either inside the journaling layer or indicated to us by the client + * (eg. ext3), and that we and should not commit any further + * transactions. + */ + +static inline int is_journal_aborted(journal_t *journal) +{ + return journal->j_flags & JBD2_ABORT; +} + +static inline int is_handle_aborted(handle_t *handle) +{ + if (handle->h_aborted || !handle->h_transaction) + return 1; + return is_journal_aborted(handle->h_transaction->t_journal); +} + +static inline void jbd2_journal_abort_handle(handle_t *handle) +{ + handle->h_aborted = 1; +} + +#endif /* __KERNEL__ */ + +/* Comparison functions for transaction IDs: perform comparisons using + * modulo arithmetic so that they work over sequence number wraps. */ + +static inline int tid_gt(tid_t x, tid_t y) +{ + int difference = (x - y); + return (difference > 0); +} + +static inline int tid_geq(tid_t x, tid_t y) +{ + int difference = (x - y); + return (difference >= 0); +} + +extern int jbd2_journal_blocks_per_page(struct inode *inode); +extern size_t journal_tag_bytes(journal_t *journal); + +static inline bool jbd2_journal_has_csum_v2or3_feature(journal_t *j) +{ + return jbd2_has_feature_csum2(j) || jbd2_has_feature_csum3(j); +} + +static inline int jbd2_journal_has_csum_v2or3(journal_t *journal) +{ + WARN_ON_ONCE(jbd2_journal_has_csum_v2or3_feature(journal) && + journal->j_chksum_driver == NULL); + + return journal->j_chksum_driver != NULL; +} + +/* + * We reserve t_outstanding_credits >> JBD2_CONTROL_BLOCKS_SHIFT for + * transaction control blocks. + */ +#define JBD2_CONTROL_BLOCKS_SHIFT 5 + +/* + * Return the minimum number of blocks which must be free in the journal + * before a new transaction may be started. Must be called under j_state_lock. + */ +static inline int jbd2_space_needed(journal_t *journal) +{ + int nblocks = journal->j_max_transaction_buffers; + return nblocks + (nblocks >> JBD2_CONTROL_BLOCKS_SHIFT); +} + +/* + * Return number of free blocks in the log. Must be called under j_state_lock. + */ +static inline unsigned long jbd2_log_space_left(journal_t *journal) +{ + /* Allow for rounding errors */ + unsigned long free = journal->j_free - 32; + + if (journal->j_committing_transaction) { + unsigned long committing = atomic_read(&journal-> + j_committing_transaction->t_outstanding_credits); + + /* Transaction + control blocks */ + free -= committing + (committing >> JBD2_CONTROL_BLOCKS_SHIFT); + } + return free; +} + +/* + * Definitions which augment the buffer_head layer + */ + +/* journaling buffer types */ +#define BJ_None 0 /* Not journaled */ +#define BJ_Metadata 1 /* Normal journaled metadata */ +#define BJ_Forget 2 /* Buffer superseded by this transaction */ +#define BJ_Shadow 3 /* Buffer contents being shadowed to the log */ +#define BJ_Reserved 4 /* Buffer is reserved for access by journal */ +#define BJ_Types 5 + +extern int jbd_blocks_per_page(struct inode *inode); + +/* JBD uses a CRC32 checksum */ +#define JBD_MAX_CHECKSUM_SIZE 4 + +#if 0 +static inline u32 jbd2_chksum(journal_t *journal, u32 crc, + const void *address, unsigned int length) +{ + struct { + struct shash_desc shash; + char ctx[JBD_MAX_CHECKSUM_SIZE]; + } desc; + int err; + + BUG_ON(crypto_shash_descsize(journal->j_chksum_driver) > + JBD_MAX_CHECKSUM_SIZE); + + desc.shash.tfm = journal->j_chksum_driver; + desc.shash.flags = 0; + *(u32 *)desc.ctx = crc; + + err = crypto_shash_update(&desc.shash, address, length); + BUG_ON(err); + + return *(u32 *)desc.ctx; +} +#endif + +/* Return most recent uncommitted transaction */ +static inline tid_t jbd2_get_latest_transaction(journal_t *journal) +{ + tid_t tid; + + //read_lock(&journal->j_state_lock); + tid = journal->j_commit_request; + if (journal->j_running_transaction) + tid = journal->j_running_transaction->t_tid; + //read_unlock(&journal->j_state_lock); + return tid; +} + +#ifdef __KERNEL__ + +#define buffer_trace_init(bh) do {} while (0) +#define print_buffer_fields(bh) do {} while (0) +#define print_buffer_trace(bh) do {} while (0) +#define BUFFER_TRACE(bh, info) do {} while (0) +#define BUFFER_TRACE2(bh, bh2, info) do {} while (0) +#define JBUFFER_TRACE(jh, info) do {} while (0) + +#endif /* __KERNEL__ */ + +#define EFSBADCRC EBADMSG /* Bad CRC detected */ +#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ + +#endif /* _LINUX_JBD2_H */ diff --git a/README.md b/README.md index 2daccf3..7a6145f 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ About and Visual Studio 2019. This is work in progress. If you need a stable driver you should get the latest official release from http://www.ext2fsd.com. If you want to try this branch you should still install the oficial release and then copy this driver over the old in \windows\system32\drivers. + The current status of the development is that metadata checksums is implemented but there is an + calculation error in the inode checksums that must be investigated before I start with jbd2. Bo Branten.