diff mbox series

[RFC,1/3] mm: mmap: export necessary functions for overlayfs' mmap

Message ID 20200829095101.25350-2-cgxu519@mykernel.net (mailing list archive)
State New, archived
Headers show
Series ovl: stacked mmap for shared map | expand

Commit Message

Chengguang Xu Aug. 29, 2020, 9:50 a.m. UTC
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 <cgxu519@mykernel.net>
---
 include/linux/mm.h |  2 ++
 mm/filemap.c       | 28 ++++++++++++++++++++++++++++
 mm/internal.h      | 22 ----------------------
 3 files changed, 30 insertions(+), 22 deletions(-)
diff mbox series

Patch

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) { }