## Automatically generated incremental diff
## From:   linux-2.4.14-pre3
## To:     linux-2.4.14-pre4
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.4.14-pre3/Makefile linux/Makefile
--- linux-2.4.14-pre3/Makefile	Mon Dec  3 23:23:22 2001
+++ linux/Makefile	Mon Dec  3 23:23:36 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 14
-EXTRAVERSION =-pre3
+EXTRAVERSION =-pre4
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.14-pre3/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c
--- linux-2.4.14-pre3/arch/i386/kernel/apic.c	Thu Oct  4 18:42:54 2001
+++ linux/arch/i386/kernel/apic.c	Mon Dec  3 23:23:36 2001
@@ -588,6 +588,7 @@
 		goto no_apic;
 	case X86_VENDOR_INTEL:
 		if (boot_cpu_data.x86 == 6 ||
+		    (boot_cpu_data.x86 == 15 && cpu_has_apic) ||
 		    (boot_cpu_data.x86 == 5 && cpu_has_apic))
 			break;
 		goto no_apic;
diff -urN linux-2.4.14-pre3/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- linux-2.4.14-pre3/drivers/block/ll_rw_blk.c	Mon Dec  3 23:23:22 2001
+++ linux/drivers/block/ll_rw_blk.c	Mon Dec  3 23:23:37 2001
@@ -446,12 +446,15 @@
 	DECLARE_WAITQUEUE(wait, current);
 
 	generic_unplug_device(q);
-	add_wait_queue_exclusive(&q->wait_for_request, &wait);
+	add_wait_queue(&q->wait_for_request, &wait);
 	do {
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		if (q->rq[rw].count < batch_requests)
 			schedule();
-	} while ((rq = get_request(q,rw)) == NULL);
+		spin_lock_irq(&io_request_lock);
+		rq = get_request(q,rw);
+		spin_unlock_irq(&io_request_lock);
+	} while (rq == NULL);
 	remove_wait_queue(&q->wait_for_request, &wait);
 	current->state = TASK_RUNNING;
 	return rq;
diff -urN linux-2.4.14-pre3/drivers/block/paride/pcd.c linux/drivers/block/paride/pcd.c
--- linux-2.4.14-pre3/drivers/block/paride/pcd.c	Mon Dec  3 23:23:22 2001
+++ linux/drivers/block/paride/pcd.c	Mon Dec  3 23:23:37 2001
@@ -271,7 +271,7 @@
 	release:		cdrom_release,
 	ioctl:			cdrom_ioctl,
 	check_media_change:	cdrom_media_changed,
-}
+};
 
 static struct cdrom_device_ops pcd_dops = {
 	pcd_open,
diff -urN linux-2.4.14-pre3/drivers/char/drm/drmP.h linux/drivers/char/drm/drmP.h
--- linux-2.4.14-pre3/drivers/char/drm/drmP.h	Tue Oct 23 22:00:10 2001
+++ linux/drivers/char/drm/drmP.h	Mon Dec  3 23:23:37 2001
@@ -780,31 +780,23 @@
 				/* Mapping support (drm_vm.h) */
 #if LINUX_VERSION_CODE < 0x020317
 extern unsigned long DRM(vm_nopage)(struct vm_area_struct *vma,
-				    unsigned long address,
-				    int write_access);
+				    unsigned long address);
 extern unsigned long DRM(vm_shm_nopage)(struct vm_area_struct *vma,
-					unsigned long address,
-					int write_access);
+					unsigned long address);
 extern unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma,
-					unsigned long address,
-					int write_access);
+					unsigned long address);
 extern unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
-				       unsigned long address,
-				       int write_access);
+				       unsigned long address);
 #else
 				/* Return type changed in 2.3.23 */
 extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
-				   unsigned long address,
-				   int write_access);
+				   unsigned long address);
 extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
-				       unsigned long address,
-				       int write_access);
+				       unsigned long address);
 extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
-				       unsigned long address,
-				       int write_access);
+				       unsigned long address);
 extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
-				      unsigned long address,
-				      int write_access);
+				      unsigned long address);
 #endif
 extern void	     DRM(vm_open)(struct vm_area_struct *vma);
 extern void	     DRM(vm_close)(struct vm_area_struct *vma);
