]> git.hungrycats.org Git - linux/commitdiff
v2.4.13.3 -> v2.4.13.4
authorLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 04:29:56 +0000 (20:29 -0800)
committerLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 04:29:56 +0000 (20:29 -0800)
  - Mikael Pettersson: fix P4 boot with APIC enabled
  - me: fix device queuing thinko, clean up VM locking

19 files changed:
Makefile
arch/i386/kernel/apic.c
drivers/block/ll_rw_blk.c
drivers/block/paride/pcd.c
drivers/char/drm/drmP.h
drivers/char/drm/drm_vm.h
drivers/char/random.c
fs/buffer.c
include/linux/mm.h
kernel/ksyms.c
mm/filemap.c
mm/memory.c
mm/page_alloc.c
mm/page_io.c
mm/shmem.c
mm/swap.c
mm/swap_state.c
mm/swapfile.c
mm/vmscan.c

index 0dec1ad73766eb1990644c86b07302b7bfea1b03..e2feeea8859d11e94049b10968f20caf58f100ec 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 14
-EXTRAVERSION =-pre3
+EXTRAVERSION =-pre4
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
index 1d043c8df977c011224c857523d7ef7559d944f5..2b68085ca7e8e23cc3fbdcb61f52e7ada30d06e7 100644 (file)
@@ -588,6 +588,7 @@ static int __init detect_init_APIC (void)
                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;
index 1ff9387b7e0f5519c4a4f29af9ab1761596ed83a..1700c37592ab8cdb46712bf699015395d2fdd6c1 100644 (file)
@@ -446,12 +446,15 @@ static struct request *__get_request_wait(request_queue_t *q, int rw)
        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;
