Index: /trunk/src/kWorker/kWorker.c
===================================================================
--- /trunk/src/kWorker/kWorker.c	(revision 2867)
+++ /trunk/src/kWorker/kWorker.c	(revision 2868)
@@ -4716,7 +4716,8 @@
 
     /*
-     * Invalidate the missing cache entries.
+     * Invalidate the volatile parts of cache (kBuild output directory,
+     * temporary directory, whatever).
      */
-    kFsCacheInvalidateMissing(g_pFsCache);
+    kFsCacheInvalidateCustomBoth(g_pFsCache);
     return 0;
 }
@@ -5234,15 +5235,27 @@
 int main(int argc, char **argv)
 {
-    KSIZE   cbMsgBuf = 0;
-    KU8    *pbMsgBuf = NULL;
-    int     i;
-    HANDLE  hPipe = INVALID_HANDLE_VALUE;
+    KSIZE           cbMsgBuf = 0;
+    KU8            *pbMsgBuf = NULL;
+    int             i;
+    HANDLE          hPipe = INVALID_HANDLE_VALUE;
+    const char     *pszTmp;
+    KFSLOOKUPERROR  enmIgnored;
 
     /*
-     * Create the cache.
+     * Create the cache and mark the temporary directory as using the custom revision.
      */
     g_pFsCache = kFsCacheCreate(KFSCACHE_F_MISSING_OBJECTS | KFSCACHE_F_MISSING_PATHS);
     if (!g_pFsCache)
         return kwErrPrintfRc(3, "kFsCacheCreate failed!\n");
+
+    pszTmp = getenv("TEMP");
+    if (pszTmp && *pszTmp != '\0')
+        kFsCacheSetupCustomRevisionForTree(g_pFsCache, kFsCacheLookupA(g_pFsCache, pszTmp, &enmIgnored));
+    pszTmp = getenv("TMP");
+    if (pszTmp && *pszTmp != '\0')
+        kFsCacheSetupCustomRevisionForTree(g_pFsCache, kFsCacheLookupA(g_pFsCache, pszTmp, &enmIgnored));
+    pszTmp = getenv("TMPDIR");
+    if (pszTmp && *pszTmp != '\0')
+        kFsCacheSetupCustomRevisionForTree(g_pFsCache, kFsCacheLookupA(g_pFsCache, pszTmp, &enmIgnored));
 
     /*
@@ -5271,4 +5284,12 @@
                 return kwErrPrintfRc(2, "--pipe takes an argument!\n");
         }
+        else if (strcmp(argv[i], "--volatile") == 0)
+        {
+            i++;
+            if (i < argc)
+                kFsCacheSetupCustomRevisionForTree(g_pFsCache, kFsCacheLookupA(g_pFsCache, argv[i], &enmIgnored));
+            else
+                return kwErrPrintfRc(2, "--volatile takes an argument!\n");
+        }
         else if (strcmp(argv[i], "--test") == 0)
             return kwTestRun(argc - i - 1, &argv[i + 1]);
@@ -5277,8 +5298,8 @@
                  || strcmp(argv[i], "-?") == 0)
         {
-            printf("usage: kWorker --pipe <pipe-handle>\n"
+            printf("usage: kWorker [--volatile dir] --pipe <pipe-handle>\n"
                    "usage: kWorker <--help|-h>\n"
                    "usage: kWorker <--version|-V>\n"
-                   "usage: kWorker --test [<times> [--chdir <dir>]] -- args\n"
+                   "usage: kWorker [--volatile dir] --test [<times> [--chdir <dir>]] -- args\n"
                    "\n"
                    "This is an internal kmk program that is used via the builtin_kSubmit.\n");
Index: /trunk/src/kmk/dir-nt-bird.c
===================================================================
--- /trunk/src/kmk/dir-nt-bird.c	(revision 2867)
+++ /trunk/src/kmk/dir-nt-bird.c	(revision 2868)
@@ -114,5 +114,5 @@
                 {
                     PKFSOBJ pNameObj = kFsCacheLookupRelativeToDirA(g_pFsCache, (PKFSDIR)pDirObj,
-                                                                    pszName, strlen(pszName), &enmError);
+                                                                    pszName, strlen(pszName), &enmError, NULL);
                     if (pNameObj)
                     {
Index: /trunk/src/kmk/kmkbuiltin/kSubmit.c
===================================================================
--- /trunk/src/kmk/kmkbuiltin/kSubmit.c	(revision 2867)
+++ /trunk/src/kmk/kmkbuiltin/kSubmit.c	(revision 2868)
@@ -307,4 +307,14 @@
     size_t const    cbExecutableBuf = GET_PATH_MAX;
     PATH_VAR(szExecutable);
+#define TUPLE(a_sz)     a_sz, sizeof(a_sz) - 1
+    struct variable *pVarVolatile = lookup_variable(TUPLE("PATH_OUT"));
+    if (pVarVolatile)
+    { /* likely */ }
+    else
+    {
+        pVarVolatile = lookup_variable(TUPLE("PATH_OUT_BASE"));
+        if (!pVarVolatile)
+            warn("Neither PATH_OUT_BASE nor PATH_OUT was found.");
+    }
 
     /*
@@ -373,5 +383,10 @@
                 {
                     char        szHandleArg[32];
-                    const char *apszArgs[4] = { szExecutable, "--pipe", szHandleArg, NULL };
+                    const char *apszArgs[6] =
+                    {
+                        szExecutable, "--pipe", szHandleArg,
+                        pVarVolatile ? "--volatile" : NULL, pVarVolatile ? pVarVolatile->value : NULL,
+                        NULL
+                    };
                     _snprintf(szHandleArg, sizeof(szHandleArg), "%p", hWorkerPipe);
 
Index: /trunk/src/lib/nt/kFsCache.c
===================================================================
--- /trunk/src/lib/nt/kFsCache.c	(revision 2867)
+++ /trunk/src/lib/nt/kFsCache.c	(revision 2868)
@@ -399,23 +399,28 @@
  * @param   fAbsolute           Whether it can be refreshed using an absolute
  *                              lookup or requires the slow treatment.
+ * @parma   idxMissingGen       The missing generation index.
  * @param   idxHashTab          The hash table index of the path.
  * @param   enmError            The lookup error.
  */
 static PKFSHASHA kFsCacheCreatePathHashTabEntryA(PKFSCACHE pCache, PKFSOBJ pFsObj, const char *pszPath, KU32 cchPath,
-                                                 KU32 uHashPath, KU32 idxHashTab, BOOL fAbsolute, KFSLOOKUPERROR enmError)
+                                                 KU32 uHashPath, KU32 idxHashTab, BOOL fAbsolute, KU32 idxMissingGen,
+                                                 KFSLOOKUPERROR enmError)
 {
     PKFSHASHA pHashEntry = (PKFSHASHA)kHlpAlloc(sizeof(*pHashEntry) + cchPath + 1);
     if (pHashEntry)
     {
-        pHashEntry->uHashPath   = uHashPath;
-        pHashEntry->cchPath     = (KU16)cchPath;
-        pHashEntry->fAbsolute   = fAbsolute;
-        pHashEntry->pFsObj      = pFsObj;
-        pHashEntry->enmError    = enmError;
-        pHashEntry->pszPath     = (const char *)kHlpMemCopy(pHashEntry + 1, pszPath, cchPath + 1);
+        pHashEntry->uHashPath       = uHashPath;
+        pHashEntry->cchPath         = (KU16)cchPath;
+        pHashEntry->fAbsolute       = fAbsolute;
+        pHashEntry->idxMissingGen   = (KU8)idxMissingGen;
+        pHashEntry->pFsObj          = pFsObj;
+        pHashEntry->enmError        = enmError;
+        pHashEntry->pszPath         = (const char *)kHlpMemCopy(pHashEntry + 1, pszPath, cchPath + 1);
         if (pFsObj)
-            pHashEntry->uCacheGen = pCache->uGeneration;
+            pHashEntry->uCacheGen = pFsObj->bObjType != KFSOBJ_TYPE_MISSING
+                                  ? pCache->auGenerations[       pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                  : pCache->auGenerationsMissing[pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
         else if (enmError != KFSLOOKUPERROR_UNSUPPORTED)
-            pHashEntry->uCacheGen = pCache->uGenerationMissing;
+            pHashEntry->uCacheGen = pCache->auGenerationsMissing[idxMissingGen];
         else
             pHashEntry->uCacheGen = KFSOBJ_CACHE_GEN_IGNORE;
@@ -444,23 +449,28 @@
  * @param   fAbsolute           Whether it can be refreshed using an absolute
  *                              lookup or requires the slow treatment.
+ * @parma   idxMissingGen       The missing generation index.
  * @param   idxHashTab          The hash table index of the path.
  * @param   enmError            The lookup error.
  */
 static PKFSHASHW kFsCacheCreatePathHashTabEntryW(PKFSCACHE pCache, PKFSOBJ pFsObj, const wchar_t *pwszPath, KU32 cwcPath,
-                                                 KU32 uHashPath, KU32 idxHashTab, BOOL fAbsolute, KFSLOOKUPERROR enmError)
+                                                 KU32 uHashPath, KU32 idxHashTab, BOOL fAbsolute, KU32 idxMissingGen,
+                                                 KFSLOOKUPERROR enmError)
 {
     PKFSHASHW pHashEntry = (PKFSHASHW)kHlpAlloc(sizeof(*pHashEntry) + (cwcPath + 1) * sizeof(wchar_t));
     if (pHashEntry)
     {
-        pHashEntry->uHashPath   = uHashPath;
-        pHashEntry->cwcPath     = cwcPath;
-        pHashEntry->fAbsolute   = fAbsolute;
-        pHashEntry->pFsObj      = pFsObj;
-        pHashEntry->enmError    = enmError;
-        pHashEntry->pwszPath    = (const wchar_t *)kHlpMemCopy(pHashEntry + 1, pwszPath, (cwcPath + 1) * sizeof(wchar_t));
+        pHashEntry->uHashPath       = uHashPath;
+        pHashEntry->cwcPath         = cwcPath;
+        pHashEntry->fAbsolute       = fAbsolute;
+        pHashEntry->idxMissingGen   = (KU8)idxMissingGen;
+        pHashEntry->pFsObj          = pFsObj;
+        pHashEntry->enmError        = enmError;
+        pHashEntry->pwszPath        = (const wchar_t *)kHlpMemCopy(pHashEntry + 1, pwszPath, (cwcPath + 1) * sizeof(wchar_t));
         if (pFsObj)
-            pHashEntry->uCacheGen = pCache->uGeneration;
+            pHashEntry->uCacheGen = pFsObj->bObjType != KFSOBJ_TYPE_MISSING
+                                  ? pCache->auGenerations[       pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                  : pCache->auGenerationsMissing[pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
         else if (enmError != KFSLOOKUPERROR_UNSUPPORTED)
-            pHashEntry->uCacheGen = pCache->uGenerationMissing;
+            pHashEntry->uCacheGen = pCache->auGenerationsMissing[idxMissingGen];
         else
             pHashEntry->uCacheGen = KFSOBJ_CACHE_GEN_IGNORE;
@@ -555,10 +565,12 @@
         pObj->u32Magic      = KFSOBJ_MAGIC;
         pObj->cRefs         = 1;
-        pObj->uCacheGen     = bObjType != KFSOBJ_TYPE_MISSING ? pCache->uGeneration : pCache->uGenerationMissing;
+        pObj->uCacheGen     = bObjType != KFSOBJ_TYPE_MISSING
+                            ? pCache->auGenerations[pParent->Obj.fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                            : pCache->auGenerationsMissing[pParent->Obj.fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
         pObj->bObjType      = bObjType;
         pObj->fHaveStats    = K_FALSE;
         pObj->abUnused[0]   = K_FALSE;
         pObj->abUnused[1]   = K_FALSE;
-        pObj->fFlags        = pParent->Obj.fFlags;
+        pObj->fFlags        = pParent->Obj.fFlags & KFSOBJ_F_INHERITED_MASK;
         pObj->pParent       = pParent;
         pObj->pUserDataHead = NULL;
@@ -1502,5 +1514,5 @@
         pDir->fNeedRePopulating = K_FALSE;
         if (pDir->Obj.uCacheGen != KFSOBJ_CACHE_GEN_IGNORE)
-            pDir->Obj.uCacheGen = pCache->uGeneration;
+            pDir->Obj.uCacheGen = pCache->auGenerations[pDir->Obj.fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
         return K_TRUE;
     }
@@ -1544,5 +1556,5 @@
         && !pDir->fNeedRePopulating
         && (   pDir->Obj.uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
-            || pDir->Obj.uCacheGen == pCache->uGeneration) )
+            || pDir->Obj.uCacheGen == pCache->auGenerations[pDir->Obj.fFlags & KFSOBJ_F_USE_CUSTOM_GEN]) )
         return K_TRUE;
     return kFsCachePopuplateOrRefreshDir(pCache, pDir, penmError ? penmError : &enmIgnored);
@@ -1590,5 +1602,5 @@
     {
         KFSCACHE_LOG(("Parent of missing not written to %s/%s\n", pMissing->pParent->Obj.pszName, pMissing->pszName));
-        pMissing->uCacheGen = pCache->uGenerationMissing;
+        pMissing->uCacheGen = pCache->auGenerationsMissing[pMissing->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
     }
     else
@@ -1612,5 +1624,5 @@
              * Probably more likely that a missing node stays missing.
              */
-            pMissing->uCacheGen = pCache->uGenerationMissing;
+            pMissing->uCacheGen = pCache->auGenerationsMissing[pMissing->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
             KFSCACHE_LOG(("Still missing %s/%s\n", pMissing->pParent->Obj.pszName, pMissing->pszName));
         }
@@ -1629,5 +1641,5 @@
                           pMissing->pParent->Obj.pszName, pMissing->pszName, bObjType, BasicInfo.FileAttributes));
             pMissing->bObjType  = bObjType;
-            pMissing->uCacheGen = pCache->uGenerationMissing;
+            pMissing->uCacheGen = pCache->auGenerations[pMissing->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
 /**
  * @todo refresh missing object names when it appears.
@@ -1799,5 +1811,5 @@
             if (MY_NT_SUCCESS(rcNt))
             {
-                pObj->uCacheGen = pCache->uGeneration;
+                pObj->uCacheGen = pCache->auGenerations[pObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
                 fRc = K_TRUE;
             }
@@ -1858,5 +1870,5 @@
             if (MY_NT_SUCCESS(rcNt))
             {
-                pObj->uCacheGen = pCache->uGeneration;
+                pObj->uCacheGen = pCache->auGenerations[pObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
                 fRc = K_TRUE;
             }
@@ -2276,7 +2288,10 @@
  * @param   penmError           Where to return details as to why the lookup
  *                              failed.
+ * @param   ppLastAncestor      Where to return the last parent element found
+ *                              (referenced) in case of error an path/file not
+ *                              found problem.  Optional.
  */
 PKFSOBJ kFsCacheLookupRelativeToDirA(PKFSCACHE pCache, PKFSDIR pParent, const char *pszPath, KU32 cchPath,
-                                     KFSLOOKUPERROR *penmError)
+                                     KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
 {
     /*
@@ -2284,4 +2299,6 @@
      */
     KU32 off = 0;
+    if (ppLastAncestor)
+        *ppLastAncestor = NULL;
     for (;;)
     {
@@ -2312,5 +2329,5 @@
         if (   pParent->fPopulated
             && (   pParent->Obj.uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
-                || pParent->Obj.uCacheGen == pCache->uGeneration) )
+                || pParent->Obj.uCacheGen == pCache->auGenerations[pParent->Obj.fFlags & KFSOBJ_F_USE_CUSTOM_GEN]) )
         { /* likely */ }
         else if (kFsCachePopuplateOrRefreshDir(pCache, pParent, penmError))
@@ -2340,4 +2357,6 @@
             else
                 *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_FOUND;
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
             return NULL;
         }
@@ -2350,5 +2369,5 @@
             if (   pChild->bObjType != KFSOBJ_TYPE_MISSING
                 || pChild->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
-                || pChild->uCacheGen == pCache->uGenerationMissing
+                || pChild->uCacheGen == pCache->auGenerationsMissing[pChild->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
                 || kFsCacheRefreshMissing(pCache, pChild, penmError) )
             { /* likely */ }
@@ -2367,10 +2386,14 @@
         {
             *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_DIR;
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
             return NULL;
         }
         else if (   pChild->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
-                 || pChild->uCacheGen == pCache->uGenerationMissing)
+                 || pChild->uCacheGen == pCache->auGenerationsMissing[pChild->fFlags & KFSOBJ_F_USE_CUSTOM_GEN])
         {
             *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_FOUND;
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
             return NULL;
         }
@@ -2378,5 +2401,9 @@
             pParent = (PKFSDIR)pChild;
         else
+        {
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
             return NULL;
+        }
     }
 
@@ -2401,7 +2428,10 @@
  * @param   penmError           Where to return details as to why the lookup
  *                              failed.
+ * @param   ppLastAncestor      Where to return the last parent element found
+ *                              (referenced) in case of error an path/file not
+ *                              found problem.  Optional.
  */
 PKFSOBJ kFsCacheLookupRelativeToDirW(PKFSCACHE pCache, PKFSDIR pParent, const wchar_t *pwszPath, KU32 cwcPath,
-                                     KFSLOOKUPERROR *penmError)
+                                     KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
 {
     /*
@@ -2409,4 +2439,6 @@
      */
     KU32 off = 0;
+    if (ppLastAncestor)
+        *ppLastAncestor = NULL;
     for (;;)
     {
@@ -2437,5 +2469,5 @@
         if (   pParent->fPopulated
             && (   pParent->Obj.uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
-                || pParent->Obj.uCacheGen == pCache->uGeneration) )
+                || pParent->Obj.uCacheGen == pCache->auGenerations[pParent->Obj.fFlags & KFSOBJ_F_USE_CUSTOM_GEN]) )
         { /* likely */ }
         else if (kFsCachePopuplateOrRefreshDir(pCache, pParent, penmError))
@@ -2465,4 +2497,6 @@
             else
                 *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_FOUND;
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
             return NULL;
         }
@@ -2475,5 +2509,5 @@
             if (   pChild->bObjType != KFSOBJ_TYPE_MISSING
                 || pChild->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
-                || pChild->uCacheGen == pCache->uGenerationMissing
+                || pChild->uCacheGen == pCache->auGenerationsMissing[pChild->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
                 || kFsCacheRefreshMissing(pCache, pChild, penmError) )
             { /* likely */ }
@@ -2492,10 +2526,14 @@
         {
             *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_DIR;
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
             return NULL;
         }
         else if (   pChild->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
-                 || pChild->uCacheGen == pCache->uGenerationMissing)
+                 || pChild->uCacheGen == pCache->auGenerationsMissing[pChild->fFlags & KFSOBJ_F_USE_CUSTOM_GEN])
         {
             *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_FOUND;
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
             return NULL;
         }
@@ -2503,5 +2541,9 @@
             pParent = (PKFSDIR)pChild;
         else
+        {
+            if (ppLastAncestor)
+                *ppLastAncestor = kFsCacheObjRetainInternal(&pParent->Obj);
             return NULL;
+        }
     }
 
@@ -2525,8 +2567,12 @@
  * @param   penmError           Where to return details as to why the lookup
  *                              failed.
- */
-static PKFSOBJ kFsCacheLookupAbsoluteA(PKFSCACHE pCache, const char *pszPath, KU32 cchPath, KFSLOOKUPERROR *penmError)
-{
-    PKFSOBJ     pChild;
+ * @param   ppLastAncestor      Where to return the last parent element found
+ *                              (referenced) in case of error an path/file not
+ *                              found problem.  Optional.
+ */
+static PKFSOBJ kFsCacheLookupAbsoluteA(PKFSCACHE pCache, const char *pszPath, KU32 cchPath,
+                                       KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
+{
+    PKFSOBJ     pRoot;
     KU32        cchSlashes;
     KU32        offEnd;
@@ -2545,9 +2591,9 @@
         offEnd = 2;
         kHlpAssert(IS_SLASH(pszPath[2]));
-        pChild = kFswCacheLookupDrive(pCache, toupper(pszPath[0]), penmError);
+        pRoot = kFswCacheLookupDrive(pCache, toupper(pszPath[0]), penmError);
     }
     else if (   IS_SLASH(pszPath[0])
              && IS_SLASH(pszPath[1]) )
-        pChild = kFswCacheLookupUncShareA(pCache, pszPath, &offEnd, penmError);
+        pRoot = kFswCacheLookupUncShareA(pCache, pszPath, &offEnd, penmError);
     else
     {
@@ -2555,5 +2601,5 @@
         return NULL;
     }
-    if (pChild)
+    if (pRoot)
     { /* likely */ }
     else
@@ -2572,19 +2618,22 @@
     if (offEnd >= cchPath)
     {
-        if (   pChild->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
-            || pChild->uCacheGen == (pChild->bObjType != KFSOBJ_TYPE_MISSING ? pCache->uGeneration : pCache->uGenerationMissing)
-            || kFsCacheRefreshObj(pCache, pChild, penmError))
-            return kFsCacheObjRetainInternal(pChild);
+        if (   pRoot->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+            || pRoot->uCacheGen == (  pRoot->bObjType != KFSOBJ_TYPE_MISSING
+                                    ? pCache->auGenerations[       pRoot->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                    : pCache->auGenerationsMissing[pRoot->fFlags & KFSOBJ_F_USE_CUSTOM_GEN])
+            || kFsCacheRefreshObj(pCache, pRoot, penmError))
+            return kFsCacheObjRetainInternal(pRoot);
         return NULL;
     }
 
     /* Check that we've got a valid result and not a cached negative one. */
-    if (pChild->bObjType == KFSOBJ_TYPE_DIR)
+    if (pRoot->bObjType == KFSOBJ_TYPE_DIR)
     { /* likely */ }
     else
     {
-        kHlpAssert(pChild->bObjType == KFSOBJ_TYPE_MISSING);
-        kHlpAssert(pChild->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE || pChild->uCacheGen == pCache->uGenerationMissing);
-        return pChild;
+        kHlpAssert(pRoot->bObjType == KFSOBJ_TYPE_MISSING);
+        kHlpAssert(   pRoot->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+                   || pRoot->uCacheGen == pCache->auGenerationsMissing[pRoot->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]);
+        return pRoot;
     }
 
@@ -2593,6 +2642,6 @@
      * remainder of the path starting with it.
      */
-    return kFsCacheLookupRelativeToDirA(pCache, (PKFSDIR)pChild, &pszPath[offEnd + cchSlashes],
-                                        cchPath - offEnd - cchSlashes, penmError);
+    return kFsCacheLookupRelativeToDirA(pCache, (PKFSDIR)pRoot, &pszPath[offEnd + cchSlashes],
+                                        cchPath - offEnd - cchSlashes, penmError, ppLastAncestor);
 }
 
@@ -2612,9 +2661,13 @@
  * @param   penmError           Where to return details as to why the lookup
  *                              failed.
- */
-static PKFSOBJ kFsCacheLookupAbsoluteW(PKFSCACHE pCache, const wchar_t *pwszPath, KU32 cwcPath, KFSLOOKUPERROR *penmError)
+ * @param   ppLastAncestor      Where to return the last parent element found
+ *                              (referenced) in case of error an path/file not
+ *                              found problem.  Optional.
+ */
+static PKFSOBJ kFsCacheLookupAbsoluteW(PKFSCACHE pCache, const wchar_t *pwszPath, KU32 cwcPath,
+                                       KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
 {
     PKFSDIR     pParent = &pCache->RootDir;
-    PKFSOBJ     pChild;
+    PKFSOBJ     pRoot;
     KU32        off;
     KU32        cwcSlashes;
@@ -2635,9 +2688,9 @@
         offEnd = 2;
         kHlpAssert(IS_SLASH(pwszPath[2]));
-        pChild = kFswCacheLookupDrive(pCache, toupper(pwszPath[0]), penmError);
+        pRoot = kFswCacheLookupDrive(pCache, toupper(pwszPath[0]), penmError);
     }
     else if (   IS_SLASH(pwszPath[0])
              && IS_SLASH(pwszPath[1]) )
-        pChild = kFswCacheLookupUncShareW(pCache, pwszPath, &offEnd, penmError);
+        pRoot = kFswCacheLookupUncShareW(pCache, pwszPath, &offEnd, penmError);
     else
     {
@@ -2645,5 +2698,5 @@
         return NULL;
     }
-    if (pChild)
+    if (pRoot)
     { /* likely */ }
     else
@@ -2662,19 +2715,22 @@
     if (offEnd >= cwcPath)
     {
-        if (   pChild->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
-            || pChild->uCacheGen == (pChild->bObjType != KFSOBJ_TYPE_MISSING ? pCache->uGeneration : pCache->uGenerationMissing)
-            || kFsCacheRefreshObj(pCache, pChild, penmError))
-            return kFsCacheObjRetainInternal(pChild);
+        if (   pRoot->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+            || pRoot->uCacheGen == (pRoot->bObjType != KFSOBJ_TYPE_MISSING
+                                    ? pCache->auGenerations[       pRoot->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                    : pCache->auGenerationsMissing[pRoot->fFlags & KFSOBJ_F_USE_CUSTOM_GEN])
+            || kFsCacheRefreshObj(pCache, pRoot, penmError))
+            return kFsCacheObjRetainInternal(pRoot);
         return NULL;
     }
 
     /* Check that we've got a valid result and not a cached negative one. */
-    if (pChild->bObjType == KFSOBJ_TYPE_DIR)
+    if (pRoot->bObjType == KFSOBJ_TYPE_DIR)
     { /* likely */ }
     else
     {
-        kHlpAssert(pChild->bObjType == KFSOBJ_TYPE_MISSING);
-        kHlpAssert(pChild->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE || pChild->uCacheGen == pCache->uGenerationMissing);
-        return pChild;
+        kHlpAssert(pRoot->bObjType == KFSOBJ_TYPE_MISSING);
+        kHlpAssert(   pRoot->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
+                   || pRoot->uCacheGen == pCache->auGenerationsMissing[pRoot->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]);
+        return pRoot;
     }
 
@@ -2683,6 +2739,6 @@
      * remainder of the path starting with it.
      */
-    return kFsCacheLookupRelativeToDirW(pCache, (PKFSDIR)pChild, &pwszPath[offEnd + cwcSlashes],
-                                        cwcPath - offEnd - cwcSlashes, penmError);
+    return kFsCacheLookupRelativeToDirW(pCache, (PKFSDIR)pRoot, &pwszPath[offEnd + cwcSlashes],
+                                        cwcPath - offEnd - cwcSlashes, penmError, ppLastAncestor);
 }
 
@@ -2700,6 +2756,10 @@
  * @param   penmError           Where to return details as to why the lookup
  *                              failed.
- */
-static PKFSOBJ kFsCacheLookupSlowA(PKFSCACHE pCache, const char *pszPath, KU32 cchPath, KFSLOOKUPERROR *penmError)
+ * @param   ppLastAncestor      Where to return the last parent element found
+ *                              (referenced) in case of error an path/file not
+ *                              found problem.  Optional.
+ */
+static PKFSOBJ kFsCacheLookupSlowA(PKFSCACHE pCache, const char *pszPath, KU32 cchPath,
+                                   KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
 {
     /*
@@ -2714,5 +2774,5 @@
         PKFSOBJ pFsObj;
         KFSCACHE_LOG2(("kFsCacheLookupSlowA(%s)\n", pszPath));
-        pFsObj = kFsCacheLookupAbsoluteA(pCache, szFull, cchFull, penmError);
+        pFsObj = kFsCacheLookupAbsoluteA(pCache, szFull, cchFull, penmError, ppLastAncestor);
 
 #if 0 /* No need to do this until it's actually queried. */
@@ -2749,6 +2809,10 @@
  * @param   penmError           Where to return details as to why the lookup
  *                              failed.
- */
-static PKFSOBJ kFsCacheLookupSlowW(PKFSCACHE pCache, const wchar_t *pwszPath, KU32 wcwPath, KFSLOOKUPERROR *penmError)
+ * @param   ppLastAncestor      Where to return the last parent element found
+ *                              (referenced) in case of error an path/file not
+ *                              found problem.  Optional.
+ */
+static PKFSOBJ kFsCacheLookupSlowW(PKFSCACHE pCache, const wchar_t *pwszPath, KU32 wcwPath,
+                                   KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor)
 {
     /*
@@ -2763,5 +2827,5 @@
         PKFSOBJ pFsObj;
         KFSCACHE_LOG2(("kFsCacheLookupSlowA(%ls)\n", pwszPath));
-        pFsObj = kFsCacheLookupAbsoluteW(pCache, wszFull, cwcFull, penmError);
+        pFsObj = kFsCacheLookupAbsoluteW(pCache, wszFull, cwcFull, penmError, ppLastAncestor);
 
 #if 0 /* No need to do this until it's actually queried. */
@@ -2796,10 +2860,13 @@
 static PKFSHASHA kFsCacheRefreshPathA(PKFSCACHE pCache, PKFSHASHA pHashEntry, KU32 idxHashTab)
 {
+    PKFSOBJ pLastAncestor = NULL;
     if (!pHashEntry->pFsObj)
     {
         if (pHashEntry->fAbsolute)
-            pHashEntry->pFsObj = kFsCacheLookupAbsoluteA(pCache, pHashEntry->pszPath, pHashEntry->cchPath, &pHashEntry->enmError);
+            pHashEntry->pFsObj = kFsCacheLookupAbsoluteA(pCache, pHashEntry->pszPath, pHashEntry->cchPath,
+                                                         &pHashEntry->enmError, &pLastAncestor);
         else
-            pHashEntry->pFsObj = kFsCacheLookupSlowA(pCache, pHashEntry->pszPath, pHashEntry->cchPath, &pHashEntry->enmError);
+            pHashEntry->pFsObj = kFsCacheLookupSlowA(pCache, pHashEntry->pszPath, pHashEntry->cchPath,
+                                                     &pHashEntry->enmError, &pLastAncestor);
     }
     else
@@ -2816,8 +2883,8 @@
                 if (pHashEntry->fAbsolute)
                     pHashEntry->pFsObj = kFsCacheLookupAbsoluteA(pCache, pHashEntry->pszPath, pHashEntry->cchPath,
-                                                                 &pHashEntry->enmError);
+                                                                 &pHashEntry->enmError, &pLastAncestor);
                 else
                     pHashEntry->pFsObj = kFsCacheLookupSlowA(pCache, pHashEntry->pszPath, pHashEntry->cchPath,
-                                                             &pHashEntry->enmError);
+                                                             &pHashEntry->enmError, &pLastAncestor);
             }
         }
@@ -2830,5 +2897,14 @@
         }
     }
-    pHashEntry->uCacheGen = pCache->uGenerationMissing;
+
+    if (pLastAncestor && !pHashEntry->pFsObj)
+        pHashEntry->idxMissingGen = pLastAncestor->fFlags & KFSOBJ_F_USE_CUSTOM_GEN;
+    pHashEntry->uCacheGen = !pHashEntry->pFsObj
+                          ? pCache->auGenerationsMissing[pHashEntry->idxMissingGen]
+                          : pHashEntry->pFsObj->bObjType == KFSOBJ_TYPE_MISSING
+                          ? pCache->auGenerationsMissing[pHashEntry->pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                          : pCache->auGenerations[       pHashEntry->pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
+    if (pLastAncestor)
+        kFsCacheObjRelease(pCache, pLastAncestor);
     return pHashEntry;
 }
@@ -2845,10 +2921,13 @@
 static PKFSHASHW kFsCacheRefreshPathW(PKFSCACHE pCache, PKFSHASHW pHashEntry, KU32 idxHashTab)
 {
+    PKFSOBJ pLastAncestor = NULL;
     if (!pHashEntry->pFsObj)
     {
         if (pHashEntry->fAbsolute)
-            pHashEntry->pFsObj = kFsCacheLookupAbsoluteW(pCache, pHashEntry->pwszPath, pHashEntry->cwcPath, &pHashEntry->enmError);
+            pHashEntry->pFsObj = kFsCacheLookupAbsoluteW(pCache, pHashEntry->pwszPath, pHashEntry->cwcPath,
+                                                         &pHashEntry->enmError, &pLastAncestor);
         else
-            pHashEntry->pFsObj = kFsCacheLookupSlowW(pCache, pHashEntry->pwszPath, pHashEntry->cwcPath, &pHashEntry->enmError);
+            pHashEntry->pFsObj = kFsCacheLookupSlowW(pCache, pHashEntry->pwszPath, pHashEntry->cwcPath,
+                                                     &pHashEntry->enmError, &pLastAncestor);
     }
     else
@@ -2865,8 +2944,8 @@
                 if (pHashEntry->fAbsolute)
                     pHashEntry->pFsObj = kFsCacheLookupAbsoluteW(pCache, pHashEntry->pwszPath, pHashEntry->cwcPath,
-                                                                 &pHashEntry->enmError);
+                                                                 &pHashEntry->enmError, &pLastAncestor);
                 else
                     pHashEntry->pFsObj = kFsCacheLookupSlowW(pCache, pHashEntry->pwszPath, pHashEntry->cwcPath,
-                                                             &pHashEntry->enmError);
+                                                             &pHashEntry->enmError, &pLastAncestor);
             }
         }
@@ -2879,5 +2958,13 @@
         }
     }
-    pHashEntry->uCacheGen = pCache->uGenerationMissing;
+    if (pLastAncestor && !pHashEntry->pFsObj)
+        pHashEntry->idxMissingGen = pLastAncestor->fFlags & KFSOBJ_F_USE_CUSTOM_GEN;
+    pHashEntry->uCacheGen = !pHashEntry->pFsObj
+                          ? pCache->auGenerationsMissing[pHashEntry->idxMissingGen]
+                          : pHashEntry->pFsObj->bObjType == KFSOBJ_TYPE_MISSING
+                          ? pCache->auGenerationsMissing[pHashEntry->pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                          : pCache->auGenerations[       pHashEntry->pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN];
+    if (pLastAncestor)
+        kFsCacheObjRelease(pCache, pLastAncestor);
     return pHashEntry;
 }
@@ -2922,6 +3009,11 @@
                 && kHlpMemComp(pHashEntry->pszPath, pchPath, cchPath) == 0)
             {
+                PKFSOBJ pFsObj;
                 if (   pHashEntry->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
-                    || pHashEntry->uCacheGen == (pHashEntry->pFsObj ? pCache->uGeneration : pCache->uGenerationMissing)
+                    || pHashEntry->uCacheGen == (  (pFsObj = pHashEntry->pFsObj) != NULL
+                                                 ? pFsObj->bObjType != KFSOBJ_TYPE_MISSING
+                                                   ? pCache->auGenerations[       pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                                   : pCache->auGenerationsMissing[pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                                 : pCache->auGenerationsMissing[pHashEntry->idxMissingGen])
                     || (pHashEntry = kFsCacheRefreshPathA(pCache, pHashEntry, idxHashTab)) )
                 {
@@ -2948,4 +3040,5 @@
         PKFSOBJ pFsObj;
         KBOOL   fAbsolute;
+        PKFSOBJ pLastAncestor = NULL;
 
         /* Is absolute without any '..' bits? */
@@ -2958,10 +3051,10 @@
             && !kFsCacheHasDotDotA(pchPath, cchPath) )
         {
-            pFsObj = kFsCacheLookupAbsoluteA(pCache, pchPath, cchPath, penmError);
+            pFsObj = kFsCacheLookupAbsoluteA(pCache, pchPath, cchPath, penmError, &pLastAncestor);
             fAbsolute = K_TRUE;
         }
         else
         {
-            pFsObj = kFsCacheLookupSlowA(pCache, pchPath, cchPath, penmError);
+            pFsObj = kFsCacheLookupSlowA(pCache, pchPath, cchPath, penmError, &pLastAncestor);
             fAbsolute = K_FALSE;
         }
@@ -2970,5 +3063,8 @@
                 && *penmError != KFSLOOKUPERROR_PATH_TOO_LONG)
             || *penmError == KFSLOOKUPERROR_UNSUPPORTED )
-            kFsCacheCreatePathHashTabEntryA(pCache, pFsObj, pchPath, cchPath, uHashPath, idxHashTab, fAbsolute, *penmError);
+            kFsCacheCreatePathHashTabEntryA(pCache, pFsObj, pchPath, cchPath, uHashPath, idxHashTab, fAbsolute,
+                                            pLastAncestor ? pLastAncestor->bObjType & KFSOBJ_F_USE_CUSTOM_GEN : 0, *penmError);
+        if (pLastAncestor)
+            kFsCacheObjRelease(pCache, pLastAncestor);
 
         pCache->cLookups++;
@@ -3021,6 +3117,11 @@
                 && kHlpMemComp(pHashEntry->pwszPath, pwcPath, cwcPath) == 0)
             {
+                PKFSOBJ pFsObj;
                 if (   pHashEntry->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
-                    || pHashEntry->uCacheGen == (pHashEntry->pFsObj ? pCache->uGeneration : pCache->uGenerationMissing)
+                    || pHashEntry->uCacheGen == ((pFsObj = pHashEntry->pFsObj) != NULL
+                                                 ? pFsObj->bObjType != KFSOBJ_TYPE_MISSING
+                                                   ? pCache->auGenerations[       pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                                   : pCache->auGenerationsMissing[pFsObj->fFlags & KFSOBJ_F_USE_CUSTOM_GEN]
+                                                 : pCache->auGenerationsMissing[pHashEntry->idxMissingGen])
                     || (pHashEntry = kFsCacheRefreshPathW(pCache, pHashEntry, idxHashTab)) )
                 {
@@ -3047,4 +3148,5 @@
         PKFSOBJ pFsObj;
         KBOOL   fAbsolute;
+        PKFSOBJ pLastAncestor = NULL;
 
         /* Is absolute without any '..' bits? */
@@ -3057,10 +3159,10 @@
             && !kFsCacheHasDotDotW(pwcPath, cwcPath) )
         {
-            pFsObj = kFsCacheLookupAbsoluteW(pCache, pwcPath, cwcPath, penmError);
+            pFsObj = kFsCacheLookupAbsoluteW(pCache, pwcPath, cwcPath, penmError, &pLastAncestor);
             fAbsolute = K_TRUE;
         }
         else
         {
-            pFsObj = kFsCacheLookupSlowW(pCache, pwcPath, cwcPath, penmError);
+            pFsObj = kFsCacheLookupSlowW(pCache, pwcPath, cwcPath, penmError, &pLastAncestor);
             fAbsolute = K_FALSE;
         }
@@ -3069,5 +3171,8 @@
                 && *penmError != KFSLOOKUPERROR_PATH_TOO_LONG)
             || *penmError == KFSLOOKUPERROR_UNSUPPORTED )
