Changeset 69959 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Dec 6, 2017 4:48:34 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 119462
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp
r69943 r69959 56 56 /** The maximum node cache size (in bytes). */ 57 57 #if ARCH_BITS >= 64 58 # define RTFSNTFS_MAX_ NODE_CACHE_SIZE _1M58 # define RTFSNTFS_MAX_CORE_CACHE_SIZE _512K 59 59 #else 60 # define RTFSNTFS_MAX_NODE_CACHE_SIZE _256K 60 # define RTFSNTFS_MAX_CORE_CACHE_SIZE _128K 61 #endif 62 /** The maximum node cache size (in bytes). */ 63 #if ARCH_BITS >= 64 64 # define RTFSNTFS_MAX_NODE_CACHE_SIZE _1M 65 #else 66 # define RTFSNTFS_MAX_NODE_CACHE_SIZE _256K 61 67 #endif 62 68 … … 208 214 typedef struct RTFSNTFSCORE 209 215 { 216 /** Entry in either the RTFSNTFSVOL::CoreInUseHead or CoreUnusedHead. 217 * Instances is moved to/from CoreUnusedHead as cRefs reaches zero and one 218 * respectively. */ 219 RTLISTNODE ListEntry; 210 220 /** Reference counter. */ 211 221 uint32_t volatile cRefs; 222 /** The estimated memory cost of this object. */ 223 uint32_t cbCost; 212 224 /** Pointer to the volume. */ 213 225 PRTFSNTFSVOL pVol; … … 421 433 uint64_t uSerialNo; 422 434 435 /** @name MFT record and core object cache. 436 * @{ */ 423 437 /** The '$Mft' data attribute. */ 424 438 PRTFSNTFSATTR pMftData; 439 /** Root of the MFT record tree (RTFSNTFSMFTREC). */ 440 AVLU64TREE MftRoot; 441 /** List of in use core objects (RTFSNTFSCORE::cRefs > 0). (RTFSNTFSCORE) */ 442 RTLISTANCHOR CoreInUseHead; 443 /** List of unused core objects (RTFSNTFSCORE::cRefs == 0). (RTFSNTFSCORE) 444 * The most recently used nodes are found at the of the list. So, when 445 * cbCoreObjects gets to high, we remove and destroy objects from the tail. */ 446 RTLISTANCHOR CoreUnusedHead; 447 /** Total core object memory cost (sum of all RTFSNTFSCORE::cbCost). */ 448 size_t cbCoreObjects; 449 /** @} */ 425 450 426 451 /** @name Allocation bitmap and cache. … … 437 462 void *pvBitmap; 438 463 /** @} */ 439 440 /** Root of the MFT record tree (RTFSNTFSMFTREC). */441 AVLU64TREE MftRoot;442 464 443 465 /** @name Directory/index related. … … 473 495 * Internal Functions * 474 496 *********************************************************************************************************************************/ 497 static uint32_t rtFsNtfsCore_Destroy(PRTFSNTFSCORE pThis); 498 static void rtFsNtfsIdxVol_TrimCoreObjectCache(PRTFSNTFSVOL pThis); 475 499 static uint32_t rtFsNtfsCore_Release(PRTFSNTFSCORE pThis); 476 500 static uint32_t rtFsNtfsCore_Retain(PRTFSNTFSCORE pThis); … … 480 504 static int rtFsNtfsVol_NewDirFromShared(PRTFSNTFSVOL pThis, PRTFSNTFSDIRSHRD pSharedDir, PRTVFSDIR phVfsDir); 481 505 static uint32_t rtFsNtfsDirShrd_Retain(PRTFSNTFSDIRSHRD pThis); 506 static void rtFsNtfsIdxVol_TrimIndexNodeCache(PRTFSNTFSVOL pThis); 482 507 static uint32_t rtFsNtfsIdxNode_Release(PRTFSNTFSIDXNODE pNode); 483 508 static uint32_t rtFsNtfsIdxNode_Retain(PRTFSNTFSIDXNODE pNode); … … 1093 1118 * pRec->pCore (with one reference for the caller). 1094 1119 * 1095 * ASSUMES caller will release pRec->pCore on failure. 1120 * ASSUMES caller will insert pRec->pCore into the CoreInUseHead list on 1121 * success, and destroy it on failure. It is better to have caller do the 1122 * inserting/destroy, since we don't want to cache a failed parsing attempt. 1123 * (It is also preferable to add RTFSNTFSCORE::cbCost once it's fully calculated 1124 * and in the place as the insertion.) 1096 1125 * 1097 1126 * @returns IPRT status code. … … 1126 1155 1127 1156 pCore->cRefs = 1; 1157 pCore->cbCost = pThis->cbMftRecord + sizeof(*pCore); 1128 1158 pCore->pVol = pThis; 1129 1159 RTListInit(&pCore->AttribHead); … … 1634 1664 if (RT_SUCCESS(rc)) 1635 1665 { 1666 PRTFSNTFSCORE pCore = pRec->pCore; 1636 1667 rtFsNtfsMftRec_Release(pRec, pThis); 1637 *ppCore = pRec->pCore; 1668 1669 /* Insert core into the cache list and update the cost, maybe trimming the cache. */ 1670 RTListAppend(&pThis->CoreInUseHead, &pCore->ListEntry); 1671 pThis->cbCoreObjects += pCore->cbCost; 1672 if (pThis->cbCoreObjects > RTFSNTFS_MAX_CORE_CACHE_SIZE) 1673 rtFsNtfsIdxVol_TrimCoreObjectCache(pThis); 1674 1675 *ppCore = pCore; 1638 1676 return VINF_SUCCESS; 1639 1677 } 1640 rtFsNtfsCore_Release(pRec->pCore); 1678 1679 rtFsNtfsCore_Destroy(pRec->pCore); 1641 1680 rtFsNtfsMftRec_Release(pRec, pThis); 1642 1681 } … … 1724 1763 * Destroys a core structure. 1725 1764 * 1765 * ASSUMES the caller has remove @a pThis from the list it's on and updated the 1766 * cbCoreObjects as necessary. 1767 * 1726 1768 * @returns 0 1727 1769 * @param pThis The core structure. … … 1777 1819 1778 1820 /** 1821 * Trims the core object cache down to RTFSNTFS_MAX_CORE_CACHE_SIZE. 1822 * 1823 * @param pThis The NTFS volume instance. 1824 */ 1825 static void rtFsNtfsIdxVol_TrimCoreObjectCache(PRTFSNTFSVOL pThis) 1826 { 1827 while (pThis->cbCoreObjects > RTFSNTFS_MAX_CORE_CACHE_SIZE) 1828 { 1829 PRTFSNTFSCORE pCore = RTListRemoveFirst(&pThis->CoreUnusedHead, RTFSNTFSCORE, ListEntry); 1830 if (!pCore) 1831 break; 1832 pThis->cbCoreObjects -= pCore->cbCost; 1833 rtFsNtfsCore_Destroy(pCore); 1834 } 1835 } 1836 1837 1838 /** 1779 1839 * Releases a refernece to a core structure, maybe destroying it. 1780 1840 * … … 1790 1850 if (cRefs != 0) 1791 1851 return cRefs; 1792 return rtFsNtfsCore_Destroy(pThis); 1852 1853 /* Move from in-use list to unused list. Trim the cache if too big. */ 1854 RTListNodeRemove(&pThis->ListEntry); 1855 1856 PRTFSNTFSVOL pVol = pThis->pVol; 1857 RTListAppend(&pVol->CoreUnusedHead, &pThis->ListEntry); 1858 if (pVol->cbCoreObjects > RTFSNTFS_MAX_CORE_CACHE_SIZE) 1859 rtFsNtfsIdxVol_TrimCoreObjectCache(pVol); 1793 1860 } 1794 1861 return 0; … … 1805 1872 { 1806 1873 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs); 1874 if (cRefs == 1) 1875 { 1876 /* Move from unused list to in-use list. */ 1877 RTListNodeRemove(&pThis->ListEntry); 1878 RTListAppend(&pThis->pVol->CoreInUseHead, &pThis->ListEntry); 1879 } 1807 1880 Assert(cRefs < 128); 1808 1881 return cRefs; … … 2203 2276 */ 2204 2277 static DECLCALLBACK(int) rtFsNtfsFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime, 2205 2278 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime) 2206 2279 { 2207 2280 RT_NOREF(pvThis, pAccessTime, pModificationTime, pChangeTime, pBirthTime); … … 2263 2336 2264 2337 /** 2265 * NTFS FSfile operations.2266 */ 2267 DECL_HIDDEN_CONST(const RTVFSFILEOPS)g_rtFsNtfsFileOps =2338 * NTFS file operations. 2339 */ 2340 static const RTVFSFILEOPS g_rtFsNtfsFileOps = 2268 2341 { 2269 2342 { /* Stream */ … … 2367 2440 pNewFile->offFile = 0; 2368 2441 pNewFile->pShared = pShared; 2442 rtFsNtfsCore_Release(pCore); 2369 2443 return VINF_SUCCESS; 2370 2444 } … … 2894 2968 static int rtFsNtfsIdxRootInfo_QueryNode(PRTFSNTFSIDXROOTINFO pRootInfo, int64_t iNode, PRTFSNTFSIDXNODE *ppNode) 2895 2969 { 2970 PRTFSNTFSVOL pVol = pRootInfo->NodeInfo.pVol; 2971 2896 2972 /* 2897 2973 * A bit of paranoia. These has been checked already when loading, but it … … 2907 2983 uint64_t offNode = iNode << pRootInfo->cNodeAddressByteShift; 2908 2984 uint64_t offNodeOnDisk = rtFsNtfsAttr_OffsetToDisk(pRootInfo->pAlloc, offNode, NULL); 2909 PRTFSNTFSIDXNODE pNode = (PRTFSNTFSIDXNODE)RTAvlU64Get(&p RootInfo->NodeInfo.pVol->IdxNodeCacheRoot, offNodeOnDisk);2985 PRTFSNTFSIDXNODE pNode = (PRTFSNTFSIDXNODE)RTAvlU64Get(&pVol->IdxNodeCacheRoot, offNodeOnDisk); 2910 2986 if (pNode) 2911 2987 { … … 2961 3037 2962 3038 /* 2963 * Insert it into the cache .3039 * Insert it into the cache, trimming the cache if necessary. 2964 3040 */ 2965 bool fInsertOkay = RTAvlU64Insert(&p RootInfo->NodeInfo.pVol->IdxNodeCacheRoot, &pNode->TreeNode);3041 bool fInsertOkay = RTAvlU64Insert(&pVol->IdxNodeCacheRoot, &pNode->TreeNode); 2966 3042 Assert(fInsertOkay); 2967 3043 if (fInsertOkay) 2968 3044 { 3045 pVol->cIdxNodes += 1; 3046 pVol->cbIdxNodes += pNode->cbCost; 3047 if (pVol->cbIdxNodes > RTFSNTFS_MAX_CORE_CACHE_SIZE) 3048 rtFsNtfsIdxVol_TrimIndexNodeCache(pVol); 3049 2969 3050 *ppNode = pNode; 2970 3051 return VINF_SUCCESS; … … 3344 3425 if (pVol->cbIdxNodes > RTFSNTFS_MAX_NODE_CACHE_SIZE) 3345 3426 rtFsNtfsIdxVol_TrimIndexNodeCache(pVol); 3346 rtFsNtfsIdxVol_TrimIndexNodeCache(pVol);3347 3427 return 0; 3348 3428 } … … 4051 4131 4052 4132 /** 4053 * NTFS fileoperations.4133 * NTFS directory operations. 4054 4134 */ 4055 4135 static const RTVFSDIROPS g_rtFsNtfsDirOps = … … 4228 4308 4229 4309 4310 /** 4311 * Callback for RTAvlU64Destroy used by rtFsNtfsVol_Close to destroy the MFT 4312 * record cache. 4313 * 4314 * @returns VINF_SUCCESS 4315 * @param pNode The MFT record to destroy. 4316 * @param pvUser Ignored. 4317 */ 4318 static DECLCALLBACK(int) rtFsNtFsVol_DestroyCachedMftRecord(PAVLU64NODECORE pNode, void *pvUser) 4319 { 4320 PRTFSNTFSMFTREC pMftRec = (PRTFSNTFSMFTREC)pNode; 4321 RT_NOREF(pvUser); 4322 4323 RTMemFree(pMftRec->pbRec); 4324 pMftRec->pbRec = NULL; 4325 RTMemFree(pMftRec); 4326 4327 return VINF_SUCCESS; 4328 } 4329 4330 4331 4332 /** 4333 * Callback for RTAvlU64Destroy used by rtFsNtfsVol_Close to destroy the index 4334 * node cache. 4335 * 4336 * @returns VINF_SUCCESS 4337 * @param pNode The index node to destroy. 4338 * @param pvUser Ignored. 4339 */ 4340 static DECLCALLBACK(int) rtFsNtfsVol_DestroyIndexNode(PAVLU64NODECORE pNode, void *pvUser) 4341 { 4342 PRTFSNTFSIDXNODE pIdxNode = (PRTFSNTFSIDXNODE)pNode; 4343 RT_NOREF(pvUser); 4344 4345 RTMemFree(pIdxNode->pNode); 4346 RTMemFree(pIdxNode->NodeInfo.papEntries); 4347 pIdxNode->pNode = NULL; 4348 pIdxNode->NodeInfo.papEntries = NULL; 4349 pIdxNode->NodeInfo.pIndexHdr = NULL; 4350 pIdxNode->NodeInfo.pVol = NULL; 4351 return VINF_SUCCESS; 4352 } 4353 4230 4354 4231 4355 /** … … 4235 4359 { 4236 4360 PRTFSNTFSVOL pThis = (PRTFSNTFSVOL)pvThis; 4237 4361 Log(("rtFsNtfsVol_Close(%p):\n", pThis)); 4362 4363 /* 4364 * Index / directory related members. 4365 */ 4366 if (pThis->pRootDir) 4367 { 4368 rtFsNtfsDirShrd_Release(pThis->pRootDir); 4369 pThis->pRootDir = NULL; 4370 } 4371 4372 RTAvlU64Destroy(&pThis->IdxNodeCacheRoot, rtFsNtfsVol_DestroyIndexNode, NULL); 4373 4374 RTMemFree(pThis->pawcUpcase); 4375 pThis->pawcUpcase = NULL; 4376 4377 pThis->IdxNodeUnusedHead.pPrev = pThis->IdxNodeUnusedHead.pNext = NULL; 4378 4379 /* 4380 * Allocation bitmap cache. 4381 */ 4382 if (pThis->pMftBitmap) 4383 { 4384 rtFsNtfsCore_Release(pThis->pMftBitmap->pCore); 4385 pThis->pMftBitmap = NULL; 4386 } 4387 RTMemFree(pThis->pvBitmap); 4388 pThis->pvBitmap = NULL; 4389 4390 /* 4391 * The MFT and MFT cache. 4392 */ 4393 if (pThis->pMftData) 4394 { 4395 rtFsNtfsCore_Release(pThis->pMftData->pCore); 4396 pThis->pMftData = NULL; 4397 } 4398 4399 Assert(RTListIsEmpty(&pThis->CoreInUseHead)); 4400 PRTFSNTFSCORE pCurCore, pNextCore; 4401 RTListForEachSafe(&pThis->CoreInUseHead, pCurCore, pNextCore, RTFSNTFSCORE, ListEntry) 4402 rtFsNtfsCore_Destroy(pCurCore); 4403 RTListForEachSafe(&pThis->CoreUnusedHead, pCurCore, pNextCore, RTFSNTFSCORE, ListEntry) 4404 rtFsNtfsCore_Destroy(pCurCore); 4405 4406 pThis->CoreInUseHead.pPrev = pThis->CoreInUseHead.pNext = NULL; 4407 pThis->CoreUnusedHead.pPrev = pThis->CoreUnusedHead.pNext = NULL; 4408 4409 Assert(pThis->MftRoot == NULL); 4410 RTAvlU64Destroy(&pThis->MftRoot, rtFsNtFsVol_DestroyCachedMftRecord, NULL); 4411 4412 /* 4413 * Backing file and handles. 4414 */ 4238 4415 RTVfsFileRelease(pThis->hVfsBacking); 4239 4416 pThis->hVfsBacking = NIL_RTVFSFILE; … … 4311 4488 4312 4489 4313 DECL_HIDDEN_CONST(const RTVFSOPS) g_rtFsNtfsVolOps = 4490 /** 4491 * NTFS volume operations. 4492 */ 4493 static const RTVFSOPS g_rtFsNtfsVolOps = 4314 4494 { 4315 4495 /* .Obj = */ … … 4831 5011 if (RT_SUCCESS(rc)) 4832 5012 { 4833 pThis->pMftData = rtFsNtfsCore_FindUnnamedAttribute(pRec->pCore, NTFS_AT_DATA); 4834 if (pThis->pMftData) 5013 PRTFSNTFSCORE pCore = pRec->pCore; 5014 PRTFSNTFSATTR pMftData; 5015 pThis->pMftData = pMftData = rtFsNtfsCore_FindUnnamedAttribute(pCore, NTFS_AT_DATA); 5016 if (pMftData) 4835 5017 { 4836 5018 /* 4837 5019 * Validate the '$Mft' MFT record. 4838 5020 */ 4839 if (!pThis->pMftData->pAttrHdr->fNonResident) 5021 PNTFSATTRIBHDR pAttrHdr = pMftData->pAttrHdr; 5022 if (!pAttrHdr->fNonResident) 4840 5023 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "MFT record #0 unnamed DATA attribute is resident!"); 4841 else if ( (uint64_t)RT_LE2H_U64(p This->pMftData->pAttrHdr->u.NonRes.cbAllocated) < pThis->cbMftRecord * 16U4842 || (uint64_t)RT_LE2H_U64(p This->pMftData->pAttrHdr->u.NonRes.cbAllocated) >= pThis->cbBacking)5024 else if ( (uint64_t)RT_LE2H_U64(pAttrHdr->u.NonRes.cbAllocated) < pThis->cbMftRecord * 16U 5025 || (uint64_t)RT_LE2H_U64(pAttrHdr->u.NonRes.cbAllocated) >= pThis->cbBacking) 4843 5026 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 4844 5027 "MFT record #0 unnamed DATA attribute allocated size is out of range: %#RX64", 4845 RT_LE2H_U64(p This->pMftData->pAttrHdr->u.NonRes.cbAllocated));4846 else if ( (uint64_t)RT_LE2H_U64(p This->pMftData->pAttrHdr->u.NonRes.cbInitialized) < pThis->cbMftRecord * 16U4847 || (uint64_t)RT_LE2H_U64(p This->pMftData->pAttrHdr->u.NonRes.cbInitialized) >= pThis->cbBacking)5028 RT_LE2H_U64(pAttrHdr->u.NonRes.cbAllocated)); 5029 else if ( (uint64_t)RT_LE2H_U64(pAttrHdr->u.NonRes.cbInitialized) < pThis->cbMftRecord * 16U 5030 || (uint64_t)RT_LE2H_U64(pAttrHdr->u.NonRes.cbInitialized) >= pThis->cbBacking) 4848 5031 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 4849 5032 "MFT record #0 unnamed DATA attribute initialized size is out of range: %#RX64", 4850 RT_LE2H_U64(p This->pMftData->pAttrHdr->u.NonRes.cbInitialized));4851 else if ( (uint64_t)RT_LE2H_U64(p This->pMftData->pAttrHdr->u.NonRes.cbData) < pThis->cbMftRecord * 16U4852 || (uint64_t)RT_LE2H_U64(p This->pMftData->pAttrHdr->u.NonRes.cbData) >= pThis->cbBacking)5033 RT_LE2H_U64(pAttrHdr->u.NonRes.cbInitialized)); 5034 else if ( (uint64_t)RT_LE2H_U64(pAttrHdr->u.NonRes.cbData) < pThis->cbMftRecord * 16U 5035 || (uint64_t)RT_LE2H_U64(pAttrHdr->u.NonRes.cbData) >= pThis->cbBacking) 4853 5036 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 4854 5037 "MFT record #0 unnamed DATA attribute allocated size is out of range: %#RX64", 4855 RT_LE2H_U64(p This->pMftData->pAttrHdr->u.NonRes.cbData));4856 else if (p This->pMftData->pAttrHdr->u.NonRes.uCompressionUnit != 0)5038 RT_LE2H_U64(pAttrHdr->u.NonRes.cbData)); 5039 else if (pAttrHdr->u.NonRes.uCompressionUnit != 0) 4857 5040 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 4858 5041 "MFT record #0 unnamed DATA attribute is compressed: %#x", 4859 p This->pMftData->pAttrHdr->u.NonRes.uCompressionUnit);4860 else if (p This->pMftData->Extents.cExtents == 0)5042 pAttrHdr->u.NonRes.uCompressionUnit); 5043 else if (pMftData->Extents.cExtents == 0) 4861 5044 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, 4862 5045 "MFT record #0 unnamed DATA attribute has no data on the disk"); 4863 else if (p This->pMftData->Extents.paExtents[0].off != offDisk)5046 else if (pMftData->Extents.paExtents[0].off != offDisk) 4864 5047 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 4865 5048 "MFT record #0 unnamed DATA attribute has a bogus disk offset: %#RX64, expected %#RX64", 4866 p This->pMftData->Extents.paExtents[0].off, offDisk);4867 else if (!rtFsNtfsCore_FindUnnamedAttribute(p Rec->pCore, NTFS_AT_BITMAP))5049 pMftData->Extents.paExtents[0].off, offDisk); 5050 else if (!rtFsNtfsCore_FindUnnamedAttribute(pCore, NTFS_AT_BITMAP)) 4868 5051 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "MFT record #0 has no unnamed BITMAP attribute!"); 4869 5052 else 4870 5053 { 4871 PRTFSNTFSATTR pFilenameAttr = rtFsNtfsCore_FindUnnamedAttribute(p Rec->pCore, NTFS_AT_FILENAME);5054 PRTFSNTFSATTR pFilenameAttr = rtFsNtfsCore_FindUnnamedAttribute(pCore, NTFS_AT_FILENAME); 4872 5055 if (!pFilenameAttr) 4873 5056 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "MFT record #0 has no FILENAME attribute!"); … … 4890 5073 { 4891 5074 /* 4892 * Looks like we're good. 5075 * Looks like we're good. Insert core record into the cache. 4893 5076 */ 5077 RTListAppend(&pThis->CoreInUseHead, &pCore->ListEntry); 5078 pThis->cbCoreObjects += pCore->cbCost; 5079 5080 Assert(pCore->cRefs == 1); 5081 Assert(pRec->cRefs == 2); 5082 rtFsNtfsMftRec_Release(pRec, pThis); 5083 4894 5084 return VINF_SUCCESS; 4895 5085 } … … 4901 5091 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "MFT record #0 has no unnamed DATA attribute!"); 4902 5092 } 4903 rtFsNtfsCore_ Release(pRec->pCore);5093 rtFsNtfsCore_Destroy(pRec->pCore); 4904 5094 rtFsNtfsMftRec_Release(pRec, pThis); 4905 5095 } … … 5084 5274 pThis->fMntFlags = fMntFlags; 5085 5275 pThis->fNtfsFlags = fNtfsFlags; 5276 RTListInit(&pThis->CoreInUseHead); 5277 RTListInit(&pThis->CoreUnusedHead); 5086 5278 RTListInit(&pThis->IdxNodeUnusedHead); 5087 5279
Note:
See TracChangeset
for help on using the changeset viewer.