- llist_for_each(pos, n, regions, head)
- {
- if (pos->start <= cur_addr) {
- break;
+ v_mapping mapping;
+ for (size_t i = 0; i < length; i += PG_SIZE) {
+ if (!vmm_lookupat(mnt, start + i, &mapping)) {
+ continue;
+ }
+
+ if (PG_IS_DIRTY(*mapping.pte)) {
+ size_t offset = mapping.va - region->start + region->foff;
+ struct v_inode* inode = region->mfile->inode;
+
+ region->mfile->ops->write_page(inode, (void*)mapping.va, offset);
+
+ *mapping.pte &= ~PG_DIRTY;
+
+ cpu_flush_page((ptr_t)mapping.pte);
+ } else if ((options & MS_INVALIDATE)) {
+ goto invalidate;
+ }
+
+ if (options & MS_INVALIDATE_ALL) {
+ goto invalidate;
+ }
+
+ continue;
+
+ invalidate:
+ *mapping.pte &= ~PG_PRESENT;
+ pmm_free_page(mapping.pa);
+ cpu_flush_page((ptr_t)mapping.pte);
+ }
+}
+
+int
+mem_msync(ptr_t mnt,
+ vm_regions_t* regions,
+ ptr_t addr,
+ size_t length,
+ int options)
+{
+ struct mm_region* pos = list_entry(regions->next, struct mm_region, head);
+ while (length && (ptr_t)&pos->head != (ptr_t)regions) {
+ if (pos->end >= addr && pos->start <= addr) {
+ size_t l = MIN(length, pos->end - addr);
+ mem_sync_pages(mnt, pos, addr, l, options);
+
+ addr += l;
+ length -= l;