From 859b81ab005ac2e2673de3d248534206180058d1 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sun, 29 Jul 2012 20:22:20 +0200 Subject: [PATCH] --- yaml --- r: 320471 b: refs/heads/master c: 9f92448ceeea5326db7d114005a7e7ac03904edf h: refs/heads/master i: 320469: 2ec373569f1286b2105df0dc8e15b711543e0c69 320467: eedacddfdfdc891daf143a46d43c45e7460a8a41 320463: c6d86850f0387d8bd3eaffbfe285d66d75194536 v: v3 --- [refs] | 2 +- trunk/kernel/events/uprobes.c | 27 ++++++++++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/[refs] b/[refs] index 09f54d933c83..cb2a53fc6dbe 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 089ba999dc881a7549d97c55ac9e0052d061867d +refs/heads/master: 9f92448ceeea5326db7d114005a7e7ac03904edf diff --git a/trunk/kernel/events/uprobes.c b/trunk/kernel/events/uprobes.c index 23c562b7fc2e..5db150b306d2 100644 --- a/trunk/kernel/events/uprobes.c +++ b/trunk/kernel/events/uprobes.c @@ -139,10 +139,15 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, struct mm_struct *mm = vma->vm_mm; spinlock_t *ptl; pte_t *ptep; + int err; + /* freeze PageSwapCache() for try_to_free_swap() below */ + lock_page(page); + + err = -EAGAIN; ptep = page_check_address(page, mm, addr, &ptl, 0); if (!ptep) - return -EAGAIN; + goto unlock; get_page(kpage); page_add_new_anon_rmap(kpage, vma, addr); @@ -162,7 +167,10 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr, put_page(page); pte_unmap_unlock(ptep, ptl); - return 0; + err = 0; + unlock: + unlock_page(page); + return err; } /** @@ -216,15 +224,10 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, ret = -ENOMEM; new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr); if (!new_page) - goto put_out; + goto put_old; __SetPageUptodate(new_page); - /* - * lock page will serialize against do_wp_page()'s - * PageAnon() handling - */ - lock_page(old_page); /* copy the page now that we've got it stable */ vaddr_old = kmap_atomic(old_page); vaddr_new = kmap_atomic(new_page); @@ -237,15 +240,13 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, ret = anon_vma_prepare(vma); if (ret) - goto unlock_out; + goto put_new; ret = __replace_page(vma, vaddr, old_page, new_page); -unlock_out: - unlock_page(old_page); +put_new: page_cache_release(new_page); - -put_out: +put_old: put_page(old_page); if (unlikely(ret == -EAGAIN))