Bug 1655953 - Remove mutex lock for protecting the padding file; r=dom-workers-and-storage-reviewers,sg,asuth,janv

Depends on D81680

Differential Revision: https://phabricator.services.mozilla.com/D85279
This commit is contained in:
Tom Tung 2021-04-16 01:09:10 +00:00
Родитель f2aee4b5a8
Коммит abf9f74311
4 изменённых файлов: 88 добавлений и 114 удалений

66
dom/cache/FileUtils.cpp поставляемый
Просмотреть файл

@ -58,9 +58,9 @@ int64_t RoundUp(int64_t aX, int64_t aY);
// Finally, the virtual padding size will be the result minus the response size.
int64_t BodyGeneratePadding(int64_t aBodyFileSize, uint32_t aPaddingInfo);
nsresult LockedDirectoryPaddingWrite(nsIFile& aBaseDir,
DirPaddingFile aPaddingFileType,
int64_t aPaddingSize);
nsresult DirectoryPaddingWrite(nsIFile& aBaseDir,
DirPaddingFile aPaddingFileType,
int64_t aPaddingSize);
const auto kMorgueDirectory = u"morgue"_ns;
@ -311,9 +311,9 @@ int64_t BodyGeneratePadding(const int64_t aBodyFileSize,
return RoundUp(randomSize, kRoundUpNumber) - aBodyFileSize;
}
nsresult LockedDirectoryPaddingWrite(nsIFile& aBaseDir,
DirPaddingFile aPaddingFileType,
int64_t aPaddingSize) {
nsresult DirectoryPaddingWrite(nsIFile& aBaseDir,
DirPaddingFile aPaddingFileType,
int64_t aPaddingSize) {
MOZ_DIAGNOSTIC_ASSERT(aPaddingSize >= 0);
CACHE_TRY_INSPECT(
@ -553,7 +553,7 @@ bool DirectoryPaddingFileExists(nsIFile& aBaseDir,
CACHE_TRY_RETURN(MOZ_TO_RESULT_INVOKE(file, Exists), false);
}
Result<int64_t, nsresult> LockedDirectoryPaddingGet(nsIFile& aBaseDir) {
Result<int64_t, nsresult> DirectoryPaddingGet(nsIFile& aBaseDir) {
MOZ_DIAGNOSTIC_ASSERT(
!DirectoryPaddingFileExists(aBaseDir, DirPaddingFile::TMP_FILE));
@ -575,26 +575,25 @@ Result<int64_t, nsresult> LockedDirectoryPaddingGet(nsIFile& aBaseDir) {
}));
}
nsresult LockedDirectoryPaddingInit(nsIFile& aBaseDir) {
CACHE_TRY(LockedDirectoryPaddingWrite(aBaseDir, DirPaddingFile::FILE, 0));
nsresult DirectoryPaddingInit(nsIFile& aBaseDir) {
CACHE_TRY(DirectoryPaddingWrite(aBaseDir, DirPaddingFile::FILE, 0));
return NS_OK;
}
nsresult LockedUpdateDirectoryPaddingFile(nsIFile& aBaseDir,
mozIStorageConnection& aConn,
const int64_t aIncreaseSize,
const int64_t aDecreaseSize,
const bool aTemporaryFileExist) {
nsresult UpdateDirectoryPaddingFile(nsIFile& aBaseDir,
mozIStorageConnection& aConn,
const int64_t aIncreaseSize,
const int64_t aDecreaseSize,
const bool aTemporaryFileExist) {
MOZ_DIAGNOSTIC_ASSERT(aIncreaseSize >= 0);
MOZ_DIAGNOSTIC_ASSERT(aDecreaseSize >= 0);
const auto directoryPaddingGetResult =
aTemporaryFileExist ? Maybe<int64_t>{} : [&aBaseDir] {
CACHE_TRY_RETURN(
QM_OR_ELSE_WARN(
LockedDirectoryPaddingGet(aBaseDir).map(Some<int64_t>),
MapNotFoundToDefault<Maybe<int64_t>>),
QM_OR_ELSE_WARN(DirectoryPaddingGet(aBaseDir).map(Some<int64_t>),
MapNotFoundToDefault<Maybe<int64_t>>),
Maybe<int64_t>{});
}();
@ -608,8 +607,7 @@ nsresult LockedUpdateDirectoryPaddingFile(nsIFile& aBaseDir,
// Not delete the temporary padding file here, because we're going
// to overwrite it below anyway.
CACHE_TRY(
LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::FILE));
CACHE_TRY(DirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::FILE));
// We don't need to add the aIncreaseSize or aDecreaseSize here,
// because it's already encompassed within the database.
@ -640,8 +638,7 @@ nsresult LockedUpdateDirectoryPaddingFile(nsIFile& aBaseDir,
// incorrect.
// Delete padding file to indicate the padding size is incorrect for
// avoiding error happening in the following lines.
CACHE_TRY(
LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::FILE));
CACHE_TRY(DirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::FILE));
CACHE_TRY_UNWRAP(currentPaddingSize,
db::FindOverallPaddingSize(aConn));
@ -666,13 +663,13 @@ nsresult LockedUpdateDirectoryPaddingFile(nsIFile& aBaseDir,
MOZ_DIAGNOSTIC_ASSERT(currentPaddingSize >= 0);
CACHE_TRY(LockedDirectoryPaddingWrite(aBaseDir, DirPaddingFile::TMP_FILE,
currentPaddingSize));
CACHE_TRY(DirectoryPaddingWrite(aBaseDir, DirPaddingFile::TMP_FILE,
currentPaddingSize));
return NS_OK;
}
nsresult LockedDirectoryPaddingFinalizeWrite(nsIFile& aBaseDir) {
nsresult DirectoryPaddingFinalizeWrite(nsIFile& aBaseDir) {
MOZ_DIAGNOSTIC_ASSERT(
DirectoryPaddingFileExists(aBaseDir, DirPaddingFile::TMP_FILE));
@ -685,28 +682,27 @@ nsresult LockedDirectoryPaddingFinalizeWrite(nsIFile& aBaseDir) {
return NS_OK;
}
Result<int64_t, nsresult> LockedDirectoryPaddingRestore(
nsIFile& aBaseDir, mozIStorageConnection& aConn, const bool aMustRestore) {
Result<int64_t, nsresult> DirectoryPaddingRestore(nsIFile& aBaseDir,
mozIStorageConnection& aConn,
const bool aMustRestore) {
// The content of padding file is untrusted, so remove it here.
CACHE_TRY(LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::FILE));
CACHE_TRY(DirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::FILE));
CACHE_TRY_INSPECT(const int64_t& paddingSize,
db::FindOverallPaddingSize(aConn));
MOZ_DIAGNOSTIC_ASSERT(paddingSize >= 0);
CACHE_TRY(
LockedDirectoryPaddingWrite(aBaseDir, DirPaddingFile::FILE, paddingSize),
(aMustRestore ? Err(tryTempError)
: Result<int64_t, nsresult>{paddingSize}));
CACHE_TRY(DirectoryPaddingWrite(aBaseDir, DirPaddingFile::FILE, paddingSize),
(aMustRestore ? Err(tryTempError)
: Result<int64_t, nsresult>{paddingSize}));
CACHE_TRY(
LockedDirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::TMP_FILE));
CACHE_TRY(DirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::TMP_FILE));
return paddingSize;
}
nsresult LockedDirectoryPaddingDeleteFile(nsIFile& aBaseDir,
DirPaddingFile aPaddingFileType) {
nsresult DirectoryPaddingDeleteFile(nsIFile& aBaseDir,
DirPaddingFile aPaddingFileType) {
CACHE_TRY_INSPECT(
const auto& file,
CloneFileAndAppend(aBaseDir, aPaddingFileType == DirPaddingFile::TMP_FILE

25
dom/cache/FileUtils.h поставляемый
Просмотреть файл

@ -99,24 +99,25 @@ bool DirectoryPaddingFileExists(nsIFile& aBaseDir,
*/
// Returns a Result with a success value denoting the padding size.
Result<int64_t, nsresult> LockedDirectoryPaddingGet(nsIFile& aBaseDir);
Result<int64_t, nsresult> DirectoryPaddingGet(nsIFile& aBaseDir);
nsresult LockedDirectoryPaddingInit(nsIFile& aBaseDir);
nsresult DirectoryPaddingInit(nsIFile& aBaseDir);
nsresult LockedUpdateDirectoryPaddingFile(nsIFile& aBaseDir,
mozIStorageConnection& aConn,
int64_t aIncreaseSize,
int64_t aDecreaseSize,
bool aTemporaryFileExist);
nsresult UpdateDirectoryPaddingFile(nsIFile& aBaseDir,
mozIStorageConnection& aConn,
int64_t aIncreaseSize,
int64_t aDecreaseSize,
bool aTemporaryFileExist);
nsresult LockedDirectoryPaddingFinalizeWrite(nsIFile& aBaseDir);
nsresult DirectoryPaddingFinalizeWrite(nsIFile& aBaseDir);
// Returns a Result with a success value denoting the padding size.
Result<int64_t, nsresult> LockedDirectoryPaddingRestore(
nsIFile& aBaseDir, mozIStorageConnection& aConn, bool aMustRestore);
Result<int64_t, nsresult> DirectoryPaddingRestore(nsIFile& aBaseDir,
mozIStorageConnection& aConn,
bool aMustRestore);
nsresult LockedDirectoryPaddingDeleteFile(nsIFile& aBaseDir,
DirPaddingFile aPaddingFileType);
nsresult DirectoryPaddingDeleteFile(nsIFile& aBaseDir,
DirPaddingFile aPaddingFileType);
} // namespace cache
} // namespace dom
} // namespace mozilla

56
dom/cache/QuotaClient.cpp поставляемый
Просмотреть файл

@ -122,7 +122,7 @@ Result<UsageInfo, nsresult> GetBodyUsage(nsIFile& aMorgueDir,
}));
}
Result<int64_t, nsresult> LockedGetPaddingSizeFromDB(
Result<int64_t, nsresult> GetPaddingSizeFromDB(
nsIFile& aDir, nsIFile& aDBFile, const OriginMetadata& aOriginMetadata) {
QuotaInfo quotaInfo;
static_cast<OriginMetadata&>(quotaInfo) = aOriginMetadata;
@ -145,13 +145,13 @@ Result<int64_t, nsresult> LockedGetPaddingSizeFromDB(
CACHE_TRY_INSPECT(const auto& conn, OpenDBConnection(quotaInfo, aDBFile));
// Make sure that the database has the latest schema before we try to read
// from it. We have to do this because LockedGetPaddingSizeFromDB is called
// from it. We have to do this because GetPaddingSizeFromDB is called
// by InitOrigin. And it means that SetupAction::RunSyncWithDBOnTarget hasn't
// checked the schema for the given origin yet).
CACHE_TRY(db::CreateOrMigrateSchema(*conn));
CACHE_TRY_RETURN(LockedDirectoryPaddingRestore(aDir, *conn,
/* aMustRestore */ false));
CACHE_TRY_RETURN(DirectoryPaddingRestore(aDir, *conn,
/* aMustRestore */ false));
}
} // namespace
@ -159,8 +159,7 @@ Result<int64_t, nsresult> LockedGetPaddingSizeFromDB(
const nsLiteralString kCachesSQLiteFilename = u"caches.sqlite"_ns;
const nsLiteralString kMorgueDirectoryFilename = u"morgue"_ns;
CacheQuotaClient::CacheQuotaClient()
: mDirPaddingFileMutex("DOMCacheQuotaClient.mDirPaddingFileMutex") {
CacheQuotaClient::CacheQuotaClient() {
AssertIsOnBackgroundThread();
MOZ_DIAGNOSTIC_ASSERT(!sInstance);
sInstance = this;
@ -191,7 +190,7 @@ Result<UsageInfo, nsresult> CacheQuotaClient::InitOrigin(
CACHE_TRY_INSPECT(
const auto& cachesSQLiteFile,
([dir, this]() -> Result<nsCOMPtr<nsIFile>, nsresult> {
([dir]() -> Result<nsCOMPtr<nsIFile>, nsresult> {
CACHE_TRY_INSPECT(const auto& cachesSQLite,
CloneFileAndAppend(*dir, kCachesSQLiteFilename));
@ -210,15 +209,11 @@ Result<UsageInfo, nsresult> CacheQuotaClient::InitOrigin(
// XXX Long term, we might even think about removing entire origin
// directory because missing caches.sqlite while other files exist can
// be interpreted as database corruption.
{
MutexAutoLock lock(mDirPaddingFileMutex);
CACHE_TRY(mozilla::dom::cache::DirectoryPaddingDeleteFile(
*dir, DirPaddingFile::TMP_FILE));
CACHE_TRY(mozilla::dom::cache::LockedDirectoryPaddingDeleteFile(
*dir, DirPaddingFile::TMP_FILE));
CACHE_TRY(mozilla::dom::cache::LockedDirectoryPaddingDeleteFile(
*dir, DirPaddingFile::FILE));
}
CACHE_TRY(mozilla::dom::cache::DirectoryPaddingDeleteFile(
*dir, DirPaddingFile::FILE));
CACHE_TRY_INSPECT(const auto& morgueDir,
CloneFileAndAppend(*dir, kMorgueDirectoryFilename));
@ -245,13 +240,11 @@ Result<UsageInfo, nsresult> CacheQuotaClient::InitOrigin(
CACHE_TRY_INSPECT(
const auto& paddingSize,
([this, dir, cachesSQLiteFile,
([dir, cachesSQLiteFile,
&aOriginMetadata]() -> Result<int64_t, nsresult> {
MutexAutoLock lock(mDirPaddingFileMutex);
if (!DirectoryPaddingFileExists(*dir, DirPaddingFile::TMP_FILE)) {
const auto& maybePaddingSize = [dir]() -> Maybe<int64_t> {
CACHE_TRY_RETURN(LockedDirectoryPaddingGet(*dir).map(Some<int64_t>),
CACHE_TRY_RETURN(DirectoryPaddingGet(*dir).map(Some<int64_t>),
Nothing{});
}();
@ -263,8 +256,8 @@ Result<UsageInfo, nsresult> CacheQuotaClient::InitOrigin(
// If the temporary file still exists or failing to get the padding size
// from the padding file, then we need to get the padding size from the
// database and restore the padding file.
CACHE_TRY_RETURN(LockedGetPaddingSizeFromDB(*dir, *cachesSQLiteFile,
aOriginMetadata));
CACHE_TRY_RETURN(
GetPaddingSizeFromDB(*dir, *cachesSQLiteFile, aOriginMetadata));
}()));
CACHE_TRY_INSPECT(
@ -428,9 +421,7 @@ nsresult CacheQuotaClient::UpgradeStorageFrom2_0To2_1(nsIFile* aDirectory) {
AssertIsOnIOThread();
MOZ_DIAGNOSTIC_ASSERT(aDirectory);
MutexAutoLock lock(mDirPaddingFileMutex);
CACHE_TRY(LockedDirectoryPaddingInit(*aDirectory));
CACHE_TRY(DirectoryPaddingInit(*aDirectory));
return NS_OK;
}
@ -441,11 +432,9 @@ nsresult CacheQuotaClient::RestorePaddingFileInternal(
MOZ_DIAGNOSTIC_ASSERT(aBaseDir);
MOZ_DIAGNOSTIC_ASSERT(aConn);
MutexAutoLock lock(mDirPaddingFileMutex);
CACHE_TRY_INSPECT(const int64_t& dummyPaddingSize,
LockedDirectoryPaddingRestore(*aBaseDir, *aConn,
/* aMustRestore */ true));
DirectoryPaddingRestore(*aBaseDir, *aConn,
/* aMustRestore */ true));
Unused << dummyPaddingSize;
return NS_OK;
@ -456,8 +445,6 @@ nsresult CacheQuotaClient::WipePaddingFileInternal(const QuotaInfo& aQuotaInfo,
MOZ_ASSERT(!NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(aBaseDir);
MutexAutoLock lock(mDirPaddingFileMutex);
MOZ_ASSERT(DirectoryPaddingFileExists(*aBaseDir, DirPaddingFile::FILE));
CACHE_TRY_INSPECT(
@ -471,7 +458,7 @@ nsresult CacheQuotaClient::WipePaddingFileInternal(const QuotaInfo& aQuotaInfo,
directoryPaddingGetResult,
([&aBaseDir]() -> Result<Maybe<int64_t>, nsresult> {
CACHE_TRY_RETURN(
LockedDirectoryPaddingGet(*aBaseDir).map(Some<int64_t>),
DirectoryPaddingGet(*aBaseDir).map(Some<int64_t>),
Maybe<int64_t>{});
}()));
}
@ -491,13 +478,12 @@ nsresult CacheQuotaClient::WipePaddingFileInternal(const QuotaInfo& aQuotaInfo,
DecreaseUsageForQuotaInfo(aQuotaInfo, paddingSize);
}
CACHE_TRY(LockedDirectoryPaddingDeleteFile(*aBaseDir, DirPaddingFile::FILE));
CACHE_TRY(DirectoryPaddingDeleteFile(*aBaseDir, DirPaddingFile::FILE));
// Remove temporary file if we have one.
CACHE_TRY(
LockedDirectoryPaddingDeleteFile(*aBaseDir, DirPaddingFile::TMP_FILE));
CACHE_TRY(DirectoryPaddingDeleteFile(*aBaseDir, DirPaddingFile::TMP_FILE));
CACHE_TRY(LockedDirectoryPaddingInit(*aBaseDir));
CACHE_TRY(DirectoryPaddingInit(*aBaseDir));
return NS_OK;
}

55
dom/cache/QuotaClientImpl.h поставляемый
Просмотреть файл

@ -81,38 +81,33 @@ class CacheQuotaClient final : public quota::Client {
return NS_OK;
}
{
MutexAutoLock lock(mDirPaddingFileMutex);
// Don't delete the temporary padding file in case of an error to force the
// next action recalculate the padding size.
CACHE_TRY(UpdateDirectoryPaddingFile(aBaseDir, aConn, aIncreaseSize,
aDecreaseSize,
temporaryPaddingFileExist));
// Don't delete the temporary padding file in case of an error to force
// the next action recalculate the padding size.
CACHE_TRY(LockedUpdateDirectoryPaddingFile(aBaseDir, aConn, aIncreaseSize,
aDecreaseSize,
temporaryPaddingFileExist));
// Don't delete the temporary padding file in case of an error to force the
// next action recalculate the padding size.
CACHE_TRY(aCommitHook());
// Don't delete the temporary padding file in case of an error to force
// the next action recalculate the padding size.
CACHE_TRY(aCommitHook());
QM_TRY(QM_OR_ELSE_WARN(
ToResult(DirectoryPaddingFinalizeWrite(aBaseDir)),
([&aBaseDir](const nsresult) -> Result<Ok, nsresult> {
// Force restore file next time.
Unused << DirectoryPaddingDeleteFile(aBaseDir, DirPaddingFile::FILE);
QM_TRY(QM_OR_ELSE_WARN(
ToResult(LockedDirectoryPaddingFinalizeWrite(aBaseDir)),
([&aBaseDir](const nsresult) -> Result<Ok, nsresult> {
// Force restore file next time.
Unused << LockedDirectoryPaddingDeleteFile(aBaseDir,
DirPaddingFile::FILE);
// Ensure that we are able to force the padding file
// to be restored.
MOZ_ASSERT(
DirectoryPaddingFileExists(aBaseDir, DirPaddingFile::TMP_FILE));
// Ensure that we are able to force the padding file to
// be restored.
MOZ_ASSERT(
DirectoryPaddingFileExists(aBaseDir, DirPaddingFile::TMP_FILE));
// Since both the body file and header have been stored
// in the file-system, just make the action be resolve
// and let the padding file be restored in the next
// action.
return Ok{};
})));
}
// Since both the body file and header have been
// stored in the file-system, just make the action be
// resolve and let the padding file be restored in the
// next action.
return Ok{};
})));
return NS_OK;
}
@ -133,10 +128,6 @@ class CacheQuotaClient final : public quota::Client {
void FinalizeShutdown() override;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CacheQuotaClient, override)
// Mutex lock to protect directroy padding files. It should only be acquired
// in DOM Cache IO threads and Quota IO thread.
mozilla::Mutex mDirPaddingFileMutex;
};
} // namespace cache