/*++ Copyright (c) 1991-4 Microsoft Corporation Module Name: ftdisk.h Abstract: These are the structures that FtDisk driver uses to support IO to NTFT volumes. Author: Bob Rinne (bobri) 2-Feb-1992 Mike Glass (mglass) Notes: Revision History: --*/ #include "stdio.h" #include #include #include #include "ftlog.h" #if DBG extern ULONG FtDebug; #endif #ifdef POOL_TAGGING #undef ExAllocatePool #undef ExAllocatePoolWithQuota #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'tFtN') #define ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,'tFtN') #endif // // Define empty structure for RCB so it can be referenced before // it is defined. // struct _RCB; // // Short hand definition for passing the FtRoot device extension through // the system worker thread to the FtThread code. The device controls // passed through the system worker thread do not get any data returned // to the caller. Therefore the OutputBufferLength field of the irp stack // can be used to pass the root device extension. // #define FtRootExtensionPtr Parameters.DeviceIoControl.OutputBufferLength // // Short hand definitions for state information stored in the Irp stack // location of the original (or master) Irp. // #define FtOrgIrpCount Parameters.Others.Argument1 #define FtOrgIrpPrimaryExtension Parameters.Others.Argument2 #define FtOrgIrpWaitingRegen Parameters.Others.Argument3 #define FtOrgIrpNextIrp Parameters.Others.Argument4 // // Short hand definitions for state information stored in the stack // reserved for FT use in Irps allocated for lower-level drivers. // #define FtLowIrpRegenerateRegionLocale Parameters.Others.Argument2 #define FtLowIrpAllocatedMdl Parameters.Others.Argument3 #define FtLowIrpMasterIrp Parameters.Others.Argument4 // // Delays for allocation problems. NOTE: These are WAGs! // These delays are used in the FT thread context for allocating Irps // and buffers. // #define IRP_DELAY 1000 #define BUFFER_DELAY 10000 // // Macros for managing I/O queue lengths on extensions. // #define DECREMENT_QUEUELENGTH(EXTENSION) InterlockedDecrement( \ (PLONG)&EXTENSION->QueueLength) #define INCREMENT_QUEUELENGTH(EXTENSION) InterlockedIncrement( \ (PLONG)&EXTENSION->QueueLength) // // Bad sector completion handler prototype. // typedef NTSTATUS (*PFT_BAD_SECTOR_ROUTINE) ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); // // Indicator of controller type. // typedef enum _FT_ADAPTOR_TYPE { Scsi, Esdi, Ide, Other } FT_ADAPTOR_TYPE, *PFT_ADAPTOR_TYPE; // // Indicator of member type. // NOTE: This is not in the enum for FT_TYPE. // #define FtRoot (-1) // // Active read policy for the mirror or stripe. // typedef UCHAR FT_READ_POLICY; #define ReadPrimary 0 #define ReadBackUp 1 #define ReadBoth 2 // // Control over writes. // typedef UCHAR FT_WRITE_POLICY; #define Sequential 0 #define Parallel 1 // // Object identification. This is used to identify device // object referenced by this element location in the device extension. // typedef struct _FT_DEVICE_IDENTITY { FT_ADAPTOR_TYPE Adaptor; UCHAR PartitionType; ULONG BusId; // // The logical disk and partition number - filled in during initialization. // ULONG DiskNumber; ULONG PartitionNumber; // // Drive signature returned when the partition table is read. // ULONG Signature; // // A stored copy of the drive geometry. // DISK_GEOMETRY DiskGeometry; // // Saved information about the partition. // LARGE_INTEGER PartitionOffset; LARGE_INTEGER PartitionLength; LARGE_INTEGER PartitionEnd; LARGE_INTEGER OriginalLength; ULONG OriginalHidden; ULONG HiddenSectors; } FT_DEVICE_IDENTITY, *PFT_DEVICE_IDENTITY; // // Thread sychronization structure. // typedef struct _FT_THREAD_DESCRIPTION { HANDLE Handle; // Thread handle. PVOID Object; // Thread object. KSEMAPHORE Semaphore; // Semaphore for request list access. KSPIN_LOCK SpinLock; // Spin lock to protect request list. LIST_ENTRY List; // List of requests for FT thread. KEVENT Event; // Synchronization event for I/O. } FT_THREAD_DESCRIPTION, *PFT_THREAD_DESCRIPTION; typedef enum _FT_REGENERATE_LOCATION { BeforeRegenerateRegion, InRegenerateRegion, AfterRegenerateRegion } FT_REGENERATE_LOCATION, *PFT_REGENERATE_LOCATION; // // A lock region is an area of a partition that is locked from all I/O. // typedef struct _FT_REGENERATE_REGION { // // NOTE: Must have a MUTEX in the lock region for removal. // KSPIN_LOCK SpinLock; LIST_ENTRY WaitingIrpChain; ULONG RowNumber; BOOLEAN Active; } FT_REGENERATE_REGION, *PFT_REGENERATE_REGION; // // Macros for working with the registry. // // // PDISK_PARTITION // FtpFindPartitionRegistry( // IN PDISK_CONFIG_HEADER Registry, // IN PFT_MEMBER_DESCRIPTION FtMember // ) // // Routine Description: // // This routine locates a partition description in the registry information. // // Arguments: // // Registry - pointer to the configuration information from the registry. // FtMember - pointer to the FT member configuration located in the registry. // // Return Value: // // A pointer to the disk partition description in the registry. // #define FtpFindPartitionRegistry(REGSTART, MEMBER) \ (PDISK_PARTITION) ((PUCHAR)REGSTART + MEMBER->OffsetToPartitionInfo) // // Macros for manipulating the lock region. // // // VOID // InitializeRegenerateRegion( // IN PDEVICE_EXTENSION EXTENSION, // IN PFT_REGENERATE_REGION REGION // ) // // Routine Description: // // This macro initializes the regeneration region for the FT component. // // Arguments: // // EXTENSION - The device extension to be initialized. // REGION - The regeneration region for the device extension. // // Return Values: // // None. // #define InitializeRegenerateRegion(EXTENSION, REGION) \ { \ REGION->RowNumber = 0; \ REGION->Active = FALSE; \ InitializeListHead(®ION->WaitingIrpChain); \ } // // VOID // CheckForRegenerateRegion( // IN PDEVICE_EXTENSION EXTENSION, // IN BOOLEAN RESULT, // IN KIRQL IRQL // ) // // Routine Description: // // This macro determines if the regeneration region is active for the // FT component. If it is the RESULT value is set to indicate this. // This is a macro, so the actual BOOLEAN value is passed in not a pointer // to the value. // // Arguments: // // EXTENSION - the device extension in question. // RESULT - the actual BOOLEAN name for the result. // IRQL - the kernel IRQL for holding the spinlock. // // Return Values: // // None. // #define CheckForRegenerateRegion(EXTENSION, RESULT, IRQL) \ { \ KeAcquireSpinLock(&EXTENSION->RegenerateRegionForGroup->SpinLock, \ &IRQL); \ RESULT = EXTENSION->RegenerateRegionForGroup->Active; \ } // // VOID // AcquireRegenerateRegionCheck( // IN PDEVICE_EXTENSION EXTENSION, // IN KIRQL IRQL // ) // // Routine Description: // // This routine acquires the regeneration region for the FT component. // // Arguments: // // EXTENSION - the device extension for the FT component. // IRQL - the kernel IRQL for holding the spinlock. // // Return Values: // // None. // #define AcquireRegenerateRegionCheck(EXTENSION, IRQL) \ KeAcquireSpinLock(&EXTENSION->RegenerateRegionForGroup->SpinLock, \ &IRQL) // // VOID // ReleaseRegenerateRegionCheck( // IN PDEVICE_EXTENSION EXTENSION, // IN KIRQL IRQL // ) // // Routine Description: // // This macro releases the regeneration region for other use. The // regeneration region must have first been acquired via a call to // AcquireRegenerateRegionCheck(). // // Arguments: // // EXTENSION - the device extension for the FT component. // IRQL - the kernel IRQL for holding the spinlock. // // Return Values: // // None. // #define ReleaseRegenerateRegionCheck(EXTENSION, IRQL) \ KeReleaseSpinLock(&EXTENSION->RegenerateRegionForGroup->SpinLock, \ IRQL) // // VOID // DeactivateRegenerateRegion( // IN PFT_REGENERATE_REGION REGION // ) // // Routine Description: // // This macro turns off the function of the regeneration region. // // Arguments: // // REGION - the regeneration region to deactivate. // // Return Values: // // None. // #define DeactivateRegenerateRegion(REGION) \ { \ KIRQL irql; \ \ KeAcquireSpinLock(®ION->SpinLock, \ &irql); \ REGION->Active = FALSE; \ KeReleaseSpinLock(®ION->SpinLock, \ irql); \ } // // VOID // ActivateRegenerateRegion( // IN PFT_REGENERATE_REGION REGION // ) // // Routine Description: // // This macro turns on the function of the regeneration region. // // Arguments: // // REGION - the regeneration region to activate. // // Return Values: // // None. // #define ActivateRegenerateRegion(REGION) \ { \ KIRQL irql; \ \ KeAcquireSpinLock(®ION->SpinLock, \ &irql); \ REGION->Active = TRUE; \ KeReleaseSpinLock(®ION->SpinLock, \ irql); \ } // // VOID // LockNextRegion( // IN PFT_REGENERATE_REGION REGION // ) // // Routine Description: // // This macro increments the row for the regeneration region. // // Arguments: // // REGION - the region to increment. // // Return Values: // // None. // #define LockNextRegion(REGION) \ InterlockedIncrement( \ (PLONG)®ION->RowNumber) // // VOID // QueueIrpToThread( // IN PDEVICE_EXTENSION EXTENSION, // IN PIRP IRP // ) // // Routine Description: // // This macro queues an Irp to the regeneration thread for later // processing when the regeneration region is now longer the area // of the disk where this Irp is intended. // // Arguments: // // EXTENSION - a pointer to the device extension of the FT component. // IRP - the Irp to queue. // // Return Values: // // None. // #define QueueIrpToThread(EXTENSION, IRP) \ InsertTailList( \ &EXTENSION->RegenerateRegionForGroup->WaitingIrpChain, \ &IRP->Tail.Overlay.ListEntry); // // VOID // ThreadDequeueIrp( // IN PFT_REGENERATE_REGION REGION, // IN PIRP IRPPTR // ) // // Routine Description: // // This macro is used by the regeneration thread to obtain Irps that // have been queued for the thread to process once the regeneration // region has moved. The macro will return NULL if there are no more // Irps to process. // // Arguments: // // REGION - The regeneration region in use. // IRPPTR - a pointer to an IRP pointer. // // Return Values: // // None. // #define ThreadDequeueIrp(REGION, IRPPTR) \ { \ PLIST_ENTRY listEntry; \ \ listEntry = ExInterlockedRemoveHeadList( \ ®ION->WaitingIrpChain, \ ®ION->SpinLock); \ if (listEntry == NULL) { \ IRPPTR = NULL; \ } else { \ IRPPTR = CONTAINING_RECORD(listEntry, IRP, \ Tail.Overlay.ListEntry); \ } \ } // // Recovery thread support macros. // #define FT_THREAD_RECOVERY 0x00 #define FT_THREAD_RESTART 0x01 #define MAXIMUM_STRIPE_RECOVERY_THREAD_COUNT 0x04 // // VOID // FtpQueueIrpToRecoveryThread( // IN PDEVICE_EXTENSION EXTENSION, // IN PIRP IRP, // IN PVOID CONTEXT // ) // // Routine Description: // // This macro inserts the provided Irp on the queue of Irps to be processed // by the recovery thread. After the Irp has been inserted, the thread will // be set to the running state via the thread semaphore. // // Arguments: // // EXTENSION - a pointer to any FT device extension. This is used to locate // the FtRoot extension for queueing the Irp. // IRP - a pointer to the failing request to start recovery. // CONTEXT - a pointer to context information to be passed to the // recovery handling routine. // // Return Values: // // None. // #define FtpQueueIrpToRecoveryThread(EXTENSION, INIRP, CONTEXT) { \ PFT_THREAD_DESCRIPTION ftThread; \ PIO_STACK_LOCATION nextStack; \ ftThread = &((PDEVICE_EXTENSION) \ (EXTENSION->ObjectUnion.FtRootObject->DeviceExtension))->FtUnion.Thread;\ DebugPrint((2, "FtpQueueIrpToRecoveryThread: Irp %x Context %x\n", \ INIRP, CONTEXT)); \ nextStack = IoGetNextIrpStackLocation(INIRP); \ nextStack->Context = (PVOID) CONTEXT; \ nextStack->DeviceObject = (PDEVICE_OBJECT) EXTENSION; \ (VOID)ExInterlockedInsertTailList(&ftThread->List, \ &INIRP->Tail.Overlay.ListEntry, \ &ftThread->SpinLock); \ (VOID) KeReleaseSemaphore(&ftThread->Semaphore, \ (KPRIORITY) 0, \ 1, \ FALSE); \ } // // VOID // FtpQueueRcbToRecoveryThread( // IN PDEVICE_EXTENSION EXTENSION, // IN PRCB INRCB // ) // // Routine Description: // // This macro inserts the provided Rcb on the queue of Rcbs to be processed // by the recovery thread. After the RCB has been inserted, the thread will // be set to the running state via the thread semaphore. // // Arguments: // // EXTENSION - a pointer to any FT device extension. This is used to locate // the FtRoot extension for queueing the Irp. // INRCB - a pointer to the RCB of the failing request to start recovery. // // Return Values: // // None. // #define FtpQueueRcbToRecoveryThread(EXTENSION, INRCB) { \ PFT_THREAD_DESCRIPTION ftThread; \ ftThread = &((PDEVICE_EXTENSION) \ (EXTENSION->ObjectUnion.FtRootObject->DeviceExtension))->FtUnion.Thread;\ (VOID)ExInterlockedInsertTailList(&ftThread->List, \ &INRCB->ListEntry, \ &ftThread->SpinLock); \ (VOID) KeReleaseSemaphore(&ftThread->Semaphore, \ (KPRIORITY) 0, \ 1, \ FALSE); \ } #define FtpQueueRcbToRestartThread(EXTENSION, RCB) { \ PFT_THREAD_DESCRIPTION ftThread; \ ftThread = \ &((PDEVICE_EXTENSION)EXTENSION-> \ ObjectUnion.FtRootObject->DeviceExtension)->RestartThread; \ ExInterlockedInsertTailList(&ftThread->List, \ &RCB->ListEntry, \ &ftThread->SpinLock); \ KeReleaseSemaphore(&ftThread->Semaphore, \ (KPRIORITY) 0, \ 1, \ FALSE); \ } // // VOID // FtpFreeIrp( // IN PIRP IRP // ) // // Routine Description: // // This macro frees the irp. In a debug build it verifies the stack // is set to the FT stack to catch frees of irps in process. // // Arguments: // // IRP - pointer to irp to free. // // Return Values: // // None. // #define FtpFreeIrp(IRP) \ ASSERT(IRP->CurrentLocation == IRP->StackCount); \ IoFreeIrp(IRP) // // Description information for mirror or stripe // // // Device Extension // typedef struct _DEVICE_EXTENSION { PDEVICE_OBJECT DeviceObject; // back pointer to the FT device object union { PDEVICE_OBJECT FtRootObject; // Locates the FT base object PDRIVER_OBJECT FtDriverObject; // Locates the FT driver object only // in the FtRoot extension itself. } ObjectUnion; PDEVICE_OBJECT TargetObject; // Real device object for partition // // Chain pointer to next FT device extension for the next disk. // struct _DEVICE_EXTENSION *DiskChain; // // Points to partition 0 for the disk containing this partition. // struct _DEVICE_EXTENSION *WholeDisk; // // This points to the next entry in the chain of partitions on a disk. // struct _DEVICE_EXTENSION *ProtectChain; // // Locates the next member for an FT component. // struct _DEVICE_EXTENSION *NextMember; // // The first healthy member in an FT set. // struct _DEVICE_EXTENSION *ZeroMember; // // See bit definitions below. // ULONG Flags; // // Collection of items that uniquely indicate each partitions role // within the NTFT system. // FT_TYPE Type; // Mirror, Stripe or physical disk? USHORT FtGroup; // Ordinal number from config registry. USHORT MemberRole; // Location in FT component. FT_READ_POLICY ReadPolicy; // Current read operation policy. FT_WRITE_POLICY WritePolicy; // Current write operation policy. BOOLEAN IgnoreReadPolicy; // registry override for balanced read. FT_STATE VolumeState; // General state of the set. FT_PARTITION_STATE MemberState; // State of member. union { FT_DEVICE_IDENTITY Identity;// Physical location identity. FT_THREAD_DESCRIPTION Thread; // Thread information. } FtUnion; // // For the FtRoot element, this is the count of disks in the // system. For FT components this is the count of members (i.e. // 2 for mirrors). // union { ULONG NumberOfMembers; ULONG NumberOfDisks; } FtCount; // // The lock region is used to protect an area of a mirror while the // primary data is being copied to the secondary. // PFT_REGENERATE_REGION RegenerateRegionForGroup; FT_REGENERATE_REGION RegenerateRegion; // // The work queue is used to pass FT_COPY or Orphan requests through // the system worker to FT code that will operate under the system // worker thread. // BOOLEAN WorkItemBusy; KSPIN_LOCK WorkItemSpinLock; WORK_QUEUE_ITEM WorkItem; // // Spinlock controlling count of outstanding IRPs. // KSPIN_LOCK IrpCountSpinLock; // // Io queue counts for extension. // ULONG QueueLength; KSPIN_LOCK QueueLengthSpinLock; // // Lookaside list for stripe control packets. // NPAGED_LOOKASIDE_LIST RcbLookasideListHead; // // Emergency buffers for StripeWithParity writes. // PVOID ParityBuffers; KSPIN_LOCK ParityBufferLock; // // Queue for RCBs waiting on buffers. // struct _RCB *WaitingOnBuffer; // // Restart IO waiting on buffers thread // FT_THREAD_DESCRIPTION RestartThread; // Thread information. // // Root of B-Tree for region locking // struct _RCB *LockTree; // // Spinlock for B-Tree // KSPIN_LOCK TreeSpinLock; // // Stripe recovery thread count and list. // ULONG StripeThreadCount; KSPIN_LOCK StripeThreadSpinLock; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; #define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION) // // In the Ft root extension, the ProtectChain is used to keep extensions // for any missing members created for mirrors and parity stripes. // #define MissingMemberChain ProtectChain // // Defininition of flag bits in FtRootExtension // #define FTF_MISSING_MEMBER 0x00000002 #define FTF_NO_SECTOR_MAPPING 0x00000004 #define FTF_EMERGENCY_BUFFER_IN_USE 0x00000008 #define FTF_CLEAN_SHUTDOWN 0x00000010 #define FTF_RCB_LOOKASIDE_ALLOCATED 0x00000020 #define FTF_RESTART_THREAD_STARTED 0x00000040 #define FTF_RECOVERY_THREAD_STARTED 0x00000080 #define FTF_EMERGENCY_BUFFER_ALLOCATED 0x00000100 #define FTF_SYNCHRONIZATION_FAILED 0x00000200 // // Definition of flag bits in ZeroMember // #define FTF_REGENERATION_REGION_INITIALIZED 0x00000400 // // Definition of flag bits in member extensions // #define FTF_CONFIGURATION_CHANGED 0x00000800 // // VOID // IsMemberAnOrphan( // IN PDEVICE_EXTENSION EXTENSION // ) // // Routine Description: // // This macro detemines if the member has been orphaned. // // Arguments: // // EXTENSION - the device extension in question. // // Return Values: // // TRUE - if member is not healthy // FALSE - if member is ready for use // #define IsMemberAnOrphan(EXTENSION) ((EXTENSION)->MemberState == Orphaned) // // BOOLEAN // IsSectorError( // IN NTSTATUS Status // ) // // Routine Description: // // Returns TRUE if status is a sector error // that can be corrected. // // #define IsSectorError(STATUS) (STATUS == STATUS_DEVICE_DATA_ERROR || \ STATUS == STATUS_CRC_ERROR) // // VOID // MarkMemberAsOrphan( // IN PDEVICE_EXTENSION EXTENSION // ) // // Routine Description: // // This macro marks the device extension as an orphan. // // Arguments: // // EXTENSION - the device extension in question. // // Return Values: // // None. // #define MarkMemberAsOrphan(EXTENSION) { \ PDEVICE_EXTENSION zeroMember = EXTENSION->ZeroMember; \ if (zeroMember->VolumeState == FtStateOk) { \ zeroMember->VolumeState = FtHasOrphan; \ } \ (EXTENSION)->MemberState = Orphaned; \ } // // VOID // MarkSetAsDisabled( // IN PDEVICE_EXTENSION EXTENSION // ) // // Routine Description: // // This routine will completely disable an FT set. // // Arguments: // // EXTENSION - the device extension for the zero member. // // Return Values: // // None. // #define MarkSetAsDisabled(EXTENSION) { \ EXTENSION->VolumeState = FtDisabled; \ } typedef VOID (*PSTRIPE_START_ROUTINE) ( IN struct _RCB *Rcb ); // // Constants for stripes. // #define STRIPE_SIZE ((ULONG) 0x00010000) #define STRIPE_SHIFT 16 #define STRIPE_OFFSET(X) (X & (STRIPE_SIZE -1)) // // Constants for stripes with parity. // #define FT_PARITY_BUFFER_LIMIT 0x00111000 #define RCB_TYPE 0x4d47 // // Request Control Block // typedef struct _RCB { CSHORT Type; // 00 USHORT Size; // 02 struct _RCB *Link; // 04 struct _RCB *Left; // 08 struct _RCB *Right; // 0C struct _RCB *Middle; // 10 PIRP OriginalIrp; // 14 PDEVICE_EXTENSION ZeroExtension; // 18 PDEVICE_EXTENSION MemberExtension; // 1C PULONG IrpCount; // 20 ULONG NumberOfMembers; // 24 ULONG WhichStripe; // 28 ULONG WhichRow; // 2C ULONG WhichMember; // 30 ULONG ParityStripe; // 34 LIST_ENTRY ListEntry; // 38 ULONG RequestLength; // 40 PDEVICE_OBJECT TargetObject; // 44 PIRP PrimaryIrp; // 48 PIRP SecondaryIrp; // 4C PVOID ReadBuffer; // 50 PVOID WriteBuffer; // 54 PVOID SystemBuffer; // 58 PVOID VirtualBuffer; // 5C struct _RCB *PreviousRcb; // 60 struct _RCB *OtherRcb; // 64 IO_STATUS_BLOCK IoStatus; // 68 LARGE_INTEGER RequestOffset; // 70 PIO_COMPLETION_ROUTINE CompletionRoutine; PSTRIPE_START_ROUTINE StartRoutine; // 7C UCHAR MajorFunction; // 80 UCHAR Pad; // 81 USHORT Flags; // 82 } RCB, *PRCB; // // RCB flag bit definitions // #define RCB_FLAGS_RECOVERY_ATTEMPTED 0x0001 #define RCB_FLAGS_PARITY_REQUEST 0x0002 #define RCB_FLAGS_SPARE_UNUSED 0x0004 #define RCB_FLAGS_EMERGENCY_BUFFERS 0x0008 #define RCB_FLAGS_REGENERATION_ACTIVE 0x0010 #define RCB_FLAGS_KEEP_RCB_ALIGNED 0x0020 #define RCB_FLAGS_SECOND_PHASE 0x0040 #define RCB_FLAGS_ACTIVE 0x0080 #define RCB_FLAGS_WAIT_FOR_BUFFERS 0x0100 #define RCB_FLAGS_WRITE_BUFFER_MAPPED 0x0200 #define RCB_FLAGS_ORPHAN 0x0400 #define RCB_FLAGS_WAIT_FOR_REGION 0x0800 // // Location control enumeration. This enum is used internally in the FT // driver when the file systems make a read primary or read secondary request. // typedef enum _FT_DATA_LOCALE { FromPrimary, FromSecondary } FT_DATA_LOCALE, *PFT_DATA_LOCALE; // // This structure is used to pass context information in servicing the // FT_SYNC_REDUNDANT_COPY device control. // typedef struct _FT_SYNC_CONTEXT { FT_SYNC_INFORMATION SyncInfo; PDEVICE_EXTENSION DeviceExtension; ULONG IoctlCode; PIRP Irp; } FT_SYNC_CONTEXT, *PFT_SYNC_CONTEXT; // // Procedure prototypes. // #if DBG #define FT_NUMBER_OF_IRP_LOG_ENTRIES 70 typedef struct _IRP_LOG { ULONG InUse; PVOID Context; PIRP Irp; PIRP AssociatedIrp; } IRP_LOG, *PIRP_LOG; VOID FtDebugPrint( ULONG DebugPrintLevel, PCCHAR DebugMessage, ... ); #define DebugPrint(X) FtDebugPrint X #else #define DebugPrint(X) #endif // DBG // // The following routines are general purpose routines for the fault tolerance // driver and may only be called under a thread context. // VOID FtRecoveryThread( IN PDEVICE_EXTENSION FtRootExtension ); VOID FtRestartThread( IN PDEVICE_EXTENSION FtRootExtension ); VOID FtThreadProcessIrp( IN PIRP Irp ); VOID FtThreadSynchronize( IN PVOID Context ); NTSTATUS FtThreadStartNewThread( IN PDEVICE_EXTENSION DeviceExtension, IN ULONG IoctlCode, IN PIRP Irp ); VOID FtThreadVerifyMirror( IN PDEVICE_EXTENSION DeviceExtension ); NTSTATUS FtThreadVerifyStripe( IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp ); NTSTATUS FtCreateThread( IN PDEVICE_EXTENSION DeviceExtension, IN PFT_THREAD_DESCRIPTION FtThread, IN PKSTART_ROUTINE ThreadRoutine ); VOID FtThreadMirrorRecovery( IN PDEVICE_EXTENSION DeviceExtension, IN PIRP FailingIrp, IN PVOID Context ); VOID FtThreadStripeRecovery( IN PRCB Rcb ); PUCHAR FtThreadAllocateBuffer( IN OUT PULONG DesiredSize, IN BOOLEAN SizeRequired ); NTSTATUS FtThreadReadWriteSectors( IN UCHAR MajorFunction, IN PDEVICE_EXTENSION DeviceExtension, IN PVOID Buffer, IN PLARGE_INTEGER ByteOffset, IN ULONG Length ); NTSTATUS FtThreadFindFailingSector( IN UCHAR MajorFunction, IN PDEVICE_EXTENSION DeviceExtension, IN PVOID Buffer, IN PLARGE_INTEGER ByteOffset, IN ULONG Length, IN OUT PULONG FailingOffset ); BOOLEAN FtThreadMapBadSector( IN PDEVICE_EXTENSION DeviceExtension, IN PLARGE_INTEGER ByteOffset ); VOID FtThreadSetVerifyState( IN PDEVICE_EXTENSION DeviceExtension, IN BOOLEAN State ); // // The following are general purpose routines for the fault tolerance driver. // #if DBG VOID FtpCompleteRequest( IN PIRP Irp, IN CCHAR Boost ); VOID FtpRecordIrp( IN PIRP Irp ); VOID FtpInitializeIrpLog(); #else #define FtpCompleteRequest(IRP, BOOST) IoCompleteRequest(IRP, BOOST); #endif VOID FtpLogError( IN PDEVICE_EXTENSION DeviceExtension, IN NTSTATUS SpecificIoStatus, IN NTSTATUS FinalStatus, IN ULONG UniqueErrorValue, IN PIRP Irp ); NTSTATUS FtpAttach( IN PDRIVER_OBJECT DriverObject, IN PUCHAR AttachName, IN PUCHAR DeviceName, IN OUT PDEVICE_EXTENSION *DeviceExtension ); NTSTATUS FtpGetPartitionInformation( IN PUCHAR DeviceName, IN OUT PDRIVE_LAYOUT_INFORMATION *DriveLayout, OUT PDISK_GEOMETRY DiskGeometryPtr ); NTSTATUS FtpReturnRegistryInformation( IN PUCHAR ValueName, IN OUT PVOID *FreePoolAddress, IN OUT PVOID *Information ); NTSTATUS FtpWriteRegistryInformation( IN PUCHAR ValueName, IN PVOID Information, IN ULONG InformationLength ); VOID FtpConfigure( IN PDEVICE_EXTENSION FtRootExtension, IN BOOLEAN MaintenanceMode ); PIRP FtpDuplicateIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP InIrp ); PIRP FtpDuplicatePartialIrp( IN PDEVICE_OBJECT FtObject, IN PIRP InIrp, IN PVOID VirtualAddress, IN LARGE_INTEGER ByteOffset, IN ULONG Length ); PDEVICE_EXTENSION FtpFindDeviceExtension( IN PDEVICE_EXTENSION FtRootExtension, IN ULONG Signature, IN LARGE_INTEGER StartingOffset, IN LARGE_INTEGER Length ); VOID FtpChangeMemberStateInRegistry( IN PDEVICE_EXTENSION DeviceExtension, IN FT_PARTITION_STATE NewState ); VOID FtDiskFindDisks( PDRIVER_OBJECT DriverObject, PVOID FtRootDevice, ULONG Count ); PDEVICE_OBJECT FtpGetTargetObject( IN PDEVICE_EXTENSION DeviceExtension, IN ULONG MemberRole ); PIRP FtpBuildRequest( IN PDEVICE_OBJECT DeviceObject, IN PLARGE_INTEGER StartingOffset, IN ULONG TransferCount, IN PVOID BufferAddress, IN UCHAR Flags, IN PETHREAD Thread, IN UCHAR Function ); VOID FtpVolumeLength( IN PDEVICE_EXTENSION DeviceExtension, IN PLARGE_INTEGER ResultLength ); PRCB FtpAllocateRcb( PDEVICE_EXTENSION DeviceExtension ); VOID FtpFreeRcb( PRCB Rcb ); VOID FtpInitializeRcbLookasideListHead( IN PDEVICE_EXTENSION FtRootExtension ); NTSTATUS FtpInitializeParityZone( IN PDEVICE_EXTENSION FtRootExtension ); FT_REGENERATE_LOCATION FtpRelationToRegenerateRegion( IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp ); // // Exposed routines for mirror support. // NTSTATUS MirrorReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); VOID MirrorSpecialRead( IN PIRP Irp ); NTSTATUS MirrorIoCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ); NTSTATUS MirrorVerify( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); VOID MirrorRecoveryThread( IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN PVOID Context ); VOID MirrorRecoverFailedIo( PDEVICE_EXTENSION DeviceExtension, PIRP FailingIrp, PVOID Context ); VOID MirrorDeviceFailure( IN PDEVICE_EXTENSION DeviceExtension, IN PIRP FailingIrp, IN PVOID Context ); // // Exposed routines for stripe support. // NTSTATUS StripeDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); VOID StripeReadWrite( IN PRCB Rcb ); VOID StripeSpecialRead( IN PIRP Irp ); VOID StripeWithParityWrite( IN PRCB Rcb ); VOID StripeVerify( IN PRCB Rcb ); NTSTATUS StripeIoCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ); NTSTATUS StripeWithParityIoCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ); NTSTATUS StripeReadFromSecondaryIoCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ); NTSTATUS StripeRecoverSectors( PDEVICE_EXTENSION DeviceExtension, PVOID ResultBuffer, PLARGE_INTEGER ByteOffset, ULONG NumberOfBytes, ULONG Member ); VOID StripeDeviceFailure( PDEVICE_EXTENSION DeviceExtension, PRCB Rcb ); VOID StripeRecoverFailedIo( PDEVICE_EXTENSION DeviceExtension, PRCB Rcb ); BOOLEAN StripeInsertRequest( IN PRCB Rcb ); PRCB StripeRemoveRequest( IN PRCB Rcb ); VOID StripeDebugDumpRcb( IN PRCB Rcb, IN ULONG DebugLevel ); VOID StripeInitializeParity( PDEVICE_EXTENSION DeviceExtension ); VOID StripeRegenerateParity( PDEVICE_EXTENSION DeviceExtension ); VOID StripeSynchronizeParity( IN PDEVICE_EXTENSION DeviceExtension, IN PFT_SYNC_INFORMATION SyncInfo ); VOID StripeSynchronizeRow( IN PRCB Rcb ); // // Exposed routines for Volume Set support. // NTSTATUS VolumeSetReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS VolumeSetIoCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ); NTSTATUS VolumeSetVerify( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); // // Function declarations called by the I/O system. // NTSTATUS FtDiskInitialize( IN PDRIVER_OBJECT DriverObject ); NTSTATUS FtDiskCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS FtDiskReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS FtDiskDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS FtDiskShutdownFlush( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS FtDiskIoCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ); NTSTATUS FtpDetachDevices( IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp ); NTSTATUS FtpAttachDevices( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ); VOID FtpFreeMdl( IN PMDL Mdl ); PDEVICE_EXTENSION FtpGetMemberDeviceExtension( IN PDEVICE_EXTENSION DeviceExtension, IN USHORT MemberNumber ); NTSTATUS FtpSpecialRead( IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN PLARGE_INTEGER Offset, IN ULONG Size, IN PIRP IrpToComplete ); VOID FtpOrphanMember( IN PDEVICE_EXTENSION DeviceExtension );