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