-            kFsCacheCreatePathHashTabEntryW(pCache, pFsObj, pwcPath, cwcPath, uHashPath, idxHashTab, fAbsolute, *penmError);
+            kFsCacheCreatePathHashTabEntryW(pCache, pFsObj, pwcPath, cwcPath, uHashPath, idxHashTab, fAbsolute,
+                                            pLastAncestor ? pLastAncestor->bObjType & KFSOBJ_F_USE_CUSTOM_GEN : 0, *penmError);
+        if (pLastAncestor)
+            kFsCacheObjRelease(pCache, pLastAncestor);
 
         pCache->cLookups++;
@@ -3739,12 +3844,12 @@
 {
     kHlpAssert(pCache->u32Magic == KFSOBJ_MAGIC);
-    pCache->uGenerationMissing++;
+    pCache->auGenerationsMissing[0]++;
     kHlpAssert(pCache->uGenerationMissing < KU32_MAX);
-    KFSCACHE_LOG(("Invalidate missing %#x\n", pCache->uGenerationMissing));
-}
-
-
-/**
- * Invalidate all cache entries of missing files.
+    KFSCACHE_LOG(("Invalidate missing %#x\n", pCache->auGenerationsMissing[0]));
+}
+
+
+/**
+ * Invalidate all cache entries (regular, custom & missing).
  *
  * @param   pCache      The cache.
@@ -3753,12 +3858,104 @@
 {
     kHlpAssert(pCache->u32Magic == KFSOBJ_MAGIC);
-    pCache->uGenerationMissing++;
-    kHlpAssert(pCache->uGenerationMissing < KU32_MAX);
-    pCache->uGeneration++;
-    kHlpAssert(pCache->uGeneration < KU32_MAX);
-    KFSCACHE_LOG(("Invalidate all %#x/%#x\n", pCache->uGenerationMissing, pCache->uGeneration));
-
-}
-
+
+    pCache->auGenerationsMissing[0]++;
+    kHlpAssert(pCache->auGenerationsMissing[0] < KU32_MAX);
+    pCache->auGenerationsMissing[1]++;
+    kHlpAssert(pCache->auGenerationsMissing[1] < KU32_MAX);
+
+    pCache->auGenerations[0]++;
+    kHlpAssert(pCache->auGenerations[0] < KU32_MAX);
+    pCache->auGenerations[1]++;
+    kHlpAssert(pCache->auGenerations[1] < KU32_MAX);
+
+    KFSCACHE_LOG(("Invalidate all - default: %#x/%#x,  custom: %#x/%#x\n",
+                  pCache->auGenerationsMissing[0], pCache->auGenerations[0],
+                  pCache->auGenerationsMissing[1], pCache->auGenerations[1]));
+}
+
+
+/**
+ * Invalidate all cache entries with custom generation handling set.
+ *
+ * @see     kFsCacheSetupCustomRevisionForTree, KFSOBJ_F_USE_CUSTOM_GEN
+ * @param   pCache      The cache.
+ */
+void kFsCacheInvalidateCustomMissing(PKFSCACHE pCache)
+{
+    kHlpAssert(pCache->u32Magic == KFSOBJ_MAGIC);
+    pCache->auGenerationsMissing[1]++;
+    kHlpAssert(pCache->auGenerationsMissing[1] < KU32_MAX);
+    KFSCACHE_LOG(("Invalidate missing custom %#x\n", pCache->auGenerationsMissing[1]));
+}
+
+
+/**
+ * Invalidate all cache entries with custom generation handling set, both
+ * missing and regular present entries.
+ *
+ * @see     kFsCacheSetupCustomRevisionForTree, KFSOBJ_F_USE_CUSTOM_GEN
+ * @param   pCache      The cache.
+ */
+void kFsCacheInvalidateCustomBoth(PKFSCACHE pCache)
+{
+    kHlpAssert(pCache->u32Magic == KFSOBJ_MAGIC);
+    pCache->auGenerations[1]++;
+    kHlpAssert(pCache->auGenerations[1] < KU32_MAX);
+    pCache->auGenerationsMissing[1]++;
+    kHlpAssert(pCache->auGenerationsMissing[1] < KU32_MAX);
+    KFSCACHE_LOG(("Invalidate both custom %#x/%#x\n", pCache->auGenerationsMissing[1], pCache->auGenerations[1]));
+}
+
+
+
+/**
+ * Applies the given flags to all the objects in a tree.
+ *
+ * @param   pRoot               Where to start applying the flag changes.
+ * @param   fAndMask            The AND mask.
+ * @param   fOrMask             The OR mask.
+ */
+static void kFsCacheApplyFlagsToTree(PKFSDIR pRoot, KU32 fAndMask, KU32 fOrMask)
+{
+    PKFSOBJ    *ppCur = ((PKFSDIR)pRoot)->papChildren;
+    KU32        cLeft = ((PKFSDIR)pRoot)->cChildren;
+    while (cLeft-- > 0)
+    {
+        PKFSOBJ pCur = *ppCur++;
+        if (pCur->bObjType != KFSOBJ_TYPE_DIR)
+            pCur->fFlags = (fAndMask & pCur->fFlags) | fOrMask;
+        else
+            kFsCacheApplyFlagsToTree((PKFSDIR)pCur, fAndMask, fOrMask);
+    }
+
+    pRoot->Obj.fFlags = (fAndMask & pRoot->Obj.fFlags) | fOrMask;
+}
+
+
+/**
+ * Sets up using custom revisioning for the specified directory tree or file.
+ *
+ * There are some restrictions of the current implementation:
+ *      - If the root of the sub-tree is ever deleted from the cache (i.e.
+ *        deleted in real life and reflected in the cache), the setting is lost.
+ *      - It is not automatically applied to the lookup paths caches.
+ *
+ * @returns K_TRUE on success, K_FALSE on failure.
+ * @param   pCache              The cache.
+ * @param   pRoot               The root of the subtree.  A non-directory is
+ *                              fine, like a missing node.
+ */
+KBOOL kFsCacheSetupCustomRevisionForTree(PKFSCACHE pCache, PKFSOBJ pRoot)
+{
+    if (pRoot)
+    {
+        if (pRoot->bObjType == KFSOBJ_TYPE_DIR)
+            kFsCacheApplyFlagsToTree((PKFSDIR)pRoot, KU32_MAX, KFSOBJ_F_USE_CUSTOM_GEN);
+        else
+            pRoot->fFlags |= KFSOBJ_F_USE_CUSTOM_GEN;
+        return K_TRUE;
+    }
+    return K_FALSE;
+}
 
 
@@ -3809,6 +4006,8 @@
             pCache->u32Magic        = KFSCACHE_MAGIC;
             pCache->fFlags          = fFlags;
