VirtualBox

Ignore:
Timestamp:
Jan 26, 2019 6:54:44 PM (6 years ago)
Author:
vboxsync
Message:

Runtime/xfsvfs.cpp: Updates

File:
1 edited

Legend:

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

    r76642 r77008  
    112112    /** Inode flags. */
    113113    uint16_t          fFlags;
     114    /** Inode version. */
     115    uint8_t           uVersion;
     116    /** Number of extents in the data fork for XFS_INODE_FORMAT_EXTENTS. */
     117    uint32_t          cExtentsData;
     118    /** Raw inode data. */
     119    uint8_t           abData[1];
    114120} RTFSXFSINODE;
    115121/** Pointer to an in-memory inode. */
     
    329335}
    330336
    331 
     337#if 0 /* unused */
    332338/**
    333339 * Logs a AG free space block.
     
    367373    }
    368374}
    369 
     375#endif
    370376
    371377/**
     
    541547
    542548/**
     549 * Returns the size of the core inode structure on disk for the given version.
     550 *
     551 * @returns Size of the on disk inode structure in bytes.
     552 * @param   uVersion            The inode version.
     553 */
     554DECLINLINE(size_t) rtFsXfsInodeGetSz(uint8_t uVersion)
     555{
     556    if (uVersion < 3)
     557        return RT_OFFSETOF(XFSINODECORE, uChkSum);
     558    return sizeof(XFSINODECORE);
     559}
     560
     561
     562/**
     563 * Returns the pointer to the data fork of the given inode.
     564 *
     565 * @returns Pointer to the data fork.
     566 * @param   pThis               The XFS volume instance.
     567 * @param   pInode              The inode to get the data fork for.
     568 * @param   pcb                 Where to store the size of the remaining data area beginning with the fork.
     569 */
     570DECLINLINE(void *) rtFsXfsInodeGetDataFork(PRTFSXFSVOL pThis, PRTFSXFSINODE pInode, size_t *pcb)
     571{
     572    size_t offDataFork = rtFsXfsInodeGetSz(pInode->uVersion);
     573    size_t cbInodeData = pThis->cbInode - offDataFork;
     574    if (pcb)
     575        *pcb = cbInodeData;
     576
     577    return &pInode->abData[offDataFork];
     578}
     579
     580
     581/**
    543582 * Allocates a new block group.
    544583 *
     
    696735}
    697736
    698 
     737#if 0 /* unused */
    699738/**
    700739 * Allocates a new alloction group.
     
    850889        rtFsXfsAg_Free(pThis, pAg);
    851890}
    852 
     891#endif
    853892
    854893/**
     
    861900static PRTFSXFSINODE rtFsXfsInode_Alloc(PRTFSXFSVOL pThis, uint32_t iInode)
    862901{
    863     PRTFSXFSINODE pInode = (PRTFSXFSINODE)RTMemAllocZ(sizeof(RTFSXFSINODE));
     902    size_t cbAlloc = RT_UOFFSETOF_DYN(RTFSXFSINODE, abData[pThis->cbInode]);
     903    PRTFSXFSINODE pInode = (PRTFSXFSINODE)RTMemAllocZ(cbAlloc);
    864904    if (RT_LIKELY(pInode))
    865905    {
    866906        pInode->Core.Key = iInode;
    867907        pInode->cRefs    = 0;
    868         pThis->cbInodes  += sizeof(RTFSXFSINODE);
     908        pThis->cbInodes  += cbAlloc;
    869909    }
    870910
     
    899939        Assert(pCore == &pInode->Core); RT_NOREF(pCore);
    900940        RTMemFree(pInode);
    901         pThis->cbInodes -= sizeof(RTFSXFSINODE);
     941        pThis->cbInodes -= RT_UOFFSETOF_DYN(RTFSXFSINODE, abData[pThis->cbInode]);
    902942    }
    903943}
     
    914954{
    915955    PRTFSXFSINODE pInode = NULL;
    916     if (pThis->cbInodes + sizeof(RTFSXFSINODE) <= RTFSXFS_MAX_INODE_CACHE_SIZE)
     956    if (pThis->cbInodes + RT_UOFFSETOF_DYN(RTFSXFSINODE, abData[pThis->cbInode]) <= RTFSXFS_MAX_INODE_CACHE_SIZE)
    917957        pInode = rtFsXfsInode_Alloc(pThis, iInode);
    918958    else
     
    9641004
    9651005            uint64_t offRead = (iAg * pThis->cBlocksPerAg + uBlock) * pThis->cbBlock + offBlock;
    966             XFSINODECORE Inode;
    967             rc = RTVfsFileReadAt(pThis->hVfsBacking, offRead, &Inode, RT_MIN(sizeof(Inode), pThis->cbInode), NULL);
     1006            rc = RTVfsFileReadAt(pThis->hVfsBacking, offRead, &pInode->abData[0], pThis->cbInode, NULL);
    9681007            if (RT_SUCCESS(rc))
    9691008            {
     1009                PCXFSINODECORE pInodeCore = (PCXFSINODECORE)&pInode->abData[0];
     1010
    9701011#ifdef LOG_ENABLED
    971                 rtFsXfsInode_Log(pThis, iInode, &Inode);
     1012                rtFsXfsInode_Log(pThis, iInode, pInodeCore);
    9721013#endif
    9731014
    9741015                pInode->offInode            = offRead;
    975                 pInode->fFlags              = RT_BE2H_U16(Inode.fFlags);
    976                 pInode->enmFormat           = Inode.enmFormat;
    977                 pInode->ObjInfo.cbObject    = RT_BE2H_U64(Inode.cbInode);
    978                 pInode->ObjInfo.cbAllocated = RT_BE2H_U64(Inode.cBlocks) * pThis->cbBlock;
    979                 RTTimeSpecSetSeconds(&pInode->ObjInfo.AccessTime, RT_BE2H_U32(Inode.TsLastAccessed.cSecEpoch));
    980                 RTTimeSpecAddNano(&pInode->ObjInfo.AccessTime, RT_BE2H_U32(Inode.TsLastAccessed.cNanoSec));
    981                 RTTimeSpecSetSeconds(&pInode->ObjInfo.ModificationTime, RT_BE2H_U32(Inode.TsLastModified.cSecEpoch));
    982                 RTTimeSpecAddNano(&pInode->ObjInfo.ModificationTime, RT_BE2H_U32(Inode.TsLastModified.cNanoSec));
    983                 RTTimeSpecSetSeconds(&pInode->ObjInfo.ChangeTime, RT_BE2H_U32(Inode.TsCreatedModified.cSecEpoch));
    984                 RTTimeSpecAddNano(&pInode->ObjInfo.ChangeTime, RT_BE2H_U32(Inode.TsCreatedModified.cNanoSec));
     1016                pInode->fFlags              = RT_BE2H_U16(pInodeCore->fFlags);
     1017                pInode->enmFormat           = pInodeCore->enmFormat;
     1018                pInode->cExtentsData        = RT_BE2H_U32(pInodeCore->cExtentsData);
     1019                pInode->ObjInfo.cbObject    = RT_BE2H_U64(pInodeCore->cbInode);
     1020                pInode->ObjInfo.cbAllocated = RT_BE2H_U64(pInodeCore->cBlocks) * pThis->cbBlock;
     1021                RTTimeSpecSetSeconds(&pInode->ObjInfo.AccessTime, RT_BE2H_U32(pInodeCore->TsLastAccessed.cSecEpoch));
     1022                RTTimeSpecAddNano(&pInode->ObjInfo.AccessTime, RT_BE2H_U32(pInodeCore->TsLastAccessed.cNanoSec));
     1023                RTTimeSpecSetSeconds(&pInode->ObjInfo.ModificationTime, RT_BE2H_U32(pInodeCore->TsLastModified.cSecEpoch));
     1024                RTTimeSpecAddNano(&pInode->ObjInfo.ModificationTime, RT_BE2H_U32(pInodeCore->TsLastModified.cNanoSec));
     1025                RTTimeSpecSetSeconds(&pInode->ObjInfo.ChangeTime, RT_BE2H_U32(pInodeCore->TsCreatedModified.cSecEpoch));
     1026                RTTimeSpecAddNano(&pInode->ObjInfo.ChangeTime, RT_BE2H_U32(pInodeCore->TsCreatedModified.cNanoSec));
    9851027                pInode->ObjInfo.Attr.enmAdditional = RTFSOBJATTRADD_UNIX;
    986                 pInode->ObjInfo.Attr.u.Unix.uid    = RT_BE2H_U32(Inode.uUid);
    987                 pInode->ObjInfo.Attr.u.Unix.gid    = RT_BE2H_U32(Inode.uGid);
    988                 pInode->ObjInfo.Attr.u.Unix.cHardlinks = RT_BE2H_U16(Inode.cOnLinks); /** @todo v2 inodes. */
     1028                pInode->ObjInfo.Attr.u.Unix.uid    = RT_BE2H_U32(pInodeCore->uUid);
     1029                pInode->ObjInfo.Attr.u.Unix.gid    = RT_BE2H_U32(pInodeCore->uGid);
     1030                pInode->ObjInfo.Attr.u.Unix.cHardlinks = RT_BE2H_U16(pInodeCore->cOnLinks); /** @todo v2 inodes. */
    9891031                pInode->ObjInfo.Attr.u.Unix.INodeIdDevice = 0;
    9901032                pInode->ObjInfo.Attr.u.Unix.INodeId       = iInode;
    9911033                pInode->ObjInfo.Attr.u.Unix.fFlags        = 0;
    992                 pInode->ObjInfo.Attr.u.Unix.GenerationId  = RT_BE2H_U32(Inode.cGeneration);
     1034                pInode->ObjInfo.Attr.u.Unix.GenerationId  = RT_BE2H_U32(pInodeCore->cGeneration);
    9931035                pInode->ObjInfo.Attr.u.Unix.Device        = 0;
    994                 if (Inode.iVersion >= 3)
     1036                if (pInodeCore->iVersion >= 3)
    9951037                {
    996                     RTTimeSpecSetSeconds(&pInode->ObjInfo.BirthTime, RT_BE2H_U32(Inode.TsCreation.cSecEpoch));
    997                     RTTimeSpecAddNano(&pInode->ObjInfo.BirthTime, RT_BE2H_U32(Inode.TsCreation.cNanoSec));
     1038                    RTTimeSpecSetSeconds(&pInode->ObjInfo.BirthTime, RT_BE2H_U32(pInodeCore->TsCreation.cSecEpoch));
     1039                    RTTimeSpecAddNano(&pInode->ObjInfo.BirthTime, RT_BE2H_U32(pInodeCore->TsCreation.cNanoSec));
    9981040                }
    9991041                else
     
    10021044                /* Fill in the mode. */
    10031045                pInode->ObjInfo.Attr.fMode = 0;
    1004                 uint16_t fInodeMode = RT_BE2H_U16(Inode.fMode);
     1046                uint16_t fInodeMode = RT_BE2H_U16(pInodeCore->fMode);
    10051047                switch (XFS_INODE_MODE_TYPE_GET_TYPE(fInodeMode))
    10061048                {
     
    11361178
    11371179/**
     1180 * Locates the location of the next level in the B+Tree mapping the given offset.
     1181 *
     1182 * @returns Filesystem block number where the next level of the B+Tree is stored.
     1183 * @param   paoffFile           Array of file offset mappings.
     1184 * @param   pauFsBlock          Array of filesystem block mappings.
     1185 * @param   cEntries            Number of entries in the extent index node array.
     1186 * @param   iBlock              The block to resolve.
     1187 */
     1188DECLINLINE(XFSDFSBNO) rtFsXfsInode_BTreeNdLocateNextLvl(XFSDFILOFF *paoffFile, XFSDFSBNO *pauFsBlock,
     1189                                                        uint16_t cEntries, XFSDFILOFF offFile)
     1190{
     1191    for (uint32_t i = 1; i < cEntries; i++)
     1192    {
     1193        if (   RT_BE2H_U64(paoffFile[i - 1]) <= offFile
     1194            && RT_BE2H_U64(paoffFile[i]) > offFile)
     1195            return RT_BE2H_U64(pauFsBlock[i]);
     1196    }
     1197
     1198    /* Nothing found so far, the last entry must cover the block as the array is sorted. */
     1199    return RT_BE2H_U64(pauFsBlock[cEntries - 1]);
     1200}
     1201
     1202
     1203/**
     1204 * Locates the extent mapping the file offset in the given extents list.
     1205 *
     1206 * @returns IPRT status.
     1207 * @param   pExtents            The array of extents to search.
     1208 * @param   cEntries            Number of entries in the array.
     1209 * @param   uBlock              The file offset to search the matching mapping for.
     1210 * @param   cBlocks             Number of blocks requested.
     1211 * @param   piBlockFs           Where to store the filesystem block on success.
     1212 * @param   pcBlocks            Where to store the number of contiguous blocks on success.
     1213 * @param   pfSparse            Where to store the sparse flag on success.
     1214 */
     1215DECLINLINE(int) rtFsXfsInode_ExtentLocate(PCXFSEXTENT paExtents, uint16_t cEntries, XFSDFILOFF uBlock,
     1216                                          size_t cBlocks, uint64_t *piBlockFs, size_t *pcBlocks, bool *pfSparse)
     1217{
     1218    int rc = VERR_VFS_BOGUS_FORMAT;
     1219
     1220    for (uint32_t i = 0; i < cEntries; i++)
     1221    {
     1222        PCXFSEXTENT pExtent = &paExtents[i];
     1223        uint64_t iBlockExtent = XFS_EXTENT_GET_LOGICAL_BLOCK(pExtent);
     1224        size_t cBlocksExtent = XFS_EXTENT_GET_BLOCK_COUNT(pExtent);
     1225
     1226        if (   uBlock >= iBlockExtent
     1227            && uBlock < iBlockExtent + cBlocksExtent)
     1228        {
     1229            uint64_t offExtentBlocks = uBlock - iBlockExtent;
     1230            *piBlockFs = XFS_EXTENT_GET_DISK_BLOCK(pExtent) + offExtentBlocks;
     1231            *pcBlocks  = RT_MIN(cBlocks, cBlocksExtent - offExtentBlocks);
     1232            *pfSparse  = XFS_EXTENT_IS_UNWRITTEN(pExtent);
     1233            rc = VINF_SUCCESS;
     1234            break;
     1235        }
     1236    }
     1237
     1238    return rc;
     1239}
     1240
     1241
     1242/**
     1243 * Validates the given node header.
     1244 *
     1245 * @returns IPRT status code.
     1246 * @param   pThis               The XFS volume instance.
     1247 * @param   pNd                 The node header to validate.
     1248 * @param   iLvl                The current level.
     1249 */
     1250static int rtFsXfsInode_BTreeNdValidate(PRTFSXFSVOL pThis, PCXFSBTREENODEHDR pNd, uint16_t iLvl)
     1251{
     1252    RT_NOREF(pThis, pNd, iLvl);
     1253    /** @todo */
     1254    return VINF_SUCCESS;
     1255}
     1256
     1257
     1258/**
    11381259 * Maps the given inode block to the destination filesystem block.
    11391260 *
     
    11521273                                     uint64_t *piBlockFs, size_t *pcBlocks, bool *pfSparse)
    11531274{
    1154     RT_NOREF(pThis, pInode, iBlock, cBlocks, piBlockFs, pcBlocks, pfSparse);
    1155     return VERR_NOT_IMPLEMENTED;
     1275    int rc = VINF_SUCCESS;
     1276
     1277    switch (pInode->enmFormat)
     1278    {
     1279        case XFS_INODE_FORMAT_EXTENTS:
     1280        {
     1281            size_t cbRemaining = 0;
     1282            PCXFSEXTENT paExtents = (PCXFSEXTENT)rtFsXfsInodeGetDataFork(pThis, pInode, &cbRemaining);
     1283
     1284            if (cbRemaining <= pInode->cExtentsData * sizeof(XFSEXTENT))
     1285                rc = rtFsXfsInode_ExtentLocate(paExtents, pInode->cExtentsData, cBlocks, iBlock,
     1286                                               piBlockFs, pcBlocks, pfSparse);
     1287            else
     1288                rc = VERR_VFS_BOGUS_FORMAT;
     1289            break;
     1290        }
     1291        case XFS_INODE_FORMAT_BTREE:
     1292        {
     1293            size_t cbRemaining = 0;
     1294            PCXFSBTREEROOTHDR pRoot = (PCXFSBTREEROOTHDR)rtFsXfsInodeGetDataFork(pThis, pInode, &cbRemaining);
     1295            if (cbRemaining >= RT_BE2H_U16(pRoot->cRecs) * (sizeof(XFSDFSBNO) + sizeof(XFSDFILOFF)) + sizeof(XFSBTREEROOTHDR))
     1296            {
     1297                XFSDFILOFF *poffFile = (XFSDFILOFF *)(pRoot + 1);
     1298                XFSDFSBNO  *puFsBlock = (XFSDFSBNO *)(&poffFile[RT_BE2H_U16(pRoot->cRecs)]);
     1299
     1300                XFSDFSBNO uFsBlock = rtFsXfsInode_BTreeNdLocateNextLvl(poffFile, puFsBlock, RT_BE2H_U16(pRoot->cRecs),
     1301                                                                       iBlock);
     1302                uint16_t iLvl = RT_BE2H_U16(pRoot->iLvl) - 1;
     1303
     1304                /* Resolve intermediate levels. */
     1305                while (   iLvl > 0
     1306                       && RT_SUCCESS(rc))
     1307                {
     1308                    PRTFSXFSBLOCKENTRY pEntry;
     1309                    PCXFSBTREENODEHDR pNd;
     1310
     1311                    rc = rtFsXfsVol_BlockLoad(pThis, uFsBlock, &pEntry, (void **)&pNd);
     1312                    if (RT_SUCCESS(rc))
     1313                    {
     1314                        rc = rtFsXfsInode_BTreeNdValidate(pThis, pNd, iLvl);
     1315                        if (RT_SUCCESS(rc))
     1316                        {
     1317                            poffFile = (XFSDFILOFF *)(pNd + 1);
     1318                            puFsBlock = (XFSDFSBNO *)(&poffFile[RT_BE2H_U16(pNd->cRecs)]);
     1319                            uFsBlock = rtFsXfsInode_BTreeNdLocateNextLvl(poffFile, puFsBlock, RT_BE2H_U16(pRoot->cRecs),
     1320                                                                         iBlock);
     1321                            iLvl--;
     1322                        }
     1323                        rtFsXfsVol_BlockRelease(pThis, pEntry);
     1324                    }
     1325                }
     1326
     1327                /* Load the leave node and parse it. */
     1328                if (RT_SUCCESS(rc))
     1329                {
     1330                    PRTFSXFSBLOCKENTRY pEntry;
     1331                    PCXFSBTREENODEHDR pNd;
     1332
     1333                    rc = rtFsXfsVol_BlockLoad(pThis, uFsBlock, &pEntry, (void **)&pNd);
     1334                    if (RT_SUCCESS(rc))
     1335                    {
     1336                        rc = rtFsXfsInode_BTreeNdValidate(pThis, pNd, iLvl);
     1337                        if (RT_SUCCESS(rc))
     1338                        {
     1339                            PCXFSEXTENT paExtents = (PCXFSEXTENT)(pNd + 1);
     1340                            rc = rtFsXfsInode_ExtentLocate(paExtents, RT_BE2H_U16(pNd->cRecs), cBlocks, iBlock,
     1341                                                           piBlockFs, pcBlocks, pfSparse);
     1342                        }
     1343                        rtFsXfsVol_BlockRelease(pThis, pEntry);
     1344                    }
     1345                }
     1346            }
     1347            else
     1348                rc = VERR_VFS_BOGUS_FORMAT;
     1349            break;
     1350        }
     1351        case XFS_INODE_FORMAT_LOCAL:
     1352        case XFS_INODE_FORMAT_UUID:
     1353        case XFS_INODE_FORMAT_DEV:
     1354        default:
     1355            rc = VERR_VFS_BOGUS_FORMAT;
     1356    }
     1357
     1358    return rc;
    11561359}
    11571360
     
    11781381        else
    11791382            cbRead = (uint64_t)pInode->ObjInfo.cbObject - off;
     1383    }
     1384
     1385    if (pInode->enmFormat == XFS_INODE_FORMAT_LOCAL)
     1386    {
     1387        /* Fast path when the data is inlined in the inode. */
     1388        size_t cbRemaining = 0;
     1389        uint8_t *pbSrc = (uint8_t *)rtFsXfsInodeGetDataFork(pThis, pInode, &cbRemaining);
     1390        if (off + cbRemaining <= (uint64_t)pInode->ObjInfo.cbObject)
     1391        {
     1392            memcpy(pvBuf, &pbSrc[off], cbRead);
     1393            *pcbRead = cbRead;
     1394        }
     1395        else
     1396            rc = VERR_VFS_BOGUS_FORMAT;
     1397
     1398        return rc;
    11801399    }
    11811400
Note: See TracChangeset for help on using the changeset viewer.

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