diff mbox

Btrfs: pwrite blocked when writing from the mmaped buffer of the same page

Message ID 1865303E0DED764181A9D882DEF65FB682F3F80FDF@shsmsx502.ccr.corp.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Xin Zhong Dec. 7, 2010, 9:34 a.m. UTC
None
diff mbox

Patch

diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index c1faded..805f2ee 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -57,11 +57,15 @@  static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
 				     PAGE_CACHE_SIZE - offset, write_bytes);
 		struct page *page = prepared_pages[pg];
 again:
-		if (unlikely(iov_iter_fault_in_readable(i, count)))
-			return -EFAULT;
-
-		/* Copy data from userspace to the current page */
-		copied = iov_iter_copy_from_user(page, i, offset, count);
+		/*
+		 * Copy data from userspace to the current page
+		 *
+		 * Disable pagefault to avoid recursive lock since
+		 * the pages are already locked
+		 */
+		pagefault_disable();
+		copied = iov_iter_copy_from_user_atomic(page, i, offset, count);
+		pagefault_enable();

 		/* Flush processor's dcache for this page */
 		flush_dcache_page(page);
@@ -974,6 +978,15 @@  static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
 		if (ret)
 			goto out;

+		/*
+		 * fault pages before locking them in prepare_pages
+		 * to avoid recursive lock
+		 */
+		if (unlikely(iov_iter_fault_in_readable(&i, write_bytes))) {
+			ret = -EFAULT;
+			goto out;
+		}
+
 		ret = prepare_pages(root, file, pages, num_pages,
 				    pos, first_index, last_index,
 				    write_bytes);