patch-2.4.5 linux/mm/filemap.c

Next file: linux/mm/highmem.c
Previous file: linux/mm/bootmem.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.4/linux/mm/filemap.c linux/mm/filemap.c
@@ -9,6 +9,7 @@
  * most "normal" filesystems (but you don't /have/ to use this:
  * the NFS filesystem used to do this differently, for example)
  */
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/shm.h>
 #include <linux/mman.h>
@@ -284,6 +285,34 @@
 	spin_unlock(&pagecache_lock);
 }
 
+/*
+ * This function is pretty much like __find_page_nolock(), but it only
+ * requires 2 arguments and doesn't mark the page as touched, making it
+ * ideal for ->writepage() clustering and other places where you don't
+ * want to mark the page referenced.
+ *
+ * The caller needs to hold the pagecache_lock.
+ */
+static struct page * FASTCALL(__find_page_simple(struct address_space *, unsigned long));
+static struct page * __find_page_simple(struct address_space *mapping, unsigned long index)
+{
+	struct page **next = page_hash(mapping, index);;
+
+	for (;;) {
+		struct page *page = *next;
+		if (!page)
+			break;
+		next = &page->next_hash;
+		if (page->mapping != mapping)
+			continue;
+		if (page->index != index)
+			continue;
+		return page;
+	}
+
+	return NULL;
+}
+
 static inline struct page * __find_page_nolock(struct address_space *mapping, unsigned long offset, struct page *page)
 {
 	goto inside;
@@ -298,14 +327,9 @@
 		if (page->index == offset)
 			break;
 	}
-	/*
-	 * Touching the page may move it to the active list.
-	 * If we end up with too few inactive pages, we wake
-	 * up kswapd.
-	 */
-	age_page_up(page);
-	if (inactive_shortage() > inactive_target / 2 && free_shortage())
-			wakeup_kswapd();
+	/* Mark the page referenced, kswapd will find it later. */
+	SetPageReferenced(page);
+
 not_found:
 	return page;
 }
@@ -331,7 +355,7 @@
 	return 0;
 }
 
-static int waitfor_one_page(struct page *page)
+int waitfor_one_page(struct page *page)
 {
 	int error = 0;
 	struct buffer_head *bh, *head = page->buffers;
@@ -762,7 +786,6 @@
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct address_space *mapping = inode->i_mapping;
-	struct page **hash;
 	struct page *page;
 	unsigned long start;
 
@@ -783,8 +806,7 @@
 	 */
 	spin_lock(&pagecache_lock);
 	while (--index >= start) {
-		hash = page_hash(mapping, index);
-		page = __find_page_nolock(mapping, index, *hash);
+		page = __find_page_simple(mapping, index);
 		if (!page)
 			break;
 		deactivate_page(page);
@@ -2549,11 +2571,14 @@
 	 *	Linus frestrict idea will clean these up nicely..
 	 */
 	 
-	if (pos > inode->i_sb->s_maxbytes)
+	if (pos >= inode->i_sb->s_maxbytes)
 	{
-		send_sig(SIGXFSZ, current, 0);
-		err = -EFBIG;
-		goto out;	
+		if (count || pos > inode->i_sb->s_maxbytes) {
+			send_sig(SIGXFSZ, current, 0);
+			err = -EFBIG;
+			goto out;
+		}
+		/* zero-length writes at ->s_maxbytes are OK */
 	}
 
 	if (pos + count > inode->i_sb->s_maxbytes)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)