Source code of Windows XP (NT5)
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.

682 lines
15 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 Cdfs called
  7. by the Fsd/Fsp dispatch driver.
  8. // @@BEGIN_DDKSPLIT
  9. Author:
  10. Brian Andrew [BrianAn] 01-July-1995
  11. Revision History:
  12. // @@END_DDKSPLIT
  13. --*/
  14. #include "CdProcs.h"
  15. //
  16. // The Bug check file id for this module
  17. //
  18. #define BugCheckFileId (CDFS_BUG_CHECK_LOCKCTRL)
  19. #ifdef ALLOC_PRAGMA
  20. #pragma alloc_text(PAGE, CdCommonLockControl)
  21. #pragma alloc_text(PAGE, CdFastLock)
  22. #pragma alloc_text(PAGE, CdFastUnlockAll)
  23. #pragma alloc_text(PAGE, CdFastUnlockAllByKey)
  24. #pragma alloc_text(PAGE, CdFastUnlockSingle)
  25. #endif
  26. NTSTATUS
  27. CdCommonLockControl (
  28. IN PIRP_CONTEXT IrpContext,
  29. IN PIRP Irp
  30. )
  31. /*++
  32. Routine Description:
  33. This is the common routine for Lock Control called by both the fsd and fsp
  34. threads.
  35. Arguments:
  36. Irp - Supplies the Irp to process
  37. Return Value:
  38. NTSTATUS - The return status for the operation
  39. --*/
  40. {
  41. NTSTATUS Status;
  42. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  43. TYPE_OF_OPEN TypeOfOpen;
  44. PFCB Fcb;
  45. PCCB Ccb;
  46. PAGED_CODE();
  47. //
  48. // Extract and decode the type of file object we're being asked to process
  49. //
  50. TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
  51. //
  52. // If the file is not a user file open then we reject the request
  53. // as an invalid parameter
  54. //
  55. if (TypeOfOpen != UserFileOpen) {
  56. CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
  57. return STATUS_INVALID_PARAMETER;
  58. }
  59. //
  60. // We check whether we can proceed based on the state of the file oplocks.
  61. // This call might post the irp for us.
  62. //
  63. Status = FsRtlCheckOplock( &Fcb->Oplock,
  64. Irp,
  65. IrpContext,
  66. CdOplockComplete,
  67. NULL );
  68. //
  69. // If we don't get success then the oplock package completed the request.
  70. //
  71. if (Status != STATUS_SUCCESS) {
  72. return Status;
  73. }
  74. //
  75. // Verify the Fcb.
  76. //
  77. CdVerifyFcbOperation( IrpContext, Fcb );
  78. //
  79. // If we don't have a file lock, then get one now.
  80. //
  81. if (Fcb->FileLock == NULL) { CdCreateFileLock( IrpContext, Fcb, TRUE ); }
  82. //
  83. // Now call the FsRtl routine to do the actual processing of the
  84. // Lock request
  85. //
  86. Status = FsRtlProcessFileLock( Fcb->FileLock, Irp, NULL );
  87. //
  88. // Set the flag indicating if Fast I/O is possible
  89. //
  90. CdLockFcb( IrpContext, Fcb );
  91. Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
  92. CdUnlockFcb( IrpContext, Fcb );
  93. //
  94. // Complete the request.
  95. //
  96. CdCompleteRequest( IrpContext, NULL, Status );
  97. return Status;
  98. }
  99. BOOLEAN
  100. CdFastLock (
  101. IN PFILE_OBJECT FileObject,
  102. IN PLARGE_INTEGER FileOffset,
  103. IN PLARGE_INTEGER Length,
  104. PEPROCESS ProcessId,
  105. ULONG Key,
  106. BOOLEAN FailImmediately,
  107. BOOLEAN ExclusiveLock,
  108. OUT PIO_STATUS_BLOCK IoStatus,
  109. IN PDEVICE_OBJECT DeviceObject
  110. )
  111. /*++
  112. Routine Description:
  113. This is a call back routine for doing the fast lock call.
  114. Arguments:
  115. FileObject - Supplies the file object used in this operation
  116. FileOffset - Supplies the file offset used in this operation
  117. Length - Supplies the length used in this operation
  118. ProcessId - Supplies the process ID used in this operation
  119. Key - Supplies the key used in this operation
  120. FailImmediately - Indicates if the request should fail immediately
  121. if the lock cannot be granted.
  122. ExclusiveLock - Indicates if this is a request for an exclusive or
  123. shared lock
  124. IoStatus - Receives the Status if this operation is successful
  125. Return Value:
  126. BOOLEAN - TRUE if this operation completed and FALSE if caller
  127. needs to take the long route.
  128. --*/
  129. {
  130. BOOLEAN Results = FALSE;
  131. PFCB Fcb;
  132. TYPE_OF_OPEN TypeOfOpen;
  133. PAGED_CODE();
  134. ASSERT_FILE_OBJECT( FileObject );
  135. IoStatus->Information = 0;
  136. //
  137. // Decode the type of file object we're being asked to process and
  138. // make sure that is is only a user file open.
  139. //
  140. TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
  141. if (TypeOfOpen != UserFileOpen) {
  142. IoStatus->Status = STATUS_INVALID_PARAMETER;
  143. return TRUE;
  144. }
  145. //
  146. // Only deal with 'good' Fcb's.
  147. //
  148. if (!CdVerifyFcbOperation( NULL, Fcb )) {
  149. return FALSE;
  150. }
  151. FsRtlEnterFileSystem();
  152. //
  153. // Use a try-finally to facilitate cleanup.
  154. //
  155. try {
  156. //
  157. // We check whether we can proceed based on the state of the file oplocks.
  158. //
  159. if ((Fcb->Oplock != NULL) && !FsRtlOplockIsFastIoPossible( &Fcb->Oplock )) {
  160. try_return( NOTHING );
  161. }
  162. //
  163. // If we don't have a file lock, then get one now.
  164. //
  165. if ((Fcb->FileLock == NULL) && !CdCreateFileLock( NULL, Fcb, FALSE )) {
  166. try_return( NOTHING );
  167. }
  168. //
  169. // Now call the FsRtl routine to perform the lock request.
  170. //
  171. if (Results = FsRtlFastLock( Fcb->FileLock,
  172. FileObject,
  173. FileOffset,
  174. Length,
  175. ProcessId,
  176. Key,
  177. FailImmediately,
  178. ExclusiveLock,
  179. IoStatus,
  180. NULL,
  181. FALSE )) {
  182. //
  183. // Set the flag indicating if Fast I/O is questionable. We
  184. // only change this flag if the current state is possible.
  185. // Retest again after synchronizing on the header.
  186. //
  187. if (Fcb->IsFastIoPossible == FastIoIsPossible) {
  188. CdLockFcb( NULL, Fcb );
  189. Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
  190. CdUnlockFcb( NULL, Fcb );
  191. }
  192. }
  193. try_exit: NOTHING;
  194. } finally {
  195. FsRtlExitFileSystem();
  196. }
  197. return Results;
  198. }
  199. BOOLEAN
  200. CdFastUnlockSingle (
  201. IN PFILE_OBJECT FileObject,
  202. IN PLARGE_INTEGER FileOffset,
  203. IN PLARGE_INTEGER Length,
  204. PEPROCESS ProcessId,
  205. ULONG Key,
  206. OUT PIO_STATUS_BLOCK IoStatus,
  207. IN PDEVICE_OBJECT DeviceObject
  208. )
  209. /*++
  210. Routine Description:
  211. This is a call back routine for doing the fast unlock single call.
  212. Arguments:
  213. FileObject - Supplies the file object used in this operation
  214. FileOffset - Supplies the file offset used in this operation
  215. Length - Supplies the length used in this operation
  216. ProcessId - Supplies the process ID used in this operation
  217. Key - Supplies the key used in this operation
  218. Status - Receives the Status if this operation is successful
  219. Return Value:
  220. BOOLEAN - TRUE if this operation completed and FALSE if caller
  221. needs to take the long route.
  222. --*/
  223. {
  224. BOOLEAN Results = FALSE;
  225. TYPE_OF_OPEN TypeOfOpen;
  226. PFCB Fcb;
  227. PAGED_CODE();
  228. IoStatus->Information = 0;
  229. //
  230. // Decode the type of file object we're being asked to process and
  231. // make sure that is is only a user file open.
  232. //
  233. TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
  234. if (TypeOfOpen != UserFileOpen) {
  235. IoStatus->Status = STATUS_INVALID_PARAMETER;
  236. return TRUE;
  237. }
  238. //
  239. // Only deal with 'good' Fcb's.
  240. //
  241. if (!CdVerifyFcbOperation( NULL, Fcb )) {
  242. return FALSE;
  243. }
  244. //
  245. // If there is no lock then return immediately.
  246. //
  247. if (Fcb->FileLock == NULL) {
  248. IoStatus->Status = STATUS_RANGE_NOT_LOCKED;
  249. return TRUE;
  250. }
  251. FsRtlEnterFileSystem();
  252. try {
  253. //
  254. // We check whether we can proceed based on the state of the file oplocks.
  255. //
  256. if ((Fcb->Oplock != NULL) && !FsRtlOplockIsFastIoPossible( &Fcb->Oplock )) {
  257. try_return( NOTHING );
  258. }
  259. //
  260. // If we don't have a file lock, then get one now.
  261. //
  262. if ((Fcb->FileLock == NULL) && !CdCreateFileLock( NULL, Fcb, FALSE )) {
  263. try_return( NOTHING );
  264. }
  265. //
  266. // Now call the FsRtl routine to do the actual processing of the
  267. // Lock request. The call will always succeed.
  268. //
  269. Results = TRUE;
  270. IoStatus->Status = FsRtlFastUnlockSingle( Fcb->FileLock,
  271. FileObject,
  272. FileOffset,
  273. Length,
  274. ProcessId,
  275. Key,
  276. NULL,
  277. FALSE );
  278. //
  279. // Set the flag indicating if Fast I/O is possible. We are
  280. // only concerned if there are no longer any filelocks on this
  281. // file.
  282. //
  283. if (!FsRtlAreThereCurrentFileLocks( Fcb->FileLock ) &&
  284. (Fcb->IsFastIoPossible != FastIoIsPossible)) {
  285. CdLockFcb( IrpContext, Fcb );
  286. Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
  287. CdUnlockFcb( IrpContext, Fcb );
  288. }
  289. try_exit: NOTHING;
  290. } finally {
  291. FsRtlExitFileSystem();
  292. }
  293. return Results;
  294. }
  295. BOOLEAN
  296. CdFastUnlockAll (
  297. IN PFILE_OBJECT FileObject,
  298. PEPROCESS ProcessId,
  299. OUT PIO_STATUS_BLOCK IoStatus,
  300. IN PDEVICE_OBJECT DeviceObject
  301. )
  302. /*++
  303. Routine Description:
  304. This is a call back routine for doing the fast unlock all call.
  305. Arguments:
  306. FileObject - Supplies the file object used in this operation
  307. ProcessId - Supplies the process ID used in this operation
  308. Status - Receives the Status if this operation is successful
  309. Return Value:
  310. BOOLEAN - TRUE if this operation completed and FALSE if caller
  311. needs to take the long route.
  312. --*/
  313. {
  314. BOOLEAN Results = FALSE;
  315. TYPE_OF_OPEN TypeOfOpen;
  316. PFCB Fcb;
  317. PAGED_CODE();
  318. IoStatus->Information = 0;
  319. //
  320. // Decode the type of file object we're being asked to process and
  321. // make sure that is is only a user file open.
  322. //
  323. TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
  324. if (TypeOfOpen != UserFileOpen) {
  325. IoStatus->Status = STATUS_INVALID_PARAMETER;
  326. return TRUE;
  327. }
  328. //
  329. // Only deal with 'good' Fcb's.
  330. //
  331. if (!CdVerifyFcbOperation( NULL, Fcb )) {
  332. return FALSE;
  333. }
  334. //
  335. // If there is no lock then return immediately.
  336. //
  337. if (Fcb->FileLock == NULL) {
  338. IoStatus->Status = STATUS_RANGE_NOT_LOCKED;
  339. return TRUE;
  340. }
  341. FsRtlEnterFileSystem();
  342. try {
  343. //
  344. // We check whether we can proceed based on the state of the file oplocks.
  345. //
  346. if ((Fcb->Oplock != NULL) && !FsRtlOplockIsFastIoPossible( &Fcb->Oplock )) {
  347. try_return( NOTHING );
  348. }
  349. //
  350. // If we don't have a file lock, then get one now.
  351. //
  352. if ((Fcb->FileLock == NULL) && !CdCreateFileLock( NULL, Fcb, FALSE )) {
  353. try_return( NOTHING );
  354. }
  355. //
  356. // Now call the FsRtl routine to do the actual processing of the
  357. // Lock request. The call will always succeed.
  358. //
  359. Results = TRUE;
  360. IoStatus->Status = FsRtlFastUnlockAll( Fcb->FileLock,
  361. FileObject,
  362. ProcessId,
  363. NULL );
  364. //
  365. // Set the flag indicating if Fast I/O is possible
  366. //
  367. CdLockFcb( IrpContext, Fcb );
  368. Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
  369. CdUnlockFcb( IrpContext, Fcb );
  370. try_exit: NOTHING;
  371. } finally {
  372. FsRtlExitFileSystem();
  373. }
  374. return Results;
  375. }
  376. BOOLEAN
  377. CdFastUnlockAllByKey (
  378. IN PFILE_OBJECT FileObject,
  379. PVOID ProcessId,
  380. ULONG Key,
  381. OUT PIO_STATUS_BLOCK IoStatus,
  382. IN PDEVICE_OBJECT DeviceObject
  383. )
  384. /*++
  385. Routine Description:
  386. This is a call back routine for doing the fast unlock all by key call.
  387. Arguments:
  388. FileObject - Supplies the file object used in this operation
  389. ProcessId - Supplies the process ID used in this operation
  390. Key - Supplies the key used in this operation
  391. Status - Receives the Status if this operation is successful
  392. Return Value:
  393. BOOLEAN - TRUE if this operation completed and FALSE if caller
  394. needs to take the long route.
  395. --*/
  396. {
  397. BOOLEAN Results = FALSE;
  398. TYPE_OF_OPEN TypeOfOpen;
  399. PFCB Fcb;
  400. PAGED_CODE();
  401. IoStatus->Information = 0;
  402. //
  403. // Decode the type of file object we're being asked to process and
  404. // make sure that is is only a user file open.
  405. //
  406. TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
  407. if (TypeOfOpen != UserFileOpen) {
  408. IoStatus->Status = STATUS_INVALID_PARAMETER;
  409. return TRUE;
  410. }
  411. //
  412. // Only deal with 'good' Fcb's.
  413. //
  414. if (!CdVerifyFcbOperation( NULL, Fcb )) {
  415. return FALSE;
  416. }
  417. //
  418. // If there is no lock then return immediately.
  419. //
  420. if (Fcb->FileLock == NULL) {
  421. IoStatus->Status = STATUS_RANGE_NOT_LOCKED;
  422. return TRUE;
  423. }
  424. FsRtlEnterFileSystem();
  425. try {
  426. //
  427. // We check whether we can proceed based on the state of the file oplocks.
  428. //
  429. if ((Fcb->Oplock != NULL) && !FsRtlOplockIsFastIoPossible( &Fcb->Oplock )) {
  430. try_return( NOTHING );
  431. }
  432. //
  433. // If we don't have a file lock, then get one now.
  434. //
  435. if ((Fcb->FileLock == NULL) && !CdCreateFileLock( NULL, Fcb, FALSE )) {
  436. try_return( NOTHING );
  437. }
  438. //
  439. // Now call the FsRtl routine to do the actual processing of the
  440. // Lock request. The call will always succeed.
  441. //
  442. Results = TRUE;
  443. IoStatus->Status = FsRtlFastUnlockAllByKey( Fcb->FileLock,
  444. FileObject,
  445. ProcessId,
  446. Key,
  447. NULL );
  448. //
  449. // Set the flag indicating if Fast I/O is possible
  450. //
  451. CdLockFcb( IrpContext, Fcb );
  452. Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
  453. CdUnlockFcb( IrpContext, Fcb );
  454. try_exit: NOTHING;
  455. } finally {
  456. FsRtlExitFileSystem();
  457. }
  458. return Results;
  459. }