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.

719 lines
17 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. LockCtrl.c
  5. Abstract:
  6. This module implements the Lock Control routines for Fat called
  7. by the dispatch driver.
  8. // @@BEGIN_DDKSPLIT
  9. Author:
  10. Gary Kimura [GaryKi] 28-Dec-1989
  11. Revision History:
  12. // @@END_DDKSPLIT
  13. --*/
  14. #include "FatProcs.h"
  15. //
  16. // The local debug trace level
  17. //
  18. #define Dbg (DEBUG_TRACE_LOCKCTRL)
  19. #ifdef ALLOC_PRAGMA
  20. #pragma alloc_text(PAGE, FatCommonLockControl)
  21. #pragma alloc_text(PAGE, FatFastLock)
  22. #pragma alloc_text(PAGE, FatFastUnlockAll)
  23. #pragma alloc_text(PAGE, FatFastUnlockAllByKey)
  24. #pragma alloc_text(PAGE, FatFastUnlockSingle)
  25. #pragma alloc_text(PAGE, FatFsdLockControl)
  26. #endif
  27. NTSTATUS
  28. FatFsdLockControl (
  29. IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
  30. IN PIRP Irp
  31. )
  32. /*++
  33. Routine Description:
  34. This routine implements the FSD part of Lock control operations
  35. Arguments:
  36. VolumeDeviceObject - Supplies the volume device object where the
  37. file exists
  38. Irp - Supplies the Irp being processed
  39. Return Value:
  40. NTSTATUS - The FSD status for the IRP
  41. --*/
  42. {
  43. NTSTATUS Status;
  44. PIRP_CONTEXT IrpContext = NULL;
  45. BOOLEAN TopLevel;
  46. DebugTrace(+1, Dbg, "FatFsdLockControl\n", 0);
  47. //
  48. // Call the common Lock Control routine, with blocking allowed if
  49. // synchronous
  50. //
  51. FsRtlEnterFileSystem();
  52. TopLevel = FatIsIrpTopLevel( Irp );
  53. try {
  54. IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
  55. Status = FatCommonLockControl( IrpContext, Irp );
  56. } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {
  57. //
  58. // We had some trouble trying to perform the requested
  59. // operation, so we'll abort the I/O request with
  60. // the error status that we get back from the
  61. // execption code
  62. //
  63. Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
  64. }
  65. if (TopLevel) { IoSetTopLevelIrp( NULL ); }
  66. FsRtlExitFileSystem();
  67. //
  68. // And return to our caller
  69. //
  70. DebugTrace(-1, Dbg, "FatFsdLockControl -> %08lx\n", Status);
  71. UNREFERENCED_PARAMETER( VolumeDeviceObject );
  72. return Status;
  73. }
  74. BOOLEAN
  75. FatFastLock (
  76. IN PFILE_OBJECT FileObject,
  77. IN PLARGE_INTEGER FileOffset,
  78. IN PLARGE_INTEGER Length,
  79. PEPROCESS ProcessId,
  80. ULONG Key,
  81. BOOLEAN FailImmediately,
  82. BOOLEAN ExclusiveLock,
  83. OUT PIO_STATUS_BLOCK IoStatus,
  84. IN PDEVICE_OBJECT DeviceObject
  85. )
  86. /*++
  87. Routine Description:
  88. This is a call back routine for doing the fast lock call.
  89. Arguments:
  90. FileObject - Supplies the file object used in this operation
  91. FileOffset - Supplies the file offset used in this operation
  92. Length - Supplies the length used in this operation
  93. ProcessId - Supplies the process ID used in this operation
  94. Key - Supplies the key used in this operation
  95. FailImmediately - Indicates if the request should fail immediately
  96. if the lock cannot be granted.
  97. ExclusiveLock - Indicates if this is a request for an exclusive or
  98. shared lock
  99. IoStatus - Receives the Status if this operation is successful
  100. Return Value:
  101. BOOLEAN - TRUE if this operation completed and FALSE if caller
  102. needs to take the long route.
  103. --*/
  104. {
  105. BOOLEAN Results;
  106. PVCB Vcb;
  107. PFCB Fcb;
  108. PCCB Ccb;
  109. DebugTrace(+1, Dbg, "FatFastLock\n", 0);
  110. //
  111. // Decode the type of file object we're being asked to process and make
  112. // sure it is only a user file open.
  113. //
  114. if (FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ) != UserFileOpen) {
  115. IoStatus->Status = STATUS_INVALID_PARAMETER;
  116. IoStatus->Information = 0;
  117. DebugTrace(-1, Dbg, "FatFastLock -> TRUE (STATUS_INVALID_PARAMETER)\n", 0);
  118. return TRUE;
  119. }
  120. //
  121. // Acquire exclusive access to the Fcb this operation can always wait
  122. //
  123. FsRtlEnterFileSystem();
  124. try {
  125. //
  126. // We check whether we can proceed
  127. // based on the state of the file oplocks.
  128. //
  129. if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {
  130. try_return( Results = FALSE );
  131. }
  132. //
  133. // Now call the FsRtl routine to do the actual processing of the
  134. // Lock request
  135. //
  136. if (Results = FsRtlFastLock( &Fcb->Specific.Fcb.FileLock,
  137. FileObject,
  138. FileOffset,
  139. Length,
  140. ProcessId,
  141. Key,
  142. FailImmediately,
  143. ExclusiveLock,
  144. IoStatus,
  145. NULL,
  146. FALSE )) {
  147. //
  148. // Set the flag indicating if Fast I/O is possible
  149. //
  150. Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
  151. }
  152. try_exit: NOTHING;
  153. } finally {
  154. DebugUnwind( FatFastLock );
  155. //
  156. // Release the Fcb, and return to our caller
  157. //
  158. FsRtlExitFileSystem();
  159. DebugTrace(-1, Dbg, "FatFastLock -> %08lx\n", Results);
  160. }
  161. return Results;
  162. }
  163. BOOLEAN
  164. FatFastUnlockSingle (
  165. IN PFILE_OBJECT FileObject,
  166. IN PLARGE_INTEGER FileOffset,
  167. IN PLARGE_INTEGER Length,
  168. PEPROCESS ProcessId,
  169. ULONG Key,
  170. OUT PIO_STATUS_BLOCK IoStatus,
  171. IN PDEVICE_OBJECT DeviceObject
  172. )
  173. /*++
  174. Routine Description:
  175. This is a call back routine for doing the fast unlock single call.
  176. Arguments:
  177. FileObject - Supplies the file object used in this operation
  178. FileOffset - Supplies the file offset used in this operation
  179. Length - Supplies the length used in this operation
  180. ProcessId - Supplies the process ID used in this operation
  181. Key - Supplies the key used in this operation
  182. Status - Receives the Status if this operation is successful
  183. Return Value:
  184. BOOLEAN - TRUE if this operation completed and FALSE if caller
  185. needs to take the long route.
  186. --*/
  187. {
  188. BOOLEAN Results;
  189. PVCB Vcb;
  190. PFCB Fcb;
  191. PCCB Ccb;
  192. DebugTrace(+1, Dbg, "FatFastUnlockSingle\n", 0);
  193. IoStatus->Information = 0;
  194. //
  195. // Decode the type of file object we're being asked to process and make sure
  196. // it is only a user file open
  197. //
  198. if (FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ) != UserFileOpen) {
  199. IoStatus->Status = STATUS_INVALID_PARAMETER;
  200. DebugTrace(-1, Dbg, "FatFastUnlockSingle -> TRUE (STATUS_INVALID_PARAMETER)\n", 0);
  201. return TRUE;
  202. }
  203. //
  204. // Acquire exclusive access to the Fcb this operation can always wait
  205. //
  206. FsRtlEnterFileSystem();
  207. try {
  208. //
  209. // We check whether we can proceed based on the state of the file oplocks.
  210. //
  211. if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {
  212. try_return( Results = FALSE );
  213. }
  214. //
  215. // Now call the FsRtl routine to do the actual processing of the
  216. // Lock request. The call will always succeed.
  217. //
  218. Results = TRUE;
  219. IoStatus->Status = FsRtlFastUnlockSingle( &Fcb->Specific.Fcb.FileLock,
  220. FileObject,
  221. FileOffset,
  222. Length,
  223. ProcessId,
  224. Key,
  225. NULL,
  226. FALSE );
  227. //
  228. // Set the flag indicating if Fast I/O is possible
  229. //
  230. Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
  231. try_exit: NOTHING;
  232. } finally {
  233. DebugUnwind( FatFastUnlockSingle );
  234. //
  235. // Release the Fcb, and return to our caller
  236. //
  237. FsRtlExitFileSystem();
  238. DebugTrace(-1, Dbg, "FatFastUnlockSingle -> %08lx\n", Results);
  239. }
  240. return Results;
  241. }
  242. BOOLEAN
  243. FatFastUnlockAll (
  244. IN PFILE_OBJECT FileObject,
  245. PEPROCESS ProcessId,
  246. OUT PIO_STATUS_BLOCK IoStatus,
  247. IN PDEVICE_OBJECT DeviceObject
  248. )
  249. /*++
  250. Routine Description:
  251. This is a call back routine for doing the fast unlock all call.
  252. Arguments:
  253. FileObject - Supplies the file object used in this operation
  254. ProcessId - Supplies the process ID used in this operation
  255. Status - Receives the Status if this operation is successful
  256. Return Value:
  257. BOOLEAN - TRUE if this operation completed and FALSE if caller
  258. needs to take the long route.
  259. --*/
  260. {
  261. BOOLEAN Results;
  262. PVCB Vcb;
  263. PFCB Fcb;
  264. PCCB Ccb;
  265. DebugTrace(+1, Dbg, "FatFastUnlockAll\n", 0);
  266. IoStatus->Information = 0;
  267. //
  268. // Decode the type of file object we're being asked to process and make sure
  269. // it is only a user file open.
  270. //
  271. if (FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ) != UserFileOpen) {
  272. IoStatus->Status = STATUS_INVALID_PARAMETER;
  273. DebugTrace(-1, Dbg, "FatFastUnlockAll -> TRUE (STATUS_INVALID_PARAMETER)\n", 0);
  274. return TRUE;
  275. }
  276. //
  277. // Acquire exclusive access to the Fcb this operation can always wait
  278. //
  279. FsRtlEnterFileSystem();
  280. (VOID) ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );
  281. try {
  282. //
  283. // We check whether we can proceed based on the state of the file oplocks.
  284. //
  285. if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {
  286. try_return( Results = FALSE );
  287. }
  288. //
  289. // Now call the FsRtl routine to do the actual processing of the
  290. // Lock request. The call will always succeed.
  291. //
  292. Results = TRUE;
  293. IoStatus->Status = FsRtlFastUnlockAll( &Fcb->Specific.Fcb.FileLock,
  294. FileObject,
  295. ProcessId,
  296. NULL );
  297. //
  298. // Set the flag indicating if Fast I/O is possible
  299. //
  300. Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
  301. try_exit: NOTHING;
  302. } finally {
  303. DebugUnwind( FatFastUnlockAll );
  304. //
  305. // Release the Fcb, and return to our caller
  306. //
  307. ExReleaseResourceLite( (Fcb)->Header.Resource );
  308. FsRtlExitFileSystem();
  309. DebugTrace(-1, Dbg, "FatFastUnlockAll -> %08lx\n", Results);
  310. }
  311. return Results;
  312. }
  313. BOOLEAN
  314. FatFastUnlockAllByKey (
  315. IN PFILE_OBJECT FileObject,
  316. PVOID ProcessId,
  317. ULONG Key,
  318. OUT PIO_STATUS_BLOCK IoStatus,
  319. IN PDEVICE_OBJECT DeviceObject
  320. )
  321. /*++
  322. Routine Description:
  323. This is a call back routine for doing the fast unlock all by key call.
  324. Arguments:
  325. FileObject - Supplies the file object used in this operation
  326. ProcessId - Supplies the process ID used in this operation
  327. Key - Supplies the key used in this operation
  328. Status - Receives the Status if this operation is successful
  329. Return Value:
  330. BOOLEAN - TRUE if this operation completed and FALSE if caller
  331. needs to take the long route.
  332. --*/
  333. {
  334. BOOLEAN Results;
  335. PVCB Vcb;
  336. PFCB Fcb;
  337. PCCB Ccb;
  338. DebugTrace(+1, Dbg, "FatFastUnlockAllByKey\n", 0);
  339. IoStatus->Information = 0;
  340. //
  341. // Decode the type of file object we're being asked to process and make sure
  342. // it is only a user file open.
  343. //
  344. if (FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ) != UserFileOpen) {
  345. IoStatus->Status = STATUS_INVALID_PARAMETER;
  346. DebugTrace(-1, Dbg, "FatFastUnlockAll -> TRUE (STATUS_INVALID_PARAMETER)\n", 0);
  347. return TRUE;
  348. }
  349. //
  350. // Acquire exclusive access to the Fcb this operation can always wait
  351. //
  352. FsRtlEnterFileSystem();
  353. (VOID) ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );
  354. try {
  355. //
  356. // We check whether we can proceed based on the state of the file oplocks.
  357. //
  358. if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {
  359. try_return( Results = FALSE );
  360. }
  361. //
  362. // Now call the FsRtl routine to do the actual processing of the
  363. // Lock request. The call will always succeed.
  364. //
  365. Results = TRUE;
  366. IoStatus->Status = FsRtlFastUnlockAllByKey( &Fcb->Specific.Fcb.FileLock,
  367. FileObject,
  368. ProcessId,
  369. Key,
  370. NULL );
  371. //
  372. // Set the flag indicating if Fast I/O is possible
  373. //
  374. Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
  375. try_exit: NOTHING;
  376. } finally {
  377. DebugUnwind( FatFastUnlockAllByKey );
  378. //
  379. // Release the Fcb, and return to our caller
  380. //
  381. ExReleaseResourceLite( (Fcb)->Header.Resource );
  382. FsRtlExitFileSystem();
  383. DebugTrace(-1, Dbg, "FatFastUnlockAllByKey -> %08lx\n", Results);
  384. }
  385. return Results;
  386. }
  387. NTSTATUS
  388. FatCommonLockControl (
  389. IN PIRP_CONTEXT IrpContext,
  390. IN PIRP Irp
  391. )
  392. /*++
  393. Routine Description:
  394. This is the common routine for doing Lock control operations called
  395. by both the fsd and fsp threads
  396. Arguments:
  397. Irp - Supplies the Irp to process
  398. Return Value:
  399. NTSTATUS - The return status for the operation
  400. --*/
  401. {
  402. NTSTATUS Status;
  403. PIO_STACK_LOCATION IrpSp;
  404. TYPE_OF_OPEN TypeOfOpen;
  405. PVCB Vcb;
  406. PFCB Fcb;
  407. PCCB Ccb;
  408. BOOLEAN OplockPostIrp = FALSE;
  409. //
  410. // Get a pointer to the current Irp stack location
  411. //
  412. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  413. DebugTrace(+1, Dbg, "FatCommonLockControl\n", 0);
  414. DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp);
  415. DebugTrace( 0, Dbg, "MinorFunction = %08lx\n", IrpSp->MinorFunction);
  416. //
  417. // Decode the type of file object we're being asked to process
  418. //
  419. TypeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb );
  420. //
  421. // If the file is not a user file open then we reject the request
  422. // as an invalid parameter
  423. //
  424. if (TypeOfOpen != UserFileOpen) {
  425. FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
  426. DebugTrace(-1, Dbg, "FatCommonLockControl -> STATUS_INVALID_PARAMETER\n", 0);
  427. return STATUS_INVALID_PARAMETER;
  428. }
  429. //
  430. // Acquire exclusive access to the Fcb and enqueue the Irp if we didn't
  431. // get access
  432. //
  433. if (!FatAcquireSharedFcb( IrpContext, Fcb )) {
  434. Status = FatFsdPostRequest( IrpContext, Irp );
  435. DebugTrace(-1, Dbg, "FatCommonLockControl -> %08lx\n", Status);
  436. return Status;
  437. }
  438. try {
  439. //
  440. // We check whether we can proceed
  441. // based on the state of the file oplocks.
  442. //
  443. Status = FsRtlCheckOplock( &Fcb->Specific.Fcb.Oplock,
  444. Irp,
  445. IrpContext,
  446. FatOplockComplete,
  447. NULL );
  448. if (Status != STATUS_SUCCESS) {
  449. OplockPostIrp = TRUE;
  450. try_return( NOTHING );
  451. }
  452. //
  453. // Now call the FsRtl routine to do the actual processing of the
  454. // Lock request
  455. //
  456. Status = FsRtlProcessFileLock( &Fcb->Specific.Fcb.FileLock, Irp, NULL );
  457. //
  458. // Set the flag indicating if Fast I/O is possible
  459. //
  460. Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
  461. try_exit: NOTHING;
  462. } finally {
  463. DebugUnwind( FatCommonLockControl );
  464. //
  465. // Only if this is not an abnormal termination do we delete the
  466. // irp context
  467. //
  468. if (!AbnormalTermination() && !OplockPostIrp) {
  469. FatCompleteRequest( IrpContext, FatNull, 0 );
  470. }
  471. //
  472. // Release the Fcb, and return to our caller
  473. //
  474. FatReleaseFcb( IrpContext, Fcb );
  475. DebugTrace(-1, Dbg, "FatCommonLockControl -> %08lx\n", Status);
  476. }
  477. return Status;
  478. }