ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cmlazy.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.