ReactOS 0.4.17-dev-1190-g4c812f4
blockdev.c File Reference
#include "ntfs.h"
#include <debug.h>
Include dependency graph for blockdev.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

VOID NtfsInitIoRunList (OUT PNTFS_IO_RUN_LIST RunList)
 
NtfsAddIoRun

@implemented

Appends one contiguous piece to a request's run list.

Parameters
RunListThe list being built, previously initialized by NtfsInitIoRunList()
LboByte offset on the volume of this piece, or NTFS_SPARSE_LBO if the piece has no backing storage
ByteCountSize of this piece, in bytes
Returns
STATUS_SUCCESS, or STATUS_INSUFFICIENT_RESOURCES if the list had to grow and the allocation failed.
Remarks
Runs tile the caller's buffer in the order they are added, so the buffer offset is implied. A piece continuing the previous one is merged into it, keeping contiguous files down to a single IRP.
NTSTATUS NtfsAddIoRun (IN OUT PNTFS_IO_RUN_LIST RunList, IN LONGLONG Lbo, IN ULONG ByteCount)
 
VOID NtfsFreeIoRunList (IN OUT PNTFS_IO_RUN_LIST RunList)
 
static NTSTATUS NTAPI NtfsIoRunCompletionRoutine (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
 
static NTSTATUS NtfsBuildIoRunIrp (IN PDEVICE_OBJECT DeviceObject, IN PNTFS_IO_CONTEXT IoContext, IN UCHAR MajorFunction, IN PUCHAR Buffer, IN ULONG BufferLength, IN OUT PNTFS_IO_RUN Run, IN BOOLEAN Override)
 
static NTSTATUS NtfsIssueIoRuns (IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN OUT PUCHAR Buffer, IN PMDL BorrowedMdl OPTIONAL, IN PNTFS_IO_RUN_LIST RunList, IN BOOLEAN Override, OUT PULONG BytesTransferred)
 
NtfsPerformIoRuns

@implemented

Reads or writes the pieces described by RunList, all in parallel.

Parameters
DeviceObjectStorage device to transfer to or from
MajorFunctionIRP_MJ_READ or IRP_MJ_WRITE
SectorSizeSector size the storage device requires transfers to be aligned to
BufferSystem-space buffer of RunList->TotalLength bytes, tiled by the runs
RunListThe pieces to transfer. Consumed by this call: the runs are rewritten in place to satisfy the device's alignment requirements.
OverrideWhether to set SL_OVERRIDE_VERIFY_VOLUME on the requests
BytesTransferredOptionally receives how much of the request was satisfied
Returns
STATUS_SUCCESS on success, STATUS_INSUFFICIENT_RESOURCES if an allocation failed, STATUS_NOT_IMPLEMENTED for a write to a sparse run, since that's probably not happening for this driver
static NTSTATUS NtfsPerformIoRunsInternal (IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN PMDL BorrowedMdl OPTIONAL, IN PNTFS_IO_RUN_LIST RunList, IN BOOLEAN Override, OUT PULONG BytesTransferred OPTIONAL)
 
static NTSTATUS NTAPI NtfsForwardedIrpCompletionRoutine (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
 
static NTSTATUS NtfsForwardIrpToRun (IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN PIRP Irp, IN PNTFS_IO_RUN Run, IN BOOLEAN Override, OUT PULONG BytesTransferred)
 
NtfsPerformIrpIoRuns

@implemented

Transfers the runs of a request that originated from an IRP, forwarding that IRP straight to the storage stack when the request allows it.

Parameters
DeviceObjectStorage device to transfer to or from
MajorFunctionIRP_MJ_READ or IRP_MJ_WRITE
SectorSizeSector size the storage device requires transfers to be aligned to
IrpThe request being served. May be NULL, in which case this is exactly NtfsPerformIoRuns().
BufferSystem-space mapping of the IRP's buffer, used whenever the request cannot simply be forwarded
RunListThe pieces to transfer
OverrideWhether to set SL_OVERRIDE_VERIFY_VOLUME on the requests
BytesTransferredReceives how much of the request was satisfied
Returns
STATUS_SUCCESS on success, otherwise the status of the failing transfer.
NTSTATUS NtfsPerformIrpIoRuns (IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN ULONG SectorSize, IN PIRP Irp, IN OUT PUCHAR Buffer, IN PNTFS_IO_RUN_LIST RunList, IN BOOLEAN Override, OUT PULONG BytesTransferred)
 
NTSTATUS NtfsPerformIoRuns (IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN PNTFS_IO_RUN_LIST RunList, IN BOOLEAN Override, OUT PULONG BytesTransferred OPTIONAL)
 
NtfsReadDisk

@implemented

Reads a single contiguous range from the given DeviceObject.

Parameters
DeviceObjectDevice to read from
StartingOffsetOffset, in bytes, from the start of the device object
LengthHow much data to read, in bytes
SectorSizeSize of the sector on the disk that the read must be aligned to
BufferSystem-space buffer receiving the data
OverrideWhether to set SL_OVERRIDE_VERIFY_VOLUME on the request
Returns
STATUS_SUCCESS in case of success, STATUS_INSUFFICIENT_RESOURCES if a memory allocation failed, or whatever status the storage stack returned.
NTSTATUS NtfsReadDisk (IN PDEVICE_OBJECT DeviceObject, IN LONGLONG StartingOffset, IN ULONG Length, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
 
NtfsWriteDisk

@implemented

Writes data from the given buffer to the given DeviceObject.

Parameters
DeviceObjectDevice to write to
StartingOffsetOffset, in bytes, from the start of the device object where the data will be written
LengthHow much data will be written, in bytes
SectorSizeSize of the sector on the disk that the write must be aligned to
BufferThe data that's being written to the device
Returns
STATUS_SUCCESS in case of success, STATUS_INSUFFICIENT_RESOURCES if a memory allocation failed, or whatever status the storage stack returned.
NTSTATUS NtfsWriteDisk (IN PDEVICE_OBJECT DeviceObject, IN LONGLONG StartingOffset, IN ULONG Length, IN ULONG SectorSize, IN const PUCHAR Buffer)
 
NtfsFlushDevice

@implemented

Asks the storage stack to push everything it is holding out to the media.

Parameters
DeviceObjectDevice to flush
Returns
STATUS_SUCCESS on success, or whatever the storage stack returned.
NTSTATUS NtfsFlushDevice (IN PDEVICE_OBJECT DeviceObject)
 
NTSTATUS NtfsReadSectors (IN PDEVICE_OBJECT DeviceObject, IN ULONG DiskSector, IN ULONG SectorCount, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
 
NTSTATUS NtfsDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, IN ULONG ControlCode, IN PVOID InputBuffer, IN ULONG InputBufferSize, IN OUT PVOID OutputBuffer, IN OUT PULONG OutputBufferSize, IN BOOLEAN Override)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 31 of file blockdev.c.

Function Documentation

◆ NtfsAddIoRun()

NTSTATUS NtfsAddIoRun ( IN OUT PNTFS_IO_RUN_LIST  RunList,
IN LONGLONG  Lbo,
IN ULONG  ByteCount 
)

Definition at line 74 of file blockdev.c.

77{
78 PNTFS_IO_RUN LastRun;
79 PNTFS_IO_RUN NewRuns;
80 ULONG NewCapacity;
81
82 if (ByteCount == 0)
83 return STATUS_SUCCESS;
84
85 /* Does this piece simply continue the previous one? */
86 if (RunList->Count != 0)
87 {
88 LastRun = &RunList->Runs[RunList->Count - 1];
89
90 if (LastRun->ByteCount <= MAXULONG - ByteCount &&
91 ((Lbo == NTFS_SPARSE_LBO && LastRun->Lbo == NTFS_SPARSE_LBO) ||
92 (Lbo != NTFS_SPARSE_LBO && LastRun->Lbo != NTFS_SPARSE_LBO &&
93 LastRun->Lbo + LastRun->ByteCount == Lbo)))
94 {
95 LastRun->ByteCount += ByteCount;
96 RunList->TotalLength += ByteCount;
97 return STATUS_SUCCESS;
98 }
99 }
100
101 if (RunList->Count == RunList->Capacity)
102 {
103 NewCapacity = RunList->Capacity * 2;
104
105 /* Non-paged: a run list stays live across the transfer, and a request
106 * on the paging path must not fault while walking it. */
108 NewCapacity * sizeof(NTFS_IO_RUN),
110 if (NewRuns == NULL)
111 {
112 DPRINT1("Not enough memory to grow the I/O run list!\n");
114 }
115
116 RtlCopyMemory(NewRuns, RunList->Runs, RunList->Count * sizeof(NTFS_IO_RUN));
117
118 if (RunList->Runs != RunList->StackRuns)
119 {
120 ExFreePoolWithTag(RunList->Runs, TAG_IO_RUNS);
121 }
122
123 RunList->Runs = NewRuns;
124 RunList->Capacity = NewCapacity;
125 }
126
127 LastRun = &RunList->Runs[RunList->Count];
128 LastRun->Lbo = Lbo;
129 LastRun->BufferOffset = RunList->TotalLength;
130 LastRun->ByteCount = ByteCount;
131 LastRun->SavedIrp = NULL;
132
133 RunList->Count++;
134 RunList->TotalLength += ByteCount;
135
136 return STATUS_SUCCESS;
137}
#define DPRINT1
Definition: precomp.h:8
#define NULL
Definition: types.h:112
#define TAG_IO_RUNS
Definition: nodetype.h:168
#define NTFS_SPARSE_LBO
Definition: ntfs.h:510
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
IN PFCB IN VBO OUT PLBO Lbo
Definition: fatprocs.h:309
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define STATUS_SUCCESS
Definition: shellext.h:65
PIRP SavedIrp
Definition: ntfs.h:522
LONGLONG Lbo
Definition: ntfs.h:519
ULONG BufferOffset
Definition: ntfs.h:520
ULONG ByteCount
Definition: ntfs.h:521
#define MAXULONG
Definition: typedefs.h:251
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099

Referenced by NtfsMapAttributeRuns(), NtfsReadDisk(), NtfsReadWriteVolume(), and NtfsWriteDisk().

◆ NtfsBuildIoRunIrp()

static NTSTATUS NtfsBuildIoRunIrp ( IN PDEVICE_OBJECT  DeviceObject,
IN PNTFS_IO_CONTEXT  IoContext,
IN UCHAR  MajorFunction,
IN PUCHAR  Buffer,
IN ULONG  BufferLength,
IN OUT PNTFS_IO_RUN  Run,
IN BOOLEAN  Override 
)
static

Definition at line 204 of file blockdev.c.

211{
213 PIRP Irp;
214 PMDL Mdl;
215
216 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
217 if (Irp == NULL)
218 {
219 DPRINT1("IoAllocateIrp failed!\n");
221 }
222
223 if (Run->BufferOffset == 0 && Run->ByteCount == BufferLength)
224 {
225 Mdl = IoContext->MasterMdl;
226 }
227 else
228 {
229 PUCHAR MasterVa = (PUCHAR)IoContext->MasterVa + Run->BufferOffset;
230
231 Mdl = IoAllocateMdl(MasterVa,
232 Run->ByteCount,
233 FALSE,
234 FALSE,
235 NULL);
236 if (Mdl == NULL)
237 {
238 DPRINT1("IoAllocateMdl failed!\n");
239 IoFreeIrp(Irp);
241 }
242
243 IoBuildPartialMdl(IoContext->MasterMdl,
244 Mdl,
245 MasterVa,
246 Run->ByteCount);
247 }
248
249 Irp->MdlAddress = Mdl;
250 Irp->Flags |= IRP_NOCACHE;
251
253 Stack->MajorFunction = MajorFunction;
254 Stack->Parameters.Read.Length = Run->ByteCount;
255 Stack->Parameters.Read.ByteOffset.QuadPart = Run->Lbo;
256
257 if (Override)
258 {
260 }
261
264 IoContext,
265 TRUE,
266 TRUE,
267 TRUE);
268
269 Run->SavedIrp = Irp;
270
271 return STATUS_SUCCESS;
272}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define IoAllocateMdl
Definition: fxmdl.h:88
VOID NTAPI IoBuildPartialMdl(IN PMDL SourceMdl, IN PMDL TargetMdl, IN PVOID VirtualAddress, IN ULONG Length)
Definition: iomdl.c:96
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
_In_ PIRP Irp
Definition: kse.h:79
static NTSTATUS NTAPI NtfsIoRunCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
Definition: blockdev.c:162
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:647
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1698
Definition: bidi.c:435
unsigned char * PUCHAR
Definition: typedefs.h:53
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_In_ UCHAR MajorFunction
Definition: wdfdevice.h:1703
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3777
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2702
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
#define IRP_NOCACHE

Referenced by NtfsIssueIoRuns().

◆ NtfsDeviceIoControl()

NTSTATUS NtfsDeviceIoControl ( IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  ControlCode,
IN PVOID  InputBuffer,
IN ULONG  InputBufferSize,
IN OUT PVOID  OutputBuffer,
IN OUT PULONG  OutputBufferSize,
IN BOOLEAN  Override 
)

Definition at line 1029 of file blockdev.c.

1036{
1039 KEVENT Event;
1040 PIRP Irp;
1042
1044
1045 IoStatus.Status = STATUS_SUCCESS;
1046 IoStatus.Information = 0;
1047
1048 DPRINT("Building device I/O control request ...\n");
1055 FALSE,
1056 &Event,
1057 &IoStatus);
1058 if (Irp == NULL)
1059 {
1060 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
1062 }
1063
1064 if (Override)
1065 {
1068 }
1069
1070 DPRINT("Calling IO Driver... with irp %p\n", Irp);
1072 if (Status == STATUS_PENDING)
1073 {
1075 Status = IoStatus.Status;
1076 }
1077
1078 if (OutputBufferSize)
1079 {
1080 *OutputBufferSize = IoStatus.Information;
1081 }
1082
1083 return Status;
1084}
LONG NTSTATUS
Definition: precomp.h:26
_In_ ULONG InputBufferSize
Definition: dispmprt.h:616
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
Definition: dispmprt.h:1287
_In_ ULONG _In_ ULONG OutputBufferSize
Definition: dispmprt.h:618
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
Status
Definition: gdiplustypes.h:24
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define KernelMode
Definition: asm.h:38
@ NotificationEvent
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:913
#define IoCallDriver
Definition: irp.c:1257
#define DPRINT
Definition: sndvol32.h:73
#define STATUS_PENDING
Definition: telnetd.h:14
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
_IRQL_requires_same_ typedef _In_ ULONG ControlCode
Definition: wmitypes.h:55
@ Executive
Definition: ketypes.h:467

Referenced by NtfsGetVolumeData(), and NtfsHasFileSystem().

◆ NtfsFlushDevice()

NTSTATUS NtfsFlushDevice ( IN PDEVICE_OBJECT  DeviceObject)

Definition at line 964 of file blockdev.c.

965{
966 NTFS_IO_CONTEXT IoContext;
969 PIRP Irp;
970
971 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
972 if (Irp == NULL)
973 {
974 DPRINT1("IoAllocateIrp failed!\n");
976 }
977
978 RtlZeroMemory(&IoContext, sizeof(IoContext));
980 IoContext.Status = STATUS_SUCCESS;
981 IoContext.IrpCount = 1;
982
984 Stack->MajorFunction = IRP_MJ_FLUSH_BUFFERS;
985
988 &IoContext,
989 TRUE,
990 TRUE,
991 TRUE);
992
994
996
997 Status = (NTSTATUS)IoContext.Status;
998
1001 {
1003 }
1004
1005 DPRINT("NtfsFlushDevice() done (Status %lx)\n", Status);
1006
1007 return Status;
1008}
#define VOID
Definition: acefi.h:82
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define NTSTATUS
Definition: precomp.h:19
if(dx< 0)
Definition: linetemp.h:194
volatile LONG IrpCount
Definition: ntfs.h:539
volatile LONG Status
Definition: ntfs.h:540
KEVENT SyncEvent
Definition: ntfs.h:550
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define IRP_MJ_FLUSH_BUFFERS

