Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

413 lines
10 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. install.c
  5. Abstract:
  6. Staging File Install Command Server.
  7. Author:
  8. Billy J. Fuller 09-Jun-1997
  9. Environment
  10. User mode winnt
  11. --*/
  12. #include <ntreppch.h>
  13. #pragma hdrstop
  14. #include <frs.h>
  15. #include <tablefcn.h>
  16. #include <perrepsr.h>
  17. //
  18. // Struct for the Staging File Generator Command Server
  19. // Contains info about the queues and the threads
  20. //
  21. COMMAND_SERVER InstallCs;
  22. ULONG MaxInstallCsThreads;
  23. #if 0
  24. //
  25. // Currently unused.
  26. //
  27. //
  28. // Retry times
  29. //
  30. #define INSTALLCS_RETRY_MIN (1 * 1000) // 1 second
  31. #define INSTALLCS_RETRY_MAX (10 * 1000) // 10 seconds
  32. BOOL
  33. InstallCsDelCsSubmit(
  34. IN PCOMMAND_PACKET Cmd
  35. )
  36. /*++
  37. Routine Description:
  38. Set the timer and kick off a delayed staging file command
  39. Arguments:
  40. Cmd
  41. Return Value:
  42. None.
  43. --*/
  44. {
  45. #undef DEBSUB
  46. #define DEBSUB "InstallCsDelCsSubmit:"
  47. //
  48. // Extend the retry time (but not too long)
  49. //
  50. RsTimeout(Cmd) <<= 1;
  51. if (RsTimeout(Cmd) > INSTALLCS_RETRY_MAX)
  52. return FALSE;
  53. //
  54. // or too short
  55. //
  56. if (RsTimeout(Cmd) < INSTALLCS_RETRY_MIN)
  57. RsTimeout(Cmd) = INSTALLCS_RETRY_MIN;
  58. //
  59. // This command will come back to us in a bit
  60. //
  61. FrsDelCsSubmitSubmit(&InstallCs, Cmd, RsTimeout(Cmd));
  62. return TRUE;
  63. }
  64. #endif 0
  65. VOID
  66. InstallCsInstallStage(
  67. IN PCOMMAND_PACKET Cmd
  68. )
  69. /*++
  70. Routine Description:
  71. Install the staging file into the target file. If successfull then
  72. send the CO to the retire code. If not and the condition is retryable then
  73. send the CO to the retry code. Otherwise abort the CO.
  74. Arguments:
  75. Cmd
  76. Return Value:
  77. None.
  78. --*/
  79. {
  80. #undef DEBSUB
  81. #define DEBSUB "InstallCsInstallStage:"
  82. ULONG WStatus;
  83. PCHANGE_ORDER_ENTRY Coe;
  84. //
  85. // Install the staging file
  86. //
  87. Coe = RsCoe(Cmd);
  88. WStatus = StuInstallStage(Coe);
  89. if (!WIN_SUCCESS(WStatus)) {
  90. if (DOES_CO_DELETE_FILE_NAME(RsCoc(Cmd))) {
  91. //
  92. // All delete and moveout change orders go thru retire. At this
  93. // point they are done except possibly for the final on-disk
  94. // delete. If the on-disk delete failed then the
  95. // COE_FLAG_NEED_DELETE is set in the
  96. // change order which sets IDREC_FLAGS_DELETE_DEFERRED in the
  97. // IDTable record for the file.
  98. //
  99. FRS_ASSERT(COE_FLAG_ON(Coe, COE_FLAG_NEED_DELETE));
  100. SET_CHANGE_ORDER_STATE(Coe, IBCO_INSTALL_DEL_RETRY);
  101. PM_INC_CTR_REPSET(Coe->NewReplica, FInstalled, 1);
  102. //
  103. // Retire this change order
  104. //
  105. ChgOrdInboundRetired(Coe);
  106. //
  107. // non-NULL change order entries kick the completion function
  108. // to start retry/unjoin. No need since we have retired this co.
  109. //
  110. RsCoe(Cmd) = NULL;
  111. goto out;
  112. }
  113. //
  114. // Something is wrong; try again later
  115. //
  116. // If it is retryable then retry.
  117. // Note that an ERROR_FILE_NOT_FOUND return from StuExecuteInstall means that the
  118. // pre-exisitng target file was not found. Most likely because it was
  119. // deleted out from under us. We should be getting a Local change order
  120. // that will update the IDTable entry so when this CO is retried later
  121. // it will get rejected.
  122. //
  123. if (WIN_RETRY_INSTALL(WStatus) ||
  124. (WStatus == ERROR_FILE_NOT_FOUND)) {
  125. CHANGE_ORDER_TRACEW(3, Coe, "Retrying install", WStatus);
  126. //
  127. // Retry this single change order if the namespace isn't
  128. // being altered (not a create or rename). Otherwise,
  129. // unjoin the cxtion and force all change orders through
  130. // retry so they will be retried in order at join; just
  131. // in case this change order affects later ones.
  132. //
  133. // Unjoining is sort of extreme; need less expensive recovery.
  134. // But if we don't unjoin (say for a rename) and a
  135. // create CO arrives next then we will have a name conflict
  136. // that should not have occurred just because a sharing violation
  137. // prevented us from doing the rename.
  138. //
  139. if ((!CoCmdIsDirectory(RsCoc(Cmd))) ||
  140. (!FrsDoesCoAlterNameSpace(RsCoc(Cmd)))) {
  141. CHANGE_ORDER_TRACE(3, Coe, "Submit CO to install retry");
  142. ChgOrdInboundRetry(Coe, IBCO_INSTALL_RETRY);
  143. //
  144. // non-NULL change order entries kick the completion
  145. // function to start a retry/unjoin. No need since we have
  146. // retired this co.
  147. //
  148. RsCoe(Cmd) = NULL;
  149. }
  150. goto out;
  151. } else {
  152. //
  153. // Not retryable.
  154. //
  155. // Note: If it's not a problem with the staging file we should send
  156. // it on even if we can't install it. Not clear what non-retryable
  157. // errors this would apply to though. For now just abort it.
  158. //
  159. SET_COE_FLAG(Coe, COE_FLAG_STAGE_ABORTED);
  160. CHANGE_ORDER_TRACEW(3, Coe, "Install failed; co aborted", WStatus);
  161. //
  162. // Increment the Files Installed Counter
  163. //
  164. PM_INC_CTR_REPSET(Coe->NewReplica, FInstalledError, 1);
  165. }
  166. } else {
  167. //
  168. // Install succeeded. Increment the Files Installed Counter.
  169. //
  170. CHANGE_ORDER_TRACE(3, Coe, "Install success");
  171. PM_INC_CTR_REPSET(Coe->NewReplica, FInstalled, 1);
  172. //
  173. // If this CO created a preinstall file then tell the retire path to
  174. // perform the final rename. Updates to existing files don't create
  175. // preinstall files.
  176. //
  177. if (COE_FLAG_ON(Coe, COE_FLAG_PREINSTALL_CRE)) {
  178. SET_COE_FLAG(Coe, COE_FLAG_NEED_RENAME);
  179. }
  180. }
  181. //
  182. // Installing the fetched staging file
  183. //
  184. SET_CHANGE_ORDER_STATE(Coe, IBCO_INSTALL_COMPLETE);
  185. //
  186. // Retire this change order
  187. //
  188. ChgOrdInboundRetired(Coe);
  189. //
  190. // non-NULL change order entries kick the completion function
  191. // to start retry/unjoin. No need since we have retired this co.
  192. //
  193. RsCoe(Cmd) = NULL;
  194. out:
  195. //
  196. // ERROR_SUCCESS just means we have handled all of the conditions
  197. // that arose; no need for the cleanup function to intervene.
  198. //
  199. // Unless RsCoe(Cmd) is non-NULL; in which case the completion
  200. // function will initiate a retry/unjoin.
  201. //
  202. FrsCompleteCommand(Cmd, ERROR_SUCCESS);
  203. }
  204. DWORD
  205. MainInstallCs(
  206. PVOID Arg
  207. )
  208. /*++
  209. Routine Description:
  210. Entry point for a thread serving the Staging File Install Command Server.
  211. Arguments:
  212. Arg - thread
  213. Return Value:
  214. None.
  215. --*/
  216. {
  217. #undef DEBSUB
  218. #define DEBSUB "MainInstallCs:"
  219. ULONG WStatus = ERROR_SUCCESS;
  220. PCOMMAND_PACKET Cmd;
  221. PFRS_THREAD FrsThread = (PFRS_THREAD)Arg;
  222. //
  223. // Thread is pointing at the correct command server
  224. //
  225. FRS_ASSERT(FrsThread->Data == &InstallCs);
  226. FrsThread->Exit = ThSupExitWithTombstone;
  227. //
  228. // Try-Finally
  229. //
  230. try {
  231. //
  232. // Capture exception.
  233. //
  234. try {
  235. //
  236. // Pull entries off the queue and process them
  237. //
  238. cant_exit_yet:
  239. while (Cmd = FrsGetCommandServer(&InstallCs)) {
  240. switch (Cmd->Command) {
  241. case CMD_INSTALL_STAGE:
  242. DPRINT1(3, "Install: command install stage 0x%x\n", Cmd);
  243. InstallCsInstallStage(Cmd);
  244. break;
  245. default:
  246. DPRINT1(0, "Staging File Install: unknown command 0x%x\n", Cmd->Command);
  247. FrsCompleteCommand(Cmd, ERROR_INVALID_FUNCTION);
  248. break;
  249. }
  250. }
  251. //
  252. // Exit
  253. //
  254. FrsExitCommandServer(&InstallCs, FrsThread);
  255. goto cant_exit_yet;
  256. //
  257. // Get exception status.
  258. //
  259. } except (EXCEPTION_EXECUTE_HANDLER) {
  260. GET_EXCEPTION_CODE(WStatus);
  261. }
  262. } finally {
  263. if (WIN_SUCCESS(WStatus)) {
  264. if (AbnormalTermination()) {
  265. WStatus = ERROR_OPERATION_ABORTED;
  266. }
  267. }
  268. DPRINT_WS(0, "InstallCs finally.", WStatus);
  269. //
  270. // Trigger FRS shutdown if we terminated abnormally.
  271. //
  272. if (!WIN_SUCCESS(WStatus)) {
  273. DPRINT(0, "InstallCs terminated abnormally, forcing service shutdown.\n");
  274. FrsIsShuttingDown = TRUE;
  275. SetEvent(ShutDownEvent);
  276. } else {
  277. WStatus = ERROR_SUCCESS;
  278. }
  279. }
  280. return WStatus;
  281. }
  282. VOID
  283. FrsInstallCsInitialize(
  284. VOID
  285. )
  286. /*++
  287. Routine Description:
  288. Initialize the staging file installer
  289. Arguments:
  290. None.
  291. Return Value:
  292. None.
  293. --*/
  294. {
  295. #undef DEBSUB
  296. #define DEBSUB "FrsInstallCsInitialize:"
  297. //
  298. // Initialize the command servers
  299. //
  300. CfgRegReadDWord(FKC_MAX_INSTALLCS_THREADS, NULL, 0, &MaxInstallCsThreads);
  301. FrsInitializeCommandServer(&InstallCs, MaxInstallCsThreads, L"InstallCs", MainInstallCs);
  302. }
  303. VOID
  304. ShutDownInstallCs(
  305. VOID
  306. )
  307. /*++
  308. Routine Description:
  309. Shutdown the staging file installer command server.
  310. Arguments:
  311. None.
  312. Return Value:
  313. None.
  314. --*/
  315. {
  316. #undef DEBSUB
  317. #define DEBSUB "ShutDownInstallCs:"
  318. FrsRunDownCommandServer(&InstallCs, &InstallCs.Queue);
  319. }
  320. VOID
  321. FrsInstallCsSubmitTransfer(
  322. IN PCOMMAND_PACKET Cmd,
  323. IN USHORT Command
  324. )
  325. /*++
  326. Routine Description:
  327. Transfer a request to the staging file generator
  328. Arguments:
  329. Cmd
  330. Return Value:
  331. None.
  332. --*/
  333. {
  334. #undef DEBSUB
  335. #define DEBSUB "FrsInstallCsSubmitTransfer:"
  336. //
  337. // Submit a request to allocate staging area
  338. //
  339. Cmd->TargetQueue = &InstallCs.Queue;
  340. Cmd->Command = Command;
  341. RsTimeout(Cmd) = 0;
  342. DPRINT1(5, "Install: submit %x\n", Cmd);
  343. FrsSubmitCommandServer(&InstallCs, Cmd);
  344. }