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.

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