NT4/private/ntos/dd/ntft/ftdisk.h
2020-09-30 17:12:29 +02:00

1570 lines
37 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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 <ntdskreg.h>
#include <ntddft.h>
#include <ntdddisk.h>
#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(&REGION->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(&REGION->SpinLock, \
&irql); \
REGION->Active = FALSE; \
KeReleaseSpinLock(&REGION->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(&REGION->SpinLock, \
&irql); \
REGION->Active = TRUE; \
KeReleaseSpinLock(&REGION->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)&REGION->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( \
&REGION->WaitingIrpChain, \
&REGION->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
);