-            pCache->uGeneration     = KU32_MAX / 2;
-            pCache->uGenerationMissing = 1;
+            pCache->auGenerations[0]        = KU32_MAX / 4;
+            pCache->auGenerations[1]        = KU32_MAX / 32;
+            pCache->auGenerationsMissing[0] = KU32_MAX / 256;
+            pCache->auGenerationsMissing[1] = 1;
             pCache->cObjects        = 1;
             pCache->cbObjects       = sizeof(pCache->RootDir) + pCache->RootDir.cHashTab * sizeof(pCache->RootDir.paHashTab[0]);
Index: /trunk/src/lib/nt/kFsCache.h
===================================================================
--- /trunk/src/lib/nt/kFsCache.h	(revision 2867)
+++ /trunk/src/lib/nt/kFsCache.h	(revision 2868)
@@ -80,10 +80,17 @@
 /** @name KFSOBJ_F_XXX - KFSOBJ::fFlags
  * @{ */
+ /** Use custom generation.
+  * @remarks This is given the value 1, as we use it as an index into
+  *          KFSCACHE::auGenerations, 0 being the default. */
+#define KFSOBJ_F_USE_CUSTOM_GEN         KU32_C(0x00000001)
+
 /** Whether the file system update the modified timestamp of directories
  * when something is removed from it or added to it.
  * @remarks They say NTFS is the only windows filesystem doing this.  */