diff -urN linux-2.4.14-pre3/drivers/char/drm/drm_vm.h linux/drivers/char/drm/drm_vm.h
--- linux-2.4.14-pre3/drivers/char/drm/drm_vm.h	Tue Oct 23 22:00:11 2001
+++ linux/drivers/char/drm/drm_vm.h	Mon Dec  3 23:23:37 2001
@@ -58,13 +58,11 @@
 
 #if LINUX_VERSION_CODE < 0x020317
 unsigned long DRM(vm_nopage)(struct vm_area_struct *vma,
-			     unsigned long address,
-			     int write_access)
+			     unsigned long address)
 #else
 				/* Return type changed in 2.3.23 */
 struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
-			    unsigned long address,
-			    int write_access)
+			    unsigned long address)
 #endif
 {
 #if __REALLY_HAVE_AGP
@@ -136,13 +134,11 @@
 
 #if LINUX_VERSION_CODE < 0x020317
 unsigned long DRM(vm_shm_nopage)(struct vm_area_struct *vma,
-				 unsigned long address,
-				 int write_access)
+				 unsigned long address)
 #else
 				/* Return type changed in 2.3.23 */
 struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
-				unsigned long address,
-				int write_access)
+				unsigned long address)
 #endif
 {
 #if LINUX_VERSION_CODE >= 0x020300
@@ -272,13 +268,11 @@
 
 #if LINUX_VERSION_CODE < 0x020317
 unsigned long DRM(vm_dma_nopage)(struct vm_area_struct *vma,
-				 unsigned long address,
-				 int write_access)
+				 unsigned long address)
 #else
 				/* Return type changed in 2.3.23 */
 struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
-				unsigned long address,
-				int write_access)
+				unsigned long address)
 #endif
 {
 	drm_file_t	 *priv	 = vma->vm_file->private_data;
@@ -309,13 +303,11 @@
 
 #if LINUX_VERSION_CODE < 0x020317
 unsigned long DRM(vm_sg_nopage)(struct vm_area_struct *vma,
-				unsigned long address,
-				int write_access)
+				unsigned long address)
 #else
 				/* Return type changed in 2.3.23 */
 struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
