Message ID | 20191220142548.7118-3-kirill.shutemov@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Fix two above-47bit hint address vs. THP bugs | expand |
Hi "Kirill, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on linus/master] [also build test WARNING on v5.5-rc3 next-20191220] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982] url: https://github.com/0day-ci/linux/commits/Kirill-A-Shutemov/Fix-two-above-47bit-hint-address-vs-THP-bugs/20191223-221713 base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 46cf053efec6a3a5f343fead837777efe8252a46 reproduce: # apt-get install sparse # sparse version: v0.6.1-129-g341daf20-dirty make ARCH=x86_64 allmodconfig make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' If you fix the issue, kindly add following tag Reported-by: kbuild test robot <lkp@intel.com> sparse warnings: (new ones prefixed by >>) >> mm/shmem.c:2147:34: sparse: sparse: incorrect type in argument 1 (different base types) >> mm/shmem.c:2147:34: sparse: expected struct file * >> mm/shmem.c:2147:34: sparse: got unsigned long uaddr vim +2147 mm/shmem.c 2073 2074 unsigned long shmem_get_unmapped_area(struct file *file, 2075 unsigned long uaddr, unsigned long len, 2076 unsigned long pgoff, unsigned long flags) 2077 { 2078 unsigned long (*get_area)(struct file *, 2079 unsigned long, unsigned long, unsigned long, unsigned long); 2080 unsigned long addr; 2081 unsigned long offset; 2082 unsigned long inflated_len; 2083 unsigned long inflated_addr; 2084 unsigned long inflated_offset; 2085 2086 if (len > TASK_SIZE) 2087 return -ENOMEM; 2088 2089 get_area = current->mm->get_unmapped_area; 2090 addr = get_area(file, uaddr, len, pgoff, flags); 2091 2092 if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGE_PAGECACHE)) 2093 return addr; 2094 if (IS_ERR_VALUE(addr)) 2095 return addr; 2096 if (addr & ~PAGE_MASK) 2097 return addr; 2098 if (addr > TASK_SIZE - len) 2099 return addr; 2100 2101 if (shmem_huge == SHMEM_HUGE_DENY) 2102 return addr; 2103 if (len < HPAGE_PMD_SIZE) 2104 return addr; 2105 if (flags & MAP_FIXED) 2106 return addr; 2107 /* 2108 * Our priority is to support MAP_SHARED mapped hugely; 2109 * and support MAP_PRIVATE mapped hugely too, until it is COWed. 2110 * But if caller specified an address hint and we allocated area there 2111 * successfully, respect that as before. 2112 */ 2113 if (uaddr == addr) 2114 return addr; 2115 2116 if (shmem_huge != SHMEM_HUGE_FORCE) { 2117 struct super_block *sb; 2118 2119 if (file) { 2120 VM_BUG_ON(file->f_op != &shmem_file_operations); 2121 sb = file_inode(file)->i_sb; 2122 } else { 2123 /* 2124 * Called directly from mm/mmap.c, or drivers/char/mem.c 2125 * for "/dev/zero", to create a shared anonymous object. 2126 */ 2127 if (IS_ERR(shm_mnt)) 2128 return addr; 2129 sb = shm_mnt->mnt_sb; 2130 } 2131 if (SHMEM_SB(sb)->huge == SHMEM_HUGE_NEVER) 2132 return addr; 2133 } 2134 2135 offset = (pgoff << PAGE_SHIFT) & (HPAGE_PMD_SIZE-1); 2136 if (offset && offset + len < 2 * HPAGE_PMD_SIZE) 2137 return addr; 2138 if ((addr & (HPAGE_PMD_SIZE-1)) == offset) 2139 return addr; 2140 2141 inflated_len = len + HPAGE_PMD_SIZE - PAGE_SIZE; 2142 if (inflated_len > TASK_SIZE) 2143 return addr; 2144 if (inflated_len < len) 2145 return addr; 2146 > 2147 inflated_addr = get_area(uaddr, 0, inflated_len, 0, flags); 2148 if (IS_ERR_VALUE(inflated_addr)) 2149 return addr; 2150 if (inflated_addr & ~PAGE_MASK) 2151 return addr; 2152 2153 inflated_offset = inflated_addr & (HPAGE_PMD_SIZE-1); 2154 inflated_addr += offset - inflated_offset; 2155 if (inflated_offset > offset) 2156 inflated_addr += HPAGE_PMD_SIZE; 2157 2158 if (inflated_addr > TASK_SIZE - len) 2159 return addr; 2160 return inflated_addr; 2161 } 2162 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation
diff --git a/mm/shmem.c b/mm/shmem.c index 165fa6332993..dc539482ce67 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2107,9 +2107,10 @@ unsigned long shmem_get_unmapped_area(struct file *file, /* * Our priority is to support MAP_SHARED mapped hugely; * and support MAP_PRIVATE mapped hugely too, until it is COWed. - * But if caller specified an address hint, respect that as before. + * But if caller specified an address hint and we allocated area there + * successfully, respect that as before. */ - if (uaddr) + if (uaddr == addr) return addr; if (shmem_huge != SHMEM_HUGE_FORCE) { @@ -2143,7 +2144,7 @@ unsigned long shmem_get_unmapped_area(struct file *file, if (inflated_len < len) return addr; - inflated_addr = get_area(NULL, 0, inflated_len, 0, flags); + inflated_addr = get_area(uaddr, 0, inflated_len, 0, flags); if (IS_ERR_VALUE(inflated_addr)) return addr; if (inflated_addr & ~PAGE_MASK)
Shmem/tmpfs tries to provide THP-friendly mappings if huge pages are enabled. But it doesn't work well with above-47bit hint address. Normally, the kernel doesn't create userspace mappings above 47-bit, even if the machine allows this (such as with 5-level paging on x86-64). Not all user space is ready to handle wide addresses. It's known that at least some JIT compilers use higher bits in pointers to encode their information. Userspace can ask for allocation from full address space by specifying hint address (with or without MAP_FIXED) above 47-bits. If the application doesn't need a particular address, but wants to allocate from whole address space it can specify -1 as a hint address. Unfortunately, this trick breaks THP alignment in shmem/tmp: shmem_get_unmapped_area() would not try to allocate PMD-aligned area if *any* hint address specified. This can be fixed by requesting the aligned area if the we failed to allocated at user-specified hint address. The request with inflated length will also take the user-specified hint address. This way we will not lose an allocation request from the full address space. Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Fixes: b569bab78d8d ("x86/mm: Prepare to expose larger address space to userspace") --- mm/shmem.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)