From f97f22cb0b9dca2a797feccc580b3b8fdb238ac3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 4 Feb 2002 20:29:56 -0800 Subject: [PATCH] v2.4.13.3 -> v2.4.13.4 - Mikael Pettersson: fix P4 boot with APIC enabled - me: fix device queuing thinko, clean up VM locking --- Makefile | 2 +- arch/i386/kernel/apic.c | 1 + drivers/block/ll_rw_blk.c | 7 ++- drivers/block/paride/pcd.c | 2 +- drivers/char/drm/drmP.h | 24 ++++------- drivers/char/drm/drm_vm.h | 24 ++++------- drivers/char/random.c | 2 +- fs/buffer.c | 6 --- include/linux/mm.h | 11 ++--- kernel/ksyms.c | 1 - mm/filemap.c | 47 ++++++++++---------- mm/memory.c | 87 ++++++++++++++++++++------------------ mm/page_alloc.c | 4 -- mm/page_io.c | 9 ---- mm/shmem.c | 20 ++------- mm/swap.c | 4 -- mm/swap_state.c | 13 +----- mm/swapfile.c | 4 +- mm/vmscan.c | 35 ++++++++------- 19 files changed, 120 insertions(+), 183 deletions(-) diff --git a/Makefile b/Makefile index 0dec1ad73766..e2feeea8859d 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 14 -EXTRAVERSION =-pre3 +EXTRAVERSION =-pre4 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 1d043c8df977..2b68085ca7e8 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -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; diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 1ff9387b7e0f..1700c37592ab 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -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; diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 5c4d3adb30e1..e3048d01c543 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -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, diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 345415380c54..36e513ac41c9 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -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); diff --git a/drivers/char/drm/drm_vm.h b/drivers/char/drm/drm_vm.h index 113a8e94b9cd..a3589af1edfe 100644 --- a/drivers/char/drm/drm_vm.h +++ b/drivers/char/drm/drm_vm.h @@ -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 diff --git a/drivers/char/random.c b/drivers/char/random.c index 9355f9e3b18e..b2bc6f564fa6 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -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. diff --git a/fs/buffer.c b/fs/buffer.c index 34b53f73a934..f942be60660b 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -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; diff --git a/include/linux/mm.h b/include/linux/mm.h index 23e7812c5d5b..6cbd7ed4c464 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -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.. diff --git a/kernel/ksyms.c b/kernel/ksyms.c index f3e76ac75df5..1dcb9dc518c3 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -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); diff --git a/mm/filemap.c b/mm/filemap.c index b7398642769b..be3b3b2c2113 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -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: /* diff --git a/mm/memory.c b/mm/memory.c index 758d481b849e..df6ffe94f5ff 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -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; } /* diff --git a/mm/page_alloc.c b/mm/page_alloc.c index b31add55a252..14d1aab223de 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -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)) diff --git a/mm/page_io.c b/mm/page_io.c index 1b61746e3f15..2153dca11958 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -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); diff --git a/mm/shmem.c b/mm/shmem.c index c6dc9ff0ebfa..29445e120dee 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -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); diff --git a/mm/swap.c b/mm/swap.c index 7f987cfa75f0..51f8541cd59e 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -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 --git a/mm/swap_state.c b/mm/swap_state.c index cc336b345399..30d0c085cd6d 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -17,17 +17,8 @@ #include -/* - * 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; diff --git a/mm/swapfile.c b/mm/swapfile.c index aa732e754660..e1f34979e747 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -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 diff --git a/mm/vmscan.c b/mm/vmscan.c index 8ef4561e2a3c..a0fc8504fb82 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -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) -- 2.39.5