[RFC PATCH 1/3] mm: mmap: export necessary functions for overlayfs' mmap
From: Chengguang Xu <hidden>
Date: 2020-08-29 09:52:03
Also in:
linux-unionfs
Subsystem:
memory management, memory management - core, page cache, the rest · Maintainers:
Andrew Morton, David Hildenbrand, Matthew Wilcox, Jan Kara, Linus Torvalds
In shared mode mmap, if overlayfs' inode does not have data in upper layer, it should call maybe_unlock_mmap_for_io() to release lock and waiting for IO in ->fault handler. Meanwhile, in order to avoid endless retry we should also check flag FAULT_FLAG_TRIED carefully in ->fault handler. Signed-off-by: Chengguang Xu <redacted> --- include/linux/mm.h | 2 ++ mm/filemap.c | 28 ++++++++++++++++++++++++++++ mm/internal.h | 22 ---------------------- 3 files changed, 30 insertions(+), 22 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index dc7b87310c10..214b23734eed 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h@@ -1656,6 +1656,8 @@ void unmap_mapping_pages(struct address_space *mapping, pgoff_t start, pgoff_t nr, bool even_cows); void unmap_mapping_range(struct address_space *mapping, loff_t const holebegin, loff_t const holelen, int even_cows); +struct file *maybe_unlock_mmap_for_io(struct vm_fault *vmf, struct file *fpin); +bool fault_flag_check(struct vm_fault *vmf, unsigned int flag); #else static inline vm_fault_t handle_mm_fault(struct vm_area_struct *vma, unsigned long address, unsigned int flags)
diff --git a/mm/filemap.c b/mm/filemap.c
index f0ae9a6308cb..8a226f8ca262 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c@@ -2704,6 +2704,34 @@ int generic_file_readonly_mmap(struct file *file, struct vm_area_struct *vma) return -EINVAL; return generic_file_mmap(file, vma); } + +struct file *maybe_unlock_mmap_for_io(struct vm_fault *vmf, + struct file *fpin) +{ + int flags = vmf->flags; + + if (fpin) + return fpin; + + /* + * FAULT_FLAG_RETRY_NOWAIT means we don't want to wait on page locks or + * anything, so we only pin the file and drop the mmap_lock if only + * FAULT_FLAG_ALLOW_RETRY is set, while this is the first attempt. + */ + if (fault_flag_allow_retry_first(flags) && + !(flags & FAULT_FLAG_RETRY_NOWAIT)) { + fpin = get_file(vmf->vma->vm_file); + mmap_read_unlock(vmf->vma->vm_mm); + } + return fpin; +} +EXPORT_SYMBOL(maybe_unlock_mmap_for_io); + +bool fault_flag_check(struct vm_fault *vmf, unsigned int flag) +{ + return vmf->flags & flag; +} +EXPORT_SYMBOL(fault_flag_check); #else vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf) {
diff --git a/mm/internal.h b/mm/internal.h
index 9886db20d94f..ef19235c6bf1 100644
--- a/mm/internal.h
+++ b/mm/internal.h@@ -402,28 +402,6 @@ vma_address(struct page *page, struct vm_area_struct *vma) return max(start, vma->vm_start); } - -static inline struct file *maybe_unlock_mmap_for_io(struct vm_fault *vmf, - struct file *fpin) -{ - int flags = vmf->flags; - - if (fpin) - return fpin; - - /* - * FAULT_FLAG_RETRY_NOWAIT means we don't want to wait on page locks or - * anything, so we only pin the file and drop the mmap_lock if only - * FAULT_FLAG_ALLOW_RETRY is set, while this is the first attempt. - */ - if (fault_flag_allow_retry_first(flags) && - !(flags & FAULT_FLAG_RETRY_NOWAIT)) { - fpin = get_file(vmf->vma->vm_file); - mmap_read_unlock(vmf->vma->vm_mm); - } - return fpin; -} - #else /* !CONFIG_MMU */ static inline void clear_page_mlock(struct page *page) { } static inline void mlock_vma_page(struct page *page) { }
--
2.20.1