Referenced by NtfsFlushBuffers().

◆ NtfsForwardedIrpCompletionRoutine()

static NTSTATUS NTAPI NtfsForwardedIrpCompletionRoutine ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Context 
)
static

Definition at line 642 of file blockdev.c.

645{
647
649
650 IoContext->Status = Irp->IoStatus.Status;
651 IoContext->BytesTransferred = (LONG)Irp->IoStatus.Information;
652
654
656}
struct _NTFS_IO_CONTEXT * PNTFS_IO_CONTEXT
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
long LONG
Definition: pedump.c:60
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
volatile LONG BytesTransferred
Definition: ntfs.h:541
#define IO_NO_INCREMENT
Definition: iotypes.h:598

Referenced by NtfsForwardIrpToRun().

◆ NtfsForwardIrpToRun()

static NTSTATUS NtfsForwardIrpToRun ( IN PDEVICE_OBJECT  DeviceObject,
IN UCHAR  MajorFunction,
IN PIRP  Irp,
IN PNTFS_IO_RUN  Run,
IN BOOLEAN  Override,
OUT PULONG  BytesTransferred 
)
static

Definition at line 663 of file blockdev.c.

669{
670 NTFS_IO_CONTEXT IoContext;
672
673 DPRINT("Forwarding IRP %p for a single run at %I64x, %lu bytes\n",
674 Irp, Run->Lbo, Run->ByteCount);
675
676 RtlZeroMemory(&IoContext, sizeof(IoContext));
678 IoContext.Status = STATUS_SUCCESS;
679
681 Stack->MajorFunction = MajorFunction;
682 Stack->MinorFunction = 0;
683 Stack->FileObject = NULL;
684 Stack->Parameters.Read.Length = Run->ByteCount;
685 Stack->Parameters.Read.ByteOffset.QuadPart = Run->Lbo;
686 Stack->Flags = Override ? SL_OVERRIDE_VERIFY_VOLUME : 0;
687
688 /* Must come last: it takes over Control on this same stack location. */
691 &IoContext,
692 TRUE,
693 TRUE,
694 TRUE);
695
697
699
701
702 return (NTSTATUS)IoContext.Status;
703}
return
Definition: dirsup.c:529
static NTSTATUS NTAPI NtfsForwardedIrpCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
Definition: blockdev.c:642
_Must_inspect_result_ _In_ WDFUSBDEVICE _In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_SEND_OPTIONS _In_ PWDF_USB_CONTROL_SETUP_PACKET _In_opt_ PWDF_MEMORY_DESCRIPTOR _Out_opt_ PULONG BytesTransferred
Definition: wdfusb.h:1342