-			       unsigned long address,
-			       int write_access)
+			       unsigned long address)
 #endif
 {
 #if LINUX_VERSION_CODE >= 0x020300
diff -urN linux-2.4.14-pre3/drivers/char/random.c linux/drivers/char/random.c
--- linux-2.4.14-pre3/drivers/char/random.c	Mon Dec  3 23:23:23 2001
+++ linux/drivers/char/random.c	Mon Dec  3 23:23:37 2001
@@ -569,7 +569,7 @@
 	__u32 w;
 
 	while (nwords--) {
-		w = rotate_left(r->input_rotate, *in);
+		w = rotate_left(r->input_rotate, *in++);
 		i = r->add_ptr = (r->add_ptr - 1) & wordmask;
 		/*
 		 * Normally, we add 7 bits of rotation to the pool.
diff -urN linux-2.4.14-pre3/fs/buffer.c linux/fs/buffer.c
--- linux-2.4.14-pre3/fs/buffer.c	Mon Dec  3 23:23:23 2001
+++ linux/fs/buffer.c	Mon Dec  3 23:23:37 2001
@@ -770,12 +770,6 @@
 	if (!PageError(page))
 		SetPageUptodate(page);
 
-	/*
-	 * Run the hooks that have to be done when a page I/O has completed.
-	 */
-	if (PageTestandClearDecrAfter(page))
-		atomic_dec(&nr_async_pages);
-
 	UnlockPage(page);
 
 	return;
diff -urN linux-2.4.14-pre3/include/linux/mm.h linux/include/linux/mm.h
--- linux-2.4.14-pre3/include/linux/mm.h	Mon Dec  3 23:23:23 2001
+++ linux/include/linux/mm.h	Mon Dec  3 23:23:38 2001
@@ -125,7 +125,7 @@
 struct vm_operations_struct {
 	void (*open)(struct vm_area_struct * area);
 	void (*close)(struct vm_area_struct * area);
-	struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int write_access);
+	struct page * (*nopage)(struct vm_area_struct * area, unsigned long address);
 };
 
 /*
@@ -270,7 +270,7 @@
 #define PG_referenced		 2
 #define PG_uptodate		 3
 #define PG_dirty		 4
-#define PG_decr_after		 5
+#define PG_unused		 5
 #define PG_active		 6
 #define PG_inactive		 7
 #define PG_slab			 8
@@ -325,9 +325,6 @@
 #define SetPageReferenced(page)	set_bit(PG_referenced, &(page)->flags)
 #define ClearPageReferenced(page)	clear_bit(PG_referenced, &(page)->flags)
 #define PageTestandClearReferenced(page)	test_and_clear_bit(PG_referenced, &(page)->flags)
-#define PageDecrAfter(page)	test_bit(PG_decr_after, &(page)->flags)
-#define SetPageDecrAfter(page)	set_bit(PG_decr_after, &(page)->flags)
-#define PageTestandClearDecrAfter(page)	test_and_clear_bit(PG_decr_after, &(page)->flags)
 #define PageSlab(page)		test_bit(PG_slab, &(page)->flags)
 #define PageSetSlab(page)	set_bit(PG_slab, &(page)->flags)
 #define PageClearSlab(page)	clear_bit(PG_slab, &(page)->flags)
@@ -415,7 +412,7 @@
 extern void clear_page_tables(struct mm_struct *, unsigned long, int);
 
 extern int fail_writepage(struct page *);
-struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int no_share);
+struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address);
 struct file *shmem_file_setup(char * name, loff_t size);
 extern void shmem_lock(struct file * file, int lock);
 extern int shmem_zero_setup(struct vm_area_struct *);
@@ -541,7 +538,7 @@
 
 /* generic vm_area_ops exported for stackable file systems */
 extern int filemap_sync(struct vm_area_struct *, unsigned long,	size_t, unsigned int);
-extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int);
+extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long);
 
 /*
  * GFP bitmasks..
diff -urN linux-2.4.14-pre3/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.4.14-pre3/kernel/ksyms.c	Wed Oct 17 14:32:50 2001
+++ linux/kernel/ksyms.c	Mon Dec  3 23:23:38 2001
@@ -491,7 +491,6 @@
 EXPORT_SYMBOL(fsync_inode_buffers);
 EXPORT_SYMBOL(fsync_inode_data_buffers);
 EXPORT_SYMBOL(clear_inode);
-EXPORT_SYMBOL(nr_async_pages);
 EXPORT_SYMBOL(___strtok);
 EXPORT_SYMBOL(init_special_inode);
 EXPORT_SYMBOL(read_ahead);
diff -urN linux-2.4.14-pre3/mm/filemap.c linux/mm/filemap.c
--- linux-2.4.14-pre3/mm/filemap.c	Mon Dec  3 23:23:23 2001
+++ linux/mm/filemap.c	Mon Dec  3 23:23:38 2001
@@ -49,8 +49,13 @@
 
 spinlock_t pagecache_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 /*
- * NOTE: to avoid deadlocking you must never acquire the pagecache_lock with
- *       the pagemap_lru_lock held.
+ * NOTE: to avoid deadlocking you must never acquire the pagemap_lru_lock 
+ *	with the pagecache_lock held.
+ *
+ * Ordering:
+ *	swap_lock ->
+ *		pagemap_lru_lock ->
+ *			pagecache_lock
  */
 spinlock_t pagemap_lru_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
@@ -164,8 +169,8 @@
 
 	head = &inode->i_mapping->clean_pages;
 
-	spin_lock(&pagecache_lock);
 	spin_lock(&pagemap_lru_lock);
+	spin_lock(&pagecache_lock);
 	curr = head->next;
 
 	while (curr != head) {
@@ -196,8 +201,8 @@
 		continue;
 	}
 
-	spin_unlock(&pagemap_lru_lock);
 	spin_unlock(&pagecache_lock);
+	spin_unlock(&pagemap_lru_lock);
 }
 
 static inline void truncate_partial_page(struct page *page, unsigned partial)
@@ -633,8 +638,9 @@
 	spin_lock(&pagecache_lock);
 	add_page_to_inode_queue(mapping, page);
 	add_page_to_hash_queue(page, page_hash(mapping, index));
