Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

merge mm-hotfixes-stable into mm-stable to pick up depended-upon changes

+80 -21
+7
lib/maple_tree.c
··· 4107 4107 * mas_wr_append: Attempt to append 4108 4108 * @wr_mas: the maple write state 4109 4109 * 4110 + * This is currently unsafe in rcu mode since the end of the node may be cached 4111 + * by readers while the node contents may be updated which could result in 4112 + * inaccurate information. 4113 + * 4110 4114 * Return: True if appended, false otherwise 4111 4115 */ 4112 4116 static inline bool mas_wr_append(struct ma_wr_state *wr_mas, ··· 4119 4115 unsigned char end = wr_mas->node_end; 4120 4116 struct ma_state *mas = wr_mas->mas; 4121 4117 unsigned char node_pivots = mt_pivots[wr_mas->type]; 4118 + 4119 + if (mt_in_rcu(mas->tree)) 4120 + return false; 4122 4121 4123 4122 if (mas->offset != wr_mas->node_end) 4124 4123 return false;
+1 -1
mm/huge_memory.c
··· 1607 1607 * If other processes are mapping this folio, we couldn't discard 1608 1608 * the folio unless they all do MADV_FREE so let's skip the folio. 1609 1609 */ 1610 - if (folio_mapcount(folio) != 1) 1610 + if (folio_estimated_sharers(folio) != 1) 1611 1611 goto out; 1612 1612 1613 1613 if (!folio_trylock(folio))
+3 -3
mm/madvise.c
··· 383 383 folio = pfn_folio(pmd_pfn(orig_pmd)); 384 384 385 385 /* Do not interfere with other mappings of this folio */ 386 - if (folio_mapcount(folio) != 1) 386 + if (folio_estimated_sharers(folio) != 1) 387 387 goto huge_unlock; 388 388 389 389 if (pageout_anon_only_filter && !folio_test_anon(folio)) ··· 459 459 if (folio_test_large(folio)) { 460 460 int err; 461 461 462 - if (folio_mapcount(folio) != 1) 462 + if (folio_estimated_sharers(folio) != 1) 463 463 break; 464 464 if (pageout_anon_only_filter && !folio_test_anon(folio)) 465 465 break; ··· 683 683 if (folio_test_large(folio)) { 684 684 int err; 685 685 686 - if (folio_mapcount(folio) != 1) 686 + if (folio_estimated_sharers(folio) != 1) 687 687 break; 688 688 if (!folio_trylock(folio)) 689 689 break;
+4 -2
mm/shmem.c
··· 806 806 XA_STATE(xas, &mapping->i_pages, start); 807 807 struct page *page; 808 808 unsigned long swapped = 0; 809 + unsigned long max = end - 1; 809 810 810 811 rcu_read_lock(); 811 - xas_for_each(&xas, page, end - 1) { 812 + xas_for_each(&xas, page, max) { 812 813 if (xas_retry(&xas, page)) 813 814 continue; 814 815 if (xa_is_value(page)) 815 816 swapped++; 816 - 817 + if (xas.xa_index == max) 818 + break; 817 819 if (need_resched()) { 818 820 xas_pause(&xas); 819 821 cond_resched_rcu();
+65 -15
tools/testing/selftests/cachestat/test_cachestat.c
··· 4 4 #include <stdio.h> 5 5 #include <stdbool.h> 6 6 #include <linux/kernel.h> 7 + #include <linux/magic.h> 7 8 #include <linux/mman.h> 8 9 #include <sys/mman.h> 9 10 #include <sys/shm.h> 10 11 #include <sys/syscall.h> 12 + #include <sys/vfs.h> 11 13 #include <unistd.h> 12 14 #include <string.h> 13 15 #include <fcntl.h> 14 16 #include <errno.h> 15 17 16 18 #include "../kselftest.h" 19 + 20 + #define NR_TESTS 9 17 21 18 22 static const char * const dev_files[] = { 19 23 "/dev/zero", "/dev/null", "/dev/urandom", ··· 95 91 } 96 92 97 93 /* 94 + * fsync() is implemented via noop_fsync() on tmpfs. This makes the fsync() 95 + * test fail below, so we need to check for test file living on a tmpfs. 96 + */ 97 + static bool is_on_tmpfs(int fd) 98 + { 99 + struct statfs statfs_buf; 100 + 101 + if (fstatfs(fd, &statfs_buf)) 102 + return false; 103 + 104 + return statfs_buf.f_type == TMPFS_MAGIC; 105 + } 106 + 107 + /* 98 108 * Open/create the file at filename, (optionally) write random data to it 99 109 * (exactly num_pages), then test the cachestat syscall on this file. 100 110 * 101 111 * If test_fsync == true, fsync the file, then check the number of dirty 102 112 * pages. 103 113 */ 104 - bool test_cachestat(const char *filename, bool write_random, bool create, 105 - bool test_fsync, unsigned long num_pages, int open_flags, 106 - mode_t open_mode) 114 + static int test_cachestat(const char *filename, bool write_random, bool create, 115 + bool test_fsync, unsigned long num_pages, 116 + int open_flags, mode_t open_mode) 107 117 { 108 118 size_t PS = sysconf(_SC_PAGESIZE); 109 119 int filesize = num_pages * PS; 110 - bool ret = true; 120 + int ret = KSFT_PASS; 111 121 long syscall_ret; 112 122 struct cachestat cs; 113 123 struct cachestat_range cs_range = { 0, filesize }; ··· 130 112 131 113 if (fd == -1) { 132 114 ksft_print_msg("Unable to create/open file.\n"); 133 - ret = false; 115 + ret = KSFT_FAIL; 134 116 goto out; 135 117 } else { 136 118 ksft_print_msg("Create/open %s\n", filename); ··· 139 121 if (write_random) { 140 122 if (!write_exactly(fd, filesize)) { 141 123 ksft_print_msg("Unable to access urandom.\n"); 142 - ret = false; 124 + ret = KSFT_FAIL; 143 125 goto out1; 144 126 } 145 127 } ··· 150 132 151 133 if (syscall_ret) { 152 134 ksft_print_msg("Cachestat returned non-zero.\n"); 153 - ret = false; 135 + ret = KSFT_FAIL; 154 136 goto out1; 155 137 156 138 } else { ··· 160 142 if (cs.nr_cache + cs.nr_evicted != num_pages) { 161 143 ksft_print_msg( 162 144 "Total number of cached and evicted pages is off.\n"); 163 - ret = false; 145 + ret = KSFT_FAIL; 164 146 } 165 147 } 166 148 } 167 149 168 150 if (test_fsync) { 169 - if (fsync(fd)) { 151 + if (is_on_tmpfs(fd)) { 152 + ret = KSFT_SKIP; 153 + } else if (fsync(fd)) { 170 154 ksft_print_msg("fsync fails.\n"); 171 - ret = false; 155 + ret = KSFT_FAIL; 172 156 } else { 173 157 syscall_ret = syscall(cachestat_nr, fd, &cs_range, &cs, 0); 174 158 ··· 181 161 print_cachestat(&cs); 182 162 183 163 if (cs.nr_dirty) { 184 - ret = false; 164 + ret = KSFT_FAIL; 185 165 ksft_print_msg( 186 166 "Number of dirty should be zero after fsync.\n"); 187 167 } 188 168 } else { 189 169 ksft_print_msg("Cachestat (after fsync) returned non-zero.\n"); 190 - ret = false; 170 + ret = KSFT_FAIL; 191 171 goto out1; 192 172 } 193 173 } ··· 256 236 257 237 int main(void) 258 238 { 259 - int ret = 0; 239 + int ret; 240 + 241 + ksft_print_header(); 242 + 243 + ret = syscall(__NR_cachestat, -1, NULL, NULL, 0); 244 + if (ret == -1 && errno == ENOSYS) 245 + ksft_exit_skip("cachestat syscall not available\n"); 246 + 247 + ksft_set_plan(NR_TESTS); 248 + 249 + if (ret == -1 && errno == EBADF) { 250 + ksft_test_result_pass("bad file descriptor recognized\n"); 251 + ret = 0; 252 + } else { 253 + ksft_test_result_fail("bad file descriptor ignored\n"); 254 + ret = 1; 255 + } 260 256 261 257 for (int i = 0; i < 5; i++) { 262 258 const char *dev_filename = dev_files[i]; 263 259 264 260 if (test_cachestat(dev_filename, false, false, false, 265 - 4, O_RDONLY, 0400)) 261 + 4, O_RDONLY, 0400) == KSFT_PASS) 266 262 ksft_test_result_pass("cachestat works with %s\n", dev_filename); 267 263 else { 268 264 ksft_test_result_fail("cachestat fails with %s\n", dev_filename); ··· 287 251 } 288 252 289 253 if (test_cachestat("tmpfilecachestat", true, true, 290 - true, 4, O_CREAT | O_RDWR, 0400 | 0600)) 254 + false, 4, O_CREAT | O_RDWR, 0600) == KSFT_PASS) 291 255 ksft_test_result_pass("cachestat works with a normal file\n"); 292 256 else { 293 257 ksft_test_result_fail("cachestat fails with normal file\n"); 294 258 ret = 1; 259 + } 260 + 261 + switch (test_cachestat("tmpfilecachestat", true, true, 262 + true, 4, O_CREAT | O_RDWR, 0600)) { 263 + case KSFT_FAIL: 264 + ksft_test_result_fail("cachestat fsync fails with normal file\n"); 265 + ret = KSFT_FAIL; 266 + break; 267 + case KSFT_PASS: 268 + ksft_test_result_pass("cachestat fsync works with a normal file\n"); 269 + break; 270 + case KSFT_SKIP: 271 + ksft_test_result_skip("tmpfilecachestat is on tmpfs\n"); 272 + break; 295 273 } 296 274 297 275 if (test_cachestat_shmem())