-#define KFSOBJ_F_WORKING_DIR_MTIME      KU32_C(0x00000001)
+#define KFSOBJ_F_WORKING_DIR_MTIME      KU32_C(0x00000002)
 /** NTFS file system volume. */
 #define KFSOBJ_F_NTFS                   KU32_C(0x80000000)
+/** Flags that are automatically inherited. */
+#define KFSOBJ_F_INHERITED_MASK         KU32_C(0xffffffff)
 /** @} */
 
@@ -304,4 +311,6 @@
     /** Set if aboslute path.   */
     KBOOL               fAbsolute;
+    /** Index into KFSCACHE:auGenerationsMissing when pFsObj is NULL. */
+    KU8                 idxMissingGen;
     /** The cache generation ID. */
     KU32                uCacheGen;
@@ -333,4 +342,6 @@
     /** Set if aboslute path.   */
     KBOOL               fAbsolute;
+    /** Index into KFSCACHE:auGenerationsMissing when pFsObj is NULL. */
+    KU8                 idxMissingGen;
     /** The cache generation ID. */
     KU32                uCacheGen;
@@ -365,8 +376,18 @@
     KU32                fFlags;
 
-    /** The current cache generation for objects that already exists. */
-    KU32                uGeneration;
-    /** The current cache generation for missing objects, negative results, ++. */
-    KU32                uGenerationMissing;
+    /** The default and custom cache generations for stuff that exists, indexed by
+     *  KFSOBJ_F_USE_CUSTOM_GEN.
+     *
+     * The custom generation can be used to invalidate parts of the file system that
+     * are known to be volatile without triggering refreshing of the more static
+     * parts.  Like the 'out' directory in a kBuild setup or a 'TEMP' directory are
+     * expected to change and you need to invalidate the caching of these frequently
+     * to stay on top of things.  Whereas the sources, headers, compilers, sdk,
+     * ddks, windows directory and such generally doesn't change all that often.
+     */
+    KU32                auGenerations[2];
+    /** The current cache generation for missing objects, negative results, ++.
+     * This comes with a custom variant too.  Indexed by KFSOBJ_F_USE_CUSTOM_GEN. */
+    KU32                auGenerationsMissing[2];
 
     /** Number of cache objects. */