-	lru_cache_add(page);
 	spin_unlock(&pagecache_lock);
+
+	lru_cache_add(page);
 }
 
 /*
@@ -653,7 +659,6 @@
 	page->index = offset;
 	add_page_to_inode_queue(mapping, page);
 	add_page_to_hash_queue(page, hash);
-	lru_cache_add(page);
 }
 
 void add_to_page_cache(struct page * page, struct address_space * mapping, unsigned long offset)
@@ -661,6 +666,7 @@
 	spin_lock(&pagecache_lock);
 	__add_to_page_cache(page, mapping, offset, page_hash(mapping, offset));
 	spin_unlock(&pagecache_lock);
+	lru_cache_add(page);
 }
 
 int add_to_page_cache_unique(struct page * page,
@@ -680,6 +686,8 @@
 	}
 
 	spin_unlock(&pagecache_lock);
+	if (!err)
+		lru_cache_add(page);
 	return err;
 }
 
@@ -909,7 +917,9 @@
 				newpage = NULL;
 			}
 			spin_unlock(&pagecache_lock);
-			if (unlikely(newpage != NULL))
+			if (newpage == NULL)
+				lru_cache_add(page);
+			else 
 				page_cache_release(newpage);
 		}
 	}
@@ -1385,6 +1395,7 @@
 		page = cached_page;
 		__add_to_page_cache(page, mapping, index, hash);
 		spin_unlock(&pagecache_lock);
+		lru_cache_add(page);		
 		cached_page = NULL;
 
 		goto readpage;
@@ -1671,14 +1682,13 @@
  * it in the page cache, and handles the special cases reasonably without
  * having a lot of duplicated code.
  */
-struct page * filemap_nopage(struct vm_area_struct * area,
-	unsigned long address, int no_share)
+struct page * filemap_nopage(struct vm_area_struct * area, unsigned long address)
 {
 	int error;
 	struct file *file = area->vm_file;
 	struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
 	struct inode *inode = mapping->host;
-	struct page *page, **hash, *old_page;
+	struct page *page, **hash;
 	unsigned long size, pgoff, endoff;
 
 	pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
@@ -1724,22 +1734,9 @@
 	 * Found the page and have a reference on it, need to check sharing
 	 * and possibly copy it over to another page..
 	 */
-	old_page = page;
 	mark_page_accessed(page);
-	if (no_share) {
-		struct page *new_page = alloc_page(GFP_HIGHUSER);
-
-		if (new_page) {
-			copy_user_highpage(new_page, old_page, address);
-			flush_page_to_ram(new_page);
-		} else
-			new_page = NOPAGE_OOM;
-		page_cache_release(page);
-		return new_page;
-	}
-
-	flush_page_to_ram(old_page);
-	return old_page;
+	flush_page_to_ram(page);
+	return page;
 
 no_cached_page:
 	/*
diff -urN linux-2.4.14-pre3/mm/memory.c linux/mm/memory.c
--- linux-2.4.14-pre3/mm/memory.c	Mon Dec  3 23:23:23 2001
+++ linux/mm/memory.c	Mon Dec  3 23:23:38 2001
@@ -906,7 +906,8 @@
  * change only once the write actually happens. This avoids a few races,
  * and potentially makes it more efficient.
  *
- * We hold the mm semaphore and the page_table_lock on entry and exit.
+ * We hold the mm semaphore and the page_table_lock on entry and exit
+ * with the page_table_lock released.
  */
 static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
 	unsigned long address, pte_t *page_table, pte_t pte)
@@ -950,6 +951,7 @@
 			break;
 		flush_cache_page(vma, address);
 		establish_pte(vma, address, page_table, pte_mkyoung(pte_mkdirty(pte_mkwrite(pte))));
+		spin_unlock(&mm->page_table_lock);
 		return 1;	/* Minor fault */
 	}
 
@@ -978,15 +980,16 @@
 		/* Free the old page.. */
 		new_page = old_page;
 	}
+	spin_unlock(&mm->page_table_lock);
 	free_lru_page(new_page);
 	return 1;	/* Minor fault */
 
 bad_wp_page:
+	spin_unlock(&mm->page_table_lock);
 	printk("do_wp_page: bogus page at address %08lx (page 0x%lx)\n",address,(unsigned long)old_page);
 	return -1;
 no_mem:
 	free_lru_page(old_page);
-	spin_lock(&mm->page_table_lock);
 	return -1;
 }
 
@@ -1091,10 +1094,6 @@
 	 */
 	num = valid_swaphandles(entry, &offset);
 	for (i = 0; i < num; offset++, i++) {
-		/* Don't block on I/O for read-ahead */
-		if (atomic_read(&nr_async_pages) >=
-		    pager_daemon.swap_cluster << page_cluster)
-			break;
 		/* Ok, do the async read-ahead now */
 		new_page = read_swap_cache_async(SWP_ENTRY(SWP_TYPE(entry), offset));
 		if (!new_page)
@@ -1109,7 +1108,8 @@
 	(swapper_space.nrpages*5 > total_swap_pages*4)
 
 /*
- * We hold the mm semaphore and the page_table_lock on entry and exit.
+ * We hold the mm semaphore and the page_table_lock on entry and
+ * should release the pagetable lock on exit..
  */
 static int do_swap_page(struct mm_struct * mm,
 	struct vm_area_struct * vma, unsigned long address,
@@ -1126,24 +1126,23 @@
 		swapin_readahead(entry);
 		page = read_swap_cache_async(entry);
 		if (!page) {
-			spin_lock(&mm->page_table_lock);
 			/*
 			 * Back out if somebody else faulted in this pte while
 			 * we released the page table lock.
 			 */
-			return pte_same(*page_table, orig_pte) ? -1 : 1;
+			int retval;
+			spin_lock(&mm->page_table_lock);
+			retval = pte_same(*page_table, orig_pte) ? -1 : 1;
+			spin_unlock(&mm->page_table_lock);
+			return retval;
 		}
 
 		/* Had to read the page from swap area: Major fault */
 		ret = 2;
 	}
 
-	/*
-	 * Freeze the "shared"ness of the page, ie page_count + swap_count.
-	 * Must lock page before transferring our swap count to already
-	 * obtained page count.
-	 */
-	lock_page(page);
+	if (!Page_Uptodate(page))
+		wait_on_page(page);
 
 	/*
 	 * Back out if somebody else faulted in this pte while we
@@ -1153,6 +1152,7 @@
 	if (!pte_same(*page_table, orig_pte)) {
 		UnlockPage(page);
 		page_cache_release(page);
+		spin_unlock(&mm->page_table_lock);
 		return 1;
 	}
 		
@@ -1161,16 +1161,6 @@
 	pte = mk_pte(page, vma->vm_page_prot);
 
 	swap_free(entry);
-	mark_page_accessed(page);
-	if (exclusive_swap_page(page)) {
-		if (write_access || vm_swap_full()) {
-			pte = pte_mkdirty(pte);
-			if (vma->vm_flags & VM_WRITE)
-				pte = pte_mkwrite(pte);
-			delete_from_swap_cache(page);
-		}
-	}
-	UnlockPage(page);
 
 	flush_page_to_ram(page);
 	flush_icache_page(vma, page);
@@ -1178,6 +1168,7 @@
 
 	/* No need to invalidate - it was non-present before */
 	update_mmu_cache(vma, address, pte);
+	spin_unlock(&mm->page_table_lock);
 	return ret;
 }
 
@@ -1208,6 +1199,7 @@
 		spin_lock(&mm->page_table_lock);
 		if (!pte_none(*page_table)) {
 			page_cache_release(page);
+			spin_unlock(&mm->page_table_lock);
 			return 1;
 		}
 		mm->rss++;
@@ -1220,10 +1212,10 @@
 
 	/* No need to invalidate - it was non-present before */
 	update_mmu_cache(vma, addr, entry);
+	spin_unlock(&mm->page_table_lock);
 	return 1;	/* Minor fault */
 
 no_mem:
-	spin_lock(&mm->page_table_lock);
 	return -1;
 }
 
@@ -1237,7 +1229,7 @@
  * do not need to flush old virtual caches or the TLB.
  *
  * This is called with the MM semaphore held and the page table
