From 7f815dd2ddefa7fa9b53a6d7c604529468dfdd24 Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Sun, 13 Apr 2008 17:03:11 +0100 Subject: [PATCH] Fixed handling of pages that are SHARED and ANONYMOUS Normally anon && shared pages need to COW once and any newer accesses by other sharing processes should simply map the COW'ed pages to themselves as writeable. We didn't have that but instead every ANON && SHARED write fault was going into the COW path, causing the same offset'ed page to be COW'ed twice. Next: Factor out the l4_map code to a common point at the end of all fault handling paths. --- tasks/mm0/src/fault.c | 45 +++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/tasks/mm0/src/fault.c b/tasks/mm0/src/fault.c index 6c592d6..8a73c6e 100644 --- a/tasks/mm0/src/fault.c +++ b/tasks/mm0/src/fault.c @@ -461,14 +461,24 @@ int __do_page_fault(struct fault_data *fault) /* Handle write */ if ((reason & VM_WRITE) && (pte_flags & VM_READ)) { - /* Copy-on-write. For all private 'union' all anonymous vmas. */ - if ((vma_flags & VMA_PRIVATE) || (vma_flags & VMA_ANONYMOUS)) + /* Copy-on-write. All private vmas are always COW */ + if (vma_flags & VMA_PRIVATE) copy_on_write(fault); - /* Regular files */ - if ((vma_flags & VMA_SHARED) && !(vma_flags & VMA_ANONYMOUS)) { - /* No regular files are mapped yet */ - BUG(); + /* + * This handles shared pages that are both anon and non-anon. + * + * Anon/Shared pages: + * First access from first process is COW. All subsequent RW + * accesses (which are attempts of *sharing*) simply map that + * page to faulting processes. + * + * Non-anon/shared pages: + * First access from first process simply writes to the pages + * of that file. All subsequent accesses by other processes + * do so as well. + */ + else if ((vma_flags & VMA_SHARED)) { file_offset = fault_to_file_offset(fault); BUG_ON(!(vmo_link = vma_next_link(&vma->vm_obj_list, &vma->vm_obj_list))); @@ -476,9 +486,23 @@ int __do_page_fault(struct fault_data *fault) /* Get the page from its pager */ if (IS_ERR(page = vmo_link->obj->pager->ops.page_in(vmo_link->obj, file_offset))) { - printf("%s: Could not obtain faulty page.\n", - __TASKNAME__); - BUG(); + /* + * Writable page does not exist, + * if it is anonymous, it needs to be COW'ed, + * otherwise the file must have paged-in this + * page, so its a bug. + */ + if (vma_flags & VMA_ANONYMOUS) { + copy_on_write(fault); + + /* We're done. So return */ + return 0; + } else { + printf("%s: Could not obtain faulty " + "page from regular file.\n", + __TASKNAME__); + BUG(); + } } BUG_ON(!page); @@ -490,7 +514,8 @@ int __do_page_fault(struct fault_data *fault) dprintf("%s: Mapped 0x%x as writable to tid %d.\n", __TASKNAME__, page_align(fault->address), fault->task->tid); vm_object_print(vmo_link->obj); - } + } else + BUG(); } return 0;