Referenced by NtfsPerformIrpIoRuns().

◆ NtfsFreeIoRunList()

VOID NtfsFreeIoRunList ( IN OUT PNTFS_IO_RUN_LIST  RunList)

Definition at line 140 of file blockdev.c.

141{
142 if (RunList->Runs != RunList->StackRuns && RunList->Runs != NULL)
143 {
144 ExFreePoolWithTag(RunList->Runs, TAG_IO_RUNS);
145 }
146
147 RunList->Runs = NULL;
148 RunList->Count = 0;
149 RunList->Capacity = 0;
150 RunList->TotalLength = 0;
151}

Referenced by NtfsReadDisk(), NtfsReadWriteVolume(), NtfsWriteDisk(), ReadAttributeToIrp(), and WriteAttributeFromIrp().

◆ NtfsInitIoRunList()

VOID NtfsInitIoRunList ( OUT PNTFS_IO_RUN_LIST  RunList)

Definition at line 40 of file blockdev.c.

41{
42 RunList->Runs = RunList->StackRuns;
43 RunList->Capacity = NTFS_MAX_IO_RUNS_ON_STACK;
44 RunList->Count = 0;
45 RunList->TotalLength = 0;
46}
#define NTFS_MAX_IO_RUNS_ON_STACK
Definition: ntfs.h:513