- * spinlock held.
+ * spinlock held. Exit with the spinlock released.
  */
 static int do_no_page(struct mm_struct * mm, struct vm_area_struct * vma,
 	unsigned long address, int write_access, pte_t *page_table)
@@ -1249,18 +1241,27 @@
 		return do_anonymous_page(mm, vma, page_table, write_access, address);
 	spin_unlock(&mm->page_table_lock);
 
-	/*
-	 * The third argument is "no_share", which tells the low-level code
-	 * to copy, not share the page even if sharing is possible.  It's
-	 * essentially an early COW detection.
-	 */
-	new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, (vma->vm_flags & VM_SHARED)?0:write_access);
+	new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK);
 
-	spin_lock(&mm->page_table_lock);
 	if (new_page == NULL)	/* no page was available -- SIGBUS */
 		return 0;
 	if (new_page == NOPAGE_OOM)
 		return -1;
+
+	/*
+	 * Should we do an early C-O-W break?
+	 */
+	if (write_access && !(vma->vm_flags & VM_SHARED)) {
+		struct page * page = alloc_page(GFP_HIGHUSER);
+		if (!page)
+			return -1;
+		copy_highpage(page, new_page);
+		page_cache_release(new_page);
+		lru_cache_add(page);
+		new_page = page;
+	}
+
+	spin_lock(&mm->page_table_lock);
 	/*
 	 * This silly early PAGE_DIRTY setting removes a race
 	 * due to the bad i386 page protection. But it's valid
@@ -1277,20 +1278,19 @@
 		flush_page_to_ram(new_page);
 		flush_icache_page(vma, new_page);
 		entry = mk_pte(new_page, vma->vm_page_prot);
-		if (write_access) {
+		if (write_access)
 			entry = pte_mkwrite(pte_mkdirty(entry));
-		} else if (page_count(new_page) > 1 &&
-			   !(vma->vm_flags & VM_SHARED))
-			entry = pte_wrprotect(entry);
 		set_pte(page_table, entry);
 	} else {
 		/* One of our sibling threads was faster, back out. */
-		page_cache_release(new_page);
+		free_lru_page(new_page);
+		spin_unlock(&mm->page_table_lock);
 		return 1;
 	}
 
 	/* no need to invalidate: a not-present page shouldn't be cached */
 	update_mmu_cache(vma, address, entry);
+	spin_unlock(&mm->page_table_lock);
 	return 2;	/* Major fault */
 }
 
@@ -1311,6 +1311,9 @@
  * The adding of pages is protected by the MM semaphore (which we hold),
  * so we don't need to worry about a page being suddenly been added into
  * our VM.
+ *
+ * We enter with the pagetable spinlock held, we are supposed to
+ * release it when done.
  */
 static inline int handle_pte_fault(struct mm_struct *mm,
 	struct vm_area_struct * vma, unsigned long address,
@@ -1338,6 +1341,7 @@
 	}
 	entry = pte_mkyoung(entry);
 	establish_pte(vma, address, pte, entry);
+	spin_unlock(&mm->page_table_lock);
 	return 1;
 }
 
