patch-2.0.31 linux/mm/filemap.c

Next file: linux/mm/kmalloc.c
Previous file: linux/kernel/time.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.30/linux/mm/filemap.c linux/mm/filemap.c
@@ -41,18 +41,7 @@
  * Simple routines for both non-shared and shared mappings.
  */
 
-/*
- * This is a special fast page-free routine that _only_ works
- * on page-cache pages that we are currently using. We can
- * just decrement the page count, because we know that the page
- * has a count > 1 (the page cache itself counts as one, and
- * we're currently using it counts as one). So we don't need
- * the full free_page() stuff..
- */
-static inline void release_page(struct page * page)
-{
-	atomic_dec(&page->count);
-}
+#define release_page(page) __free_page((page))
 
 /*
  * Invalidate the pages of an inode, removing all pages that aren't
@@ -100,7 +89,7 @@
 		/* page wholly truncated - free it */
 		if (offset >= start) {
 			if (PageLocked(page)) {
-				wait_on_page(page);
+				__wait_on_page(page);
 				goto repeat;
 			}
 			inode->i_nrpages--;
@@ -125,7 +114,7 @@
 	}
 }
 
-int shrink_mmap(int priority, int dma)
+int shrink_mmap(int priority, int dma, int can_do_io)
 {
 	static int clock = 0;
 	struct page * page;
@@ -169,8 +158,12 @@
 		switch (page->count) {
 			case 1:
 				/* If it has been referenced recently, don't free it */
-				if (clear_bit(PG_referenced, &page->flags))
+				if (clear_bit(PG_referenced, &page->flags)) {
+					/* age this page potential used */
+					if (priority < 4)
+						age_page(page);
 					break;
+				}
 
 				/* is it a page cache page? */
 				if (page->inode) {
@@ -181,7 +174,7 @@
 				}
 
 				/* is it a buffer cache page? */
-				if (bh && try_to_free_buffer(bh, &bh, 6))
+				if (can_do_io && bh && try_to_free_buffer(bh, &bh, 6))
 					return 1;
 				break;
 
@@ -448,7 +441,7 @@
 
 #define PageAlignSize(size) (((size) + PAGE_SIZE -1) & PAGE_MASK)
 
-#if 0  /* small readahead */
+#ifdef CONFIG_READA_SMALL  /* small readahead */
 #define MAX_READAHEAD PageAlignSize(4096*7)
 #define MIN_READAHEAD PageAlignSize(4096*2)
 #else /* large readahead */
@@ -743,10 +736,7 @@
 	filp->f_reada = 1;
 	if (page_cache)
 		free_page(page_cache);
-	if (!IS_RDONLY(inode)) {
-		inode->i_atime = CURRENT_TIME;
-		inode->i_dirt = 1;
-	}
+	UPDATE_ATIME(inode)
 	if (!read)
 		read = error;
 	return read;
@@ -784,8 +774,15 @@
 found_page:
 	/*
 	 * Ok, found a page in the page cache, now we need to check
-	 * that it's up-to-date
+	 * that it's up-to-date.  First check whether we'll need an
+	 * extra page -- better to overlap the allocation with the I/O.
 	 */
+	if (no_share && !new_page) {
+		new_page = __get_free_page(GFP_KERNEL);
+		if (!new_page)
+			goto failure;
+	}
+
 	if (PageLocked(page))
 		goto page_locked_wait;
 	if (!PageUptodate(page))
@@ -810,13 +807,8 @@
 	}
 
 	/*
-	 * Check that we have another page to copy it over to..
+	 * No sharing ... copy to the new page.
 	 */
-	if (!new_page) {
-		new_page = __get_free_page(GFP_KERNEL);
-		if (!new_page)
-			goto failure;
-	}
 	memcpy((void *) new_page, (void *) old_page, PAGE_SIZE);
 	flush_page_to_ram(new_page);
 	release_page(page);
@@ -880,6 +872,8 @@
 	 */
 failure:
 	release_page(page);
+	if (new_page)
+		free_page(new_page);
 no_page:
 	return 0;
 }
@@ -1003,6 +997,8 @@
 	unsigned long page;
 	int error;
 
+	if (pte_none(pte))
+		return 0;
 	if (!(flags & MS_INVALIDATE)) {
 		if (!pte_present(pte))
 			return 0;
@@ -1015,8 +1011,6 @@
 		page = pte_page(pte);
 		mem_map[MAP_NR(page)].count++;
 	} else {
-		if (pte_none(pte))
-			return 0;
 		flush_cache_page(vma, address);
 		pte_clear(ptep);
 		flush_tlb_page(vma, address);
@@ -1178,10 +1172,7 @@
 		return -EACCES;
 	if (!inode->i_op || !inode->i_op->readpage)
 		return -ENOEXEC;
-	if (!IS_RDONLY(inode)) {
-		inode->i_atime = CURRENT_TIME;
-		inode->i_dirt = 1;
-	}
+	UPDATE_ATIME(inode)
 	vma->vm_inode = inode;
 	inode->i_count++;
 	vma->vm_ops = ops;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov