1570 lines
37 KiB
C
1570 lines
37 KiB
C
/*++
|
||
|
||
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(®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
|
||
);
|