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.

4254 lines
135 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. fmgum.c
  5. Abstract:
  6. Cluster FM Global Update processing routines.
  7. Author:
  8. Rod Gamache (rodga) 24-Apr-1996
  9. Revision History:
  10. --*/
  11. #include "fmp.h"
  12. #include "ntrtl.h"
  13. #if NO_SHARED_LOCKS
  14. extern CRITICAL_SECTION gLockDmpRoot;
  15. #else
  16. extern RTL_RESOURCE gLockDmpRoot;
  17. #endif
  18. #define NODE_ID_SZ 6
  19. #define LOG_MODULE FMGUM
  20. DWORD
  21. WINAPI
  22. FmpGumReceiveUpdates(
  23. IN DWORD Context,
  24. IN BOOL SourceNode,
  25. IN DWORD BufferLength,
  26. IN PVOID Buffer
  27. )
  28. /*++
  29. Routine Description:
  30. Updates the specified resource (contained within Buffer) with a new
  31. state.
  32. Arguments:
  33. Context - The message update type.
  34. SourceNode - TRUE if this is the source node for this update.
  35. FALSE otherwise.
  36. BufferLength - Length of the received buffer.
  37. Buffer - The actual buffer
  38. Returns:
  39. ERROR_SUCCESS
  40. --*/
  41. {
  42. PFM_RESOURCE resource;
  43. //
  44. // Chittur Subbaraman (chitturs) - 4/18/99
  45. //
  46. // If FM groups are not fully initialized or FM is shutting down, then
  47. // don't do anything.
  48. //
  49. if ( !FmpFMGroupsInited ||
  50. FmpShutdown ) {
  51. return(ERROR_SUCCESS);
  52. }
  53. switch ( Context ) {
  54. case FmUpdateFailureCount:
  55. {
  56. PGUM_FAILURE_COUNT failureCount;
  57. PFM_GROUP group;
  58. //
  59. // This update type is always sent.
  60. // On the originating node, all of the work must be done by
  61. // the sending thread.
  62. // On the non-originating nodes, no locks can be acquired! This
  63. // would cause hang situations with operations like move.
  64. // ... this is okay, since the locking must be done on the sending
  65. // node anyway, which owns the group.
  66. //
  67. if ( SourceNode == FALSE ) {
  68. if ( BufferLength <= sizeof(GUM_FAILURE_COUNT) ) {
  69. ClRtlLogPrint(LOG_UNUSUAL, "[FM] Gum FailureCount receive buffer too small!\n");
  70. return(ERROR_SUCCESS);
  71. }
  72. failureCount = (PGUM_FAILURE_COUNT)Buffer;
  73. group = OmReferenceObjectById( ObjectTypeGroup,
  74. (LPCWSTR)&failureCount->GroupId[0] );
  75. if ( group == NULL ) {
  76. ClRtlLogPrint(LOG_UNUSUAL,
  77. "[FM] Gum FailureCount failed to find group %1!ws!\n",
  78. failureCount->GroupId);
  79. return(ERROR_SUCCESS);
  80. }
  81. ClRtlLogPrint(LOG_NOISE,
  82. "[FM] GUM update failure count %1!ws!, count %2!u!\n",
  83. failureCount->GroupId,
  84. failureCount->Count);
  85. //FmpAcquireLocalGroupLock( group );
  86. if ( group->OwnerNode == NmLocalNode ) {
  87. ClRtlLogPrint(LOG_NOISE,
  88. "[FM] Gum FailureCount wrong owner for %1!ws!\n",
  89. failureCount->GroupId);
  90. } else {
  91. group->NumberOfFailures = failureCount->Count;
  92. if ( failureCount->NewTime ) {
  93. group->FailureTime = GetTickCount();
  94. }
  95. }
  96. //FmpReleaseLocalGroupLock( group );
  97. OmDereferenceObject( group );
  98. }
  99. break;
  100. }
  101. case FmUpdateCreateGroup:
  102. {
  103. PGUM_CREATE_GROUP GumGroup;
  104. DWORD Status = ERROR_SUCCESS;
  105. GumGroup = (PGUM_CREATE_GROUP)Buffer;
  106. Status = FmpUpdateCreateGroup( GumGroup, SourceNode );
  107. return(Status);
  108. }
  109. case FmUpdateCreateResource:
  110. {
  111. DWORD dwStatus = ERROR_SUCCESS;
  112. PGUM_CREATE_RESOURCE GumResource =
  113. (PGUM_CREATE_RESOURCE)Buffer;
  114. dwStatus = FmpUpdateCreateResource( GumResource );
  115. return( dwStatus );
  116. }
  117. case FmUpdateAddPossibleNode:
  118. case FmUpdateRemovePossibleNode:
  119. {
  120. PGUM_CHANGE_POSSIBLE_NODE pGumChange;
  121. PFM_RESOURCE pResource;
  122. LPWSTR pszResourceId;
  123. LPWSTR pszNodeId;
  124. PNM_NODE pNode;
  125. DWORD dwStatus;
  126. DWORD dwControlCode;
  127. PFMP_POSSIBLE_NODE pPossibleNode;
  128. pGumChange = (PGUM_CHANGE_POSSIBLE_NODE)Buffer;
  129. pszResourceId = pGumChange->ResourceId;
  130. pszNodeId = (LPWSTR)((PCHAR)pszResourceId +
  131. pGumChange->ResourceIdLen);
  132. pResource = OmReferenceObjectById(ObjectTypeResource,pszResourceId);
  133. pNode = OmReferenceObjectById(ObjectTypeNode, pszNodeId);
  134. CL_ASSERT(pResource != NULL);
  135. CL_ASSERT(pNode != NULL);
  136. pPossibleNode = LocalAlloc( LMEM_FIXED,
  137. sizeof(FMP_POSSIBLE_NODE) );
  138. if ( pPossibleNode == NULL )
  139. {
  140. return(ERROR_NOT_ENOUGH_MEMORY);
  141. }
  142. if (Context == FmUpdateAddPossibleNode)
  143. {
  144. dwControlCode = CLUSCTL_RESOURCE_ADD_OWNER;
  145. }
  146. else
  147. {
  148. dwControlCode = CLUSCTL_RESOURCE_REMOVE_OWNER;
  149. }
  150. dwStatus = FmpUpdateChangeResourceNode(SourceNode,
  151. pResource, pNode, dwControlCode);
  152. //if status is not successful then return, else notify
  153. //resource dlls
  154. if (dwStatus != ERROR_SUCCESS)
  155. {
  156. //dereference the objects
  157. OmDereferenceObject(pResource);
  158. OmDereferenceObject(pNode);
  159. //free the memory
  160. LocalFree(pPossibleNode);
  161. return(dwStatus);
  162. }
  163. pPossibleNode->Resource = pResource;
  164. pPossibleNode->Node = pNode;
  165. pPossibleNode->ControlCode = dwControlCode;
  166. //
  167. // Tell the resource about the ADD/REMOVE in a worker thread.
  168. //
  169. FmpPostWorkItem( FM_EVENT_RESOURCE_CHANGE,
  170. pPossibleNode,
  171. 0 );
  172. //
  173. // Chittur Subbaraman (chitturs) - 6/7/99
  174. //
  175. // Don't reference pPossibleNode any more. It could have
  176. // been freed by the worker thread by the time you get
  177. // here.
  178. //
  179. ClusterEvent( CLUSTER_EVENT_RESOURCE_PROPERTY_CHANGE,
  180. pResource );
  181. // Let the worker thread perform the derefs/Frees
  182. return(dwStatus);
  183. }
  184. case FmUpdateJoin:
  185. if ( CsDmOrFmHasChanged )
  186. {
  187. //
  188. // We can only send back SEQMISMATCH if we're a pure Windows Server 2003 (or later) environment.
  189. // In a mixed mode cluster, a W2K node would end up infinitely retrying the FM join.
  190. //
  191. DWORD dwClusterHighestVersion;
  192. NmGetClusterOperationalVersion( &dwClusterHighestVersion, NULL, NULL );
  193. if ( CLUSTER_GET_MAJOR_VERSION( dwClusterHighestVersion ) < NT51_MAJOR_VERSION )
  194. {
  195. ClRtlLogPrint(LOG_UNUSUAL,"[FM] DM or FM update has occured during join; rejecting FmUpdateJoin.\n" );
  196. return ERROR_CLUSTER_DATABASE_SEQMISMATCH;
  197. }
  198. // Don't need to reset CsDmOrFmHasChanged here -- we will reset it when we see the DmUpdateJoin.
  199. }
  200. break;
  201. case FmUpdateCreateResourceType:
  202. {
  203. DWORD dwStatus;
  204. dwStatus = FmpUpdateCreateResourceType( Buffer );
  205. return( dwStatus );
  206. }
  207. break;
  208. case FmUpdateDeleteResourceType:
  209. {
  210. BOOL ResourceExists = FALSE;
  211. PFM_RESTYPE Type;
  212. Type = OmReferenceObjectById( ObjectTypeResType,
  213. (LPWSTR)Buffer);
  214. if (Type == NULL) {
  215. return(ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND);
  216. }
  217. //
  218. // Make sure no resources exist of this type.
  219. //
  220. OmEnumObjects( ObjectTypeResource,
  221. FmpFindResourceType,
  222. Type,
  223. &ResourceExists);
  224. if (ResourceExists) {
  225. OmDereferenceObject(Type);
  226. return(ERROR_DIR_NOT_EMPTY);
  227. }
  228. //
  229. // We need to dereference the object twice to get
  230. // rid of it. But then any notification handlers will
  231. // not get a chance to see the object by the time
  232. // the handler gets called. So we use the EP_DEREF_CONTEXT
  233. // flag to get the event processor to do the second deref
  234. // once everything has been dispatched.
  235. //
  236. FmpDeleteResType(Type);
  237. ClusterEventEx( CLUSTER_EVENT_RESTYPE_DELETED,
  238. EP_DEREF_CONTEXT,
  239. Type );
  240. }
  241. break;
  242. case FmUpdateChangeGroup:
  243. {
  244. PGUM_CHANGE_GROUP pGumChange;
  245. PFM_RESOURCE pResource;
  246. LPWSTR pszResourceId;
  247. LPWSTR pszGroupId;
  248. PFM_GROUP pNewGroup;
  249. DWORD dwStatus;
  250. DWORD dwClusterHighestVersion;
  251. pGumChange = (PGUM_CHANGE_GROUP)Buffer;
  252. pszResourceId = pGumChange->ResourceId;
  253. pszGroupId = (LPWSTR)((PCHAR)pszResourceId +
  254. pGumChange->ResourceIdLen);
  255. //
  256. // Find the specified resource and group.
  257. //
  258. pResource = OmReferenceObjectById(ObjectTypeResource,
  259. pszResourceId);
  260. if (pResource == NULL) {
  261. return(ERROR_RESOURCE_NOT_FOUND);
  262. }
  263. pNewGroup = OmReferenceObjectById(ObjectTypeGroup,
  264. pszGroupId);
  265. if (pNewGroup == NULL) {
  266. OmDereferenceObject(pResource);
  267. return(ERROR_SUCCESS);
  268. }
  269. dwStatus = FmpUpdateChangeResourceGroup(SourceNode,
  270. pResource, pNewGroup);
  271. OmDereferenceObject(pNewGroup);
  272. OmDereferenceObject(pResource);
  273. return(dwStatus);
  274. }
  275. break;
  276. default:
  277. {
  278. }
  279. ClRtlLogPrint(LOG_UNUSUAL,"[FM] Gum received bad context, %1!u!\n",
  280. Context);
  281. }
  282. return(ERROR_SUCCESS);
  283. } // FmpGumReceiveUpdates
  284. DWORD
  285. FmpUpdateChangeQuorumResource2(
  286. IN BOOL SourceNode,
  287. IN LPCWSTR NewQuorumResourceId,
  288. IN LPCWSTR szRootClusFilePath,
  289. IN LPDWORD pdwMaxQuorumLogSize,
  290. IN LPDWORD pdwQuorumArbTimeout,
  291. IN LPDWORD pdwNewQuorumResourceCharacterictics OPTIONAL
  292. )
  293. /*++
  294. Routine Description:
  295. Perform updates related to changing of the quorum resource.
  296. Arguments:
  297. Return Value:
  298. ERROR_SUCCESS if successful.
  299. A Win32 error code otherwise.
  300. --*/
  301. {
  302. PFM_RESOURCE pResource;
  303. PFM_RESOURCE pOldQuoResource=NULL;
  304. DWORD dwStatus;
  305. DWORD dwChkPtSeq;
  306. HDMKEY ResKey;
  307. HLOCALXSACTION hXsaction = NULL;
  308. HLOG hNewQuoLog=NULL;
  309. WCHAR szQuorumLogPath[MAX_PATH];
  310. if ( !FmpFMGroupsInited ||
  311. FmpShutdown ) {
  312. return(ERROR_SUCCESS);
  313. }
  314. lstrcpyW(szQuorumLogPath, szRootClusFilePath);
  315. //lstrcatW(szQuorumLogPath, cszClusLogFileRootDir);
  316. pResource = OmReferenceObjectById( ObjectTypeResource,
  317. NewQuorumResourceId );
  318. if (pResource == NULL)
  319. {
  320. ClRtlLogPrint(LOG_UNUSUAL,
  321. "[FM] FmpUpdateChangeQuorumResource: Resource <%1!ws!> could not be found....\n",
  322. NewQuorumResourceId);
  323. return(ERROR_SUCCESS);
  324. }
  325. DmPauseDiskManTimer();
  326. //since the resource->quorum is going to change, acquire the quocritsec
  327. //always acquire the gQuoCritsec before gQuoLock
  328. ACQUIRE_EXCLUSIVE_LOCK(gQuoChangeLock);
  329. //prevent any resources from going online at this time
  330. ACQUIRE_EXCLUSIVE_LOCK(gQuoLock);
  331. //pause any changes to the cluster database
  332. //always acquire this lock after gQuoLock(refer to the ordering of locks
  333. // in fminit.c)
  334. ACQUIRE_EXCLUSIVE_LOCK(gLockDmpRoot);
  335. //if this resource was already a quorum resource
  336. if (!pResource->QuorumResource)
  337. {
  338. //
  339. // Now find the current quorum resource.
  340. //
  341. OmEnumObjects( ObjectTypeResource,
  342. FmpFindQuorumResource,
  343. &pOldQuoResource,
  344. NULL );
  345. if ( pOldQuoResource != NULL )
  346. {
  347. CL_ASSERT( pOldQuoResource->QuorumResource );
  348. // Stop the quorum reservation thread!
  349. pOldQuoResource->QuorumResource = FALSE;
  350. }
  351. //set the new resource to be the quorum resource
  352. pResource->QuorumResource = TRUE;
  353. }
  354. //writes to the old log file
  355. hXsaction = DmBeginLocalUpdate();
  356. if (!hXsaction)
  357. {
  358. dwStatus = GetLastError();
  359. goto FnExit;
  360. }
  361. dwStatus = DmLocalSetValue( hXsaction,
  362. DmQuorumKey,
  363. cszPath,
  364. REG_SZ,
  365. (LPBYTE)szQuorumLogPath,
  366. (lstrlenW(szQuorumLogPath)+1) * sizeof(WCHAR));
  367. if (dwStatus != ERROR_SUCCESS)
  368. goto FnExit;
  369. #ifdef CLUSTER_TESTPOINT
  370. TESTPT(TpFailLocalXsaction) {
  371. LPWSTR pszStr = szQuorumLogPath;
  372. dwStatus = (MAX_PATH * sizeof(WCHAR));
  373. dwStatus = DmQuerySz( DmQuorumKey,
  374. cszPath,
  375. &pszStr,
  376. &dwStatus,
  377. &dwStatus);
  378. ClRtlLogPrint(LOG_UNUSUAL,
  379. "[FM] Testing failing a local transaction midway- new quorum path %1!ws!\r\n",
  380. szQuorumLogPath);
  381. dwStatus = 999999;
  382. goto FnExit;
  383. }
  384. #endif
  385. dwStatus = DmLocalSetValue( hXsaction,
  386. DmQuorumKey,
  387. cszMaxQuorumLogSize,
  388. REG_DWORD,
  389. (LPBYTE)pdwMaxQuorumLogSize,
  390. sizeof(DWORD));
  391. if (dwStatus != ERROR_SUCCESS)
  392. goto FnExit;
  393. //if the old quorum resource is different from the new quorum resource
  394. if ((pOldQuoResource) && (pOldQuoResource != pResource))
  395. {
  396. //get/set the new/old resource's flags
  397. //set the core flag on the new quorum resource
  398. ResKey = DmOpenKey( DmResourcesKey,
  399. NewQuorumResourceId,
  400. KEY_READ | KEY_SET_VALUE);
  401. if (!ResKey)
  402. {
  403. dwStatus = GetLastError();
  404. goto FnExit;
  405. }
  406. pResource->ExFlags |= CLUS_FLAG_CORE;
  407. dwStatus = DmLocalSetValue( hXsaction,
  408. ResKey,
  409. CLUSREG_NAME_FLAGS,
  410. REG_DWORD,
  411. (LPBYTE)&(pResource->ExFlags),
  412. sizeof(DWORD));
  413. DmCloseKey( ResKey );
  414. if (dwStatus != ERROR_SUCCESS)
  415. goto FnExit;
  416. //unset the core flag on the old quorum resource
  417. ResKey = DmOpenKey( DmResourcesKey,
  418. OmObjectId(pOldQuoResource),
  419. KEY_READ | KEY_SET_VALUE);
  420. if (!ResKey)
  421. {
  422. dwStatus = GetLastError();
  423. goto FnExit;
  424. }
  425. pOldQuoResource->ExFlags &= ~CLUS_FLAG_CORE;
  426. //unset the core flag on the old quorum resource
  427. dwStatus = DmLocalSetValue( hXsaction,
  428. ResKey,
  429. CLUSREG_NAME_FLAGS,
  430. REG_DWORD,
  431. (LPBYTE)&(pOldQuoResource->ExFlags),
  432. sizeof(DWORD));
  433. DmCloseKey( ResKey );
  434. if (dwStatus != ERROR_SUCCESS)
  435. goto FnExit;
  436. }
  437. //
  438. // Set the quorum resource value.
  439. //
  440. dwStatus = DmLocalSetValue( hXsaction,
  441. DmQuorumKey,
  442. CLUSREG_NAME_QUORUM_RESOURCE,
  443. REG_SZ,
  444. (CONST BYTE *)OmObjectId(pResource),
  445. (lstrlenW(OmObjectId(pResource))+1)*sizeof(WCHAR));
  446. if (dwStatus != ERROR_SUCCESS)
  447. {
  448. goto FnExit;
  449. }
  450. if (pdwQuorumArbTimeout)
  451. {
  452. //if this is a mixed mode cluster pdwQourumArbTimeout will be NULL
  453. // Update the cluster registry from there
  454. // MM reads this location on startup
  455. dwStatus = DmLocalSetValue( hXsaction,
  456. DmClusterParametersKey,
  457. CLUSREG_NAME_QUORUM_ARBITRATION_TIMEOUT,
  458. REG_DWORD,
  459. (CONST PUCHAR)pdwQuorumArbTimeout,
  460. sizeof(DWORD) );
  461. if ( dwStatus != ERROR_SUCCESS )
  462. {
  463. ClRtlLogPrint(LOG_UNUSUAL,
  464. "[FM] FmSetQuorumResource: failed to set the cluster arbitration timeout, status = %1!u!\n",
  465. dwStatus);
  466. goto FnExit;
  467. }
  468. ClRtlLogPrint(LOG_NOISE,
  469. "[FM] FmSetQuorumResource: setting QuorumArbitratrionTimeout to be = %1!u!\n",
  470. *pdwQuorumArbTimeout);
  471. // Tell MM about the change...
  472. MmQuorumArbitrationTimeout = *pdwQuorumArbTimeout;
  473. }
  474. FnExit:
  475. if (dwStatus == ERROR_SUCCESS)
  476. {
  477. LPWSTR szClusterName=NULL;
  478. DWORD dwSize=0;
  479. DWORD dwCharacteristics = CLUS_CHAR_UNKNOWN;
  480. //commit the update on the old log file,
  481. //any nodes that were done, will get this change
  482. //I cant delete this file
  483. DmCommitLocalUpdate(hXsaction);
  484. if ( !ARGUMENT_PRESENT ( pdwNewQuorumResourceCharacterictics ) )
  485. {
  486. pdwNewQuorumResourceCharacterictics = &dwCharacteristics;
  487. }
  488. //
  489. // If the caller has passed in characteristics, then don't bother to drop a control
  490. // code into a resource dll to find the characteristics in the following function.
  491. // Dropping a control code from within a GUM handler is disaster waiting to happen.
  492. //
  493. //
  494. //close the old log file, open the new one and take a checkpoint
  495. DmSwitchToNewQuorumLog(szQuorumLogPath, *pdwNewQuorumResourceCharacterictics);
  496. // SS:the buffer should contain the current cluster name ?
  497. DmQuerySz( DmClusterParametersKey,
  498. CLUSREG_NAME_CLUS_NAME,
  499. &szClusterName,
  500. &dwSize,
  501. &dwSize);
  502. if (szClusterName)
  503. ClusterEventEx(CLUSTER_EVENT_PROPERTY_CHANGE,
  504. EP_FREE_CONTEXT,
  505. szClusterName);
  506. if ((pOldQuoResource) && (pOldQuoResource != pResource))
  507. {
  508. //generate the resource property change events
  509. ClusterEvent( CLUSTER_EVENT_RESOURCE_PROPERTY_CHANGE,
  510. pResource );
  511. ClusterEvent( CLUSTER_EVENT_RESOURCE_PROPERTY_CHANGE,
  512. pOldQuoResource );
  513. }
  514. }
  515. else
  516. {
  517. if (hXsaction) DmAbortLocalUpdate(hXsaction);
  518. //reinstall the tombstone
  519. DmReinstallTombStone(szQuorumLogPath);
  520. //
  521. // Make sure the flags are reset back
  522. //
  523. if ((pOldQuoResource) && (pOldQuoResource != pResource))
  524. {
  525. pOldQuoResource->QuorumResource = TRUE;
  526. pResource->QuorumResource = FALSE;
  527. }
  528. }
  529. if (pOldQuoResource) OmDereferenceObject(pOldQuoResource);
  530. OmDereferenceObject(pResource);
  531. //release locks
  532. RELEASE_LOCK(gLockDmpRoot);
  533. RELEASE_LOCK(gQuoLock);
  534. RELEASE_LOCK(gQuoChangeLock);
  535. DmRestartDiskManTimer();
  536. return(dwStatus);
  537. }
  538. DWORD
  539. FmpUpdateChangeQuorumResource(
  540. IN BOOL SourceNode,
  541. IN LPCWSTR NewQuorumResourceId,
  542. IN LPCWSTR szRootClusFilePath,
  543. IN LPDWORD pdwMaxQuorumLogSize
  544. )
  545. /*++
  546. Routine Description:
  547. Perform updates related to changing of the quorum resource.
  548. Arguments:
  549. Return Value:
  550. ERROR_SUCCESS if successful.
  551. A Win32 error code otherwise.
  552. --*/
  553. {
  554. return(FmpUpdateChangeQuorumResource2(SourceNode, NewQuorumResourceId, szRootClusFilePath,
  555. pdwMaxQuorumLogSize, NULL, NULL));
  556. }
  557. DWORD
  558. FmpUpdateResourceState(
  559. IN BOOL SourceNode,
  560. IN LPCWSTR ResourceId,
  561. IN PGUM_RESOURCE_STATE ResourceState
  562. )
  563. /*++
  564. Routine Description:
  565. GUM update handler for resource state changes.
  566. Arguments:
  567. SourceNode - Supplies whether or not this node was the source of the update
  568. ResourceId - Supplies the id of the resource whose state is changing
  569. ResourceState - Supplies the new state of the resource.
  570. Return Value:
  571. ERROR_SUCCESS if successful
  572. Win32 error code otherwise
  573. --*/
  574. {
  575. PFM_RESOURCE resource;
  576. if ( !FmpFMGroupsInited ) {
  577. return(ERROR_SUCCESS);
  578. }
  579. //
  580. // This update type is always sent.
  581. // On the originating node, all of the work must be done by
  582. // the sending thread.
  583. // On the non-originating nodes, no locks can be acquired! This
  584. // would cause some hang situations with operations like move.
  585. // ... this is okay, since the locking must be done on the sending
  586. // node anyway, which owns the group.
  587. //
  588. if ( SourceNode == FALSE ) {
  589. resource = OmReferenceObjectById( ObjectTypeResource, ResourceId );
  590. if ( resource == NULL ) {
  591. ClRtlLogPrint(LOG_UNUSUAL,
  592. "[FM] Gum ResourceState failed to find resource %1!ws!\n",
  593. ResourceId);
  594. CL_LOGFAILURE( ERROR_RESOURCE_NOT_FOUND );
  595. return(ERROR_SUCCESS);
  596. }
  597. ClRtlLogPrint(LOG_NOISE,
  598. "[FM] Gum update resource %1!ws!, state %2!u!, current state %3!u!.\n",
  599. ResourceId,
  600. ResourceState->State,
  601. ResourceState->PersistentState);
  602. //FmpAcquireLocalResourceLock( resource );
  603. if ( resource->Group->OwnerNode == NmLocalNode ) {
  604. ClRtlLogPrint(LOG_NOISE,
  605. "[FM] Gum ResourceState wrong owner for %1!ws!\n",
  606. ResourceId);
  607. } else {
  608. resource->State = ResourceState->State;
  609. resource->PersistentState = ResourceState->PersistentState;
  610. resource->StateSequence = ResourceState->StateSequence;
  611. switch ( ResourceState->State ) {
  612. case ClusterResourceOnline:
  613. ClusterEvent( CLUSTER_EVENT_RESOURCE_ONLINE, resource );
  614. break;
  615. case ClusterResourceOffline:
  616. ClusterEvent( CLUSTER_EVENT_RESOURCE_OFFLINE, resource );
  617. break;
  618. case ClusterResourceFailed:
  619. ClusterEvent( CLUSTER_EVENT_RESOURCE_FAILED, resource );
  620. break;
  621. case ClusterResourceOnlinePending:
  622. case ClusterResourceOfflinePending:
  623. ClusterEvent( CLUSTER_EVENT_RESOURCE_CHANGE, resource );
  624. break;
  625. default:
  626. ClRtlLogPrint(LOG_UNUSUAL,
  627. "[FM] Gum update resource state, bad state %1!u!\n",
  628. ResourceState->State);
  629. break;
  630. }
  631. }
  632. OmDereferenceObject( resource );
  633. }
  634. return(ERROR_SUCCESS);
  635. }
  636. DWORD
  637. FmpUpdateGroupState(
  638. IN BOOL SourceNode,
  639. IN LPCWSTR GroupId,
  640. IN LPCWSTR NodeId,
  641. IN PGUM_GROUP_STATE GroupState
  642. )
  643. /*++
  644. Routine Description:
  645. GUM update handler for group state changes.
  646. Arguments:
  647. SourceNode - Supplies whether or not this node was the source of the update
  648. GroupId - Supplies the id of the resource whose state is changing
  649. NodeId - Supplies the node id of the group owner.
  650. GroupState - Supplies the new state of the group.
  651. Return Value:
  652. ERROR_SUCCESS if successful
  653. Win32 error code otherwise
  654. --*/
  655. {
  656. PFM_GROUP group;
  657. PWSTR nodeId;
  658. PNM_NODE node;
  659. if ( !FmpFMGroupsInited ) {
  660. return(ERROR_SUCCESS);
  661. }
  662. //
  663. // This update type is always sent.
  664. // On the originating node, all of the work must be done by
  665. // the sending thread.
  666. // On the non-originating nodes, no locks can be acquired! This
  667. // would cause some hang situations with operations like move.
  668. // ... this is okay, since the locking must be done on the sending
  669. // node anyway, which owns the group.
  670. //
  671. if ( SourceNode == FALSE ) {
  672. group = OmReferenceObjectById( ObjectTypeGroup,
  673. GroupId );
  674. if ( group == NULL ) {
  675. ClRtlLogPrint(LOG_UNUSUAL,
  676. "[FM] Gum GroupState failed to find group %1!ws!\n",
  677. GroupId);
  678. return(ERROR_SUCCESS);
  679. }
  680. ClRtlLogPrint(LOG_NOISE,
  681. "[FM] GUM update group %1!ws!, state %2!u!\n",
  682. GroupId,
  683. GroupState->State);
  684. if ( group->OwnerNode == NmLocalNode ) {
  685. ClRtlLogPrint(LOG_NOISE,
  686. "[FM] Gum GroupState wrong owner for %1!ws!\n",
  687. GroupId);
  688. } else {
  689. group->State = GroupState->State;
  690. group->PersistentState = GroupState->PersistentState;
  691. group->StateSequence = GroupState->StateSequence;
  692. node = OmReferenceObjectById( ObjectTypeNode,
  693. NodeId );
  694. if ( node == NULL ) {
  695. ClRtlLogPrint(LOG_UNUSUAL,
  696. "[FM] Owner of Group %1!ws! cannot be found %2!ws!\n",
  697. GroupId,
  698. NodeId);
  699. } else {
  700. ClRtlLogPrint(LOG_NOISE,
  701. "[FM] New owner of Group %1!ws! is %2!ws!, state %3!u!, curstate %4!u!.\n",
  702. OmObjectId( group ),
  703. OmObjectId( node ),
  704. group->State,
  705. group->PersistentState);
  706. if ( !FmpInPreferredList( group, node, FALSE, NULL ) ) {
  707. ClRtlLogPrint( LOG_UNUSUAL,
  708. "[FM] New owner %1!ws! is not in preferred list for group %2!ws!.\n",
  709. OmObjectId( node ),
  710. OmObjectId( group ));
  711. }
  712. }
  713. group->OwnerNode = node;
  714. switch ( GroupState->State ) {
  715. case ClusterGroupOnline:
  716. case ClusterGroupPartialOnline:
  717. ClusterEvent( CLUSTER_EVENT_GROUP_ONLINE, group );
  718. break;
  719. case ClusterGroupOffline:
  720. ClusterEvent( CLUSTER_EVENT_GROUP_OFFLINE, group );
  721. break;
  722. default:
  723. ClRtlLogPrint(LOG_UNUSUAL,"[FM] Gum update group state, bad state %1!u!\n", GroupState->State);
  724. break;
  725. }
  726. }
  727. OmDereferenceObject( group );
  728. }
  729. return(ERROR_SUCCESS);
  730. }
  731. DWORD
  732. FmpUpdateGroupNode(
  733. IN BOOL SourceNode,
  734. IN LPCWSTR GroupId,
  735. IN LPCWSTR NodeId
  736. )
  737. /*++
  738. Routine Description:
  739. GUM update handler for group node changes. This is required for
  740. notification
  741. when a group moves between nodes but does not change state (i.e. it was
  742. already offline)
  743. Arguments:
  744. SourceNode - Supplies whether or not this node was the source of the update
  745. GroupId - Supplies the id of the resource whose state is changing
  746. NodeId - Supplies the node id of the group owner.
  747. Return Value:
  748. ERROR_SUCCESS if successful
  749. Win32 error code otherwise
  750. --*/
  751. {
  752. PFM_GROUP pGroup;
  753. DWORD dwStatus = ERROR_SUCCESS;
  754. PNM_NODE pNode = NULL;
  755. PNM_NODE pPrevNode = NULL;
  756. if ( !FmpFMGroupsInited )
  757. {
  758. return(ERROR_SUCCESS);
  759. }
  760. pGroup = OmReferenceObjectById( ObjectTypeGroup,
  761. GroupId );
  762. if (pGroup == NULL)
  763. {
  764. ClRtlLogPrint(LOG_CRITICAL,
  765. "[FM] FmpUpdateGroupNode: GroupID = %1!ws! could not be found...\n",
  766. GroupId);
  767. //
  768. // Chittur Subbaraman (chitturs) - 6/12/99
  769. //
  770. // Return ERROR_SUCCESS here since this is what NT4 side does.
  771. // Compatibility pain !
  772. //
  773. goto FnExit;
  774. }
  775. pNode = OmReferenceObjectById(ObjectTypeNode,
  776. NodeId);
  777. if (pNode == NULL)
  778. {
  779. dwStatus = ERROR_CLUSTER_NODE_NOT_FOUND;
  780. goto FnExit;
  781. }
  782. //
  783. // HACKHACK: Chittur Subbaraman (chitturs) - 5/20/99
  784. // Comment out as a temporary solution to avoid deadlocks.
  785. //
  786. // FmpAcquireLocalGroupLock(pGroup);
  787. pPrevNode = pGroup->OwnerNode;
  788. //set the new owner node, incr ref count
  789. OmReferenceObject(pNode);
  790. pGroup->OwnerNode = pNode;
  791. //decr ref count on previous owner
  792. OmDereferenceObject(pPrevNode);
  793. //
  794. // HACKHACK: Chittur Subbaraman (chitturs) - 5/20/99
  795. // Comment out as a temporary solution to avoid deadlocks.
  796. //
  797. // FmpReleaseLocalGroupLock(pGroup);
  798. //generate an event to signify group owner node change
  799. ClusterEvent(CLUSTER_EVENT_GROUP_CHANGE, pGroup);
  800. FnExit:
  801. if (pGroup) OmDereferenceObject(pGroup);
  802. if (pNode) OmDereferenceObject(pNode);
  803. return(dwStatus);
  804. }
  805. DWORD
  806. FmpUpdateChangeClusterName(
  807. IN BOOL SourceNode,
  808. IN LPCWSTR szNewName
  809. )
  810. /*++
  811. Routine Description:
  812. GUM update routine for changing the name of the cluster.
  813. This changes the name property of the core network name resource
  814. as well. The resource is notified about it by a worker thread that
  815. the name has been changed.
  816. Arguments:
  817. SourceNode - Supplies whether or not this node originated the update.
  818. NewName - Supplies the new name of the cluster.
  819. Return Value:
  820. ERROR_SUCCESS if successful
  821. Win32 error code otherwise
  822. --*/
  823. {
  824. LPWSTR Buffer;
  825. DWORD Length;
  826. DWORD Status = ERROR_SUCCESS;
  827. LPWSTR ClusterNameId=NULL;
  828. DWORD idMaxSize = 0;
  829. DWORD idSize = 0;
  830. PFM_RESOURCE Resource=NULL;
  831. HDMKEY ResKey = NULL;
  832. HDMKEY ParamKey = NULL;
  833. HLOCALXSACTION hXsaction=NULL;
  834. DWORD cbNewClusterName;
  835. LPWSTR lpszNewClusterName;
  836. if ( !FmpFMGroupsInited ||
  837. FmpShutdown )
  838. {
  839. return(ERROR_SUCCESS);
  840. }
  841. cbNewClusterName = ( lstrlen ( szNewName ) + 1 ) * sizeof ( WCHAR );
  842. hXsaction = DmBeginLocalUpdate();
  843. if (!hXsaction)
  844. {
  845. Status = ERROR_SUCCESS;
  846. goto FnExit;
  847. }
  848. //find the core network name resource, set its private properties
  849. Status = DmQuerySz( DmClusterParametersKey,
  850. CLUSREG_NAME_CLUS_CLUSTER_NAME_RES,
  851. (LPWSTR*)&ClusterNameId,
  852. &idMaxSize,
  853. &idSize);
  854. if (Status != ERROR_SUCCESS) {
  855. ClRtlLogPrint(LOG_CRITICAL,
  856. "[FM] FmpUpdateChangeClusterName: failed to get cluster name resource, status=%1!u!.\n",
  857. Status);
  858. goto FnExit;
  859. }
  860. //
  861. // Reference the specified resource ID.
  862. //
  863. Resource = OmReferenceObjectById( ObjectTypeResource, ClusterNameId );
  864. if (Resource == NULL) {
  865. Status = ERROR_RESOURCE_NOT_FOUND;
  866. ClRtlLogPrint(LOG_CRITICAL,
  867. "[FM] FmpUpdateChangeClusterName: failed to find the cluster name resource, status=%1!u!\n",
  868. Status);
  869. goto FnExit;
  870. }
  871. ResKey = DmOpenKey(DmResourcesKey, ClusterNameId, KEY_READ | KEY_SET_VALUE);
  872. if (!ResKey)
  873. {
  874. Status = GetLastError();
  875. goto FnExit;
  876. }
  877. ParamKey = DmOpenKey(ResKey, cszParameters, KEY_READ | KEY_SET_VALUE);
  878. if (!ParamKey)
  879. {
  880. Status = GetLastError();
  881. goto FnExit;
  882. }
  883. Status = DmLocalSetValue(hXsaction,
  884. ParamKey,
  885. CLUSREG_NAME_NET_NAME,
  886. REG_SZ,
  887. (CONST BYTE *)szNewName,
  888. cbNewClusterName);
  889. if ( Status != ERROR_SUCCESS )
  890. {
  891. ClRtlLogPrint(LOG_CRITICAL,
  892. "[FM] FmpUpdateChangeClusterName: failed to set the Name property, Status=%1!u!\n",
  893. Status);
  894. goto FnExit;
  895. }
  896. //update the default cluster name
  897. Status = DmLocalSetValue(hXsaction,
  898. DmClusterParametersKey,
  899. CLUSREG_NAME_CLUS_NAME,
  900. REG_SZ,
  901. (CONST BYTE *)szNewName,
  902. cbNewClusterName);
  903. if (Status != ERROR_SUCCESS)
  904. {
  905. ClRtlLogPrint(LOG_CRITICAL,
  906. "[FM] FmpUpdateChangeClusterName: failed to set the cluster name property,Status=%1!u!\n",
  907. Status);
  908. goto FnExit;
  909. }
  910. //
  911. // Update the CsClusterName variable.
  912. // TODO: Need synchronization on CsClusterName
  913. //
  914. lpszNewClusterName = LocalAlloc ( LPTR, cbNewClusterName );
  915. if ( lpszNewClusterName == NULL )
  916. {
  917. Status = GetLastError();
  918. ClRtlLogPrint(LOG_CRITICAL, "[FM] FmpUpdateChangeClusterName: Alloc for name failed, Status=%1!u!\n",
  919. Status);
  920. goto FnExit;
  921. }
  922. LocalFree ( CsClusterName );
  923. CsClusterName = lpszNewClusterName;
  924. lstrcpy ( CsClusterName, szNewName );
  925. //the cluster_event_property_change is generated by the api itself using
  926. //the cluster wide event after netname has finished the applying the changes
  927. FnExit:
  928. if (ClusterNameId) LocalFree(ClusterNameId);
  929. if (ParamKey) DmCloseKey(ParamKey);
  930. if (ResKey) DmCloseKey(ResKey);
  931. if (Resource) OmDereferenceObject(Resource);
  932. if (hXsaction)
  933. {
  934. if (Status == ERROR_SUCCESS)
  935. DmCommitLocalUpdate(hXsaction);
  936. else
  937. DmAbortLocalUpdate(hXsaction);
  938. }
  939. return(Status);
  940. }
  941. DWORD
  942. FmpUpdateChangeResourceName(
  943. IN BOOL bSourceNode,
  944. IN LPCWSTR lpszResourceId,
  945. IN LPCWSTR lpszNewName
  946. )
  947. /*++
  948. Routine Description:
  949. GUM dispatch routine for changing the friendly name of a resource.
  950. Arguments:
  951. bSourceNode - Supplies whether or not this node initiated the GUM update.
  952. Not used.
  953. lpszResourceId - Supplies the resource ID.
  954. lpszNewName - Supplies the new friendly name.
  955. Return Value:
  956. ERROR_SUCCESS if successful.
  957. Win32 error code otherwise.
  958. --*/
  959. {
  960. PFM_RESOURCE pResource = NULL;
  961. DWORD dwStatus;
  962. HDMKEY hKey = NULL;
  963. DWORD dwDisposition;
  964. HLOCALXSACTION
  965. hXsaction = NULL;
  966. PFM_RES_CHANGE_NAME pResChangeName = NULL;
  967. if ( !FmpFMGroupsInited ||
  968. FmpShutdown ) {
  969. return( ERROR_SUCCESS );
  970. }
  971. //
  972. // Chittur Subbaraman (chitturs) - 6/28/99
  973. //
  974. // Restructure this GUM update as a local transaction.
  975. //
  976. //
  977. pResource = OmReferenceObjectById( ObjectTypeResource, lpszResourceId );
  978. if ( pResource == NULL )
  979. {
  980. ClRtlLogPrint(LOG_UNUSUAL,
  981. "[FM] FmpUpdateChangeResourceName: Resource <%1!ws!> could not be found....\n",
  982. lpszResourceId);
  983. return( ERROR_RESOURCE_NOT_FOUND );
  984. }
  985. ClRtlLogPrint(LOG_NOISE,
  986. "[FM] FmpUpdateChangeResourceName: Entry for resource <%1!ws!>, New name = <%2!ws!>...\n",
  987. lpszResourceId,
  988. lpszNewName);
  989. //
  990. // Start a transaction
  991. //
  992. hXsaction = DmBeginLocalUpdate();
  993. if ( !hXsaction )
  994. {
  995. dwStatus = GetLastError();
  996. ClRtlLogPrint(LOG_UNUSUAL,
  997. "[FM] FmpUpdateChangeResourceName: Failed in starting a transaction for resource %1!ws!, Status =%2!d!....\n",
  998. lpszResourceId,
  999. dwStatus);
  1000. goto FnExit;
  1001. }
  1002. //
  1003. // Open the resources key.
  1004. //
  1005. hKey = DmLocalCreateKey( hXsaction,
  1006. DmResourcesKey,
  1007. lpszResourceId,
  1008. 0,
  1009. KEY_READ | KEY_WRITE,
  1010. NULL,
  1011. &dwDisposition );
  1012. if ( hKey == NULL )
  1013. {
  1014. dwStatus = GetLastError();
  1015. ClRtlLogPrint(LOG_UNUSUAL,
  1016. "[FM] FmpUpdateChangeResourceName: Failed in opening the resources key for resource %1!ws!, Status =%2!d!....\n",
  1017. lpszResourceId,
  1018. dwStatus);
  1019. goto FnExit;
  1020. }
  1021. CL_ASSERT( dwDisposition != REG_CREATED_NEW_KEY );
  1022. //
  1023. // Set the resource name in the registry
  1024. //
  1025. dwStatus = DmLocalSetValue( hXsaction,
  1026. hKey,
  1027. CLUSREG_NAME_RES_NAME,
  1028. REG_SZ,
  1029. ( CONST BYTE * ) lpszNewName,
  1030. ( lstrlenW( lpszNewName ) + 1 ) *
  1031. sizeof( WCHAR ) );
  1032. if( dwStatus != ERROR_SUCCESS )
  1033. {
  1034. ClRtlLogPrint(LOG_CRITICAL,
  1035. "[FM] FmpUpdateChangeResourceName: DmLocalSetValue for resource %1!ws! fails, Status = %2!d!...\n",
  1036. lpszResourceId,
  1037. dwStatus);
  1038. goto FnExit;
  1039. }
  1040. pResChangeName = LocalAlloc( LMEM_FIXED,
  1041. lstrlenW( lpszNewName ) * sizeof ( WCHAR ) +
  1042. sizeof( FM_RES_CHANGE_NAME ) );
  1043. if ( pResChangeName == NULL )
  1044. {
  1045. dwStatus = GetLastError();
  1046. ClRtlLogPrint(LOG_UNUSUAL,
  1047. "[FM] FmpUpdateChangeResourceName: Unable to allocate memory for ResChangeName structure for resource <%1!ws!>, Status =%2!d!....\n",
  1048. lpszResourceId,
  1049. dwStatus);
  1050. goto FnExit;
  1051. }
  1052. dwStatus = OmSetObjectName( pResource, lpszNewName );
  1053. if ( dwStatus != ERROR_SUCCESS )
  1054. {
  1055. ClRtlLogPrint(LOG_CRITICAL,
  1056. "[FM] FmpUpdateChangeResourceName: Unable to set name <%3!ws!> for resource <%1!ws!>, Status =%2!d!....\n",
  1057. lpszResourceId,
  1058. dwStatus,
  1059. lpszNewName );
  1060. LocalFree( pResChangeName );
  1061. goto FnExit;
  1062. }
  1063. pResChangeName->pResource = pResource;
  1064. lstrcpyW( pResChangeName->szNewResourceName, lpszNewName );
  1065. //
  1066. // The FM worker thread will free the memory for the pResChangeName
  1067. // structure as well as dereference the pResource object.
  1068. //
  1069. FmpPostWorkItem( FM_EVENT_RESOURCE_NAME_CHANGE, pResChangeName, 0 );
  1070. pResource = NULL;
  1071. ClRtlLogPrint(LOG_NOISE,
  1072. "[FM] FmpUpdateChangeResourceName: Successfully changed name of resource <%1!ws!> to <%2!ws!>...\n",
  1073. lpszResourceId,
  1074. lpszNewName);
  1075. FnExit:
  1076. if ( pResource != NULL )
  1077. {
  1078. OmDereferenceObject( pResource );
  1079. }
  1080. if ( hKey != NULL )
  1081. {
  1082. DmCloseKey( hKey );
  1083. }
  1084. if ( ( dwStatus == ERROR_SUCCESS ) && ( hXsaction ) )
  1085. {
  1086. DmCommitLocalUpdate( hXsaction );
  1087. }
  1088. else
  1089. {
  1090. if ( hXsaction ) DmAbortLocalUpdate( hXsaction );
  1091. }
  1092. ClRtlLogPrint(LOG_NOISE,
  1093. "[FM] FmpUpdateChangeResourceName: Exit for resource %1!ws!, Status=%2!u!...\n",
  1094. lpszResourceId,
  1095. dwStatus);
  1096. return( dwStatus );
  1097. }
  1098. /****
  1099. @func DWORD | FmpUpdatePossibleNodesForResType| This update is called to
  1100. update the possible nodes for a resource type.
  1101. @parm IN BOOL | SourceNode | set to TRUE, if the update originated at this
  1102. node.
  1103. @parm IN LPCWSTR | lpszResTypeName | The name of the resource type.
  1104. @parm IN DWORD | dwBufLength | The size of the multi-sz string pointed
  1105. to by pBuf
  1106. @parm IN PVOID | pBuf | A pointer to the buffer containing the names of
  1107. the nodes that support this resource type.
  1108. @comm The possible list of nodes that supports the given resource type is
  1109. updated with the list provided.
  1110. @rdesc Returns a result code. ERROR_SUCCESS on success.
  1111. @xref <f FmpDecisionPossibleDmSwitchToNewQuorumLog>
  1112. ****/
  1113. DWORD
  1114. FmpUpdatePossibleNodeForResType(
  1115. IN BOOL SourceNode,
  1116. IN LPCWSTR lpszResTypeName,
  1117. IN LPDWORD pdwBufLength,
  1118. IN PVOID pBuf
  1119. )
  1120. {
  1121. PFM_RESTYPE pResType;
  1122. DWORD dwStatus;
  1123. HDMKEY hResTypeKey = NULL;
  1124. HLOCALXSACTION hXsaction = NULL;
  1125. LIST_ENTRY NewPosNodeList;
  1126. PLIST_ENTRY pListEntry;
  1127. PRESTYPE_POSSIBLE_ENTRY pResTypePosEntry = NULL;
  1128. //
  1129. // Chittur Subbaraman (chitturs) - 5/13/99
  1130. //
  1131. // Don't check for FmpFMGroupsInited condition since this GUM
  1132. // handler is called by the forming node before that variable
  1133. // is set to TRUE. This update always comes after the
  1134. // corresponding restypes have been created and is made
  1135. // internally by the clussvc following this order. Note that
  1136. // a joining node cannot receive this update until groups are
  1137. // inited since GUM receive updates are turned on only after
  1138. // the FmpFMGroupsInited variable is set to TRUE. Also, the
  1139. // intracluster RPC is fired up in a forming node only after
  1140. // the groups are inited. Hence, there is no major danger
  1141. // of this GUM handler being called if the corresponding
  1142. // restype is not created.
  1143. //
  1144. if ( FmpShutdown ) {
  1145. return(ERROR_SUCCESS);
  1146. }
  1147. InitializeListHead(&NewPosNodeList);
  1148. pResType = OmReferenceObjectById( ObjectTypeResType,
  1149. lpszResTypeName);
  1150. if (!pResType)
  1151. {
  1152. dwStatus = ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND;
  1153. goto FnExit;
  1154. }
  1155. dwStatus = FmpAddPossibleNodeToList(pBuf, *pdwBufLength, &NewPosNodeList);
  1156. if (dwStatus != ERROR_SUCCESS)
  1157. {
  1158. goto FnExit;
  1159. }
  1160. //writes to the old log file
  1161. hXsaction = DmBeginLocalUpdate();
  1162. if (!hXsaction)
  1163. {
  1164. dwStatus = GetLastError();
  1165. goto FnExit;
  1166. }
  1167. hResTypeKey = DmOpenKey(DmResourceTypesKey,
  1168. lpszResTypeName,
  1169. KEY_READ | KEY_WRITE);
  1170. if (hResTypeKey == NULL)
  1171. {
  1172. dwStatus = GetLastError();
  1173. goto FnExit;
  1174. }
  1175. //if there are no possible owners, delete the value
  1176. if (pBuf && *pdwBufLength)
  1177. {
  1178. dwStatus = DmLocalSetValue( hXsaction,
  1179. hResTypeKey,
  1180. CLUSREG_NAME_RESTYPE_POSSIBLE_NODES,
  1181. REG_MULTI_SZ,
  1182. (LPBYTE)pBuf,
  1183. *pdwBufLength);
  1184. }
  1185. else
  1186. {
  1187. dwStatus = DmLocalDeleteValue( hXsaction,
  1188. hResTypeKey,
  1189. CLUSREG_NAME_RESTYPE_POSSIBLE_NODES);
  1190. if (dwStatus == ERROR_FILE_NOT_FOUND)
  1191. {
  1192. dwStatus = ERROR_SUCCESS;
  1193. }
  1194. }
  1195. FnExit:
  1196. if (dwStatus == ERROR_SUCCESS)
  1197. {
  1198. //commit the update on the old log file,
  1199. //any nodes that were done, will get this change
  1200. //I cant delete this file
  1201. DmCommitLocalUpdate(hXsaction);
  1202. ACQUIRE_EXCLUSIVE_LOCK(gResTypeLock);
  1203. //free the old list
  1204. while (!IsListEmpty(&pResType->PossibleNodeList))
  1205. {
  1206. pListEntry = RemoveHeadList(&pResType->PossibleNodeList);
  1207. pResTypePosEntry = CONTAINING_RECORD(pListEntry, RESTYPE_POSSIBLE_ENTRY,
  1208. PossibleLinkage);
  1209. OmDereferenceObject(pResTypePosEntry->PossibleNode);
  1210. LocalFree(pResTypePosEntry);
  1211. }
  1212. //now switch the possible owners list for the
  1213. //resource type
  1214. while (!IsListEmpty(&(NewPosNodeList)))
  1215. {
  1216. //remove from the new prepared list and hang
  1217. //it of the restype structure
  1218. pListEntry = RemoveHeadList(&NewPosNodeList);
  1219. InsertTailList(&pResType->PossibleNodeList, pListEntry);
  1220. pResTypePosEntry = CONTAINING_RECORD(pListEntry, RESTYPE_POSSIBLE_ENTRY,
  1221. PossibleLinkage);
  1222. ClRtlLogPrint(LOG_NOISE,
  1223. "[FM] FmpUpdatePossibleNodesForRestype:Adding node %1!ws! to %2!ws! resource type's possible node list...\n",
  1224. OmObjectId(pResTypePosEntry->PossibleNode),
  1225. lpszResTypeName);
  1226. }
  1227. RELEASE_LOCK(gResTypeLock);
  1228. ClusterEvent( CLUSTER_EVENT_RESTYPE_PROPERTY_CHANGE,
  1229. pResType );
  1230. }
  1231. else
  1232. {
  1233. //free up the NewPostNodeList
  1234. if (hXsaction) DmAbortLocalUpdate(hXsaction);
  1235. //if a new list was prepared, free it
  1236. while (!IsListEmpty(&(NewPosNodeList)))
  1237. {
  1238. pListEntry = RemoveHeadList(&NewPosNodeList);
  1239. pResTypePosEntry = CONTAINING_RECORD(pListEntry, RESTYPE_POSSIBLE_ENTRY,
  1240. PossibleLinkage);
  1241. OmDereferenceObject(pResTypePosEntry->PossibleNode);
  1242. LocalFree(pResTypePosEntry);
  1243. }
  1244. }
  1245. if (hResTypeKey) DmCloseKey(hResTypeKey);
  1246. if (pResType) OmDereferenceObject(pResType);
  1247. return(dwStatus);
  1248. }
  1249. /****
  1250. @func DWORD | FmpDecidePossibleNodeForResType| When the quorum resource is changed,
  1251. the FM invokes this api on the owner node of the new quorum resource
  1252. to create a new quorum log file.
  1253. @parm IN PVOID | pResource | The new quorum resource.
  1254. @parm IN LPCWSTR | lpszPath | The path for temporary cluster files.
  1255. @parm IN DWORD | dwMaxQuoLogSize | The maximum size limit for the quorum log file.
  1256. @comm When a quorum resource is changed, the fm calls this funtion before it
  1257. updates the quorum resource. If a new log file needs to be created,
  1258. a checkpoint is taken.
  1259. @rdesc Returns a result code. ERROR_SUCCESS on success.
  1260. @xref <f DmSwitchToNewQuorumLog>
  1261. ****/
  1262. DWORD FmpDecidePossibleNodeForResType
  1263. (
  1264. IN PGUM_VOTE_DECISION_CONTEXT pDecisionContext,
  1265. IN DWORD dwVoteBufLength,
  1266. IN PVOID pVoteBuf,
  1267. IN DWORD dwNumVotes,
  1268. IN BOOL bDidAllActiveNodesVote,
  1269. OUT LPDWORD pdwOutputBufSize,
  1270. OUT PVOID *ppOutputBuf
  1271. )
  1272. {
  1273. DWORD dwStatus = ERROR_SUCCESS;
  1274. DWORD i;
  1275. PFMP_VOTE_POSSIBLE_NODE_FOR_RESTYPE pFmpVote;
  1276. LPWSTR lpmszPossibleNodes = NULL;
  1277. DWORD dwlpmszLen = 0;
  1278. PVOID pGumBuffer = NULL;
  1279. DWORD dwNodeId;
  1280. WCHAR szNodeId[NODE_ID_SZ];
  1281. LPWSTR lpmszCurrentPossibleNodes=NULL;
  1282. BOOL bChange = FALSE;
  1283. HDMKEY hResTypeKey = NULL;
  1284. DWORD dwSize;
  1285. DWORD dwStringBufSize = 0;
  1286. BOOL bAssumeSupported;
  1287. LPWSTR TypeName = NULL;
  1288. //First get the type name from pDecisionContext
  1289. TypeName=(LPWSTR)LocalAlloc(LMEM_FIXED,pDecisionContext->dwInputBufLength);
  1290. if(TypeName==NULL)
  1291. {
  1292. ClRtlLogPrint(LOG_CRITICAL,"[FM] FmpDecidePossibleNodeForResType: Not Enough Memory, error= %1!d!\r\n",
  1293. GetLastError());
  1294. goto FnExit;
  1295. }
  1296. CopyMemory(TypeName,pDecisionContext->pInputBuf,pDecisionContext->dwInputBufLength);
  1297. //initialize the out params
  1298. *ppOutputBuf = NULL;
  1299. *pdwOutputBufSize = 0;
  1300. bAssumeSupported= *((BOOL*)pDecisionContext->pContext);
  1301. if (bAssumeSupported)
  1302. {
  1303. hResTypeKey = DmOpenKey(DmResourceTypesKey,
  1304. TypeName,
  1305. KEY_READ | KEY_WRITE);
  1306. if (hResTypeKey == NULL)
  1307. {
  1308. dwStatus = GetLastError();
  1309. CL_LOGFAILURE(dwStatus);
  1310. goto FnExit;
  1311. }
  1312. //pass the current possible node list to the decider
  1313. dwStatus = DmQueryString(hResTypeKey,
  1314. CLUSREG_NAME_RESTYPE_POSSIBLE_NODES,
  1315. REG_MULTI_SZ,
  1316. &lpmszCurrentPossibleNodes,
  1317. &dwStringBufSize,
  1318. &dwSize);
  1319. if (dwStatus != ERROR_SUCCESS)
  1320. {
  1321. //if the possible node list is not found this is ok
  1322. //ie. only if there is some other error we give up
  1323. if ( dwStatus != ERROR_FILE_NOT_FOUND )
  1324. {
  1325. CL_LOGFAILURE(dwStatus);
  1326. goto FnExit;
  1327. }
  1328. }
  1329. DmCloseKey(hResTypeKey);
  1330. hResTypeKey = NULL;
  1331. }
  1332. //if the current list is passed in, dont remove any possible
  1333. //nodes from the list if they dont vote, simply add the new ones
  1334. if (lpmszCurrentPossibleNodes)
  1335. {
  1336. DWORD dwStrLen;
  1337. //make a copy of the multi-sz
  1338. dwlpmszLen = ClRtlMultiSzLength(lpmszCurrentPossibleNodes);
  1339. dwStrLen = dwlpmszLen * sizeof(WCHAR);
  1340. lpmszPossibleNodes = LocalAlloc(LMEM_FIXED, dwStrLen);
  1341. if (!lpmszPossibleNodes)
  1342. {
  1343. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  1344. CL_LOGFAILURE(dwStatus);
  1345. goto FnExit;
  1346. }
  1347. CopyMemory(lpmszPossibleNodes, lpmszCurrentPossibleNodes, dwStrLen);
  1348. }
  1349. for (i = 0; i< dwNumVotes; i++)
  1350. {
  1351. pFmpVote = (PFMP_VOTE_POSSIBLE_NODE_FOR_RESTYPE)
  1352. GETVOTEFROMBUF(pVoteBuf, pDecisionContext->dwVoteLength, i+1 , &dwNodeId);
  1353. //if not a valid vote, skip
  1354. if (!pFmpVote)
  1355. continue;
  1356. CL_ASSERT((PBYTE)pFmpVote <= ((PBYTE)pVoteBuf + dwVoteBufLength -
  1357. sizeof(FMP_VOTE_POSSIBLE_NODE_FOR_RESTYPE)));
  1358. szNodeId[ NODE_ID_SZ-1 ] = UNICODE_NULL;
  1359. _snwprintf( szNodeId, NODE_ID_SZ-1, L"%d" , dwNodeId );
  1360. if (pFmpVote->bPossibleNode)
  1361. {
  1362. if (lpmszCurrentPossibleNodes)
  1363. {
  1364. //if the string is already there, dont append it again
  1365. if (ClRtlMultiSzScan(lpmszCurrentPossibleNodes, szNodeId))
  1366. continue;
  1367. }
  1368. dwStatus = ClRtlMultiSzAppend(&lpmszPossibleNodes,
  1369. &dwlpmszLen, szNodeId);
  1370. bChange = TRUE;
  1371. if (dwStatus != ERROR_SUCCESS)
  1372. goto FnExit;
  1373. }
  1374. else
  1375. {
  1376. //if a current list was specified
  1377. //this node is not a possible node anymore, remove it from the list
  1378. if (lpmszCurrentPossibleNodes)
  1379. {
  1380. ClRtlLogPrint(LOG_NOISE,
  1381. "[FM] FmpDecidePossibleNodesForRestype: Removing node %1!ws! from %2!ws! restype possibleowner list \r\n",
  1382. szNodeId,TypeName);
  1383. dwStatus = ClRtlMultiSzRemove(lpmszPossibleNodes, &dwlpmszLen, szNodeId);
  1384. if (dwStatus == ERROR_SUCCESS)
  1385. {
  1386. //if the node is successfully removed
  1387. bChange = TRUE;
  1388. }
  1389. else if (dwStatus != ERROR_FILE_NOT_FOUND)
  1390. {
  1391. //if the node exists but cannot be removed return with error
  1392. //if the node didnt exist, we dont do anything bChange remains
  1393. //set at FALSE
  1394. goto FnExit;
  1395. }
  1396. else
  1397. {
  1398. dwStatus = ERROR_SUCCESS;
  1399. }
  1400. }
  1401. }
  1402. }
  1403. //if nothing has changed dont issue a gum update
  1404. if (!bChange)
  1405. {
  1406. dwStatus = ERROR_ALREADY_EXISTS;
  1407. goto FnExit;
  1408. }
  1409. //dwlpmszLen contains the size of the multi-sz string in the
  1410. //number of characters, make it the number of bytes
  1411. dwlpmszLen *= sizeof(WCHAR);
  1412. pGumBuffer = GumMarshallArgs(pdwOutputBufSize, 3,
  1413. pDecisionContext->dwInputBufLength, pDecisionContext->pInputBuf,
  1414. sizeof(DWORD), &dwlpmszLen, dwlpmszLen, lpmszPossibleNodes);
  1415. *ppOutputBuf = pGumBuffer;
  1416. FnExit:
  1417. if (lpmszPossibleNodes) LocalFree(lpmszPossibleNodes);
  1418. if (hResTypeKey)
  1419. DmCloseKey(hResTypeKey);
  1420. if (lpmszCurrentPossibleNodes)
  1421. LocalFree(lpmszCurrentPossibleNodes);
  1422. if(TypeName)
  1423. LocalFree(TypeName);
  1424. return(dwStatus);
  1425. }
  1426. /****
  1427. @func DWORD | FmpUpdateChangeResourceNode| This update is called to
  1428. update the possible nodes for a resource.
  1429. @parm IN BOOL | SourceNode | set to TRUE, if the update originated at this
  1430. node.
  1431. @parm IN PFM_RESOURCE | pResource | A pointer to the resource whose
  1432. possible node list is being updated.
  1433. @parm IN PNM_NODE | pNode | A pointer to the node to be added/removed
  1434. from the possible node lis.
  1435. @parm IN DWORD | dwControlCode | If CLUSCTL_RESOURCE_ADD_OWNER then
  1436. the node is added to the possible node list, else it is removed.
  1437. @comm The possible list of nodes for a resource is updated.
  1438. @rdesc Returns a result code. ERROR_SUCCESS on success.
  1439. ****/
  1440. DWORD
  1441. FmpUpdateChangeResourceNode(
  1442. IN BOOL SourceNode,
  1443. IN PFM_RESOURCE pResource,
  1444. IN PNM_NODE pNode,
  1445. IN DWORD dwControlCode
  1446. )
  1447. {
  1448. DWORD dwStatus;
  1449. HDMKEY hResKey = NULL;
  1450. HLOCALXSACTION hXsaction = NULL;
  1451. //Dont acquire the local resource lock since acquiring that
  1452. //within gum updates causes deadlock
  1453. //use the global resource lock to synchronize this call
  1454. //with the enumeration of possible nodes
  1455. FmpAcquireResourceLock();
  1456. //start a transaction
  1457. hXsaction = DmBeginLocalUpdate();
  1458. if (!hXsaction)
  1459. {
  1460. dwStatus = GetLastError();
  1461. goto FnExit;
  1462. }
  1463. //
  1464. // BUGBUG: What if in-memory stuff succeeds and registry stuff fails ? We get into
  1465. // inconsistent state. Better to move this code to the end after succeeding in
  1466. // registry changes.
  1467. //
  1468. if (dwControlCode == CLUSCTL_RESOURCE_ADD_OWNER)
  1469. {
  1470. dwStatus = FmpAddPossibleNode(pResource,
  1471. pNode);
  1472. } else
  1473. {
  1474. dwStatus = FmpRemovePossibleNode(pResource,
  1475. pNode,
  1476. FALSE);
  1477. }
  1478. if (dwStatus != ERROR_SUCCESS)
  1479. {
  1480. ClRtlLogPrint( LOG_NOISE,
  1481. "[FM] FmpUpdateChangeResourceNode, failed possible node updatefor resource <%1!ws!>, error %2!u!\n",
  1482. OmObjectName(pResource),
  1483. dwStatus );
  1484. goto FnExit;
  1485. }
  1486. //fix the registry
  1487. //SS - do we need to fix the preferred node list
  1488. hResKey = DmOpenKey(DmResourcesKey,
  1489. OmObjectId(pResource),
  1490. KEY_READ | KEY_WRITE);
  1491. if (hResKey == NULL)
  1492. {
  1493. dwStatus = GetLastError();
  1494. goto FnExit;
  1495. }
  1496. if (dwControlCode == CLUSCTL_RESOURCE_ADD_OWNER)
  1497. {
  1498. dwStatus = DmLocalAppendToMultiSz(
  1499. hXsaction,
  1500. hResKey,
  1501. CLUSREG_NAME_RES_POSSIBLE_OWNERS,
  1502. OmObjectId(pNode));
  1503. }
  1504. else
  1505. {
  1506. dwStatus = DmLocalRemoveFromMultiSz(
  1507. hXsaction,
  1508. hResKey,
  1509. CLUSREG_NAME_RES_POSSIBLE_OWNERS,
  1510. OmObjectId(pNode));
  1511. if (dwStatus == ERROR_FILE_NOT_FOUND)
  1512. {
  1513. DWORD i;
  1514. DWORD Result;
  1515. PNM_NODE pEnumNode;
  1516. //
  1517. // Possible nodes did not exist, so create a new entry
  1518. // with every possible node in it. FM will already have
  1519. // removed the passed in node from the possible node list.
  1520. //
  1521. i=0;
  1522. do {
  1523. Result = FmEnumResourceNode(pResource,
  1524. i,
  1525. &pEnumNode);
  1526. if (Result == ERROR_SUCCESS)
  1527. {
  1528. dwStatus = DmLocalAppendToMultiSz(
  1529. hXsaction,
  1530. hResKey,
  1531. CLUSREG_NAME_RES_POSSIBLE_OWNERS,
  1532. OmObjectId(pEnumNode));
  1533. OmDereferenceObject(pEnumNode);
  1534. }
  1535. else if ((Result == ERROR_NO_MORE_ITEMS) &&
  1536. (i == 0))
  1537. {
  1538. //
  1539. // This is a funny corner case where there is a one
  1540. // node cluster and a resource with no possibleowners
  1541. // entry, and somebody removes the only node in the cluster
  1542. // from the possible owners list. Set PossibleOwners to
  1543. // the empty set.
  1544. //
  1545. dwStatus = DmLocalSetValue(
  1546. hXsaction,
  1547. hResKey,
  1548. CLUSREG_NAME_RES_POSSIBLE_OWNERS,
  1549. REG_MULTI_SZ,
  1550. (CONST BYTE *)L"\0",
  1551. 2);
  1552. }
  1553. ++i;
  1554. } while ( Result == ERROR_SUCCESS );
  1555. //map the error to success
  1556. dwStatus = ERROR_SUCCESS;
  1557. }
  1558. }
  1559. DmCloseKey(hResKey);
  1560. FnExit:
  1561. //release the lock
  1562. FmpReleaseResourceLock();
  1563. if (dwStatus == ERROR_SUCCESS)
  1564. {
  1565. //commit the update on the old log file,
  1566. //any nodes that were done, will get this change
  1567. //I cant delete this file
  1568. DmCommitLocalUpdate(hXsaction);
  1569. }
  1570. else
  1571. {
  1572. //SS: BUGBUG :: validation for possible node should
  1573. //be done before the registry is switched
  1574. //the inmemory structure should be changed only on success
  1575. //if there is a failure in the registry apis..the
  1576. //in memory structure will be out of sync with registry
  1577. if (hXsaction) DmAbortLocalUpdate(hXsaction);
  1578. }
  1579. return(dwStatus);
  1580. }
  1581. /****
  1582. @func DWORD | FmpUpdateChangeResourceGroup| This update is called to
  1583. update the group to which the resource belongs.
  1584. @parm IN BOOL | bSourceNode | set to TRUE, if the update originated at this
  1585. node.
  1586. @parm IN PFM_RESOURCE | pResource | A pointer to the resource whose
  1587. possible node list is being updated.
  1588. @parm IN PFM_GROUP | pNewGroup | A pointer to the node to be added/removed
  1589. from the possible node lis.
  1590. @comm The possible list of nodes for a resource is updated.
  1591. @rdesc Returns a result code. ERROR_SUCCESS on success.
  1592. ****/
  1593. DWORD FmpUpdateChangeResourceGroup(
  1594. IN BOOL bSourceNode,
  1595. IN PFM_RESOURCE pResource,
  1596. IN PFM_GROUP pNewGroup)
  1597. {
  1598. DWORD dwStatus = ERROR_SUCCESS;
  1599. PFM_GROUP pOldGroup;
  1600. PFM_DEPENDENCY_TREE pTree = NULL;
  1601. HLOCALXSACTION hXsaction = NULL;
  1602. HDMKEY hOldGroupKey = NULL;
  1603. HDMKEY hNewGroupKey = NULL;
  1604. PLIST_ENTRY pListEntry;
  1605. PFM_DEPENDTREE_ENTRY pEntry;
  1606. pOldGroup = pResource->Group;
  1607. //
  1608. // Check to make sure the resource is not already in the group.
  1609. //
  1610. if (pOldGroup == pNewGroup)
  1611. {
  1612. dwStatus = ERROR_ALREADY_EXISTS;
  1613. goto FnExit;
  1614. }
  1615. //
  1616. // Synchronize both the old and the new groups.
  1617. // Lock the lowest by lowest Group Id first - to prevent deadlocks!
  1618. // Note - the order of release is unimportant.
  1619. //
  1620. // strictly, the comparison below cannot be equal!
  1621. //
  1622. if ( lstrcmpiW( OmObjectId( pOldGroup ), OmObjectId( pNewGroup ) ) <= 0 )
  1623. {
  1624. FmpAcquireLocalGroupLock( pOldGroup );
  1625. FmpAcquireLocalGroupLock( pNewGroup );
  1626. }
  1627. else
  1628. {
  1629. FmpAcquireLocalGroupLock( pNewGroup );
  1630. FmpAcquireLocalGroupLock( pOldGroup );
  1631. }
  1632. //start a transaction
  1633. hXsaction = DmBeginLocalUpdate();
  1634. if (!hXsaction)
  1635. {
  1636. dwStatus = GetLastError();
  1637. goto FnUnlock;
  1638. }
  1639. //
  1640. // For now... both Groups must be owned by the same node.
  1641. //
  1642. if ( pResource->Group->OwnerNode != pNewGroup->OwnerNode )
  1643. {
  1644. dwStatus = ERROR_HOST_NODE_NOT_GROUP_OWNER;
  1645. goto FnUnlock;
  1646. }
  1647. //
  1648. // Create a full dependency tree,
  1649. //
  1650. pTree = FmCreateFullDependencyTree(pResource);
  1651. if ( pTree == NULL )
  1652. {
  1653. dwStatus = GetLastError();
  1654. goto FnUnlock;
  1655. }
  1656. //
  1657. // Add each resource in the dependency tree to its new group's list.
  1658. //
  1659. hNewGroupKey = DmOpenKey(DmGroupsKey,
  1660. OmObjectId(pNewGroup),
  1661. KEY_READ | KEY_WRITE);
  1662. if (hNewGroupKey == NULL) {
  1663. dwStatus = GetLastError();
  1664. goto FnUnlock;
  1665. }
  1666. hOldGroupKey = DmOpenKey(DmGroupsKey,
  1667. OmObjectId(pOldGroup),
  1668. KEY_READ | KEY_WRITE);
  1669. if (hOldGroupKey == NULL) {
  1670. dwStatus = GetLastError();
  1671. goto FnUnlock;
  1672. }
  1673. //
  1674. // For each resource in the dependency tree, remove it from the
  1675. // old group list and add it to the new group list
  1676. //
  1677. pListEntry = pTree->ListHead.Flink;
  1678. while (pListEntry != &pTree->ListHead) {
  1679. pEntry = CONTAINING_RECORD(pListEntry,
  1680. FM_DEPENDTREE_ENTRY,
  1681. ListEntry);
  1682. pListEntry = pListEntry->Flink;
  1683. dwStatus = DmLocalRemoveFromMultiSz(hXsaction,
  1684. hOldGroupKey,
  1685. CLUSREG_NAME_GRP_CONTAINS,
  1686. OmObjectId(pEntry->Resource));
  1687. if (dwStatus != ERROR_SUCCESS) {
  1688. goto FnUnlock;
  1689. }
  1690. dwStatus = DmLocalAppendToMultiSz(hXsaction,
  1691. hNewGroupKey,
  1692. CLUSREG_NAME_GRP_CONTAINS,
  1693. OmObjectId(pEntry->Resource));
  1694. if (dwStatus != ERROR_SUCCESS) {
  1695. goto FnUnlock;
  1696. }
  1697. }
  1698. //
  1699. // Passed all the checks, do the in-memorymove.
  1700. //
  1701. pListEntry = pTree->ListHead.Flink;
  1702. while (pListEntry != &pTree->ListHead)
  1703. {
  1704. pEntry = CONTAINING_RECORD(pListEntry,
  1705. FM_DEPENDTREE_ENTRY,
  1706. ListEntry);
  1707. pListEntry = pListEntry->Flink;
  1708. //
  1709. // Move this resource
  1710. //
  1711. RemoveEntryList(&pEntry->Resource->ContainsLinkage);
  1712. InsertHeadList(&pNewGroup->Contains,
  1713. &pEntry->Resource->ContainsLinkage);
  1714. OmReferenceObject(pNewGroup);
  1715. pEntry->Resource->Group = pNewGroup;
  1716. ++pEntry->Resource->StateSequence;
  1717. ClusterEvent(CLUSTER_EVENT_RESOURCE_CHANGE,pEntry->Resource);
  1718. OmDereferenceObject(pOldGroup);
  1719. }
  1720. FnUnlock:
  1721. //
  1722. // Now release all locks.
  1723. //
  1724. FmpReleaseLocalGroupLock( pNewGroup );
  1725. FmpReleaseLocalGroupLock( pOldGroup );
  1726. FnExit:
  1727. if (pTree) FmDestroyFullDependencyTree(pTree);
  1728. if (hOldGroupKey) DmCloseKey(hOldGroupKey);
  1729. if (hNewGroupKey) DmCloseKey(hNewGroupKey);
  1730. if (dwStatus == ERROR_SUCCESS)
  1731. {
  1732. ClusterEvent(CLUSTER_EVENT_GROUP_PROPERTY_CHANGE,pNewGroup);
  1733. ClusterEvent(CLUSTER_EVENT_GROUP_PROPERTY_CHANGE,pOldGroup);
  1734. DmCommitLocalUpdate(hXsaction);
  1735. }
  1736. else
  1737. {
  1738. if (hXsaction) DmAbortLocalUpdate(hXsaction);
  1739. }
  1740. return(dwStatus);
  1741. }
  1742. DWORD
  1743. FmpUpdateAddDependency(
  1744. IN BOOL SourceNode,
  1745. IN LPCWSTR ResourceId,
  1746. IN LPCWSTR DependsOnId
  1747. )
  1748. /*++
  1749. Routine Description:
  1750. GUM dispatch routine for adding a dependency
  1751. Arguments:
  1752. SourceNode - Supplies whether or not this node initiated the GUM update.
  1753. Not used.
  1754. ResourceId - Supplies the resource ID of the resource that should have a
  1755. dependency added.
  1756. DependsOnId - Supplies the resource ID of the resource that should provide
  1757. for ResourceId.
  1758. Return Value:
  1759. ERROR_SUCCESS if successful.
  1760. Win32 error code otherwise.
  1761. --*/
  1762. {
  1763. PFM_RESOURCE Resource;
  1764. PFM_RESOURCE DependsOn;
  1765. PDEPENDENCY dependency;
  1766. //
  1767. // Chittur Subbaraman (chitturs) - 4/18/99
  1768. //
  1769. // If FM groups are not fully initialized or FM is shutting down, then
  1770. // don't do anything.
  1771. //
  1772. if ( !FmpFMGroupsInited ||
  1773. FmpShutdown ) {
  1774. return(ERROR_SUCCESS);
  1775. }
  1776. dependency = LocalAlloc(LMEM_FIXED, sizeof(DEPENDENCY));
  1777. if (dependency == NULL) {
  1778. CsInconsistencyHalt( ERROR_NOT_ENOUGH_MEMORY );
  1779. return(ERROR_NOT_ENOUGH_MEMORY);
  1780. }
  1781. Resource = OmReferenceObjectById(ObjectTypeResource,
  1782. ResourceId);
  1783. if (Resource == NULL) {
  1784. CL_LOGFAILURE( ERROR_RESOURCE_NOT_FOUND );
  1785. LocalFree(dependency);
  1786. return(ERROR_RESOURCE_NOT_FOUND);
  1787. }
  1788. DependsOn = OmReferenceObjectById(ObjectTypeResource,
  1789. DependsOnId);
  1790. if (DependsOn == NULL) {
  1791. OmDereferenceObject(Resource);
  1792. LocalFree(dependency);
  1793. CL_LOGFAILURE( ERROR_DEPENDENCY_NOT_FOUND );
  1794. return(ERROR_DEPENDENCY_NOT_FOUND);
  1795. }
  1796. dependency->DependentResource = Resource;
  1797. dependency->ProviderResource = DependsOn;
  1798. FmpAcquireResourceLock();
  1799. InsertTailList( &DependsOn->ProvidesFor,
  1800. &dependency->ProviderLinkage );
  1801. InsertTailList( &Resource->DependsOn,
  1802. &dependency->DependentLinkage );
  1803. FmpReleaseResourceLock();
  1804. ClusterEvent( CLUSTER_EVENT_RESOURCE_PROPERTY_CHANGE,
  1805. Resource );
  1806. //SS: we leave the reference counts on both the objects
  1807. //as a dependency referrring to them has been created.
  1808. return(ERROR_SUCCESS);
  1809. } // FmpUpdateAddDependency
  1810. DWORD
  1811. FmpUpdateRemoveDependency(
  1812. IN BOOL SourceNode,
  1813. IN LPCWSTR ResourceId,
  1814. IN LPCWSTR DependsOnId
  1815. )
  1816. /*++
  1817. Routine Description:
  1818. GUM dispatch routine for adding a dependency
  1819. Arguments:
  1820. SourceNode - Supplies whether or not this node initiated the GUM update.
  1821. Not used.
  1822. ResourceId - Supplies the resource ID of the resource that should have a
  1823. dependency removed.
  1824. DependsOnId - Supplies the resource ID of the resource that provides
  1825. for ResourceId.
  1826. Return Value:
  1827. ERROR_SUCCESS if successful.
  1828. Win32 error code otherwise.
  1829. --*/
  1830. {
  1831. PFM_RESOURCE Resource;
  1832. PFM_RESOURCE DependsOn;
  1833. PDEPENDENCY dependency;
  1834. PLIST_ENTRY ListEntry;
  1835. DWORD Status=ERROR_SUCCESS;
  1836. //
  1837. // Chittur Subbaraman (chitturs) - 4/18/99
  1838. //
  1839. // If FM groups are not fully initialized or FM is shutting down, then
  1840. // don't do anything.
  1841. //
  1842. if ( !FmpFMGroupsInited ||
  1843. FmpShutdown ) {
  1844. return(ERROR_SUCCESS);
  1845. }
  1846. Resource = OmReferenceObjectById(ObjectTypeResource,
  1847. ResourceId);
  1848. if (Resource == NULL) {
  1849. CL_LOGFAILURE( ERROR_RESOURCE_NOT_FOUND );
  1850. return(ERROR_RESOURCE_NOT_FOUND);
  1851. }
  1852. DependsOn = OmReferenceObjectById(ObjectTypeResource,
  1853. DependsOnId);
  1854. if (DependsOn == NULL) {
  1855. OmDereferenceObject(Resource);
  1856. CL_LOGFAILURE( ERROR_RESOURCE_NOT_FOUND );
  1857. return(ERROR_RESOURCE_NOT_FOUND);
  1858. }
  1859. //
  1860. // Walk through the dependency list of the resource searching
  1861. // for a match.
  1862. //
  1863. FmpAcquireResourceLock();
  1864. ListEntry = Resource->DependsOn.Flink;
  1865. while (ListEntry != &Resource->DependsOn) {
  1866. dependency = CONTAINING_RECORD(ListEntry,
  1867. DEPENDENCY,
  1868. DependentLinkage);
  1869. CL_ASSERT(dependency->DependentResource == Resource);
  1870. if (dependency->ProviderResource == DependsOn) {
  1871. //
  1872. // Found a match. Remove it from its list and
  1873. // free it up.
  1874. //
  1875. RemoveEntryList(&dependency->ProviderLinkage);
  1876. RemoveEntryList(&dependency->DependentLinkage);
  1877. // dereference the providor and dependent resource
  1878. OmDereferenceObject(dependency->DependentResource);
  1879. OmDereferenceObject(dependency->ProviderResource);
  1880. LocalFree(dependency);
  1881. break;
  1882. }
  1883. ListEntry = ListEntry->Flink;
  1884. }
  1885. FmpReleaseResourceLock();
  1886. if (ListEntry != &Resource->DependsOn) {
  1887. //
  1888. // A match was found. Dereference the provider resource
  1889. // to account for the dependency removal and return success.
  1890. //
  1891. ClusterEvent( CLUSTER_EVENT_RESOURCE_PROPERTY_CHANGE,
  1892. Resource );
  1893. Status = ERROR_SUCCESS;
  1894. } else {
  1895. Status = ERROR_DEPENDENCY_NOT_FOUND;
  1896. }
  1897. //SS: dereference the objects earlier referenced
  1898. OmDereferenceObject(Resource);
  1899. OmDereferenceObject(DependsOn);
  1900. return(Status);
  1901. } // FmpUpdateRemoveDependency
  1902. DWORD
  1903. FmpUpdateDeleteGroup(
  1904. IN BOOL SourceNode,
  1905. IN LPCWSTR GroupId
  1906. )
  1907. /*++
  1908. Routine Description:
  1909. GUM dispatch routine for deleting a group.
  1910. Arguments:
  1911. SourceNode - Supplies whether or not this node initiated the GUM update.
  1912. Not used.
  1913. GroupId - Supplies the group ID.
  1914. Return Value:
  1915. ERROR_SUCCESS if successful.
  1916. Win32 error code otherwise.
  1917. --*/
  1918. {
  1919. DWORD dwStatus = ERROR_SUCCESS;
  1920. PFM_GROUP pGroup = NULL;
  1921. PLIST_ENTRY listEntry;
  1922. PPREFERRED_ENTRY preferredEntry;
  1923. BOOL bLocked = FALSE;
  1924. //
  1925. // Chittur Subbaraman (chitturs) - 4/18/99
  1926. //
  1927. // If FM groups are not fully initialized or FM is shutting down, then
  1928. // don't do anything.
  1929. //
  1930. if ( !FmpFMGroupsInited ||
  1931. FmpShutdown ) {
  1932. return(ERROR_SUCCESS);
  1933. }
  1934. //
  1935. // Find the specified Group.
  1936. //
  1937. pGroup = OmReferenceObjectById( ObjectTypeGroup,
  1938. GroupId );
  1939. if ( pGroup == NULL ) {
  1940. dwStatus = ERROR_GROUP_NOT_FOUND;
  1941. return(dwStatus);
  1942. }
  1943. ClRtlLogPrint(LOG_NOISE,
  1944. "[FM] DeleteGroup %1!ws!, address = %2!lx!.\n",
  1945. OmObjectId(pGroup),
  1946. pGroup );
  1947. //
  1948. // Chittur Subbaraman (chitturs) - 1/12/99
  1949. //
  1950. // Try to acquire lock, and make sure the Contains list is empty.
  1951. //
  1952. // Most of the calls to manipulate groups make calls to the owner
  1953. // node of the group and this operation is serialized by GUM. So,
  1954. // there is no major danger if we do the operations in this function
  1955. // without holding the group lock. However, we can't rule out
  1956. // corruption 100% as of now.
  1957. //
  1958. // If you block within the GUM handler here, then no events in
  1959. // the cluster proceed forward and things come to a grinding halt.
  1960. //
  1961. // A case in point:
  1962. // (1) Thread 1 (the thread that calls this function) grabs the
  1963. // GUM lock and waits for the group lock.
  1964. // (2) Thread 2 (FmWorkerThread) grabs the group lock and calls
  1965. // resmon attempting to close a resource. It gets blocked on
  1966. // the resmon eventlist lock.
  1967. // (3) Thread 3 calls RmResourceControl to set the resource name
  1968. // which grabs the resmon eventlist lock and then in turn calls
  1969. // ClusterRegSetValue and then gets blocked on the GUM lock.
  1970. //
  1971. FmpTryAcquireLocalGroupLock( pGroup, bLocked );
  1972. if ( !IsListEmpty( &pGroup->Contains ) )
  1973. {
  1974. dwStatus = ERROR_DIR_NOT_EMPTY;
  1975. goto FnExit;
  1976. }
  1977. //
  1978. // Close the Group's registry key.
  1979. //
  1980. DmRundownList( &pGroup->DmRundownList );
  1981. if ( pGroup->RegistryKey != NULL ) {
  1982. DmCloseKey( pGroup->RegistryKey );
  1983. pGroup->RegistryKey = NULL;
  1984. }
  1985. //
  1986. // Remove from the node list
  1987. //
  1988. dwStatus = OmRemoveObject( pGroup );
  1989. ClusterEvent( CLUSTER_EVENT_GROUP_DELETED, pGroup );
  1990. //
  1991. // This dereference would normally cause the group to eventually disappear,
  1992. // however the event notification above will keep a ref on the object
  1993. // until all notifications have been delivered.
  1994. //
  1995. OmDereferenceObject( pGroup );
  1996. //
  1997. // Make sure the preferred owners list is drained.
  1998. //
  1999. while ( !IsListEmpty( &pGroup->PreferredOwners ) ) {
  2000. listEntry = RemoveHeadList(&pGroup->PreferredOwners);
  2001. preferredEntry = CONTAINING_RECORD( listEntry,
  2002. PREFERRED_ENTRY,
  2003. PreferredLinkage );
  2004. OmDereferenceObject( preferredEntry->PreferredNode );
  2005. LocalFree( preferredEntry );
  2006. }
  2007. //
  2008. // Free the string associated with the AntiAffinityClassName field.
  2009. //
  2010. LocalFree ( pGroup->lpszAntiAffinityClassName );
  2011. pGroup->dwStructState |= FM_GROUP_STRUCT_MARKED_FOR_DELETE;
  2012. FnExit:
  2013. if( bLocked )
  2014. {
  2015. FmpReleaseLocalGroupLock( pGroup );
  2016. }
  2017. //
  2018. // Dereference for reference above.
  2019. //
  2020. if (pGroup) OmDereferenceObject( pGroup );
  2021. return(dwStatus);
  2022. } // FmpUpdateDeleteGroup
  2023. /****
  2024. @func DWORD | FmpUpdateGroupIntendedOwner| This update is called on
  2025. a move just before the source node requests the target node
  2026. to take over the group.
  2027. @parm IN BOOL | bSourceNode | set to TRUE, if the update originated at
  2028. this
  2029. node.
  2030. @parm IN PFM_GROUP | pszGroupId | The ID of the group that is about
  2031. to move.
  2032. @parm IN PDWORD | pdwNodeId| A pointer to a DWORD that contains the
  2033. ID of the node that is the destination of this move. It is
  2034. set to ClusterInvalidNodeId by the destination node when it has
  2035. accepted the group.
  2036. @comm The purpose of this update is to let all nodes know that a move
  2037. is impending. If the source node dies while a move is in progress
  2038. then preference is given to the target of the move rather than the
  2039. node that is chosen by the FmpUpdateAssignOwnerToGroups
  2040. @rdesc Returns a result code. ERROR_SUCCESS on success.
  2041. ****/
  2042. DWORD
  2043. FmpUpdateGroupIntendedOwner(
  2044. IN BOOL SourceNode,
  2045. IN LPCWSTR pszGroupId,
  2046. IN PDWORD pdwNodeId
  2047. )
  2048. {
  2049. PFM_GROUP pGroup = NULL;
  2050. DWORD dwStatus = ERROR_SUCCESS;
  2051. PNM_NODE pNode = NULL;
  2052. PNM_NODE pPrevNode;
  2053. WCHAR pszNodeId[ NODE_ID_SZ ];
  2054. if ( !FmpFMGroupsInited )
  2055. {
  2056. return(ERROR_SUCCESS);
  2057. }
  2058. pGroup = OmReferenceObjectById( ObjectTypeGroup,
  2059. pszGroupId );
  2060. if (pGroup == NULL)
  2061. {
  2062. dwStatus = ERROR_GROUP_NOT_FOUND;
  2063. goto FnExit;
  2064. }
  2065. if (*pdwNodeId != ClusterInvalidNodeId)
  2066. {
  2067. pszNodeId [ NODE_ID_SZ - 1 ] = UNICODE_NULL;
  2068. _snwprintf(pszNodeId, NODE_ID_SZ-1, L"%u", *pdwNodeId);
  2069. pNode = OmReferenceObjectById(ObjectTypeNode,
  2070. pszNodeId);
  2071. if (pNode == NULL)
  2072. {
  2073. dwStatus = ERROR_CLUSTER_NODE_NOT_FOUND;
  2074. goto FnExit;
  2075. }
  2076. } else if (pGroup->pIntendedOwner == NULL)
  2077. {
  2078. dwStatus = ERROR_CLUSTER_INVALID_NODE;
  2079. ClRtlLogPrint(LOG_NOISE,
  2080. "[FM] FmpUpdateGroupIntendedOwner: Group <%1!ws!> intended owner is already invalid, not setting....\n",
  2081. pszGroupId);
  2082. goto FnExit;
  2083. }
  2084. //
  2085. // HACKHACK: Chittur Subbaraman (chitturs) - 5/20/99
  2086. // Comment out as a temporary solution to avoid deadlocks.
  2087. //
  2088. // FmpAcquireLocalGroupLock(pGroup);
  2089. pPrevNode = pGroup->pIntendedOwner;
  2090. //set the new owner node, incr ref count
  2091. if (pNode) OmReferenceObject(pNode);
  2092. pGroup->pIntendedOwner = pNode;
  2093. //decr ref count on previous owner
  2094. if (pPrevNode) OmDereferenceObject(pPrevNode);
  2095. //
  2096. // HACKHACK: Chittur Subbaraman (chitturs) - 5/20/99
  2097. // Comment out as a temporary solution to avoid deadlocks.
  2098. //
  2099. // FmpReleaseLocalGroupLock(pGroup);
  2100. FnExit:
  2101. if (pGroup) OmDereferenceObject(pGroup);
  2102. if (pNode) OmDereferenceObject(pNode);
  2103. return(dwStatus);
  2104. }
  2105. /****
  2106. @func DWORD | FmpUpdateAssignOwnerToGroups| This update is made when
  2107. a node goes down to take ownership of all the orphaned groups.
  2108. @parm IN BOOL | bSourceNode | set to TRUE, if the update originated at
  2109. this
  2110. node.
  2111. @parm IN LPCWSTR | pszGroupId | The ID of the group that is about
  2112. to move.
  2113. @parm IN PDWORD | pdwNodeId| A pointer to a DWORD that contains the
  2114. ID of the node that is the destination of this move. It is
  2115. set to ClusterInvalidNodeId by the destination node when it has
  2116. accepted the group.
  2117. @comm The purpose of this update is to let all nodes know that a move
  2118. is impending. If the source node dies while a move is in progress
  2119. ,
  2120. then preference is given to the target of the move rather than the
  2121. node that is chosen by the FmpClaimNodeGroups algorithm.
  2122. @rdesc returns ERROR_SUCCESS.
  2123. ****/
  2124. DWORD
  2125. FmpUpdateAssignOwnerToGroups(
  2126. IN BOOL SourceNode,
  2127. IN LPCWSTR pszNodeId
  2128. )
  2129. {
  2130. PNM_NODE pNode = NULL;
  2131. DWORD dwStatus = ERROR_SUCCESS;
  2132. DWORD dwNodeId;
  2133. //
  2134. // Chittur Subbaraman (chitturs) - 4/18/99
  2135. //
  2136. // If FM groups are not fully initialized or FM is shutting down, then
  2137. // don't do anything.
  2138. //
  2139. if ( !FmpFMGroupsInited || FmpShutdown )
  2140. {
  2141. return(ERROR_SUCCESS);
  2142. }
  2143. //
  2144. // In a node evict, the NM GUM handler gets rids of the dead node from the OM list.
  2145. // This node down FM GUM handler could follow the NM evict GUM handler since NM
  2146. // lets an evict through once *it* declares a node as down. At that time, there is no
  2147. // guarantee that the FM node down GUM has executed since that GUM is issued in the
  2148. // async phase of node down processing and could very well follow the NM evict GUM
  2149. // handler. Thus, this GUM handler and associated functions CANNOT call OM to get
  2150. // a node object from the node ID string. Thus, this GUM handler and associated
  2151. // functions are carefully written to work with a node ID as opposed to a node object.
  2152. //
  2153. dwNodeId = wcstoul( pszNodeId, NULL, 10 );
  2154. //if this update has already been seen after the node down
  2155. //ignore this one
  2156. if (gFmpNodeArray[dwNodeId].dwNodeDownProcessingInProgress == 0)
  2157. {
  2158. ClRtlLogPrint(LOG_NOISE,
  2159. "[FM] FmpUpdateAssignOwnersToGroups, %1!ws! node down has been processed already\n",
  2160. pszNodeId);
  2161. goto FnExit;
  2162. }
  2163. //
  2164. // Assign ownership to all groups owned by the dead node
  2165. //
  2166. dwStatus = FmpAssignOwnersToGroups(pszNodeId, NULL, NULL);
  2167. if (dwStatus != ERROR_SUCCESS)
  2168. {
  2169. ClRtlLogPrint(LOG_CRITICAL,
  2170. "[FM] FmpUpdateAssignOwnersToGroups failed %1!d!\n",
  2171. dwStatus);
  2172. }
  2173. //mark that the node down processing has been done
  2174. gFmpNodeArray[dwNodeId].dwNodeDownProcessingInProgress = 0;
  2175. FnExit:
  2176. return(dwStatus);
  2177. }
  2178. /****
  2179. @func DWORD | FmpUpdateApproveJoin| The joining node
  2180. makes this update call.
  2181. @parm IN BOOL | bSourceNode | set to TRUE, if the update originated at
  2182. this
  2183. node.
  2184. @parm IN LPCWSTR | pszGroupId | The ID of the group that is about
  2185. to move.
  2186. @parm IN PDWORD | pdwNodeId| A pointer to a DWORD that contains the
  2187. ID of the node that is the destination of this move. It is
  2188. set to ClusterInvalidNodeId by the destination node when it has
  2189. accepted the group.
  2190. @comm The purpose of this update is to let all nodes know that a move
  2191. is impending. If the source node dies while a move is in progress
  2192. ,
  2193. then preference is given to the target of the move rather than the
  2194. node that is chosen by the FmpClaimNodeGroups algorithm.
  2195. @rdesc returns ERROR_SUCCESS.
  2196. ****/
  2197. DWORD
  2198. FmpUpdateApproveJoin(
  2199. IN BOOL SourceNode,
  2200. IN LPCWSTR pszNodeId
  2201. )
  2202. {
  2203. PNM_NODE pNode = NULL;
  2204. DWORD dwStatus = ERROR_SUCCESS;
  2205. //
  2206. // Chittur Subbaraman (chitturs) - 4/18/99
  2207. //
  2208. // If FM groups are not fully initialized or FM is shutting down, then
  2209. // don't do anything.
  2210. //
  2211. if ( !FmpFMGroupsInited || FmpShutdown )
  2212. {
  2213. return(ERROR_SUCCESS);
  2214. }
  2215. pNode = OmReferenceObjectById( ObjectTypeNode,
  2216. pszNodeId );
  2217. if (!pNode)
  2218. {
  2219. ClRtlLogPrint(LOG_CRITICAL,
  2220. "[FM] FmpUpdateAssignOwnersToGroups, %1!ws! node not found\n",
  2221. pszNodeId);
  2222. //should we return failure here
  2223. //is evict of a node synchronized with everything
  2224. goto FnExit;
  2225. }
  2226. if (pNode == NmLocalNode)
  2227. {
  2228. // SS: can I become the locker now
  2229. // If so, there what do I do
  2230. //i approve of my own join
  2231. goto FnExit;
  2232. }
  2233. //if a node is trying to join before the processing
  2234. //for its last death has been completed, ask it to retry
  2235. if (gFmpNodeArray[NmGetNodeId(pNode)].dwNodeDownProcessingInProgress == 1)
  2236. {
  2237. ClRtlLogPrint(LOG_CRITICAL,
  2238. "[FM] FmpUpdateApproveJoin, %1!ws! node down hasnt been processed as yet\n",
  2239. pszNodeId);
  2240. dwStatus = ERROR_RETRY;
  2241. goto FnExit;
  2242. }
  2243. FnExit:
  2244. if (pNode) OmDereferenceObject(pNode);
  2245. return(dwStatus);
  2246. }
  2247. /****
  2248. @func DWORD | FmpUpdateCreateGroup | GUM update handler for creating
  2249. a group.
  2250. @parm IN OUT PGUM_CREATE_GROUP | pGumGroup | Buffer containing group info
  2251. @parm IN BOOL | bSourceNode | Indicates whether this call originated
  2252. from this node.
  2253. @comm This GUM update creates a group and is structured as a local
  2254. transaction so that both registry entries and in-memory
  2255. structures are updated consistently.
  2256. @rdesc Returns ERROR_SUCCESS on success. A Win32 error code otherwise.
  2257. ****/
  2258. DWORD
  2259. FmpUpdateCreateGroup(
  2260. IN OUT PGUM_CREATE_GROUP pGumGroup,
  2261. IN BOOL bSourceNode
  2262. )
  2263. {
  2264. DWORD dwStatus = ERROR_SUCCESS;
  2265. HDMKEY hKey = NULL;
  2266. DWORD dwDisposition;
  2267. HLOCALXSACTION
  2268. hXsaction = NULL;
  2269. LPCWSTR lpszNodeId = NULL;
  2270. PNM_NODE pNode = NULL;
  2271. DWORD dwGroupIdLen = 0;
  2272. DWORD dwGroupNameLen = 0;
  2273. LPWSTR lpszGroupId = NULL;
  2274. LPCWSTR lpszGroupName = NULL;
  2275. BOOL bLocked = FALSE;
  2276. //
  2277. // Chittur Subbaraman (chitturs) - 5/27/99
  2278. //
  2279. // Restructure this GUM update as a local transaction.
  2280. //
  2281. dwGroupIdLen = pGumGroup->GroupIdLen;
  2282. dwGroupNameLen = pGumGroup->GroupNameLen;
  2283. lpszGroupId = pGumGroup->GroupId;
  2284. lpszGroupName = (PWSTR)((PCHAR)lpszGroupId +
  2285. dwGroupIdLen );
  2286. ClRtlLogPrint(LOG_NOISE,
  2287. "[FM] FmpUpdateCreateGroup: Entry for group %1!ws!...\n",
  2288. lpszGroupId);
  2289. //
  2290. // Start a transaction
  2291. //
  2292. hXsaction = DmBeginLocalUpdate();
  2293. if ( !hXsaction )
  2294. {
  2295. dwStatus = GetLastError();
  2296. ClRtlLogPrint(LOG_UNUSUAL,
  2297. "[FM] FmpUpdateCreateGroup, Failed in starting a transaction for group %1!ws!, Status =%2!d!....\n",
  2298. lpszGroupId,
  2299. dwStatus);
  2300. return( dwStatus );
  2301. }
  2302. //
  2303. // Create the new group key.
  2304. //
  2305. hKey = DmLocalCreateKey( hXsaction,
  2306. DmGroupsKey,
  2307. lpszGroupId,
  2308. 0,
  2309. KEY_READ | KEY_WRITE,
  2310. NULL,
  2311. &dwDisposition );
  2312. if ( hKey == NULL )
  2313. {
  2314. dwStatus = GetLastError();
  2315. ClRtlLogPrint(LOG_UNUSUAL,
  2316. "[FM] FmpUpdateCreateGroup, Failed in creating the group key for group %1!ws!, Status =%2!d!....\n",
  2317. lpszGroupId,
  2318. dwStatus);
  2319. goto FnExit;
  2320. }
  2321. if ( dwDisposition != REG_CREATED_NEW_KEY )
  2322. {
  2323. ClRtlLogPrint(LOG_CRITICAL,
  2324. "[FM] FmpUpdateCreateGroup used GUID %1!ws! that already existed! This is impossible.\n",
  2325. lpszGroupId);
  2326. dwStatus = ERROR_ALREADY_EXISTS;
  2327. goto FnExit;
  2328. }
  2329. CL_ASSERT( dwDisposition == REG_CREATED_NEW_KEY );
  2330. //
  2331. // Set the group name in the registry
  2332. //
  2333. dwStatus = DmLocalSetValue( hXsaction,
  2334. hKey,
  2335. CLUSREG_NAME_GRP_NAME,
  2336. REG_SZ,
  2337. ( CONST BYTE * ) lpszGroupName,
  2338. ( lstrlenW( lpszGroupName ) + 1 ) *
  2339. sizeof( WCHAR ) );
  2340. if( dwStatus != ERROR_SUCCESS )
  2341. {
  2342. ClRtlLogPrint(LOG_CRITICAL,
  2343. "[FM] FmpUpdateCreateGroup: DmLocalSetValue for group %1!ws! fails, Status = %2!d!...\n",
  2344. lpszGroupId,
  2345. dwStatus);
  2346. goto FnExit;
  2347. }
  2348. //
  2349. // We really shouldn't be acquiring locks here... but
  2350. // we'll try anyway. If we fail, we must return an error
  2351. // because we have nothing to return.
  2352. //
  2353. FmpTryAcquireGroupLock( bLocked, 500 );
  2354. if ( !bLocked )
  2355. {
  2356. pGumGroup->Group = NULL;
  2357. dwStatus = ERROR_SHARING_VIOLATION;
  2358. goto FnExit;
  2359. }
  2360. pGumGroup->Group = FmpCreateGroup( lpszGroupId, TRUE );
  2361. if ( pGumGroup->Group == NULL )
  2362. {
  2363. dwStatus = GetLastError();
  2364. ClRtlLogPrint(LOG_UNUSUAL,
  2365. "[FM] FmpUpdateCreateGroup, FmpCreateFroup failed for group %1!ws!, Status =%2!d!....\n",
  2366. lpszGroupId,
  2367. dwStatus);
  2368. goto FnExit;
  2369. } else
  2370. {
  2371. if ( bSourceNode )
  2372. {
  2373. OmReferenceObject( pGumGroup->Group );
  2374. OmReferenceObject( NmLocalNode );
  2375. pNode = NmLocalNode;
  2376. } else {
  2377. lpszNodeId = (PWSTR)((PCHAR)lpszGroupId +
  2378. dwGroupIdLen +
  2379. dwGroupNameLen );
  2380. pNode = OmReferenceObjectById( ObjectTypeNode, lpszNodeId );
  2381. if ( pNode == NULL )
  2382. {
  2383. CL_LOGFAILURE( ERROR_CLUSTER_NODE_NOT_FOUND );
  2384. dwStatus = ERROR_CLUSTER_NODE_NOT_FOUND;
  2385. ClRtlLogPrint(LOG_UNUSUAL,
  2386. "[FM] FmpUpdateCreateGroup, Could not find node for group %1!ws!, Status =%2!d!....\n",
  2387. lpszGroupId,
  2388. dwStatus);
  2389. CsInconsistencyHalt( ERROR_CLUSTER_NODE_NOT_FOUND );
  2390. }
  2391. }
  2392. CL_ASSERT( pGumGroup->Group->OwnerNode == NULL );
  2393. if ( !FmpInPreferredList( pGumGroup->Group, pNode , FALSE, NULL) )
  2394. {
  2395. ClRtlLogPrint(LOG_UNUSUAL,
  2396. "[FM] FmpUpdateCreateGroup, node %1!ws! is not in preferred list for group %2!ws!.\n",
  2397. OmObjectId( pNode ),
  2398. OmObjectId( pGumGroup->Group ));
  2399. }
  2400. pGumGroup->Group->OwnerNode = pNode;
  2401. if ( OmSetObjectName( pGumGroup->Group, lpszGroupName ) != ERROR_SUCCESS )
  2402. {
  2403. ClRtlLogPrint(LOG_UNUSUAL,
  2404. "[FM] FmpUpdateCreateGroup, Cannot set name for group %1!ws!...\n",
  2405. OmObjectId( pGumGroup->Group ));
  2406. }
  2407. ClusterEvent( CLUSTER_EVENT_GROUP_ADDED, pGumGroup->Group );
  2408. }
  2409. FnExit:
  2410. if ( bLocked )
  2411. {
  2412. FmpReleaseGroupLock( );
  2413. }
  2414. if ( hKey != NULL )
  2415. {
  2416. DmCloseKey( hKey );
  2417. }
  2418. if ( ( dwStatus == ERROR_SUCCESS ) &&
  2419. ( hXsaction != NULL ) )
  2420. {
  2421. DmCommitLocalUpdate( hXsaction );
  2422. }
  2423. else
  2424. {
  2425. if ( hXsaction ) DmAbortLocalUpdate( hXsaction );
  2426. }
  2427. ClRtlLogPrint(LOG_NOISE,
  2428. "[FM] FmpUpdateCreateGroup: Exit for group %1!ws!, Status=%2!u!...\n",
  2429. lpszGroupId,
  2430. dwStatus);
  2431. return( dwStatus );
  2432. }
  2433. /****
  2434. @func DWORD | FmpUpdateCompleteGroupMove | This update is made when
  2435. FmpTakeGroupRequest fails with an RPC error.
  2436. @parm IN BOOL | bSourceNode | Set to TRUE, if the update originated at
  2437. this node. Not used.
  2438. @parm IN LPCWSTR | pszNodeId | The ID of the dead node.
  2439. @parm IN LPCWSTR | pszGroupId | The ID of the group which was in the
  2440. middle of the move.
  2441. @comm The purpose of this update is to let the ownership of the
  2442. group which was in the middle of the move determined consistently.
  2443. @rdesc Returns ERROR_SUCCESS.
  2444. ****/
  2445. DWORD
  2446. FmpUpdateCompleteGroupMove(
  2447. IN BOOL bSourceNode,
  2448. IN LPCWSTR pszNodeId,
  2449. IN LPCWSTR pszGroupId
  2450. )
  2451. {
  2452. PFM_GROUP pGroup = NULL;
  2453. DWORD dwStatus = ERROR_SUCCESS;
  2454. //
  2455. // Chittur Subbaraman (chitturs) - 4/2/2000
  2456. //
  2457. // If FM groups are not fully initialized, then don't do anything.
  2458. // Don't check for shutdown since we need to handle take group
  2459. // exceptions for the quorum group even during a shutdown.
  2460. //
  2461. if ( !FmpFMGroupsInited )
  2462. {
  2463. return( ERROR_SUCCESS );
  2464. }
  2465. pGroup = OmReferenceObjectById( ObjectTypeGroup,
  2466. pszGroupId );
  2467. if ( !pGroup )
  2468. {
  2469. ClRtlLogPrint(LOG_CRITICAL,
  2470. "[FM] FmpUpdateCompleteGroupMove, %1!ws! group not found\n",
  2471. pszGroupId);
  2472. goto FnExit;
  2473. }
  2474. //
  2475. // Assign ownership to this group which was in the middle of a move
  2476. //
  2477. dwStatus = FmpAssignOwnersToGroups( pszNodeId, pGroup, NULL );
  2478. if ( dwStatus != ERROR_SUCCESS )
  2479. {
  2480. ClRtlLogPrint(LOG_CRITICAL,
  2481. "[FM] FmpUpdateCompleteGroupMove failed with error %1!d!\n",
  2482. dwStatus);
  2483. }
  2484. FnExit:
  2485. if ( pGroup ) OmDereferenceObject( pGroup );
  2486. return( dwStatus );
  2487. }
  2488. DWORD
  2489. FmpUpdateCheckAndSetGroupOwner(
  2490. IN BOOL bSourceNode,
  2491. IN LPCWSTR lpszGroupId,
  2492. IN LPCWSTR lpszNodeId
  2493. )
  2494. /*++
  2495. Routine Description:
  2496. GUM update handler called from FmpTakeGroupRequest for NT5 cluster
  2497. to set the group owner ONLY IF its intended owner is the future
  2498. owner node.
  2499. Arguments:
  2500. bSourceNode - Supplies whether or not this node was the source of the update
  2501. lpszGroupId - Supplies the id of the resource whose state is changing
  2502. lpszNodeId - Supplies the node id of the group owner.
  2503. Return Value:
  2504. ERROR_SUCCESS if successful
  2505. Win32 error code otherwise
  2506. --*/
  2507. {
  2508. PFM_GROUP pGroup = NULL;
  2509. DWORD dwStatus = ERROR_SUCCESS;
  2510. PNM_NODE pNode = NULL;
  2511. PNM_NODE pPrevNode = NULL;
  2512. //dont check for shutdown - we cant afford to lose ownership notifications
  2513. //while we are shutting down
  2514. //since we dont destroy any fm structures - there shouldnt be a problem in
  2515. //handling these
  2516. if ( !FmpFMGroupsInited )
  2517. {
  2518. return( ERROR_SUCCESS );
  2519. }
  2520. ClRtlLogPrint(LOG_NOISE,
  2521. "[FM] FmpUpdateCheckAndSetGroupOwner: Entry for Group = <%1!ws!>....\n",
  2522. lpszGroupId);
  2523. //
  2524. // Chittur Subbaraman (chitturs) - 7/27/99
  2525. //
  2526. // This GUM handler sets the group ownership only if the future owner
  2527. // node is the group's intended owner. If the intended owner is NULL,
  2528. // it means the node down processing GUM handler has taken charge
  2529. // of this group. If the intended owner is not NULL and not the
  2530. // future owner node, then it means that the node down processing
  2531. // GUM handler has assigned ownership to the group and the group
  2532. // started moving to a different target before the FmpTakeGroupRequest
  2533. // that issued this GUM due as a part of the first move operation
  2534. // got a chance to execute. In both cases, lay your hands off the
  2535. // group.
  2536. //
  2537. pGroup = OmReferenceObjectById( ObjectTypeGroup,
  2538. lpszGroupId );
  2539. if ( pGroup == NULL )
  2540. {
  2541. ClRtlLogPrint(LOG_CRITICAL,
  2542. "[FM] FmpUpdateCheckAndSetGroupOwner: GroupID = %1!ws! could not be found...\n",
  2543. lpszGroupId);
  2544. dwStatus = ERROR_GROUP_NOT_FOUND;
  2545. goto FnExit;
  2546. }
  2547. pNode = OmReferenceObjectById( ObjectTypeNode,
  2548. lpszNodeId );
  2549. if ( pNode == NULL )
  2550. {
  2551. ClRtlLogPrint(LOG_CRITICAL,
  2552. "[FM] FmpUpdateCheckAndSetGroupOwner: NodeID = %1!ws! could not be found, Group = %2!ws!...\n",
  2553. lpszNodeId,
  2554. lpszGroupId);
  2555. dwStatus = ERROR_CLUSTER_NODE_NOT_FOUND;
  2556. goto FnExit;
  2557. }
  2558. if ( pGroup->pIntendedOwner != pNode )
  2559. {
  2560. ClRtlLogPrint(LOG_CRITICAL,
  2561. "[FM] FmpUpdateCheckAndSetGroupOwner: Group = <%1!ws!> intended owner is invalid, not setting group ownership...\n",
  2562. lpszGroupId);
  2563. dwStatus = ERROR_GROUP_NOT_AVAILABLE;
  2564. goto FnExit;
  2565. }
  2566. pPrevNode = pGroup->OwnerNode;
  2567. //
  2568. // Set the new owner node, incr ref count
  2569. //
  2570. OmReferenceObject( pNode );
  2571. pGroup->OwnerNode = pNode;
  2572. //
  2573. // Decrement the ref count on previous owner
  2574. //
  2575. OmDereferenceObject( pPrevNode );
  2576. //
  2577. // Generate an event to signify group owner node change
  2578. //
  2579. ClusterEvent( CLUSTER_EVENT_GROUP_CHANGE, pGroup );
  2580. FnExit:
  2581. if ( pGroup ) OmDereferenceObject( pGroup );
  2582. if ( pNode ) OmDereferenceObject( pNode );
  2583. ClRtlLogPrint(LOG_NOISE,
  2584. "[FM] FmpUpdateCheckAndSetGroupOwner: Exit for Group = <%1!ws!>, Status=%2!u!....\n",
  2585. lpszGroupId,
  2586. dwStatus);
  2587. return( dwStatus );
  2588. }
  2589. DWORD
  2590. FmpUpdateCreateResourceType(
  2591. IN PVOID Buffer
  2592. )
  2593. /*++
  2594. Routine Description:
  2595. GUM update handler called for creating a resource type. For
  2596. NT5.1 clusters, this GUM handler does both the registry and
  2597. in-memory updates as a local transaction.
  2598. Arguments:
  2599. Buffer - Buffer containing resource type information.
  2600. Return Value:
  2601. ERROR_SUCCESS if successful
  2602. Win32 error code otherwise
  2603. --*/
  2604. {
  2605. PFM_RESTYPE pResType = NULL;
  2606. LPWSTR lpszTypeName;
  2607. LPWSTR lpszDisplayName;
  2608. LPWSTR lpszDllName;
  2609. DWORD dwStatus = ERROR_SUCCESS;
  2610. DWORD dwLooksAlive;
  2611. DWORD dwIsAlive;
  2612. DWORD dwDllNameLen;
  2613. DWORD dwDisplayNameLen;
  2614. DWORD dwTypeNameLen;
  2615. DWORD dwClusterHighestVersion;
  2616. DWORD dwDisposition;
  2617. HLOCALXSACTION hXsaction = NULL;
  2618. HDMKEY hTypeKey = NULL;
  2619. //
  2620. // Chittur Subbaraman (chitturs) - 2/8/2000
  2621. //
  2622. // Rewrite this GUM handler as a local transaction (for NT5.1 only)
  2623. //
  2624. lpszTypeName = ( LPWSTR ) Buffer;
  2625. ClRtlLogPrint(LOG_NOISE,
  2626. "[FM] FmpUpdateCreateResourceType, Entry for resource type %1!ws!...\n",
  2627. lpszTypeName);
  2628. pResType = OmReferenceObjectById( ObjectTypeResType,
  2629. lpszTypeName );
  2630. if ( pResType )
  2631. {
  2632. dwStatus = ERROR_ALREADY_EXISTS;
  2633. ClRtlLogPrint(LOG_CRITICAL,
  2634. "[FM] FmpUpdateCreateResourceType, Resource type %1!ws! already exists, Status = %2!d!...\n",
  2635. lpszTypeName,
  2636. dwStatus);
  2637. OmDereferenceObject( pResType );
  2638. return( dwStatus );
  2639. }
  2640. dwTypeNameLen = ( lstrlenW( lpszTypeName ) + 1 ) * sizeof( WCHAR );
  2641. lpszDisplayName = ( LPWSTR ) ( ( PCHAR ) Buffer + dwTypeNameLen );
  2642. dwDisplayNameLen = ( lstrlenW( lpszDisplayName ) + 1 ) * sizeof( WCHAR );
  2643. lpszDllName = ( LPWSTR ) ( ( PCHAR ) Buffer +
  2644. dwTypeNameLen +
  2645. dwDisplayNameLen );
  2646. dwDllNameLen = ( lstrlenW( lpszDllName ) + 1 ) * sizeof( WCHAR );
  2647. NmGetClusterOperationalVersion( &dwClusterHighestVersion,
  2648. NULL,
  2649. NULL );
  2650. if ( CLUSTER_GET_MAJOR_VERSION( dwClusterHighestVersion ) <
  2651. NT51_MAJOR_VERSION )
  2652. {
  2653. goto skip_registry_updates;
  2654. }
  2655. dwLooksAlive = *( DWORD UNALIGNED * ) ( ( ( PCHAR ) Buffer +
  2656. dwTypeNameLen +
  2657. dwDisplayNameLen +
  2658. dwDllNameLen ) );
  2659. dwIsAlive = *( DWORD UNALIGNED * ) ( ( ( PCHAR ) Buffer +
  2660. dwTypeNameLen +
  2661. dwDisplayNameLen +
  2662. dwDllNameLen +
  2663. sizeof( DWORD ) ) );
  2664. //
  2665. // Start a transaction
  2666. //
  2667. hXsaction = DmBeginLocalUpdate();
  2668. if ( !hXsaction )
  2669. {
  2670. dwStatus = GetLastError();
  2671. ClRtlLogPrint(LOG_CRITICAL,
  2672. "[FM] FmpUpdateCreateResourceType, Failed in starting a transaction for resource type %1!ws!, Status =%2!d!....\n",
  2673. lpszTypeName,
  2674. dwStatus);
  2675. return( dwStatus );
  2676. }
  2677. hTypeKey = DmLocalCreateKey( hXsaction,
  2678. DmResourceTypesKey,
  2679. lpszTypeName,
  2680. 0,
  2681. KEY_READ | KEY_WRITE,
  2682. NULL,
  2683. &dwDisposition );
  2684. if ( hTypeKey == NULL )
  2685. {
  2686. dwStatus = GetLastError();
  2687. ClRtlLogPrint(LOG_CRITICAL,
  2688. "[FM] FmpUpdateCreateResourceType, Failed in creating the resource types key for resource type %1!ws!, Status =%2!d!....\n",
  2689. lpszTypeName,
  2690. dwStatus);
  2691. goto FnExit;
  2692. }
  2693. if ( dwDisposition != REG_CREATED_NEW_KEY )
  2694. {
  2695. dwStatus = ERROR_ALREADY_EXISTS;
  2696. ClRtlLogPrint(LOG_CRITICAL,
  2697. "[FM] FmpUpdateCreateResourceType, Duplicate resource types key exists for resource type %1!ws!, Status =%2!d!....\n",
  2698. lpszTypeName,
  2699. dwStatus);
  2700. goto FnExit;
  2701. }
  2702. dwStatus = DmLocalSetValue( hXsaction,
  2703. hTypeKey,
  2704. CLUSREG_NAME_RESTYPE_DLL_NAME,
  2705. REG_SZ,
  2706. ( CONST BYTE * )lpszDllName,
  2707. dwDllNameLen );
  2708. if ( dwStatus != ERROR_SUCCESS )
  2709. {
  2710. ClRtlLogPrint(LOG_CRITICAL,
  2711. "[FM] FmpUpdateCreateResourceType, Failed in setting the DLL name for resource type %1!ws!, Status =%2!d!....\n",
  2712. lpszTypeName,
  2713. dwStatus);
  2714. goto FnExit;
  2715. }
  2716. dwStatus = DmLocalSetValue( hXsaction,
  2717. hTypeKey,
  2718. CLUSREG_NAME_RESTYPE_IS_ALIVE,
  2719. REG_DWORD,
  2720. ( CONST BYTE * )&dwIsAlive,
  2721. sizeof( DWORD ) );
  2722. if ( dwStatus != ERROR_SUCCESS )
  2723. {
  2724. ClRtlLogPrint(LOG_CRITICAL,
  2725. "[FM] FmpUpdateCreateResourceType, Failed in setting the Is Alive interval for resource type %1!ws!, Status =%2!d!....\n",
  2726. lpszTypeName,
  2727. dwStatus);
  2728. goto FnExit;
  2729. }
  2730. dwStatus = DmLocalSetValue( hXsaction,
  2731. hTypeKey,
  2732. CLUSREG_NAME_RESTYPE_LOOKS_ALIVE,
  2733. REG_DWORD,
  2734. ( CONST BYTE * )&dwLooksAlive,
  2735. sizeof( DWORD ) );
  2736. if ( dwStatus != ERROR_SUCCESS )
  2737. {
  2738. ClRtlLogPrint(LOG_CRITICAL,
  2739. "[FM] FmpUpdateCreateResourceType, Failed in setting the Looks Alive interval for resource type %1!ws!, Status =%2!d!....\n",
  2740. lpszTypeName,
  2741. dwStatus);
  2742. goto FnExit;
  2743. }
  2744. dwStatus = DmLocalSetValue( hXsaction,
  2745. hTypeKey,
  2746. CLUSREG_NAME_RESTYPE_NAME,
  2747. REG_SZ,
  2748. ( CONST BYTE * )lpszDisplayName,
  2749. dwDisplayNameLen );
  2750. if ( dwStatus != ERROR_SUCCESS )
  2751. {
  2752. ClRtlLogPrint(LOG_CRITICAL,
  2753. "[FM] FmpUpdateCreateResourceType, Failed in setting the display name for resource type %1!ws!, Status =%2!d!....\n",
  2754. lpszTypeName,
  2755. dwStatus);
  2756. goto FnExit;
  2757. }
  2758. skip_registry_updates:
  2759. pResType = FmpCreateResType( lpszTypeName );
  2760. if ( pResType != NULL )
  2761. {
  2762. dwStatus = FmpRmLoadResTypeDll( pResType );
  2763. if ( dwStatus == ERROR_SUCCESS )
  2764. {
  2765. pResType->State = RESTYPE_STATE_LOADS;
  2766. } else
  2767. {
  2768. ClRtlLogPrint(LOG_NOISE,
  2769. "[FM] FmpUpdateCreateResourceType: Unable to load dll for resource type %1!ws!, Status=%2!u!...\n",
  2770. lpszTypeName,
  2771. dwStatus);
  2772. //
  2773. // Some nodes may not support this resource type. So, consider
  2774. // the loading failure as success. However, log the error.
  2775. //
  2776. dwStatus = ERROR_SUCCESS;
  2777. }
  2778. } else
  2779. {
  2780. dwStatus = GetLastError();
  2781. ClRtlLogPrint(LOG_NOISE,
  2782. "[FM] FmpUpdateCreateResourceType: Unable to create resource type %1!ws!, Status=%2!u!...\n",
  2783. lpszTypeName,
  2784. dwStatus);
  2785. }
  2786. FnExit:
  2787. if ( hTypeKey != NULL )
  2788. {
  2789. DmCloseKey( hTypeKey );
  2790. }
  2791. if ( ( dwStatus == ERROR_SUCCESS ) &&
  2792. ( hXsaction != NULL ) )
  2793. {
  2794. DmCommitLocalUpdate( hXsaction );
  2795. }
  2796. else
  2797. {
  2798. if ( hXsaction ) DmAbortLocalUpdate( hXsaction );
  2799. }
  2800. ClRtlLogPrint(LOG_NOISE,
  2801. "[FM] FmpUpdateCreateResourceType: Exit for resource type %1!ws!, Status=%2!u!...\n",
  2802. lpszTypeName,
  2803. dwStatus);
  2804. return( dwStatus );
  2805. }
  2806. DWORD
  2807. FmpUpdateCreateResource(
  2808. IN OUT PGUM_CREATE_RESOURCE pGumResource
  2809. )
  2810. {
  2811. /*++
  2812. Routine Description:
  2813. GUM update handler called for creating a resource. For
  2814. NT5.1 clusters, this GUM handler does both the registry and
  2815. in-memory updates as a local transaction.
  2816. Arguments:
  2817. pGumResource - Structure containing resource information.
  2818. Return Value:
  2819. ERROR_SUCCESS if successful
  2820. Win32 error code otherwise
  2821. --*/
  2822. DWORD dwStatus = ERROR_SUCCESS;
  2823. HDMKEY hResourceKey = NULL;
  2824. HDMKEY hGroupKey = NULL;
  2825. DWORD dwDisposition;
  2826. HLOCALXSACTION
  2827. hXsaction = NULL;
  2828. DWORD dwClusterHighestVersion;
  2829. PGUM_CREATE_RESOURCE GumResource;
  2830. LPWSTR lpszResourceId = NULL;
  2831. LPWSTR lpszResourceName = NULL;
  2832. LPWSTR lpszResourceType = NULL;
  2833. PFM_GROUP pGroup = NULL;
  2834. PFM_RESTYPE pResType = NULL;
  2835. DWORD dwpollIntervals = CLUSTER_RESOURCE_USE_DEFAULT_POLL_INTERVAL;
  2836. DWORD dwPersistentState = 0;
  2837. DWORD dwResourceTypeLen = 0;
  2838. DWORD dwFlags = 0;
  2839. HDMKEY hParamKey = NULL;
  2840. //
  2841. // Chittur Subbaraman (chitturs) - 1/30/2000
  2842. //
  2843. // Restructure this GUM update as a local transaction.
  2844. //
  2845. lpszResourceId = (LPWSTR)( (PCHAR) pGumResource->GroupId +
  2846. pGumResource->GroupIdLen );
  2847. lpszResourceName = (LPWSTR)( (PCHAR) pGumResource->GroupId +
  2848. pGumResource->GroupIdLen +
  2849. pGumResource->ResourceIdLen );
  2850. pGroup = OmReferenceObjectById( ObjectTypeGroup,
  2851. pGumResource->GroupId );
  2852. if ( pGroup == NULL )
  2853. {
  2854. CL_LOGFAILURE( ERROR_GROUP_NOT_FOUND );
  2855. ClRtlLogPrint(LOG_CRITICAL,
  2856. "[FM] FmpUpdateCreateResource: Group for resource %1!ws! not found.\n",
  2857. lpszResourceId);
  2858. return( ERROR_GROUP_NOT_FOUND );
  2859. }
  2860. ClRtlLogPrint(LOG_NOISE,
  2861. "[FM] FmpUpdateCreateResource: Entry for resource %1!ws!...\n",
  2862. lpszResourceId);
  2863. //
  2864. // If we are dealing with the mixed mode cluster, don't bother to
  2865. // do these registry updates since the API layer would do it.
  2866. //
  2867. NmGetClusterOperationalVersion( &dwClusterHighestVersion,
  2868. NULL,
  2869. NULL );
  2870. if ( CLUSTER_GET_MAJOR_VERSION( dwClusterHighestVersion ) <
  2871. NT51_MAJOR_VERSION )
  2872. {
  2873. ClRtlLogPrint(LOG_NOISE,
  2874. "[FM] FmpUpdateCreateResource: Skipping registry updates for resource %1!ws!...\n",
  2875. lpszResourceId);
  2876. goto skip_registry_updates;
  2877. }
  2878. dwResourceTypeLen = *( DWORD UNALIGNED * )( (PCHAR) pGumResource->GroupId +
  2879. pGumResource->GroupIdLen +
  2880. pGumResource->ResourceIdLen +
  2881. (lstrlenW(lpszResourceName)+1) * sizeof(WCHAR) );
  2882. lpszResourceType = (LPWSTR)( (PCHAR) pGumResource->GroupId +
  2883. pGumResource->GroupIdLen +
  2884. pGumResource->ResourceIdLen +
  2885. (lstrlenW(lpszResourceName)+1) * sizeof(WCHAR) +
  2886. sizeof( DWORD ) );
  2887. dwFlags = *( DWORD UNALIGNED * )( (PCHAR) pGumResource->GroupId +
  2888. pGumResource->GroupIdLen +
  2889. pGumResource->ResourceIdLen +
  2890. (lstrlenW(lpszResourceName)+1) * sizeof(WCHAR) +
  2891. sizeof( DWORD ) +
  2892. dwResourceTypeLen );
  2893. //
  2894. // Start a transaction
  2895. //
  2896. hXsaction = DmBeginLocalUpdate();
  2897. if ( !hXsaction )
  2898. {
  2899. dwStatus = GetLastError();
  2900. ClRtlLogPrint(LOG_UNUSUAL,
  2901. "[FM] FmpUpdateCreateResource, Failed in starting a transaction for resource %1!ws!, Status =%2!d!....\n",
  2902. lpszResourceId,
  2903. dwStatus);
  2904. OmDereferenceObject( pGroup );
  2905. return( dwStatus );
  2906. }
  2907. //
  2908. // Create the new resources key.
  2909. //
  2910. hResourceKey = DmLocalCreateKey( hXsaction,
  2911. DmResourcesKey,
  2912. lpszResourceId,
  2913. 0,
  2914. KEY_READ | KEY_WRITE,
  2915. NULL,
  2916. &dwDisposition );
  2917. if ( hResourceKey == NULL )
  2918. {
  2919. dwStatus = GetLastError();
  2920. ClRtlLogPrint(LOG_UNUSUAL,
  2921. "[FM] FmpUpdateCreateResource, Failed in creating the resource key for resource %1!ws!, Status =%2!d!....\n",
  2922. lpszResourceId,
  2923. dwStatus);
  2924. goto FnExit;
  2925. }
  2926. if ( dwDisposition != REG_CREATED_NEW_KEY )
  2927. {
  2928. ClRtlLogPrint(LOG_CRITICAL,
  2929. "[FM] FmpUpdateCreateResource used GUID %1!ws! that already existed! This is impossible.\n",
  2930. lpszResourceId);
  2931. dwStatus = ERROR_ALREADY_EXISTS;
  2932. goto FnExit;
  2933. }
  2934. CL_ASSERT( dwDisposition == REG_CREATED_NEW_KEY );
  2935. //
  2936. // Set the resource name in the registry
  2937. //
  2938. dwStatus = DmLocalSetValue( hXsaction,
  2939. hResourceKey,
  2940. CLUSREG_NAME_RES_NAME,
  2941. REG_SZ,
  2942. (CONST BYTE *)lpszResourceName,
  2943. (lstrlenW(lpszResourceName)+1)*sizeof(WCHAR) );
  2944. if( dwStatus != ERROR_SUCCESS )
  2945. {
  2946. ClRtlLogPrint(LOG_CRITICAL,
  2947. "[FM] FmpUpdateCreateResource: DmLocalSetValue (resource name) for resource %1!ws! fails, Status = %2!d!...\n",
  2948. lpszResourceId,
  2949. dwStatus);
  2950. goto FnExit;
  2951. }
  2952. //
  2953. // Set the resource's type in the registry
  2954. // Note we reference the resource type and use its ID
  2955. // so that the case is correct.
  2956. //
  2957. pResType = OmReferenceObjectById( ObjectTypeResType, lpszResourceType );
  2958. CL_ASSERT( pResType != NULL );
  2959. dwStatus = DmLocalSetValue( hXsaction,
  2960. hResourceKey,
  2961. CLUSREG_NAME_RES_TYPE,
  2962. REG_SZ,
  2963. (CONST BYTE *) OmObjectId( pResType ),
  2964. (lstrlenW( lpszResourceType ) + 1 )*sizeof(WCHAR) );
  2965. OmDereferenceObject( pResType );
  2966. if ( dwStatus != ERROR_SUCCESS )
  2967. {
  2968. ClRtlLogPrint(LOG_CRITICAL,
  2969. "[FM] FmpUpdateCreateResource: DmLocalSetValue (resource type) for resource %1!ws! fails, Status = %2!d!...\n",
  2970. lpszResourceId,
  2971. dwStatus);
  2972. goto FnExit;
  2973. }
  2974. //
  2975. // Set the resource's poll intervals in the registry.
  2976. //
  2977. dwStatus = DmLocalSetValue( hXsaction,
  2978. hResourceKey,
  2979. CLUSREG_NAME_RES_LOOKS_ALIVE,
  2980. REG_DWORD,
  2981. (CONST BYTE *)&dwpollIntervals,
  2982. 4 );
  2983. if ( dwStatus != ERROR_SUCCESS )
  2984. {
  2985. ClRtlLogPrint(LOG_CRITICAL,
  2986. "[FM] FmpUpdateCreateResource: DmLocalSetValue (looks alive) for resource %1!ws! fails, Status = %2!d!...\n",
  2987. lpszResourceId,
  2988. dwStatus);
  2989. goto FnExit;
  2990. }
  2991. dwStatus = DmLocalSetValue( hXsaction,
  2992. hResourceKey,
  2993. CLUSREG_NAME_RES_IS_ALIVE,
  2994. REG_DWORD,
  2995. (CONST BYTE *)&dwpollIntervals,
  2996. 4);
  2997. if ( dwStatus != ERROR_SUCCESS )
  2998. {
  2999. ClRtlLogPrint(LOG_CRITICAL,
  3000. "[FM] FmpUpdateCreateResource: DmLocalSetValue (is alive) for resource %1!ws! fails, Status = %2!d!...\n",
  3001. lpszResourceId,
  3002. dwStatus);
  3003. goto FnExit;
  3004. }
  3005. //
  3006. // If this resource should be started in a separate monitor, set that
  3007. // parameter now.
  3008. //
  3009. if ( dwFlags & CLUSTER_RESOURCE_SEPARATE_MONITOR )
  3010. {
  3011. DWORD dwSeparateMonitor = 1;
  3012. dwStatus = DmLocalSetValue( hXsaction,
  3013. hResourceKey,
  3014. CLUSREG_NAME_RES_SEPARATE_MONITOR,
  3015. REG_DWORD,
  3016. (CONST BYTE *)&dwSeparateMonitor,
  3017. sizeof( dwSeparateMonitor ) );
  3018. if ( dwStatus != ERROR_SUCCESS)
  3019. {
  3020. ClRtlLogPrint(LOG_CRITICAL,
  3021. "[FM] FmpUpdateCreateResource: DmLocalSetValue (separate monitor) for resource %1!ws! fails, Status = %2!d!...\n",
  3022. lpszResourceId,
  3023. dwStatus);
  3024. goto FnExit;
  3025. }
  3026. }
  3027. //
  3028. // Create a Parameters key for the resource.
  3029. //
  3030. hParamKey = DmLocalCreateKey( hXsaction,
  3031. hResourceKey,
  3032. CLUSREG_KEYNAME_PARAMETERS,
  3033. 0,
  3034. KEY_READ,
  3035. NULL,
  3036. &dwDisposition );
  3037. if ( hParamKey == NULL )
  3038. {
  3039. dwStatus = GetLastError();
  3040. ClRtlLogPrint(LOG_CRITICAL,
  3041. "[FM] FmpUpdateCreateResource: DmLocalCreateKey (parameters) for resource %1!ws! fails, Status = %2!d!...\n",
  3042. lpszResourceId,
  3043. dwStatus);
  3044. CL_LOGFAILURE( dwStatus );
  3045. goto FnExit;
  3046. } else
  3047. {
  3048. DmCloseKey( hParamKey );
  3049. }
  3050. hGroupKey = DmOpenKey( DmGroupsKey,
  3051. OmObjectId(pGroup),
  3052. KEY_READ | KEY_WRITE);
  3053. if ( hGroupKey == NULL )
  3054. {
  3055. dwStatus = GetLastError();
  3056. ClRtlLogPrint(LOG_CRITICAL,
  3057. "[FM] FmpUpdateCreateResource: DmOpenKey (group key) for resource %1!ws! fails, Status = %2!d!...\n",
  3058. lpszResourceId,
  3059. dwStatus);
  3060. goto FnExit;
  3061. }
  3062. //
  3063. // Chittur Subbaraman (chitturs) - 5/25/99
  3064. //
  3065. // Make sure you set the persistent state of the resource to
  3066. // ClusterResourceOffline before you create the resource. If
  3067. // this is not done, if you create a resource in a group which
  3068. // is online, the group's persistent state value (i.e., 1 in
  3069. // this case) is inherited by the resource in FmpQueryResourceInfo
  3070. // (only the memory state is set and not the registry state and
  3071. // this was a problem as well) and if you move such a group to
  3072. // another node, it will bring the newly created resource online.
  3073. //
  3074. dwStatus = DmLocalSetValue( hXsaction,
  3075. hResourceKey,
  3076. CLUSREG_NAME_RES_PERSISTENT_STATE,
  3077. REG_DWORD,
  3078. ( CONST BYTE * )&dwPersistentState,
  3079. sizeof( DWORD ) );
  3080. if ( dwStatus != ERROR_SUCCESS )
  3081. {
  3082. ClRtlLogPrint(LOG_CRITICAL,
  3083. "[FM] FmpUpdateCreateResource: DmLocalSetValue (persistent state) for resource %1!ws! fails, Status = %2!d!...\n",
  3084. lpszResourceId,
  3085. dwStatus);
  3086. goto FnExit;
  3087. }
  3088. //
  3089. // Add the resource to the Contains value of the specified group.
  3090. //
  3091. dwStatus = DmLocalAppendToMultiSz( hXsaction,
  3092. hGroupKey,
  3093. CLUSREG_NAME_GRP_CONTAINS,
  3094. lpszResourceId );
  3095. if ( dwStatus != ERROR_SUCCESS )
  3096. {
  3097. ClRtlLogPrint(LOG_CRITICAL,
  3098. "[FM] FmpUpdateCreateResource: DmLocalAppendToMultiSz (contains key) for resource %1!ws! fails, Status = %2!d!...\n",
  3099. lpszResourceId,
  3100. dwStatus);
  3101. goto FnExit;
  3102. }
  3103. skip_registry_updates:
  3104. FmpAcquireResourceLock();
  3105. pGumResource->Resource = FmpCreateResource( pGroup,
  3106. lpszResourceId,
  3107. lpszResourceName,
  3108. FALSE );
  3109. if ( pGumResource->Resource == NULL )
  3110. {
  3111. dwStatus = GetLastError();
  3112. ClRtlLogPrint(LOG_CRITICAL,
  3113. "[FM] FmpUpdateCreateResource: FmpCreateResource for resource %1!ws! fails, Status = %2!d!...\n",
  3114. lpszResourceId,
  3115. dwStatus);
  3116. } else
  3117. {
  3118. ClusterEvent( CLUSTER_EVENT_GROUP_PROPERTY_CHANGE,
  3119. pGroup );
  3120. ClusterEvent( CLUSTER_EVENT_RESOURCE_ADDED,
  3121. pGumResource->Resource );
  3122. if ( pGumResource->Resource )
  3123. {
  3124. OmReferenceObject( pGumResource->Resource );
  3125. FmpPostWorkItem( FM_EVENT_RESOURCE_ADDED,
  3126. pGumResource->Resource,
  3127. 0 );
  3128. }
  3129. }
  3130. FmpReleaseResourceLock();
  3131. FnExit:
  3132. if ( pGroup != NULL )
  3133. {
  3134. OmDereferenceObject( pGroup );
  3135. }
  3136. if ( hResourceKey != NULL )
  3137. {
  3138. DmCloseKey( hResourceKey );
  3139. }
  3140. if ( hGroupKey != NULL )
  3141. {
  3142. DmCloseKey( hGroupKey );
  3143. }
  3144. if ( ( dwStatus == ERROR_SUCCESS ) &&
  3145. ( hXsaction != NULL ) )
  3146. {
  3147. DmCommitLocalUpdate( hXsaction );
  3148. }
  3149. else
  3150. {
  3151. if ( hXsaction ) DmAbortLocalUpdate( hXsaction );
  3152. }
  3153. ClRtlLogPrint(LOG_NOISE,
  3154. "[FM] FmpUpdateCreateResource: Exit for resource %1!ws!, Status=%2!u!...\n",
  3155. lpszResourceId,
  3156. dwStatus);
  3157. return( dwStatus );
  3158. }
  3159. DWORD
  3160. FmpUpdateDeleteResource(
  3161. IN BOOL bSourceNode,
  3162. IN LPCWSTR lpszResourceId
  3163. )
  3164. /*++
  3165. Routine Description:
  3166. GUM dispatch routine for deleting a resource. For NT5.1 clusters, this is structured as
  3167. as local transaction.
  3168. Arguments:
  3169. bSourceNode - Supplies whether or not this node initiated the GUM update.
  3170. Not used.
  3171. lpszResourceId - Supplies the resource ID.
  3172. Return Value:
  3173. ERROR_SUCCESS if successful.
  3174. Win32 error code otherwise.
  3175. --*/
  3176. {
  3177. PFM_RESOURCE pResource = NULL;
  3178. PFM_GROUP pGroup = NULL;
  3179. PLIST_ENTRY pListEntry = NULL;
  3180. PDEPENDENCY pDependency = NULL;
  3181. PPOSSIBLE_ENTRY pPossibleEntry = NULL;
  3182. DWORD dwStatus;
  3183. HLOCALXSACTION
  3184. hXsaction = NULL;
  3185. DWORD dwClusterHighestVersion;
  3186. HDMKEY pGroupKey;
  3187. //
  3188. // Chittur Subbaraman (chitturs) - 9/7/2000
  3189. //
  3190. // Structure this GUM update as a local transaction.
  3191. //
  3192. //
  3193. // If FM groups are not fully initialized or FM is shutting down, then
  3194. // don't do anything.
  3195. //
  3196. if ( !FmpFMGroupsInited || FmpShutdown )
  3197. {
  3198. return( ERROR_SUCCESS );
  3199. }
  3200. pResource = OmReferenceObjectById( ObjectTypeResource, lpszResourceId );
  3201. if ( pResource == NULL )
  3202. {
  3203. ClRtlLogPrint(LOG_UNUSUAL,
  3204. "[FM] FmpUpdateDeleteResource: Resource %1!ws! cannot be found....\n",
  3205. lpszResourceId );
  3206. return( ERROR_RESOURCE_NOT_FOUND );
  3207. }
  3208. ClRtlLogPrint(LOG_NOISE,
  3209. "[FM] FmpUpdateDeleteResource: Delete resource %1!ws!, address %2!lx!....\n",
  3210. lpszResourceId,
  3211. pResource );
  3212. //
  3213. // NOTE: It is difficult to include the checkpoint removal in a local transaction, so keep it
  3214. // out for now. Also, note that these functions MUST be called BEFORE the Resources key is
  3215. // deleted since they enumerate the values under "Resources\RegSync" and "Resources\CryptoSync".
  3216. //
  3217. if ( pResource->Group->OwnerNode == NmLocalNode )
  3218. {
  3219. CpckRemoveResourceCheckpoints( pResource );
  3220. CpRemoveResourceCheckpoints( pResource );
  3221. }
  3222. //
  3223. // Start a transaction
  3224. //
  3225. hXsaction = DmBeginLocalUpdate();
  3226. if ( !hXsaction )
  3227. {
  3228. dwStatus = GetLastError();
  3229. ClRtlLogPrint(LOG_CRITICAL,
  3230. "[FM] FmpUpdateDeleteResource: Failed in starting a transaction for resource %1!ws!, Status =%2!d!....\n",
  3231. lpszResourceId,
  3232. dwStatus);
  3233. goto FnExit;
  3234. }
  3235. //
  3236. // Cannot acquire group lock here to avoid deadlocks with this current design.
  3237. //
  3238. //
  3239. // Remove all registry entries corresponding to the DependsOn list.
  3240. //
  3241. pListEntry = pResource->DependsOn.Flink;
  3242. while ( pListEntry != &pResource->DependsOn )
  3243. {
  3244. pDependency = CONTAINING_RECORD( pListEntry,
  3245. DEPENDENCY,
  3246. DependentLinkage );
  3247. CL_ASSERT( pDependency->DependentResource == pResource );
  3248. pListEntry = pListEntry->Flink;
  3249. //
  3250. // Note that the removal of registry entries is done as a local transaction.
  3251. //
  3252. dwStatus = FmpRemoveResourceDependency( hXsaction,
  3253. pResource,
  3254. pDependency->ProviderResource );
  3255. if ( dwStatus != ERROR_SUCCESS )
  3256. {
  3257. ClRtlLogPrint(LOG_CRITICAL,
  3258. "[FM] FmpUpdateDeleteResource: Unable to remove 'DependsOn' registry entries for resource %1!ws!, Status =%2!d!....\n",
  3259. lpszResourceId,
  3260. dwStatus);
  3261. goto FnExit;
  3262. }
  3263. }
  3264. //
  3265. // Remove all registry entries corresponding to the ProvidesFor list.
  3266. //
  3267. pListEntry = pResource->ProvidesFor.Flink;
  3268. while ( pListEntry != &pResource->ProvidesFor )
  3269. {
  3270. pDependency = CONTAINING_RECORD( pListEntry,
  3271. DEPENDENCY,
  3272. ProviderLinkage );
  3273. CL_ASSERT( pDependency->ProviderResource == pResource );
  3274. pListEntry = pListEntry->Flink;
  3275. //
  3276. // Note that the removal of registry entries is done as a local transaction.
  3277. //
  3278. dwStatus = FmpRemoveResourceDependency( hXsaction,
  3279. pDependency->DependentResource,
  3280. pResource );
  3281. if ( dwStatus != ERROR_SUCCESS )
  3282. {
  3283. ClRtlLogPrint(LOG_CRITICAL,
  3284. "[FM] FmpUpdateDeleteResource: Unable to remove 'ProvidesFor' registry entries for resource %1!ws!, Status=%2!d!....\n",
  3285. lpszResourceId,
  3286. dwStatus);
  3287. goto FnExit;
  3288. }
  3289. }
  3290. //
  3291. // If we are dealing with a Whistler-Win2K cluster, don't bother to
  3292. // do these registry updates since the API layer would do it.
  3293. //
  3294. NmGetClusterOperationalVersion( &dwClusterHighestVersion,
  3295. NULL,
  3296. NULL );
  3297. if ( CLUSTER_GET_MAJOR_VERSION( dwClusterHighestVersion ) <
  3298. NT51_MAJOR_VERSION )
  3299. {
  3300. ClRtlLogPrint(LOG_NOISE,
  3301. "[FM] FmpUpdateDeleteResource: Skipping registry updates for resource %1!ws!...\n",
  3302. lpszResourceId);
  3303. goto skip_registry_updates;
  3304. }
  3305. dwStatus = DmLocalDeleteTree( hXsaction,
  3306. DmResourcesKey,
  3307. OmObjectId( pResource ) );
  3308. if ( ( dwStatus != ERROR_SUCCESS ) &&
  3309. ( dwStatus != ERROR_FILE_NOT_FOUND ) )
  3310. {
  3311. ClRtlLogPrint(LOG_CRITICAL,
  3312. "[FM] FmpUpdateDeleteResource: Unable to remove 'Resources' tree for resource %1!ws!, Status=%2!d!....\n",
  3313. lpszResourceId,
  3314. dwStatus);
  3315. goto FnExit;
  3316. }
  3317. pGroupKey = DmOpenKey( DmGroupsKey,
  3318. OmObjectId( pResource->Group ),
  3319. KEY_READ | KEY_SET_VALUE );
  3320. if ( pGroupKey == NULL )
  3321. {
  3322. dwStatus = GetLastError();
  3323. ClRtlLogPrint(LOG_CRITICAL,
  3324. "[FM] FmpUpdateDeleteResource: Unable to find 'Groups' key for resource %1!ws!, Status=%2!d!....\n",
  3325. lpszResourceId,
  3326. dwStatus);
  3327. goto FnExit;
  3328. }
  3329. dwStatus = DmLocalRemoveFromMultiSz( hXsaction,
  3330. pGroupKey,
  3331. CLUSREG_NAME_GRP_CONTAINS,
  3332. OmObjectId( pResource ) );
  3333. DmCloseKey( pGroupKey );
  3334. if ( dwStatus != ERROR_SUCCESS )
  3335. {
  3336. ClRtlLogPrint(LOG_CRITICAL,
  3337. "[FM] FmpUpdateDeleteResource: Unable to remove contains list for resource %1!ws! in group %2!ws!, Status=%3!d!....\n",
  3338. lpszResourceId,
  3339. OmObjectId( pResource->Group ),
  3340. dwStatus);
  3341. goto FnExit;
  3342. }
  3343. skip_registry_updates:
  3344. //
  3345. // Remove all list entries corresponding to the DependsOn list.
  3346. //
  3347. pListEntry = pResource->DependsOn.Flink;
  3348. while ( pListEntry != &pResource->DependsOn ) {
  3349. pDependency = CONTAINING_RECORD( pListEntry,
  3350. DEPENDENCY,
  3351. DependentLinkage );
  3352. pListEntry = pListEntry->Flink;
  3353. RemoveEntryList( &pDependency->ProviderLinkage );
  3354. RemoveEntryList( &pDependency->DependentLinkage );
  3355. OmDereferenceObject( pDependency->DependentResource );
  3356. OmDereferenceObject( pDependency->ProviderResource );
  3357. LocalFree( pDependency );
  3358. }
  3359. //
  3360. // Remove all list entries corresponding to the ProvidesFor list.
  3361. //
  3362. pListEntry = pResource->ProvidesFor.Flink;
  3363. while ( pListEntry != &pResource->ProvidesFor ) {
  3364. pDependency = CONTAINING_RECORD( pListEntry,
  3365. DEPENDENCY,
  3366. ProviderLinkage );
  3367. pListEntry = pListEntry->Flink;
  3368. RemoveEntryList( &pDependency->ProviderLinkage );
  3369. RemoveEntryList( &pDependency->DependentLinkage );
  3370. OmDereferenceObject( pDependency->DependentResource );
  3371. OmDereferenceObject( pDependency->ProviderResource );
  3372. LocalFree( pDependency );
  3373. }
  3374. //
  3375. // Remove all entries from the possible owners list.
  3376. //
  3377. while ( !IsListEmpty( &pResource->PossibleOwners ) )
  3378. {
  3379. pListEntry = RemoveHeadList( &pResource->PossibleOwners );
  3380. pPossibleEntry = CONTAINING_RECORD( pListEntry,
  3381. POSSIBLE_ENTRY,
  3382. PossibleLinkage );
  3383. OmDereferenceObject( pPossibleEntry->PossibleNode );
  3384. LocalFree( pPossibleEntry );
  3385. }
  3386. //
  3387. // Remove this resource from the Contains list.
  3388. //
  3389. RemoveEntryList( &pResource->ContainsLinkage );
  3390. OmDereferenceObject( pResource );
  3391. //
  3392. // Close the resource's registry key.
  3393. //
  3394. DmRundownList( &pResource->DmRundownList );
  3395. if ( pResource->RegistryKey != NULL )
  3396. {
  3397. DmCloseKey( pResource->RegistryKey );
  3398. pResource->RegistryKey = NULL;
  3399. }
  3400. //
  3401. // SS: we do not delete the reference to the resource here
  3402. // since we will shortly have to add one before posting a notification
  3403. // to the fm worker thread.
  3404. //
  3405. // Post a work item to close the resource in the resource handler.
  3406. // Note that this must be done asynchronously as we cannot call
  3407. // the resource monitor from a GUM handler. If we do, resources
  3408. // do funny things and make deadlocks.
  3409. //
  3410. FmpPostWorkItem( FM_EVENT_RESOURCE_DELETED, pResource, 0 );
  3411. //
  3412. // Decrement resource type reference.
  3413. //
  3414. if ( pResource->Type != NULL ) {
  3415. OmDereferenceObject( pResource->Type );
  3416. pResource->Type = NULL;
  3417. }
  3418. //
  3419. // Remove the resource from the resource list.
  3420. //
  3421. dwStatus = OmRemoveObject( pResource );
  3422. ClusterEvent( CLUSTER_EVENT_RESOURCE_DELETED, pResource );
  3423. ClusterEvent( CLUSTER_EVENT_GROUP_PROPERTY_CHANGE,
  3424. pResource->Group );
  3425. //
  3426. // Mark the resource as deleted
  3427. //
  3428. pResource->dwStructState = FM_RESOURCE_STRUCT_MARKED_FOR_DELETE;
  3429. FnExit:
  3430. OmDereferenceObject( pResource );
  3431. if ( ( dwStatus == ERROR_SUCCESS ) &&
  3432. ( hXsaction != NULL ) )
  3433. {
  3434. DmCommitLocalUpdate( hXsaction );
  3435. }
  3436. else
  3437. {
  3438. if ( hXsaction ) DmAbortLocalUpdate( hXsaction );
  3439. }
  3440. ClRtlLogPrint(LOG_NOISE,
  3441. "[FM] FmpUpdateDeleteResource: Exit for resource %1!ws!, Status=%2!u!...\n",
  3442. lpszResourceId,
  3443. dwStatus);
  3444. return( dwStatus );
  3445. } // FmpUpdateDeleteResource
  3446. DWORD
  3447. FmpUpdateUseRandomizedNodeListForGroups(
  3448. IN BOOL SourceNode,
  3449. IN LPCWSTR pszNodeId,
  3450. IN PFM_GROUP_NODE_LIST pGroupNodeList
  3451. )
  3452. /*++
  3453. Routine Description:
  3454. GUM dispatch routine for using a randomized preferred list for group ownership on
  3455. node down.
  3456. Arguments:
  3457. bSourceNode - Supplies whether or not this node initiated the GUM update.
  3458. Not used.
  3459. pszNodeId - Supplies the ID of the node that is down.
  3460. pGroupNodeList - Randomized preferred node list for groups.
  3461. Return Value:
  3462. ERROR_SUCCESS if successful.
  3463. Win32 error code otherwise.
  3464. --*/
  3465. {
  3466. DWORD dwStatus = ERROR_SUCCESS;
  3467. DWORD dwNodeId;
  3468. //
  3469. // Chittur Subbaraman (chitturs) - 4/19/2001
  3470. //
  3471. // If FM groups are not fully initialized or FM is shutting down, then
  3472. // don't do anything.
  3473. //
  3474. if ( !FmpFMGroupsInited || FmpShutdown )
  3475. {
  3476. return( ERROR_SUCCESS );
  3477. }
  3478. //
  3479. // In a node evict, the NM GUM handler gets rids of the dead node from the OM list.
  3480. // This node down FM GUM handler could follow the NM evict GUM handler since NM
  3481. // lets an evict through once *it* declares a node as down. At that time, there is no
  3482. // guarantee that the FM node down GUM has executed since that GUM is issued in the
  3483. // async phase of node down processing and could very well follow the NM evict GUM
  3484. // handler. Thus, this GUM handler and associated functions CANNOT call OM to get
  3485. // a node object from the node ID string. Thus, this GUM handler and associated
  3486. // functions are carefully written to work with a node ID as opposed to a node object.
  3487. //
  3488. dwNodeId = wcstoul( pszNodeId, NULL, 10 );
  3489. //
  3490. // If this update has already been seen after the node down, ignore this one
  3491. //
  3492. if ( gFmpNodeArray[dwNodeId].dwNodeDownProcessingInProgress == 0 )
  3493. {
  3494. ClRtlLogPrint(LOG_NOISE,
  3495. "[FM] FmpUpdateUseRandomizedNodeListForGroups: %1!ws! node down has been processed already...\n",
  3496. pszNodeId);
  3497. goto FnExit;
  3498. }
  3499. //
  3500. // Assign ownership to all groups owned by the dead node
  3501. //
  3502. dwStatus = FmpAssignOwnersToGroups( pszNodeId,
  3503. NULL,
  3504. pGroupNodeList );
  3505. if ( dwStatus != ERROR_SUCCESS )
  3506. {
  3507. ClRtlLogPrint(LOG_CRITICAL,
  3508. "[FM] FmpUpdateUseRandomizedNodeListForGroups: FmpAssignOwnersToGroups failed %1!d!\n",
  3509. dwStatus);
  3510. }
  3511. //
  3512. // Mark that the node down processing has been done
  3513. //
  3514. gFmpNodeArray[dwNodeId].dwNodeDownProcessingInProgress = 0;
  3515. FnExit:
  3516. return( dwStatus );
  3517. }// FmpUpdateUseRandomizedNodeListForGroups