The patch below includes the last one, and more or less reverts the 2.3.14
changes (without reintroducing the bug it was meant to fix, I hope). Would
it actually make sense to look at the whole function again? AFAICS the comments
about overlapping allocation and I/O are wrong - surely we have to start the
I/O, *then* allocate the page, if we want to overlap them? Would that be worth
doing?
Does lmbench time this sort of stuff?
(Oh, I fixed a rather misleading comment in memory.c as well):
--- mm/filemap.c.orig Fri Aug 20 05:33:00 1999
+++ mm/filemap.c Fri Aug 20 05:43:59 1999
@@ -1315,8 +1315,10 @@
goto failure;
}
- if (!Page_Uptodate(page))
+ if (!Page_Uptodate(page)) {
+ lock_page(page);
goto page_not_uptodate;
+ }
success:
/*
@@ -1337,8 +1339,13 @@
}
/*
- * No sharing ... copy to the new page.
+ * No sharing ... get a new page if necessary and copy to it.
*/
+ if (!new_page)
+ new_page = page_cache_alloc();
+ if (!new_page)
+ goto no_page;
+
copy_page(new_page, old_page);
flush_page_to_ram(new_page);
page_cache_release(page);
@@ -1346,6 +1353,13 @@
no_cached_page:
/*
+ * read ahead won't read past end of file, so we will have
+ * to add the page ourselves.
+ */
+ if (offset >= inode->i_size)
+ goto add_new_page;
+
+ /*
* Try to read in an entire cluster at once.
*/
reada = offset;
@@ -1362,8 +1376,22 @@
*/
goto retry_find;
+add_new_page:
+ if (!new_page)
+ new_page = page_cache_alloc();
+ if (!new_page)
+ goto no_page;
+
+ /*
+ * Add the new page to the page cache. If someone beat
+ * us to it, go and look for the page again.
+ */
+ page = page_cache_entry(new_page);
+ if (add_to_page_cache_unique(page, inode, offset, hash))
+ goto retry_find;
+ new_page = 0;
+
page_not_uptodate:
- lock_page(page);
if (Page_Uptodate(page)) {
UnlockPage(page);
goto success;
@@ -1375,6 +1403,7 @@
wait_on_page(page);
if (Page_Uptodate(page))
goto success;
+ lock_page(page);
}
/*
@@ -1383,8 +1412,11 @@
* because there really aren't any performance issues here
* and we need to check for errors.
*/
- if (!PageLocked(page))
- PAGE_BUG(page);
+ if (Page_Uptodate(page)) {
+ UnlockPage(page);
+ goto success;
+ }
+
ClearPageError(page);
error = inode->i_op->readpage(file, page);
if (error)
--- mm/memory.c.orig Fri Aug 20 04:51:16 1999
+++ mm/memory.c Fri Aug 20 04:51:29 1999
@@ -1034,8 +1034,7 @@
* As this is called only for pages that do not currently exist, we
* do not need to flush old virtual caches or the TLB.
*
- * This is called with the MM semaphore and the kernel lock held.
- * We need to release the kernel lock as soon as possible..
+ * This is called with the MM semaphore held.
*/
static int do_no_page(struct task_struct * tsk, struct vm_area_struct * vma,
unsigned long address, int write_access, pte_t *page_table)
-- When in doubt, use brute force. -- Ken Thompson- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/