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.

413 lines
8.0 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. blklock.c
  5. Abstract:
  6. This module implements routines for managing byte range lock blocks.
  7. Author:
  8. Andy Herron (andyhe) 15-Nov-1999
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include "blklock.tmh"
  13. #pragma hdrstop
  14. #ifdef INCLUDE_SMB_PERSISTENT
  15. #define BugCheckFileId SRV_FILE_BLKLOCK
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text( PAGE, SrvAllocateLock )
  18. #pragma alloc_text( PAGE, SrvFindAndReferenceLock )
  19. #pragma alloc_text( PAGE, SrvCloseLock )
  20. #pragma alloc_text( PAGE, SrvCloseLocksOnRfcb )
  21. #pragma alloc_text( PAGE, SrvDereferenceLock )
  22. #endif
  23. VOID
  24. SrvAllocateLock (
  25. OUT PBYTELOCK *Lock,
  26. IN PRFCB Rfcb,
  27. IN LARGE_INTEGER Offset,
  28. IN LARGE_INTEGER Length,
  29. IN BOOLEAN Exclusive
  30. )
  31. /*++
  32. Routine Description:
  33. This function allocates a lock block from the FSP heap.
  34. Arguments:
  35. Lock - Returns a pointer to the lock block, or NULL if
  36. no heap space was available.
  37. Rfcb - file which owns this lock. MFCB lock will be taken to insert lock
  38. into list.
  39. Offset - offset of lock in file.
  40. Length - lock length.
  41. Exclusive - is this a shared or exclusive lock?
  42. Return Value:
  43. None.
  44. --*/
  45. {
  46. PBYTELOCK lock;
  47. PNONPAGED_MFCB npMfcb;
  48. PAGED_CODE( );
  49. if ( ! Rfcb->PersistentHandle ) {
  50. *Lock = NULL;
  51. return;
  52. }
  53. //
  54. // Attempt to allocate from the heap.
  55. //
  56. lock = ALLOCATE_HEAP( sizeof(BYTELOCK), BlockTypeByteRangeLock );
  57. *Lock = lock;
  58. if ( lock == NULL ) {
  59. INTERNAL_ERROR(
  60. ERROR_LEVEL_EXPECTED,
  61. "SrvAllocateLock: Unable to allocate %d bytes from heap",
  62. sizeof(BYTELOCK),
  63. NULL
  64. );
  65. return;
  66. }
  67. IF_DEBUG(HEAP) {
  68. SrvPrint1( "SrvAllocateLock: Allocated byte range lock at %lx\n", lock );
  69. }
  70. RtlZeroMemory( lock, sizeof(BYTELOCK) );
  71. SET_BLOCK_TYPE_STATE_SIZE( lock, BlockTypeByteRangeLock, BlockStateActive, BlockTypeByteRangeLock );
  72. lock->BlockHeader.ReferenceCount = 2; // allow for Active status and caller's pointer
  73. lock->Rfcb = Rfcb;
  74. lock->LockOffset.QuadPart = Offset.QuadPart;
  75. lock->LockLength.QuadPart = Length.QuadPart;
  76. lock->Exclusive = Exclusive;
  77. INITIALIZE_REFERENCE_HISTORY( lock );
  78. npMfcb = Rfcb->Lfcb->Mfcb->NonpagedMfcb;
  79. ACQUIRE_LOCK( &npMfcb->Lock );
  80. SrvInsertHeadList( &Rfcb->PagedRfcb->ByteRangeLocks, &lock->RfcbListEntry );
  81. RELEASE_LOCK( &npMfcb->Lock );
  82. // INCREMENT_DEBUG_STAT( SrvDbgStatistics.SessionInfo.Allocations );
  83. return;
  84. } // SrvAllocateLock
  85. PBYTELOCK
  86. SrvFindAndReferenceLock (
  87. IN PRFCB Rfcb,
  88. IN LARGE_INTEGER Offset,
  89. IN LARGE_INTEGER Length,
  90. IN BOOLEAN Exclusive
  91. )
  92. /*++
  93. Routine Description:
  94. This function finds a lock, references it and returns it.
  95. Arguments:
  96. Rfcb - file which owns this lock. MFCB lock will be taken to insert lock
  97. into list.
  98. Offset - offset of lock in file.
  99. Length - lock length.
  100. Exclusive - is this a shared or exclusive lock?
  101. Return Value:
  102. PBYTELOCK - pointer to lock structure, null if doesn't exist.
  103. --*/
  104. {
  105. PBYTELOCK lock = NULL;
  106. PLIST_ENTRY listEntry;
  107. PLIST_ENTRY listHead;
  108. PNONPAGED_MFCB npMfcb;
  109. PAGED_CODE( );
  110. if (! Rfcb->PersistentHandle ) {
  111. return NULL;
  112. }
  113. npMfcb = Rfcb->Lfcb->Mfcb->NonpagedMfcb;
  114. ACQUIRE_LOCK( &npMfcb->Lock );
  115. listHead = &Rfcb->PagedRfcb->ByteRangeLocks;
  116. listEntry = listHead->Flink;
  117. while (listEntry != listHead) {
  118. lock = CONTAINING_RECORD( listEntry,
  119. BYTELOCK,
  120. RfcbListEntry
  121. );
  122. if ( GET_BLOCK_STATE(lock) == BlockStateActive &&
  123. lock->LockOffset.QuadPart == Offset.QuadPart &&
  124. lock->LockLength.QuadPart == Length.QuadPart &&
  125. lock->Exclusive == Exclusive ) {
  126. IF_DEBUG(REFCNT) {
  127. SrvPrint2( "Referencing byte lock 0x%lx; old refcnt %lx\n",
  128. lock, lock->BlockHeader.ReferenceCount );
  129. }
  130. ASSERT( GET_BLOCK_TYPE( lock ) == BlockTypeByteRangeLock );
  131. ASSERT( lock->BlockHeader.ReferenceCount > 0 );
  132. InterlockedIncrement( &lock->BlockHeader.ReferenceCount );
  133. break;
  134. }
  135. lock = NULL;
  136. listEntry = listEntry->Flink;
  137. }
  138. RELEASE_LOCK( &npMfcb->Lock );
  139. return lock;
  140. } // SrvFindAndReferenceLock
  141. VOID
  142. SrvCloseLock (
  143. IN PBYTELOCK Lock,
  144. IN BOOLEAN HaveLock
  145. )
  146. /*++
  147. Routine Description:
  148. This routine closes out the byte range lock block.
  149. Arguments:
  150. Lock - Supplies a pointer to the lock block that is to be closed.
  151. Return Value:
  152. None.
  153. --*/
  154. {
  155. PNONPAGED_MFCB npMfcb;
  156. PAGED_CODE( );
  157. ASSERT( Lock->Rfcb != NULL );
  158. if (!HaveLock) {
  159. npMfcb = Lock->Rfcb->Lfcb->Mfcb->NonpagedMfcb;
  160. ACQUIRE_LOCK( &npMfcb->Lock );
  161. }
  162. if ( GET_BLOCK_STATE(Lock) == BlockStateActive ) {
  163. IF_DEBUG(BLOCK1) SrvPrint1( "Closing byte lock at 0x%lx\n", Lock );
  164. SET_BLOCK_STATE( Lock, BlockStateClosing );
  165. SrvRemoveEntryList( &Rfcb->PagedRfcb->ByteRangeLocks, &Lock->RfcbListEntry );
  166. if (!HaveLock) {
  167. RELEASE_LOCK( &npMfcb->Lock );
  168. }
  169. // if ( we're in the state file ) {
  170. //
  171. // remove us from state file.
  172. // }
  173. Lock->Rfcb = NULL;
  174. //
  175. // Dereference the lock (to indicate that it's no longer
  176. // open).
  177. //
  178. SrvDereferenceLock( Lock );
  179. } else {
  180. if (!HaveLock) {
  181. RELEASE_LOCK( &npMfcb->Lock );
  182. }
  183. }
  184. return;
  185. } // SrvCloseLock
  186. VOID
  187. SrvCloseLocksOnRfcb (
  188. IN PRFCB Rfcb
  189. )
  190. /*++
  191. Routine Description:
  192. This function closes all locks on an RFCB. It walks the RFCB's
  193. list of locks, calling SrvCloseLock as appropriate.
  194. Arguments:
  195. Rfcb - Supplies a pointer to a Rfcb Block
  196. Return Value:
  197. None.
  198. --*/
  199. {
  200. PBYTELOCK lock;
  201. PLIST_ENTRY listEntry;
  202. PLIST_ENTRY listHead;
  203. PNONPAGED_MFCB npMfcb;
  204. PAGED_CODE( );
  205. if (! Rfcb->PersistentHandle ) {
  206. return;
  207. }
  208. npMfcb = Rfcb->Lfcb->Mfcb->NonpagedMfcb;
  209. ACQUIRE_LOCK( &npMfcb->Lock );
  210. listHead = &Rfcb->PagedRfcb->ByteRangeLocks;
  211. listEntry = listHead->Flink;
  212. while (listEntry != listHead) {
  213. lock = CONTAINING_RECORD( listEntry,
  214. BYTELOCK,
  215. RfcbListEntry
  216. );
  217. listEntry = listEntry->Flink;
  218. SrvCloseLock( lock, TRUE );
  219. }
  220. RELEASE_LOCK( &npMfcb->Lock );
  221. return;
  222. } // SrvCloseLocksOnRfcb
  223. VOID SRVFASTCALL
  224. SrvDereferenceLock (
  225. IN PBYTELOCK Lock
  226. )
  227. /*++
  228. Routine Description:
  229. This function decrements the reference count on a lock. If the
  230. reference count goes to zero, the lock block is deleted.
  231. Arguments:
  232. Lock - Address of lock
  233. Return Value:
  234. None.
  235. --*/
  236. {
  237. LONG result;
  238. PAGED_CODE( );
  239. //
  240. // Enter a critical section and decrement the reference count on the
  241. // block.
  242. //
  243. IF_DEBUG(REFCNT) {
  244. SrvPrint2( "Dereferencing byte lock 0x%lx; old refcnt %lx\n",
  245. Lock, Lock->BlockHeader.ReferenceCount );
  246. }
  247. ASSERT( GET_BLOCK_TYPE( Lock ) == BlockTypeByteRangeLock );
  248. ASSERT( Lock->BlockHeader.ReferenceCount > 0 );
  249. result = InterlockedDecrement(
  250. &Lock->BlockHeader.ReferenceCount
  251. );
  252. if ( result == 0 ) {
  253. ASSERT( GET_BLOCK_STATE(Lock) == BlockStateClosing );
  254. //
  255. // Free the session block.
  256. //
  257. DEBUG SET_BLOCK_TYPE_STATE_SIZE( Lock, BlockTypeGarbage, BlockStateDead, -1 );
  258. DEBUG Lock->BlockHeader.ReferenceCount = -1;
  259. FREE_HEAP( Lock );
  260. IF_DEBUG(HEAP) {
  261. SrvPrint1( "SrvDereferenceLock: Freed session byte lock at 0x%lx\n", Lock );
  262. }
  263. }
  264. return;
  265. } // SrvDereferenceLock
  266. #endif // def INCLUDE_SMB_PERSISTENT
  267. // blklock.c eof