Message ID | 20210122212926.3457593-8-axelrasmussen@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | userfaultfd: add minor fault handling | expand |
Hi Axel, Thank you for the patch! Yet something to improve: [auto build test ERROR on arm64/for-next/core] [also build test ERROR on powerpc/next s390/features tip/perf/core linus/master v5.11-rc5 next-20210122] [cannot apply to hp-parisc/for-next hnaz-linux-mm/master ia64/next sparc-next/master sparc/master] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Axel-Rasmussen/userfaultfd-add-minor-fault-handling/20210125-104035 base: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core config: powerpc-randconfig-r006-20210125 (attached as .config) compiler: powerpc-linux-gcc (GCC) 9.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/b8fb53c3a341b9b853aa3286286c807088311dbd git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Axel-Rasmussen/userfaultfd-add-minor-fault-handling/20210125-104035 git checkout b8fb53c3a341b9b853aa3286286c807088311dbd # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=powerpc If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All error/warnings (new ones prefixed by >>): In file included from fs/proc/task_mmu.c:4: >> include/linux/hugetlb.h:142:10: warning: 'enum mcopy_atomic_mode' declared inside parameter list will not be visible outside of this definition or declaration 142 | enum mcopy_atomic_mode mode, | ^~~~~~~~~~~~~~~~~ -- In file included from fs/proc/meminfo.c:6: >> include/linux/hugetlb.h:142:10: warning: 'enum mcopy_atomic_mode' declared inside parameter list will not be visible outside of this definition or declaration 142 | enum mcopy_atomic_mode mode, | ^~~~~~~~~~~~~~~~~ fs/proc/meminfo.c:22:28: warning: no previous prototype for 'arch_report_meminfo' [-Wmissing-prototypes] 22 | void __attribute__((weak)) arch_report_meminfo(struct seq_file *m) | ^~~~~~~~~~~~~~~~~~~ -- In file included from kernel/events/core.c:31: >> include/linux/hugetlb.h:142:10: warning: 'enum mcopy_atomic_mode' declared inside parameter list will not be visible outside of this definition or declaration 142 | enum mcopy_atomic_mode mode, | ^~~~~~~~~~~~~~~~~ kernel/events/core.c:6535:6: warning: no previous prototype for 'perf_pmu_snapshot_aux' [-Wmissing-prototypes] 6535 | long perf_pmu_snapshot_aux(struct perf_buffer *rb, | ^~~~~~~~~~~~~~~~~~~~~ -- In file included from kernel/fork.c:51: >> include/linux/hugetlb.h:142:10: warning: 'enum mcopy_atomic_mode' declared inside parameter list will not be visible outside of this definition or declaration 142 | enum mcopy_atomic_mode mode, | ^~~~~~~~~~~~~~~~~ kernel/fork.c:161:13: warning: no previous prototype for 'arch_release_task_struct' [-Wmissing-prototypes] 161 | void __weak arch_release_task_struct(struct task_struct *tsk) | ^~~~~~~~~~~~~~~~~~~~~~~~ kernel/fork.c:746:20: warning: no previous prototype for 'arch_task_cache_init' [-Wmissing-prototypes] 746 | void __init __weak arch_task_cache_init(void) { } | ^~~~~~~~~~~~~~~~~~~~ -- In file included from arch/powerpc/mm/pgtable.c:25: >> include/linux/hugetlb.h:142:10: warning: 'enum mcopy_atomic_mode' declared inside parameter list will not be visible outside of this definition or declaration 142 | enum mcopy_atomic_mode mode, | ^~~~~~~~~~~~~~~~~ arch/powerpc/mm/pgtable.c:337:8: warning: no previous prototype for '__find_linux_pte' [-Wmissing-prototypes] 337 | pte_t *__find_linux_pte(pgd_t *pgdir, unsigned long ea, | ^~~~~~~~~~~~~~~~ -- In file included from include/linux/migrate.h:8, from mm/page_alloc.c:61: >> include/linux/hugetlb.h:142:10: warning: 'enum mcopy_atomic_mode' declared inside parameter list will not be visible outside of this definition or declaration 142 | enum mcopy_atomic_mode mode, | ^~~~~~~~~~~~~~~~~ mm/page_alloc.c:3597:15: warning: no previous prototype for 'should_fail_alloc_page' [-Wmissing-prototypes] 3597 | noinline bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) | ^~~~~~~~~~~~~~~~~~~~~~ mm/page_alloc.c:6258:23: warning: no previous prototype for 'memmap_init' [-Wmissing-prototypes] 6258 | void __meminit __weak memmap_init(unsigned long size, int nid, | ^~~~~~~~~~~ -- In file included from mm/hugetlb.c:39: >> include/linux/hugetlb.h:142:10: warning: 'enum mcopy_atomic_mode' declared inside parameter list will not be visible outside of this definition or declaration 142 | enum mcopy_atomic_mode mode, | ^~~~~~~~~~~~~~~~~ >> mm/hugetlb.c:4659:13: warning: 'enum mcopy_atomic_mode' declared inside parameter list will not be visible outside of this definition or declaration 4659 | enum mcopy_atomic_mode mode, | ^~~~~~~~~~~~~~~~~ >> mm/hugetlb.c:4659:31: error: parameter 6 ('mode') has incomplete type 4659 | enum mcopy_atomic_mode mode, | ~~~~~~~~~~~~~~~~~~~~~~~^~~~ mm/hugetlb.c: In function 'hugetlb_mcopy_atomic_pte': >> mm/hugetlb.c:4675:25: error: 'MCOPY_ATOMIC_CONTINUE' undeclared (first use in this function) 4675 | if (!*pagep && mode != MCOPY_ATOMIC_CONTINUE) { | ^~~~~~~~~~~~~~~~~~~~~ mm/hugetlb.c:4675:25: note: each undeclared identifier is reported only once for each function it appears in -- In file included from mm/util.c:16: >> include/linux/hugetlb.h:142:10: warning: 'enum mcopy_atomic_mode' declared inside parameter list will not be visible outside of this definition or declaration 142 | enum mcopy_atomic_mode mode, | ^~~~~~~~~~~~~~~~~ mm/util.c: In function 'page_mapping': mm/util.c:700:15: warning: variable 'entry' set but not used [-Wunused-but-set-variable] 700 | swp_entry_t entry; | ^~~~~ -- In file included from include/linux/migrate.h:8, from mm/compaction.c:13: >> include/linux/hugetlb.h:142:10: warning: 'enum mcopy_atomic_mode' declared inside parameter list will not be visible outside of this definition or declaration 142 | enum mcopy_atomic_mode mode, | ^~~~~~~~~~~~~~~~~ mm/compaction.c:56:27: warning: 'HPAGE_FRAG_CHECK_INTERVAL_MSEC' defined but not used [-Wunused-const-variable=] 56 | static const unsigned int HPAGE_FRAG_CHECK_INTERVAL_MSEC = 500; | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- In file included from include/linux/migrate.h:8, from kernel/sched/sched.h:53, from kernel/sched/fair.c:23: >> include/linux/hugetlb.h:142:10: warning: 'enum mcopy_atomic_mode' declared inside parameter list will not be visible outside of this definition or declaration 142 | enum mcopy_atomic_mode mode, | ^~~~~~~~~~~~~~~~~ kernel/sched/fair.c:5388:6: warning: no previous prototype for 'init_cfs_bandwidth' [-Wmissing-prototypes] 5388 | void init_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {} | ^~~~~~~~~~~~~~~~~~ kernel/sched/fair.c:11195:6: warning: no previous prototype for 'free_fair_sched_group' [-Wmissing-prototypes] 11195 | void free_fair_sched_group(struct task_group *tg) { } | ^~~~~~~~~~~~~~~~~~~~~ kernel/sched/fair.c:11197:5: warning: no previous prototype for 'alloc_fair_sched_group' [-Wmissing-prototypes] 11197 | int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent) | ^~~~~~~~~~~~~~~~~~~~~~ kernel/sched/fair.c:11202:6: warning: no previous prototype for 'online_fair_sched_group' [-Wmissing-prototypes] 11202 | void online_fair_sched_group(struct task_group *tg) { } | ^~~~~~~~~~~~~~~~~~~~~~~ kernel/sched/fair.c:11204:6: warning: no previous prototype for 'unregister_fair_sched_group' [-Wmissing-prototypes] 11204 | void unregister_fair_sched_group(struct task_group *tg) { } | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ -- In file included from include/linux/migrate.h:8, from kernel/sched/sched.h:53, from kernel/sched/rt.c:6: >> include/linux/hugetlb.h:142:10: warning: 'enum mcopy_atomic_mode' declared inside parameter list will not be visible outside of this definition or declaration 142 | enum mcopy_atomic_mode mode, | ^~~~~~~~~~~~~~~~~ kernel/sched/rt.c:253:6: warning: no previous prototype for 'free_rt_sched_group' [-Wmissing-prototypes] 253 | void free_rt_sched_group(struct task_group *tg) { } | ^~~~~~~~~~~~~~~~~~~ kernel/sched/rt.c:255:5: warning: no previous prototype for 'alloc_rt_sched_group' [-Wmissing-prototypes] 255 | int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent) | ^~~~~~~~~~~~~~~~~~~~ kernel/sched/rt.c:669:6: warning: no previous prototype for 'sched_rt_bandwidth_account' [-Wmissing-prototypes] 669 | bool sched_rt_bandwidth_account(struct rt_rq *rt_rq) | ^~~~~~~~~~~~~~~~~~~~~~~~~~ .. vim +4659 mm/hugetlb.c 4649 4650 /* 4651 * Used by userfaultfd UFFDIO_COPY. Based on mcopy_atomic_pte with 4652 * modifications for huge pages. 4653 */ 4654 int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, 4655 pte_t *dst_pte, 4656 struct vm_area_struct *dst_vma, 4657 unsigned long dst_addr, 4658 unsigned long src_addr, > 4659 enum mcopy_atomic_mode mode, 4660 struct page **pagep) 4661 { 4662 struct address_space *mapping; 4663 pgoff_t idx; 4664 unsigned long size; 4665 int vm_shared = dst_vma->vm_flags & VM_SHARED; 4666 struct hstate *h = hstate_vma(dst_vma); 4667 pte_t _dst_pte; 4668 spinlock_t *ptl; 4669 int ret; 4670 struct page *page; 4671 4672 mapping = dst_vma->vm_file->f_mapping; 4673 idx = vma_hugecache_offset(h, dst_vma, dst_addr); 4674 > 4675 if (!*pagep && mode != MCOPY_ATOMIC_CONTINUE) { 4676 ret = -ENOMEM; 4677 page = alloc_huge_page(dst_vma, dst_addr, 0); 4678 if (IS_ERR(page)) 4679 goto out; 4680 4681 ret = copy_huge_page_from_user(page, 4682 (const void __user *) src_addr, 4683 pages_per_huge_page(h), false); 4684 4685 /* fallback to copy_from_user outside mmap_lock */ 4686 if (unlikely(ret)) { 4687 ret = -ENOENT; 4688 *pagep = page; 4689 /* don't free the page */ 4690 goto out; 4691 } 4692 } else if (mode == MCOPY_ATOMIC_CONTINUE) { 4693 ret = -EFAULT; 4694 page = find_lock_page(mapping, idx); 4695 *pagep = NULL; 4696 if (!page) 4697 goto out; 4698 } else { 4699 page = *pagep; 4700 *pagep = NULL; 4701 } 4702 4703 /* 4704 * The memory barrier inside __SetPageUptodate makes sure that 4705 * preceding stores to the page contents become visible before 4706 * the set_pte_at() write. 4707 */ 4708 __SetPageUptodate(page); 4709 4710 /* Add shared, newly allocated pages to the page cache. */ 4711 if (vm_shared && mode != MCOPY_ATOMIC_CONTINUE) { 4712 size = i_size_read(mapping->host) >> huge_page_shift(h); 4713 ret = -EFAULT; 4714 if (idx >= size) 4715 goto out_release_nounlock; 4716 4717 /* 4718 * Serialization between remove_inode_hugepages() and 4719 * huge_add_to_page_cache() below happens through the 4720 * hugetlb_fault_mutex_table that here must be hold by 4721 * the caller. 4722 */ 4723 ret = huge_add_to_page_cache(page, mapping, idx); 4724 if (ret) 4725 goto out_release_nounlock; 4726 } 4727 4728 ptl = huge_pte_lockptr(h, dst_mm, dst_pte); 4729 spin_lock(ptl); 4730 4731 /* 4732 * Recheck the i_size after holding PT lock to make sure not 4733 * to leave any page mapped (as page_mapped()) beyond the end 4734 * of the i_size (remove_inode_hugepages() is strict about 4735 * enforcing that). If we bail out here, we'll also leave a 4736 * page in the radix tree in the vm_shared case beyond the end 4737 * of the i_size, but remove_inode_hugepages() will take care 4738 * of it as soon as we drop the hugetlb_fault_mutex_table. 4739 */ 4740 size = i_size_read(mapping->host) >> huge_page_shift(h); 4741 ret = -EFAULT; 4742 if (idx >= size) 4743 goto out_release_unlock; 4744 4745 ret = -EEXIST; 4746 if (!huge_pte_none(huge_ptep_get(dst_pte))) 4747 goto out_release_unlock; 4748 4749 if (vm_shared) { 4750 page_dup_rmap(page, true); 4751 } else { 4752 ClearPagePrivate(page); 4753 hugepage_add_new_anon_rmap(page, dst_vma, dst_addr); 4754 } 4755 4756 _dst_pte = make_huge_pte(dst_vma, page, dst_vma->vm_flags & VM_WRITE); 4757 if (dst_vma->vm_flags & VM_WRITE) 4758 _dst_pte = huge_pte_mkdirty(_dst_pte); 4759 _dst_pte = pte_mkyoung(_dst_pte); 4760 4761 set_huge_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte); 4762 4763 (void)huge_ptep_set_access_flags(dst_vma, dst_addr, dst_pte, _dst_pte, 4764 dst_vma->vm_flags & VM_WRITE); 4765 hugetlb_count_add(pages_per_huge_page(h), dst_mm); 4766 4767 /* No need to invalidate - it was non-present before */ 4768 update_mmu_cache(dst_vma, dst_addr, dst_pte); 4769 4770 spin_unlock(ptl); 4771 if (mode != MCOPY_ATOMIC_CONTINUE) 4772 set_page_huge_active(page); 4773 if (vm_shared) 4774 unlock_page(page); 4775 ret = 0; 4776 out: 4777 return ret; 4778 out_release_unlock: 4779 spin_unlock(ptl); 4780 if (vm_shared) 4781 unlock_page(page); 4782 out_release_nounlock: 4783 put_page(page); 4784 goto out; 4785 } 4786 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Hi Axel, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on arm64/for-next/core] [also build test WARNING on powerpc/next s390/features tip/perf/core linus/master v5.11-rc5 next-20210122] [cannot apply to hp-parisc/for-next hnaz-linux-mm/master ia64/next sparc-next/master sparc/master] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Axel-Rasmussen/userfaultfd-add-minor-fault-handling/20210125-104035 base: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core config: x86_64-randconfig-a013-20210125 (attached as .config) compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 12d0753aca22896fda2cf76781b0ee0524d55065) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install x86_64 cross compiling tool for clang build # apt-get install binutils-x86-64-linux-gnu # https://github.com/0day-ci/linux/commit/b8fb53c3a341b9b853aa3286286c807088311dbd git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Axel-Rasmussen/userfaultfd-add-minor-fault-handling/20210125-104035 git checkout b8fb53c3a341b9b853aa3286286c807088311dbd # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): In file included from kernel/sched/core.c:13: In file included from kernel/sched/sched.h:53: In file included from include/linux/migrate.h:8: >> include/linux/hugetlb.h:142:10: warning: declaration of 'enum mcopy_atomic_mode' will not be visible outside of this function [-Wvisibility] enum mcopy_atomic_mode mode, ^ kernel/sched/core.c:2884:20: warning: unused function 'rq_has_pinned_tasks' [-Wunused-function] static inline bool rq_has_pinned_tasks(struct rq *rq) ^ kernel/sched/core.c:4687:20: warning: unused function 'sched_tick_start' [-Wunused-function] static inline void sched_tick_start(int cpu) { } ^ kernel/sched/core.c:4688:20: warning: unused function 'sched_tick_stop' [-Wunused-function] static inline void sched_tick_stop(int cpu) { } ^ 4 warnings generated. -- In file included from kernel/sched/loadavg.c:9: In file included from kernel/sched/sched.h:53: In file included from include/linux/migrate.h:8: >> include/linux/hugetlb.h:142:10: warning: declaration of 'enum mcopy_atomic_mode' will not be visible outside of this function [-Wvisibility] enum mcopy_atomic_mode mode, ^ 1 warning generated. -- In file included from kernel/sched/fair.c:23: In file included from kernel/sched/sched.h:53: In file included from include/linux/migrate.h:8: >> include/linux/hugetlb.h:142:10: warning: declaration of 'enum mcopy_atomic_mode' will not be visible outside of this function [-Wvisibility] enum mcopy_atomic_mode mode, ^ kernel/sched/fair.c:5388:6: warning: no previous prototype for function 'init_cfs_bandwidth' [-Wmissing-prototypes] void init_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {} ^ kernel/sched/fair.c:5388:1: note: declare 'static' if the function is not intended to be used outside of this translation unit void init_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {} ^ static kernel/sched/fair.c:11195:6: warning: no previous prototype for function 'free_fair_sched_group' [-Wmissing-prototypes] void free_fair_sched_group(struct task_group *tg) { } ^ kernel/sched/fair.c:11195:1: note: declare 'static' if the function is not intended to be used outside of this translation unit void free_fair_sched_group(struct task_group *tg) { } ^ static kernel/sched/fair.c:11197:5: warning: no previous prototype for function 'alloc_fair_sched_group' [-Wmissing-prototypes] int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent) ^ kernel/sched/fair.c:11197:1: note: declare 'static' if the function is not intended to be used outside of this translation unit int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent) ^ static kernel/sched/fair.c:11202:6: warning: no previous prototype for function 'online_fair_sched_group' [-Wmissing-prototypes] void online_fair_sched_group(struct task_group *tg) { } ^ kernel/sched/fair.c:11202:1: note: declare 'static' if the function is not intended to be used outside of this translation unit void online_fair_sched_group(struct task_group *tg) { } ^ static kernel/sched/fair.c:11204:6: warning: no previous prototype for function 'unregister_fair_sched_group' [-Wmissing-prototypes] void unregister_fair_sched_group(struct task_group *tg) { } ^ kernel/sched/fair.c:11204:1: note: declare 'static' if the function is not intended to be used outside of this translation unit void unregister_fair_sched_group(struct task_group *tg) { } ^ static kernel/sched/fair.c:486:20: warning: unused function 'list_del_leaf_cfs_rq' [-Wunused-function] static inline void list_del_leaf_cfs_rq(struct cfs_rq *cfs_rq) ^ kernel/sched/fair.c:2985:20: warning: unused function 'account_numa_enqueue' [-Wunused-function] static inline void account_numa_enqueue(struct rq *rq, struct task_struct *p) ^ kernel/sched/fair.c:2989:20: warning: unused function 'account_numa_dequeue' [-Wunused-function] static inline void account_numa_dequeue(struct rq *rq, struct task_struct *p) ^ kernel/sched/fair.c:2993:20: warning: unused function 'update_scan_period' [-Wunused-function] static inline void update_scan_period(struct task_struct *p, int new_cpu) ^ kernel/sched/fair.c:4083:20: warning: unused function 'remove_entity_load_avg' [-Wunused-function] static inline void remove_entity_load_avg(struct sched_entity *se) {} ^ kernel/sched/fair.c:5369:20: warning: unused function 'sync_throttle' [-Wunused-function] static inline void sync_throttle(struct task_group *tg, int cpu) {} ^ kernel/sched/fair.c:5382:19: warning: unused function 'throttled_lb_pair' [-Wunused-function] static inline int throttled_lb_pair(struct task_group *tg, ^ kernel/sched/fair.c:5394:37: warning: unused function 'tg_cfs_bandwidth' [-Wunused-function] static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg) ^ kernel/sched/fair.c:5398:20: warning: unused function 'destroy_cfs_bandwidth' [-Wunused-function] static inline void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {} ^ kernel/sched/fair.c:5399:20: warning: unused function 'update_runtime_enabled' [-Wunused-function] static inline void update_runtime_enabled(struct rq *rq) {} ^ kernel/sched/fair.c:5400:20: warning: unused function 'unthrottle_offline_cfs_rqs' [-Wunused-function] static inline void unthrottle_offline_cfs_rqs(struct rq *rq) {} ^ 17 warnings generated. -- In file included from kernel/sched/rt.c:6: In file included from kernel/sched/sched.h:53: In file included from include/linux/migrate.h:8: >> include/linux/hugetlb.h:142:10: warning: declaration of 'enum mcopy_atomic_mode' will not be visible outside of this function [-Wvisibility] enum mcopy_atomic_mode mode, ^ kernel/sched/rt.c:253:6: warning: no previous prototype for function 'free_rt_sched_group' [-Wmissing-prototypes] void free_rt_sched_group(struct task_group *tg) { } ^ kernel/sched/rt.c:253:1: note: declare 'static' if the function is not intended to be used outside of this translation unit void free_rt_sched_group(struct task_group *tg) { } ^ static kernel/sched/rt.c:255:5: warning: no previous prototype for function 'alloc_rt_sched_group' [-Wmissing-prototypes] int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent) ^ kernel/sched/rt.c:255:1: note: declare 'static' if the function is not intended to be used outside of this translation unit int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent) ^ static kernel/sched/rt.c:669:6: warning: no previous prototype for function 'sched_rt_bandwidth_account' [-Wmissing-prototypes] bool sched_rt_bandwidth_account(struct rt_rq *rt_rq) ^ kernel/sched/rt.c:669:1: note: declare 'static' if the function is not intended to be used outside of this translation unit bool sched_rt_bandwidth_account(struct rt_rq *rt_rq) ^ static kernel/sched/rt.c:421:20: warning: unused function 'need_pull_rt_task' [-Wunused-function] static inline bool need_pull_rt_task(struct rq *rq, struct task_struct *prev) ^ kernel/sched/rt.c:426:20: warning: unused function 'pull_rt_task' [-Wunused-function] static inline void pull_rt_task(struct rq *this_rq) ^ kernel/sched/rt.c:476:20: warning: unused function 'rt_task_fits_capacity' [-Wunused-function] static inline bool rt_task_fits_capacity(struct task_struct *p, int cpu) ^ kernel/sched/rt.c:1113:6: warning: unused function 'inc_rt_prio_smp' [-Wunused-function] void inc_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio) {} ^ kernel/sched/rt.c:1115:6: warning: unused function 'dec_rt_prio_smp' [-Wunused-function] void dec_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio) {} ^ 9 warnings generated. -- In file included from kernel/sched/deadline.c:18: In file included from kernel/sched/sched.h:53: In file included from include/linux/migrate.h:8: >> include/linux/hugetlb.h:142:10: warning: declaration of 'enum mcopy_atomic_mode' will not be visible outside of this function [-Wvisibility] enum mcopy_atomic_mode mode, ^ kernel/sched/deadline.c:700:20: warning: unused function 'need_pull_dl_task' [-Wunused-function] static inline bool need_pull_dl_task(struct rq *rq, struct task_struct *prev) ^ kernel/sched/deadline.c:705:20: warning: unused function 'pull_dl_task' [-Wunused-function] static inline void pull_dl_task(struct rq *rq) ^ 3 warnings generated. -- In file included from mm/page_alloc.c:61: In file included from include/linux/migrate.h:8: >> include/linux/hugetlb.h:142:10: warning: declaration of 'enum mcopy_atomic_mode' will not be visible outside of this function [-Wvisibility] enum mcopy_atomic_mode mode, ^ mm/page_alloc.c:3597:15: warning: no previous prototype for function 'should_fail_alloc_page' [-Wmissing-prototypes] noinline bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) ^ mm/page_alloc.c:3597:10: note: declare 'static' if the function is not intended to be used outside of this translation unit noinline bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order) ^ static mm/page_alloc.c:6258:23: warning: no previous prototype for function 'memmap_init' [-Wmissing-prototypes] void __meminit __weak memmap_init(unsigned long size, int nid, ^ mm/page_alloc.c:6258:1: note: declare 'static' if the function is not intended to be used outside of this translation unit void __meminit __weak memmap_init(unsigned long size, int nid, ^ static 3 warnings generated. -- In file included from mm/hugetlb.c:39: >> include/linux/hugetlb.h:142:10: warning: declaration of 'enum mcopy_atomic_mode' will not be visible outside of this function [-Wvisibility] enum mcopy_atomic_mode mode, ^ >> mm/hugetlb.c:4659:13: warning: declaration of 'enum mcopy_atomic_mode' will not be visible outside of this function [-Wvisibility] enum mcopy_atomic_mode mode, ^ mm/hugetlb.c:4654:5: error: conflicting types for 'hugetlb_mcopy_atomic_pte' int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, ^ include/linux/hugetlb.h:138:5: note: previous declaration is here int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, pte_t *dst_pte, ^ mm/hugetlb.c:4659:31: error: variable has incomplete type 'enum mcopy_atomic_mode' enum mcopy_atomic_mode mode, ^ mm/hugetlb.c:4659:13: note: forward declaration of 'enum mcopy_atomic_mode' enum mcopy_atomic_mode mode, ^ mm/hugetlb.c:4675:25: error: use of undeclared identifier 'MCOPY_ATOMIC_CONTINUE' if (!*pagep && mode != MCOPY_ATOMIC_CONTINUE) { ^ mm/hugetlb.c:4692:21: error: use of undeclared identifier 'MCOPY_ATOMIC_CONTINUE' } else if (mode == MCOPY_ATOMIC_CONTINUE) { ^ mm/hugetlb.c:4711:27: error: use of undeclared identifier 'MCOPY_ATOMIC_CONTINUE' if (vm_shared && mode != MCOPY_ATOMIC_CONTINUE) { ^ mm/hugetlb.c:4771:14: error: use of undeclared identifier 'MCOPY_ATOMIC_CONTINUE' if (mode != MCOPY_ATOMIC_CONTINUE) ^ 2 warnings and 6 errors generated. -- In file included from mm/z3fold.c:33: In file included from include/linux/migrate.h:8: >> include/linux/hugetlb.h:142:10: warning: declaration of 'enum mcopy_atomic_mode' will not be visible outside of this function [-Wvisibility] enum mcopy_atomic_mode mode, ^ mm/z3fold.c:287:37: warning: unused function 'handle_to_z3fold_header' [-Wunused-function] static inline struct z3fold_header *handle_to_z3fold_header(unsigned long h) ^ 2 warnings generated. vim +142 include/linux/hugetlb.h 108 109 void reset_vma_resv_huge_pages(struct vm_area_struct *vma); 110 int hugetlb_sysctl_handler(struct ctl_table *, int, void *, size_t *, loff_t *); 111 int hugetlb_overcommit_handler(struct ctl_table *, int, void *, size_t *, 112 loff_t *); 113 int hugetlb_treat_movable_handler(struct ctl_table *, int, void *, size_t *, 114 loff_t *); 115 int hugetlb_mempolicy_sysctl_handler(struct ctl_table *, int, void *, size_t *, 116 loff_t *); 117 118 int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *); 119 long follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, 120 struct page **, struct vm_area_struct **, 121 unsigned long *, unsigned long *, long, unsigned int, 122 int *); 123 void unmap_hugepage_range(struct vm_area_struct *, 124 unsigned long, unsigned long, struct page *); 125 void __unmap_hugepage_range_final(struct mmu_gather *tlb, 126 struct vm_area_struct *vma, 127 unsigned long start, unsigned long end, 128 struct page *ref_page); 129 void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, 130 unsigned long start, unsigned long end, 131 struct page *ref_page); 132 void hugetlb_report_meminfo(struct seq_file *); 133 int hugetlb_report_node_meminfo(char *buf, int len, int nid); 134 void hugetlb_show_meminfo(void); 135 unsigned long hugetlb_total_pages(void); 136 vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, 137 unsigned long address, unsigned int flags); 138 int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, pte_t *dst_pte, 139 struct vm_area_struct *dst_vma, 140 unsigned long dst_addr, 141 unsigned long src_addr, > 142 enum mcopy_atomic_mode mode, 143 struct page **pagep); 144 int hugetlb_reserve_pages(struct inode *inode, long from, long to, 145 struct vm_area_struct *vma, 146 vm_flags_t vm_flags); 147 long hugetlb_unreserve_pages(struct inode *inode, long start, long end, 148 long freed); 149 bool isolate_huge_page(struct page *page, struct list_head *list); 150 void putback_active_hugepage(struct page *page); 151 void move_hugetlb_state(struct page *oldpage, struct page *newpage, int reason); 152 void free_huge_page(struct page *page); 153 void hugetlb_fix_reserve_counts(struct inode *inode); 154 extern struct mutex *hugetlb_fault_mutex_table; 155 u32 hugetlb_fault_mutex_hash(struct address_space *mapping, pgoff_t idx); 156 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Hi Axel, Thank you for the patch! Yet something to improve: [auto build test ERROR on arm64/for-next/core] [also build test ERROR on powerpc/next s390/features tip/perf/core linus/master v5.11-rc5 next-20210122] [cannot apply to hp-parisc/for-next hnaz-linux-mm/master ia64/next sparc-next/master sparc/master] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Axel-Rasmussen/userfaultfd-add-minor-fault-handling/20210125-104035 base: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core config: x86_64-randconfig-a013-20210125 (attached as .config) compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 12d0753aca22896fda2cf76781b0ee0524d55065) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install x86_64 cross compiling tool for clang build # apt-get install binutils-x86-64-linux-gnu # https://github.com/0day-ci/linux/commit/b8fb53c3a341b9b853aa3286286c807088311dbd git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Axel-Rasmussen/userfaultfd-add-minor-fault-handling/20210125-104035 git checkout b8fb53c3a341b9b853aa3286286c807088311dbd # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): In file included from mm/hugetlb.c:39: include/linux/hugetlb.h:142:10: warning: declaration of 'enum mcopy_atomic_mode' will not be visible outside of this function [-Wvisibility] enum mcopy_atomic_mode mode, ^ mm/hugetlb.c:4659:13: warning: declaration of 'enum mcopy_atomic_mode' will not be visible outside of this function [-Wvisibility] enum mcopy_atomic_mode mode, ^ >> mm/hugetlb.c:4654:5: error: conflicting types for 'hugetlb_mcopy_atomic_pte' int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, ^ include/linux/hugetlb.h:138:5: note: previous declaration is here int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, pte_t *dst_pte, ^ >> mm/hugetlb.c:4659:31: error: variable has incomplete type 'enum mcopy_atomic_mode' enum mcopy_atomic_mode mode, ^ mm/hugetlb.c:4659:13: note: forward declaration of 'enum mcopy_atomic_mode' enum mcopy_atomic_mode mode, ^ >> mm/hugetlb.c:4675:25: error: use of undeclared identifier 'MCOPY_ATOMIC_CONTINUE' if (!*pagep && mode != MCOPY_ATOMIC_CONTINUE) { ^ mm/hugetlb.c:4692:21: error: use of undeclared identifier 'MCOPY_ATOMIC_CONTINUE' } else if (mode == MCOPY_ATOMIC_CONTINUE) { ^ mm/hugetlb.c:4711:27: error: use of undeclared identifier 'MCOPY_ATOMIC_CONTINUE' if (vm_shared && mode != MCOPY_ATOMIC_CONTINUE) { ^ mm/hugetlb.c:4771:14: error: use of undeclared identifier 'MCOPY_ATOMIC_CONTINUE' if (mode != MCOPY_ATOMIC_CONTINUE) ^ 2 warnings and 6 errors generated. vim +/hugetlb_mcopy_atomic_pte +4654 mm/hugetlb.c 86e5216f8d8aa25 Adam Litke 2006-01-06 4649 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4650 /* 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4651 * Used by userfaultfd UFFDIO_COPY. Based on mcopy_atomic_pte with 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4652 * modifications for huge pages. 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4653 */ 8fb5debc5fcd450 Mike Kravetz 2017-02-22 @4654 int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4655 pte_t *dst_pte, 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4656 struct vm_area_struct *dst_vma, 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4657 unsigned long dst_addr, 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4658 unsigned long src_addr, b8fb53c3a341b9b Axel Rasmussen 2021-01-22 @4659 enum mcopy_atomic_mode mode, 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4660 struct page **pagep) 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4661 { 1e3921471354244 Andrea Arcangeli 2017-11-02 4662 struct address_space *mapping; 1e3921471354244 Andrea Arcangeli 2017-11-02 4663 pgoff_t idx; 1e3921471354244 Andrea Arcangeli 2017-11-02 4664 unsigned long size; 1c9e8def43a3452 Mike Kravetz 2017-02-22 4665 int vm_shared = dst_vma->vm_flags & VM_SHARED; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4666 struct hstate *h = hstate_vma(dst_vma); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4667 pte_t _dst_pte; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4668 spinlock_t *ptl; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4669 int ret; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4670 struct page *page; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4671 b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4672 mapping = dst_vma->vm_file->f_mapping; b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4673 idx = vma_hugecache_offset(h, dst_vma, dst_addr); b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4674 b8fb53c3a341b9b Axel Rasmussen 2021-01-22 @4675 if (!*pagep && mode != MCOPY_ATOMIC_CONTINUE) { 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4676 ret = -ENOMEM; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4677 page = alloc_huge_page(dst_vma, dst_addr, 0); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4678 if (IS_ERR(page)) 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4679 goto out; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4680 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4681 ret = copy_huge_page_from_user(page, 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4682 (const void __user *) src_addr, 810a56b943e265b Mike Kravetz 2017-02-22 4683 pages_per_huge_page(h), false); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4684 c1e8d7c6a7a682e Michel Lespinasse 2020-06-08 4685 /* fallback to copy_from_user outside mmap_lock */ 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4686 if (unlikely(ret)) { 9e368259ad98835 Andrea Arcangeli 2018-11-30 4687 ret = -ENOENT; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4688 *pagep = page; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4689 /* don't free the page */ 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4690 goto out; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4691 } b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4692 } else if (mode == MCOPY_ATOMIC_CONTINUE) { b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4693 ret = -EFAULT; b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4694 page = find_lock_page(mapping, idx); b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4695 *pagep = NULL; b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4696 if (!page) b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4697 goto out; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4698 } else { 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4699 page = *pagep; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4700 *pagep = NULL; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4701 } 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4702 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4703 /* 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4704 * The memory barrier inside __SetPageUptodate makes sure that 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4705 * preceding stores to the page contents become visible before 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4706 * the set_pte_at() write. 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4707 */ 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4708 __SetPageUptodate(page); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4709 b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4710 /* Add shared, newly allocated pages to the page cache. */ b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4711 if (vm_shared && mode != MCOPY_ATOMIC_CONTINUE) { 1e3921471354244 Andrea Arcangeli 2017-11-02 4712 size = i_size_read(mapping->host) >> huge_page_shift(h); 1e3921471354244 Andrea Arcangeli 2017-11-02 4713 ret = -EFAULT; 1e3921471354244 Andrea Arcangeli 2017-11-02 4714 if (idx >= size) 1e3921471354244 Andrea Arcangeli 2017-11-02 4715 goto out_release_nounlock; 1c9e8def43a3452 Mike Kravetz 2017-02-22 4716 1e3921471354244 Andrea Arcangeli 2017-11-02 4717 /* 1e3921471354244 Andrea Arcangeli 2017-11-02 4718 * Serialization between remove_inode_hugepages() and 1e3921471354244 Andrea Arcangeli 2017-11-02 4719 * huge_add_to_page_cache() below happens through the 1e3921471354244 Andrea Arcangeli 2017-11-02 4720 * hugetlb_fault_mutex_table that here must be hold by 1e3921471354244 Andrea Arcangeli 2017-11-02 4721 * the caller. 1e3921471354244 Andrea Arcangeli 2017-11-02 4722 */ 1c9e8def43a3452 Mike Kravetz 2017-02-22 4723 ret = huge_add_to_page_cache(page, mapping, idx); 1c9e8def43a3452 Mike Kravetz 2017-02-22 4724 if (ret) 1c9e8def43a3452 Mike Kravetz 2017-02-22 4725 goto out_release_nounlock; 1c9e8def43a3452 Mike Kravetz 2017-02-22 4726 } 1c9e8def43a3452 Mike Kravetz 2017-02-22 4727 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4728 ptl = huge_pte_lockptr(h, dst_mm, dst_pte); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4729 spin_lock(ptl); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4730 1e3921471354244 Andrea Arcangeli 2017-11-02 4731 /* 1e3921471354244 Andrea Arcangeli 2017-11-02 4732 * Recheck the i_size after holding PT lock to make sure not 1e3921471354244 Andrea Arcangeli 2017-11-02 4733 * to leave any page mapped (as page_mapped()) beyond the end 1e3921471354244 Andrea Arcangeli 2017-11-02 4734 * of the i_size (remove_inode_hugepages() is strict about 1e3921471354244 Andrea Arcangeli 2017-11-02 4735 * enforcing that). If we bail out here, we'll also leave a 1e3921471354244 Andrea Arcangeli 2017-11-02 4736 * page in the radix tree in the vm_shared case beyond the end 1e3921471354244 Andrea Arcangeli 2017-11-02 4737 * of the i_size, but remove_inode_hugepages() will take care 1e3921471354244 Andrea Arcangeli 2017-11-02 4738 * of it as soon as we drop the hugetlb_fault_mutex_table. 1e3921471354244 Andrea Arcangeli 2017-11-02 4739 */ 1e3921471354244 Andrea Arcangeli 2017-11-02 4740 size = i_size_read(mapping->host) >> huge_page_shift(h); 1e3921471354244 Andrea Arcangeli 2017-11-02 4741 ret = -EFAULT; 1e3921471354244 Andrea Arcangeli 2017-11-02 4742 if (idx >= size) 1e3921471354244 Andrea Arcangeli 2017-11-02 4743 goto out_release_unlock; 1e3921471354244 Andrea Arcangeli 2017-11-02 4744 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4745 ret = -EEXIST; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4746 if (!huge_pte_none(huge_ptep_get(dst_pte))) 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4747 goto out_release_unlock; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4748 1c9e8def43a3452 Mike Kravetz 2017-02-22 4749 if (vm_shared) { 1c9e8def43a3452 Mike Kravetz 2017-02-22 4750 page_dup_rmap(page, true); 1c9e8def43a3452 Mike Kravetz 2017-02-22 4751 } else { 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4752 ClearPagePrivate(page); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4753 hugepage_add_new_anon_rmap(page, dst_vma, dst_addr); 1c9e8def43a3452 Mike Kravetz 2017-02-22 4754 } 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4755 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4756 _dst_pte = make_huge_pte(dst_vma, page, dst_vma->vm_flags & VM_WRITE); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4757 if (dst_vma->vm_flags & VM_WRITE) 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4758 _dst_pte = huge_pte_mkdirty(_dst_pte); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4759 _dst_pte = pte_mkyoung(_dst_pte); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4760 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4761 set_huge_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4762 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4763 (void)huge_ptep_set_access_flags(dst_vma, dst_addr, dst_pte, _dst_pte, 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4764 dst_vma->vm_flags & VM_WRITE); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4765 hugetlb_count_add(pages_per_huge_page(h), dst_mm); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4766 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4767 /* No need to invalidate - it was non-present before */ 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4768 update_mmu_cache(dst_vma, dst_addr, dst_pte); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4769 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4770 spin_unlock(ptl); b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4771 if (mode != MCOPY_ATOMIC_CONTINUE) cb6acd01e2e43fd Mike Kravetz 2019-02-28 4772 set_page_huge_active(page); 1c9e8def43a3452 Mike Kravetz 2017-02-22 4773 if (vm_shared) 1c9e8def43a3452 Mike Kravetz 2017-02-22 4774 unlock_page(page); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4775 ret = 0; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4776 out: 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4777 return ret; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4778 out_release_unlock: 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4779 spin_unlock(ptl); 1c9e8def43a3452 Mike Kravetz 2017-02-22 4780 if (vm_shared) 1c9e8def43a3452 Mike Kravetz 2017-02-22 4781 unlock_page(page); 5af10dfd0afc559 Andrea Arcangeli 2017-08-10 4782 out_release_nounlock: 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4783 put_page(page); 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4784 goto out; 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4785 } 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4786 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
This build error seems to be caused by a missing #ifdef CONFIG_USERFAULTFD. I'll send a v3 with this fix, after waiting for other feedback on the v2 version. On Mon, Jan 25, 2021 at 5:37 AM kernel test robot <lkp@intel.com> wrote: > > Hi Axel, > > Thank you for the patch! Yet something to improve: > > [auto build test ERROR on arm64/for-next/core] > [also build test ERROR on powerpc/next s390/features tip/perf/core linus/master v5.11-rc5 next-20210122] > [cannot apply to hp-parisc/for-next hnaz-linux-mm/master ia64/next sparc-next/master sparc/master] > [If your patch is applied to the wrong git tree, kindly drop us a note. > And when submitting patch, we suggest to use '--base' as documented in > https://git-scm.com/docs/git-format-patch] > > url: https://github.com/0day-ci/linux/commits/Axel-Rasmussen/userfaultfd-add-minor-fault-handling/20210125-104035 > base: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core > config: x86_64-randconfig-a013-20210125 (attached as .config) > compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 12d0753aca22896fda2cf76781b0ee0524d55065) > reproduce (this is a W=1 build): > wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross > chmod +x ~/bin/make.cross > # install x86_64 cross compiling tool for clang build > # apt-get install binutils-x86-64-linux-gnu > # https://github.com/0day-ci/linux/commit/b8fb53c3a341b9b853aa3286286c807088311dbd > git remote add linux-review https://github.com/0day-ci/linux > git fetch --no-tags linux-review Axel-Rasmussen/userfaultfd-add-minor-fault-handling/20210125-104035 > git checkout b8fb53c3a341b9b853aa3286286c807088311dbd > # save the attached .config to linux build tree > COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 > > If you fix the issue, kindly add following tag as appropriate > Reported-by: kernel test robot <lkp@intel.com> > > All errors (new ones prefixed by >>): > > In file included from mm/hugetlb.c:39: > include/linux/hugetlb.h:142:10: warning: declaration of 'enum mcopy_atomic_mode' will not be visible outside of this function [-Wvisibility] > enum mcopy_atomic_mode mode, > ^ > mm/hugetlb.c:4659:13: warning: declaration of 'enum mcopy_atomic_mode' will not be visible outside of this function [-Wvisibility] > enum mcopy_atomic_mode mode, > ^ > >> mm/hugetlb.c:4654:5: error: conflicting types for 'hugetlb_mcopy_atomic_pte' > int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, > ^ > include/linux/hugetlb.h:138:5: note: previous declaration is here > int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, pte_t *dst_pte, > ^ > >> mm/hugetlb.c:4659:31: error: variable has incomplete type 'enum mcopy_atomic_mode' > enum mcopy_atomic_mode mode, > ^ > mm/hugetlb.c:4659:13: note: forward declaration of 'enum mcopy_atomic_mode' > enum mcopy_atomic_mode mode, > ^ > >> mm/hugetlb.c:4675:25: error: use of undeclared identifier 'MCOPY_ATOMIC_CONTINUE' > if (!*pagep && mode != MCOPY_ATOMIC_CONTINUE) { > ^ > mm/hugetlb.c:4692:21: error: use of undeclared identifier 'MCOPY_ATOMIC_CONTINUE' > } else if (mode == MCOPY_ATOMIC_CONTINUE) { > ^ > mm/hugetlb.c:4711:27: error: use of undeclared identifier 'MCOPY_ATOMIC_CONTINUE' > if (vm_shared && mode != MCOPY_ATOMIC_CONTINUE) { > ^ > mm/hugetlb.c:4771:14: error: use of undeclared identifier 'MCOPY_ATOMIC_CONTINUE' > if (mode != MCOPY_ATOMIC_CONTINUE) > ^ > 2 warnings and 6 errors generated. > > > vim +/hugetlb_mcopy_atomic_pte +4654 mm/hugetlb.c > > 86e5216f8d8aa25 Adam Litke 2006-01-06 4649 > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4650 /* > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4651 * Used by userfaultfd UFFDIO_COPY. Based on mcopy_atomic_pte with > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4652 * modifications for huge pages. > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4653 */ > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 @4654 int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4655 pte_t *dst_pte, > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4656 struct vm_area_struct *dst_vma, > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4657 unsigned long dst_addr, > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4658 unsigned long src_addr, > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 @4659 enum mcopy_atomic_mode mode, > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4660 struct page **pagep) > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4661 { > 1e3921471354244 Andrea Arcangeli 2017-11-02 4662 struct address_space *mapping; > 1e3921471354244 Andrea Arcangeli 2017-11-02 4663 pgoff_t idx; > 1e3921471354244 Andrea Arcangeli 2017-11-02 4664 unsigned long size; > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4665 int vm_shared = dst_vma->vm_flags & VM_SHARED; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4666 struct hstate *h = hstate_vma(dst_vma); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4667 pte_t _dst_pte; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4668 spinlock_t *ptl; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4669 int ret; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4670 struct page *page; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4671 > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4672 mapping = dst_vma->vm_file->f_mapping; > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4673 idx = vma_hugecache_offset(h, dst_vma, dst_addr); > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4674 > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 @4675 if (!*pagep && mode != MCOPY_ATOMIC_CONTINUE) { > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4676 ret = -ENOMEM; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4677 page = alloc_huge_page(dst_vma, dst_addr, 0); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4678 if (IS_ERR(page)) > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4679 goto out; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4680 > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4681 ret = copy_huge_page_from_user(page, > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4682 (const void __user *) src_addr, > 810a56b943e265b Mike Kravetz 2017-02-22 4683 pages_per_huge_page(h), false); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4684 > c1e8d7c6a7a682e Michel Lespinasse 2020-06-08 4685 /* fallback to copy_from_user outside mmap_lock */ > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4686 if (unlikely(ret)) { > 9e368259ad98835 Andrea Arcangeli 2018-11-30 4687 ret = -ENOENT; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4688 *pagep = page; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4689 /* don't free the page */ > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4690 goto out; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4691 } > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4692 } else if (mode == MCOPY_ATOMIC_CONTINUE) { > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4693 ret = -EFAULT; > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4694 page = find_lock_page(mapping, idx); > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4695 *pagep = NULL; > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4696 if (!page) > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4697 goto out; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4698 } else { > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4699 page = *pagep; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4700 *pagep = NULL; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4701 } > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4702 > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4703 /* > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4704 * The memory barrier inside __SetPageUptodate makes sure that > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4705 * preceding stores to the page contents become visible before > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4706 * the set_pte_at() write. > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4707 */ > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4708 __SetPageUptodate(page); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4709 > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4710 /* Add shared, newly allocated pages to the page cache. */ > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4711 if (vm_shared && mode != MCOPY_ATOMIC_CONTINUE) { > 1e3921471354244 Andrea Arcangeli 2017-11-02 4712 size = i_size_read(mapping->host) >> huge_page_shift(h); > 1e3921471354244 Andrea Arcangeli 2017-11-02 4713 ret = -EFAULT; > 1e3921471354244 Andrea Arcangeli 2017-11-02 4714 if (idx >= size) > 1e3921471354244 Andrea Arcangeli 2017-11-02 4715 goto out_release_nounlock; > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4716 > 1e3921471354244 Andrea Arcangeli 2017-11-02 4717 /* > 1e3921471354244 Andrea Arcangeli 2017-11-02 4718 * Serialization between remove_inode_hugepages() and > 1e3921471354244 Andrea Arcangeli 2017-11-02 4719 * huge_add_to_page_cache() below happens through the > 1e3921471354244 Andrea Arcangeli 2017-11-02 4720 * hugetlb_fault_mutex_table that here must be hold by > 1e3921471354244 Andrea Arcangeli 2017-11-02 4721 * the caller. > 1e3921471354244 Andrea Arcangeli 2017-11-02 4722 */ > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4723 ret = huge_add_to_page_cache(page, mapping, idx); > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4724 if (ret) > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4725 goto out_release_nounlock; > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4726 } > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4727 > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4728 ptl = huge_pte_lockptr(h, dst_mm, dst_pte); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4729 spin_lock(ptl); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4730 > 1e3921471354244 Andrea Arcangeli 2017-11-02 4731 /* > 1e3921471354244 Andrea Arcangeli 2017-11-02 4732 * Recheck the i_size after holding PT lock to make sure not > 1e3921471354244 Andrea Arcangeli 2017-11-02 4733 * to leave any page mapped (as page_mapped()) beyond the end > 1e3921471354244 Andrea Arcangeli 2017-11-02 4734 * of the i_size (remove_inode_hugepages() is strict about > 1e3921471354244 Andrea Arcangeli 2017-11-02 4735 * enforcing that). If we bail out here, we'll also leave a > 1e3921471354244 Andrea Arcangeli 2017-11-02 4736 * page in the radix tree in the vm_shared case beyond the end > 1e3921471354244 Andrea Arcangeli 2017-11-02 4737 * of the i_size, but remove_inode_hugepages() will take care > 1e3921471354244 Andrea Arcangeli 2017-11-02 4738 * of it as soon as we drop the hugetlb_fault_mutex_table. > 1e3921471354244 Andrea Arcangeli 2017-11-02 4739 */ > 1e3921471354244 Andrea Arcangeli 2017-11-02 4740 size = i_size_read(mapping->host) >> huge_page_shift(h); > 1e3921471354244 Andrea Arcangeli 2017-11-02 4741 ret = -EFAULT; > 1e3921471354244 Andrea Arcangeli 2017-11-02 4742 if (idx >= size) > 1e3921471354244 Andrea Arcangeli 2017-11-02 4743 goto out_release_unlock; > 1e3921471354244 Andrea Arcangeli 2017-11-02 4744 > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4745 ret = -EEXIST; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4746 if (!huge_pte_none(huge_ptep_get(dst_pte))) > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4747 goto out_release_unlock; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4748 > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4749 if (vm_shared) { > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4750 page_dup_rmap(page, true); > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4751 } else { > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4752 ClearPagePrivate(page); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4753 hugepage_add_new_anon_rmap(page, dst_vma, dst_addr); > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4754 } > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4755 > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4756 _dst_pte = make_huge_pte(dst_vma, page, dst_vma->vm_flags & VM_WRITE); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4757 if (dst_vma->vm_flags & VM_WRITE) > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4758 _dst_pte = huge_pte_mkdirty(_dst_pte); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4759 _dst_pte = pte_mkyoung(_dst_pte); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4760 > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4761 set_huge_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4762 > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4763 (void)huge_ptep_set_access_flags(dst_vma, dst_addr, dst_pte, _dst_pte, > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4764 dst_vma->vm_flags & VM_WRITE); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4765 hugetlb_count_add(pages_per_huge_page(h), dst_mm); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4766 > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4767 /* No need to invalidate - it was non-present before */ > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4768 update_mmu_cache(dst_vma, dst_addr, dst_pte); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4769 > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4770 spin_unlock(ptl); > b8fb53c3a341b9b Axel Rasmussen 2021-01-22 4771 if (mode != MCOPY_ATOMIC_CONTINUE) > cb6acd01e2e43fd Mike Kravetz 2019-02-28 4772 set_page_huge_active(page); > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4773 if (vm_shared) > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4774 unlock_page(page); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4775 ret = 0; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4776 out: > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4777 return ret; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4778 out_release_unlock: > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4779 spin_unlock(ptl); > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4780 if (vm_shared) > 1c9e8def43a3452 Mike Kravetz 2017-02-22 4781 unlock_page(page); > 5af10dfd0afc559 Andrea Arcangeli 2017-08-10 4782 out_release_nounlock: > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4783 put_page(page); > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4784 goto out; > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4785 } > 8fb5debc5fcd450 Mike Kravetz 2017-02-22 4786 > > --- > 0-DAY CI Kernel Test Service, Intel Corporation > https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c index 968aca3e3ee9..80a3fca389b8 100644 --- a/fs/userfaultfd.c +++ b/fs/userfaultfd.c @@ -1530,6 +1530,10 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx, if (!(uffdio_register.mode & UFFDIO_REGISTER_MODE_WP)) ioctls_out &= ~((__u64)1 << _UFFDIO_WRITEPROTECT); + /* CONTINUE ioctl is only supported for MINOR ranges. */ + if (!(uffdio_register.mode & UFFDIO_REGISTER_MODE_MINOR)) + ioctls_out &= ~((__u64)1 << _UFFDIO_CONTINUE); + /* * Now that we scanned all vmas we can already tell * userland which ioctls methods are guaranteed to @@ -1883,6 +1887,66 @@ static int userfaultfd_writeprotect(struct userfaultfd_ctx *ctx, return ret; } +static int userfaultfd_continue(struct userfaultfd_ctx *ctx, unsigned long arg) +{ + __s64 ret; + struct uffdio_continue uffdio_continue; + struct uffdio_continue __user *user_uffdio_continue; + struct userfaultfd_wake_range range; + + user_uffdio_continue = (struct uffdio_continue __user *)arg; + + ret = -EAGAIN; + if (READ_ONCE(ctx->mmap_changing)) + goto out; + + ret = -EFAULT; + if (copy_from_user(&uffdio_continue, user_uffdio_continue, + /* don't copy the output fields */ + sizeof(uffdio_continue) - (sizeof(__s64)))) + goto out; + + ret = validate_range(ctx->mm, &uffdio_continue.range.start, + uffdio_continue.range.len); + if (ret) + goto out; + + ret = -EINVAL; + /* double check for wraparound just in case. */ + if (uffdio_continue.range.start + uffdio_continue.range.len <= + uffdio_continue.range.start) { + goto out; + } + if (uffdio_continue.mode & ~UFFDIO_CONTINUE_MODE_DONTWAKE) + goto out; + + if (mmget_not_zero(ctx->mm)) { + ret = mcopy_continue(ctx->mm, uffdio_continue.range.start, + uffdio_continue.range.len, + &ctx->mmap_changing); + mmput(ctx->mm); + } else { + return -ESRCH; + } + + if (unlikely(put_user(ret, &user_uffdio_continue->mapped))) + return -EFAULT; + if (ret < 0) + goto out; + + /* len == 0 would wake all */ + BUG_ON(!ret); + range.len = ret; + if (!(uffdio_continue.mode & UFFDIO_CONTINUE_MODE_DONTWAKE)) { + range.start = uffdio_continue.range.start; + wake_userfault(ctx, &range); + } + ret = range.len == uffdio_continue.range.len ? 0 : -EAGAIN; + +out: + return ret; +} + static inline unsigned int uffd_ctx_features(__u64 user_features) { /* @@ -1967,6 +2031,9 @@ static long userfaultfd_ioctl(struct file *file, unsigned cmd, case UFFDIO_WRITEPROTECT: ret = userfaultfd_writeprotect(ctx, arg); break; + case UFFDIO_CONTINUE: + ret = userfaultfd_continue(ctx, arg); + break; } return ret; } diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index f94a35296618..f9fd7df1d586 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -139,6 +139,7 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, pte_t *dst_pte, struct vm_area_struct *dst_vma, unsigned long dst_addr, unsigned long src_addr, + enum mcopy_atomic_mode mode, struct page **pagep); int hugetlb_reserve_pages(struct inode *inode, long from, long to, struct vm_area_struct *vma, diff --git a/include/linux/userfaultfd_k.h b/include/linux/userfaultfd_k.h index fb9abaeb4194..2fcb686211e8 100644 --- a/include/linux/userfaultfd_k.h +++ b/include/linux/userfaultfd_k.h @@ -37,6 +37,22 @@ extern int sysctl_unprivileged_userfaultfd; extern vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason); +/* + * The mode of operation for __mcopy_atomic and its helpers. + * + * This is almost an implementation detail (mcopy_atomic below doesn't take this + * as a parameter), but it's exposed here because memory-kind-specific + * implementations (e.g. hugetlbfs) need to know the mode of operation. + */ +enum mcopy_atomic_mode { + /* A normal copy_from_user into the destination range. */ + MCOPY_ATOMIC_NORMAL, + /* Don't copy; map the destination range to the zero page. */ + MCOPY_ATOMIC_ZEROPAGE, + /* Just setup the dst_vma, without modifying the underlying page(s). */ + MCOPY_ATOMIC_CONTINUE, +}; + extern ssize_t mcopy_atomic(struct mm_struct *dst_mm, unsigned long dst_start, unsigned long src_start, unsigned long len, bool *mmap_changing, __u64 mode); @@ -44,6 +60,8 @@ extern ssize_t mfill_zeropage(struct mm_struct *dst_mm, unsigned long dst_start, unsigned long len, bool *mmap_changing); +extern ssize_t mcopy_continue(struct mm_struct *dst_mm, unsigned long dst_start, + unsigned long len, bool *mmap_changing); extern int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start, unsigned long len, bool enable_wp, bool *mmap_changing); diff --git a/include/uapi/linux/userfaultfd.h b/include/uapi/linux/userfaultfd.h index f24dd4fcbad9..bafbeb1a2624 100644 --- a/include/uapi/linux/userfaultfd.h +++ b/include/uapi/linux/userfaultfd.h @@ -40,10 +40,12 @@ ((__u64)1 << _UFFDIO_WAKE | \ (__u64)1 << _UFFDIO_COPY | \ (__u64)1 << _UFFDIO_ZEROPAGE | \ - (__u64)1 << _UFFDIO_WRITEPROTECT) + (__u64)1 << _UFFDIO_WRITEPROTECT | \ + (__u64)1 << _UFFDIO_CONTINUE) #define UFFD_API_RANGE_IOCTLS_BASIC \ ((__u64)1 << _UFFDIO_WAKE | \ - (__u64)1 << _UFFDIO_COPY) + (__u64)1 << _UFFDIO_COPY | \ + (__u64)1 << _UFFDIO_CONTINUE) /* * Valid ioctl command number range with this API is from 0x00 to @@ -59,6 +61,7 @@ #define _UFFDIO_COPY (0x03) #define _UFFDIO_ZEROPAGE (0x04) #define _UFFDIO_WRITEPROTECT (0x06) +#define _UFFDIO_CONTINUE (0x07) #define _UFFDIO_API (0x3F) /* userfaultfd ioctl ids */ @@ -77,6 +80,8 @@ struct uffdio_zeropage) #define UFFDIO_WRITEPROTECT _IOWR(UFFDIO, _UFFDIO_WRITEPROTECT, \ struct uffdio_writeprotect) +#define UFFDIO_CONTINUE _IOR(UFFDIO, _UFFDIO_CONTINUE, \ + struct uffdio_continue) /* read() structure */ struct uffd_msg { @@ -268,6 +273,18 @@ struct uffdio_writeprotect { __u64 mode; }; +struct uffdio_continue { + struct uffdio_range range; +#define UFFDIO_CONTINUE_MODE_DONTWAKE ((__u64)1<<0) + __u64 mode; + + /* + * Fields below here are written by the ioctl and must be at the end: + * the copy_from_user will not read past here. + */ + __s64 mapped; +}; + /* * Flags for the userfaultfd(2) system call itself. */ diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 6f9d8349f818..740a090f34d1 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -4656,6 +4656,7 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, struct vm_area_struct *dst_vma, unsigned long dst_addr, unsigned long src_addr, + enum mcopy_atomic_mode mode, struct page **pagep) { struct address_space *mapping; @@ -4668,7 +4669,10 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, int ret; struct page *page; - if (!*pagep) { + mapping = dst_vma->vm_file->f_mapping; + idx = vma_hugecache_offset(h, dst_vma, dst_addr); + + if (!*pagep && mode != MCOPY_ATOMIC_CONTINUE) { ret = -ENOMEM; page = alloc_huge_page(dst_vma, dst_addr, 0); if (IS_ERR(page)) @@ -4685,6 +4689,12 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, /* don't free the page */ goto out; } + } else if (mode == MCOPY_ATOMIC_CONTINUE) { + ret = -EFAULT; + page = find_lock_page(mapping, idx); + *pagep = NULL; + if (!page) + goto out; } else { page = *pagep; *pagep = NULL; @@ -4697,13 +4707,8 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, */ __SetPageUptodate(page); - mapping = dst_vma->vm_file->f_mapping; - idx = vma_hugecache_offset(h, dst_vma, dst_addr); - - /* - * If shared, add to page cache - */ - if (vm_shared) { + /* Add shared, newly allocated pages to the page cache. */ + if (vm_shared && mode != MCOPY_ATOMIC_CONTINUE) { size = i_size_read(mapping->host) >> huge_page_shift(h); ret = -EFAULT; if (idx >= size) @@ -4763,7 +4768,8 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, update_mmu_cache(dst_vma, dst_addr, dst_pte); spin_unlock(ptl); - set_page_huge_active(page); + if (mode != MCOPY_ATOMIC_CONTINUE) + set_page_huge_active(page); if (vm_shared) unlock_page(page); ret = 0; diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index b2ce61c1b50d..a762b9cefaea 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -207,7 +207,7 @@ static __always_inline ssize_t __mcopy_atomic_hugetlb(struct mm_struct *dst_mm, unsigned long dst_start, unsigned long src_start, unsigned long len, - bool zeropage) + enum mcopy_atomic_mode mode) { int vm_alloc_shared = dst_vma->vm_flags & VM_SHARED; int vm_shared = dst_vma->vm_flags & VM_SHARED; @@ -227,7 +227,7 @@ static __always_inline ssize_t __mcopy_atomic_hugetlb(struct mm_struct *dst_mm, * by THP. Since we can not reliably insert a zero page, this * feature is not supported. */ - if (zeropage) { + if (mode == MCOPY_ATOMIC_ZEROPAGE) { mmap_read_unlock(dst_mm); return -EINVAL; } @@ -273,8 +273,6 @@ static __always_inline ssize_t __mcopy_atomic_hugetlb(struct mm_struct *dst_mm, } while (src_addr < src_start + len) { - pte_t dst_pteval; - BUG_ON(dst_addr >= dst_start + len); /* @@ -297,16 +295,17 @@ static __always_inline ssize_t __mcopy_atomic_hugetlb(struct mm_struct *dst_mm, goto out_unlock; } - err = -EEXIST; - dst_pteval = huge_ptep_get(dst_pte); - if (!huge_pte_none(dst_pteval)) { - mutex_unlock(&hugetlb_fault_mutex_table[hash]); - i_mmap_unlock_read(mapping); - goto out_unlock; + if (mode != MCOPY_ATOMIC_CONTINUE) { + if (!huge_pte_none(huge_ptep_get(dst_pte))) { + err = -EEXIST; + mutex_unlock(&hugetlb_fault_mutex_table[hash]); + i_mmap_unlock_read(mapping); + goto out_unlock; + } } err = hugetlb_mcopy_atomic_pte(dst_mm, dst_pte, dst_vma, - dst_addr, src_addr, &page); + dst_addr, src_addr, mode, &page); mutex_unlock(&hugetlb_fault_mutex_table[hash]); i_mmap_unlock_read(mapping); @@ -408,7 +407,7 @@ extern ssize_t __mcopy_atomic_hugetlb(struct mm_struct *dst_mm, unsigned long dst_start, unsigned long src_start, unsigned long len, - bool zeropage); + enum mcopy_atomic_mode mode); #endif /* CONFIG_HUGETLB_PAGE */ static __always_inline ssize_t mfill_atomic_pte(struct mm_struct *dst_mm, @@ -417,7 +416,7 @@ static __always_inline ssize_t mfill_atomic_pte(struct mm_struct *dst_mm, unsigned long dst_addr, unsigned long src_addr, struct page **page, - bool zeropage, + enum mcopy_atomic_mode mode, bool wp_copy) { ssize_t err; @@ -433,22 +432,38 @@ static __always_inline ssize_t mfill_atomic_pte(struct mm_struct *dst_mm, * and not in the radix tree. */ if (!(dst_vma->vm_flags & VM_SHARED)) { - if (!zeropage) + switch (mode) { + case MCOPY_ATOMIC_NORMAL: err = mcopy_atomic_pte(dst_mm, dst_pmd, dst_vma, dst_addr, src_addr, page, wp_copy); - else + break; + case MCOPY_ATOMIC_ZEROPAGE: err = mfill_zeropage_pte(dst_mm, dst_pmd, dst_vma, dst_addr); + break; + /* It only makes sense to CONTINUE for shared memory. */ + case MCOPY_ATOMIC_CONTINUE: + err = -EINVAL; + break; + } } else { VM_WARN_ON_ONCE(wp_copy); - if (!zeropage) + switch (mode) { + case MCOPY_ATOMIC_NORMAL: err = shmem_mcopy_atomic_pte(dst_mm, dst_pmd, dst_vma, dst_addr, src_addr, page); - else + break; + case MCOPY_ATOMIC_ZEROPAGE: err = shmem_mfill_zeropage_pte(dst_mm, dst_pmd, dst_vma, dst_addr); + break; + case MCOPY_ATOMIC_CONTINUE: + /* FIXME: Add minor fault interception for shmem. */ + err = -EINVAL; + break; + } } return err; @@ -458,7 +473,7 @@ static __always_inline ssize_t __mcopy_atomic(struct mm_struct *dst_mm, unsigned long dst_start, unsigned long src_start, unsigned long len, - bool zeropage, + enum mcopy_atomic_mode mcopy_mode, bool *mmap_changing, __u64 mode) { @@ -527,7 +542,7 @@ static __always_inline ssize_t __mcopy_atomic(struct mm_struct *dst_mm, */ if (is_vm_hugetlb_page(dst_vma)) return __mcopy_atomic_hugetlb(dst_mm, dst_vma, dst_start, - src_start, len, zeropage); + src_start, len, mcopy_mode); if (!vma_is_anonymous(dst_vma) && !vma_is_shmem(dst_vma)) goto out_unlock; @@ -577,7 +592,7 @@ static __always_inline ssize_t __mcopy_atomic(struct mm_struct *dst_mm, BUG_ON(pmd_trans_huge(*dst_pmd)); err = mfill_atomic_pte(dst_mm, dst_pmd, dst_vma, dst_addr, - src_addr, &page, zeropage, wp_copy); + src_addr, &page, mcopy_mode, wp_copy); cond_resched(); if (unlikely(err == -ENOENT)) { @@ -626,14 +641,22 @@ ssize_t mcopy_atomic(struct mm_struct *dst_mm, unsigned long dst_start, unsigned long src_start, unsigned long len, bool *mmap_changing, __u64 mode) { - return __mcopy_atomic(dst_mm, dst_start, src_start, len, false, - mmap_changing, mode); + return __mcopy_atomic(dst_mm, dst_start, src_start, len, + MCOPY_ATOMIC_NORMAL, mmap_changing, mode); } ssize_t mfill_zeropage(struct mm_struct *dst_mm, unsigned long start, unsigned long len, bool *mmap_changing) { - return __mcopy_atomic(dst_mm, start, 0, len, true, mmap_changing, 0); + return __mcopy_atomic(dst_mm, start, 0, len, MCOPY_ATOMIC_ZEROPAGE, + mmap_changing, 0); +} + +ssize_t mcopy_continue(struct mm_struct *dst_mm, unsigned long start, + unsigned long len, bool *mmap_changing) +{ + return __mcopy_atomic(dst_mm, start, 0, len, MCOPY_ATOMIC_CONTINUE, + mmap_changing, 0); } int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start,
This ioctl is how userspace ought to resolve "minor" userfaults. The idea is, userspace is notified that a minor fault has occurred. It might change the contents of the page using its second non-UFFD mapping, or not. Then, it calls UFFDIO_CONTINUE to tell the kernel "I have ensured the page contents are correct, carry on setting up the mapping". Note that it doesn't make much sense to use UFFDIO_{COPY,ZEROPAGE} for MINOR registered VMAs. ZEROPAGE maps the VMA to the zero page; but in the minor fault case, we already have some pre-existing underlying page. Likewise, UFFDIO_COPY isn't useful if we have a second non-UFFD mapping. We'd just use memcpy() or similar instead. It turns out hugetlb_mcopy_atomic_pte() already does very close to what we want, if an existing page is provided via `struct page **pagep`. We already special-case the behavior a bit for the UFFDIO_ZEROPAGE case, so just extend that design: add an enum for the three modes of operation, and make the small adjustments needed for the MCOPY_ATOMIC_CONTINUE case. (Basically, look up the existing page, and avoid adding the existing page to the page cache or calling set_page_huge_active() on it.) Signed-off-by: Axel Rasmussen <axelrasmussen@google.com> --- fs/userfaultfd.c | 67 +++++++++++++++++++++++++++++++ include/linux/hugetlb.h | 1 + include/linux/userfaultfd_k.h | 18 +++++++++ include/uapi/linux/userfaultfd.h | 21 +++++++++- mm/hugetlb.c | 24 ++++++----- mm/userfaultfd.c | 69 +++++++++++++++++++++----------- 6 files changed, 166 insertions(+), 34 deletions(-)