VirtualBox

Changeset 69959 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Dec 6, 2017 4:48:34 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
119462
Message:

iprt/ntfsvfs.cpp: Implement proper resource cleanup on volume close. Added MFT record / core object caching.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp

    r69943 r69959  
    5656/** The maximum node cache size (in bytes).    */
    5757#if ARCH_BITS >= 64
    58 # define RTFSNTFS_MAX_NODE_CACHE_SIZE        _1M
     58# define RTFSNTFS_MAX_CORE_CACHE_SIZE       _512K
    5959#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
    6167#endif
    6268
     
    208214typedef struct RTFSNTFSCORE
    209215{
     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;
    210220    /** Reference counter.   */
    211221    uint32_t volatile   cRefs;
     222    /** The estimated memory cost of this object. */
     223    uint32_t            cbCost;
    212224    /** Pointer to the volume. */
    213225    PRTFSNTFSVOL        pVol;
     
    421433    uint64_t            uSerialNo;
    422434
     435    /** @name MFT record and core object cache.
     436     * @{ */
    423437    /** The '$Mft' data attribute. */
    424438    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    /** @} */
    425450
    426451    /** @name Allocation bitmap and cache.
     
    437462    void               *pvBitmap;
    438463    /** @} */
    439 
    440     /** Root of the MFT record tree (RTFSNTFSMFTREC). */
    441     AVLU64TREE          MftRoot;
    442464
    443465    /** @name Directory/index related.
     
    473495*   Internal Functions                                                                                                           *
    474496*********************************************************************************************************************************/
     497static uint32_t rtFsNtfsCore_Destroy(PRTFSNTFSCORE pThis);
     498static void     rtFsNtfsIdxVol_TrimCoreObjectCache(PRTFSNTFSVOL pThis);
    475499static uint32_t rtFsNtfsCore_Release(PRTFSNTFSCORE pThis);
    476500static uint32_t rtFsNtfsCore_Retain(PRTFSNTFSCORE pThis);
     
    480504static int      rtFsNtfsVol_NewDirFromShared(PRTFSNTFSVOL pThis, PRTFSNTFSDIRSHRD pSharedDir, PRTVFSDIR phVfsDir);
    481505static uint32_t rtFsNtfsDirShrd_Retain(PRTFSNTFSDIRSHRD pThis);
     506static void     rtFsNtfsIdxVol_TrimIndexNodeCache(PRTFSNTFSVOL pThis);
    482507static uint32_t rtFsNtfsIdxNode_Release(PRTFSNTFSIDXNODE pNode);
    483508static uint32_t rtFsNtfsIdxNode_Retain(PRTFSNTFSIDXNODE pNode);
     
    10931118 * pRec->pCore (with one reference for the caller).
    10941119 *
    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.)
    10961125 *
    10971126 * @returns IPRT status code.
     
    11261155
    11271156    pCore->cRefs    = 1;
     1157    pCore->cbCost   = pThis->cbMftRecord + sizeof(*pCore);
    11281158    pCore->pVol     = pThis;
    11291159    RTListInit(&pCore->AttribHead);
     
    16341664        if (RT_SUCCESS(rc))
    16351665        {
     1666            PRTFSNTFSCORE pCore = pRec->pCore;
    16361667            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;
    16381676            return VINF_SUCCESS;
    16391677        }
    1640         rtFsNtfsCore_Release(pRec->pCore);
     1678
     1679        rtFsNtfsCore_Destroy(pRec->pCore);
    16411680        rtFsNtfsMftRec_Release(pRec, pThis);
    16421681    }
     
    17241763 * Destroys a core structure.
    17251764 *
     1765 * ASSUMES the caller has remove @a pThis from the list it's on and updated the
     1766 * cbCoreObjects as necessary.
     1767 *
    17261768 * @returns 0
    17271769 * @param   pThis               The core structure.
     
    17771819
    17781820/**
     1821 * Trims the core object cache down to RTFSNTFS_MAX_CORE_CACHE_SIZE.
     1822 *
     1823 * @param   pThis               The NTFS volume instance.
     1824 */
     1825static 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/**
    17791839 * Releases a refernece to a core structure, maybe destroying it.
    17801840 *
     
    17901850        if (cRefs != 0)
    17911851            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);
    17931860    }
    17941861    return 0;
     
    18051872{
    18061873    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    }
    18071880    Assert(cRefs < 128);
    18081881    return cRefs;
     
    22032276 */
    22042277static DECLCALLBACK(int) rtFsNtfsFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
    2205                                                  PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
     2278                                               PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
    22062279{
    22072280    RT_NOREF(pvThis, pAccessTime, pModificationTime, pChangeTime, pBirthTime);
     
    22632336
    22642337/**
    2265  * NTFS FS file operations.
    2266  */
    2267 DECL_HIDDEN_CONST(const RTVFSFILEOPS) g_rtFsNtfsFileOps =
     2338 * NTFS file operations.
     2339 */
     2340static const RTVFSFILEOPS g_rtFsNtfsFileOps =
    22682341{
    22692342    { /* Stream */
     
    23672440                        pNewFile->offFile = 0;
    23682441                        pNewFile->pShared = pShared;
     2442                        rtFsNtfsCore_Release(pCore);
    23692443                        return VINF_SUCCESS;
    23702444                    }
     
    28942968static int rtFsNtfsIdxRootInfo_QueryNode(PRTFSNTFSIDXROOTINFO pRootInfo, int64_t iNode, PRTFSNTFSIDXNODE *ppNode)
    28952969{
     2970    PRTFSNTFSVOL pVol = pRootInfo->NodeInfo.pVol;
     2971
    28962972    /*
    28972973     * A bit of paranoia.  These has been checked already when loading, but it
     
    29072983    uint64_t offNode = iNode << pRootInfo->cNodeAddressByteShift;
    29082984    uint64_t offNodeOnDisk = rtFsNtfsAttr_OffsetToDisk(pRootInfo->pAlloc, offNode, NULL);
    2909     PRTFSNTFSIDXNODE pNode = (PRTFSNTFSIDXNODE)RTAvlU64Get(&pRootInfo->NodeInfo.pVol->IdxNodeCacheRoot, offNodeOnDisk);
     2985    PRTFSNTFSIDXNODE pNode = (PRTFSNTFSIDXNODE)RTAvlU64Get(&pVol->IdxNodeCacheRoot, offNodeOnDisk);
    29102986    if (pNode)
    29112987    {
     
    29613037
    29623038                        /*
    2963                          * Insert it into the cache.
     3039                         * Insert it into the cache, trimming the cache if necessary.
    29643040                         */
    2965                         bool fInsertOkay = RTAvlU64Insert(&pRootInfo->NodeInfo.pVol->IdxNodeCacheRoot, &pNode->TreeNode);
     3041                        bool fInsertOkay = RTAvlU64Insert(&pVol->IdxNodeCacheRoot, &pNode->TreeNode);
    29663042                        Assert(fInsertOkay);
    29673043                        if (fInsertOkay)
    29683044                        {
     3045                            pVol->cIdxNodes  += 1;
     3046                            pVol->cbIdxNodes += pNode->cbCost;
     3047                            if (pVol->cbIdxNodes > RTFSNTFS_MAX_CORE_CACHE_SIZE)
     3048                                rtFsNtfsIdxVol_TrimIndexNodeCache(pVol);
     3049
    29693050                            *ppNode = pNode;
    29703051                            return VINF_SUCCESS;
     
    33443425        if (pVol->cbIdxNodes > RTFSNTFS_MAX_NODE_CACHE_SIZE)
    33453426            rtFsNtfsIdxVol_TrimIndexNodeCache(pVol);
    3346         rtFsNtfsIdxVol_TrimIndexNodeCache(pVol);
    33473427        return 0;
    33483428    }
     
    40514131
    40524132/**
    4053  * NTFS file operations.
     4133 * NTFS directory operations.
    40544134 */
    40554135static const RTVFSDIROPS g_rtFsNtfsDirOps =
     
    42284308
    42294309
     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 */
     4318static 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 */
     4340static 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
    42304354
    42314355/**
     
    42354359{
    42364360    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     */
    42384415    RTVfsFileRelease(pThis->hVfsBacking);
    42394416    pThis->hVfsBacking = NIL_RTVFSFILE;
     
    43114488
    43124489
    4313 DECL_HIDDEN_CONST(const RTVFSOPS) g_rtFsNtfsVolOps =
     4490/**
     4491 * NTFS volume operations.
     4492 */
     4493static const RTVFSOPS g_rtFsNtfsVolOps =
    43144494{
    43154495    /* .Obj = */
     
    48315011        if (RT_SUCCESS(rc))
    48325012        {
    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)
    48355017            {
    48365018                /*
    48375019                 * Validate the '$Mft' MFT record.
    48385020                 */
    4839                 if (!pThis->pMftData->pAttrHdr->fNonResident)
     5021                PNTFSATTRIBHDR pAttrHdr = pMftData->pAttrHdr;
     5022                if (!pAttrHdr->fNonResident)
    48405023                    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(pThis->pMftData->pAttrHdr->u.NonRes.cbAllocated) <  pThis->cbMftRecord * 16U
    4842                          || (uint64_t)RT_LE2H_U64(pThis->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)
    48435026                    rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
    48445027                                                 "MFT record #0 unnamed DATA attribute allocated size is out of range: %#RX64",
    4845                                                  RT_LE2H_U64(pThis->pMftData->pAttrHdr->u.NonRes.cbAllocated));
    4846                 else if (   (uint64_t)RT_LE2H_U64(pThis->pMftData->pAttrHdr->u.NonRes.cbInitialized) <  pThis->cbMftRecord * 16U
    4847                          || (uint64_t)RT_LE2H_U64(pThis->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)
    48485031                    rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
    48495032                                                 "MFT record #0 unnamed DATA attribute initialized size is out of range: %#RX64",
    4850                                                  RT_LE2H_U64(pThis->pMftData->pAttrHdr->u.NonRes.cbInitialized));
    4851                 else if (   (uint64_t)RT_LE2H_U64(pThis->pMftData->pAttrHdr->u.NonRes.cbData) <  pThis->cbMftRecord * 16U
    4852                          || (uint64_t)RT_LE2H_U64(pThis->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)
    48535036                    rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
    48545037                                                 "MFT record #0 unnamed DATA attribute allocated size is out of range: %#RX64",
    4855                                                  RT_LE2H_U64(pThis->pMftData->pAttrHdr->u.NonRes.cbData));
    4856                 else if (pThis->pMftData->pAttrHdr->u.NonRes.uCompressionUnit != 0)
     5038                                                 RT_LE2H_U64(pAttrHdr->u.NonRes.cbData));
     5039                else if (pAttrHdr->u.NonRes.uCompressionUnit != 0)
    48575040                    rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
    48585041                                                 "MFT record #0 unnamed DATA attribute is compressed: %#x",
    4859                                                  pThis->pMftData->pAttrHdr->u.NonRes.uCompressionUnit);
    4860                 else if (pThis->pMftData->Extents.cExtents == 0)
     5042                                                 pAttrHdr->u.NonRes.uCompressionUnit);
     5043                else if (pMftData->Extents.cExtents == 0)
    48615044                    rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT,
    48625045                                               "MFT record #0 unnamed DATA attribute has no data on the disk");
    4863                 else if (pThis->pMftData->Extents.paExtents[0].off != offDisk)
     5046                else if (pMftData->Extents.paExtents[0].off != offDisk)
    48645047                    rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
    48655048                                                 "MFT record #0 unnamed DATA attribute has a bogus disk offset: %#RX64, expected %#RX64",
    4866                                                  pThis->pMftData->Extents.paExtents[0].off, offDisk);
    4867                 else if (!rtFsNtfsCore_FindUnnamedAttribute(pRec->pCore, NTFS_AT_BITMAP))
     5049                                                 pMftData->Extents.paExtents[0].off, offDisk);
     5050                else if (!rtFsNtfsCore_FindUnnamedAttribute(pCore, NTFS_AT_BITMAP))
    48685051                    rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "MFT record #0 has no unnamed BITMAP attribute!");
    48695052                else
    48705053                {
    4871                     PRTFSNTFSATTR pFilenameAttr = rtFsNtfsCore_FindUnnamedAttribute(pRec->pCore, NTFS_AT_FILENAME);
     5054                    PRTFSNTFSATTR pFilenameAttr = rtFsNtfsCore_FindUnnamedAttribute(pCore, NTFS_AT_FILENAME);
    48725055                    if (!pFilenameAttr)
    48735056                        rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "MFT record #0 has no FILENAME attribute!");
     
    48905073                        {
    48915074                            /*
    4892                              * Looks like we're good.
     5075                             * Looks like we're good.  Insert core record into the cache.
    48935076                             */
     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
    48945084                            return VINF_SUCCESS;
    48955085                        }
     
    49015091                rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "MFT record #0 has no unnamed DATA attribute!");
    49025092        }
    4903         rtFsNtfsCore_Release(pRec->pCore);
     5093        rtFsNtfsCore_Destroy(pRec->pCore);
    49045094        rtFsNtfsMftRec_Release(pRec, pThis);
    49055095    }
     
    50845274        pThis->fMntFlags      = fMntFlags;
    50855275        pThis->fNtfsFlags     = fNtfsFlags;
     5276        RTListInit(&pThis->CoreInUseHead);
     5277        RTListInit(&pThis->CoreUnusedHead);
    50865278        RTListInit(&pThis->IdxNodeUnusedHead);
    50875279
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette