static int shared_pagefault(struct vmproc *vmp, struct vir_region *region, struct phys_region *ph, int write, vfs_callback_t cb, void *state, int statelen, int *io) { struct vir_region *src_region; struct vmproc *src_vmp; struct phys_region *pr; if(getsrc(region, &src_vmp, &src_region) != OK) { return EINVAL; } assert(ph->ph->phys == MAP_NONE); pb_free(ph->ph); if(!(pr = physblock_get(src_region, ph->offset))) { int r; if((r=map_pf(src_vmp, src_region, ph->offset, write, NULL, NULL, 0, io)) != OK) return r; if(!(pr = physblock_get(src_region, ph->offset))) { panic("missing region after pagefault handling"); } } pb_link(ph, pr->ph, ph->offset, region); return OK; }
int do_mapcache(message *msg) { dev_t dev = msg->m_u.m_vmmcp.dev; u64_t dev_off = (u64_t) msg->m_u.m_vmmcp.dev_offset_pages * VM_PAGE_SIZE; u64_t ino_off = (u64_t) msg->m_u.m_vmmcp.ino_offset_pages * VM_PAGE_SIZE; int n; int bytes = msg->m_u.m_vmmcp.pages * VM_PAGE_SIZE; struct vir_region *vr; struct vmproc *caller; vir_bytes offset; int io = 0; if(vm_isokendpt(msg->m_source, &n) != OK) panic("bogus source"); caller = &vmproc[n]; if(bytes < VM_PAGE_SIZE) return EINVAL; if(!(vr = map_page_region(caller, VM_PAGE_SIZE, VM_DATATOP, bytes, VR_ANON | VR_WRITABLE, 0, &mem_type_cache))) { printf("VM: map_page_region failed\n"); return ENOMEM; } assert(vr->length == bytes); for(offset = 0; offset < bytes; offset += VM_PAGE_SIZE) { struct cached_page *hb; assert(vr->length == bytes); assert(offset < vr->length); if(!(hb = find_cached_page_bydev(dev, dev_off + offset, msg->m_u.m_vmmcp.ino, ino_off + offset, 1))) { map_unmap_region(caller, vr, 0, bytes); return ENOENT; } assert(!vr->param.pb_cache); vr->param.pb_cache = hb->page; assert(vr->length == bytes); assert(offset < vr->length); if(map_pf(caller, vr, offset, 1, NULL, NULL, 0, &io) != OK) { map_unmap_region(caller, vr, 0, bytes); printf("VM: map_pf failed\n"); return ENOMEM; } assert(!vr->param.pb_cache); } memset(msg, 0, sizeof(*msg)); msg->m_u.m_vmmcp_reply.addr = (void *) vr->vaddr; assert(vr); #if CACHE_SANITY cache_sanitycheck_internal(); #endif return OK; }