Referenced by NtfsReadDisk(), NtfsReadWriteVolume(), NtfsWriteDisk(), ReadAttributeToIrp(), and WriteAttributeFromIrp().

◆ NtfsIoRunCompletionRoutine()

static NTSTATUS NTAPI NtfsIoRunCompletionRoutine ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Context 
)
static

Definition at line 162 of file blockdev.c.

165{
167
169
170 if (NT_SUCCESS(Irp->IoStatus.Status))
171 {
173 (LONG)Irp->IoStatus.Information);
174 }
175 else
176 {
177 /* First error wins; STATUS_SUCCESS is the "nothing failed yet" sentinel. */
179 Irp->IoStatus.Status,
181 }
182
183 /* The master MDL belongs to the issuer and outlives every run built from it. */
184 if (Irp->MdlAddress != NULL && Irp->MdlAddress != IoContext->MasterMdl)
185 {
186 IoFreeMdl(Irp->MdlAddress);
187 }
188
189 IoFreeIrp(Irp);
190
191 if (InterlockedDecrement(&IoContext->IrpCount) == 0)
192 {
194 }
195
197}
#define InterlockedDecrement
Definition: armddk.h:52
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define IoFreeMdl
Definition: fxmdl.h:89
#define InterlockedExchangeAdd
Definition: interlocked.h:196
#define InterlockedCompareExchange
Definition: interlocked.h:119
PMDL MasterMdl
Definition: ntfs.h:546

