1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /**
33 * @defgroup los_vm_filemap vm filemap definition
34 * @ingroup kernel
35 */
36
37 #include "los_vm_filemap.h"
38 #include "los_vm_page.h"
39 #include "los_vm_phys.h"
40 #include "los_vm_common.h"
41 #include "los_vm_fault.h"
42 #include "los_process_pri.h"
43 #include "los_vm_lock.h"
44 #ifdef LOSCFG_FS_VFS
45 #include "vnode.h"
46 #endif
47
48 #ifndef UNUSED
49 #define UNUSED(x) (VOID)(x)
50 #endif
51
52 #ifdef LOSCFG_DEBUG_VERSION
53 static int g_totalPageCacheTry = 0;
54 static int g_totalPageCacheHit = 0;
55 #define TRACE_TRY_CACHE() do { g_totalPageCacheTry++; } while (0)
56 #define TRACE_HIT_CACHE() do { g_totalPageCacheHit++; } while (0)
57
ResetPageCacheHitInfo(int * try,int * hit)58 VOID ResetPageCacheHitInfo(int *try, int *hit)
59 {
60 *try = g_totalPageCacheTry;
61 *hit = g_totalPageCacheHit;
62 g_totalPageCacheHit = 0;
63 g_totalPageCacheTry = 0;
64 }
65 #else
66 #define TRACE_TRY_CACHE()
67 #define TRACE_HIT_CACHE()
68 #endif
69
70 #ifdef LOSCFG_KERNEL_VM
71
OsPageCacheAdd(LosFilePage * page,struct page_mapping * mapping,VM_OFFSET_T pgoff)72 STATIC VOID OsPageCacheAdd(LosFilePage *page, struct page_mapping *mapping, VM_OFFSET_T pgoff)
73 {
74 LosFilePage *fpage = NULL;
75
76 LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) {
77 if (fpage->pgoff > pgoff) {
78 LOS_ListTailInsert(&fpage->node, &page->node);
79 goto done_add;
80 }
81 }
82
83 LOS_ListTailInsert(&mapping->page_list, &page->node);
84
85 done_add:
86 mapping->nrpages++;
87 }
88
OsAddToPageacheLru(LosFilePage * page,struct page_mapping * mapping,VM_OFFSET_T pgoff)89 VOID OsAddToPageacheLru(LosFilePage *page, struct page_mapping *mapping, VM_OFFSET_T pgoff)
90 {
91 OsPageCacheAdd(page, mapping, pgoff);
92 OsLruCacheAdd(page, VM_LRU_ACTIVE_FILE);
93 }
94
OsPageCacheDel(LosFilePage * fpage)95 VOID OsPageCacheDel(LosFilePage *fpage)
96 {
97 /* delete from file cache list */
98 LOS_ListDelete(&fpage->node);
99 fpage->mapping->nrpages--;
100
101 /* unmap and remove map info */
102 if (OsIsPageMapped(fpage)) {
103 OsUnmapAllLocked(fpage);
104 }
105
106 LOS_PhysPageFree(fpage->vmPage);
107
108 LOS_MemFree(m_aucSysMem0, fpage);
109 }
110
OsAddMapInfo(LosFilePage * page,LosArchMmu * archMmu,VADDR_T vaddr)111 VOID OsAddMapInfo(LosFilePage *page, LosArchMmu *archMmu, VADDR_T vaddr)
112 {
113 LosMapInfo *info = NULL;
114
115 info = (LosMapInfo *)LOS_MemAlloc(m_aucSysMem0, sizeof(LosMapInfo));
116 if (info == NULL) {
117 VM_ERR("OsAddMapInfo alloc memory failed!");
118 return;
119 }
120 info->page = page;
121 info->archMmu = archMmu;
122 info->vaddr = vaddr;
123
124 LOS_ListAdd(&page->i_mmap, &info->node);
125 page->n_maps++;
126 }
127
OsGetMapInfo(const LosFilePage * page,const LosArchMmu * archMmu,VADDR_T vaddr)128 LosMapInfo *OsGetMapInfo(const LosFilePage *page, const LosArchMmu *archMmu, VADDR_T vaddr)
129 {
130 LosMapInfo *info = NULL;
131 const LOS_DL_LIST *immap = &page->i_mmap;
132
133 LOS_DL_LIST_FOR_EACH_ENTRY(info, immap, LosMapInfo, node) {
134 if ((info->archMmu == archMmu) && (info->vaddr == vaddr) && (info->page == page)) {
135 return info;
136 }
137 }
138
139 return NULL;
140 }
141
OsDeletePageCacheLru(LosFilePage * page)142 VOID OsDeletePageCacheLru(LosFilePage *page)
143 {
144 /* delete from lru list */
145 OsLruCacheDel(page);
146 /* delete from cache list and free pmm if needed */
147 OsPageCacheDel(page);
148 }
149
OsPageCacheUnmap(LosFilePage * fpage,LosArchMmu * archMmu,VADDR_T vaddr)150 STATIC VOID OsPageCacheUnmap(LosFilePage *fpage, LosArchMmu *archMmu, VADDR_T vaddr)
151 {
152 UINT32 intSave;
153 LosMapInfo *info = NULL;
154
155 LOS_SpinLockSave(&fpage->physSeg->lruLock, &intSave);
156 info = OsGetMapInfo(fpage, archMmu, vaddr);
157 if (info == NULL) {
158 VM_ERR("OsPageCacheUnmap get map info failed!");
159 } else {
160 OsUnmapPageLocked(fpage, info);
161 }
162 if (!(OsIsPageMapped(fpage) && ((fpage->flags & VM_MAP_REGION_FLAG_PERM_EXECUTE) ||
163 OsIsPageDirty(fpage->vmPage)))) {
164 OsPageRefDecNoLock(fpage);
165 }
166
167 LOS_SpinUnlockRestore(&fpage->physSeg->lruLock, intSave);
168 }
169
OsVmmFileRemove(LosVmMapRegion * region,LosArchMmu * archMmu,VM_OFFSET_T pgoff)170 VOID OsVmmFileRemove(LosVmMapRegion *region, LosArchMmu *archMmu, VM_OFFSET_T pgoff)
171 {
172 UINT32 intSave;
173 vaddr_t vaddr;
174 paddr_t paddr = 0;
175 struct Vnode *vnode = NULL;
176 struct page_mapping *mapping = NULL;
177 LosFilePage *fpage = NULL;
178 LosFilePage *tmpPage = NULL;
179 LosVmPage *mapPage = NULL;
180
181 if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.vnode == NULL)) {
182 return;
183 }
184 vnode = region->unTypeData.rf.vnode;
185 mapping = &vnode->mapping;
186 vaddr = region->range.base + ((UINT32)(pgoff - region->pgOff) << PAGE_SHIFT);
187
188 status_t status = LOS_ArchMmuQuery(archMmu, vaddr, &paddr, NULL);
189 if (status != LOS_OK) {
190 return;
191 }
192
193 mapPage = LOS_VmPageGet(paddr);
194
195 /* is page is in cache list */
196 LOS_SpinLockSave(&mapping->list_lock, &intSave);
197 fpage = OsFindGetEntry(mapping, pgoff);
198 /* no cache or have cache but not map(cow), free it direct */
199 if ((fpage == NULL) || (fpage->vmPage != mapPage)) {
200 LOS_PhysPageFree(mapPage);
201 LOS_ArchMmuUnmap(archMmu, vaddr, 1);
202 /* this is a page cache map! */
203 } else {
204 OsPageCacheUnmap(fpage, archMmu, vaddr);
205 if (OsIsPageDirty(fpage->vmPage)) {
206 tmpPage = OsDumpDirtyPage(fpage);
207 }
208 }
209 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
210
211 if (tmpPage) {
212 OsDoFlushDirtyPage(tmpPage);
213 }
214 return;
215 }
216
OsMarkPageDirty(LosFilePage * fpage,const LosVmMapRegion * region,INT32 off,INT32 len)217 VOID OsMarkPageDirty(LosFilePage *fpage, const LosVmMapRegion *region, INT32 off, INT32 len)
218 {
219 if (region != NULL) {
220 OsSetPageDirty(fpage->vmPage);
221 fpage->dirtyOff = off;
222 fpage->dirtyEnd = len;
223 } else {
224 OsSetPageDirty(fpage->vmPage);
225 if ((off + len) > fpage->dirtyEnd) {
226 fpage->dirtyEnd = off + len;
227 }
228
229 if (off < fpage->dirtyOff) {
230 fpage->dirtyOff = off;
231 }
232 }
233 }
234
GetDirtySize(LosFilePage * fpage,struct Vnode * vnode)235 STATIC UINT32 GetDirtySize(LosFilePage *fpage, struct Vnode *vnode)
236 {
237 UINT32 fileSize;
238 UINT32 dirtyBegin;
239 UINT32 dirtyEnd;
240 struct stat buf_stat;
241
242 if (stat(vnode->filePath, &buf_stat) != OK) {
243 VM_ERR("FlushDirtyPage get file size failed. (filePath=%s)", vnode->filePath);
244 return 0;
245 }
246
247 fileSize = buf_stat.st_size;
248 dirtyBegin = ((UINT32)fpage->pgoff << PAGE_SHIFT);
249 dirtyEnd = dirtyBegin + PAGE_SIZE;
250
251 if (dirtyBegin >= fileSize) {
252 return 0;
253 }
254
255 if (dirtyEnd >= fileSize) {
256 return fileSize - dirtyBegin;
257 }
258
259 return PAGE_SIZE;
260 }
261
OsFlushDirtyPage(LosFilePage * fpage)262 STATIC INT32 OsFlushDirtyPage(LosFilePage *fpage)
263 {
264 UINT32 ret;
265 size_t len;
266 char *buff = NULL;
267 struct Vnode *vnode = fpage->mapping->host;
268 if (vnode == NULL) {
269 VM_ERR("page cache vnode error");
270 return LOS_NOK;
271 }
272
273 len = fpage->dirtyEnd - fpage->dirtyOff;
274 len = (len == 0) ? GetDirtySize(fpage, vnode) : len;
275 if (len == 0) {
276 OsCleanPageDirty(fpage->vmPage);
277 return LOS_OK;
278 }
279
280 buff = (char *)OsVmPageToVaddr(fpage->vmPage);
281
282 /* actually, we did not update the fpage->dirtyOff */
283 ret = vnode->vop->WritePage(vnode, (VOID *)buff, fpage->pgoff, len);
284 if (ret <= 0) {
285 VM_ERR("WritePage error ret %d", ret);
286 } else {
287 OsCleanPageDirty(fpage->vmPage);
288 }
289 ret = (ret <= 0) ? LOS_NOK : LOS_OK;
290
291 return ret;
292 }
293
OsDumpDirtyPage(LosFilePage * oldFPage)294 LosFilePage *OsDumpDirtyPage(LosFilePage *oldFPage)
295 {
296 LosFilePage *newFPage = NULL;
297
298 newFPage = (LosFilePage *)LOS_MemAlloc(m_aucSysMem0, sizeof(LosFilePage));
299 if (newFPage == NULL) {
300 VM_ERR("Failed to allocate for temp page!");
301 return NULL;
302 }
303
304 OsCleanPageDirty(oldFPage->vmPage);
305 (VOID)memcpy_s(newFPage, sizeof(LosFilePage), oldFPage, sizeof(LosFilePage));
306
307 return newFPage;
308 }
309
OsDoFlushDirtyPage(LosFilePage * fpage)310 VOID OsDoFlushDirtyPage(LosFilePage *fpage)
311 {
312 if (fpage == NULL) {
313 return;
314 }
315 (VOID)OsFlushDirtyPage(fpage);
316 LOS_MemFree(m_aucSysMem0, fpage);
317 }
318
OsReleaseFpage(struct page_mapping * mapping,LosFilePage * fpage)319 STATIC VOID OsReleaseFpage(struct page_mapping *mapping, LosFilePage *fpage)
320 {
321 UINT32 intSave;
322 UINT32 lruSave;
323 SPIN_LOCK_S *lruLock = &fpage->physSeg->lruLock;
324 LOS_SpinLockSave(&mapping->list_lock, &intSave);
325 LOS_SpinLockSave(lruLock, &lruSave);
326 OsCleanPageLocked(fpage->vmPage);
327 OsDeletePageCacheLru(fpage);
328 LOS_SpinUnlockRestore(lruLock, lruSave);
329 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
330 }
331
OsDelMapInfo(LosVmMapRegion * region,LosVmPgFault * vmf,BOOL cleanDirty)332 VOID OsDelMapInfo(LosVmMapRegion *region, LosVmPgFault *vmf, BOOL cleanDirty)
333 {
334 UINT32 intSave;
335 LosMapInfo *info = NULL;
336 LosFilePage *fpage = NULL;
337 struct page_mapping *mapping = NULL;
338
339 if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.vnode == NULL) || (vmf == NULL)) {
340 return;
341 }
342
343 mapping = ®ion->unTypeData.rf.vnode->mapping;
344 LOS_SpinLockSave(&mapping->list_lock, &intSave);
345 fpage = OsFindGetEntry(mapping, vmf->pgoff);
346 if (fpage == NULL) {
347 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
348 return;
349 }
350
351 if (cleanDirty) {
352 OsCleanPageDirty(fpage->vmPage);
353 }
354 info = OsGetMapInfo(fpage, ®ion->space->archMmu, (vaddr_t)vmf->vaddr);
355 if (info != NULL) {
356 fpage->n_maps--;
357 LOS_ListDelete(&info->node);
358 LOS_AtomicDec(&fpage->vmPage->refCounts);
359 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
360 LOS_MemFree(m_aucSysMem0, info);
361 return;
362 }
363 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
364 }
365
OsVmmFileFault(LosVmMapRegion * region,LosVmPgFault * vmf)366 INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
367 {
368 INT32 ret;
369 VOID *kvaddr = NULL;
370
371 UINT32 intSave;
372 bool newCache = false;
373 struct Vnode *vnode = NULL;
374 struct page_mapping *mapping = NULL;
375 LosFilePage *fpage = NULL;
376
377 if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.vnode == NULL) || (vmf == NULL)) {
378 VM_ERR("Input param is NULL");
379 return LOS_NOK;
380 }
381 vnode = region->unTypeData.rf.vnode;
382 mapping = &vnode->mapping;
383
384 /* get or create a new cache node */
385 LOS_SpinLockSave(&mapping->list_lock, &intSave);
386 fpage = OsFindGetEntry(mapping, vmf->pgoff);
387 TRACE_TRY_CACHE();
388 if (fpage != NULL) {
389 TRACE_HIT_CACHE();
390 OsPageRefIncLocked(fpage);
391 } else {
392 fpage = OsPageCacheAlloc(mapping, vmf->pgoff);
393 if (fpage == NULL) {
394 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
395 VM_ERR("Failed to alloc a page frame");
396 return LOS_NOK;
397 }
398 newCache = true;
399 }
400 OsSetPageLocked(fpage->vmPage);
401 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
402 kvaddr = OsVmPageToVaddr(fpage->vmPage);
403
404 /* read file to new page cache */
405 if (newCache) {
406 ret = vnode->vop->ReadPage(vnode, kvaddr, fpage->pgoff << PAGE_SHIFT);
407 if (ret == 0) {
408 VM_ERR("Failed to read from file!");
409 OsReleaseFpage(mapping, fpage);
410 return LOS_NOK;
411 }
412 LOS_SpinLockSave(&mapping->list_lock, &intSave);
413 OsAddToPageacheLru(fpage, mapping, vmf->pgoff);
414 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
415 }
416
417 LOS_SpinLockSave(&mapping->list_lock, &intSave);
418 /* cow fault case no need to save mapinfo */
419 if (!((vmf->flags & VM_MAP_PF_FLAG_WRITE) && !(region->regionFlags & VM_MAP_REGION_FLAG_SHARED))) {
420 OsAddMapInfo(fpage, ®ion->space->archMmu, (vaddr_t)vmf->vaddr);
421 fpage->flags = region->regionFlags;
422 }
423
424 /* share page fault, mark the page dirty */
425 if ((vmf->flags & VM_MAP_PF_FLAG_WRITE) && (region->regionFlags & VM_MAP_REGION_FLAG_SHARED)) {
426 OsMarkPageDirty(fpage, region, 0, 0);
427 }
428
429 vmf->pageKVaddr = kvaddr;
430 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
431 return LOS_OK;
432 }
433
OsFileCacheFlush(struct page_mapping * mapping)434 VOID OsFileCacheFlush(struct page_mapping *mapping)
435 {
436 UINT32 intSave;
437 UINT32 lruLock;
438 LOS_DL_LIST_HEAD(dirtyList);
439 LosFilePage *ftemp = NULL;
440 LosFilePage *fpage = NULL;
441
442 if (mapping == NULL) {
443 return;
444 }
445 LOS_SpinLockSave(&mapping->list_lock, &intSave);
446 LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) {
447 LOS_SpinLockSave(&fpage->physSeg->lruLock, &lruLock);
448 if (OsIsPageDirty(fpage->vmPage)) {
449 ftemp = OsDumpDirtyPage(fpage);
450 if (ftemp != NULL) {
451 LOS_ListTailInsert(&dirtyList, &ftemp->node);
452 }
453 }
454 LOS_SpinUnlockRestore(&fpage->physSeg->lruLock, lruLock);
455 }
456 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
457
458 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, ftemp, &dirtyList, LosFilePage, node) {
459 OsDoFlushDirtyPage(fpage);
460 }
461 }
462
OsFileCacheRemove(struct page_mapping * mapping)463 VOID OsFileCacheRemove(struct page_mapping *mapping)
464 {
465 UINT32 intSave;
466 UINT32 lruSave;
467 SPIN_LOCK_S *lruLock = NULL;
468 LOS_DL_LIST_HEAD(dirtyList);
469 LosFilePage *ftemp = NULL;
470 LosFilePage *fpage = NULL;
471 LosFilePage *fnext = NULL;
472
473 LOS_SpinLockSave(&mapping->list_lock, &intSave);
474 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, fnext, &mapping->page_list, LosFilePage, node) {
475 lruLock = &fpage->physSeg->lruLock;
476 LOS_SpinLockSave(lruLock, &lruSave);
477 if (OsIsPageDirty(fpage->vmPage)) {
478 ftemp = OsDumpDirtyPage(fpage);
479 if (ftemp != NULL) {
480 LOS_ListTailInsert(&dirtyList, &ftemp->node);
481 }
482 }
483
484 OsDeletePageCacheLru(fpage);
485 LOS_SpinUnlockRestore(lruLock, lruSave);
486 }
487 LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
488
489 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(fpage, fnext, &dirtyList, LosFilePage, node) {
490 OsDoFlushDirtyPage(fpage);
491 }
492 }
493
494 LosVmFileOps g_commVmOps = {
495 .open = NULL,
496 .close = NULL,
497 .fault = OsVmmFileFault,
498 .remove = OsVmmFileRemove,
499 };
500
OsVfsFileMmap(struct file * filep,LosVmMapRegion * region)501 INT32 OsVfsFileMmap(struct file *filep, LosVmMapRegion *region)
502 {
503 region->unTypeData.rf.vmFOps = &g_commVmOps;
504 region->unTypeData.rf.vnode = filep->f_vnode;
505 region->unTypeData.rf.f_oflags = filep->f_oflags;
506
507 return ENOERR;
508 }
509
OsNamedMMap(struct file * filep,LosVmMapRegion * region)510 STATUS_T OsNamedMMap(struct file *filep, LosVmMapRegion *region)
511 {
512 struct Vnode *vnode = NULL;
513 if (filep == NULL) {
514 return LOS_ERRNO_VM_MAP_FAILED;
515 }
516 file_hold(filep);
517 vnode = filep->f_vnode;
518 VnodeHold();
519 vnode->useCount++;
520 VnodeDrop();
521 if (filep->ops != NULL && filep->ops->mmap != NULL) {
522 if (vnode->type == VNODE_TYPE_CHR || vnode->type == VNODE_TYPE_BLK) {
523 LOS_SetRegionTypeDev(region);
524 } else {
525 LOS_SetRegionTypeFile(region);
526 }
527 int ret = filep->ops->mmap(filep, region);
528 if (ret != LOS_OK) {
529 file_release(filep);
530 return LOS_ERRNO_VM_MAP_FAILED;
531 }
532 } else {
533 VM_ERR("mmap file type unknown");
534 file_release(filep);
535 return LOS_ERRNO_VM_MAP_FAILED;
536 }
537 file_release(filep);
538 return LOS_OK;
539 }
540
OsFindGetEntry(struct page_mapping * mapping,VM_OFFSET_T pgoff)541 LosFilePage *OsFindGetEntry(struct page_mapping *mapping, VM_OFFSET_T pgoff)
542 {
543 LosFilePage *fpage = NULL;
544
545 LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) {
546 if (fpage->pgoff == pgoff) {
547 return fpage;
548 }
549
550 if (fpage->pgoff > pgoff) {
551 break;
552 }
553 }
554
555 return NULL;
556 }
557
558 /* need mutex & change memory to dma zone. */
OsPageCacheAlloc(struct page_mapping * mapping,VM_OFFSET_T pgoff)559 LosFilePage *OsPageCacheAlloc(struct page_mapping *mapping, VM_OFFSET_T pgoff)
560 {
561 VOID *kvaddr = NULL;
562 LosVmPhysSeg *physSeg = NULL;
563 LosVmPage *vmPage = NULL;
564 LosFilePage *fpage = NULL;
565
566 vmPage = LOS_PhysPageAlloc();
567 if (vmPage == NULL) {
568 VM_ERR("alloc vm page failed");
569 return NULL;
570 }
571 physSeg = OsVmPhysSegGet(vmPage);
572 kvaddr = OsVmPageToVaddr(vmPage);
573 if ((physSeg == NULL) || (kvaddr == NULL)) {
574 LOS_PhysPageFree(vmPage);
575 VM_ERR("alloc vm page failed!");
576 return NULL;
577 }
578
579 fpage = (LosFilePage *)LOS_MemAlloc(m_aucSysMem0, sizeof(LosFilePage));
580 if (fpage == NULL) {
581 LOS_PhysPageFree(vmPage);
582 VM_ERR("Failed to allocate for page!");
583 return NULL;
584 }
585
586 (VOID)memset_s((VOID *)fpage, sizeof(LosFilePage), 0, sizeof(LosFilePage));
587
588 LOS_ListInit(&fpage->i_mmap);
589 LOS_ListInit(&fpage->node);
590 LOS_ListInit(&fpage->lru);
591 fpage->n_maps = 0;
592 fpage->dirtyOff = PAGE_SIZE;
593 fpage->dirtyEnd = 0;
594 fpage->physSeg = physSeg;
595 fpage->vmPage = vmPage;
596 fpage->mapping = mapping;
597 fpage->pgoff = pgoff;
598 (VOID)memset_s(kvaddr, PAGE_SIZE, 0, PAGE_SIZE);
599
600 return fpage;
601 }
602
603 #ifndef LOSCFG_FS_VFS
OsVfsFileMmap(struct file * filep,LosVmMapRegion * region)604 INT32 OsVfsFileMmap(struct file *filep, LosVmMapRegion *region)
605 {
606 UNUSED(filep);
607 UNUSED(region);
608 return ENOERR;
609 }
610 #endif
611
612 #endif
613