Philippe Gerum wrote:
> On Tue, 2007-08-07 at 17:09 +0200, Gilles Chanteperdrix wrote:
>> On 8/7/07, Jan Kiszka <[EMAIL PROTECTED]> wrote:
>>> Gilles Chanteperdrix wrote:
>>>> The fact that you are in a hurry should not be an excuse to propose a
>>>> fix which is much worse than the bug itself.
>>> Please explain.
>> Using GFP_ATOMIC is not a good idea, because the kernel needs the
>> GFP_ATOMIC pools for allocation that take place from really atomic
>> contexts such as interruption handlers for instance. fork should not
>> be an atomic context.
>>
>> So the only reason I see why you propose this patch is because you are
>> in a hurry. Ok, before we fix this properly, you can use GFP_ATOMIC
>> locally, but please do not make
>> this an official patch.
>>
> 
> I'm afraid you are both right. Draining pages from the atomic pool might
> starve truely atomic contexts, and releasing the lock guarding the
> pagetable pages for the source mm seems contradictory with what the
> current code tries to achieve in holding it.
> 
> Here is a patch preallocating the page for the cow-breaking code, which
> relies on the lock breaking pattern already in place. Not exactly
> pretty, slightly tested here (UP, spinlock debug), but looks ok so far.
> Needs SMP testing before any attempt is made to merge it.

Funny. I just finished my own patch of this kind and made it pass a
basic COW stress test here. Find it below, it is very similar. Will
now analyse yours to see which one looks nicer and/or is more correct.

Jan


---
 mm/memory.c |   38 +++++++++++++++++++++++++++++---------
 1 file changed, 29 insertions(+), 9 deletions(-)

Index: linux-2.6.20.15/mm/memory.c
===================================================================
--- linux-2.6.20.15.orig/mm/memory.c
+++ linux-2.6.20.15/mm/memory.c
@@ -456,7 +456,7 @@ static inline void cow_user_page(struct 
 static inline int
 copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                pte_t *dst_pte, pte_t *src_pte, struct vm_area_struct *vma,
-               unsigned long addr, int *rss)
+               unsigned long addr, int *rss, struct page **new_page)
 {
        unsigned long vm_flags = vma->vm_flags;
        pte_t pte = *src_pte;
@@ -498,13 +498,15 @@ copy_one_pte(struct mm_struct *dst_mm, s
 #ifdef CONFIG_IPIPE
                if (((vm_flags|src_mm->def_flags) & (VM_LOCKED|VM_PINNED)) == 
(VM_LOCKED|VM_PINNED)) {
                        struct page *old_page = vm_normal_page(vma, addr, pte);
-                       page = alloc_page_vma(GFP_HIGHUSER, vma, addr);
+
+                       page = *new_page;
                        if (!page)
                                return -ENOMEM;
+                       *new_page = NULL;
 
                        cow_user_page(page, old_page, addr, vma);
                        pte = mk_pte(page, vma->vm_page_prot);
-                       
+
                        if (vm_flags & VM_SHARED)
                                pte = pte_mkclean(pte);
                        pte = pte_mkold(pte);
@@ -546,12 +548,23 @@ static int copy_pte_range(struct mm_stru
        spinlock_t *src_ptl, *dst_ptl;
        int progress = 0;
        int rss[2];
+       int err = 0;
+       int need_new_pages = 0;
+       struct page *new_page = NULL;
 
 again:
+       if (need_new_pages && !new_page) {
+               new_page = alloc_page_vma(GFP_HIGHUSER, vma, addr);
+               if (!new_page)
+                       return -ENOMEM;
+       }
+
        rss[1] = rss[0] = 0;
        dst_pte = pte_alloc_map_lock(dst_mm, dst_pmd, addr, &dst_ptl);
-       if (!dst_pte)
-               return -ENOMEM;
+       if (!dst_pte) {
+               err = -ENOMEM;
+               goto cleanup_exit;
+       }
        src_pte = pte_offset_map_nested(src_pmd, addr);
        src_ptl = pte_lockptr(src_mm, src_pmd);
        spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
@@ -574,10 +587,13 @@ again:
                        continue;
                }
                if (copy_one_pte(dst_mm, src_mm, dst_pte,
-                                src_pte, vma, addr, rss))
-                       return -ENOMEM;
+                                src_pte, vma, addr, rss, &new_page) < 0) {
+                       need_new_pages = 1;
+                       break;
+               }
                progress += 8;
-       } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end);
+       } while (dst_pte++, src_pte++, addr += PAGE_SIZE,
+                addr != end && (!need_new_pages || new_page));
 
        arch_leave_lazy_mmu_mode();
        spin_unlock(src_ptl);
@@ -587,7 +603,11 @@ again:
        cond_resched();
        if (addr != end)
                goto again;
-       return 0;
+
+cleanup_exit:
+       if (new_page)
+               page_cache_release(new_page);
+       return err;
 }
 
 static inline int copy_pmd_range(struct mm_struct *dst_mm, struct mm_struct 
*src_mm,


Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Xenomai-core mailing list
Xenomai-core@gna.org
https://mail.gna.org/listinfo/xenomai-core

Reply via email to