Referenced by NtfsBuildIoRunIrp(), and NtfsFlushDevice().

◆ NtfsIssueIoRuns()

static NTSTATUS NtfsIssueIoRuns ( IN PDEVICE_OBJECT  DeviceObject,
IN UCHAR  MajorFunction,
IN OUT PUCHAR  Buffer,
IN PMDL BorrowedMdl  OPTIONAL,
IN PNTFS_IO_RUN_LIST  RunList,
IN BOOLEAN  Override,
OUT PULONG  BytesTransferred 
)
static

Definition at line 276 of file blockdev.c.

283{
284 NTFS_IO_CONTEXT IoContext;
287 ULONG DiskRunCount = 0;
288 ULONG Index;
289 ULONG BuiltCount = 0;
290 PIRP Irp;
291
292 *BytesTransferred = 0;
293
294 RtlZeroMemory(&IoContext, sizeof(IoContext));
296 IoContext.Status = STATUS_SUCCESS;
297
298 /* Satisfy the sparse runs, and see if any real I/O is left */
299 for (Index = 0; Index < RunList->Count; Index++)
300 {
301 Run = &RunList->Runs[Index];
302
303 if (Run->Lbo != NTFS_SPARSE_LBO)
304 {
305 DiskRunCount++;
306 continue;
307 }
308
310 {
311 DPRINT1("FIXME: Writing to sparse files is not supported yet!\n");
313 }
314
315 RtlZeroMemory(Buffer + Run->BufferOffset, Run->ByteCount);
316 *BytesTransferred += Run->ByteCount;
317 }
318
319 if (DiskRunCount == 0)
320 {
321 return STATUS_SUCCESS;
322 }
323
324 if (BorrowedMdl != NULL)
325 {
326 IoContext.MasterMdl = BorrowedMdl;
327 IoContext.MasterVa = MmGetMdlVirtualAddress(BorrowedMdl);
328 IoContext.OwnsMasterMdl = FALSE;
329 }
330 else
331 {
332 /* Our own buffer: describe and lock it once */
333 IoContext.MasterMdl = IoAllocateMdl(Buffer, RunList->TotalLength, FALSE, FALSE, NULL);
334 if (IoContext.MasterMdl == NULL)
335 {
336 DPRINT1("IoAllocateMdl failed!\n");
338 }
339
341 {
345 }
347 {
349 }
350 _SEH2_END;
351
352 if (!NT_SUCCESS(Status))
353 {
354 DPRINT1("MmProbeAndLockPages failed (Status %lx)\n", Status);
355 IoFreeMdl(IoContext.MasterMdl);
356 return Status;
357 }
358
359 IoContext.MasterVa = Buffer;
360 IoContext.OwnsMasterMdl = TRUE;
361 }
362
363 /* Build everything before issuing anything */
364 for (Index = 0; Index < RunList->Count; Index++)
365 {
366 Run = &RunList->Runs[Index];
367
368 if (Run->Lbo == NTFS_SPARSE_LBO)
369 continue;
370
372 &IoContext,
374 Buffer,
375 RunList->TotalLength,
376 Run,
377 Override);
378 if (!NT_SUCCESS(Status))
379 break;
380
381 BuiltCount++;
382 }
383
384 if (!NT_SUCCESS(Status))
385 {
386 for (Index = 0; Index < RunList->Count; Index++)
387 {
388 Run = &RunList->Runs[Index];
389
390 if (Run->SavedIrp == NULL)
391 continue;
392
393 if (Run->SavedIrp->MdlAddress != NULL &&
394 Run->SavedIrp->MdlAddress != IoContext.MasterMdl)
395 {
396 IoFreeMdl(Run->SavedIrp->MdlAddress);
397 }
398
399 IoFreeIrp(Run->SavedIrp);
400 Run->SavedIrp = NULL;
401 }
402
403 if (IoContext.OwnsMasterMdl)
404 {
405 MmUnlockPages(IoContext.MasterMdl);
406 IoFreeMdl(IoContext.MasterMdl);
407 }
408
409 return Status;
410 }
411
412 /* Publish the count before the first completion routine can run. */
413 IoContext.IrpCount = BuiltCount;
414
415 for (Index = 0; Index < RunList->Count; Index++)
416 {
417 Run = &RunList->Runs[Index];
418
419 if (Run->SavedIrp == NULL)
420 continue;
421
422 /* The completion routine frees the IRP, so drop our pointer first */
423 Irp = Run->SavedIrp;
424 Run->SavedIrp = NULL;
425
426 /* A failure here is completed by the lower driver and picked up by
427 * our completion routine like any other I/O error */
429 }
430
432
433 if (IoContext.OwnsMasterMdl)
434 {
435 MmUnlockPages(IoContext.MasterMdl);
436 IoFreeMdl(IoContext.MasterMdl);
437 }
438
439 Status = (NTSTATUS)IoContext.Status;
441 {
443 }
444
445 return Status;
446}
Definition: bufpool.h:45
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
struct tagRun Run
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:928
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1432
static NTSTATUS NtfsBuildIoRunIrp(IN PDEVICE_OBJECT DeviceObject, IN PNTFS_IO_CONTEXT IoContext, IN UCHAR MajorFunction, IN PUCHAR Buffer, IN ULONG BufferLength, IN OUT PNTFS_IO_RUN Run, IN BOOLEAN Override)
Definition: blockdev.c:204
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
#define IRP_MJ_READ
Definition: rdpdr.c:46
PVOID MasterVa
Definition: ntfs.h:547
BOOLEAN OwnsMasterMdl
Definition: ntfs.h:548
_In_ WDFCOLLECTION _In_ ULONG Index
@ IoReadAccess
Definition: ketypes.h:931
@ IoWriteAccess
Definition: ketypes.h:932
#define MmGetMdlVirtualAddress(_Mdl)