@@ -1347,7 +1351,6 @@
 int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma,
 	unsigned long address, int write_access)
 {
-	int ret = -1;
 	pgd_t *pgd;
 	pmd_t *pmd;
 
@@ -1364,10 +1367,10 @@
 	if (pmd) {
 		pte_t * pte = pte_alloc(mm, pmd, address);
 		if (pte)
-			ret = handle_pte_fault(mm, vma, address, write_access, pte);
+			return handle_pte_fault(mm, vma, address, write_access, pte);
 	}
 	spin_unlock(&mm->page_table_lock);
-	return ret;
+	return -1;
 }
 
 /*
diff -urN linux-2.4.14-pre3/mm/page_alloc.c linux/mm/page_alloc.c
--- linux-2.4.14-pre3/mm/page_alloc.c	Mon Dec  3 23:23:23 2001
+++ linux/mm/page_alloc.c	Mon Dec  3 23:23:38 2001
@@ -80,8 +80,6 @@
 		BUG();
 	if (PageLocked(page))
 		BUG();
-	if (PageDecrAfter(page))
-		BUG();
 	if (PageActive(page))
 		BUG();
 	if (PageInactive(page))
@@ -273,8 +271,6 @@
 					if (PageSwapCache(page))
 						BUG();
 					if (PageLocked(page))
-						BUG();
-					if (PageDecrAfter(page))
 						BUG();
 					if (PageActive(page))
 						BUG();
diff -urN linux-2.4.14-pre3/mm/page_io.c linux/mm/page_io.c
--- linux-2.4.14-pre3/mm/page_io.c	Wed Sep 19 23:37:30 2001
+++ linux/mm/page_io.c	Mon Dec  3 23:23:38 2001
@@ -43,11 +43,6 @@
 	struct inode *swapf = 0;
 	int wait = 0;
 
-	/* Don't allow too many pending pages in flight.. */
-	if ((rw == WRITE) && atomic_read(&nr_async_pages) >
-			pager_daemon.swap_cluster * (1 << page_cluster))
-		wait = 1;
-
 	if (rw == READ) {
 		ClearPageUptodate(page);
 		kstat.pswpin++;
@@ -75,10 +70,6 @@
 	} else {
 		return 0;
 	}
- 	if (!wait) {
- 		SetPageDecrAfter(page);
- 		atomic_inc(&nr_async_pages);
- 	}
 
  	/* block_size == PAGE_SIZE/zones_used */
  	brw_page(rw, page, dev, zones, block_size);
diff -urN linux-2.4.14-pre3/mm/shmem.c linux/mm/shmem.c
--- linux-2.4.14-pre3/mm/shmem.c	Mon Dec  3 23:23:23 2001
+++ linux/mm/shmem.c	Mon Dec  3 23:23:38 2001
@@ -449,7 +449,6 @@
 		BUG();
 
 	/* Remove it from the page cache */
-	lru_cache_del(page);
 	remove_inode_page(page);
 	page_cache_release(page);
 
@@ -468,6 +467,7 @@
 	*entry = swap;
 	info->swapped++;
 	spin_unlock(&info->lock);
+	SetPageUptodate(page);
 	set_page_dirty(page);
 	UnlockPage(page);
 	return 0;
@@ -621,7 +621,7 @@
 	return error;
 }
 
-struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int no_share)
+struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address)
 {
 	struct page * page;
 	unsigned int idx;
@@ -633,19 +633,7 @@
 	if (shmem_getpage(inode, idx, &page))
 		return page;
 
-	if (no_share) {
-		struct page *new_page = page_cache_alloc(inode->i_mapping);
-
-		if (new_page) {
-			copy_user_highpage(new_page, page, address);
-			flush_page_to_ram(new_page);
-		} else
-			new_page = NOPAGE_OOM;
-		page_cache_release(page);
-		return new_page;
-	}
-
-	flush_page_to_ram (page);
+	flush_page_to_ram(page);
 	return(page);
 }
 
@@ -1150,7 +1138,7 @@
 		
 	inode = dentry->d_inode;
 	info = SHMEM_I(inode);