@@ -437,7 +458,7 @@
 PKFSOBJ     kFsCacheLookupW(PKFSCACHE pCache, const wchar_t *pwszPath, KFSLOOKUPERROR *penmError);
 PKFSOBJ     kFsCacheLookupRelativeToDirA(PKFSCACHE pCache, PKFSDIR pParent, const char *pszPath, KU32 cchPath,
-                                         KFSLOOKUPERROR *penmError);
+                                         KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor);
 PKFSOBJ     kFsCacheLookupRelativeToDirW(PKFSCACHE pCache, PKFSDIR pParent, const wchar_t *pwszPath, KU32 cwcPath,
-                                         KFSLOOKUPERROR *penmError);
+                                         KFSLOOKUPERROR *penmError, PKFSOBJ *ppLastAncestor);
 PKFSOBJ     kFsCacheLookupWithLengthA(PKFSCACHE pCache, const char *pchPath, KSIZE cchPath, KFSLOOKUPERROR *penmError);
 PKFSOBJ     kFsCacheLookupWithLengthW(PKFSCACHE pCache, const wchar_t *pwcPath, KSIZE cwcPath, KFSLOOKUPERROR *penmError);
@@ -459,6 +480,9 @@
 PKFSCACHE   kFsCacheCreate(KU32 fFlags);
 void        kFsCacheDestroy(PKFSCACHE);
-void        kFsCacheInvalidateMissing(PKFSCACHE pFsCache);
-void        kFsCacheInvalidateAll(PKFSCACHE pFsCache);
-
-#endif
+void        kFsCacheInvalidateMissing(PKFSCACHE pCache);
+void        kFsCacheInvalidateAll(PKFSCACHE pCache);
+void        kFsCacheInvalidateCustomMissing(PKFSCACHE pCache);
+void        kFsCacheInvalidateCustomBoth(PKFSCACHE pCache);
+KBOOL       kFsCacheSetupCustomRevisionForTree(PKFSCACHE pCache, PKFSOBJ pRoot);
+
+#endif
