Changeset 77008 in vbox for trunk/src/VBox/Runtime/common/fs/xfsvfs.cpp
- Timestamp:
- Jan 26, 2019 6:54:44 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/xfsvfs.cpp
r76642 r77008 112 112 /** Inode flags. */ 113 113 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]; 114 120 } RTFSXFSINODE; 115 121 /** Pointer to an in-memory inode. */ … … 329 335 } 330 336 331 337 #if 0 /* unused */ 332 338 /** 333 339 * Logs a AG free space block. … … 367 373 } 368 374 } 369 375 #endif 370 376 371 377 /** … … 541 547 542 548 /** 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 */ 554 DECLINLINE(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 */ 570 DECLINLINE(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 /** 543 582 * Allocates a new block group. 544 583 * … … 696 735 } 697 736 698 737 #if 0 /* unused */ 699 738 /** 700 739 * Allocates a new alloction group. … … 850 889 rtFsXfsAg_Free(pThis, pAg); 851 890 } 852 891 #endif 853 892 854 893 /** … … 861 900 static PRTFSXFSINODE rtFsXfsInode_Alloc(PRTFSXFSVOL pThis, uint32_t iInode) 862 901 { 863 PRTFSXFSINODE pInode = (PRTFSXFSINODE)RTMemAllocZ(sizeof(RTFSXFSINODE)); 902 size_t cbAlloc = RT_UOFFSETOF_DYN(RTFSXFSINODE, abData[pThis->cbInode]); 903 PRTFSXFSINODE pInode = (PRTFSXFSINODE)RTMemAllocZ(cbAlloc); 864 904 if (RT_LIKELY(pInode)) 865 905 { 866 906 pInode->Core.Key = iInode; 867 907 pInode->cRefs = 0; 868 pThis->cbInodes += sizeof(RTFSXFSINODE);908 pThis->cbInodes += cbAlloc; 869 909 } 870 910 … … 899 939 Assert(pCore == &pInode->Core); RT_NOREF(pCore); 900 940 RTMemFree(pInode); 901 pThis->cbInodes -= sizeof(RTFSXFSINODE);941 pThis->cbInodes -= RT_UOFFSETOF_DYN(RTFSXFSINODE, abData[pThis->cbInode]); 902 942 } 903 943 } … … 914 954 { 915 955 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) 917 957 pInode = rtFsXfsInode_Alloc(pThis, iInode); 918 958 else … … 964 1004 965 1005 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); 968 1007 if (RT_SUCCESS(rc)) 969 1008 { 1009 PCXFSINODECORE pInodeCore = (PCXFSINODECORE)&pInode->abData[0]; 1010 970 1011 #ifdef LOG_ENABLED 971 rtFsXfsInode_Log(pThis, iInode, &Inode);1012 rtFsXfsInode_Log(pThis, iInode, pInodeCore); 972 1013 #endif 973 1014 974 1015 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)); 985 1027 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. */ 989 1031 pInode->ObjInfo.Attr.u.Unix.INodeIdDevice = 0; 990 1032 pInode->ObjInfo.Attr.u.Unix.INodeId = iInode; 991 1033 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); 993 1035 pInode->ObjInfo.Attr.u.Unix.Device = 0; 994 if ( Inode.iVersion >= 3)1036 if (pInodeCore->iVersion >= 3) 995 1037 { 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)); 998 1040 } 999 1041 else … … 1002 1044 /* Fill in the mode. */ 1003 1045 pInode->ObjInfo.Attr.fMode = 0; 1004 uint16_t fInodeMode = RT_BE2H_U16( Inode.fMode);1046 uint16_t fInodeMode = RT_BE2H_U16(pInodeCore->fMode); 1005 1047 switch (XFS_INODE_MODE_TYPE_GET_TYPE(fInodeMode)) 1006 1048 { … … 1136 1178 1137 1179 /** 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 */ 1188 DECLINLINE(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 */ 1215 DECLINLINE(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 */ 1250 static 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 /** 1138 1259 * Maps the given inode block to the destination filesystem block. 1139 1260 * … … 1152 1273 uint64_t *piBlockFs, size_t *pcBlocks, bool *pfSparse) 1153 1274 { 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; 1156 1359 } 1157 1360 … … 1178 1381 else 1179 1382 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; 1180 1399 } 1181 1400
Note:
See TracChangeset
for help on using the changeset viewer.