Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfastfat.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS FAT file system driver 00003 * LICENSE: GNU GPLv3 as published by the Free Software Foundation 00004 * FILE: drivers/filesystems/fastfat/fastfat.c 00005 * PURPOSE: Initialization routines 00006 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org) 00007 */ 00008 00009 /* INCLUDES *****************************************************************/ 00010 00011 #define NDEBUG 00012 #include "fastfat.h" 00013 00014 /* GLOBALS ******************************************************************/ 00015 00016 FAT_GLOBAL_DATA FatGlobalData; 00017 FAST_MUTEX FatCloseQueueMutex; 00018 00019 /* FUNCTIONS ****************************************************************/ 00020 00021 00022 NTSTATUS 00023 NTAPI 00024 DriverEntry(PDRIVER_OBJECT DriverObject, 00025 PUNICODE_STRING RegistryPath) 00026 { 00027 PDEVICE_OBJECT DeviceObject; 00028 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Fat"); 00029 NTSTATUS Status; 00030 00031 /* Create a device object */ 00032 Status = IoCreateDevice(DriverObject, 00033 0, 00034 &DeviceName, 00035 FILE_DEVICE_DISK_FILE_SYSTEM, 00036 0, 00037 FALSE, 00038 &DeviceObject); 00039 00040 if (!NT_SUCCESS(Status)) return Status; 00041 00042 /* Zero global storage */ 00043 RtlZeroMemory(&FatGlobalData, sizeof(FAT_GLOBAL_DATA)); 00044 FatGlobalData.DriverObject = DriverObject; 00045 FatGlobalData.DiskDeviceObject = DeviceObject; 00046 FatGlobalData.SystemProcess = PsGetCurrentProcess(); 00047 00048 /* Fill major function handlers */ 00049 DriverObject->MajorFunction[IRP_MJ_CLOSE] = FatClose; 00050 DriverObject->MajorFunction[IRP_MJ_CREATE] = FatCreate; 00051 DriverObject->MajorFunction[IRP_MJ_READ] = FatRead; 00052 DriverObject->MajorFunction[IRP_MJ_WRITE] = FatWrite; 00053 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FatFileSystemControl; 00054 DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = FatQueryInformation; 00055 DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = FatSetInformation; 00056 DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = FatDirectoryControl; 00057 DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = FatQueryVolumeInfo; 00058 DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = FatSetVolumeInfo; 00059 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = FatShutdown; 00060 DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = FatLockControl; 00061 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FatDeviceControl; 00062 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FatCleanup; 00063 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = FatFlushBuffers; 00064 //DriverObject->MajorFunction[IRP_MJ_QUERY_EA] 00065 //DriverObject->MajorFunction[IRP_MJ_SET_EA] 00066 //DriverObject->MajorFunction[IRP_MJ_PNP] 00067 00068 DriverObject->DriverUnload = NULL; 00069 00070 /* Initialize cache manager callbacks */ 00071 FatGlobalData.CacheMgrCallbacks.AcquireForLazyWrite = FatAcquireForLazyWrite; 00072 FatGlobalData.CacheMgrCallbacks.ReleaseFromLazyWrite = FatReleaseFromLazyWrite; 00073 FatGlobalData.CacheMgrCallbacks.AcquireForReadAhead = FatAcquireForReadAhead; 00074 FatGlobalData.CacheMgrCallbacks.ReleaseFromReadAhead = FatReleaseFromReadAhead; 00075 00076 FatGlobalData.CacheMgrNoopCallbacks.AcquireForLazyWrite = FatNoopAcquire; 00077 FatGlobalData.CacheMgrNoopCallbacks.ReleaseFromLazyWrite = FatNoopRelease; 00078 FatGlobalData.CacheMgrNoopCallbacks.AcquireForReadAhead = FatNoopAcquire; 00079 FatGlobalData.CacheMgrNoopCallbacks.ReleaseFromReadAhead = FatNoopRelease; 00080 00081 /* Initialize Fast I/O dispatchers */ 00082 FatInitFastIoRoutines(&FatGlobalData.FastIoDispatch); 00083 DriverObject->FastIoDispatch = &FatGlobalData.FastIoDispatch; 00084 00085 /* Initialize lookaside lists */ 00086 ExInitializeNPagedLookasideList(&FatGlobalData.NonPagedFcbList, 00087 NULL, 00088 NULL, 00089 0, 00090 sizeof(FCB), 00091 TAG_FCB, 00092 0); 00093 00094 ExInitializeNPagedLookasideList(&FatGlobalData.ResourceList, 00095 NULL, 00096 NULL, 00097 0, 00098 sizeof(ERESOURCE), 00099 TAG_CCB, 00100 0); 00101 00102 ExInitializeNPagedLookasideList(&FatGlobalData.IrpContextList, 00103 NULL, 00104 NULL, 00105 0, 00106 sizeof(FAT_IRP_CONTEXT), 00107 TAG_IRP, 00108 0); 00109 00110 /* Initialize synchronization resource for the global data */ 00111 ExInitializeResourceLite(&FatGlobalData.Resource); 00112 00113 /* Initialize queued close stuff */ 00114 InitializeListHead(&FatGlobalData.AsyncCloseList); 00115 InitializeListHead(&FatGlobalData.DelayedCloseList); 00116 FatGlobalData.FatCloseItem = IoAllocateWorkItem(DeviceObject); 00117 ExInitializeFastMutex(&FatCloseQueueMutex); 00118 00119 /* Initialize global VCB list */ 00120 InitializeListHead(&FatGlobalData.VcbListHead); 00121 00122 /* Register and reference our filesystem */ 00123 IoRegisterFileSystem(DeviceObject); 00124 ObReferenceObject(DeviceObject); 00125 return STATUS_SUCCESS; 00126 } 00127 00128 PFAT_IRP_CONTEXT 00129 NTAPI 00130 FatBuildIrpContext(PIRP Irp, 00131 BOOLEAN CanWait) 00132 { 00133 PIO_STACK_LOCATION IrpSp; 00134 PFAT_IRP_CONTEXT IrpContext; 00135 PVOLUME_DEVICE_OBJECT VolumeObject; 00136 00137 /* Get current IRP stack location */ 00138 IrpSp = IoGetCurrentIrpStackLocation(Irp); 00139 00140 /* Allocate memory for the Irp context */ 00141 IrpContext = ExAllocateFromNPagedLookasideList(&FatGlobalData.IrpContextList); 00142 00143 /* Zero init memory */ 00144 RtlZeroMemory(IrpContext, sizeof(FAT_IRP_CONTEXT)); 00145 00146 /* Save IRP, MJ and MN */ 00147 IrpContext->Irp = Irp; 00148 IrpContext->Stack = IrpSp; 00149 IrpContext->MajorFunction = IrpSp->MajorFunction; 00150 IrpContext->MinorFunction = IrpSp->MinorFunction; 00151 00152 /* Set DeviceObject */ 00153 if (IrpSp->FileObject) 00154 { 00155 IrpContext->DeviceObject = IrpSp->FileObject->DeviceObject; 00156 00157 /* Save VCB pointer */ 00158 VolumeObject = (PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject; 00159 IrpContext->Vcb = &VolumeObject->Vcb; 00160 00161 /* TODO: Handle write-through */ 00162 } 00163 else if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) 00164 { 00165 /* Handle FSCTRL case */ 00166 IrpContext->DeviceObject = IrpSp->Parameters.MountVolume.Vpb->RealDevice; 00167 } 00168 00169 /* Set Wait flag */ 00170 if (CanWait) IrpContext->Flags |= IRPCONTEXT_CANWAIT; 00171 00172 /* Return prepared context */ 00173 return IrpContext; 00174 } 00175 00176 VOID 00177 NTAPI 00178 FatDestroyIrpContext(PFAT_IRP_CONTEXT IrpContext) 00179 { 00180 PAGED_CODE(); 00181 00182 /* Make sure it has no pinned stuff */ 00183 ASSERT(IrpContext->PinCount == 0); 00184 00185 /* If there is a FatIo context associated with it - free it */ 00186 if (IrpContext->FatIoContext) 00187 { 00188 if (!(IrpContext->Flags & IRPCONTEXT_STACK_IO_CONTEXT)) 00189 { 00190 /* If a zero mdl was allocated - free it */ 00191 if (IrpContext->FatIoContext->ZeroMdl) 00192 IoFreeMdl(IrpContext->FatIoContext->ZeroMdl); 00193 00194 /* Free memory of FatIo context */ 00195 ExFreePool(IrpContext->FatIoContext); 00196 } 00197 } 00198 00199 /* Free memory */ 00200 ExFreeToNPagedLookasideList(&FatGlobalData.IrpContextList, IrpContext); 00201 } 00202 00203 VOID 00204 NTAPI 00205 FatCompleteRequest(PFAT_IRP_CONTEXT IrpContext OPTIONAL, 00206 PIRP Irp OPTIONAL, 00207 NTSTATUS Status) 00208 { 00209 PAGED_CODE(); 00210 00211 if (IrpContext) 00212 { 00213 /* TODO: Unpin repinned BCBs */ 00214 //ASSERT(IrpContext->Repinned.Bcb[0] == NULL); 00215 //FatUnpinRepinnedBcbs( IrpContext ); 00216 00217 /* Destroy IRP context */ 00218 FatDestroyIrpContext(IrpContext); 00219 } 00220 00221 /* Complete the IRP */ 00222 if (Irp) 00223 { 00224 /* Cleanup IoStatus.Information in case of error input operation */ 00225 if (NT_ERROR(Status) && (Irp->Flags & IRP_INPUT_OPERATION)) 00226 { 00227 Irp->IoStatus.Information = 0; 00228 } 00229 00230 /* Save status and complete this IRP */ 00231 Irp->IoStatus.Status = Status; 00232 IoCompleteRequest( Irp, IO_DISK_INCREMENT ); 00233 } 00234 } 00235 00236 VOID 00237 NTAPI 00238 FatDequeueRequest(IN PVOID Context) 00239 { 00240 PFAT_IRP_CONTEXT IrpContext; 00241 00242 IrpContext = (PFAT_IRP_CONTEXT) Context; 00243 00244 /* Enter critical region. */ 00245 FsRtlEnterFileSystem(); 00246 00247 /* Handle top level IRP Correctly. */ 00248 if (!FlagOn(IrpContext->Flags, IRPCONTEXT_TOPLEVEL)) 00249 IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP); 00250 00251 /* Enable Synchronous IO. */ 00252 SetFlag(IrpContext->Flags, IRPCONTEXT_CANWAIT); 00253 00254 /* Invoke the handler routine. */ 00255 IrpContext->QueuedOperationHandler(IrpContext); 00256 00257 /* Restore top level IRP. */ 00258 IoSetTopLevelIrp(NULL); 00259 00260 /* Leave critical region. */ 00261 FsRtlExitFileSystem(); 00262 } 00263 00264 VOID 00265 NTAPI 00266 FatQueueRequest(IN PFAT_IRP_CONTEXT IrpContext, 00267 IN PFAT_OPERATION_HANDLER OperationHandler) 00268 { 00269 /* Save the worker routine. */ 00270 IrpContext->QueuedOperationHandler = OperationHandler; 00271 00272 /* Indicate if top level IRP was set. */ 00273 if (IoGetTopLevelIrp() == IrpContext->Irp) 00274 SetFlag(IrpContext->Flags, IRPCONTEXT_TOPLEVEL); 00275 00276 /* Initialize work item. */ 00277 ExInitializeWorkItem(&IrpContext->WorkQueueItem, 00278 FatDequeueRequest, 00279 IrpContext); 00280 ExQueueWorkItem(&IrpContext->WorkQueueItem, 00281 DelayedWorkQueue); 00282 } 00283 00284 TYPE_OF_OPEN 00285 NTAPI 00286 FatDecodeFileObject(IN PFILE_OBJECT FileObject, 00287 OUT PVCB *Vcb, 00288 OUT PFCB *FcbOrDcb, 00289 OUT PCCB *Ccb) 00290 { 00291 TYPE_OF_OPEN TypeOfOpen = UnopenedFileObject; 00292 PVOID FsContext = FileObject->FsContext; 00293 PVOID FsContext2 = FileObject->FsContext2; 00294 00295 /* If FsContext is NULL, then everything is NULL */ 00296 if (!FsContext) 00297 { 00298 *Ccb = NULL; 00299 *FcbOrDcb = NULL; 00300 *Vcb = NULL; 00301 00302 return TypeOfOpen; 00303 } 00304 00305 /* CCB is always stored in FsContext2 */ 00306 *Ccb = FsContext2; 00307 00308 /* Switch according to the NodeType */ 00309 switch (FatNodeType(FsContext)) 00310 { 00311 /* Volume */ 00312 case FAT_NTC_VCB: 00313 *FcbOrDcb = NULL; 00314 *Vcb = FsContext; 00315 00316 TypeOfOpen = ( *Ccb == NULL ? VirtualVolumeFile : UserVolumeOpen ); 00317 00318 break; 00319 00320 /* Root or normal directory*/ 00321 case FAT_NTC_ROOT_DCB: 00322 case FAT_NTC_DCB: 00323 *FcbOrDcb = FsContext; 00324 *Vcb = (*FcbOrDcb)->Vcb; 00325 00326 TypeOfOpen = (*Ccb == NULL ? DirectoryFile : UserDirectoryOpen); 00327 00328 DPRINT("Referencing a directory: %wZ\n", &(*FcbOrDcb)->FullFileName); 00329 break; 00330 00331 /* File */ 00332 case FAT_NTC_FCB: 00333 *FcbOrDcb = FsContext; 00334 *Vcb = (*FcbOrDcb)->Vcb; 00335 00336 TypeOfOpen = (*Ccb == NULL ? EaFile : UserFileOpen); 00337 00338 DPRINT("Referencing a file: %wZ\n", &(*FcbOrDcb)->FullFileName); 00339 00340 break; 00341 00342 default: 00343 DPRINT1("Unknown node type %x\n", FatNodeType(FsContext)); 00344 ASSERT(FALSE); 00345 } 00346 00347 return TypeOfOpen; 00348 } 00349 00350 VOID 00351 NTAPI 00352 FatSetFileObject(PFILE_OBJECT FileObject, 00353 TYPE_OF_OPEN TypeOfOpen, 00354 PVOID Fcb, 00355 PCCB Ccb) 00356 { 00357 if (Fcb) 00358 { 00359 /* Check Fcb's type */ 00360 if (FatNodeType(Fcb) == FAT_NTC_VCB) 00361 { 00362 FileObject->Vpb = ((PVCB)Fcb)->Vpb; 00363 } 00364 else 00365 { 00366 FileObject->Vpb = ((PFCB)Fcb)->Vcb->Vpb; 00367 } 00368 } 00369 00370 /* Set FsContext */ 00371 if (FileObject) 00372 { 00373 FileObject->FsContext = Fcb; 00374 FileObject->FsContext2 = Ccb; 00375 } 00376 } 00377 00378 00379 BOOLEAN 00380 NTAPI 00381 FatAcquireExclusiveVcb(IN PFAT_IRP_CONTEXT IrpContext, 00382 IN PVCB Vcb) 00383 { 00384 /* Acquire VCB's resource if possible */ 00385 if (ExAcquireResourceExclusiveLite(&Vcb->Resource, 00386 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT))) 00387 { 00388 return TRUE; 00389 } 00390 else 00391 { 00392 return FALSE; 00393 } 00394 } 00395 00396 BOOLEAN 00397 NTAPI 00398 FatAcquireSharedVcb(IN PFAT_IRP_CONTEXT IrpContext, 00399 IN PVCB Vcb) 00400 { 00401 /* Acquire VCB's resource if possible */ 00402 if (ExAcquireResourceSharedLite(&Vcb->Resource, 00403 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT))) 00404 { 00405 return TRUE; 00406 } 00407 else 00408 { 00409 return FALSE; 00410 } 00411 } 00412 00413 VOID 00414 NTAPI 00415 FatReleaseVcb(IN PFAT_IRP_CONTEXT IrpContext, 00416 IN PVCB Vcb) 00417 { 00418 /* Release VCB's resource */ 00419 ExReleaseResourceLite(&Vcb->Resource); 00420 } 00421 00422 BOOLEAN 00423 NTAPI 00424 FatAcquireExclusiveFcb(IN PFAT_IRP_CONTEXT IrpContext, 00425 IN PFCB Fcb) 00426 { 00427 RetryLockingE: 00428 /* Try to acquire the exclusive lock*/ 00429 if (ExAcquireResourceExclusiveLite(Fcb->Header.Resource, 00430 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT))) 00431 { 00432 /* Wait same way MS's FASTFAT wait, i.e. 00433 checking that there are outstanding async writes, 00434 or someone is waiting on it*/ 00435 if (Fcb->OutstandingAsyncWrites && 00436 ((IrpContext->MajorFunction != IRP_MJ_WRITE) || 00437 !FlagOn(IrpContext->Irp->Flags, IRP_NOCACHE) || 00438 ExGetSharedWaiterCount(Fcb->Header.Resource) || 00439 ExGetExclusiveWaiterCount(Fcb->Header.Resource))) 00440 { 00441 KeWaitForSingleObject(Fcb->OutstandingAsyncEvent, 00442 Executive, 00443 KernelMode, 00444 FALSE, 00445 NULL); 00446 00447 /* Release the lock */ 00448 FatReleaseFcb(IrpContext, Fcb); 00449 00450 /* Retry */ 00451 goto RetryLockingE; 00452 } 00453 00454 /* Return success */ 00455 return TRUE; 00456 } 00457 00458 /* Return failure */ 00459 return FALSE; 00460 } 00461 00462 BOOLEAN 00463 NTAPI 00464 FatAcquireSharedFcb(IN PFAT_IRP_CONTEXT IrpContext, 00465 IN PFCB Fcb) 00466 { 00467 RetryLockingS: 00468 /* Try to acquire the shared lock*/ 00469 if (ExAcquireResourceSharedLite(Fcb->Header.Resource, 00470 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT))) 00471 { 00472 /* Wait same way MS's FASTFAT wait, i.e. 00473 checking that there are outstanding async writes, 00474 or someone is waiting on it*/ 00475 if (Fcb->OutstandingAsyncWrites && 00476 ((IrpContext->MajorFunction != IRP_MJ_WRITE) || 00477 !FlagOn(IrpContext->Irp->Flags, IRP_NOCACHE) || 00478 ExGetSharedWaiterCount(Fcb->Header.Resource) || 00479 ExGetExclusiveWaiterCount(Fcb->Header.Resource))) 00480 { 00481 KeWaitForSingleObject(Fcb->OutstandingAsyncEvent, 00482 Executive, 00483 KernelMode, 00484 FALSE, 00485 NULL); 00486 00487 /* Release the lock */ 00488 FatReleaseFcb(IrpContext, Fcb); 00489 00490 /* Retry */ 00491 goto RetryLockingS; 00492 } 00493 00494 /* Return success */ 00495 return TRUE; 00496 } 00497 00498 /* Return failure */ 00499 return FALSE; 00500 } 00501 00502 VOID 00503 NTAPI 00504 FatReleaseFcb(IN PFAT_IRP_CONTEXT IrpContext, 00505 IN PFCB Fcb) 00506 { 00507 /* Release FCB's resource */ 00508 ExReleaseResourceLite(Fcb->Header.Resource); 00509 } 00510 00511 PVOID 00512 FASTCALL 00513 FatMapUserBuffer(PIRP Irp) 00514 { 00515 if (!Irp->MdlAddress) 00516 return Irp->UserBuffer; 00517 else 00518 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); 00519 } 00520 00521 BOOLEAN 00522 NTAPI 00523 FatIsTopLevelIrp(IN PIRP Irp) 00524 { 00525 if (!IoGetTopLevelIrp()) 00526 { 00527 IoSetTopLevelIrp(Irp); 00528 return TRUE; 00529 } 00530 00531 return FALSE; 00532 } 00533 00534 VOID 00535 NTAPI 00536 FatNotifyReportChange(IN PFAT_IRP_CONTEXT IrpContext, 00537 IN PVCB Vcb, 00538 IN PFCB Fcb, 00539 IN ULONG Filter, 00540 IN ULONG Action) 00541 { 00542 if (Fcb->FullFileName.Buffer == NULL) 00543 FatSetFullFileNameInFcb(IrpContext, Fcb); 00544 00545 ASSERT(Fcb->FullFileName.Length != 0 ); 00546 ASSERT(Fcb->FileNameLength != 0 ); 00547 ASSERT(Fcb->FullFileName.Length > Fcb->FileNameLength ); 00548 ASSERT(Fcb->FullFileName.Buffer[(Fcb->FullFileName.Length - Fcb->FileNameLength)/sizeof(WCHAR) - 1] == L'\\' ); 00549 00550 FsRtlNotifyFullReportChange(Vcb->NotifySync, 00551 &Vcb->NotifyList, 00552 (PSTRING)&Fcb->FullFileName, 00553 (USHORT)(Fcb->FullFileName.Length - 00554 Fcb->FileNameLength), 00555 NULL, 00556 NULL, 00557 Filter, 00558 Action, 00559 NULL); 00560 } 00561 00562 /* EOF */ Generated on Sun May 27 2012 04:27:46 for ReactOS by
1.7.6.1
|