123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- SPDX-License-Identifier: GPL-2.0
- aufs5.1 mmap patch
- diff --git a/fs/proc/base.c b/fs/proc/base.c
- index 6a803a0b75df..a51f41a1b4dd 100644
- --- a/fs/proc/base.c
- +++ b/fs/proc/base.c
- @@ -2019,7 +2019,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
- down_read(&mm->mmap_sem);
- vma = find_exact_vma(mm, vm_start, vm_end);
- if (vma && vma->vm_file) {
- - *path = vma->vm_file->f_path;
- + *path = vma_pr_or_file(vma)->f_path;
- path_get(path);
- rc = 0;
- }
- diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
- index 3b63be64e436..fb9913bf3d10 100644
- --- a/fs/proc/nommu.c
- +++ b/fs/proc/nommu.c
- @@ -45,7 +45,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region)
- file = region->vm_file;
-
- if (file) {
- - struct inode *inode = file_inode(region->vm_file);
- + struct inode *inode;
- +
- + file = vmr_pr_or_file(region);
- + inode = file_inode(file);
- dev = inode->i_sb->s_dev;
- ino = inode->i_ino;
- }
- diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
- index 95ca1fe7283c..914d9fa7c596 100644
- --- a/fs/proc/task_mmu.c
- +++ b/fs/proc/task_mmu.c
- @@ -305,7 +305,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
- const char *name = NULL;
-
- if (file) {
- - struct inode *inode = file_inode(vma->vm_file);
- + struct inode *inode;
- +
- + file = vma_pr_or_file(vma);
- + inode = file_inode(file);
- dev = inode->i_sb->s_dev;
- ino = inode->i_ino;
- pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
- @@ -1760,7 +1763,7 @@ static int show_numa_map(struct seq_file *m, void *v)
- struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
- struct vm_area_struct *vma = v;
- struct numa_maps *md = &numa_priv->md;
- - struct file *file = vma->vm_file;
- + struct file *file = vma_pr_or_file(vma);
- struct mm_struct *mm = vma->vm_mm;
- struct mm_walk walk = {
- .hugetlb_entry = gather_hugetlb_stats,
- diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
- index 36bf0f2e102e..8df6cbc58756 100644
- --- a/fs/proc/task_nommu.c
- +++ b/fs/proc/task_nommu.c
- @@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
- file = vma->vm_file;
-
- if (file) {
- - struct inode *inode = file_inode(vma->vm_file);
- + struct inode *inode;
- +
- + file = vma_pr_or_file(vma);
- + inode = file_inode(file);
- dev = inode->i_sb->s_dev;
- ino = inode->i_ino;
- pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
- diff --git a/include/linux/mm.h b/include/linux/mm.h
- index 6b10c21630f5..5951915df163 100644
- --- a/include/linux/mm.h
- +++ b/include/linux/mm.h
- @@ -1486,6 +1486,28 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
- unmap_mapping_range(mapping, holebegin, holelen, 0);
- }
-
- +extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int);
- +extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[],
- + int);
- +extern void vma_do_get_file(struct vm_area_struct *, const char[], int);
- +extern void vma_do_fput(struct vm_area_struct *, const char[], int);
- +
- +#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \
- + __LINE__)
- +#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \
- + __LINE__)
- +#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__)
- +#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__)
- +
- +#ifndef CONFIG_MMU
- +extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int);
- +extern void vmr_do_fput(struct vm_region *, const char[], int);
- +
- +#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \
- + __LINE__)
- +#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__)
- +#endif /* !CONFIG_MMU */
- +
- extern int access_process_vm(struct task_struct *tsk, unsigned long addr,
- void *buf, int len, unsigned int gup_flags);
- extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
- diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
- index 4ef4bbe78a1d..8cac6e0bc1a8 100644
- --- a/include/linux/mm_types.h
- +++ b/include/linux/mm_types.h
- @@ -250,6 +250,7 @@ struct vm_region {
- unsigned long vm_top; /* region allocated to here */
- unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */
- struct file *vm_file; /* the backing file or NULL */
- + struct file *vm_prfile; /* the virtual backing file or NULL */
-
- int vm_usage; /* region usage count (access under nommu_region_sem) */
- bool vm_icache_flushed : 1; /* true if the icache has been flushed for
- @@ -324,6 +325,7 @@ struct vm_area_struct {
- unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
- units */
- struct file * vm_file; /* File we map to (can be NULL). */
- + struct file *vm_prfile; /* shadow of vm_file */
- void * vm_private_data; /* was vm_pte (shared mem) */
-
- atomic_long_t swap_readahead_info;
- diff --git a/kernel/fork.c b/kernel/fork.c
- index 9dcd18aa210b..cf478ebb6926 100644
- --- a/kernel/fork.c
- +++ b/kernel/fork.c
- @@ -546,7 +546,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
- struct inode *inode = file_inode(file);
- struct address_space *mapping = file->f_mapping;
-
- - get_file(file);
- + vma_get_file(tmp);
- if (tmp->vm_flags & VM_DENYWRITE)
- atomic_dec(&inode->i_writecount);
- i_mmap_lock_write(mapping);
- diff --git a/mm/Makefile b/mm/Makefile
- index d210cc9d6f80..e77e80ce7298 100644
- --- a/mm/Makefile
- +++ b/mm/Makefile
- @@ -39,7 +39,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \
- mm_init.o mmu_context.o percpu.o slab_common.o \
- compaction.o vmacache.o \
- interval_tree.o list_lru.o workingset.o \
- - debug.o $(mmu-y)
- + prfile.o debug.o $(mmu-y)
-
- obj-y += init-mm.o
- obj-y += memblock.o
- diff --git a/mm/filemap.c b/mm/filemap.c
- index d78f577baef2..7dcd21948a79 100644
- --- a/mm/filemap.c
- +++ b/mm/filemap.c
- @@ -2764,7 +2764,7 @@ vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf)
- vm_fault_t ret = VM_FAULT_LOCKED;
-
- sb_start_pagefault(inode->i_sb);
- - file_update_time(vmf->vma->vm_file);
- + vma_file_update_time(vmf->vma);
- lock_page(page);
- if (page->mapping != inode->i_mapping) {
- unlock_page(page);
- diff --git a/mm/mmap.c b/mm/mmap.c
- index bd7b9f293b39..f3fd32a1df36 100644
- --- a/mm/mmap.c
- +++ b/mm/mmap.c
- @@ -181,7 +181,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
- if (vma->vm_ops && vma->vm_ops->close)
- vma->vm_ops->close(vma);
- if (vma->vm_file)
- - fput(vma->vm_file);
- + vma_fput(vma);
- mpol_put(vma_policy(vma));
- vm_area_free(vma);
- return next;
- @@ -930,7 +930,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
- if (remove_next) {
- if (file) {
- uprobe_munmap(next, next->vm_start, next->vm_end);
- - fput(file);
- + vma_fput(vma);
- }
- if (next->anon_vma)
- anon_vma_merge(vma, next);
- @@ -1846,8 +1846,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
- return addr;
-
- unmap_and_free_vma:
- + vma_fput(vma);
- vma->vm_file = NULL;
- - fput(file);
-
- /* Undo any partial mapping done by a device driver. */
- unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);
- @@ -2679,7 +2679,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
- goto out_free_mpol;
-
- if (new->vm_file)
- - get_file(new->vm_file);
- + vma_get_file(new);
-
- if (new->vm_ops && new->vm_ops->open)
- new->vm_ops->open(new);
- @@ -2698,7 +2698,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
- if (new->vm_ops && new->vm_ops->close)
- new->vm_ops->close(new);
- if (new->vm_file)
- - fput(new->vm_file);
- + vma_fput(new);
- unlink_anon_vmas(new);
- out_free_mpol:
- mpol_put(vma_policy(new));
- @@ -2888,7 +2888,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
- struct vm_area_struct *vma;
- unsigned long populate = 0;
- unsigned long ret = -EINVAL;
- - struct file *file;
- + struct file *file, *prfile;
-
- pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n",
- current->comm, current->pid);
- @@ -2963,10 +2963,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
- }
- }
-
- - file = get_file(vma->vm_file);
- + vma_get_file(vma);
- + file = vma->vm_file;
- + prfile = vma->vm_prfile;
- ret = do_mmap_pgoff(vma->vm_file, start, size,
- prot, flags, pgoff, &populate, NULL);
- + if (!IS_ERR_VALUE(ret) && file && prfile) {
- + struct vm_area_struct *new_vma;
- +
- + new_vma = find_vma(mm, ret);
- + if (!new_vma->vm_prfile)
- + new_vma->vm_prfile = prfile;
- + if (new_vma != vma)
- + get_file(prfile);
- + }
- + /*
- + * two fput()s instead of vma_fput(vma),
- + * coz vma may not be available anymore.
- + */
- fput(file);
- + if (prfile)
- + fput(prfile);
- out:
- up_write(&mm->mmap_sem);
- if (populate)
- @@ -3256,7 +3273,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
- if (anon_vma_clone(new_vma, vma))
- goto out_free_mempol;
- if (new_vma->vm_file)
- - get_file(new_vma->vm_file);
- + vma_get_file(new_vma);
- if (new_vma->vm_ops && new_vma->vm_ops->open)
- new_vma->vm_ops->open(new_vma);
- vma_link(mm, new_vma, prev, rb_link, rb_parent);
- diff --git a/mm/nommu.c b/mm/nommu.c
- index 749276beb109..c7957f06fbc4 100644
- --- a/mm/nommu.c
- +++ b/mm/nommu.c
- @@ -625,7 +625,7 @@ static void __put_nommu_region(struct vm_region *region)
- up_write(&nommu_region_sem);
-
- if (region->vm_file)
- - fput(region->vm_file);
- + vmr_fput(region);
-
- /* IO memory and memory shared directly out of the pagecache
- * from ramfs/tmpfs mustn't be released here */
- @@ -763,7 +763,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma)
- if (vma->vm_ops && vma->vm_ops->close)
- vma->vm_ops->close(vma);
- if (vma->vm_file)
- - fput(vma->vm_file);
- + vma_fput(vma);
- put_nommu_region(vma->vm_region);
- vm_area_free(vma);
- }
- @@ -1286,7 +1286,7 @@ unsigned long do_mmap(struct file *file,
- goto error_just_free;
- }
- }
- - fput(region->vm_file);
- + vmr_fput(region);
- kmem_cache_free(vm_region_jar, region);
- region = pregion;
- result = start;
- @@ -1361,10 +1361,10 @@ unsigned long do_mmap(struct file *file,
- up_write(&nommu_region_sem);
- error:
- if (region->vm_file)
- - fput(region->vm_file);
- + vmr_fput(region);
- kmem_cache_free(vm_region_jar, region);
- if (vma->vm_file)
- - fput(vma->vm_file);
- + vma_fput(vma);
- vm_area_free(vma);
- return ret;
-
- diff --git a/mm/prfile.c b/mm/prfile.c
- new file mode 100644
- index 000000000000..024cdcfae1b1
- --- /dev/null
- +++ b/mm/prfile.c
- @@ -0,0 +1,86 @@
- +// SPDX-License-Identifier: GPL-2.0
- +/*
- + * Mainly for aufs which mmap(2) different file and wants to print different
- + * path in /proc/PID/maps.
- + * Call these functions via macros defined in linux/mm.h.
- + *
- + * See Documentation/filesystems/aufs/design/06mmap.txt
- + *
- + * Copyright (c) 2014-2019 Junjro R. Okajima
- + * Copyright (c) 2014 Ian Campbell
- + */
- +
- +#include <linux/mm.h>
- +#include <linux/file.h>
- +#include <linux/fs.h>
- +
- +/* #define PRFILE_TRACE */
- +static inline void prfile_trace(struct file *f, struct file *pr,
- + const char func[], int line, const char func2[])
- +{
- +#ifdef PRFILE_TRACE
- + if (pr)
- + pr_info("%s:%d: %s, %pD2\n", func, line, func2, f);
- +#endif
- +}
- +
- +void vma_do_file_update_time(struct vm_area_struct *vma, const char func[],
- + int line)
- +{
- + struct file *f = vma->vm_file, *pr = vma->vm_prfile;
- +
- + prfile_trace(f, pr, func, line, __func__);
- + file_update_time(f);
- + if (f && pr)
- + file_update_time(pr);
- +}
- +
- +struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[],
- + int line)
- +{
- + struct file *f = vma->vm_file, *pr = vma->vm_prfile;
- +
- + prfile_trace(f, pr, func, line, __func__);
- + return (f && pr) ? pr : f;
- +}
- +
- +void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line)
- +{
- + struct file *f = vma->vm_file, *pr = vma->vm_prfile;
- +
- + prfile_trace(f, pr, func, line, __func__);
- + get_file(f);
- + if (f && pr)
- + get_file(pr);
- +}
- +
- +void vma_do_fput(struct vm_area_struct *vma, const char func[], int line)
- +{
- + struct file *f = vma->vm_file, *pr = vma->vm_prfile;
- +
- + prfile_trace(f, pr, func, line, __func__);
- + fput(f);
- + if (f && pr)
- + fput(pr);
- +}
- +
- +#ifndef CONFIG_MMU
- +struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[],
- + int line)
- +{
- + struct file *f = region->vm_file, *pr = region->vm_prfile;
- +
- + prfile_trace(f, pr, func, line, __func__);
- + return (f && pr) ? pr : f;
- +}
- +
- +void vmr_do_fput(struct vm_region *region, const char func[], int line)
- +{
- + struct file *f = region->vm_file, *pr = region->vm_prfile;
- +
- + prfile_trace(f, pr, func, line, __func__);
- + fput(f);
- + if (f && pr)
- + fput(pr);
- +}
- +#endif /* !CONFIG_MMU */
|