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.

482 lines
14 KiB

  1. /*
  2. * MEDIA.C
  3. *
  4. * RSM Service : Physical Media
  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. PHYSICAL_MEDIA *NewPhysicalMedia()
  19. {
  20. PHYSICAL_MEDIA *physMedia;
  21. physMedia = GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, sizeof(PHYSICAL_MEDIA));
  22. if (physMedia){
  23. physMedia->mediaFreeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  24. if (physMedia->mediaFreeEvent){
  25. InitializeCriticalSection(&physMedia->lock);
  26. InitializeListHead(&physMedia->physMediaListEntry);
  27. physMedia->objHeader.objType = OBJECTTYPE_PHYSICALMEDIA;
  28. physMedia->objHeader.refCount = 1;
  29. // BUGBUG FINISH
  30. }
  31. else {
  32. GlobalFree(physMedia);
  33. physMedia = NULL;
  34. }
  35. }
  36. ASSERT(physMedia);
  37. return physMedia;
  38. }
  39. VOID DestroyPhysicalMedia(PHYSICAL_MEDIA *physMedia)
  40. {
  41. // BUGBUG FINISH
  42. CloseHandle(physMedia->mediaFreeEvent);
  43. DeleteCriticalSection(&physMedia->lock);
  44. GlobalFree(physMedia);
  45. }
  46. PHYSICAL_MEDIA *FindPhysicalMedia(LPNTMS_GUID physMediaId)
  47. {
  48. PHYSICAL_MEDIA *foundPhysMedia = NULL;
  49. if (physMediaId){
  50. OBJECT_HEADER *objHdr;
  51. objHdr = FindObjectInGuidHash(physMediaId);
  52. if (objHdr){
  53. if (objHdr->objType == OBJECTTYPE_PHYSICALMEDIA){
  54. foundPhysMedia = (PHYSICAL_MEDIA *)objHdr;
  55. }
  56. else {
  57. DerefObject(objHdr);
  58. }
  59. }
  60. }
  61. return foundPhysMedia;
  62. }
  63. /*
  64. * AllocatePhysicalMediaExclusive
  65. *
  66. * Allocate a partition on the specified physicalMedia with an exclusive
  67. * hold on the other partitions.
  68. */
  69. HRESULT AllocatePhysicalMediaExclusive(SESSION *thisSession,
  70. PHYSICAL_MEDIA *physMedia,
  71. LPNTMS_GUID lpPartitionId,
  72. DWORD dwTimeoutMsec)
  73. {
  74. DWORD startTime = GetTickCount();
  75. HRESULT result;
  76. ASSERT(lpPartitionId);
  77. while (TRUE){
  78. BOOL gotMedia;
  79. MEDIA_PARTITION *reservedMediaPartition = NULL;
  80. ULONG i;
  81. EnterCriticalSection(&physMedia->lock);
  82. /*
  83. * Check that the media is not held.
  84. */
  85. if (physMedia->owningSession){
  86. ASSERT(physMedia->owningSession != thisSession);
  87. gotMedia = FALSE;
  88. }
  89. else {
  90. /*
  91. * Check that none of the partitions are held.
  92. */
  93. gotMedia = TRUE;
  94. for (i = 0; i < physMedia->numPartitions; i++){
  95. MEDIA_PARTITION *thisPartition = &physMedia->partitions[i];
  96. if (thisPartition->owningSession){
  97. gotMedia = FALSE;
  98. break;
  99. }
  100. else if (RtlEqualMemory(&thisPartition->objHeader.guid, lpPartitionId, sizeof(NTMS_GUID))){
  101. ASSERT(!reservedMediaPartition);
  102. reservedMediaPartition = thisPartition;
  103. }
  104. }
  105. }
  106. if (gotMedia){
  107. if (reservedMediaPartition){
  108. physMedia->owningSession = thisSession;
  109. reservedMediaPartition->owningSession = thisSession;
  110. physMedia->numPartitionsOwnedBySession = 1;
  111. RefObject(physMedia);
  112. RefObject(reservedMediaPartition);
  113. result = ERROR_SUCCESS;
  114. }
  115. else {
  116. result = ERROR_INVALID_MEDIA;
  117. }
  118. }
  119. else {
  120. result = ERROR_MEDIA_UNAVAILABLE;
  121. }
  122. LeaveCriticalSection(&physMedia->lock);
  123. /*
  124. * If appropriate, wait for the media to become free.
  125. */
  126. if ((result == ERROR_MEDIA_UNAVAILABLE) && (dwTimeoutMsec > 0)){
  127. /*
  128. * Wait for the media to become available.
  129. */
  130. DWORD waitRes = WaitForSingleObject(physMedia->mediaFreeEvent, dwTimeoutMsec);
  131. if (waitRes == WAIT_TIMEOUT){
  132. result = ERROR_TIMEOUT;
  133. break;
  134. }
  135. else {
  136. /*
  137. * Loop around and try again.
  138. */
  139. DWORD timeNow = GetTickCount();
  140. ASSERT(timeNow >= startTime);
  141. dwTimeoutMsec -= MIN(dwTimeoutMsec, timeNow-startTime);
  142. }
  143. }
  144. else {
  145. break;
  146. }
  147. }
  148. // BUGBUG FINISH - need to move media to different media pool ?
  149. return result;
  150. }
  151. /*
  152. * AllocateNextPartitionOnExclusiveMedia
  153. *
  154. * The calling session should already hold exclusive access to the media.
  155. * This call simply reserves another partition for the caller.
  156. */
  157. HRESULT AllocateNextPartitionOnExclusiveMedia(SESSION *thisSession,
  158. PHYSICAL_MEDIA *physMedia,
  159. MEDIA_PARTITION **ppNextPartition)
  160. {
  161. MEDIA_PARTITION *reservedMediaPartition = NULL;
  162. HRESULT result;
  163. ASSERT(physMedia->numPartitionsOwnedBySession >= 1);
  164. EnterCriticalSection(&physMedia->lock);
  165. if (physMedia->owningSession == thisSession){
  166. ULONG i;
  167. /*
  168. * Just reserve the next available partition
  169. */
  170. result = ERROR_MEDIA_UNAVAILABLE;
  171. for (i = 0; i < physMedia->numPartitions; i++){
  172. MEDIA_PARTITION *thisPartition = &physMedia->partitions[i];
  173. if (thisPartition->owningSession){
  174. ASSERT(thisPartition->owningSession == thisSession);
  175. }
  176. else {
  177. reservedMediaPartition = thisPartition;
  178. reservedMediaPartition->owningSession = thisSession;
  179. RefObject(reservedMediaPartition);
  180. physMedia->numPartitionsOwnedBySession++;
  181. result = ERROR_SUCCESS;
  182. break;
  183. }
  184. }
  185. }
  186. else {
  187. ASSERT(physMedia->owningSession == thisSession);
  188. result = ERROR_INVALID_MEDIA;
  189. }
  190. LeaveCriticalSection(&physMedia->lock);
  191. *ppNextPartition = reservedMediaPartition;
  192. return result;
  193. }
  194. HRESULT AllocateMediaFromPool( SESSION *thisSession,
  195. MEDIA_POOL *mediaPool,
  196. DWORD dwTimeoutMsec,
  197. PHYSICAL_MEDIA **ppPhysMedia,
  198. BOOL opReqIfNeeded)
  199. {
  200. DWORD startTime = GetTickCount();
  201. HRESULT result;
  202. while (TRUE){
  203. PHYSICAL_MEDIA *physMedia = NULL;
  204. LIST_ENTRY *listEntry;
  205. ULONG i;
  206. EnterCriticalSection(&mediaPool->lock);
  207. if (!IsListEmpty(&mediaPool->physMediaList)){
  208. /*
  209. * Remove the media.
  210. * Deref both the pool and the media since they no longer
  211. * point to each other.
  212. */
  213. PLIST_ENTRY listEntry = RemoveHeadList(&mediaPool->physMediaList);
  214. physMedia = CONTAINING_RECORD(listEntry, PHYSICAL_MEDIA, physMediaListEntry);
  215. DerefObject(mediaPool);
  216. DerefObject(physMedia);
  217. }
  218. LeaveCriticalSection(&mediaPool->lock);
  219. if (physMedia){
  220. // BUGBUG FINISH - enqueue it in a 'inUse' queue, change state ?
  221. *ppPhysMedia = physMedia;
  222. /*
  223. * Reference the media since we're returning a pointer to it.
  224. */
  225. RefObject(physMedia);
  226. result = ERROR_SUCCESS;
  227. break;
  228. }
  229. else {
  230. // BUGBUG FINISH - based on policy, try free/scratch pool
  231. if (opReqIfNeeded){
  232. // BUGBUG FINISH - do op request and try again ...
  233. }
  234. result = ERROR_MEDIA_UNAVAILABLE;
  235. }
  236. /*
  237. * If appropriate, wait for media to become free.
  238. */
  239. if ((result == ERROR_MEDIA_UNAVAILABLE) && (dwTimeoutMsec > 0)){
  240. /*
  241. * Wait on the designated media pool to receive new media.
  242. * The media pool's event will get signalled when either it
  243. * OR THE SCRATCH POOL receives new media.
  244. */
  245. DWORD waitRes = WaitForSingleObject(mediaPool->newMediaEvent, dwTimeoutMsec);
  246. if (waitRes == WAIT_TIMEOUT){
  247. result = ERROR_TIMEOUT;
  248. break;
  249. }
  250. else {
  251. /*
  252. * Loop around and try again.
  253. */
  254. DWORD timeNow = GetTickCount();
  255. dwTimeoutMsec -= MIN(dwTimeoutMsec, timeNow-startTime);
  256. }
  257. }
  258. else {
  259. break;
  260. }
  261. }
  262. return result;
  263. }
  264. HRESULT DeletePhysicalMedia(PHYSICAL_MEDIA *physMedia)
  265. {
  266. HRESULT result;
  267. // BUGBUG FINISH
  268. DBGERR(("not implemented"));
  269. result = ERROR_CALL_NOT_IMPLEMENTED;
  270. return result;
  271. }
  272. /*
  273. * InsertPhysicalMediaInPool
  274. *
  275. * Insert the physical media (which may not currently be in any pool)
  276. * into the designated media pool.
  277. */
  278. VOID InsertPhysicalMediaInPool( MEDIA_POOL *mediaPool,
  279. PHYSICAL_MEDIA *physMedia)
  280. {
  281. ASSERT(!physMedia->owningMediaPool);
  282. EnterCriticalSection(&mediaPool->lock);
  283. EnterCriticalSection(&physMedia->lock);
  284. InsertTailList(&mediaPool->physMediaList, &physMedia->physMediaListEntry);
  285. mediaPool->numPhysMedia++;
  286. physMedia->owningMediaPool = mediaPool;
  287. /*
  288. * Reference both objects since they now point to each other.
  289. */
  290. RefObject(mediaPool);
  291. RefObject(physMedia);
  292. LeaveCriticalSection(&physMedia->lock);
  293. LeaveCriticalSection(&mediaPool->lock);
  294. }
  295. /*
  296. * RemovePhysicalMediaFromPool
  297. *
  298. * Remove the physical media from containing media pool (if any).
  299. *
  300. * Must be called with physical media lock held.
  301. * If the media is indeed in a pool, pool lock must be held as well
  302. * (use LockPhysicalMediaWithPool).
  303. */
  304. VOID RemovePhysicalMediaFromPool(PHYSICAL_MEDIA *physMedia)
  305. {
  306. MEDIA_POOL *mediaPool = physMedia->owningMediaPool;
  307. HRESULT result;
  308. if (mediaPool){
  309. ASSERT(!IsListEmpty(&mediaPool->physMediaList));
  310. ASSERT(!IsListEmpty(&physMedia->physMediaListEntry));
  311. ASSERT(mediaPool->numPhysMedia > 0);
  312. RemoveEntryList(&physMedia->physMediaListEntry);
  313. InitializeListHead(&physMedia->physMediaListEntry);
  314. mediaPool->numPhysMedia--;
  315. physMedia->owningMediaPool = NULL;
  316. /*
  317. * Dereference both objects since they no longer point to each other.
  318. */
  319. DerefObject(mediaPool);
  320. DerefObject(physMedia);
  321. }
  322. else {
  323. /*
  324. * The media is not in any pool. So succeed.
  325. */
  326. }
  327. }
  328. /*
  329. * MovePhysicalMediaToPool
  330. *
  331. * Remove the physical media from whatever pool it is currently in
  332. * and move it to destMediaPool.
  333. */
  334. HRESULT MovePhysicalMediaToPool( MEDIA_POOL *destMediaPool,
  335. PHYSICAL_MEDIA *physMedia,
  336. BOOLEAN setMediaTypeToPoolType)
  337. {
  338. HRESULT result;
  339. BOOLEAN allowImport;
  340. ULONG i;
  341. if (LockPhysicalMediaWithPool(physMedia)){
  342. /*
  343. * We can only move the media if all media partitions are
  344. * in an importable state.
  345. */
  346. allowImport = TRUE;
  347. for (i = 0; i < physMedia->numPartitions; i++){
  348. MEDIA_PARTITION *thisMediaPart = &physMedia->partitions[i];
  349. if (!thisMediaPart->allowImport){
  350. allowImport = FALSE;
  351. break;
  352. }
  353. }
  354. if (allowImport){
  355. // BUGBUG FINISH - also check that media types match, etc.
  356. RemovePhysicalMediaFromPool(physMedia);
  357. result = ERROR_SUCCESS;
  358. }
  359. else {
  360. result = ERROR_ACCESS_DENIED;
  361. }
  362. /*
  363. * Drop the lock before touching the destination media pool.
  364. * We cannot hold locks on two pools at once (may cause deadlock).
  365. */
  366. UnlockPhysicalMediaWithPool(physMedia);
  367. if (result == ERROR_SUCCESS){
  368. InsertPhysicalMediaInPool(destMediaPool, physMedia);
  369. if (setMediaTypeToPoolType){
  370. /*
  371. * Set the media's type to the media pool's type.
  372. *
  373. * This part is failable. BUGBUG ?
  374. */
  375. if (LockPhysicalMediaWithPool(physMedia)){
  376. /*
  377. * Make sure that the media didn't move while
  378. * we dropped the lock. If it did, that's ok;
  379. * we can just leave it alone and let the new pool
  380. * take over.
  381. */
  382. if (physMedia->owningMediaPool == destMediaPool){
  383. SetMediaType(physMedia, destMediaPool->mediaTypeObj);
  384. }
  385. UnlockPhysicalMediaWithPool(physMedia);
  386. }
  387. }
  388. }
  389. }
  390. else {
  391. result = ERROR_BUSY;
  392. }
  393. return result;
  394. }