Changeset 34428 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Nov 26, 2010 11:08:55 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 68200
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/PDMBlkCache.cpp
r34406 r34428 64 64 #endif 65 65 66 #define PDM_BLK_CACHE_SAVED_STATE_VERSION 1 67 66 68 /******************************************************************************* 67 69 * Internal Functions * 68 70 *******************************************************************************/ 71 72 static PPDMBLKCACHEENTRY pdmBlkCacheEntryAlloc(PPDMBLKCACHE pBlkCache, 73 uint64_t off, size_t cbData, uint8_t *pbBuffer); 74 static bool pdmBlkCacheAddDirtyEntry(PPDMBLKCACHE pBlkCache, PPDMBLKCACHEENTRY pEntry); 69 75 70 76 /** … … 752 758 } 753 759 760 static PPDMBLKCACHE pdmR3BlkCacheFindById(PPDMBLKCACHEGLOBAL pBlkCacheGlobal, const char *pcszId) 761 { 762 bool fFound = false; 763 PPDMBLKCACHE pBlkCache = NULL; 764 765 RTListForEach(&pBlkCacheGlobal->ListUsers, pBlkCache, PDMBLKCACHE, NodeCacheUser) 766 { 767 if (!RTStrCmp(pBlkCache->pszId, pcszId)) 768 { 769 fFound = true; 770 break; 771 } 772 } 773 774 return fFound ? pBlkCache : NULL; 775 } 776 754 777 /** 755 778 * Commit timer callback. … … 767 790 TMTimerSetMillies(pTimer, pCache->u32CommitTimeoutMs); 768 791 LogFlowFunc(("Entries committed, going to sleep\n")); 792 } 793 794 static DECLCALLBACK(int) pdmR3BlkCacheSaveExec(PVM pVM, PSSMHANDLE pSSM) 795 { 796 PPDMBLKCACHEGLOBAL pBlkCacheGlobal = pVM->pUVM->pdm.s.pBlkCacheGlobal; 797 798 AssertPtr(pBlkCacheGlobal); 799 800 pdmBlkCacheLockEnter(pBlkCacheGlobal); 801 802 SSMR3PutU32(pSSM, pBlkCacheGlobal->cRefs); 803 804 /* Go through the list and save all dirty entries. */ 805 PPDMBLKCACHE pBlkCache; 806 RTListForEach(&pBlkCacheGlobal->ListUsers, pBlkCache, PDMBLKCACHE, NodeCacheUser) 807 { 808 uint32_t cEntries = 0; 809 PPDMBLKCACHEENTRY pEntry; 810 811 RTSemRWRequestRead(pBlkCache->SemRWEntries, RT_INDEFINITE_WAIT); 812 SSMR3PutU32(pSSM, strlen(pBlkCache->pszId)); 813 SSMR3PutStrZ(pSSM, pBlkCache->pszId); 814 815 /* Count the number of entries to safe. */ 816 RTListForEach(&pBlkCache->ListDirtyNotCommitted, pEntry, PDMBLKCACHEENTRY, NodeNotCommitted) 817 { 818 cEntries++; 819 } 820 821 SSMR3PutU32(pSSM, cEntries); 822 823 /* Walk the list of all dirty entries and save them. */ 824 RTListForEach(&pBlkCache->ListDirtyNotCommitted, pEntry, PDMBLKCACHEENTRY, NodeNotCommitted) 825 { 826 /* A few sanity checks. */ 827 AssertMsg(!pEntry->cRefs, ("The entry is still referenced\n")); 828 AssertMsg(pEntry->fFlags & PDMBLKCACHE_ENTRY_IS_DIRTY, ("Entry is not dirty\n")); 829 AssertMsg(!(pEntry->fFlags & ~PDMBLKCACHE_ENTRY_IS_DIRTY), ("Invalid flags set\n")); 830 AssertMsg(!pEntry->pWaitingHead && !pEntry->pWaitingTail, ("There are waiting requests\n")); 831 AssertMsg( pEntry->pList == &pBlkCacheGlobal->LruRecentlyUsedIn 832 || pEntry->pList == &pBlkCacheGlobal->LruFrequentlyUsed, 833 ("Invalid list\n")); 834 AssertMsg(pEntry->cbData == pEntry->Core.KeyLast - pEntry->Core.Key + 1, 835 ("Size and range do not match\n")); 836 837 /* Save */ 838 SSMR3PutU64(pSSM, pEntry->Core.Key); 839 SSMR3PutU32(pSSM, pEntry->cbData); 840 SSMR3PutMem(pSSM, pEntry->pbData, pEntry->cbData); 841 } 842 843 RTSemRWReleaseRead(pBlkCache->SemRWEntries); 844 } 845 846 pdmBlkCacheLockLeave(pBlkCacheGlobal); 847 848 /* Terminator */ 849 return SSMR3PutU32(pSSM, UINT32_MAX); 850 } 851 852 static DECLCALLBACK(int) pdmR3BlkCacheLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 853 { 854 int rc = VINF_SUCCESS; 855 uint32_t cRefs; 856 PPDMBLKCACHEGLOBAL pBlkCacheGlobal = pVM->pUVM->pdm.s.pBlkCacheGlobal; 857 858 AssertPtr(pBlkCacheGlobal); 859 860 pdmBlkCacheLockEnter(pBlkCacheGlobal); 861 862 if (uVersion != PDM_BLK_CACHE_SAVED_STATE_VERSION) 863 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 864 865 SSMR3GetU32(pSSM, &cRefs); 866 867 if (cRefs == pBlkCacheGlobal->cRefs) 868 { 869 char *pszId = NULL; 870 871 while ( cRefs > 0 872 && RT_SUCCESS(rc)) 873 { 874 PPDMBLKCACHE pBlkCache = NULL; 875 uint32_t cbId = 0; 876 877 SSMR3GetU32(pSSM, &cbId); 878 Assert(cbId > 0); 879 880 cbId++; /* Include terminator */ 881 pszId = (char *)RTMemAllocZ(cbId * sizeof(char)); 882 if (!pszId) 883 { 884 rc = VERR_NO_MEMORY; 885 break; 886 } 887 888 rc = SSMR3GetStrZ(pSSM, pszId, cbId); 889 AssertRC(rc); 890 891 /* Search for the block cache with the provided id. */ 892 pBlkCache = pdmR3BlkCacheFindById(pBlkCacheGlobal, pszId); 893 if (!pBlkCache) 894 { 895 rc = SSMR3SetCfgError(pSSM, RT_SRC_POS, 896 N_("The VM is missing a block device. Please make sure the source and target VMs have compatible storage configurations")); 897 break; 898 } 899 900 RTStrFree(pszId); 901 pszId = NULL; 902 903 /* Get the entries */ 904 uint32_t cEntries; 905 SSMR3GetU32(pSSM, &cEntries); 906 907 while (cEntries > 0) 908 { 909 PPDMBLKCACHEENTRY pEntry; 910 uint64_t off; 911 uint32_t cbEntry; 912 913 SSMR3GetU64(pSSM, &off); 914 SSMR3GetU32(pSSM, &cbEntry); 915 916 pEntry = pdmBlkCacheEntryAlloc(pBlkCache, off, cbEntry, NULL); 917 if (!pEntry) 918 { 919 rc = VERR_NO_MEMORY; 920 break; 921 } 922 923 rc = SSMR3GetMem(pSSM, pEntry->pbData, cbEntry); 924 if (RT_FAILURE(rc)) 925 { 926 RTMemFree(pEntry->pbData); 927 RTMemFree(pEntry); 928 break; 929 } 930 931 /* Insert into the tree. */ 932 bool fInserted = RTAvlrU64Insert(pBlkCache->pTree, &pEntry->Core); 933 Assert(fInserted); 934 935 /* Add to the dirty list. */ 936 pdmBlkCacheAddDirtyEntry(pBlkCache, pEntry); 937 pdmBlkCacheEntryAddToList(&pBlkCacheGlobal->LruRecentlyUsedIn, pEntry); 938 pdmBlkCacheAdd(pBlkCacheGlobal, cbEntry); 939 pdmBlkCacheEntryRelease(pEntry); 940 cEntries--; 941 } 942 943 cRefs--; 944 } 945 946 if (pszId) 947 RTStrFree(pszId); 948 } 949 else 950 rc = SSMR3SetCfgError(pSSM, RT_SRC_POS, 951 N_("The VM is missing a block device. Please make sure the source and target VMs have compatible storage configurations")); 952 953 pdmBlkCacheLockLeave(pBlkCacheGlobal); 954 955 if (RT_SUCCESS(rc)) 956 { 957 uint32_t u32 = 0; 958 rc = SSMR3GetU32(pSSM, &u32); 959 if (RT_SUCCESS(rc)) 960 AssertMsgReturn(u32 == UINT32_MAX, ("%#x\n", u32), VERR_SSM_DATA_UNIT_FORMAT_CHANGED); 961 } 962 963 return rc; 769 964 } 770 965 … … 906 1101 if (RT_SUCCESS(rc)) 907 1102 { 908 LogRel(("BlkCache: Cache successfully initialised. Cache size is %u bytes\n", pBlkCacheGlobal->cbMax)); 909 LogRel(("BlkCache: Cache commit interval is %u ms\n", pBlkCacheGlobal->u32CommitTimeoutMs)); 910 LogRel(("BlkCache: Cache commit threshold is %u bytes\n", pBlkCacheGlobal->cbCommitDirtyThreshold)); 911 pUVM->pdm.s.pBlkCacheGlobal = pBlkCacheGlobal; 912 return VINF_SUCCESS; 1103 /* Register saved state handler. */ 1104 rc = SSMR3RegisterInternal(pVM, "pdmblkcache", 0, PDM_BLK_CACHE_SAVED_STATE_VERSION, pBlkCacheGlobal->cbMax, 1105 NULL, NULL, NULL, 1106 NULL, pdmR3BlkCacheSaveExec, NULL, 1107 NULL, pdmR3BlkCacheLoadExec, NULL); 1108 if (RT_SUCCESS(rc)) 1109 { 1110 LogRel(("BlkCache: Cache successfully initialised. Cache size is %u bytes\n", pBlkCacheGlobal->cbMax)); 1111 LogRel(("BlkCache: Cache commit interval is %u ms\n", pBlkCacheGlobal->u32CommitTimeoutMs)); 1112 LogRel(("BlkCache: Cache commit threshold is %u bytes\n", pBlkCacheGlobal->cbCommitDirtyThreshold)); 1113 pUVM->pdm.s.pBlkCacheGlobal = pBlkCacheGlobal; 1114 return VINF_SUCCESS; 1115 } 913 1116 } 914 1117 … … 965 1168 int rc = VINF_SUCCESS; 966 1169 PPDMBLKCACHE pBlkCache = NULL; 967 bool fAlreadyExists = false;968 1170 PPDMBLKCACHEGLOBAL pBlkCacheGlobal = pVM->pUVM->pdm.s.pBlkCacheGlobal; 969 1171 … … 977 1179 pdmBlkCacheLockEnter(pBlkCacheGlobal); 978 1180 979 RTListForEach(&pBlkCacheGlobal->ListUsers, pBlkCache, PDMBLKCACHE, NodeCacheUser) 980 { 981 if (!RTStrCmp(pBlkCache->pszId, pcszId)) 982 { 983 fAlreadyExists = true; 984 break; 985 } 986 } 987 988 if (!fAlreadyExists) 1181 pBlkCache = pdmR3BlkCacheFindById(pBlkCacheGlobal, pcszId); 1182 1183 if (!pBlkCache) 989 1184 { 990 1185 pBlkCache = (PPDMBLKCACHE)RTMemAllocZ(sizeof(PDMBLKCACHE)); … … 1162 1357 PPDMBLKCACHE pBlkCache = pEntry->pBlkCache; 1163 1358 1164 while (ASMAtomicReadU32(&pEntry->fFlags) & (PDMBLKCACHE_ENTRY_IO_IN_PROGRESS | PDMBLKCACHE_ENTRY_IS_DIRTY))1359 while (ASMAtomicReadU32(&pEntry->fFlags) & PDMBLKCACHE_ENTRY_IO_IN_PROGRESS) 1165 1360 { 1166 1361 /* Leave the locks to let the I/O thread make progress but reference the entry to prevent eviction. */ … … 1177 1372 } 1178 1373 1179 AssertMsg(!(pEntry->fFlags & (PDMBLKCACHE_ENTRY_IO_IN_PROGRESS | PDMBLKCACHE_ENTRY_IS_DIRTY)),1374 AssertMsg(!(pEntry->fFlags & PDMBLKCACHE_ENTRY_IO_IN_PROGRESS), 1180 1375 ("Entry is dirty and/or still in progress fFlags=%#x\n", pEntry->fFlags)); 1181 1376 … … 2270 2465 * Add the waiters to the list again. 2271 2466 */ 2467 pEntry->fFlags &= ~PDMBLKCACHE_ENTRY_IS_DIRTY; /* Clear so it gets added to the list again. */ 2272 2468 fDirty = true; 2273 2469
Note:
See TracChangeset
for help on using the changeset viewer.