index 5c4d3adb30e12c97f68f1f6072499492ed0471da..e3048d01c5435528f75a69c55c7c26e818a9d4d4 100644 (file)
@@ -271,7 +271,7 @@ static struct block_device_operations pcd_bdops = {
        release:                cdrom_release,
        ioctl:                  cdrom_ioctl,
        check_media_change:     cdrom_media_changed,
-}
+};
 
 static struct cdrom_device_ops pcd_dops = {
        pcd_open,
index 345415380c54ac92edb18d4a2a0a2d129a71d7c5..36e513ac41c99e019079c6ca57bd9038c3a5922a 100644 (file)
@@ -780,31 +780,23 @@ extern unsigned int  DRM(poll)(struct file *filp,
                                /* 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);
index 113a8e94b9cdff75efcceb38501b9eaddbd45317..a3589af1edfe52724d3f4fb83b76562db3d8735b 100644 (file)
@@ -58,13 +58,11 @@ struct vm_operations_struct   DRM(vm_sg_ops) = {
 
 #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 @@ vm_nopage_error:
 
 #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 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
 
 #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 @@ struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
 
 #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
index 9355f9e3b18e0386f82478a689160deb79c954e7..b2bc6f564fa6f36e98daec6304a871daa2ede596 100644 (file)
@@ -569,7 +569,7 @@ static void add_entropy_words(struct entropy_store *r, const __u32 *in,
        __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.
index 34b53f73a934f2e3ce501d3e89c0dc56a5fa043d..f942be60660bc96d3538a1c3f0818e13e3a755e3 100644 (file)
@@ -770,12 +770,6 @@ static void end_buffer_io_async(struct buffer_head * bh, int uptodate)
        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;
index 23e7812c5d5ba754cce37c6e196ebee7df4c8859..6cbd7ed4c464bc648b55eb95c99ec87615c7b4f6 100644 (file)
@@ -125,7 +125,7 @@ extern pgprot_t protection_map[16];
 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 @@ typedef struct page {
 #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 @@ static inline void set_page_dirty(struct page * page)
 #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 show_free_areas_node(pg_data_t *pgdat);
 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 @@ extern void truncate_inode_pages(struct address_space *, loff_t);
 
 /* 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..
index f3e76ac75df551a8e8c67352b732a03d38c8085c..1dcb9dc518c37517f89f8de30747381ebfd4f4c5 100644 (file)
@@ -491,7 +491,6 @@ EXPORT_SYMBOL(file_fsync);
 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);
index b7398642769bfac7307c28ef6fd070d053fb220c..be3b3b2c2113bd12860ff561f1b9942aad3e93b4 100644 (file)
@@ -49,8 +49,13 @@ struct page **page_hash_table;
 
 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 @@ void invalidate_inode_pages(struct inode * inode)
 
        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 @@ unlock:
                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 @@ void add_to_page_cache_locked(struct page * page, struct address_space *mapping,
        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 @@ static inline void __add_to_page_cache(struct page * page,
        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 @@ void add_to_page_cache(struct page * page, struct address_space * mapping, unsig
        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 @@ int add_to_page_cache_unique(struct page * page,
        }
 
        spin_unlock(&pagecache_lock);
+       if (!err)
+               lru_cache_add(page);
        return err;
 }
 
@@ -909,7 +917,9 @@ struct page * find_or_create_page(struct address_space *mapping, unsigned long i
                                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 @@ no_cached_page:
                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 @@ static void nopage_sequential_readahead(struct vm_area_struct * vma,
  * 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 @@ success:
         * 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:
        /*
index 758d481b849e3237ed0f35f35fda6c5cbbe81281..df6ffe94f5ffce0e56931acb27c772e587ead1ad 100644 (file)
@@ -906,7 +906,8 @@ static inline void break_cow(struct vm_area_struct * vma, struct page * new_page
  * 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 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
                        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 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
                /* 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 @@ void swapin_readahead(swp_entry_t entry)
         */
        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 @@ void swapin_readahead(swp_entry_t entry)
        (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 @@ static int do_swap_page(struct mm_struct * mm,
                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 @@ static int do_swap_page(struct mm_struct * mm,
        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 @@ static int do_swap_page(struct mm_struct * mm,
        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 @@ static int do_swap_page(struct mm_struct * mm,
 
        /* 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 @@ static int do_anonymous_page(struct mm_struct * mm, struct vm_area_struct * vma,
                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 @@ static int do_anonymous_page(struct mm_struct * mm, struct vm_area_struct * vma,
 
        /* 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 @@ no_mem:
  * 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 @@ static int do_no_page(struct mm_struct * mm, struct vm_area_struct * vma,
                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 @@ static int do_no_page(struct mm_struct * mm, struct vm_area_struct * vma,
                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 @@ static int do_no_page(struct mm_struct * mm, struct vm_area_struct * vma,
  * 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 @@ static inline int handle_pte_fault(struct mm_struct *mm,
        }
        entry = pte_mkyoung(entry);
        establish_pte(vma, address, pte, entry);
+       spin_unlock(&mm->page_table_lock);
        return 1;
 }
 
@@ -1347,7 +1351,6 @@ static inline int handle_pte_fault(struct mm_struct *mm,
 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 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma,
        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;
 }
 
 /*
index b31add55a252cd1d6ebcd5881b05ad809bd3e482..14d1aab223deb3a9aa2abbe74a1e4f467eb8d535 100644 (file)
@@ -80,8 +80,6 @@ static void __free_pages_ok (struct page *page, unsigned int order)
                BUG();
        if (PageLocked(page))
                BUG();
-       if (PageDecrAfter(page))
-               BUG();
        if (PageActive(page))
                BUG();
        if (PageInactive(page))
@@ -274,8 +272,6 @@ static struct page * balance_classzone(zone_t * classzone, unsigned int gfp_mask
                                                BUG();
                                        if (PageLocked(page))
                                                BUG();
-                                       if (PageDecrAfter(page))
-                                               BUG();
                                        if (PageActive(page))
                                                BUG();
                                        if (PageInactive(page))
index 1b61746e3f15645cd528cf00cd6b5b410ead110e..2153dca119585f5d2a1842d873c8e8920b8ebed6 100644 (file)
@@ -43,11 +43,6 @@ static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page)
        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 @@ static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page)
        } 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);
index c6dc9ff0ebfaaaaa07d6aafb2795406c4a1b1132..29445e120dee2740273954cab312ee037ac163c6 100644 (file)
@@ -449,7 +449,6 @@ getswap:
                BUG();
 
        /* Remove it from the page cache */
-       lru_cache_del(page);
        remove_inode_page(page);
        page_cache_release(page);
 
@@ -468,6 +467,7 @@ getswap:
        *entry = swap;
        info->swapped++;
        spin_unlock(&info->lock);
+       SetPageUptodate(page);
        set_page_dirty(page);
        UnlockPage(page);
        return 0;
@@ -621,7 +621,7 @@ failed:
        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 @@ struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, i
        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 @@ static int shmem_symlink(struct inode * dir, struct dentry *dentry, const char *
                
        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);
index 7f987cfa75f00240652741f3696827549200ac6e..51f8541cd59e5d736e4070a35bae4d45f5c0e529 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
 /* 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 */
index cc336b3453993cd9bfe9aac2c11e9a9992c39eaa..30d0c085cd6d538a0756ae12039feb687b6ba3be 100644 (file)
 
 #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 @@ int add_to_swap_cache(struct page *page, swp_entry_t entry)
                INC_CACHE_INFO(exist_race);
                return -EEXIST;
        }
-       SetPageUptodate(page);
        if (!PageLocked(page))
                BUG();
        if (!PageSwapCache(page))
@@ -119,8 +109,7 @@ void delete_from_swap_cache(struct page *page)
        if (!PageLocked(page))
                BUG();
 
-       if (block_flushpage(page, 0))
-               lru_cache_del(page);
+       block_flushpage(page, 0);
 
        entry.val = page->index;
 
index aa732e754660b8874432be3475a43561fc053be3..e1f34979e747900f9a709ead9a5f05c60042a3c2 100644 (file)
@@ -242,7 +242,7 @@ void free_swap_and_cache(swp_entry_t entry)
                page_cache_get(page);
                delete_from_swap_cache(page);
                UnlockPage(page);
-               page_cache_release(page);
+               free_lru_page(page);
        }
 }
 
@@ -582,7 +582,7 @@ static int try_to_unuse(unsigned int type)
                 */
                SetPageDirty(page);
                UnlockPage(page);
-               page_cache_release(page);
+               free_lru_page(page);
 
                /*
                 * Make sure that we aren't completely killing
index 8ef4561e2a3c090d01912cd563d8abf23fcbd4c7..a0fc8504fb8230509fa9cd13aee828a6dc10ac22 100644 (file)
@@ -134,6 +134,7 @@ drop_pte:
                        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 @@ static int shrink_cache(int nr_pages, zone_t * classzone, unsigned int gfp_mask,
                        }
                }
 
-               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 @@ page_mapped:
        }
        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 @@ static int shrink_caches(zone_t * classzone, int priority, unsigned int gfp_mask
        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)