summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2002-06-19 22:41:53 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-06-19 22:41:53 -0700
commit74f58650cc458fd2cd3fd5058ba345e2e74612bd (patch)
tree509e5d1fbdbea01e0e638b2f82159a451e3b856e /kernel
parent0e042f3a9e3607e5f93f42831ef01dbe835fa2b1 (diff)
[PATCH] Futex bugfixes.
This uses page_cache_release() instead of put_page(), as it might be a pagecache page.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/futex.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/kernel/futex.c b/kernel/futex.c
index bdff307969ef..332acaa2d6c5 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -70,6 +70,14 @@ static inline void tell_waiter(struct futex_q *q)
wake_up_all(&q->waiters);
}
+static inline void unpin_page(struct page *page)
+{
+ /* Avoid releasing the page which is on the LRU list. I don't
+ know if this is correct, but it stops the BUG() in
+ __free_pages_ok(). */
+ page_cache_release(page);
+}
+
static int futex_wake(struct list_head *head,
struct page *page,
unsigned int offset,
@@ -130,9 +138,9 @@ static struct page *pin_page(unsigned long page_start)
int err;
down_read(&mm->mmap_sem);
- err = get_user_pages(current, current->mm, page_start,
+ err = get_user_pages(current, mm, page_start,
1 /* one page */,
- 1 /* writable */,
+ 0 /* writable not important */,
0 /* don't force */,
&page,
NULL /* don't return vmas */);
@@ -223,7 +231,7 @@ asmlinkage int sys_futex(void *uaddr, int op, int val, struct timespec *utime)
default:
ret = -EINVAL;
}
- page_cache_release(page);
+ unpin_page(page);
return ret;
}