Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

650 lines
19 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. NtFastIo.c
  5. Abstract:
  6. This module implements NT fastio routines.
  7. Author:
  8. Joe Linn [JoeLinn] 9-Nov-1994
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //
  14. // The local debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_NTFASTIO)
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE, RxFastIoRead)
  19. #pragma alloc_text(PAGE, RxFastIoWrite)
  20. #pragma alloc_text(PAGE, RxFastIoCheckIfPossible)
  21. #endif
  22. //
  23. // these declarations would be copied to fsrtl.h
  24. //
  25. BOOLEAN
  26. FsRtlCopyRead2 (
  27. IN PFILE_OBJECT FileObject,
  28. IN PLARGE_INTEGER FileOffset,
  29. IN ULONG Length,
  30. IN BOOLEAN Wait,
  31. IN ULONG LockKey,
  32. OUT PVOID Buffer,
  33. OUT PIO_STATUS_BLOCK IoStatus,
  34. IN PDEVICE_OBJECT DeviceObject,
  35. IN ULONG_PTR TopLevelIrpValue
  36. );
  37. BOOLEAN
  38. FsRtlCopyWrite2 (
  39. IN PFILE_OBJECT FileObject,
  40. IN PLARGE_INTEGER FileOffset,
  41. IN ULONG Length,
  42. IN BOOLEAN Wait,
  43. IN ULONG LockKey,
  44. IN PVOID Buffer,
  45. OUT PIO_STATUS_BLOCK IoStatus,
  46. IN PDEVICE_OBJECT DeviceObject,
  47. IN ULONG_PTR TopLevelIrpValue
  48. );
  49. BOOLEAN
  50. RxFastIoRead (
  51. IN PFILE_OBJECT FileObject,
  52. IN PLARGE_INTEGER FileOffset,
  53. IN ULONG Length,
  54. IN BOOLEAN Wait,
  55. IN ULONG LockKey,
  56. OUT PVOID Buffer,
  57. OUT PIO_STATUS_BLOCK IoStatus,
  58. IN PDEVICE_OBJECT DeviceObject
  59. )
  60. /*++
  61. Routine Description:
  62. Basic fastio read routine for the rdr
  63. Arguments:
  64. FileObject -
  65. FileOffset -
  66. Length -
  67. Wait -
  68. LockKey -
  69. Buffer -
  70. IoStatus -
  71. DeviceObject -
  72. Return value:
  73. TRUE if successful
  74. Notes:
  75. --*/
  76. {
  77. BOOLEAN ReturnValue;
  78. RX_TOPLEVELIRP_CONTEXT TopLevelContext;
  79. PAGED_CODE();
  80. RxDbgTrace( +1, Dbg, ("RxFastIoRead\n") );
  81. RxLog(( "FastRead %lx:%lx:%lx", FileObject, FileObject->FsContext, FileObject->FsContext2 ));
  82. RxLog(( "------>> %lx@%lx %lx", Length, FileOffset->LowPart, FileOffset->HighPart ));
  83. RxWmiLog( LOG,
  84. RxFastIoRead_1,
  85. LOGPTR( FileObject )
  86. LOGPTR( FileObject->FsContext )
  87. LOGPTR( FileObject->FsContext2 )
  88. LOGULONG( Length )
  89. LOGULONG( FileOffset->LowPart )
  90. LOGULONG( FileOffset->HighPart ) );
  91. ASSERT( RxIsThisTheTopLevelIrp( NULL ) );
  92. RxInitializeTopLevelIrpContext( &TopLevelContext,
  93. ((PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP),
  94. (PRDBSS_DEVICE_OBJECT)DeviceObject );
  95. ReturnValue = FsRtlCopyRead2( FileObject,
  96. FileOffset,
  97. Length,
  98. Wait,
  99. LockKey,
  100. Buffer,
  101. IoStatus,
  102. DeviceObject,
  103. (ULONG_PTR)(&TopLevelContext) );
  104. RxDbgTrace( -1, Dbg, ("RxFastIoRead ReturnValue=%x\n", ReturnValue) );
  105. if (ReturnValue) {
  106. RxLog(( "FastReadYes %lx ret %lx:%lx", FileObject->FsContext2, IoStatus->Status, IoStatus->Information ));
  107. RxWmiLog( LOG,
  108. RxFastIoRead_2,
  109. LOGPTR( FileObject->FsContext2 )
  110. LOGULONG( IoStatus->Status )
  111. LOGPTR( IoStatus->Information ) );
  112. } else {
  113. RxLog(( "FastReadNo %lx", FileObject->FsContext2 ));
  114. RxWmiLog( LOG,
  115. RxFastIoRead_3,
  116. LOGPTR( FileObject->FsContext2 ) );
  117. }
  118. return ReturnValue;
  119. }
  120. BOOLEAN
  121. RxFastIoWrite (
  122. IN PFILE_OBJECT FileObject,
  123. IN PLARGE_INTEGER FileOffset,
  124. IN ULONG Length,
  125. IN BOOLEAN Wait,
  126. IN ULONG LockKey,
  127. IN PVOID Buffer,
  128. OUT PIO_STATUS_BLOCK IoStatus,
  129. IN PDEVICE_OBJECT DeviceObject
  130. )
  131. /*++
  132. Routine Description:
  133. Arguments:
  134. Routine Description:
  135. Basic fastio write routine for the rdr
  136. Arguments:
  137. FileObject -
  138. FileOffset -
  139. Length -
  140. Wait -
  141. LockKey -
  142. Buffer -
  143. IoStatus -
  144. DeviceObject -
  145. Return value:
  146. TRUE if successful
  147. --*/
  148. {
  149. BOOLEAN ReturnValue;
  150. RX_TOPLEVELIRP_CONTEXT TopLevelContext;
  151. PSRV_OPEN SrvOpen;
  152. PAGED_CODE();
  153. RxDbgTrace(+1, Dbg, ("RxFastIoWrite\n"));
  154. SrvOpen = ((PFOBX)(FileObject->FsContext2))->SrvOpen;
  155. if (FlagOn( SrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING )) {
  156. //
  157. // if this flag is set, we have to treat this as an unbuffered Io....sigh.
  158. //
  159. RxDbgTrace( -1, Dbg, ("RxFastIoWrite DONTUSE_WRITE_CACHEING...failing\n") );
  160. return FALSE;
  161. }
  162. ASSERT( RxIsThisTheTopLevelIrp( NULL ) );
  163. RxInitializeTopLevelIrpContext( &TopLevelContext,
  164. ((PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP),
  165. (PRDBSS_DEVICE_OBJECT)DeviceObject );
  166. ReturnValue = FsRtlCopyWrite2( FileObject,
  167. FileOffset,
  168. Length,
  169. Wait,
  170. LockKey,
  171. Buffer,
  172. IoStatus,
  173. DeviceObject,
  174. (ULONG_PTR)(&TopLevelContext) );
  175. RxDbgTrace( -1, Dbg, ("RxFastIoWrite ReturnValue=%x\n", ReturnValue) );
  176. if (ReturnValue) {
  177. RxLog(( "FWY %lx OLP: %lx SLP: %lx IOSB %lx:%lx", FileObject->FsContext2, FileOffset->LowPart, SrvOpen->Fcb->Header.FileSize.LowPart, IoStatus->Status, IoStatus->Information ));
  178. RxWmiLog( LOG,
  179. RxFastIoWrite_1,
  180. LOGPTR( FileObject->FsContext2 )
  181. LOGULONG( FileOffset->LowPart )
  182. LOGULONG( SrvOpen->Fcb->Header.FileSize.LowPart )
  183. LOGULONG( IoStatus->Status )
  184. LOGPTR( IoStatus->Information ) );
  185. } else {
  186. RxLog(( "FastWriteNo %lx", FileObject->FsContext2 ));
  187. RxWmiLog( LOG,
  188. RxFastIoWrite_2,
  189. LOGPTR( FileObject->FsContext2 ) );
  190. }
  191. return ReturnValue;
  192. }
  193. BOOLEAN
  194. RxFastIoCheckIfPossible (
  195. IN PFILE_OBJECT FileObject,
  196. IN PLARGE_INTEGER FileOffset,
  197. IN ULONG Length,
  198. IN BOOLEAN Wait,
  199. IN ULONG LockKey,
  200. IN BOOLEAN CheckForReadOperation,
  201. OUT PIO_STATUS_BLOCK IoStatus,
  202. IN PDEVICE_OBJECT DeviceObject
  203. )
  204. /*++
  205. Routine Description:
  206. This routine checks if fast i/o is possible for a read/write operation
  207. Arguments:
  208. FileObject - Supplies the file object used in the query
  209. FileOffset - Supplies the starting byte offset for the read/write operation
  210. Length - Supplies the length, in bytes, of the read/write operation
  211. Wait - Indicates if we can wait
  212. LockKey - Supplies the lock key
  213. CheckForReadOperation - Indicates if this is a check for a read or write
  214. operation
  215. IoStatus - Receives the status of the operation if our return value is
  216. FastIoReturnError
  217. Return Value:
  218. BOOLEAN - TRUE if fast I/O is possible and FALSE if the caller needs
  219. to take the long route.
  220. --*/
  221. {
  222. PFCB Fcb;
  223. PFOBX Fobx;
  224. PSRV_OPEN SrvOpen;
  225. PCHAR FailureReason = NULL;
  226. LARGE_INTEGER LargeLength;
  227. PAGED_CODE();
  228. RxDecodeFileObject( FileObject, &Fcb, &Fobx );
  229. SrvOpen = Fobx->SrvOpen;
  230. if (NodeType( Fcb ) != RDBSS_NTC_STORAGE_TYPE_FILE) {
  231. FailureReason = "notfile";
  232. } else if (FileObject->DeletePending) {
  233. FailureReason = "delpend";
  234. } else if (Fcb->NonPaged->OutstandingAsyncWrites != 0) {
  235. FailureReason = "asynW";
  236. } else if (FlagOn( SrvOpen->Flags, SRVOPEN_FLAG_ORPHANED )) {
  237. FailureReason = "srvopen orphaned";
  238. } else if (FlagOn( Fcb->FcbState, FCB_STATE_ORPHANED )) {
  239. FailureReason = "orphaned";
  240. } else if (FlagOn( SrvOpen->Flags, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING )) {
  241. FailureReason = "buf state change";
  242. } else if (FlagOn( SrvOpen->Flags, SRVOPEN_FLAG_FILE_RENAMED | SRVOPEN_FLAG_FILE_DELETED)) {
  243. FailureReason = "ren/del";
  244. } else {
  245. //
  246. // Ensure that all pending buffering state change requests are processed
  247. // before letting the operation through.
  248. //
  249. FsRtlEnterFileSystem();
  250. RxProcessChangeBufferingStateRequestsForSrvOpen( SrvOpen );
  251. FsRtlExitFileSystem();
  252. LargeLength.QuadPart = Length;
  253. //
  254. // Based on whether this is a read or write operation we call
  255. // fsrtl check for read/write
  256. //
  257. if (CheckForReadOperation) {
  258. if (!FlagOn( Fcb->FcbState, FCB_STATE_READCACHING_ENABLED )) {
  259. FailureReason = "notreadC";
  260. } else if (!FsRtlFastCheckLockForRead( &Fcb->FileLock,
  261. FileOffset,
  262. &LargeLength,
  263. LockKey,
  264. FileObject,
  265. PsGetCurrentProcess() )) {
  266. FailureReason = "readlock";
  267. }
  268. } else {
  269. if (!FlagOn( Fcb->FcbState,FCB_STATE_WRITECACHING_ENABLED )) {
  270. FailureReason = "notwriteC";
  271. } else if (!FsRtlFastCheckLockForWrite( &Fcb->FileLock,
  272. FileOffset,
  273. &LargeLength,
  274. LockKey,
  275. FileObject,
  276. PsGetCurrentProcess() )) {
  277. FailureReason = "writelock";
  278. }
  279. }
  280. }
  281. if (FailureReason) {
  282. RxLog(( "CheckFast fail %lx %s", FileObject, FailureReason ));
  283. RxWmiLog( LOG,
  284. RxFastIoCheckIfPossible,
  285. LOGPTR( FileObject )
  286. LOGARSTR( FailureReason ) );
  287. return FALSE;
  288. } else {
  289. return TRUE;
  290. }
  291. }
  292. BOOLEAN
  293. RxFastIoDeviceControl (
  294. IN PFILE_OBJECT FileObject,
  295. IN BOOLEAN Wait,
  296. IN PVOID InputBuffer OPTIONAL,
  297. IN ULONG InputBufferLength,
  298. OUT PVOID OutputBuffer OPTIONAL,
  299. IN ULONG OutputBufferLength,
  300. IN ULONG IoControlCode,
  301. OUT PIO_STATUS_BLOCK IoStatus,
  302. IN PDEVICE_OBJECT DeviceObject
  303. )
  304. /*++
  305. Routine Description:
  306. This routine is for the fast device control call.
  307. Arguments:
  308. FileObject - Supplies the file object used in this operation
  309. Wait - Indicates if we are allowed to wait for the information
  310. InputBuffer - Supplies the input buffer
  311. InputBufferLength - the length of the input buffer
  312. OutputBuffer - the output buffer
  313. OutputBufferLength - the length of the output buffer
  314. IoControlCode - the IO control code
  315. IoStatus - Receives the final status of the operation
  316. DeviceObject - the associated device object
  317. Return Value:
  318. BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
  319. needs to take the long route.
  320. Notes:
  321. The following IO control requests are handled in the first path
  322. IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER
  323. InputBuffer - pointer to the other file object
  324. InputBufferLength - length in bytes of a pointer.
  325. OutputBuffer - not used
  326. OutputBufferLength - not used
  327. IoStatus --
  328. IoStatus.Status set to STATUS_SUCCESS if both the file objects are
  329. on the same server, otherwise set to STATUS_NOT_SAME_DEVICE
  330. This is a kernel mode interface only.
  331. --*/
  332. {
  333. PFCB Fcb;
  334. BOOLEAN FastIoSucceeded;
  335. switch (IoControlCode) {
  336. case IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER:
  337. FastIoSucceeded = TRUE;
  338. try {
  339. if (InputBufferLength == sizeof( HANDLE )) {
  340. PFCB Fcb2;
  341. HANDLE File;
  342. PFILE_OBJECT FileObject2;
  343. NTSTATUS Status;
  344. Fcb = (PFCB)FileObject->FsContext;
  345. RtlCopyMemory( &File, InputBuffer, sizeof( HANDLE ) );
  346. Status = ObReferenceObjectByHandle( File,
  347. FILE_ANY_ACCESS,
  348. *IoFileObjectType,
  349. UserMode,
  350. &FileObject2,
  351. NULL );
  352. if ((Status == STATUS_SUCCESS)) {
  353. if(FileObject2->DeviceObject == DeviceObject) {
  354. Fcb2 = (PFCB)FileObject2->FsContext;
  355. if ((Fcb2 != NULL) &&
  356. (NodeTypeIsFcb( Fcb2 ))) {
  357. if (Fcb->NetRoot->SrvCall == Fcb2->NetRoot->SrvCall) {
  358. IoStatus->Status = STATUS_SUCCESS;
  359. } else {
  360. IoStatus->Status = STATUS_NOT_SAME_DEVICE;
  361. }
  362. } else {
  363. Status = STATUS_INVALID_PARAMETER;
  364. }
  365. } else {
  366. Status = STATUS_INVALID_PARAMETER;
  367. }
  368. ObDereferenceObject( FileObject2 );
  369. } else {
  370. IoStatus->Status = STATUS_INVALID_PARAMETER;
  371. }
  372. } else {
  373. IoStatus->Status = STATUS_INVALID_PARAMETER;
  374. }
  375. } except( EXCEPTION_EXECUTE_HANDLER ) {
  376. //
  377. // The I/O request was not handled successfully, abort the I/O request with
  378. // the error status that we get back from the execption code
  379. //
  380. IoStatus->Status = STATUS_INVALID_PARAMETER;
  381. FastIoSucceeded = TRUE;
  382. }
  383. break;
  384. case IOCTL_LMR_LWIO_PREIO:
  385. //
  386. // This call allows the lwio user mode caller to preserve the wait IO model for
  387. // callers that use the file handle as a synch object. Before each IO, the file
  388. // object event must be cleared and after each IO the event must be set as per
  389. // the IO manager semantics.
  390. //
  391. IoStatus->Status = STATUS_NOT_SUPPORTED;
  392. IoStatus->Information = 0;
  393. if (!FlagOn( FileObject->Flags, FO_SYNCHRONOUS_IO )) {
  394. Fcb = (PFCB)FileObject->FsContext;
  395. try {
  396. if ((Fcb != NULL) &&
  397. (NodeType( Fcb ) == RDBSS_NTC_STORAGE_TYPE_FILE) &&
  398. ((FileObject->SectionObjectPointer == NULL) ||
  399. (FileObject->SectionObjectPointer->DataSectionObject == NULL))) {
  400. KeClearEvent( &FileObject->Event );
  401. IoStatus->Status = STATUS_SUCCESS;
  402. IoStatus->Information = (ULONG_PTR) FileObject->LockOperation;
  403. }
  404. } except(EXCEPTION_EXECUTE_HANDLER) {
  405. IoStatus->Status = GetExceptionCode();
  406. }
  407. }
  408. FastIoSucceeded = TRUE;
  409. break;
  410. case IOCTL_LMR_LWIO_POSTIO:
  411. //
  412. // This call allows the lwio user mode caller to complete the user mode IO for
  413. // a given file handle. The caller specifies an IoStatus block that contains the
  414. // user mode IO outcome.
  415. //
  416. IoStatus->Status = STATUS_NOT_SUPPORTED;
  417. IoStatus->Information = 0;
  418. if (!FlagOn( FileObject->Flags, FO_SYNCHRONOUS_IO ) &&
  419. (InputBuffer != NULL) &&
  420. (InputBufferLength == sizeof( *IoStatus ))) {
  421. PIO_STATUS_BLOCK Iosb = (PIO_STATUS_BLOCK)InputBuffer;
  422. Fcb = (PFCB)FileObject->FsContext;
  423. try {
  424. if ((Fcb != NULL) &&
  425. NodeType( Fcb ) == RDBSS_NTC_STORAGE_TYPE_FILE &&
  426. ((FileObject->SectionObjectPointer == NULL) ||
  427. (FileObject->SectionObjectPointer->DataSectionObject == NULL))) {
  428. KeSetEvent( &FileObject->Event, 0, FALSE );
  429. IoStatus->Status = Iosb->Status;
  430. IoStatus->Information = Iosb->Information;
  431. }
  432. } except(EXCEPTION_EXECUTE_HANDLER) {
  433. IoStatus->Status = GetExceptionCode();
  434. IoStatus->Information = 0;
  435. }
  436. }
  437. FastIoSucceeded = TRUE;
  438. break;
  439. default:
  440. {
  441. Fcb = (PFCB)FileObject->FsContext;
  442. FastIoSucceeded = FALSE;
  443. //
  444. // Inform lwio rdr of this call
  445. //
  446. if ((Fcb != NULL) &&
  447. NodeTypeIsFcb( Fcb ) &&
  448. FlagOn( Fcb->FcbState, FCB_STATE_LWIO_ENABLED )) {
  449. PFAST_IO_DISPATCH FastIoDispatch = Fcb->MRxFastIoDispatch;
  450. if (FastIoDispatch &&
  451. FastIoDispatch->FastIoDeviceControl &&
  452. FastIoDispatch->FastIoDeviceControl( FileObject,
  453. Wait,
  454. InputBuffer,
  455. InputBufferLength,
  456. OutputBuffer,
  457. OutputBufferLength,
  458. IoControlCode,
  459. IoStatus,
  460. DeviceObject )) {
  461. FastIoSucceeded = TRUE;
  462. }
  463. }
  464. }
  465. }
  466. return FastIoSucceeded;
  467. }