Referenced by NtfsPerformIoRunsInternal().

◆ NtfsPerformIoRuns()

NTSTATUS NtfsPerformIoRuns ( IN PDEVICE_OBJECT  DeviceObject,
IN UCHAR  MajorFunction,
IN ULONG  SectorSize,
IN OUT PUCHAR  Buffer,
IN PNTFS_IO_RUN_LIST  RunList,
IN BOOLEAN  Override,
OUT PULONG BytesTransferred  OPTIONAL 
)

Definition at line 788 of file blockdev.c.

795{
799 Buffer,
800 NULL,
801 RunList,
802 Override,
804}
static NTSTATUS NtfsPerformIoRunsInternal(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN PMDL BorrowedMdl OPTIONAL, IN PNTFS_IO_RUN_LIST RunList, IN BOOLEAN Override, OUT PULONG BytesTransferred OPTIONAL)
Definition: blockdev.c:483
_In_ ULONG SectorSize
Definition: halfuncs.h:291

Referenced by NtfsReadDisk(), and NtfsWriteDisk().

◆ NtfsPerformIoRunsInternal()

static NTSTATUS NtfsPerformIoRunsInternal ( IN PDEVICE_OBJECT  DeviceObject,
IN UCHAR  MajorFunction,
IN ULONG  SectorSize,
IN OUT PUCHAR  Buffer,
IN PMDL BorrowedMdl  OPTIONAL,
IN PNTFS_IO_RUN_LIST  RunList,
IN BOOLEAN  Override,
OUT PULONG BytesTransferred  OPTIONAL 
)
static

Definition at line 483 of file blockdev.c.

