vm_operation to avoid pagefault/inval race
Subsystems (11)
Please don't take lack of response for lack of interest. The generic issue here is "what are the vfs changes needed to support cross-host mmap?". You defined the problem nicely.
Quoted 4 lines
[...]
5. One way or another, life is now hard.
Indeed. In brief, ->nopage just doesn't provide adequate coverage to support the cross-host lock.
Quoted 10 lines
One solution would be for the distributed filesystem to hold onto a lock or semaphore upon return from the nopage function. The problem is that there is no way to determine (in a timely fashion) when it safe to release this lock or semaphore.
The attached patch addresses this by adding a nopagedone function for when
do_no_page()exits. The filesystem may then drop the lock or semaphore in this nopagedone function.Thoughts? Is there some other existing way to get this done?
There is. One way is to make all of do_no_page a hook, and clearly this is more generic than what you proposed, since it covers your hook and the rest can be done with library calls. Once you've gone there, the next question to ask is "what use is the existing ->nopage" hook, and the answer is: none, really. The existing usage of ->nopage can be replaced by ->do_no_page plus library code, and the only problem is, we have to change pretty well every filesystem in and out of tree. So that gets a little, em, interesting from the 2.6.0 point of view, which is why I cc'd Andrew on this. Christoph has also expressed interest in this, which explains the other cc.
Any clustered filesystem that wants to support posix mmap is going to need this hook, so the sooner we hash this out, the better.
Regards,
Daniel
Quoted 3 lines · Daniel Phillips
and the only problem is, we have to change pretty well every
filesystem in and out of tree.
But it's only a one-liner per fs.
Quoted 6 lines · Andrew Morton
Quoted 3 lines · Daniel Phillips
and the only problem is, we have to change pretty well every
filesystem in and out of tree.But it's only a one-liner per fs.
So the general idea is to do something as follows, right? (Sorry for not just putting together a patch -- I want to make sure I understand all of your advice first!)
o Make all callers to do_no_page() instead call
vma->vm_ops->nopage().
o Make a function, perhaps named something like
install_new_page(), that does the PTE-installation and RSS-adjustment tasks currently performed by both do_no_page() and by do_anonymous_page(). (Not clear to me yet whether a full merge of these two functions is the right approach, more thought needed. Note that the nopage function is implicitly aware of whether it is handling an anonymous page or not, so a pair of functions that both call another function containing the common code is reasonable, if warranted.)
The install_new_page() function needs an additional argument to accept the new_page value that used to be returned by the nopage() function.
o Add arguments to nopage() to allow it to invoke
install_new_page().
o Change all nopage() functions to invoke install_new_page(),
but only in cases where they would -not- return VM_FAULT_OOM or VM_FAULT_SIGBUS. In these cases, these two return codes must be handed back to the caller without invoking install_new_page().
o Otherwise, the value that these nopage() functions
would normally return must be passed to install_new_page(), and the value returned by install_new_page() must be returned to the nopage() function's caller.
o Replace all occurrences of "->vm_ops = NULL" with
"->vm_ops = anonymous_vm_ops" or some such.
o The anonymous_vm_ops would have the following members:
nopage: pointer to a function containing the page-allocation
code extracted from do_anonymous_page(), followed by a call to install_new_page().
populate: NULL.
open: NULL.
close: NULL.
Thoughts?
Thanx, Paul
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 2 lines · Paul E. McKenney
So the general idea is to do something as follows, right?
It sounds reasonable. A matter of putting together the appropriate library functions and refactoring a few things.
Quoted 5 lines
o Make a function, perhaps named something like
install_new_page(), that does the PTE-installation and RSS-adjustment tasks currently performed by bothdo_no_page()and bydo_anonymous_page().
That's similar to mm/fremap.c:install_page(). (Which forgets to call update_mmu_cache(). Debatably a buglet.)
However there is not a lot of commonality between the various nopage()s and there may not be a lot to be gained from all this. There is subtle code in there and it is performance-critical. I'd be inclined to try to minimise overall code churn in this work.
RFC PATCH 1/1 Avoid vmtruncate/mmap-page-fault race
Quoted 13 lines · Andrew Morton
Quoted 2 lines · Paul E. McKenney
So the general idea is to do something as follows, right?
It sounds reasonable. A matter of putting together the appropriate library functions and refactoring a few things.
Quoted 5 lines
o Make a function, perhaps named something like
install_new_page(), that does the PTE-installation and RSS-adjustment tasks currently performed by bothdo_no_page()and bydo_anonymous_page().
Quoted 7 lines
That's similar to mm/fremap.c:install_page(). (Which forgets to call
update_mmu_cache(). Debatably a buglet.)However there is not a lot of commonality between the various nopage()s and there may not be a lot to be gained from all this. There is subtle code in there and it is performance-critical. I'd be inclined to try to minimise overall code churn in this work.
Good point! Here is a patch to do this. A "few" caveats:
o I have not tested this, in fact, I have only compiled
it for i386.
o The bit about removing checks for vm_ops==NULL and
making do_anonymous_page() be just another nopage function turned out to be problematic, since the do_anonymous_page() function wants page_table_lock held, and the other nopage functions do not.
So I kept the NULL checks, since I was going to need some anyway (I did -not- want to make every nopage function have to explicitly drop page_table_lock).
I am especially interested in feedback on this point -- did I miss something here?
o I had to expand the trace of the nopage functions to
pass through the mm_struct and the pmd_t to the new install_new_page() function.
o The nopage functions now return an int instead of
the old struct page*.
o NOPAGE_OOM and NOPAGE_SIGBUS are no more, since
one case just use VM_FAULT_OOM and VM_FAULT_SIGBUS instead.
o I still need to remove some LINUX_2_2 stuff (thanks
to Dan Phillips for letting me know it was OK to do so...).
o This patch is a bit long. Thoughts on how to break it up?
Thanx, Paul
arch/ia64/ia32/binfmt_elf32.c +3 -3
@@ -56,13 +56,13 @@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) +struct int +ia32_install_shared_page (struct mm_struct *mm,struct vm_area_struct *vma,unsigned long address,int write_access,pmd_t *pmd) {struct page *pg = ia32_shared_page[(address - vma->vm_start)/PAGE_SIZE ];get_page (pg); -return pg; +return install_new_page (mm, vma, address, write_access, pmd, pg); }static struct vm_operations_struct ia32_shared_page_vm_ops = {
arch/sparc64/mm/hugetlbpage.c +4 -3
@@ -633,11 +633,12 @@return (int ) htlbzone_pages; } -static struct page * -hugetlb_nopage (struct vm_area_struct *vma,unsigned long address,int unused) +static int +hugetlb_nopage (struct mm_struct * mm,struct vm_area_struct *vma, +unsigned long address,int write_access,pmd_t * pmd) {BUG (); -return NULL ; +return VM_FAULT_SIGBUS ; }static struct vm_operations_struct hugetlb_vm_ops = {
drivers/char/agp/alpha-agp.c +8 -5
@@ -11,9 +11,11 @@#include "agp.h" -static struct page *alpha_core_agp_vm_nopage (struct vm_area_struct *vma, -unsigned long address, -int write_access) +static int alpha_core_agp_vm_nopage (struct mm_struct *mm, +struct vm_area_struct *vma, +unsigned long address, +int write_access, +pmd_t pmd) {alpha_agp_info *agp = agp_bridge->dev_private_data;dma_addr_t dma_addr;
@@ -23,14 +25,15 @@ dma_addr = address - vma->vm_start + agp->aperture.bus_base; pa = agp->ops->translate (agp, dma_addr); -if (pa == (unsigned long )-EINVAL )return NULL ;/* no translation */ +if (pa == (unsigned long )-EINVAL )return VM_FAULT_SIGBUS ; +/* no translation */ /* * Get the page, inc the use count, and return it */ page =virt_to_page (__va (pa));get_page (page); -return page; +return install_new_page (mm, vma, address, write_access, pmd, page); } static struct aper_size_info_fixed alpha_core_agp_sizes[] =
drivers/char/drm/drmP.h +20 -12
@@ -620,18 +620,26 @@extern int DRM (fasync )(int fd,struct file *filp,int on);/* Mapping support (drm_vm.h) */ -extern struct page *DRM (vm_nopage )(struct vm_area_struct *vma, -unsigned long address, -int write_access); -extern struct page *DRM (vm_shm_nopage )(struct vm_area_struct *vma, -unsigned long address, -int write_access); -extern struct page *DRM (vm_dma_nopage )(struct vm_area_struct *vma, -unsigned long address, -int write_access); -extern struct page *DRM (vm_sg_nopage )(struct vm_area_struct *vma, -unsigned long address, -int write_access); +extern int DRM (vm_nopage )(struct mm_struct *mm, +struct vm_area_struct *vma, +unsigned long address, +int write_access, +pmd_t *pmd); +extern int DRM (vm_shm_nopage )(struct mm_struct *mm, +struct vm_area_struct *vma, +unsigned long address, +int write_access, +pmd_t *pmd); +extern int DRM (vm_dma_nopage )(struct mm_struct *mm, +struct vm_area_struct *vma, +unsigned long address, +int write_access, +pmd_t *pmd); +extern int DRM (vm_sg_nopage )(struct mm_struct *mm, +struct vm_area_struct *vma, +unsigned long address, +int write_access, +pmd_t *pmd);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);
drivers/char/drm/drm_vm.h +35 -26
125 lines not on this page · raw message
drivers/ieee1394/dma.c +9 -9
@@ -184,28 +184,28 @@/* nopage() handler for mmap access */ -static struct page * -dma_region_pagefault (struct vm_area_struct *area,unsigned long address,int write_access) +static int +dma_region_pagefault (struct mm_struct *mm,struct vm_area_struct *area, +unsigned long address,int write_access,pmd_t *pmd) {unsigned long offset;unsigned long kernel_virt_addr; -struct page *ret =NOPAGE_SIGBUS ; +struct page *page;struct dma_region *dma = (struct dma_region *) area->vm_private_data;if (!dma->kvirt) - goto out; +return VM_FAULT_SIGBUS ;if ( (address < (unsigned long ) area->vm_start) || (address > (unsigned long ) area->vm_start + (PAGE_SIZE * dma->n_pages)) ) - goto out; +return VM_FAULT_SIGBUS ; offset = address - area->vm_start; kernel_virt_addr = (unsigned long ) dma->kvirt + offset; - ret =vmalloc_to_page ((void *) kernel_virt_addr); -get_page (ret); -out: -return ret; + page =vmalloc_to_page ((void *) kernel_virt_addr); +get_page (page); +return install_new_page (mm, vma, address, write_access, pmd, page); }static struct vm_operations_struct dma_region_vm_ops = {
drivers/media/video/video-buf.c +6 -6
@@ -979,21 +979,21 @@* now ...). Bounce buffers don't work very well for the data rates * video capture has. */ -static struct page * -videobuf_vm_nopage (struct vm_area_struct *vma,unsigned long vaddr, -int write_access) +static int +videobuf_vm_nopage (struct mm_struct *mm,struct vm_area_struct *vma, +unsigned long vaddr,int write_access,pmd_t pmd) {struct page *page;dprintk (3 ,"nopage: fault @ %08lx [vma %08lx-%08lx]\n" , vaddr,vma->vm_start,vma->vm_end);if (vaddr > vma->vm_end) -return NOPAGE_SIGBUS ; +return VM_FAULT_SIGBUS ; page =alloc_page (GFP_USER );if (!page) -return NOPAGE_OOM ; +return VM_FAULT_OOM ;clear_user_page (page_address (page), vaddr, page); -return page; +return install_new_page (mm, vma, vaddr, write_access, pmd, page); } static struct vm_operations_struct videobuf_vm_ops =
drivers/scsi/sg.c +7 -6
@@ -1121,21 +1121,22 @@ } } -static struct page * -sg_vma_nopage (struct vm_area_struct *vma,unsigned long addr,int unused) +static int +sg_vma_nopage (struct mm_struct *mm,struct vm_area_struct *vma, +unsigned long addr,int write_access,pmd_t *pmd) {Sg_fd *sfp; -struct page *page =NOPAGE_SIGBUS ; +struct page *page =VM_FAULT_SIGBUS ;void *page_ptr =NULL ;unsigned long offset;Sg_scatter_hold *rsv_schp;if ((NULL == vma) || (!(sfp = (Sg_fd *) vma->vm_private_data))) -return page; +return install_new_page (mm, vma, addr, write_access, pmd, page); rsv_schp = &sfp->reserve; offset = addr - vma->vm_start;if (offset >= rsv_schp->bufflen) -return page; +return install_new_page (mm, vma, addr, write_access, pmd, page);SCSI_LOG_TIMEOUT (3 ,printk ("sg_vma_nopage: offset=%lu, scatg=%d\n" , offset, rsv_schp->k_use_sg));if (rsv_schp->k_use_sg) {/* reserve buffer is a scatter gather list */
@@ -1162,7 +1163,7 @@ page =virt_to_page (page_ptr);get_page (page);/* increment page count */ } -return page; +return install_new_page (mm, vma, addr, write_access, pmd, page); }static struct vm_operations_struct sg_mmap_vm_ops = {
drivers/sgi/char/graphics.c +4 -4
@@ -211,9 +211,9 @@/* * This is the core of the direct rendering engine. */ -struct page * -sgi_graphics_nopage (struct vm_area_struct *vma,unsigned long address,int - no_share) +struct int +sgi_graphics_nopage (struct mm_struct *mm,struct vm_area_struct *vma, +unsigned long address,int write_access,pmd_t *pmdpf) {pgd_t *pgd;pmd_t *pmd;pte_t *pte;int board =GRAPHICS_CARD (vma->vm_dentry->d_inode->i_rdev);
@@ -249,7 +249,7 @@ pte =pte_kmap_offset (pmd, address); page =pte_page (*pte);pte_kunmap (pte); -return page; +return install_new_page (mm, vma, address, write_access, pmdpf, page); }/*
fs/ncpfs/mmap.c +5 -3
@@ -25,8 +25,10 @@/* * 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) +static int ncp_file_mmap_nopage (struct mm_struct *mm, +struct vm_area_struct *area, +unsigned long address,int write_access, +pmd_t *pmd) {struct file *file = area->vm_file;struct dentry *dentry = file->f_dentry;
@@ -85,7 +87,7 @@memset (pg_addr + already_read,0 ,PAGE_SIZE - already_read);flush_dcache_page (page);kunmap (page); -return page; +return install_new_page (mm, area, address, write_access, pmd, page); } static struct vm_operations_struct ncp_file_mmap =
include/linux/mm.h +9 -10
@@ -142,7 +142,8 @@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); +int (*nopage)(struct mm_struct * mm,struct vm_area_struct * area, +unsigned long address,int write_access,pmd_t *pmd);int (*populate)(struct vm_area_struct * area,unsigned long address,unsigned long len,pgprot_t prot,unsigned long pgoff,int nonblock); };
@@ -380,12 +381,6 @@ }/* -* Error return values for the *_nopage functions -*/ -#define NOPAGE_SIGBUS (NULL) -#define NOPAGE_OOM ((struct page *) (-1)) - -/* * Different kinds of faults, as returned by handle_mm_fault(). * Used to decide whether a process gets delivered SIGBUS or * just gets major/minor fault counters bumped up.
@@ -402,8 +397,8 @@extern void show_free_areas (void ); -struct page *shmem_nopage (struct vm_area_struct * vma, -unsigned long address,int unused); +int shmem_nopage (struct mm_struct * mm,struct vm_area_struct * vma, +unsigned long address,int write_access,pmd_t * pmd);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 *);
@@ -421,6 +416,9 @@int zeromap_page_range (struct vm_area_struct *vma,unsigned long from,unsigned long size,pgprot_t prot); +extern int install_new_page (struct mm_struct *mm,struct vm_area_struct *vma, +unsigned long address,int write_access, +pmd_t *pmd,struct page * new_page);extern void invalidate_mmap_range (struct address_space *mapping,loff_t const holebegin,loff_t const holelen);
@@ -559,7 +557,8 @@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 ); +int filemap_nopage (struct mm_struct *,struct vm_area_struct *, +unsigned long ,int ,pmd_t *);/* mm/page-writeback.c */ int write_one_page (struct page *page,int wait);
kernel/ksyms.c +1 -0
@@ -116,6 +116,7 @@EXPORT_SYMBOL (max_mapnr);#endif EXPORT_SYMBOL (high_memory); +EXPORT_SYMBOL (install_new_page);EXPORT_SYMBOL (invalidate_mmap_range);EXPORT_SYMBOL (vmtruncate);EXPORT_SYMBOL (find_vma);
mm/filemap.c +7 -6
@@ -982,7 +982,8 @@* 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) +int filemap_nopage (struct mm_struct * mm,struct vm_area_struct * area, +unsigned long address,int write_access,pmd_t * pmd) {int error;struct file *file = area->vm_file;
@@ -1003,7 +1004,7 @@*/ size = (inode->i_size +PAGE_CACHE_SIZE -1 ) >>PAGE_CACHE_SHIFT ;if ((pgoff >= size) && (area->vm_mm == current->mm)) -return NULL ; +return VM_FAULT_SIGBUS ;/* * The "size" of the file, as far as mmap is concerned, isn't bigger
@@ -1057,7 +1058,7 @@* Found the page and have a reference on it. */ mark_page_accessed (page); -return page; +return install_new_page (mm, area, address, write_access, pmd, page); no_cached_page:/*
@@ -1080,8 +1081,8 @@* to schedule I/O. */ if (error == -ENOMEM ) -return NOPAGE_OOM ; -return NULL ; +return VM_FAULT_OOM ; +return VM_FAULT_SIGBUS ; page_not_uptodate:inc_page_state (pgmajfault);
@@ -1138,7 +1139,7 @@* mm layer so, possibly freeing the page cache page first. */ page_cache_release (page); -return NULL ; +return VM_FAULT_SIGBUS ; } static struct page * filemap_getpage(struct file *file, unsigned long pgoff,
mm/memory.c +34 -13
62 lines not on this page · raw message
mm/shmem.c +4 -3
@@ -936,7 +936,8 @@return error; } -struct page *shmem_nopage (struct vm_area_struct *vma,unsigned long address,int unused) +int shmem_nopage (struct mm_struct *mm,struct vm_area_struct *vma, +unsigned long address,int write_access,pmd_t *pmd) {struct inode *inode = vma->vm_file->f_dentry->d_inode;struct page *page =NULL ;
@@ -949,10 +950,10 @@ error =shmem_getpage (inode, idx, &page,SGP_CACHE );if (error) -return (error == -ENOMEM )?NOPAGE_OOM :NOPAGE_SIGBUS ; +return (error == -ENOMEM )?VM_FAULT_OOM :VM_FAULT_SIGBUS ;mark_page_accessed (page); -return page; +return install_new_page (mm, vma, address, write_access, pmd, page); } static int shmem_populate(struct vm_area_struct *vma,
sound/core/pcm_native.c +12 -12
@@ -2693,7 +2693,7 @@#endif #ifndef LINUX_2_2 -static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, unsigned long address, int no_share) +static int snd_pcm_mmap_status_nopage(struct mm_struct *mm, struct vm_area_struct *area, unsigned long address, int write_access, pmd_t *pmd)#else static unsigned long snd_pcm_mmap_status_nopage(struct vm_area_struct *area, unsigned long address, int no_share)#endif
@@ -2703,12 +2703,12 @@struct page * page;if (substream ==NULL ) -return NOPAGE_OOM ; +return VM_FAULT_OOM ; runtime = substream->runtime; page =virt_to_page (runtime->status);get_page (page);#ifndef LINUX_2_2 -return page; +return install_new_page (mm, area, address, write_access, pmd, page);#else return page_address (page);#endif
@@ -2747,7 +2747,7 @@ }#ifndef LINUX_2_2 -static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area, unsigned long address, int no_share) +static int snd_pcm_mmap_control_nopage(struct mm_struct *mm, struct vm_area_struct *area, unsigned long address, int write_access, pmd_t *pmd)#else static unsigned long snd_pcm_mmap_control_nopage(struct vm_area_struct *area, unsigned long address, int no_share)#endif
@@ -2757,12 +2757,12 @@struct page * page;if (substream ==NULL ) -return NOPAGE_OOM ; +return VM_FAULT_OOM ; runtime = substream->runtime; page =virt_to_page (runtime->control);get_page (page);#ifndef LINUX_2_2 -return page; +return install_new_page (mm, area, address, write_access, pmd, page);#else return page_address (page);#endif
@@ -2813,7 +2813,7 @@ }#ifndef LINUX_2_2 -static struct page * snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int no_share) +static int snd_pcm_mmap_data_nopage(struct mm_struct *mm, struct vm_area_struct *area, unsigned long address, int write_access, pmd_t *pmd)#else static unsigned long snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int no_share)#endif
@@ -2826,7 +2826,7 @@size_t dma_bytes;if (substream ==NULL ) -return NOPAGE_OOM ; +return VM_FAULT_OOM ; runtime = substream->runtime;#if LINUX_VERSION_CODE >=KERNEL_VERSION (2 ,3 ,25 ) offset = area->vm_pgoff <<PAGE_SHIFT ;
@@ -2834,21 +2834,21 @@ offset = area->vm_offset;#endif offset += address - area->vm_start; - snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_OOM); + snd_assert((offset % PAGE_SIZE) == 0, return VM_FAULT_OOM); dma_bytes =PAGE_ALIGN (runtime->dma_bytes);if (offset > dma_bytes -PAGE_SIZE ) -return NOPAGE_SIGBUS ; +return VM_FAULT_SIGBUS ;if (substream->ops->page) { page = substream->ops->page (substream, offset);if (! page) -return NOPAGE_OOM ; +return VM_FAULT_OOM ; }else { vaddr = runtime->dma_area + offset; page =virt_to_page (vaddr); }get_page (page);#ifndef LINUX_2_2 -return page; +return install_new_page (mm, area, address, write_access, pmd, page);#else return page_address (page);#endif
sound/oss/emu10k1/audio.c +4 -4
@@ -970,7 +970,7 @@return 0 ; } -static struct page *emu10k1_mm_nopage (struct vm_area_struct * vma,unsigned long address,int write_access) +static int emu10k1_mm_nopage (struct mm_struct * mm,struct vm_area_struct * vma,unsigned long address,int write_access,pmd_t * pmd) {struct emu10k1_wavedevice *wave_dev = vma->vm_private_data;struct woinst *woinst = wave_dev->woinst;
@@ -983,8 +983,8 @@DPD (3 ,"addr: %#lx\n" , address);if (address > vma->vm_end) { -DPF (1 ,"EXIT, returning NOPAGE_SIGBUS\n" ); -return NOPAGE_SIGBUS ;/* Disallow mremap */ +DPF (1 ,"EXIT, returning VM_FAULT_SIGBUS\n" ); +return VM_FAULT_SIGBUS ;/* Disallow mremap */ } pgoff = vma->vm_pgoff + ((address - vma->vm_start) >>PAGE_SHIFT );
@@ -1013,7 +1013,7 @@get_page (dmapage);DPD (3 ,"page: %#lx\n" , (unsigned long ) dmapage); -return dmapage; +return install_new_page (mm, vma, address, write_access, pmd, dmapage); }struct vm_operations_struct emu10k1_mm_ops = {
sound/oss/via82cxxx_audio.c +8 -8
@@ -1846,8 +1846,8 @@ } -static struct page *via_mm_nopage (struct vm_area_struct * vma, -unsigned long address,int write_access) +static int via_mm_nopage (struct mm_struct *mm,struct vm_area_struct * vma, +unsigned long address,int write_access,pmd_t *pmd) {struct via_info *card = vma->vm_private_data;struct via_channel *chan = &card->ch_out;
@@ -1863,12 +1863,12 @@ write_access);if (address > vma->vm_end) { -DPRINTK ("EXIT, returning NOPAGE_SIGBUS\n" ); -return NOPAGE_SIGBUS ;/* Disallow mremap */ +DPRINTK ("EXIT, returning VM_FAULT_SIGBUS\n" ); +return VM_FAULT_SIGBUS ;/* Disallow mremap */ }if (!card) { -DPRINTK ("EXIT, returning NOPAGE_OOM\n" ); -return NOPAGE_OOM ;/* Nothing allocated */ +DPRINTK ("EXIT, returning VM_FAULT_OOM\n" ); +return VM_FAULT_OOM ;/* Nothing allocated */ } pgoff = vma->vm_pgoff + ((address - vma->vm_start) >>PAGE_SHIFT );
@@ -1895,10 +1895,10 @@assert ((((unsigned long )chan->pgtbl[pgoff].cpuaddr) %PAGE_SIZE ) ==0 ); dmapage =virt_to_page (chan->pgtbl[pgoff].cpuaddr); -DPRINTK ("EXIT, returning page %p for cpuaddr %lXh\n" , +DPRINTK ("EXIT, installing page %p for cpuaddr %lXh\n" , dmapage, (unsigned long ) chan->pgtbl[pgoff].cpuaddr);get_page (dmapage); -return dmapage; +return install_new_page (mm, vma, address, write_access, pmd, dmapage); }
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [RFC][PATCH] Avoid vmtruncate/mmap-page-fault race
Quoted 8 lines · Paul E. McKenney
Quoted 5 lines · Andrew Morton
However there is not a lot of commonality between the various nopage()s and there may not be a lot to be gained from all this. There is subtle code in there and it is performance-critical. I'd be inclined to try to minimise overall code churn in this work.
Good point! Here is a patch to do this. A "few" caveats:
Sorry, I miss the point of this patch entirely. At the moment it just looks like an unattractive rearrangement - the code churn akpm advised against - with no bearing on that vmtruncate race. Please correct me.
Hugh
Re: [RFC][PATCH] Avoid vmtruncate/mmap-page-fault race
Quoted 3 lines · Hugh Dickins
Sorry, I miss the point of this patch entirely. At the moment it just looks like an unattractive rearrangement - the code churn akpm advised against - with no bearing on that vmtruncate race. Please correct me.
This is all about supporting cross-host mmap (nice trick, huh?). Yes, somebody should post a detailed rfc on that subject.
Regards,
Daniel
Re: [RFC][PATCH] Avoid vmtruncate/mmap-page-fault race
Quoted 7 lines · Daniel Phillips
Quoted 3 lines · Hugh Dickins
Sorry, I miss the point of this patch entirely. At the moment it just looks like an unattractive rearrangement - the code churn akpm advised against - with no bearing on that vmtruncate race. Please correct me.
This is all about supporting cross-host mmap (nice trick, huh?). Yes, somebody should post a detailed rfc on that subject.
Ah, thanks - translated into terms that I can understand, so that some ->nopage() not yet in the tree could do something after the install_new_page() returns. Hmm. Can we be sure it's appropriate for install_new_page to drop mm->page_table_lock before it returns?
Hugh