feat: page cache backed by vnode instead of filep

1, change the owner of page to vnode
2, save the file path in vnode

close: #I44TBS
Signed-off-by: Leon Chan <chenwei26@huawei.com>
This commit is contained in:
Leon Chan
2021-08-05 19:53:57 +08:00
parent ba977dd5ab
commit 38a6b804e9
18 changed files with 446 additions and 544 deletions

View File

@@ -44,6 +44,8 @@
#include "los_vm_zone.h"
#include "los_vm_common.h"
struct Vnode;
#ifdef __cplusplus
#if __cplusplus
extern "C" {
@@ -91,8 +93,8 @@ struct VmMapRegion {
UINT8 regionType; /**< vm region type: ANON, FILE, DEV */
union {
struct VmRegionFile {
unsigned int fileMagic;
struct file *file;
int f_oflags;
struct Vnode *vnode;
const LosVmFileOps *vmFOps;
} rf;
struct VmRegionAnon {

View File

@@ -38,6 +38,7 @@
#include "los_mmu_descriptor_v6.h"
#ifdef LOSCFG_FS_VFS
#include "fs/file.h"
#include "vnode.h"
#endif
#include "los_printf.h"
#include "los_vm_page.h"
@@ -55,13 +56,13 @@
const CHAR *OsGetRegionNameOrFilePath(LosVmMapRegion *region)
{
struct file *filep = NULL;
struct Vnode *vnode = NULL;
if (region == NULL) {
return "";
#ifdef LOSCFG_FS_VFS
} else if (LOS_IsRegionFileValid(region)) {
filep = region->unTypeData.rf.file;
return filep->f_path;
vnode = region->unTypeData.rf.vnode;
return vnode->filePath;
#endif
} else if (region->regionFlags & VM_MAP_REGION_FLAG_HEAP) {
return "HEAP";

View File

@@ -45,6 +45,10 @@
#include "los_process_pri.h"
#include "arm.h"
#ifdef LOSCFG_FS_VFS
#include "vnode.h"
#endif
#ifdef LOSCFG_KERNEL_VM
@@ -106,11 +110,11 @@ STATIC STATUS_T OsDoReadFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
return LOS_OK;
}
if (region->unTypeData.rf.vmFOps == NULL || region->unTypeData.rf.vmFOps->fault == NULL) {
VM_ERR("region args invalid, file path: %s", region->unTypeData.rf.file->f_path);
VM_ERR("region args invalid, file path: %s", region->unTypeData.rf.vnode->filePath);
return LOS_ERRNO_VM_INVALID_ARGS;
}
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.vnode->mapping.mux_lock);
ret = region->unTypeData.rf.vmFOps->fault(region, vmPgFault);
if (ret == LOS_OK) {
paddr = LOS_PaddrQuery(vmPgFault->pageKVaddr);
@@ -124,14 +128,14 @@ STATIC STATUS_T OsDoReadFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
if (ret < 0) {
VM_ERR("LOS_ArchMmuMap failed");
OsDelMapInfo(region, vmPgFault, false);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
return LOS_ERRNO_VM_NO_MEMORY;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
return LOS_OK;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
return LOS_ERRNO_VM_NO_MEMORY;
}
@@ -145,8 +149,8 @@ STATIC LosVmPage *OsCowUnmapOrg(LosArchMmu *archMmu, LosVmMapRegion *region, Los
LosFilePage *fpage = NULL;
VADDR_T vaddr = (VADDR_T)vmf->vaddr;
LOS_SpinLockSave(&region->unTypeData.rf.file->f_mapping->list_lock, &intSave);
fpage = OsFindGetEntry(region->unTypeData.rf.file->f_mapping, vmf->pgoff);
LOS_SpinLockSave(&region->unTypeData.rf.vnode->mapping.list_lock, &intSave);
fpage = OsFindGetEntry(&region->unTypeData.rf.vnode->mapping, vmf->pgoff);
if (fpage != NULL) {
oldPage = fpage->vmPage;
OsSetPageLocked(oldPage);
@@ -159,7 +163,7 @@ STATIC LosVmPage *OsCowUnmapOrg(LosArchMmu *archMmu, LosVmMapRegion *region, Los
} else {
LOS_ArchMmuUnmap(archMmu, vaddr, 1);
}
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
LOS_SpinUnlockRestore(&region->unTypeData.rf.vnode->mapping.list_lock, intSave);
return oldPage;
}
@@ -197,11 +201,11 @@ status_t OsDoCowFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
newPaddr = VM_PAGE_TO_PHYS(newPage);
kvaddr = OsVmPageToVaddr(newPage);
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.vnode->mapping.mux_lock);
ret = region->unTypeData.rf.vmFOps->fault(region, vmPgFault);
if (ret != LOS_OK) {
VM_ERR("call region->vm_ops->fault fail");
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
goto ERR_OUT;
}
@@ -227,10 +231,10 @@ status_t OsDoCowFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
if (ret < 0) {
VM_ERR("LOS_ArchMmuMap failed");
ret = LOS_ERRNO_VM_NO_MEMORY;
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
goto ERR_OUT;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
if (oldPage != NULL) {
OsCleanPageLocked(oldPage);
@@ -273,17 +277,17 @@ status_t OsDoSharedFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
return LOS_ERRNO_VM_NO_MEMORY;
}
LOS_SpinLockSave(&region->unTypeData.rf.file->f_mapping->list_lock, &intSave);
fpage = OsFindGetEntry(region->unTypeData.rf.file->f_mapping, vmPgFault->pgoff);
LOS_SpinLockSave(&region->unTypeData.rf.vnode->mapping.list_lock, &intSave);
fpage = OsFindGetEntry(&region->unTypeData.rf.vnode->mapping, vmPgFault->pgoff);
if (fpage) {
OsMarkPageDirty(fpage, region, 0, 0);
}
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
LOS_SpinUnlockRestore(&region->unTypeData.rf.vnode->mapping.list_lock, intSave);
return LOS_OK;
}
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.vnode->mapping.mux_lock);
ret = region->unTypeData.rf.vmFOps->fault(region, vmPgFault);
if (ret == LOS_OK) {
paddr = LOS_PaddrQuery(vmPgFault->pageKVaddr);
@@ -297,14 +301,14 @@ status_t OsDoSharedFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
if (ret < 0) {
VM_ERR("LOS_ArchMmuMap failed. ret=%d", ret);
OsDelMapInfo(region, vmPgFault, TRUE);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
return LOS_ERRNO_VM_NO_MEMORY;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
return LOS_OK;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
return ret;
}
@@ -382,7 +386,7 @@ STATUS_T OsVmPageFaultHandler(VADDR_T vaddr, UINT32 flags, ExcContext *frame)
vaddr = ROUNDDOWN(vaddr, PAGE_SIZE);
#ifdef LOSCFG_FS_VFS
if (LOS_IsRegionFileValid(region)) {
if (region->unTypeData.rf.file->f_mapping == NULL) {
if (region->unTypeData.rf.vnode == NULL) {
goto CHECK_FAILED;
}
vmPgFault.vaddr = vaddr;

View File

@@ -172,17 +172,17 @@ VOID OsVmmFileRemove(LosVmMapRegion *region, LosArchMmu *archMmu, VM_OFFSET_T pg
UINT32 intSave;
vaddr_t vaddr;
paddr_t paddr = 0;
struct file *file = NULL;
struct Vnode *vnode = NULL;
struct page_mapping *mapping = NULL;
LosFilePage *fpage = NULL;
LosFilePage *tmpPage = NULL;
LosVmPage *mapPage = NULL;
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.file->f_mapping == NULL)) {
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.vnode == NULL)) {
return;
}
file = region->unTypeData.rf.file;
mapping = file->f_mapping;
vnode = region->unTypeData.rf.vnode;
mapping = &vnode->mapping;
vaddr = region->range.base + ((UINT32)(pgoff - region->pgOff) << PAGE_SHIFT);
status_t status = LOS_ArchMmuQuery(archMmu, vaddr, &paddr, NULL);
@@ -232,15 +232,15 @@ VOID OsMarkPageDirty(LosFilePage *fpage, LosVmMapRegion *region, INT32 off, INT3
}
}
STATIC UINT32 GetDirtySize(LosFilePage *fpage, struct file *file)
STATIC UINT32 GetDirtySize(LosFilePage *fpage, struct Vnode *vnode)
{
UINT32 fileSize;
UINT32 dirtyBegin;
UINT32 dirtyEnd;
struct stat buf_stat;
if (stat(file->f_path, &buf_stat) != OK) {
VM_ERR("FlushDirtyPage get file size failed. (filepath=%s)", file->f_path);
if (stat(vnode->filePath, &buf_stat) != OK) {
VM_ERR("FlushDirtyPage get file size failed. (filePath=%s)", vnode->filePath);
return 0;
}
@@ -264,31 +264,29 @@ STATIC INT32 OsFlushDirtyPage(LosFilePage *fpage)
UINT32 ret;
size_t len;
char *buff = NULL;
VM_OFFSET_T oldPos;
struct file *file = fpage->mapping->host;
if ((file == NULL) || (file->f_vnode == NULL)) {
VM_ERR("page cache file error");
struct Vnode *vnode = fpage->mapping->host;
if (vnode == NULL) {
VM_ERR("page cache vnode error");
return LOS_NOK;
}
oldPos = file_seek(file, 0, SEEK_CUR);
buff = (char *)OsVmPageToVaddr(fpage->vmPage);
file_seek(file, (((UINT32)fpage->pgoff << PAGE_SHIFT) + fpage->dirtyOff), SEEK_SET);
len = fpage->dirtyEnd - fpage->dirtyOff;
len = (len == 0) ? GetDirtySize(fpage, file) : len;
len = (len == 0) ? GetDirtySize(fpage, vnode) : len;
if (len == 0) {
OsCleanPageDirty(fpage->vmPage);
(VOID)file_seek(file, oldPos, SEEK_SET);
return LOS_OK;
}
ret = file_write(file, (VOID *)buff, len);
buff = (char *)OsVmPageToVaddr(fpage->vmPage);
/* actually, we did not update the fpage->dirtyOff */
ret = vnode->vop->WritePage(vnode, (VOID *)buff, fpage->pgoff, len);
if (ret <= 0) {
VM_ERR("WritePage error ret %d", ret);
} else {
OsCleanPageDirty(fpage->vmPage);
}
ret = (ret <= 0) ? LOS_NOK : LOS_OK;
OsCleanPageDirty(fpage->vmPage);
(VOID)file_seek(file, oldPos, SEEK_SET);
return ret;
}
@@ -336,15 +334,17 @@ VOID OsDelMapInfo(LosVmMapRegion *region, LosVmPgFault *vmf, BOOL cleanDirty)
UINT32 intSave;
LosMapInfo *info = NULL;
LosFilePage *fpage = NULL;
struct page_mapping *mapping = NULL;
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.file->f_mapping == NULL) || (vmf == NULL)) {
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.vnode == NULL) || (vmf == NULL)) {
return;
}
LOS_SpinLockSave(&region->unTypeData.rf.file->f_mapping->list_lock, &intSave);
fpage = OsFindGetEntry(region->unTypeData.rf.file->f_mapping, vmf->pgoff);
mapping = &region->unTypeData.rf.vnode->mapping;
LOS_SpinLockSave(&mapping->list_lock, &intSave);
fpage = OsFindGetEntry(mapping, vmf->pgoff);
if (fpage == NULL) {
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
return;
}
@@ -356,31 +356,30 @@ VOID OsDelMapInfo(LosVmMapRegion *region, LosVmPgFault *vmf, BOOL cleanDirty)
fpage->n_maps--;
LOS_ListDelete(&info->node);
LOS_AtomicDec(&fpage->vmPage->refCounts);
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
LOS_MemFree(m_aucSysMem0, info);
return;
}
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
}
INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
{
INT32 ret;
VM_OFFSET_T oldPos;
VOID *kvaddr = NULL;
UINT32 intSave;
bool newCache = false;
struct file *file = NULL;
struct Vnode *vnode = NULL;
struct page_mapping *mapping = NULL;
LosFilePage *fpage = NULL;
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.file->f_mapping == NULL) || (vmf == NULL)) {
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.vnode == NULL) || (vmf == NULL)) {
VM_ERR("Input param is NULL");
return LOS_NOK;
}
file = region->unTypeData.rf.file;
mapping = file->f_mapping;
vnode = region->unTypeData.rf.vnode;
mapping = &vnode->mapping;
/* get or create a new cache node */
LOS_SpinLockSave(&mapping->list_lock, &intSave);
@@ -404,10 +403,7 @@ INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
/* read file to new page cache */
if (newCache) {
oldPos = file_seek(file, 0, SEEK_CUR);
file_seek(file, fpage->pgoff << PAGE_SHIFT, SEEK_SET);
ret = file_read(file, kvaddr, PAGE_SIZE);
file_seek(file, oldPos, SEEK_SET);
ret = vnode->vop->ReadPage(vnode, kvaddr, fpage->pgoff << PAGE_SHIFT);
if (ret == 0) {
VM_ERR("Failed to read from file!");
OsReleaseFpage(mapping, fpage);
@@ -505,8 +501,9 @@ LosVmFileOps g_commVmOps = {
INT32 OsVfsFileMmap(struct file *filep, LosVmMapRegion *region)
{
region->unTypeData.rf.vmFOps = &g_commVmOps;
region->unTypeData.rf.file = filep;
region->unTypeData.rf.fileMagic = filep->f_magicnum;
region->unTypeData.rf.vnode = filep->f_vnode;
region->unTypeData.rf.f_oflags = filep->f_oflags;
return ENOERR;
}
@@ -516,11 +513,11 @@ STATUS_T OsNamedMMap(struct file *filep, LosVmMapRegion *region)
if (filep == NULL) {
return LOS_ERRNO_VM_MAP_FAILED;
}
file_hold(filep);
vnode = filep->f_vnode;
if (vnode == NULL) {
return LOS_ERRNO_VM_MAP_FAILED;
}
VnodeHold();
vnode->useCount++;
VnodeDrop();
if (filep->ops != NULL && filep->ops->mmap != NULL) {
if (vnode->type == VNODE_TYPE_CHR || vnode->type == VNODE_TYPE_BLK) {
LOS_SetRegionTypeDev(region);
@@ -529,12 +526,15 @@ STATUS_T OsNamedMMap(struct file *filep, LosVmMapRegion *region)
}
int ret = filep->ops->mmap(filep, region);
if (ret != LOS_OK) {
file_release(filep);
return LOS_ERRNO_VM_MAP_FAILED;
}
} else {
VM_ERR("mmap file type unknown");
file_release(filep);
return LOS_ERRNO_VM_MAP_FAILED;
}
file_release(filep);
return LOS_OK;
}
@@ -600,40 +600,7 @@ LosFilePage *OsPageCacheAlloc(struct page_mapping *mapping, VM_OFFSET_T pgoff)
return fpage;
}
#ifdef LOSCFG_FS_VFS
VOID OsVmmFileRegionFree(struct file *filep, LosProcessCB *processCB)
{
int ret;
LosVmSpace *space = NULL;
LosVmMapRegion *region = NULL;
LosRbNode *pstRbNode = NULL;
LosRbNode *pstRbNodeTmp = NULL;
if (processCB == NULL) {
processCB = OsCurrProcessGet();
}
space = processCB->vmSpace;
if (space != NULL) {
(VOID)LOS_MuxAcquire(&space->regionMux);
/* free the regions associated with filep */
RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeTmp)
region = (LosVmMapRegion *)pstRbNode;
if (LOS_IsRegionFileValid(region)) {
if (region->unTypeData.rf.file != filep) {
continue;
}
ret = LOS_RegionFree(space, region);
if (ret != LOS_OK) {
VM_ERR("free region error, space %p, region %p", space, region);
}
}
RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeTmp)
(VOID)LOS_MuxRelease(&space->regionMux);
}
}
#endif
#else
#ifndef LOSCFG_FS_VFS
INT32 OsVfsFileMmap(struct file *filep, LosVmMapRegion *region)
{
UNUSED(filep);
@@ -642,3 +609,4 @@ INT32 OsVfsFileMmap(struct file *filep, LosVmMapRegion *region)
}
#endif
#endif

