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

1998 lines
40 KiB
C++

/*++
Copyright (c) 1991-5 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)
Norbert Kusters 2-Feb-1995
Notes:
Revision History:
--*/
extern "C" {
#include "ntddk.h"
#include "stdio.h"
#include <ntdskreg.h>
#include <ntddft.h>
#include <ntdddisk.h>
#include "ftlog.h"
}
#if DBG
extern "C" {
VOID
FtDebugPrint(
ULONG DebugPrintLevel,
PCCHAR DebugMessage,
...
);
extern ULONG FtDebug;
}
#define DebugPrint(X) FtDebugPrint X
#else
#define DebugPrint(X)
#endif // DBG
#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 STRIPE_SIZE ((ULONG) 0x00010000)
class TRANSFER_PACKET;
typedef TRANSFER_PACKET* PTRANSFER_PACKET;
typedef
VOID
(*FT_TRANSFER_COMPLETION_ROUTINE)(
IN PTRANSFER_PACKET TransferPacket
);
typedef
VOID
(*FT_COMPLETION_ROUTINE)(
IN PVOID Context,
IN NTSTATUS Status
);
class FT_VOLUME;
typedef FT_VOLUME* PFT_VOLUME;
typedef struct _FT_COMPLETION_ROUTINE_CONTEXT {
KSPIN_LOCK SpinLock;
NTSTATUS Status;
LONG RefCount;
FT_COMPLETION_ROUTINE CompletionRoutine;
PVOID Context;
PFT_VOLUME ParentVolume;
} FT_COMPLETION_ROUTINE_CONTEXT, *PFT_COMPLETION_ROUTINE_CONTEXT;
typedef
PVOID
(*FT_STATE_CHANGE_CALLBACK)(
IN PVOID Context,
IN FT_PARTITION_STATE MemberState
);
class FT_BASE_CLASS;
typedef FT_BASE_CLASS* PFT_BASE_CLASS;
class FT_BASE_CLASS {
public:
static
PVOID
operator new(
IN unsigned int Size
);
static
VOID
operator delete(
IN PVOID MemPtr
);
};
class TRANSFER_PACKET : public FT_BASE_CLASS {
public:
TRANSFER_PACKET(
) { _freeMdl = FALSE; _freeBuffer = FALSE; SpecialRead = 0; };
virtual
~TRANSFER_PACKET(
);
BOOLEAN
AllocateMdl(
IN PVOID Buffer,
IN ULONG Length
);
BOOLEAN
AllocateMdl(
IN ULONG Length
);
VOID
FreeMdl(
);
// These fields must be filled in by the caller.
PMDL Mdl;
ULONG Length;
LONGLONG Offset;
FT_TRANSFER_COMPLETION_ROUTINE CompletionRoutine;
PFT_VOLUME TargetVolume;
PETHREAD Thread;
UCHAR IrpFlags;
BOOLEAN ReadPacket;
UCHAR SpecialRead;
// A spin lock which may be used to resolve contention for the
// fields below. This spin lock must be initialized by the callee.
KSPIN_LOCK SpinLock;
// This field must be filled in by the callee.
IO_STATUS_BLOCK IoStatus;
// These fields are for use by the callee.
LONG RefCount;
LIST_ENTRY QueueEntry;
private:
BOOLEAN _freeMdl;
BOOLEAN _freeBuffer;
};
#define TP_SPECIAL_READ_PRIMARY (1)
#define TP_SPECIAL_READ_SECONDARY (2)
struct DEVICE_EXTENSION;
typedef DEVICE_EXTENSION* PDEVICE_EXTENSION;
class DISPATCH_TP;
typedef DISPATCH_TP* PDISPATCH_TP;
class DISPATCH_TP : public TRANSFER_PACKET {
public:
PIRP Irp;
PDEVICE_EXTENSION Extension;
};
class VOLUME_SET;
typedef VOLUME_SET* PVOLUME_SET;
class VOLSET_TP;
typedef VOLSET_TP* PVOLSET_TP;
class VOLSET_TP : public TRANSFER_PACKET {
public:
PTRANSFER_PACKET MasterPacket;
PVOLUME_SET VolumeSet;
ULONG WhichMember;
};
class STRIPE;
typedef STRIPE* PSTRIPE;
class STRIPE_TP;
typedef STRIPE_TP* PSTRIPE_TP;
class STRIPE_TP : public TRANSFER_PACKET {
public:
PTRANSFER_PACKET MasterPacket;
PSTRIPE Stripe;
ULONG WhichMember;
};
class OVERLAPPED_IO_MANAGER;
typedef OVERLAPPED_IO_MANAGER* POVERLAPPED_IO_MANAGER;
class OVERLAP_TP;
typedef OVERLAP_TP* POVERLAP_TP;
class OVERLAP_TP : public TRANSFER_PACKET {
friend class OVERLAPPED_IO_MANAGER;
public:
OVERLAP_TP(
) { InQueue = FALSE; };
virtual
~OVERLAP_TP(
);
private:
BOOLEAN AllMembers;
BOOLEAN InQueue;
LIST_ENTRY OverlapQueue;
LIST_ENTRY CompletionList;
POVERLAPPED_IO_MANAGER OverlappedIoManager;
};
class MIRROR;
typedef MIRROR* PMIRROR;
class MIRROR_TP;
typedef MIRROR_TP* PMIRROR_TP;
class MIRROR_TP : public OVERLAP_TP {
public:
MIRROR_TP(
) { OneReadFailed = FALSE; };
PTRANSFER_PACKET MasterPacket;
PMIRROR Mirror;
ULONG WhichMember;
BOOLEAN OneReadFailed;
PMIRROR_TP SecondWritePacket;
FT_TRANSFER_COMPLETION_ROUTINE SavedCompletionRoutine;
};
class MIRROR_RECOVER_TP;
typedef MIRROR_RECOVER_TP* PMIRROR_RECOVER_TP;
class MIRROR_RECOVER_TP : public MIRROR_TP {
public:
MIRROR_RECOVER_TP(
) { PartialMdl = NULL; VerifyMdl = NULL; };
virtual
~MIRROR_RECOVER_TP(
);
BOOLEAN
AllocateMdls(
IN ULONG Length
);
VOID
FreeMdls(
);
PMDL PartialMdl;
PMDL VerifyMdl;
};
class PARITY_IO_MANAGER;
typedef PARITY_IO_MANAGER* PPARITY_IO_MANAGER;
class PARITY_TP;
typedef PARITY_TP* PPARITY_TP;
class PARITY_TP : public TRANSFER_PACKET {
friend class PARITY_IO_MANAGER;
friend
VOID
UpdateParityCompletionRoutine(
IN OUT PTRANSFER_PACKET TransferPacket
);
private:
BOOLEAN Idle;
LIST_ENTRY OverlapQueue;
LIST_ENTRY UpdateQueue;
PPARITY_IO_MANAGER ParityIoManager;
LONGLONG BucketNumber;
};
class STRIPE_WP;
typedef STRIPE_WP* PSTRIPE_WP;
class SWP_TP;
typedef SWP_TP* PSWP_TP;
class SWP_TP : public OVERLAP_TP {
public:
PTRANSFER_PACKET MasterPacket;
PSTRIPE_WP StripeWithParity;
ULONG WhichMember;
FT_TRANSFER_COMPLETION_ROUTINE SavedCompletionRoutine;
BOOLEAN OneReadFailed;
};
class SWP_RECOVER_TP;
typedef SWP_RECOVER_TP* PSWP_RECOVER_TP;
class SWP_RECOVER_TP : public SWP_TP {
public:
SWP_RECOVER_TP(
) { PartialMdl = NULL; VerifyMdl = NULL; };
virtual
~SWP_RECOVER_TP(
);
BOOLEAN
AllocateMdls(
IN ULONG Length
);
VOID
FreeMdls(
);
PMDL PartialMdl;
PMDL VerifyMdl;
};
class SWP_WRITE_TP;
typedef SWP_WRITE_TP* PSWP_WRITE_TP;
class SWP_WRITE_TP : public SWP_TP {
public:
SWP_WRITE_TP(
) { ReadAndParityMdl = NULL; WriteMdl = NULL; };
virtual
~SWP_WRITE_TP(
);
BOOLEAN
AllocateMdls(
IN ULONG Length
);
VOID
FreeMdls(
);
PMDL ReadAndParityMdl;
PMDL WriteMdl;
FT_PARTITION_STATE TargetState;
ULONG ParityMember;
SWP_TP ReadWritePacket;
PARITY_TP ParityPacket;
};
class SWP_REGENERATE_TP;
typedef SWP_REGENERATE_TP *PSWP_REGENERATE_TP;
class SWP_REGENERATE_TP : public TRANSFER_PACKET {
public:
PSWP_TP MasterPacket;
ULONG WhichMember;
LIST_ENTRY RegenPacketList;
};
class SWP_REBUILD_TP;
typedef SWP_REBUILD_TP *PSWP_REBUILD_TP;
class SWP_REBUILD_TP : public SWP_TP {
public:
PFT_COMPLETION_ROUTINE_CONTEXT Context;
BOOLEAN Initialize;
};
class OVERLAPPED_IO_MANAGER : public FT_BASE_CLASS {
public:
NTSTATUS
Initialize(
IN ULONG BucketSize
);
VOID
AcquireIoRegion(
IN OUT POVERLAP_TP TransferPacket,
IN BOOLEAN AllMembers
);
VOID
ReleaseIoRegion(
IN OUT POVERLAP_TP TransferPacket
);
VOID
PromoteToAllMembers(
IN OUT POVERLAP_TP TransferPacket
);
OVERLAPPED_IO_MANAGER(
) { _spinLock = NULL; _ioQueue = NULL; };
~OVERLAPPED_IO_MANAGER(
);
private:
ULONG _numQueues;
ULONG _bucketSize;
PKSPIN_LOCK _spinLock;
PLIST_ENTRY _ioQueue;
};
class PARITY_IO_MANAGER : public FT_BASE_CLASS {
friend
VOID
UpdateParityCompletionRoutine(
IN OUT PTRANSFER_PACKET TransferPacket
);
public:
NTSTATUS
Initialize(
IN ULONG BucketSize
);
VOID
StartReadForUpdateParity(
IN LONGLONG Offset,
IN ULONG Length,
IN PFT_VOLUME TargetVolume,
IN PETHREAD Thread,
IN UCHAR IrpFlags
);
VOID
UpdateParity(
IN OUT PPARITY_TP TransferPacket
);
PARITY_IO_MANAGER(
) { _spinLock = NULL; _ioQueue = NULL; _ePacket = NULL; };
~PARITY_IO_MANAGER(
);
private:
ULONG _numQueues;
ULONG _bucketSize;
PKSPIN_LOCK _spinLock;
PLIST_ENTRY _ioQueue;
//
// Emergency packet.
//
PPARITY_TP _ePacket;
BOOLEAN _ePacketInUse;
BOOLEAN _ePacketQueueBeingServiced;
LIST_ENTRY _ePacketQueue;
KSPIN_LOCK _ePacketSpinLock;
};
class PARTITION;
typedef PARTITION* PPARTITION;
class FT_VOLUME : public FT_BASE_CLASS {
friend
VOID
SetMemberStateWorker(
IN PVOID Context
);
public:
VOID
Initialize(
);
VOID
SetMemberInformation(
IN OUT PFT_VOLUME ParentVolume,
IN PDEVICE_EXTENSION MemberExtension
) { _parentVolume = ParentVolume; _memberExtension = MemberExtension; };
PDEVICE_EXTENSION
GetMemberExtension(
) { return _memberExtension; };
virtual
VOID
Transfer(
IN OUT PTRANSFER_PACKET TransferPacket
) = 0;
virtual
VOID
ReplaceBadSector(
IN OUT PTRANSFER_PACKET TransferPacket
) = 0;
virtual
VOID
StartSyncOperations(
IN FT_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context
) = 0;
virtual
BOOLEAN
Regenerate(
IN OUT PFT_VOLUME SpareVolume,
IN FT_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context
) = 0;
virtual
VOID
FlushBuffers(
IN FT_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context
) = 0;
virtual
BOOLEAN
IsPartition(
) = 0;
virtual
ULONG
QueryNumberOfMembers(
) = 0;
virtual
PFT_VOLUME
GetMember(
IN ULONG MemberNumber
) = 0;
virtual
BOOLEAN
IsCreatingCheckData(
) = 0;
virtual
VOID
SetCheckDataDirty(
) = 0;
virtual
ULONG
QuerySectorSize(
) = 0;
virtual
LONGLONG
QueryVolumeSize(
) = 0;
virtual
FT_TYPE
QueryVolumeType(
) = 0;
virtual
FT_STATE
QueryVolumeState(
) = 0;
virtual
ULONG
QueryAlignmentRequirement(
) = 0;
virtual
VOID
SetFtBitInPartitionType(
IN BOOLEAN Value,
IN BOOLEAN SpecialBitValue
) = 0;
virtual
PPARTITION
FindPartition(
IN ULONG DiskNumber,
IN ULONG PartitionNumber
) = 0;
virtual
PPARTITION
FindPartition(
IN ULONG Signature,
IN LONGLONG Offset
) = 0;
virtual
BOOLEAN
OrphanPartition(
IN PPARTITION Partition
) = 0;
virtual
VOID
MemberStateChangeNotification(
IN PFT_VOLUME ChangedMember
);
virtual
~FT_VOLUME(
);
FT_PARTITION_STATE
QueryMemberState(
);
FT_PARTITION_STATE
QueryMemberStateUnprotected(
) { return _memberState; };
VOID
SetMemberState(
IN FT_PARTITION_STATE MemberState
);
VOID
SetMemberStateWithoutNotification(
IN FT_PARTITION_STATE MemberState
);
protected:
KSPIN_LOCK _spinLock;
private:
FT_PARTITION_STATE _memberState;
PFT_VOLUME _parentVolume;
PDEVICE_EXTENSION _memberExtension;
};
#define TRANSFER(a) ((a)->TargetVolume->Transfer((a)))
class PARTITION : public FT_VOLUME {
friend
VOID
SetFtBitInPartitionTypeWorker(
IN PVOID Context
);
friend
NTSTATUS
PartitionTransferCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID TransferPacket
);
public:
PARTITION(
) { _emergencyIrp = NULL; };
virtual
~PARTITION(
);
NTSTATUS
Initialize(
IN OUT PDEVICE_OBJECT TargetObject,
IN ULONG SectorSize,
IN ULONG DiskSignature,
IN LONGLONG PartitionOffset,
IN LONGLONG PartitionLength,
IN BOOLEAN IsOnline,
IN ULONG DiskNumber,
IN ULONG PartitionNumber
);
virtual
VOID
Transfer(
IN OUT PTRANSFER_PACKET TransferPacket
);
virtual
VOID
ReplaceBadSector(
IN OUT PTRANSFER_PACKET TransferPacket
);
virtual
VOID
StartSyncOperations(
IN FT_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context
);
virtual
BOOLEAN
Regenerate(
IN OUT PFT_VOLUME SpareVolume,
IN FT_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context
);
virtual
VOID
FlushBuffers(
IN FT_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context
);
virtual
BOOLEAN
IsPartition(
);
virtual
ULONG
QueryNumberOfMembers(
);
virtual
PFT_VOLUME
GetMember(
IN ULONG MemberNumber
);
virtual
BOOLEAN
IsCreatingCheckData(
);
virtual
VOID
SetCheckDataDirty(
);
virtual
ULONG
QuerySectorSize(
);
virtual
LONGLONG
QueryVolumeSize(
);
virtual
FT_TYPE
QueryVolumeType(
);
virtual
FT_STATE
QueryVolumeState(
);
virtual
ULONG
QueryAlignmentRequirement(
);
virtual
VOID
SetFtBitInPartitionType(
IN BOOLEAN Value,
IN BOOLEAN SpecialBitValue
);
UCHAR
QueryPartitionType(
);
virtual
PPARTITION
FindPartition(
IN ULONG DiskNumber,
IN ULONG PartitionNumber
);
virtual
PPARTITION
FindPartition(
IN ULONG Signature,
IN LONGLONG Offset
);
virtual
BOOLEAN
OrphanPartition(
IN PPARTITION Partition
);
ULONG
QueryDiskSignature(
) { return _diskSignature; };
LONGLONG
QueryPartitionOffset(
) { return _partitionOffset; };
LONGLONG
QueryPartitionLength(
) { return _partitionLength; };
BOOLEAN
IsOnline(
) { return _isOnline; };
ULONG
QueryDiskNumber(
) { return _diskNumber; };
ULONG
QueryPartitionNumber(
) { return _partitionNumber; };
private:
PDEVICE_OBJECT _targetObject;
ULONG _sectorSize;
ULONG _diskSignature;
LONGLONG _partitionOffset;
LONGLONG _partitionLength;
BOOLEAN _isOnline;
ULONG _diskNumber;
ULONG _partitionNumber;
PIRP _emergencyIrp;
BOOLEAN _emergencyIrpInUse;
LIST_ENTRY _emergencyIrpQueue;
};
class COMPOSITE_FT_VOLUME;
typedef COMPOSITE_FT_VOLUME *PCOMPOSITE_FT_VOLUME;
class COMPOSITE_FT_VOLUME : public FT_VOLUME {
public:
virtual
NTSTATUS
Initialize(
IN OUT PFT_VOLUME* VolumeArray,
IN ULONG ArraySize
);
virtual
VOID
Transfer(
IN OUT PTRANSFER_PACKET TransferPacket
) = 0;
virtual
VOID
ReplaceBadSector(
IN OUT PTRANSFER_PACKET TransferPacket
) = 0;
virtual
VOID
StartSyncOperations(
IN FT_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context
);
virtual
BOOLEAN
Regenerate(
IN OUT PFT_VOLUME SpareVolume,
IN FT_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context
);
virtual
VOID
FlushBuffers(
IN FT_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context
);
virtual
BOOLEAN
IsPartition(
);
virtual
ULONG
QueryNumberOfMembers(
);
virtual
PFT_VOLUME
GetMember(
IN ULONG MemberNumber
);
virtual
BOOLEAN
IsCreatingCheckData(
) = 0;
virtual
VOID
SetCheckDataDirty(
) = 0;
virtual
ULONG
QuerySectorSize(
);
virtual
LONGLONG
QueryVolumeSize(
) = 0;
virtual
FT_TYPE
QueryVolumeType(
) = 0;
virtual
FT_STATE
QueryVolumeState(
) = 0;
virtual
ULONG
QueryAlignmentRequirement(
);
virtual
VOID
SetFtBitInPartitionType(
IN BOOLEAN Value,
IN BOOLEAN SpecialBitValue
);
virtual
PPARTITION
FindPartition(
IN ULONG DiskNumber,
IN ULONG PartitionNumber
);
virtual
PPARTITION
FindPartition(
IN ULONG Signature,
IN LONGLONG Offset
);
virtual
BOOLEAN
OrphanPartition(
IN PPARTITION Partition
);
VOID
SetMember(
IN ULONG MemberNumber,
IN PFT_VOLUME NewVolume
);
COMPOSITE_FT_VOLUME(
) { _volumeArray = NULL; };
virtual
~COMPOSITE_FT_VOLUME(
);
protected:
PFT_VOLUME
GetMemberUnprotected(
IN ULONG MemberNumber
) { return _volumeArray[MemberNumber]; };
VOID
SetMemberUnprotected(
IN ULONG MemberNumber,
IN PFT_VOLUME NewVolume
) { _volumeArray[MemberNumber] = NewVolume; };
ULONG
QueryNumMembers(
) { return _arraySize; };
private:
PFT_VOLUME* _volumeArray;
ULONG _arraySize;
ULONG _sectorSize;
};
class VOLUME_SET : public COMPOSITE_FT_VOLUME {
friend
VOID
VolsetTransferSequentialCompletionRoutine(
IN PTRANSFER_PACKET TransferPacket
);
public:
VOLUME_SET(
) { _ePacket = NULL; };
virtual
~VOLUME_SET(
);
virtual
NTSTATUS
Initialize(
IN OUT PFT_VOLUME* VolumeArray,
IN ULONG ArraySize
);
virtual
VOID
Transfer(
IN OUT PTRANSFER_PACKET TransferPacket
);
virtual
VOID
ReplaceBadSector(
IN OUT PTRANSFER_PACKET TransferPacket
);
virtual
BOOLEAN
IsCreatingCheckData(
);
virtual
VOID
SetCheckDataDirty(
);
virtual
LONGLONG
QueryVolumeSize(
);
virtual
FT_TYPE
QueryVolumeType(
);
virtual
FT_STATE
QueryVolumeState(
);
private:
BOOLEAN
LaunchParallel(
IN OUT PTRANSFER_PACKET TransferPacket
);
VOID
LaunchSequential(
IN OUT PTRANSFER_PACKET TransferPacket
);
LONGLONG _volumeSize;
PVOLSET_TP _ePacket;
BOOLEAN _ePacketInUse;
LIST_ENTRY _ePacketQueue;
};
class STRIPE : public COMPOSITE_FT_VOLUME {
friend
VOID
StripeSequentialTransferCompletionRoutine(
IN PTRANSFER_PACKET TransferPacket
);
public:
STRIPE(
IN ULONG StripeSize
) { _stripeSize = StripeSize; _ePacket = NULL; };
virtual
~STRIPE(
);
virtual
NTSTATUS
Initialize(
IN OUT PFT_VOLUME* VolumeArray,
IN ULONG ArraySize
);
virtual
VOID
Transfer(
IN OUT PTRANSFER_PACKET TransferPacket
);
virtual
VOID
ReplaceBadSector(
IN OUT PTRANSFER_PACKET TransferPacket
);
virtual
BOOLEAN
IsCreatingCheckData(
);
virtual
VOID
SetCheckDataDirty(
);
virtual
LONGLONG
QueryVolumeSize(
);
virtual
FT_TYPE
QueryVolumeType(
);
virtual
FT_STATE
QueryVolumeState(
);
private:
BOOLEAN
LaunchParallel(
IN OUT PTRANSFER_PACKET TransferPacket
);
VOID
LaunchSequential(
IN OUT PTRANSFER_PACKET TransferPacket
);
ULONG _stripeSize;
LONGLONG _memberSize;
LONGLONG _volumeSize;
PSTRIPE_TP _ePacket;
BOOLEAN _ePacketInUse;
LIST_ENTRY _ePacketQueue;
};
class MIRROR : public COMPOSITE_FT_VOLUME {
friend
VOID
FinishRegenerate(
IN PMIRROR Mirror,
IN PFT_COMPLETION_ROUTINE_CONTEXT RegenContext,
IN PMIRROR_TP TransferPacket
);
friend
VOID
MirrorRegenerateCompletionRoutine(
IN PTRANSFER_PACKET TransferPacket
);
friend
VOID
StartRegeneration(
IN PVOID Context,
IN NTSTATUS Status
);
friend
VOID
MirrorTransferCompletionRoutine(
IN PTRANSFER_PACKET TransferPacket
);
friend
VOID
MirrorRecoverPhase8(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
MirrorRecoverPhase7(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
MirrorRecoverPhase6(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
MirrorRecoverPhase5(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
MirrorRecoverPhase4(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
MirrorRecoverPhase3(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
MirrorRecoverPhase2(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
MirrorRecoverEmergencyCompletion(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
MirrorRecoverPhase1(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
MirrorMaxTransferCompletionRoutine(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
MirrorMaxTransferEmergencyCompletion(
IN OUT PTRANSFER_PACKET TransferPacket
);
public:
virtual
~MIRROR(
);
virtual
NTSTATUS
Initialize(
IN OUT PFT_VOLUME* VolumeArray,
IN ULONG ArraySize
);
virtual
VOID
Transfer(
IN OUT PTRANSFER_PACKET TransferPacket
);
virtual
VOID
ReplaceBadSector(
IN OUT PTRANSFER_PACKET TransferPacket
);
virtual
VOID
StartSyncOperations(
IN FT_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context
);
virtual
BOOLEAN
Regenerate(
IN OUT PFT_VOLUME SpareVolume,
IN FT_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context
);
virtual
BOOLEAN
IsCreatingCheckData(
);
virtual
VOID
SetCheckDataDirty(
);
virtual
LONGLONG
QueryVolumeSize(
);
virtual
FT_TYPE
QueryVolumeType(
);
virtual
FT_STATE
QueryVolumeState(
);
virtual
BOOLEAN
OrphanPartition(
IN PPARTITION Partition
);
virtual
VOID
MemberStateChangeNotification(
IN PFT_VOLUME ChangedMember
);
MIRROR(
IN PDEVICE_EXTENSION Extension
) { _extension = Extension;
_ePacket = NULL; _ePacket2 = NULL; _eRecoverPacket = NULL; };
private:
VOID
IncrementRequestCount(
IN ULONG MemberNumber
) { _requestCount[MemberNumber]++; };
BOOLEAN
DecrementRequestCount(
IN ULONG MemberNumber
);
BOOLEAN
LaunchRead(
IN OUT PTRANSFER_PACKET TransferPacket,
IN OUT PMIRROR_TP Packet1
);
BOOLEAN
LaunchWrite(
IN OUT PTRANSFER_PACKET TransferPacket,
IN OUT PMIRROR_TP Packet1,
IN OUT PMIRROR_TP Packet2
);
VOID
Recycle(
IN OUT PMIRROR_TP TransferPacket,
IN BOOLEAN ServiceEmergencyQueue
);
VOID
Recover(
IN OUT PMIRROR_TP TransferPacket
);
VOID
MaxTransfer(
IN OUT PMIRROR_TP TransferPacket
);
PDEVICE_EXTENSION _extension;
LONGLONG _volumeSize;
//
// State for keeping track of outstanding requests.
//
LONG _requestCount[2];
FT_COMPLETION_ROUTINE _waitingForOrphanIdle;
PVOID _waitingForOrphanIdleContext;
ULONG _waitingOrphanNumber;
//
// Indicates whether or not 'StartSyncOperations' is expected.
//
BOOLEAN _syncExpected;
//
// Emergency packet.
//
PMIRROR_TP _ePacket, _ePacket2;
BOOLEAN _ePacketInUse;
LIST_ENTRY _ePacketQueue;
//
// Emergency recover packet.
//
PMIRROR_RECOVER_TP _eRecoverPacket;
BOOLEAN _eRecoverPacketInUse;
LIST_ENTRY _eRecoverPacketQueue;
//
// Overlapped io manager.
//
OVERLAPPED_IO_MANAGER _overlappedIoManager;
};
class STRIPE_WP : public COMPOSITE_FT_VOLUME {
friend
VOID
StripeWpSyncFinalCompletion(
IN PVOID Context,
IN NTSTATUS Status
);
friend
VOID
StripeWpSyncCompletionRoutine(
IN PTRANSFER_PACKET TransferPacket
);
friend
VOID
StartStripeRegeneration(
IN PVOID Context,
IN NTSTATUS Status
);
friend
VOID
StripeWpParallelTransferCompletionRoutine(
IN PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpSequentialTransferCompletionRoutine(
IN PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpWritePhase31(
IN OUT PTRANSFER_PACKET Packet
);
friend
VOID
StripeWpWritePhase30(
IN OUT PTRANSFER_PACKET Packet
);
friend
VOID
StripeWpWritePhase2(
IN OUT PTRANSFER_PACKET ReadPacket
);
friend
VOID
StripeWpWritePhase1(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpSequentialRegenerateCompletion(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpSequentialEmergencyCompletion(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpParallelRegenerateCompletion(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpRegeneratePacketPhase1(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpRecoverPhase8(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpRecoverPhase7(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpRecoverPhase6(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpRecoverPhase5(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpRecoverPhase4(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpRecoverPhase3(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpRecoverPhase2(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpRecoverEmergencyCompletion(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpRecoverPhase1(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpMaxTransferCompletionRoutine(
IN OUT PTRANSFER_PACKET TransferPacket
);
friend
VOID
StripeWpMaxTransferEmergencyCompletion(
IN OUT PTRANSFER_PACKET TransferPacket
);
public:
virtual
NTSTATUS
Initialize(
IN OUT PFT_VOLUME* VolumeArray,
IN ULONG ArraySize
);
virtual
VOID
Transfer(
IN OUT PTRANSFER_PACKET TransferPacket
);
virtual
VOID
ReplaceBadSector(
IN OUT PTRANSFER_PACKET TransferPacket
);
virtual
VOID
StartSyncOperations(
IN FT_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context
);
virtual
BOOLEAN
Regenerate(
IN OUT PFT_VOLUME SpareVolume,
IN FT_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context
);
virtual
BOOLEAN
IsCreatingCheckData(
);
virtual
VOID
SetCheckDataDirty(
);
virtual
LONGLONG
QueryVolumeSize(
);
virtual
FT_TYPE
QueryVolumeType(
);
virtual
FT_STATE
QueryVolumeState(
);
virtual
BOOLEAN
OrphanPartition(
IN PPARTITION Partition
);
STRIPE_WP(
IN PDEVICE_EXTENSION Extension,
IN ULONG StripeSize
);
virtual
~STRIPE_WP(
);
private:
VOID
IncrementRequestCount(
IN ULONG MemberNumber
) { _requestCount[MemberNumber]++; };
BOOLEAN
DecrementRequestCount(
IN ULONG MemberNumber
);
BOOLEAN
LaunchParallel(
IN OUT PTRANSFER_PACKET TransferPacket
);
VOID
LaunchSequential(
IN OUT PTRANSFER_PACKET TransferPacket
);
VOID
ReadPacket(
IN OUT PSWP_TP TransferPacket
);
VOID
WritePacket(
IN OUT PSWP_WRITE_TP TransferPacket
);
VOID
RegeneratePacket(
IN OUT PSWP_TP TransferPacket,
IN BOOLEAN AllocateRegion
);
VOID
Recover(
IN OUT PSWP_TP TransferPacket
);
VOID
MaxTransfer(
IN OUT PSWP_TP TransferPacket
);
VOID
RecycleRecoverTp(
IN OUT PSWP_RECOVER_TP TransferPacket
);
PDEVICE_EXTENSION _extension;
ULONG _stripeSize;
LONGLONG _memberSize;
LONGLONG _volumeSize;
//
// State for creating check data.
//
BOOLEAN _initializing;
//
// Indicates whether or not 'StartSyncOperations' is expected.
//
BOOLEAN _syncExpected;
//
// State for keeping track of outstanding requests.
//
PLONG _requestCount;
FT_COMPLETION_ROUTINE _waitingForOrphanIdle;
PVOID _waitingForOrphanIdleContext;
ULONG _waitingOrphanNumber;
//
// State for keeping track of overlapping write requests.
// One OVERLAPPED_IO_MANAGER for each member.
//
OVERLAPPED_IO_MANAGER _overlappedIoManager;
//
// State for serializing parity I/O.
//
PARITY_IO_MANAGER _parityIoManager;
//
// Emergency read/write packet.
//
PSWP_WRITE_TP _ePacket;
BOOLEAN _ePacketInUse;
BOOLEAN _ePacketQueueBeingServiced;
LIST_ENTRY _ePacketQueue;
//
// Emergency regenerate packet.
//
PSWP_REGENERATE_TP _eRegeneratePacket;
BOOLEAN _eRegeneratePacketInUse;
LIST_ENTRY _eRegeneratePacketQueue;
//
// Emergency recover packet.
//
PSWP_RECOVER_TP _eRecoverPacket;
BOOLEAN _eRecoverPacketInUse;
LIST_ENTRY _eRecoverPacketQueue;
};
struct DEVICE_EXTENSION {
//
// Pointer to the device object for this extension.
//
PDEVICE_OBJECT DeviceObject; // 00
//
// The logical disk and partition number - filled in during initialization.
// A DiskNumber of -1 indicated the root extension. A PartitionNumber of
// 1 or greater implies a partition while a PartitionNumber of 0 implies
// a whole disk if DiskNumber >= 0.
//
ULONG DiskNumber; // 04
ULONG PartitionNumber; // 08
//
// Pointer to the root device extension.
//
PDEVICE_EXTENSION Root; // 0C
//
// The device object on which this device object is layered.
//
PDEVICE_OBJECT TargetObject; // 10
union {
struct {
//
// A pointer to the FT_VOLUME that will handle READ and WRITE
// requests.
// Protect with 'SpinLock' below. Also, use a 'RefCount' to
// keep track of how many activities are taking place on the
// volume.
//
PFT_VOLUME FtVolume; // 14
LONG RefCount; // 18
//
// \Harddisk(N)\Partition(M) -> \Harddisk(N)\Partition(M+1)
// Protect with 'SpinLock' below.
//
PDEVICE_EXTENSION PartitionChain; // 1C
//
// Pointer to the Whole disk extension for this partition.
//
PDEVICE_EXTENSION WholeDisk; // 20
//
// Parameters about the partition that this is layered above.
//
LARGE_INTEGER PartitionOffset; // 28
LARGE_INTEGER PartitionLength; // 30
//
// Emergency queue for a transfer packet.
//
PDISPATCH_TP EmergencyTransferPacket;
LIST_ENTRY EmergencyTransferPacketQueue;
BOOLEAN EmergencyTransferPacketInUse;
} Partition;
struct {
//
// \Harddisk(N)\Paritition0 -> \Harddisk(N+1)\Partition0
// Protect with 'SpinLock' below.
//
PDEVICE_EXTENSION DiskChain; // 14
//
// Points to \Harddisk(N)\Partition(1)
// Protect with 'SpinLock' below.
//
PDEVICE_EXTENSION PartitionChain; // 18
//
// Parameters about the partition that this is layered above.
// Protect with 'SpinLock' below.
//
DISK_GEOMETRY DiskGeometry; // 20
ULONG Signature; // 38
} WholeDisk;
struct {
//
// Pointer to the driver object.
//
PDRIVER_OBJECT DriverObject; // 14
//
// Points to \Harddisk0\Partition0
// Protect with 'SpinLock' below.
//
PDEVICE_EXTENSION DiskChain; // 18
//
// The number of disks found so far.
//
ULONG NumberOfDisks; // 1C
} Root;
} u;
//
// A spin lock to protect certain fields of this extension.
//
KSPIN_LOCK SpinLock; // 3C
};
BOOLEAN
FtpIsWorseStatus(
IN NTSTATUS Status1,
IN NTSTATUS Status2
);
VOID
FtpDisolveVolume(
IN PDEVICE_EXTENSION Extension,
IN PFT_VOLUME Volume
);
VOID
FtpComputeParity(
IN PVOID TargetBuffer,
IN PVOID SourceBuffer,
IN ULONG BufferLength
);
NTSTATUS
FtpReturnRegistryInformation(
IN PCHAR ValueName,
IN OUT PVOID *FreePoolAddress,
IN OUT PVOID *Information
);
NTSTATUS
FtpWriteRegistryInformation(
IN PCHAR ValueName,
IN PVOID Information,
IN ULONG InformationLength
);
VOID
FtpLogError(
IN PDEVICE_EXTENSION DeviceExtension,
IN NTSTATUS SpecificIoStatus,
IN NTSTATUS FinalStatus,
IN ULONG UniqueErrorValue,
IN PIRP Irp
);