aufs4-mmap.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. SPDX-License-Identifier: GPL-2.0
  2. aufs4.19 mmap patch
  3. diff --git a/fs/proc/base.c b/fs/proc/base.c
  4. index 7e9f07bf..3ab5901 100644
  5. --- a/fs/proc/base.c
  6. +++ b/fs/proc/base.c
  7. @@ -2016,7 +2016,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
  8. down_read(&mm->mmap_sem);
  9. vma = find_exact_vma(mm, vm_start, vm_end);
  10. if (vma && vma->vm_file) {
  11. - *path = vma->vm_file->f_path;
  12. + *path = vma_pr_or_file(vma)->f_path;
  13. path_get(path);
  14. rc = 0;
  15. }
  16. diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
  17. index 3b63be6..fb9913b 100644
  18. --- a/fs/proc/nommu.c
  19. +++ b/fs/proc/nommu.c
  20. @@ -45,7 +45,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region)
  21. file = region->vm_file;
  22. if (file) {
  23. - struct inode *inode = file_inode(region->vm_file);
  24. + struct inode *inode;
  25. +
  26. + file = vmr_pr_or_file(region);
  27. + inode = file_inode(file);
  28. dev = inode->i_sb->s_dev;
  29. ino = inode->i_ino;
  30. }
  31. diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
  32. index 5ea1d64..7865a470 100644
  33. --- a/fs/proc/task_mmu.c
  34. +++ b/fs/proc/task_mmu.c
  35. @@ -305,7 +305,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
  36. const char *name = NULL;
  37. if (file) {
  38. - struct inode *inode = file_inode(vma->vm_file);
  39. + struct inode *inode;
  40. +
  41. + file = vma_pr_or_file(vma);
  42. + inode = file_inode(file);
  43. dev = inode->i_sb->s_dev;
  44. ino = inode->i_ino;
  45. pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
  46. @@ -1727,7 +1730,7 @@ static int show_numa_map(struct seq_file *m, void *v)
  47. struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
  48. struct vm_area_struct *vma = v;
  49. struct numa_maps *md = &numa_priv->md;
  50. - struct file *file = vma->vm_file;
  51. + struct file *file = vma_pr_or_file(vma);
  52. struct mm_struct *mm = vma->vm_mm;
  53. struct mm_walk walk = {
  54. .hugetlb_entry = gather_hugetlb_stats,
  55. diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
  56. index 0b63d68..400d1c5 100644
  57. --- a/fs/proc/task_nommu.c
  58. +++ b/fs/proc/task_nommu.c
  59. @@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
  60. file = vma->vm_file;
  61. if (file) {
  62. - struct inode *inode = file_inode(vma->vm_file);
  63. + struct inode *inode;
  64. +
  65. + file = vma_pr_or_file(vma);
  66. + inode = file_inode(file);
  67. dev = inode->i_sb->s_dev;
  68. ino = inode->i_ino;
  69. pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
  70. diff --git a/include/linux/mm.h b/include/linux/mm.h
  71. index 0416a72..4a298a9 100644
  72. --- a/include/linux/mm.h
  73. +++ b/include/linux/mm.h
  74. @@ -1440,6 +1440,28 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
  75. unmap_mapping_range(mapping, holebegin, holelen, 0);
  76. }
  77. +extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int);
  78. +extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[],
  79. + int);
  80. +extern void vma_do_get_file(struct vm_area_struct *, const char[], int);
  81. +extern void vma_do_fput(struct vm_area_struct *, const char[], int);
  82. +
  83. +#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \
  84. + __LINE__)
  85. +#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \
  86. + __LINE__)
  87. +#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__)
  88. +#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__)
  89. +
  90. +#ifndef CONFIG_MMU
  91. +extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int);
  92. +extern void vmr_do_fput(struct vm_region *, const char[], int);
  93. +
  94. +#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \
  95. + __LINE__)
  96. +#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__)
  97. +#endif /* !CONFIG_MMU */
  98. +
  99. extern int access_process_vm(struct task_struct *tsk, unsigned long addr,
  100. void *buf, int len, unsigned int gup_flags);
  101. extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
  102. diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
  103. index 5ed8f62..0122975 100644
  104. --- a/include/linux/mm_types.h
  105. +++ b/include/linux/mm_types.h
  106. @@ -239,6 +239,7 @@ struct vm_region {
  107. unsigned long vm_top; /* region allocated to here */
  108. unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */
  109. struct file *vm_file; /* the backing file or NULL */
  110. + struct file *vm_prfile; /* the virtual backing file or NULL */
  111. int vm_usage; /* region usage count (access under nommu_region_sem) */
  112. bool vm_icache_flushed : 1; /* true if the icache has been flushed for
  113. @@ -313,6 +314,7 @@ struct vm_area_struct {
  114. unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
  115. units */
  116. struct file * vm_file; /* File we map to (can be NULL). */
  117. + struct file *vm_prfile; /* shadow of vm_file */
  118. void * vm_private_data; /* was vm_pte (shared mem) */
  119. atomic_long_t swap_readahead_info;
  120. diff --git a/kernel/fork.c b/kernel/fork.c
  121. index f0b5847..fa562c3 100644
  122. --- a/kernel/fork.c
  123. +++ b/kernel/fork.c
  124. @@ -505,7 +505,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
  125. struct inode *inode = file_inode(file);
  126. struct address_space *mapping = file->f_mapping;
  127. - get_file(file);
  128. + vma_get_file(tmp);
  129. if (tmp->vm_flags & VM_DENYWRITE)
  130. atomic_dec(&inode->i_writecount);
  131. i_mmap_lock_write(mapping);
  132. diff --git a/mm/Makefile b/mm/Makefile
  133. index 26ef77a..b2869af 100644
  134. --- a/mm/Makefile
  135. +++ b/mm/Makefile
  136. @@ -39,7 +39,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \
  137. mm_init.o mmu_context.o percpu.o slab_common.o \
  138. compaction.o vmacache.o \
  139. interval_tree.o list_lru.o workingset.o \
  140. - debug.o $(mmu-y)
  141. + prfile.o debug.o $(mmu-y)
  142. obj-y += init-mm.o
  143. diff --git a/mm/filemap.c b/mm/filemap.c
  144. index 52517f2..250f675 100644
  145. --- a/mm/filemap.c
  146. +++ b/mm/filemap.c
  147. @@ -2700,7 +2700,7 @@ vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf)
  148. vm_fault_t ret = VM_FAULT_LOCKED;
  149. sb_start_pagefault(inode->i_sb);
  150. - file_update_time(vmf->vma->vm_file);
  151. + vma_file_update_time(vmf->vma);
  152. lock_page(page);
  153. if (page->mapping != inode->i_mapping) {
  154. unlock_page(page);
  155. diff --git a/mm/mmap.c b/mm/mmap.c
  156. index f7cd9cb..515e88a 100644
  157. --- a/mm/mmap.c
  158. +++ b/mm/mmap.c
  159. @@ -180,7 +180,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
  160. if (vma->vm_ops && vma->vm_ops->close)
  161. vma->vm_ops->close(vma);
  162. if (vma->vm_file)
  163. - fput(vma->vm_file);
  164. + vma_fput(vma);
  165. mpol_put(vma_policy(vma));
  166. vm_area_free(vma);
  167. return next;
  168. @@ -905,7 +905,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
  169. if (remove_next) {
  170. if (file) {
  171. uprobe_munmap(next, next->vm_start, next->vm_end);
  172. - fput(file);
  173. + vma_fput(vma);
  174. }
  175. if (next->anon_vma)
  176. anon_vma_merge(vma, next);
  177. @@ -1821,8 +1821,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
  178. return addr;
  179. unmap_and_free_vma:
  180. + vma_fput(vma);
  181. vma->vm_file = NULL;
  182. - fput(file);
  183. /* Undo any partial mapping done by a device driver. */
  184. unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);
  185. @@ -2641,7 +2641,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
  186. goto out_free_mpol;
  187. if (new->vm_file)
  188. - get_file(new->vm_file);
  189. + vma_get_file(new);
  190. if (new->vm_ops && new->vm_ops->open)
  191. new->vm_ops->open(new);
  192. @@ -2660,7 +2660,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
  193. if (new->vm_ops && new->vm_ops->close)
  194. new->vm_ops->close(new);
  195. if (new->vm_file)
  196. - fput(new->vm_file);
  197. + vma_fput(new);
  198. unlink_anon_vmas(new);
  199. out_free_mpol:
  200. mpol_put(vma_policy(new));
  201. @@ -2822,7 +2822,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
  202. struct vm_area_struct *vma;
  203. unsigned long populate = 0;
  204. unsigned long ret = -EINVAL;
  205. - struct file *file;
  206. + struct file *file, *prfile;
  207. pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n",
  208. current->comm, current->pid);
  209. @@ -2897,10 +2897,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
  210. }
  211. }
  212. - file = get_file(vma->vm_file);
  213. + vma_get_file(vma);
  214. + file = vma->vm_file;
  215. + prfile = vma->vm_prfile;
  216. ret = do_mmap_pgoff(vma->vm_file, start, size,
  217. prot, flags, pgoff, &populate, NULL);
  218. + if (!IS_ERR_VALUE(ret) && file && prfile) {
  219. + struct vm_area_struct *new_vma;
  220. +
  221. + new_vma = find_vma(mm, ret);
  222. + if (!new_vma->vm_prfile)
  223. + new_vma->vm_prfile = prfile;
  224. + if (new_vma != vma)
  225. + get_file(prfile);
  226. + }
  227. + /*
  228. + * two fput()s instead of vma_fput(vma),
  229. + * coz vma may not be available anymore.
  230. + */
  231. fput(file);
  232. + if (prfile)
  233. + fput(prfile);
  234. out:
  235. up_write(&mm->mmap_sem);
  236. if (populate)
  237. @@ -3206,7 +3223,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
  238. if (anon_vma_clone(new_vma, vma))
  239. goto out_free_mempol;
  240. if (new_vma->vm_file)
  241. - get_file(new_vma->vm_file);
  242. + vma_get_file(new_vma);
  243. if (new_vma->vm_ops && new_vma->vm_ops->open)
  244. new_vma->vm_ops->open(new_vma);
  245. vma_link(mm, new_vma, prev, rb_link, rb_parent);
  246. diff --git a/mm/nommu.c b/mm/nommu.c
  247. index e4aac33..b27b200 100644
  248. --- a/mm/nommu.c
  249. +++ b/mm/nommu.c
  250. @@ -625,7 +625,7 @@ static void __put_nommu_region(struct vm_region *region)
  251. up_write(&nommu_region_sem);
  252. if (region->vm_file)
  253. - fput(region->vm_file);
  254. + vmr_fput(region);
  255. /* IO memory and memory shared directly out of the pagecache
  256. * from ramfs/tmpfs mustn't be released here */
  257. @@ -763,7 +763,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma)
  258. if (vma->vm_ops && vma->vm_ops->close)
  259. vma->vm_ops->close(vma);
  260. if (vma->vm_file)
  261. - fput(vma->vm_file);
  262. + vma_fput(vma);
  263. put_nommu_region(vma->vm_region);
  264. vm_area_free(vma);
  265. }
  266. @@ -1286,7 +1286,7 @@ unsigned long do_mmap(struct file *file,
  267. goto error_just_free;
  268. }
  269. }
  270. - fput(region->vm_file);
  271. + vmr_fput(region);
  272. kmem_cache_free(vm_region_jar, region);
  273. region = pregion;
  274. result = start;
  275. @@ -1361,7 +1361,7 @@ unsigned long do_mmap(struct file *file,
  276. up_write(&nommu_region_sem);
  277. error:
  278. if (region->vm_file)
  279. - fput(region->vm_file);
  280. + vmr_fput(region);
  281. kmem_cache_free(vm_region_jar, region);
  282. if (vma->vm_file)
  283. fput(vma->vm_file);
  284. diff --git a/mm/prfile.c b/mm/prfile.c
  285. new file mode 100644
  286. index 0000000..a27ac36
  287. --- /dev/null
  288. +++ b/mm/prfile.c
  289. @@ -0,0 +1,86 @@
  290. +// SPDX-License-Identifier: GPL-2.0
  291. +/*
  292. + * Mainly for aufs which mmap(2) different file and wants to print different
  293. + * path in /proc/PID/maps.
  294. + * Call these functions via macros defined in linux/mm.h.
  295. + *
  296. + * See Documentation/filesystems/aufs/design/06mmap.txt
  297. + *
  298. + * Copyright (c) 2014-2018 Junjro R. Okajima
  299. + * Copyright (c) 2014 Ian Campbell
  300. + */
  301. +
  302. +#include <linux/mm.h>
  303. +#include <linux/file.h>
  304. +#include <linux/fs.h>
  305. +
  306. +/* #define PRFILE_TRACE */
  307. +static inline void prfile_trace(struct file *f, struct file *pr,
  308. + const char func[], int line, const char func2[])
  309. +{
  310. +#ifdef PRFILE_TRACE
  311. + if (pr)
  312. + pr_info("%s:%d: %s, %pD2\n", func, line, func2, f);
  313. +#endif
  314. +}
  315. +
  316. +void vma_do_file_update_time(struct vm_area_struct *vma, const char func[],
  317. + int line)
  318. +{
  319. + struct file *f = vma->vm_file, *pr = vma->vm_prfile;
  320. +
  321. + prfile_trace(f, pr, func, line, __func__);
  322. + file_update_time(f);
  323. + if (f && pr)
  324. + file_update_time(pr);
  325. +}
  326. +
  327. +struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[],
  328. + int line)
  329. +{
  330. + struct file *f = vma->vm_file, *pr = vma->vm_prfile;
  331. +
  332. + prfile_trace(f, pr, func, line, __func__);
  333. + return (f && pr) ? pr : f;
  334. +}
  335. +
  336. +void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line)
  337. +{
  338. + struct file *f = vma->vm_file, *pr = vma->vm_prfile;
  339. +
  340. + prfile_trace(f, pr, func, line, __func__);
  341. + get_file(f);
  342. + if (f && pr)
  343. + get_file(pr);
  344. +}
  345. +
  346. +void vma_do_fput(struct vm_area_struct *vma, const char func[], int line)
  347. +{
  348. + struct file *f = vma->vm_file, *pr = vma->vm_prfile;
  349. +
  350. + prfile_trace(f, pr, func, line, __func__);
  351. + fput(f);
  352. + if (f && pr)
  353. + fput(pr);
  354. +}
  355. +
  356. +#ifndef CONFIG_MMU
  357. +struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[],
  358. + int line)
  359. +{
  360. + struct file *f = region->vm_file, *pr = region->vm_prfile;
  361. +
  362. + prfile_trace(f, pr, func, line, __func__);
  363. + return (f && pr) ? pr : f;
  364. +}
  365. +
  366. +void vmr_do_fput(struct vm_region *region, const char func[], int line)
  367. +{
  368. + struct file *f = region->vm_file, *pr = region->vm_prfile;
  369. +
  370. + prfile_trace(f, pr, func, line, __func__);
  371. + fput(f);
  372. + if (f && pr)
  373. + fput(pr);
  374. +}
  375. +#endif /* !CONFIG_MMU */