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.

224 lines
6.8 KiB

  1. /*
  2. * LOCK.C
  3. *
  4. * RSM Service : Locking functions for Physical Media and Media Pools
  5. *
  6. * Author: ErvinP
  7. *
  8. * (c) 2001 Microsoft Corporation
  9. *
  10. */
  11. #include <windows.h>
  12. #include <stdlib.h>
  13. #include <wtypes.h>
  14. #include <ntmsapi.h>
  15. #include "internal.h"
  16. #include "resource.h"
  17. #include "debug.h"
  18. BOOLEAN LockPhysicalMediaWithPool_Iter(PHYSICAL_MEDIA *physMedia, ULONG numTries);
  19. BOOLEAN LockPhysicalMediaWithLibrary_Iter(PHYSICAL_MEDIA *physMedia, ULONG numTries);
  20. /*
  21. * LockPhysicalMediaWithPool
  22. *
  23. * Warning: ugly function
  24. *
  25. * We frequently need to lock a piece of media as well as
  26. * its media pool.
  27. * To avoid deadlock, we have to acquire the locks top-down
  28. * (starting with the pool). But that's difficult since we're starting
  29. * with the physical media pointer.
  30. * This function enters the media pool and physical media
  31. * critical sections in the right order.
  32. * Subsequently, the caller can safely call subroutines that re-enter
  33. * these critical sections in any order.
  34. */
  35. BOOLEAN LockPhysicalMediaWithPool(PHYSICAL_MEDIA *physMedia)
  36. {
  37. return LockPhysicalMediaWithPool_Iter(physMedia, 10);
  38. }
  39. BOOLEAN LockPhysicalMediaWithPool_Iter(PHYSICAL_MEDIA *physMedia, ULONG numTries){
  40. MEDIA_POOL *mediaPool;
  41. BOOLEAN success = FALSE;
  42. /*
  43. * 1. Get an (unreliable) snapshot of the heirarchy without grabbing
  44. * more than one lock at a time. If the media is in a pool,
  45. * reference it temporarily so that it doesn't go away while
  46. * we drop the media lock (which can then lose its ref on the pool).
  47. */
  48. EnterCriticalSection(&physMedia->lock);
  49. mediaPool = physMedia->owningMediaPool;
  50. if (mediaPool){
  51. RefObject(mediaPool);
  52. }
  53. LeaveCriticalSection(&physMedia->lock);
  54. /*
  55. * 2. Now grab the locks for the pool and media in the right order.
  56. * Then check the hierarchy again.
  57. * If its the same, we're done; otherwise, try again.
  58. *
  59. */
  60. if (mediaPool){
  61. /*
  62. * We referenced the media pool, so its guaranteed to still exist.
  63. * But the media may have been moved out of it while we
  64. * let go of the lock. If the hierarchy is still the same, then
  65. * we've got both the media and pool locked in the right order.
  66. * Otherwise, we have to back off and try again.
  67. */
  68. EnterCriticalSection(&mediaPool->lock);
  69. EnterCriticalSection(&physMedia->lock);
  70. if (physMedia->owningMediaPool == mediaPool){
  71. success = TRUE;
  72. }
  73. else {
  74. LeaveCriticalSection(&physMedia->lock);
  75. LeaveCriticalSection(&mediaPool->lock);
  76. }
  77. DerefObject(mediaPool);
  78. }
  79. else {
  80. /*
  81. * If after locking the media again it is still not in any pool,
  82. * we are set to go.
  83. */
  84. EnterCriticalSection(&physMedia->lock);
  85. if (physMedia->owningMediaPool){
  86. LeaveCriticalSection(&physMedia->lock);
  87. }
  88. else {
  89. success = TRUE;
  90. }
  91. }
  92. if (!success && (numTries > 0)){
  93. /*
  94. * Try again by calling ourselves RECURSIVELY.
  95. */
  96. Sleep(1);
  97. success = LockPhysicalMediaWithPool_Iter(physMedia, numTries-1);
  98. }
  99. return success;
  100. }
  101. /*
  102. * UnlockPhysicalMediaWithPool
  103. *
  104. * Undo LockPhysicalMediaWithPool.
  105. */
  106. VOID UnlockPhysicalMediaWithPool(PHYSICAL_MEDIA *physMedia)
  107. {
  108. if (physMedia->owningMediaPool){
  109. LeaveCriticalSection(&physMedia->owningMediaPool->lock);
  110. }
  111. LeaveCriticalSection(&physMedia->lock);
  112. }
  113. /*
  114. * LockPhysicalMediaWithLibrary
  115. *
  116. * Warning: ugly function
  117. *
  118. * Like LockPhysicalMediaWithPool, but locks the media pool
  119. * and the library. Acquires locks in the right
  120. * order (top to down) despite the fact that we're starting
  121. * from the bottom with the media.
  122. * Note that we don't have to actually grab locks for all
  123. * the media sub-pools in the hierarchy. The media pool configuration
  124. * does not change while the library lock is held.
  125. */
  126. BOOLEAN LockPhysicalMediaWithLibrary(PHYSICAL_MEDIA *physMedia)
  127. {
  128. return LockPhysicalMediaWithLibrary_Iter(physMedia, 10);
  129. }
  130. BOOLEAN LockPhysicalMediaWithLibrary_Iter(PHYSICAL_MEDIA *physMedia, ULONG numTries)
  131. {
  132. LIBRARY *lib = NULL;
  133. MEDIA_POOL *mediaPool = NULL;
  134. BOOLEAN success = FALSE;
  135. success = LockPhysicalMediaWithPool(physMedia);
  136. if (success){
  137. /*
  138. * Reference the library so it doesn't go away while
  139. * we drop the locks.
  140. */
  141. mediaPool = physMedia->owningMediaPool;
  142. if (mediaPool){
  143. RefObject(mediaPool);
  144. lib = mediaPool->owningLibrary;
  145. if (lib){
  146. RefObject(lib);
  147. }
  148. }
  149. UnlockPhysicalMediaWithPool(physMedia);
  150. /*
  151. * Now grab the locks in the right order and check if
  152. * the configuration hasn't changed while we dropped the lock.
  153. */
  154. if (lib){
  155. EnterCriticalSection(&lib->lock);
  156. success = LockPhysicalMediaWithPool(physMedia);
  157. if (success){
  158. if (physMedia->owningMediaPool &&
  159. (physMedia->owningMediaPool->owningLibrary == lib)){
  160. }
  161. else {
  162. UnlockPhysicalMediaWithPool(physMedia);
  163. success = FALSE;
  164. }
  165. }
  166. if (!success){
  167. LeaveCriticalSection(&lib->lock);
  168. }
  169. DerefObject(lib);
  170. }
  171. else {
  172. /*
  173. * Media is not in any pool or lib ?
  174. * Just make sure nothing's changed while we dropped the lock.
  175. */
  176. success = LockPhysicalMediaWithPool(physMedia);
  177. if (mediaPool){
  178. if ((physMedia->owningMediaPool == mediaPool) &&
  179. (mediaPool->owningLibrary == lib)){
  180. }
  181. else {
  182. UnlockPhysicalMediaWithPool(physMedia);
  183. success = FALSE;
  184. }
  185. }
  186. }
  187. }
  188. if (!success && (numTries > 0)){
  189. success = LockPhysicalMediaWithLibrary_Iter(physMedia, numTries-1);
  190. }
  191. return success;
  192. }
  193. VOID UnlockPhysicalMediaWithLibrary(PHYSICAL_MEDIA *physMedia)
  194. {
  195. if (physMedia->owningMediaPool &&
  196. physMedia->owningMediaPool->owningLibrary){
  197. LeaveCriticalSection(&physMedia->owningMediaPool->owningLibrary->lock);
  198. }
  199. UnlockPhysicalMediaWithPool(physMedia);
  200. }