Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencmlazy.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/config/cmapi.c 00005 * PURPOSE: Configuration Manager - Internal Registry APIs 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include "ntoskrnl.h" 00012 #define NDEBUG 00013 #include "debug.h" 00014 00015 /* GLOBALS ********************************************************************/ 00016 00017 KTIMER CmpLazyFlushTimer; 00018 KDPC CmpLazyFlushDpc; 00019 WORK_QUEUE_ITEM CmpLazyWorkItem; 00020 KTIMER CmpEnableLazyFlushTimer; 00021 KDPC CmpEnableLazyFlushDpc; 00022 BOOLEAN CmpLazyFlushPending; 00023 BOOLEAN CmpForceForceFlush; 00024 BOOLEAN CmpHoldLazyFlush = TRUE; 00025 ULONG CmpLazyFlushIntervalInSeconds = 5; 00026 ULONG CmpLazyFlushHiveCount = 7; 00027 ULONG CmpLazyFlushCount = 1; 00028 LONG CmpFlushStarveWriters; 00029 00030 /* FUNCTIONS ******************************************************************/ 00031 00032 BOOLEAN 00033 NTAPI 00034 CmpDoFlushNextHive(IN BOOLEAN ForceFlush, 00035 OUT PBOOLEAN Error, 00036 OUT PULONG DirtyCount) 00037 { 00038 NTSTATUS Status; 00039 PLIST_ENTRY NextEntry; 00040 PCMHIVE CmHive; 00041 BOOLEAN Result; 00042 ULONG HiveCount = CmpLazyFlushHiveCount; 00043 00044 /* Set Defaults */ 00045 *Error = FALSE; 00046 *DirtyCount = 0; 00047 00048 /* Don't do anything if we're not supposed to */ 00049 if (CmpNoWrite) return TRUE; 00050 00051 /* Make sure we have to flush at least one hive */ 00052 if (!HiveCount) HiveCount = 1; 00053 00054 /* Don't force flush */ 00055 CmpForceForceFlush = FALSE; 00056 00057 /* Acquire the list lock and loop */ 00058 ExAcquirePushLockShared(&CmpHiveListHeadLock); 00059 NextEntry = CmpHiveListHead.Flink; 00060 while (NextEntry != &CmpHiveListHead) 00061 { 00062 /* Get the hive and check if we should flush it */ 00063 CmHive = CONTAINING_RECORD(NextEntry, CMHIVE, HiveList); 00064 if (!(CmHive->Hive.HiveFlags & HIVE_NOLAZYFLUSH) && 00065 (CmHive->FlushCount != CmpLazyFlushCount)) 00066 { 00067 /* Great sucess! */ 00068 Result = TRUE; 00069 00070 /* Ignore clean or volatile hves */ 00071 if (!(CmHive->Hive.DirtyCount) || 00072 (CmHive->Hive.HiveFlags & HIVE_VOLATILE)) 00073 { 00074 /* Don't do anything but do update the count */ 00075 CmHive->FlushCount = CmpLazyFlushCount; 00076 } 00077 else 00078 { 00079 /* Do the sync */ 00080 DPRINT1("Flushing: %wZ\n", CmHive->FileFullPath); 00081 DPRINT1("Handle: %lx\n", CmHive->FileHandles[HFILE_TYPE_PRIMARY]); 00082 Status = HvSyncHive(&CmHive->Hive); 00083 if(!NT_SUCCESS(Status)) 00084 { 00085 /* Let them know we failed */ 00086 *Error = TRUE; 00087 Result = FALSE; 00088 } 00089 } 00090 } 00091 else if ((CmHive->Hive.DirtyCount) && 00092 (!(CmHive->Hive.HiveFlags & HIVE_VOLATILE)) && 00093 (!(CmHive->Hive.HiveFlags & HIVE_NOLAZYFLUSH))) 00094 { 00095 /* Use another lazy flusher for this hive */ 00096 ASSERT(CmHive->FlushCount == CmpLazyFlushCount); 00097 *DirtyCount += CmHive->Hive.DirtyCount; 00098 } 00099 00100 /* Try the next one */ 00101 NextEntry = NextEntry->Flink; 00102 } 00103 00104 /* Check if we've flushed everything */ 00105 if (NextEntry == &CmpHiveListHead) 00106 { 00107 /* We have, tell the caller we're done */ 00108 Result = FALSE; 00109 } 00110 else 00111 { 00112 /* We need to be called again */ 00113 Result = TRUE; 00114 } 00115 00116 /* Unlock the list and return the result */ 00117 ExReleasePushLock(&CmpHiveListHeadLock); 00118 return Result; 00119 } 00120 00121 VOID 00122 NTAPI 00123 CmpEnableLazyFlushDpcRoutine(IN PKDPC Dpc, 00124 IN PVOID DeferredContext, 00125 IN PVOID SystemArgument1, 00126 IN PVOID SystemArgument2) 00127 { 00128 /* Don't stop lazy flushing from happening anymore */ 00129 CmpHoldLazyFlush = FALSE; 00130 } 00131 00132 VOID 00133 NTAPI 00134 CmpLazyFlushDpcRoutine(IN PKDPC Dpc, 00135 IN PVOID DeferredContext, 00136 IN PVOID SystemArgument1, 00137 IN PVOID SystemArgument2) 00138 { 00139 /* Check if we should queue the lazy flush worker */ 00140 if ((!CmpLazyFlushPending) && (!CmpHoldLazyFlush)) 00141 { 00142 CmpLazyFlushPending = TRUE; 00143 ExQueueWorkItem(&CmpLazyWorkItem, DelayedWorkQueue); 00144 } 00145 } 00146 00147 VOID 00148 NTAPI 00149 CmpLazyFlush(VOID) 00150 { 00151 LARGE_INTEGER DueTime; 00152 PAGED_CODE(); 00153 00154 /* Check if we should set the lazy flush timer */ 00155 if ((!CmpNoWrite) && (!CmpHoldLazyFlush)) 00156 { 00157 /* Do it */ 00158 DueTime.QuadPart = Int32x32To64(CmpLazyFlushIntervalInSeconds, 00159 -10 * 1000 * 1000); 00160 KeSetTimer(&CmpLazyFlushTimer, DueTime, &CmpLazyFlushDpc); 00161 } 00162 } 00163 00164 VOID 00165 NTAPI 00166 CmpLazyFlushWorker(IN PVOID Parameter) 00167 { 00168 BOOLEAN ForceFlush, Result, MoreWork = FALSE; 00169 ULONG DirtyCount = 0; 00170 PAGED_CODE(); 00171 00172 /* Don't do anything if lazy flushing isn't enabled yet */ 00173 if (CmpHoldLazyFlush) return; 00174 00175 /* Check if we are forcing a flush */ 00176 ForceFlush = CmpForceForceFlush; 00177 if (ForceFlush) 00178 { 00179 /* Lock the registry exclusively */ 00180 CmpLockRegistryExclusive(); 00181 } 00182 else 00183 { 00184 /* Do a normal lock */ 00185 CmpLockRegistry(); 00186 InterlockedIncrement(&CmpFlushStarveWriters); 00187 } 00188 00189 /* Flush the next hive */ 00190 MoreWork = CmpDoFlushNextHive(ForceFlush, &Result, &DirtyCount); 00191 if (!MoreWork) 00192 { 00193 /* We're done */ 00194 InterlockedIncrement((PLONG)&CmpLazyFlushCount); 00195 } 00196 00197 /* Check if we have starved writers */ 00198 if (!ForceFlush) InterlockedDecrement(&CmpFlushStarveWriters); 00199 00200 /* Not pending anymore, release the registry lock */ 00201 CmpLazyFlushPending = FALSE; 00202 CmpUnlockRegistry(); 00203 00204 /* Check if we need to flush another hive */ 00205 if ((MoreWork) || (DirtyCount)) CmpLazyFlush(); 00206 } 00207 00208 VOID 00209 NTAPI 00210 CmpCmdInit(IN BOOLEAN SetupBoot) 00211 { 00212 LARGE_INTEGER DueTime; 00213 PAGED_CODE(); 00214 00215 /* Setup the lazy DPC */ 00216 KeInitializeDpc(&CmpLazyFlushDpc, CmpLazyFlushDpcRoutine, NULL); 00217 00218 /* Setup the lazy timer */ 00219 KeInitializeTimer(&CmpLazyFlushTimer); 00220 00221 /* Setup the lazy worker */ 00222 ExInitializeWorkItem(&CmpLazyWorkItem, CmpLazyFlushWorker, NULL); 00223 00224 /* Setup the forced-lazy DPC and timer */ 00225 KeInitializeDpc(&CmpEnableLazyFlushDpc, 00226 CmpEnableLazyFlushDpcRoutine, 00227 NULL); 00228 KeInitializeTimer(&CmpEnableLazyFlushTimer); 00229 00230 /* Enable lazy flushing after 10 minutes */ 00231 DueTime.QuadPart = Int32x32To64(600, -10 * 1000 * 1000); 00232 KeSetTimer(&CmpEnableLazyFlushTimer, DueTime, &CmpEnableLazyFlushDpc); 00233 00234 /* Setup flush variables */ 00235 CmpNoWrite = CmpMiniNTBoot; 00236 CmpWasSetupBoot = SetupBoot; 00237 00238 /* Testing: Force Lazy Flushing */ 00239 CmpHoldLazyFlush = FALSE; 00240 00241 /* Setup the hive list */ 00242 CmpInitializeHiveList(SetupBoot); 00243 } 00244 00245 NTSTATUS 00246 NTAPI 00247 CmpCmdHiveOpen(IN POBJECT_ATTRIBUTES FileAttributes, 00248 IN PSECURITY_CLIENT_CONTEXT ImpersonationContext, 00249 IN OUT PBOOLEAN Allocate, 00250 OUT PCMHIVE *NewHive, 00251 IN ULONG CheckFlags) 00252 { 00253 PUNICODE_STRING FileName; 00254 NTSTATUS Status; 00255 PAGED_CODE(); 00256 00257 /* Open the file in the current security context */ 00258 FileName = FileAttributes->ObjectName; 00259 Status = CmpInitHiveFromFile(FileName, 00260 0, 00261 NewHive, 00262 Allocate, 00263 CheckFlags); 00264 if (((Status == STATUS_ACCESS_DENIED) || 00265 (Status == STATUS_NO_SUCH_USER) || 00266 (Status == STATUS_WRONG_PASSWORD) || 00267 (Status == STATUS_ACCOUNT_EXPIRED) || 00268 (Status == STATUS_ACCOUNT_DISABLED) || 00269 (Status == STATUS_ACCOUNT_RESTRICTION)) && 00270 (ImpersonationContext)) 00271 { 00272 /* We failed due to an account/security error, impersonate SYSTEM */ 00273 Status = SeImpersonateClientEx(ImpersonationContext, NULL); 00274 if (NT_SUCCESS(Status)) 00275 { 00276 /* Now try again */ 00277 Status = CmpInitHiveFromFile(FileName, 00278 0, 00279 NewHive, 00280 Allocate, 00281 CheckFlags); 00282 00283 /* Restore impersonation token */ 00284 PsRevertToSelf(); 00285 } 00286 } 00287 00288 /* Return status of open attempt */ 00289 return Status; 00290 } 00291 00292 VOID 00293 NTAPI 00294 CmpShutdownWorkers(VOID) 00295 { 00296 /* Stop lazy flushing */ 00297 PAGED_CODE(); 00298 KeCancelTimer(&CmpLazyFlushTimer); 00299 } 00300 00301 VOID 00302 NTAPI 00303 CmSetLazyFlushState(IN BOOLEAN Enable) 00304 { 00305 /* Set state for lazy flusher */ 00306 CmpHoldLazyFlush = !Enable; 00307 } 00308 00309 /* EOF */ Generated on Sat May 26 2012 04:35:58 for ReactOS by
1.7.6.1
|