-	inode->i_size = len;
+	inode->i_size = len-1;
 	if (len <= sizeof(struct shmem_inode_info)) {
 		/* do it inline */
 		memcpy(info, symname, len);
diff -urN linux-2.4.14-pre3/mm/swap.c linux/mm/swap.c
--- linux-2.4.14-pre3/mm/swap.c	Mon Dec  3 23:23:23 2001
+++ linux/mm/swap.c	Mon Dec  3 23:23:38 2001
@@ -27,10 +27,6 @@
 /* How many pages do we try to swap or page in/out together? */
 int page_cluster;
 
-/* We track the number of pages currently being asynchronously swapped
-   out, so that we don't try to swap TOO many pages out at once */
-atomic_t nr_async_pages = ATOMIC_INIT(0);
-
 pager_daemon_t pager_daemon = {
 	512,	/* base number for calculating the number of tries */
 	SWAP_CLUSTER_MAX,	/* minimum number of tries */
diff -urN linux-2.4.14-pre3/mm/swap_state.c linux/mm/swap_state.c
--- linux-2.4.14-pre3/mm/swap_state.c	Mon Dec  3 23:23:23 2001
+++ linux/mm/swap_state.c	Mon Dec  3 23:23:38 2001
@@ -17,17 +17,8 @@
 
 #include <asm/pgtable.h>
 
-/*
- * We may have stale swap cache pages in memory: notice
- * them here and get rid of the unnecessary final write.
- */
 static int swap_writepage(struct page *page)
 {
-	if (exclusive_swap_page(page)) {
-		delete_from_swap_cache(page);
-		UnlockPage(page);
-		return 0;
-	}
 	rw_swap_page(WRITE, page);
 	return 0;
 }
@@ -82,7 +73,6 @@
 		INC_CACHE_INFO(exist_race);
 		return -EEXIST;
 	}
-	SetPageUptodate(page);
 	if (!PageLocked(page))
 		BUG();
 	if (!PageSwapCache(page))
@@ -119,8 +109,7 @@
 	if (!PageLocked(page))
 		BUG();
 
-	if (block_flushpage(page, 0))
-		lru_cache_del(page);
+	block_flushpage(page, 0);
 
 	entry.val = page->index;
 
diff -urN linux-2.4.14-pre3/mm/swapfile.c linux/mm/swapfile.c
--- linux-2.4.14-pre3/mm/swapfile.c	Mon Dec  3 23:23:23 2001
+++ linux/mm/swapfile.c	Mon Dec  3 23:23:38 2001
@@ -242,7 +242,7 @@
 		page_cache_get(page);
 		delete_from_swap_cache(page);
 		UnlockPage(page);
-		page_cache_release(page);
+		free_lru_page(page);
 	}
 }
 
@@ -582,7 +582,7 @@
 		 */
 		SetPageDirty(page);
 		UnlockPage(page);
-		page_cache_release(page);
+		free_lru_page(page);
 
 		/*
 		 * Make sure that we aren't completely killing
diff -urN linux-2.4.14-pre3/mm/vmscan.c linux/mm/vmscan.c
--- linux-2.4.14-pre3/mm/vmscan.c	Mon Dec  3 23:23:23 2001
+++ linux/mm/vmscan.c	Mon Dec  3 23:23:38 2001
@@ -134,6 +134,7 @@
 			break;
 		/* Add it to the swap cache and mark it dirty */
 		if (add_to_swap_cache(page, entry) == 0) {
+			SetPageUptodate(page);
 			set_page_dirty(page);
 			goto set_swap_pte;
 		}
@@ -459,13 +460,7 @@
 			}
 		}
 
-		if (unlikely(!spin_trylock(&pagecache_lock))) {
-			/* we hold the page lock so the page cannot go away from under us */
-			spin_unlock(&pagemap_lru_lock);
-
-			spin_lock(&pagecache_lock);
-			spin_lock(&pagemap_lru_lock);
-		}
+		spin_lock(&pagecache_lock);
 
 		/*
 		 * this is the non-racy check for busy page.
@@ -520,6 +515,20 @@
 	}
 	spin_unlock(&pagemap_lru_lock);
 
+	if (nr_pages <= 0)
+		return 0;
+
+	/*
+	 * If swapping out isn't appropriate, and 
+	 * we still fail, try the other (usually smaller)
+	 * caches instead.
+	 */
+	shrink_dcache_memory(priority, gfp_mask);
+	shrink_icache_memory(priority, gfp_mask);
+#ifdef CONFIG_QUOTA
+	shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
+#endif
+
 	return nr_pages;
 }
 
@@ -568,17 +577,7 @@
 	ratio = (unsigned long) nr_pages * nr_active_pages / ((nr_inactive_pages + 1) * 2);
 	refill_inactive(ratio);
 
-	nr_pages = shrink_cache(nr_pages, classzone, gfp_mask, priority);
-	if (nr_pages <= 0)
-		return 0;
-
-	shrink_dcache_memory(priority, gfp_mask);
-	shrink_icache_memory(priority, gfp_mask);
-#ifdef CONFIG_QUOTA
-	shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
-#endif
-
-	return nr_pages;
+	return shrink_cache(nr_pages, classzone, gfp_mask, priority);
 }
 
 int try_to_free_pages(zone_t *classzone, unsigned int gfp_mask, unsigned int order)
