From: William Lee Irwin III Our accounting of minor faults versus major faults is currently quite wrong. To fix it up we need to propagate the actual fault type back to the higher-level code. Repurpose the currently-unused third arg to ->nopage for this. Documentation/filesystems/Locking | 2 +- arch/i386/mm/hugetlbpage.c | 2 +- arch/ia64/ia32/binfmt_elf32.c | 4 +++- arch/ia64/mm/hugetlbpage.c | 2 +- arch/ppc64/mm/hugetlbpage.c | 2 +- arch/sparc64/mm/hugetlbpage.c | 2 +- drivers/char/agp/alpha-agp.c | 4 +++- drivers/char/drm/drmP.h | 8 ++++---- drivers/char/drm/drm_vm.h | 16 ++++++++++++---- drivers/ieee1394/dma.c | 4 +++- drivers/media/video/video-buf.c | 4 +++- drivers/scsi/sg.c | 4 +++- fs/ncpfs/mmap.c | 11 ++++++++++- include/linux/mm.h | 6 +++--- kernel/sys.c | 2 -- mm/filemap.c | 19 ++++++++++++++++--- mm/memory.c | 4 +--- mm/shmem.c | 32 +++++++++++++++++++------------- sound/core/pcm_native.c | 4 +++- sound/oss/emu10k1/audio.c | 4 +++- sound/oss/via82cxxx_audio.c | 9 +++++---- 21 files changed, 96 insertions(+), 49 deletions(-) diff -puN arch/i386/mm/hugetlbpage.c~pagefault-accounting-fix arch/i386/mm/hugetlbpage.c --- 25/arch/i386/mm/hugetlbpage.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/arch/i386/mm/hugetlbpage.c 2003-11-17 17:32:29.000000000 -0800 @@ -534,7 +534,7 @@ int is_hugepage_mem_enough(size_t size) * this far. */ static struct page *hugetlb_nopage(struct vm_area_struct *vma, - unsigned long address, int unused) + unsigned long address, int *unused) { BUG(); return NULL; diff -puN arch/ia64/ia32/binfmt_elf32.c~pagefault-accounting-fix arch/ia64/ia32/binfmt_elf32.c --- 25/arch/ia64/ia32/binfmt_elf32.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/arch/ia64/ia32/binfmt_elf32.c 2003-11-17 17:33:18.000000000 -0800 @@ -60,10 +60,12 @@ extern struct page *ia32_shared_page[]; extern unsigned long *ia32_gdt; struct page * -ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int no_share) +ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int *type) { struct page *pg = ia32_shared_page[smp_processor_id()]; get_page(pg); + if (type) + *type = VM_FAULT_MINOR; return pg; } diff -puN arch/ia64/mm/hugetlbpage.c~pagefault-accounting-fix arch/ia64/mm/hugetlbpage.c --- 25/arch/ia64/mm/hugetlbpage.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/arch/ia64/mm/hugetlbpage.c 2003-11-17 17:32:29.000000000 -0800 @@ -518,7 +518,7 @@ int is_hugepage_mem_enough(size_t size) return 1; } -static struct page *hugetlb_nopage(struct vm_area_struct * area, unsigned long address, int unused) +static struct page *hugetlb_nopage(struct vm_area_struct * area, unsigned long address, int *unused) { BUG(); return NULL; diff -puN arch/ppc64/mm/hugetlbpage.c~pagefault-accounting-fix arch/ppc64/mm/hugetlbpage.c --- 25/arch/ppc64/mm/hugetlbpage.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/arch/ppc64/mm/hugetlbpage.c 2003-11-17 17:32:29.000000000 -0800 @@ -921,7 +921,7 @@ int is_hugepage_mem_enough(size_t size) * this far. */ static struct page *hugetlb_nopage(struct vm_area_struct *vma, - unsigned long address, int unused) + unsigned long address, int *unused) { BUG(); return NULL; diff -puN arch/sparc64/mm/hugetlbpage.c~pagefault-accounting-fix arch/sparc64/mm/hugetlbpage.c --- 25/arch/sparc64/mm/hugetlbpage.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/arch/sparc64/mm/hugetlbpage.c 2003-11-17 17:33:50.000000000 -0800 @@ -504,7 +504,7 @@ int is_hugepage_mem_enough(size_t size) * this far. */ static struct page *hugetlb_nopage(struct vm_area_struct *vma, - unsigned long address, int unused) + unsigned long address, int *unused) { BUG(); return NULL; diff -puN Documentation/filesystems/Locking~pagefault-accounting-fix Documentation/filesystems/Locking --- 25/Documentation/filesystems/Locking~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/Documentation/filesystems/Locking 2003-11-17 17:32:29.000000000 -0800 @@ -420,7 +420,7 @@ transfer: no prototypes: void (*open)(struct vm_area_struct*); void (*close)(struct vm_area_struct*); - struct page *(*nopage)(struct vm_area_struct*, unsigned long, int); + struct page *(*nopage)(struct vm_area_struct*, unsigned long, int *); locking rules: BKL mmap_sem diff -puN drivers/char/agp/alpha-agp.c~pagefault-accounting-fix drivers/char/agp/alpha-agp.c --- 25/drivers/char/agp/alpha-agp.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/drivers/char/agp/alpha-agp.c 2003-11-17 17:32:29.000000000 -0800 @@ -13,7 +13,7 @@ static struct page *alpha_core_agp_vm_nopage(struct vm_area_struct *vma, unsigned long address, - int write_access) + int *type) { alpha_agp_info *agp = agp_bridge->dev_private_data; dma_addr_t dma_addr; @@ -30,6 +30,8 @@ static struct page *alpha_core_agp_vm_no */ page = virt_to_page(__va(pa)); get_page(page); + if (type) + *type = VM_FAULT_MINOR; return page; } diff -puN drivers/char/drm/drmP.h~pagefault-accounting-fix drivers/char/drm/drmP.h --- 25/drivers/char/drm/drmP.h~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/drivers/char/drm/drmP.h 2003-11-17 17:32:29.000000000 -0800 @@ -760,16 +760,16 @@ extern int DRM(fasync)(int fd, stru /* Mapping support (drm_vm.h) */ extern struct page *DRM(vm_nopage)(struct vm_area_struct *vma, unsigned long address, - int write_access); + int *type); extern struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, unsigned long address, - int write_access); + int *type); extern struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, unsigned long address, - int write_access); + int *type); extern struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, unsigned long address, - int write_access); + int *type); extern void DRM(vm_open)(struct vm_area_struct *vma); extern void DRM(vm_close)(struct vm_area_struct *vma); extern void DRM(vm_shm_close)(struct vm_area_struct *vma); diff -puN drivers/char/drm/drm_vm.h~pagefault-accounting-fix drivers/char/drm/drm_vm.h --- 25/drivers/char/drm/drm_vm.h~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/drivers/char/drm/drm_vm.h 2003-11-17 17:32:29.000000000 -0800 @@ -76,7 +76,7 @@ struct vm_operations_struct DRM(vm_sg_ */ struct page *DRM(vm_nopage)(struct vm_area_struct *vma, unsigned long address, - int write_access) + int *type) { #if __REALLY_HAVE_AGP drm_file_t *priv = vma->vm_file->private_data; @@ -133,6 +133,8 @@ struct page *DRM(vm_nopage)(struct vm_ar baddr, __va(agpmem->memory->memory[offset]), offset, atomic_read(&page->count)); + if (type) + *type = VM_FAULT_MINOR; return page; } vm_nopage_error: @@ -154,7 +156,7 @@ vm_nopage_error: */ struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma, unsigned long address, - int write_access) + int *type) { drm_map_t *map = (drm_map_t *)vma->vm_private_data; unsigned long offset; @@ -170,6 +172,8 @@ struct page *DRM(vm_shm_nopage)(struct v if (!page) return NOPAGE_OOM; get_page(page); + if (type) + *type = VM_FAULT_MINOR; DRM_DEBUG("shm_nopage 0x%lx\n", address); return page; @@ -268,7 +272,7 @@ void DRM(vm_shm_close)(struct vm_area_st */ struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma, unsigned long address, - int write_access) + int *type) { drm_file_t *priv = vma->vm_file->private_data; drm_device_t *dev = priv->dev; @@ -287,6 +291,8 @@ struct page *DRM(vm_dma_nopage)(struct v (offset & (~PAGE_MASK)))); get_page(page); + if (type) + *type = VM_FAULT_MINOR; DRM_DEBUG("dma_nopage 0x%lx (page %lu)\n", address, page_nr); return page; @@ -304,7 +310,7 @@ struct page *DRM(vm_dma_nopage)(struct v */ struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma, unsigned long address, - int write_access) + int *type) { drm_map_t *map = (drm_map_t *)vma->vm_private_data; drm_file_t *priv = vma->vm_file->private_data; @@ -325,6 +331,8 @@ struct page *DRM(vm_sg_nopage)(struct vm page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); page = entry->pagelist[page_offset]; get_page(page); + if (type) + *type = VM_FAULT_MINOR; return page; } diff -puN drivers/ieee1394/dma.c~pagefault-accounting-fix drivers/ieee1394/dma.c --- 25/drivers/ieee1394/dma.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/drivers/ieee1394/dma.c 2003-11-17 17:32:29.000000000 -0800 @@ -187,7 +187,7 @@ void dma_region_sync(struct dma_region * /* nopage() handler for mmap access */ static struct page* -dma_region_pagefault(struct vm_area_struct *area, unsigned long address, int write_access) +dma_region_pagefault(struct vm_area_struct *area, unsigned long address, int *type) { unsigned long offset; unsigned long kernel_virt_addr; @@ -202,6 +202,8 @@ dma_region_pagefault(struct vm_area_stru (address > (unsigned long) area->vm_start + (PAGE_SIZE * dma->n_pages)) ) goto out; + if (type) + *type = VM_FAULT_MINOR; offset = address - area->vm_start; kernel_virt_addr = (unsigned long) dma->kvirt + offset; ret = vmalloc_to_page((void*) kernel_virt_addr); diff -puN drivers/media/video/video-buf.c~pagefault-accounting-fix drivers/media/video/video-buf.c --- 25/drivers/media/video/video-buf.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/drivers/media/video/video-buf.c 2003-11-17 17:32:29.000000000 -0800 @@ -1078,7 +1078,7 @@ videobuf_vm_close(struct vm_area_struct */ static struct page* videobuf_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr, - int write_access) + int *type) { struct page *page; @@ -1090,6 +1090,8 @@ videobuf_vm_nopage(struct vm_area_struct if (!page) return NOPAGE_OOM; clear_user_page(page_address(page), vaddr, page); + if (type) + *type = VM_FAULT_MINOR; return page; } diff -puN drivers/scsi/sg.c~pagefault-accounting-fix drivers/scsi/sg.c --- 25/drivers/scsi/sg.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/drivers/scsi/sg.c 2003-11-17 17:32:29.000000000 -0800 @@ -1117,7 +1117,7 @@ sg_rb_correct4mmap(Sg_scatter_hold * rsv } static struct page * -sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int unused) +sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type) { Sg_fd *sfp; struct page *page = NOPAGE_SIGBUS; @@ -1157,6 +1157,8 @@ sg_vma_nopage(struct vm_area_struct *vma page = virt_to_page(page_ptr); get_page(page); /* increment page count */ } + if (type) + *type = VM_FAULT_MINOR; return page; } diff -puN fs/ncpfs/mmap.c~pagefault-accounting-fix fs/ncpfs/mmap.c --- 25/fs/ncpfs/mmap.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/fs/ncpfs/mmap.c 2003-11-17 17:32:29.000000000 -0800 @@ -26,7 +26,7 @@ * Fill in the supplied page for mmap */ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, - unsigned long address, int write_access) + unsigned long address, int *type) { struct file *file = area->vm_file; struct dentry *dentry = file->f_dentry; @@ -85,6 +85,15 @@ static struct page* ncp_file_mmap_nopage memset(pg_addr + already_read, 0, PAGE_SIZE - already_read); flush_dcache_page(page); kunmap(page); + + /* + * If I understand ncp_read_kernel() properly, the above always + * fetches from the network, here the analogue of disk. + * -- wli + */ + if (type) + *type = VM_FAULT_MAJOR; + inc_page_state(pgmajfault); return page; } diff -puN include/linux/mm.h~pagefault-accounting-fix include/linux/mm.h --- 25/include/linux/mm.h~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/include/linux/mm.h 2003-11-17 17:32:29.000000000 -0800 @@ -143,7 +143,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 unused); + struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int *type); int (*populate)(struct vm_area_struct * area, unsigned long address, unsigned long len, pgprot_t prot, unsigned long pgoff, int nonblock); }; @@ -407,7 +407,7 @@ static inline int page_mapped(struct pag extern void show_free_areas(void); struct page *shmem_nopage(struct vm_area_struct * vma, - unsigned long address, int unused); + unsigned long address, int *type); struct file *shmem_file_setup(char * name, loff_t size, unsigned long flags); void shmem_lock(struct file * file, int lock); int shmem_zero_setup(struct vm_area_struct *); @@ -565,7 +565,7 @@ extern unsigned long page_unuse(struct p extern void truncate_inode_pages(struct address_space *, loff_t); /* generic vm_area_ops exported for stackable file systems */ -extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int); +struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int *); /* mm/page-writeback.c */ int write_one_page(struct page *page, int wait); diff -puN kernel/sys.c~pagefault-accounting-fix kernel/sys.c --- 25/kernel/sys.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/kernel/sys.c 2003-11-17 17:32:29.000000000 -0800 @@ -1323,8 +1323,6 @@ asmlinkage long sys_setrlimit(unsigned i * either stopped or zombied. In the zombied case the task won't get * reaped till shortly after the call to getrusage(), in both cases the * task being examined is in a frozen state so the counters won't change. - * - * FIXME! Get the fault counts properly! */ int getrusage(struct task_struct *p, int who, struct rusage __user *ru) { diff -puN mm/filemap.c~pagefault-accounting-fix mm/filemap.c --- 25/mm/filemap.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/mm/filemap.c 2003-11-17 17:32:29.000000000 -0800 @@ -990,7 +990,7 @@ static int page_cache_read(struct file * * 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 unused) +struct page * filemap_nopage(struct vm_area_struct * area, unsigned long address, int *type) { int error; struct file *file = area->vm_file; @@ -999,7 +999,7 @@ struct page * filemap_nopage(struct vm_a struct inode *inode = mapping->host; struct page *page; unsigned long size, pgoff, endoff; - int did_readaround = 0; + int did_readaround = 0, majmin = VM_FAULT_MINOR; pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff; endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff; @@ -1048,6 +1048,14 @@ retry_find: if (ra->mmap_miss > ra->mmap_hit + MMAP_LOTSAMISS) goto no_cached_page; + /* + * To keep the pgmajfault counter straight, we need to + * check did_readaround, as this is an inner loop. + */ + if (!did_readaround) { + majmin = VM_FAULT_MAJOR; + inc_page_state(pgmajfault); + } did_readaround = 1; do_page_cache_readahead(mapping, file, pgoff & ~(MMAP_READAROUND-1), MMAP_READAROUND); @@ -1069,6 +1077,8 @@ success: * Found the page and have a reference on it. */ mark_page_accessed(page); + if (type) + *type = majmin; return page; outside_data_content: @@ -1104,7 +1114,10 @@ no_cached_page: return NULL; page_not_uptodate: - inc_page_state(pgmajfault); + if (!did_readaround) { + majmin = VM_FAULT_MAJOR; + inc_page_state(pgmajfault); + } lock_page(page); /* Did it get unhashed while we waited for it? */ diff -puN mm/memory.c~pagefault-accounting-fix mm/memory.c --- 25/mm/memory.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/mm/memory.c 2003-11-17 17:32:29.000000000 -0800 @@ -1431,7 +1431,7 @@ do_no_page(struct mm_struct *mm, struct } smp_rmb(); /* Prevent CPU from reordering lock-free ->nopage() */ retry: - new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, 0); + new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, &ret); /* no page was available -- either SIGBUS or OOM */ if (new_page == NOPAGE_SIGBUS) @@ -1500,14 +1500,12 @@ retry: pte_unmap(page_table); page_cache_release(new_page); spin_unlock(&mm->page_table_lock); - ret = VM_FAULT_MINOR; goto out; } /* no need to invalidate: a not-present page shouldn't be cached */ update_mmu_cache(vma, address, entry); spin_unlock(&mm->page_table_lock); - ret = VM_FAULT_MAJOR; goto out; oom: ret = VM_FAULT_OOM; diff -puN mm/shmem.c~pagefault-accounting-fix mm/shmem.c --- 25/mm/shmem.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/mm/shmem.c 2003-11-17 17:32:29.000000000 -0800 @@ -71,7 +71,7 @@ enum sgp_type { }; static int shmem_getpage(struct inode *inode, unsigned long idx, - struct page **pagep, enum sgp_type sgp); + struct page **pagep, enum sgp_type sgp, int *type); static inline struct page *shmem_dir_alloc(unsigned int gfp_mask) { @@ -540,7 +540,7 @@ static int shmem_notify_change(struct de if (attr->ia_size & (PAGE_CACHE_SIZE-1)) { (void) shmem_getpage(inode, attr->ia_size>>PAGE_CACHE_SHIFT, - &page, SGP_READ); + &page, SGP_READ, NULL); } /* * Reset SHMEM_PAGEIN flag so that shmem_truncate can @@ -765,7 +765,7 @@ redirty: * vm. If we swap it in we mark it dirty since we also free the swap * entry since a page cannot live in both the swap and page cache */ -static int shmem_getpage(struct inode *inode, unsigned long idx, struct page **pagep, enum sgp_type sgp) +static int shmem_getpage(struct inode *inode, unsigned long idx, struct page **pagep, enum sgp_type sgp, int *type) { struct address_space *mapping = inode->i_mapping; struct shmem_inode_info *info = SHMEM_I(inode); @@ -774,7 +774,7 @@ static int shmem_getpage(struct inode *i struct page *swappage; swp_entry_t *entry; swp_entry_t swap; - int error; + int error, majmin = VM_FAULT_MINOR; if (idx >= SHMEM_MAX_INDEX) return -EFBIG; @@ -811,6 +811,10 @@ repeat: if (!swappage) { shmem_swp_unmap(entry); spin_unlock(&info->lock); + /* here we actually do the io */ + if (majmin == VM_FAULT_MINOR && type) + inc_page_state(pgmajfault); + majmin = VM_FAULT_MAJOR; swapin_readahead(swap); swappage = read_swap_cache_async(swap); if (!swappage) { @@ -959,6 +963,8 @@ done: } else *pagep = ZERO_PAGE(0); } + if (type) + *type = majmin; return 0; failed: @@ -969,7 +975,7 @@ failed: return error; } -struct page *shmem_nopage(struct vm_area_struct *vma, unsigned long address, int unused) +struct page *shmem_nopage(struct vm_area_struct *vma, unsigned long address, int *type) { struct inode *inode = vma->vm_file->f_dentry->d_inode; struct page *page = NULL; @@ -980,7 +986,7 @@ struct page *shmem_nopage(struct vm_area idx += vma->vm_pgoff; idx >>= PAGE_CACHE_SHIFT - PAGE_SHIFT; - error = shmem_getpage(inode, idx, &page, SGP_CACHE); + error = shmem_getpage(inode, idx, &page, SGP_CACHE, type); if (error) return (error == -ENOMEM)? NOPAGE_OOM: NOPAGE_SIGBUS; @@ -1007,7 +1013,7 @@ static int shmem_populate(struct vm_area /* * Will need changing if PAGE_CACHE_SIZE != PAGE_SIZE */ - err = shmem_getpage(inode, pgoff, &page, sgp); + err = shmem_getpage(inode, pgoff, &page, sgp, NULL); if (err) return err; if (page) { @@ -1157,7 +1163,7 @@ static int shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) { struct inode *inode = page->mapping->host; - return shmem_getpage(inode, page->index, &page, SGP_WRITE); + return shmem_getpage(inode, page->index, &page, SGP_WRITE, NULL); } static ssize_t @@ -1214,7 +1220,7 @@ shmem_file_write(struct file *file, cons * But it still may be a good idea to prefault below. */ - err = shmem_getpage(inode, index, &page, SGP_WRITE); + err = shmem_getpage(inode, index, &page, SGP_WRITE, NULL); if (err) break; @@ -1296,7 +1302,7 @@ static void do_shmem_file_read(struct fi break; } - desc->error = shmem_getpage(inode, index, &page, SGP_READ); + desc->error = shmem_getpage(inode, index, &page, SGP_READ, NULL); if (desc->error) { if (desc->error == -EINVAL) desc->error = 0; @@ -1552,7 +1558,7 @@ static int shmem_symlink(struct inode *d iput(inode); return -ENOMEM; } - error = shmem_getpage(inode, 0, &page, SGP_WRITE); + error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL); if (error) { vm_unacct_memory(VM_ACCT(1)); iput(inode); @@ -1590,7 +1596,7 @@ static int shmem_follow_link_inline(stru static int shmem_readlink(struct dentry *dentry, char __user *buffer, int buflen) { struct page *page = NULL; - int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ); + int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL); if (res) return res; res = vfs_readlink(dentry, buffer, buflen, kmap(page)); @@ -1603,7 +1609,7 @@ static int shmem_readlink(struct dentry static int shmem_follow_link(struct dentry *dentry, struct nameidata *nd) { struct page *page = NULL; - int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ); + int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL); if (res) return res; res = vfs_follow_link(nd, kmap(page)); diff -puN sound/core/pcm_native.c~pagefault-accounting-fix sound/core/pcm_native.c --- 25/sound/core/pcm_native.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/sound/core/pcm_native.c 2003-11-17 17:32:29.000000000 -0800 @@ -2779,7 +2779,7 @@ unsigned int snd_pcm_capture_poll(struct return mask; } -static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, unsigned long address, int no_share) +static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, unsigned long address, int *type) { snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data; snd_pcm_runtime_t *runtime; @@ -2791,6 +2791,8 @@ static struct page * snd_pcm_mmap_status page = virt_to_page(runtime->status); if (!PageReserved(page)) get_page(page); + if (type) + *type = VM_FAULT_MINOR; return page; } diff -puN sound/oss/emu10k1/audio.c~pagefault-accounting-fix sound/oss/emu10k1/audio.c --- 25/sound/oss/emu10k1/audio.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/sound/oss/emu10k1/audio.c 2003-11-17 17:32:29.000000000 -0800 @@ -989,7 +989,7 @@ static int emu10k1_audio_ioctl(struct in return 0; } -static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma, unsigned long address, int write_access) +static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma, unsigned long address, int *type) { struct emu10k1_wavedevice *wave_dev = vma->vm_private_data; struct woinst *woinst = wave_dev->woinst; @@ -1032,6 +1032,8 @@ static struct page *emu10k1_mm_nopage (s get_page (dmapage); DPD(3, "page: %#lx\n", (unsigned long) dmapage); + if (type) + *type = VM_FAULT_MINOR; return dmapage; } diff -puN sound/oss/via82cxxx_audio.c~pagefault-accounting-fix sound/oss/via82cxxx_audio.c --- 25/sound/oss/via82cxxx_audio.c~pagefault-accounting-fix 2003-11-17 17:32:29.000000000 -0800 +++ 25-akpm/sound/oss/via82cxxx_audio.c 2003-11-17 17:32:29.000000000 -0800 @@ -2116,7 +2116,7 @@ static void via_dsp_cleanup (struct via_ static struct page * via_mm_nopage (struct vm_area_struct * vma, - unsigned long address, int write_access) + unsigned long address, int *type) { struct via_info *card = vma->vm_private_data; struct via_channel *chan = &card->ch_out; @@ -2124,12 +2124,11 @@ static struct page * via_mm_nopage (stru unsigned long pgoff; int rd, wr; - DPRINTK ("ENTER, start %lXh, ofs %lXh, pgoff %ld, addr %lXh, wr %d\n", + DPRINTK ("ENTER, start %lXh, ofs %lXh, pgoff %ld, addr %lXh\n", vma->vm_start, address - vma->vm_start, (address - vma->vm_start) >> PAGE_SHIFT, - address, - write_access); + address); if (address > vma->vm_end) { DPRINTK ("EXIT, returning NOPAGE_SIGBUS\n"); @@ -2167,6 +2166,8 @@ static struct page * via_mm_nopage (stru DPRINTK ("EXIT, returning page %p for cpuaddr %lXh\n", dmapage, (unsigned long) chan->pgtbl[pgoff].cpuaddr); get_page (dmapage); + if (type) + *type = VM_FAULT_MINOR; return dmapage; } _