__declspec(noinline) void PointerToDurableMappedFile::makeChunkWritable(size_t chunkno) { stdx::lock_guard<stdx::mutex> lkPrivateViews(_m); if (writable.get(chunkno)) // double check lock return; // remap all maps in this chunk. // common case is a single map, but could have more than one with smallfiles or .ns files size_t chunkStart = chunkno * MemoryMappedCOWBitset::ChunkSize; size_t chunkNext = chunkStart + MemoryMappedCOWBitset::ChunkSize; stdx::lock_guard<stdx::mutex> lkMapView(mapViewMutex); map<void*, DurableMappedFile*>::iterator i = _views.upper_bound((void*)(chunkNext - 1)); while (1) { const pair<void*, DurableMappedFile*> x = *(--i); DurableMappedFile* mmf = x.second; if (mmf == 0) break; size_t viewStart = reinterpret_cast<size_t>(x.first); size_t viewEnd = viewStart + mmf->length(); if (viewEnd <= chunkStart) break; size_t protectStart = std::max(viewStart, chunkStart); dassert(protectStart < chunkNext); size_t protectEnd = std::min(viewEnd, chunkNext); size_t protectSize = protectEnd - protectStart; dassert(protectSize > 0 && protectSize <= MemoryMappedCOWBitset::ChunkSize); DWORD oldProtection; bool ok = VirtualProtect( reinterpret_cast<void*>(protectStart), protectSize, PAGE_WRITECOPY, &oldProtection); if (!ok) { DWORD dosError = GetLastError(); if (dosError == ERROR_COMMITMENT_LIMIT) { // System has run out of memory between physical RAM & page file, tell the user BSONObjBuilder bb; ProcessInfo p; p.getExtraInfo(bb); severe() << "MongoDB has exhausted the system memory capacity."; severe() << "Current Memory Status: " << bb.obj(); } severe() << "VirtualProtect for " << mmf->filename() << " chunk " << chunkno << " failed with " << errnoWithDescription(dosError) << " (chunk size is " << protectSize << ", address is " << hex << protectStart << dec << ")" << " in mongo::makeChunkWritable, terminating" << endl; fassertFailed(16362); } } writable.set(chunkno); }