View File

@@ -42,6 +42,7 @@
#include "los_process_pri.h"
#ifdef LOSCFG_FS_VFS
#include "fs/file.h"
#include "vnode.h"
#endif
#include "los_task.h"
#include "los_memory_pri.h"
@@ -308,12 +309,12 @@ STATUS_T LOS_VmSpaceClone(LosVmSpace *oldVmSpace, LosVmSpace *newVmSpace)
#ifdef LOSCFG_FS_VFS
if (LOS_IsRegionFileValid(oldRegion)) {
LosFilePage *fpage = NULL;
LOS_SpinLockSave(&oldRegion->unTypeData.rf.file->f_mapping->list_lock, &intSave);
fpage = OsFindGetEntry(oldRegion->unTypeData.rf.file->f_mapping, newRegion->pgOff + i);
LOS_SpinLockSave(&oldRegion->unTypeData.rf.vnode->mapping.list_lock, &intSave);
fpage = OsFindGetEntry(&oldRegion->unTypeData.rf.vnode->mapping, newRegion->pgOff + i);
if ((fpage != NULL) && (fpage->vmPage == page)) { /* cow page no need map */
OsAddMapInfo(fpage, &newVmSpace->archMmu, vaddr);
}
LOS_SpinUnlockRestore(&oldRegion->unTypeData.rf.file->f_mapping->list_lock, intSave);
LOS_SpinUnlockRestore(&oldRegion->unTypeData.rf.vnode->mapping.list_lock, intSave);
}
#endif
}
@@ -436,13 +437,9 @@ VADDR_T OsAllocSpecificRange(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UIN
BOOL LOS_IsRegionFileValid(LosVmMapRegion *region)
{
struct file *filep = NULL;
if ((region != NULL) && (LOS_IsRegionTypeFile(region)) &&
(region->unTypeData.rf.file != NULL)) {
filep = region->unTypeData.rf.file;
if (region->unTypeData.rf.fileMagic == filep->f_magicnum) {
return TRUE;
}
(region->unTypeData.rf.vnode != NULL)) {
return TRUE;
}
return FALSE;
}
@@ -465,6 +462,7 @@ LosVmMapRegion *OsCreateRegion(VADDR_T vaddr, size_t len, UINT32 regionFlags, un
return region;
}
memset_s(region, sizeof(LosVmMapRegion), 0, sizeof(LosVmMapRegion));
region->range.base = vaddr;
region->range.size = len;
region->pgOff = offset;
@@ -624,6 +622,9 @@ STATUS_T LOS_RegionFree(LosVmSpace *space, LosVmMapRegion *region)
#ifdef LOSCFG_FS_VFS
if (LOS_IsRegionFileValid(region)) {
OsFilePagesRemove(space, region);
VnodeHold();
region->unTypeData.rf.vnode->useCount--;
VnodeDrop();
} else
#endif
@@ -675,8 +676,11 @@ LosVmMapRegion *OsVmRegionDup(LosVmSpace *space, LosVmMapRegion *oldRegion, VADD
#ifdef LOSCFG_FS_VFS
if (LOS_IsRegionTypeFile(oldRegion)) {
newRegion->unTypeData.rf.vmFOps = oldRegion->unTypeData.rf.vmFOps;
newRegion->unTypeData.rf.file = oldRegion->unTypeData.rf.file;
newRegion->unTypeData.rf.fileMagic = oldRegion->unTypeData.rf.fileMagic;
newRegion->unTypeData.rf.vnode = oldRegion->unTypeData.rf.vnode;
newRegion->unTypeData.rf.f_oflags = oldRegion->unTypeData.rf.f_oflags;
VnodeHold();
newRegion->unTypeData.rf.vnode->useCount++;
VnodeDrop();
}
#endif

View File

@@ -177,7 +177,7 @@ STATIC INLINE BOOL OsProtMprotectPermCheck(unsigned long prot, LosVmMapRegion *r
{
UINT32 protFlags = 0;
UINT32 permFlags = 0;
UINT32 fileFlags = (((region->unTypeData).rf).file)->f_oflags;
UINT32 fileFlags = region->unTypeData.rf.f_oflags;
permFlags |= ((fileFlags & O_ACCMODE) ^ O_RDONLY) ? 0 : VM_MAP_REGION_FLAG_PERM_READ;
permFlags |= (fileFlags & O_WRONLY) ? VM_MAP_REGION_FLAG_PERM_WRITE : 0;
permFlags |= (fileFlags & O_RDWR) ? (VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE) : 0;