

We're not allowed to do down_read() on the filemap_copy_from_user() path: the
caller has an atomic kmap.

Just fail the copy and let the filemap_copy_from_user() slow path recover.


 mm/usercopy.c |    9 +++++++++
 1 files changed, 9 insertions(+)

diff -puN mm/usercopy.c~4g4g-pin_page-atomicity-fix mm/usercopy.c
--- 25/mm/usercopy.c~4g4g-pin_page-atomicity-fix	2003-08-03 21:06:24.000000000 -0700
+++ 25-akpm/mm/usercopy.c	2003-08-03 21:08:20.000000000 -0700
@@ -46,6 +46,15 @@ static inline struct page *pin_page(unsi
 	 */
 	spin_unlock(&mm->page_table_lock);
 
+	/*
+	 * In the context of filemap_copy_from_user(), we are not allowed
+	 * to sleep.  We must fail this usercopy attempt and allow
+	 * filemap_copy_from_user() to recover: drop its atomic kmap and use
+	 * a sleeping kmap instead.
+	 */
+	if (in_atomic())
+		return NULL;
+
 	down_read(&mm->mmap_sem);
 	ret = get_user_pages(current, mm, addr, 1, write, 0, &page, NULL);
 	up_read(&mm->mmap_sem);

_