491{
493 PNTFS_IO_RUN FirstRun;
494 PNTFS_IO_RUN LastRun;
495 PUCHAR BounceBuffer;
496 LONGLONG EndLbo;
497 ULONG FrontPad = 0;
498 ULONG BackPad = 0;
499 ULONG BounceLength;
500 ULONG Transferred = 0;
501 ULONG Index;
503
504 if (BytesTransferred != NULL)
505 *BytesTransferred = 0;
506
507 if (RunList->Count == 0 || RunList->TotalLength == 0)
508 return STATUS_SUCCESS;
509
510 ASSERT(SectorSize != 0);
511
512 Length = RunList->TotalLength;
513 FirstRun = &RunList->Runs[0];
514 LastRun = &RunList->Runs[RunList->Count - 1];
515
516 /* Only the first run can start unaligned and only the last can end
517 * unaligned; the rest sit on cluster boundaries */
518 if (FirstRun->Lbo != NTFS_SPARSE_LBO)
519 {
520 FrontPad = (ULONG)(FirstRun->Lbo % SectorSize);
521 }
522
523 if (LastRun->Lbo != NTFS_SPARSE_LBO)
524 {
525 EndLbo = LastRun->Lbo + LastRun->ByteCount;
526 BackPad = (ULONG)(ROUND_UP(EndLbo, (LONGLONG)SectorSize) - EndLbo);
527 }
528
529 if (FrontPad == 0 && BackPad == 0)
530 {
533 Buffer,
534 BorrowedMdl,
535 RunList,
536 Override,
537 &Transferred);
538
539 if (BytesTransferred != NULL)
540 *BytesTransferred = min(Transferred, Length);
541
542 return Status;
543 }
544
545 BounceLength = FrontPad + Length + BackPad;
546
547 BounceBuffer = ExAllocatePoolWithTag(NonPagedPool, BounceLength, TAG_NTFS);
548 if (BounceBuffer == NULL)
549 {
550 DPRINT1("Not enough memory for an unaligned transfer!\n");
552 }
553
554 /* Grow the request out to whole sectors; everything after the first run
555 * slides along by what we prepended */
556 for (Index = 1; Index < RunList->Count; Index++)
557 {
558 RunList->Runs[Index].BufferOffset += FrontPad;
559 }
560
561 FirstRun->BufferOffset = 0;
562 FirstRun->ByteCount += FrontPad;
563 if (FirstRun->Lbo != NTFS_SPARSE_LBO)
564 FirstRun->Lbo -= FrontPad;
565
566 LastRun->ByteCount += BackPad;
567 RunList->TotalLength = BounceLength;
568
570
572 {
573 if (FrontPad != 0)
574 {
576 FirstRun->Lbo,
579 BounceBuffer,
580 Override);
581 }
582
583 /* Skip only if the read above already fetched this same sector */
584 if (NT_SUCCESS(Status) &&
585 BackPad != 0 &&
586 (FrontPad == 0 || BounceLength > SectorSize))
587 {
589 LastRun->Lbo + LastRun->ByteCount - SectorSize,
592 BounceBuffer + BounceLength - SectorSize,
593 Override);
594 }
595
596 if (NT_SUCCESS(Status))
597 {
598 RtlCopyMemory(BounceBuffer + FrontPad, Buffer, Length);
599 }
600 }
601
602 if (NT_SUCCESS(Status))
603 {
604 /* The bounce buffer is ours, so there is no MDL to borrow here. */
607 BounceBuffer,
608 NULL,
609 RunList,
610 Override,
611 &Transferred);
612
613 if (NT_SUCCESS(Status))
614 {
616 {
617 RtlCopyMemory(Buffer, BounceBuffer + FrontPad, Length);
618 }
619
620 if (BytesTransferred != NULL)
621 {
622 /* The padding is ours, not the caller's. */
623 Transferred = (Transferred > FrontPad) ? Transferred - FrontPad : 0;
624 *BytesTransferred = min(Transferred, Length);
625 }
626 }
627 }
628
629 /* The bounce buffer can hold user data; do not leave it in pool. */
630 RtlSecureZeroMemory(BounceBuffer, BounceLength);
631 ExFreePoolWithTag(BounceBuffer, TAG_NTFS);
632
633 return Status;
634}
#define TAG_NTFS
Definition: ntfs.h:12
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
#define ASSERT(a)
Definition: mode.c:44
#define min(a, b)
Definition: monoChain.cc:55
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
static NTSTATUS NtfsIssueIoRuns(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN OUT PUCHAR Buffer, IN PMDL BorrowedMdl OPTIONAL, IN PNTFS_IO_RUN_LIST RunList, IN BOOLEAN Override, OUT PULONG BytesTransferred)
Definition: blockdev.c:276
NTSTATUS NtfsReadDisk(IN PDEVICE_OBJECT DeviceObject, IN LONGLONG StartingOffset, IN ULONG Length, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
Definition: blockdev.c:836
int64_t LONGLONG
Definition: typedefs.h:68
FORCEINLINE PVOID RtlSecureZeroMemory(_Out_writes_bytes_all_(Size) PVOID Pointer, _In_ SIZE_T Size)
Definition: rtlfuncs.h:3149

Referenced by NtfsPerformIoRuns(), and NtfsPerformIrpIoRuns().

◆ NtfsPerformIrpIoRuns()

NTSTATUS NtfsPerformIrpIoRuns ( IN PDEVICE_OBJECT  DeviceObject,
IN UCHAR  MajorFunction,
IN ULONG  SectorSize,
IN PIRP  Irp,
IN OUT PUCHAR  Buffer,
IN PNTFS_IO_RUN_LIST  RunList,
IN BOOLEAN  Override,
OUT PULONG  BytesTransferred 
)

Definition at line 743 of file blockdev.c.

751{
752 PMDL BorrowedMdl = NULL;
753
754 if (Irp != NULL &&
755 Irp->MdlAddress != NULL &&
756 RunList->TotalLength <= MmGetMdlByteCount(Irp->MdlAddress))
757 {
758 /* Buffer maps exactly the pages this MDL describes, so it can stand
759 * in for one of our own, and on the paging path it must */
760 BorrowedMdl = Irp->MdlAddress;
761
762 /* One aligned run covering the lot goes straight down to the disk */
763 if (RunList->Count == 1 &&
764 RunList->Runs[0].Lbo != NTFS_SPARSE_LBO &&
765 (RunList->Runs[0].Lbo % SectorSize) == 0 &&
766 (RunList->Runs[0].ByteCount % SectorSize) == 0)
767 {
770 Irp,
771 &RunList->Runs[0],
772 Override,
774 }
775 }
776
780 Buffer,
781 BorrowedMdl,
782 RunList,
783 Override,
785}
static NTSTATUS NtfsForwardIrpToRun(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN PIRP Irp, IN PNTFS_IO_RUN Run, IN BOOLEAN Override, OUT PULONG BytesTransferred)
Definition: blockdev.c:663
#define MmGetMdlByteCount(_Mdl)

Referenced by NtfsReadWriteVolume(), ReadAttributeToIrp(), and WriteAttributeFromIrp().

◆ NtfsReadDisk()

NTSTATUS NtfsReadDisk ( IN PDEVICE_OBJECT  DeviceObject,
IN LONGLONG  StartingOffset,
IN ULONG  Length,
IN ULONG  SectorSize,
IN OUT PUCHAR  Buffer,
IN BOOLEAN  Override 
)

Definition at line 836 of file blockdev.c.

842{
843 NTFS_IO_RUN_LIST RunList;
845 ULONG Transferred;
846
847 DPRINT("NtfsReadDisk(%p, %I64x, %lu, %lu, %p, %d)\n",
849
850 if (Length == 0)
851 return STATUS_SUCCESS;
852
853 NtfsInitIoRunList(&RunList);
854
856 if (!NT_SUCCESS(Status))
857 return Status;
858
862 Buffer,
863 &RunList,
864 Override,
865 &Transferred);
866
867 NtfsFreeIoRunList(&RunList);
868
869 if (NT_SUCCESS(Status) && Transferred != Length)
870 {
871 DPRINT1("Short read: asked for %lu bytes, got %lu\n", Length, Transferred);
873 }
874
875 DPRINT("NtfsReadDisk() done (Status %x)\n", Status);
876
877 return Status;
878}
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
NTSTATUS NtfsPerformIoRuns(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN PNTFS_IO_RUN_LIST RunList, IN BOOLEAN Override, OUT PULONG BytesTransferred OPTIONAL)
Definition: blockdev.c:788
VOID NtfsFreeIoRunList(IN OUT PNTFS_IO_RUN_LIST RunList)
Definition: blockdev.c:140
NTSTATUS NtfsAddIoRun(IN OUT PNTFS_IO_RUN_LIST RunList, IN LONGLONG Lbo, IN ULONG ByteCount)
Definition: blockdev.c:74
VOID NtfsInitIoRunList(OUT PNTFS_IO_RUN_LIST RunList)
Definition: blockdev.c:40
#define STATUS_UNEXPECTED_IO_ERROR
Definition: ntstatus.h:563

Referenced by NtfsPerformIoRunsInternal(), and NtfsReadSectors().

◆ NtfsReadSectors()

NTSTATUS NtfsReadSectors ( IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  DiskSector,
IN ULONG  SectorCount,
IN ULONG  SectorSize,
IN OUT PUCHAR  Buffer,
IN BOOLEAN  Override 
)

Definition at line 1011 of file blockdev.c.

1017{
1020
1021 Offset = (LONGLONG)DiskSector * (LONGLONG)SectorSize;
1023
1025}
D3D12_VIDEO_MOTION_ESTIMATOR_SEARCH_BLOCK_SIZE BlockSize
Definition: d3d12video.idl:529
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
ULONG SectorCount
Definition: part_brfr.c:22

Referenced by NtfsGetVolumeData(), NtfsHasFileSystem(), and ReadLCN().

◆ NtfsWriteDisk()

NTSTATUS NtfsWriteDisk ( IN PDEVICE_OBJECT  DeviceObject,
IN LONGLONG  StartingOffset,
IN ULONG  Length,
IN ULONG  SectorSize,
IN const PUCHAR  Buffer 
)

Definition at line 907 of file blockdev.c.

912{
913 NTFS_IO_RUN_LIST RunList;
915 ULONG Transferred;
916
917 DPRINT("NtfsWriteDisk(%p, %I64x, %lu, %lu, %p)\n",
919
920 if (Length == 0)
921 return STATUS_SUCCESS;
922
923 NtfsInitIoRunList(&RunList);
924
926 if (!NT_SUCCESS(Status))
927 return Status;
928
932 Buffer,
933 &RunList,
934 FALSE,
935 &Transferred);
936
937 NtfsFreeIoRunList(&RunList);
938
939 if (NT_SUCCESS(Status) && Transferred != Length)
940 {
941 DPRINT1("Short write: asked for %lu bytes, wrote %lu\n", Length, Transferred);
943 }
944
945 DPRINT("NtfsWriteDisk() done (Status %x)\n", Status);
946
947 return Status;
948}
#define IRP_MJ_WRITE
Definition: rdpdr.c:47