From: William Lee Irwin III <wli@holomorphy.com> 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-23 19:16:00.000000000 -0800 +++ 25-akpm/arch/i386/mm/hugetlbpage.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/arch/ia64/ia32/binfmt_elf32.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/arch/ia64/mm/hugetlbpage.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/arch/ppc64/mm/hugetlbpage.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/arch/sparc64/mm/hugetlbpage.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/Documentation/filesystems/Locking 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/drivers/char/agp/alpha-agp.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/drivers/char/drm/drmP.h 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/drivers/char/drm/drm_vm.h 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/drivers/ieee1394/dma.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/drivers/media/video/video-buf.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/drivers/scsi/sg.c 2003-11-23 19:16:00.000000000 -0800 @@ -1118,7 +1118,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; @@ -1158,6 +1158,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-23 19:16:00.000000000 -0800 +++ 25-akpm/fs/ncpfs/mmap.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/include/linux/mm.h 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/kernel/sys.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/mm/filemap.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/mm/memory.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/mm/shmem.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/sound/core/pcm_native.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/sound/oss/emu10k1/audio.c 2003-11-23 19:16:00.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-23 19:16:00.000000000 -0800 +++ 25-akpm/sound/oss/via82cxxx_audio.c 2003-11-23 19:16:00.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; } _