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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'xarray-5.2-rc6' of git://git.infradead.org/users/willy/linux-dax

Pull XArray fixes from Matthew Wilcox:

- Account XArray nodes for the page cache to the appropriate cgroup
(Johannes Weiner)

- Fix idr_get_next() when called under the RCU lock (Matthew Wilcox)

- Add a test for xa_insert() (Matthew Wilcox)

* tag 'xarray-5.2-rc6' of git://git.infradead.org/users/willy/linux-dax:
XArray tests: Add check_insert
idr: Fix idr_get_next race with idr_remove
mm: fix page cache convergence regression

+108 -5
+1 -1
fs/inode.c
··· 362 362 363 363 static void __address_space_init_once(struct address_space *mapping) 364 364 { 365 - xa_init_flags(&mapping->i_pages, XA_FLAGS_LOCK_IRQ); 365 + xa_init_flags(&mapping->i_pages, XA_FLAGS_LOCK_IRQ | XA_FLAGS_ACCOUNT); 366 366 init_rwsem(&mapping->i_mmap_rwsem); 367 367 INIT_LIST_HEAD(&mapping->private_list); 368 368 spin_lock_init(&mapping->private_lock);
+1
include/linux/xarray.h
··· 265 265 #define XA_FLAGS_TRACK_FREE ((__force gfp_t)4U) 266 266 #define XA_FLAGS_ZERO_BUSY ((__force gfp_t)8U) 267 267 #define XA_FLAGS_ALLOC_WRAPPED ((__force gfp_t)16U) 268 + #define XA_FLAGS_ACCOUNT ((__force gfp_t)32U) 268 269 #define XA_FLAGS_MARK(mark) ((__force gfp_t)((1U << __GFP_BITS_SHIFT) << \ 269 270 (__force unsigned)(mark))) 270 271
+12 -2
lib/idr.c
··· 228 228 { 229 229 struct radix_tree_iter iter; 230 230 void __rcu **slot; 231 + void *entry = NULL; 231 232 unsigned long base = idr->idr_base; 232 233 unsigned long id = *nextid; 233 234 234 235 id = (id < base) ? 0 : id - base; 235 - slot = radix_tree_iter_find(&idr->idr_rt, &iter, id); 236 + radix_tree_for_each_slot(slot, &idr->idr_rt, &iter, id) { 237 + entry = rcu_dereference_raw(*slot); 238 + if (!entry) 239 + continue; 240 + if (!xa_is_internal(entry)) 241 + break; 242 + if (slot != &idr->idr_rt.xa_head && !xa_is_retry(entry)) 243 + break; 244 + slot = radix_tree_iter_retry(&iter); 245 + } 236 246 if (!slot) 237 247 return NULL; 238 248 id = iter.index + base; ··· 251 241 return NULL; 252 242 253 243 *nextid = id; 254 - return rcu_dereference_raw(*slot); 244 + return entry; 255 245 } 256 246 EXPORT_SYMBOL(idr_get_next); 257 247
+38
lib/test_xarray.c
··· 38 38 return xa_store(xa, index, xa_mk_index(index), gfp); 39 39 } 40 40 41 + static void xa_insert_index(struct xarray *xa, unsigned long index) 42 + { 43 + XA_BUG_ON(xa, xa_insert(xa, index, xa_mk_index(index), 44 + GFP_KERNEL) != 0); 45 + } 46 + 41 47 static void xa_alloc_index(struct xarray *xa, unsigned long index, gfp_t gfp) 42 48 { 43 49 u32 id; ··· 342 336 XA_BUG_ON(xa, xa->xa_head != node); 343 337 xa_erase_index(xa, 0); 344 338 } 339 + } 340 + 341 + static noinline void check_insert(struct xarray *xa) 342 + { 343 + unsigned long i; 344 + 345 + for (i = 0; i < 1024; i++) { 346 + xa_insert_index(xa, i); 347 + XA_BUG_ON(xa, xa_load(xa, i - 1) != NULL); 348 + XA_BUG_ON(xa, xa_load(xa, i + 1) != NULL); 349 + xa_erase_index(xa, i); 350 + } 351 + 352 + for (i = 10; i < BITS_PER_LONG; i++) { 353 + xa_insert_index(xa, 1UL << i); 354 + XA_BUG_ON(xa, xa_load(xa, (1UL << i) - 1) != NULL); 355 + XA_BUG_ON(xa, xa_load(xa, (1UL << i) + 1) != NULL); 356 + xa_erase_index(xa, 1UL << i); 357 + 358 + xa_insert_index(xa, (1UL << i) - 1); 359 + XA_BUG_ON(xa, xa_load(xa, (1UL << i) - 2) != NULL); 360 + XA_BUG_ON(xa, xa_load(xa, 1UL << i) != NULL); 361 + xa_erase_index(xa, (1UL << i) - 1); 362 + } 363 + 364 + xa_insert_index(xa, ~0UL); 365 + XA_BUG_ON(xa, xa_load(xa, 0UL) != NULL); 366 + XA_BUG_ON(xa, xa_load(xa, ~1UL) != NULL); 367 + xa_erase_index(xa, ~0UL); 368 + 369 + XA_BUG_ON(xa, !xa_empty(xa)); 345 370 } 346 371 347 372 static noinline void check_cmpxchg(struct xarray *xa) ··· 1564 1527 check_xa_mark(&array); 1565 1528 check_xa_shrink(&array); 1566 1529 check_xas_erase(&array); 1530 + check_insert(&array); 1567 1531 check_cmpxchg(&array); 1568 1532 check_reserve(&array); 1569 1533 check_reserve(&xa0);
+10 -2
lib/xarray.c
··· 298 298 xas_destroy(xas); 299 299 return false; 300 300 } 301 + if (xas->xa->xa_flags & XA_FLAGS_ACCOUNT) 302 + gfp |= __GFP_ACCOUNT; 301 303 xas->xa_alloc = kmem_cache_alloc(radix_tree_node_cachep, gfp); 302 304 if (!xas->xa_alloc) 303 305 return false; ··· 327 325 xas_destroy(xas); 328 326 return false; 329 327 } 328 + if (xas->xa->xa_flags & XA_FLAGS_ACCOUNT) 329 + gfp |= __GFP_ACCOUNT; 330 330 if (gfpflags_allow_blocking(gfp)) { 331 331 xas_unlock_type(xas, lock_type); 332 332 xas->xa_alloc = kmem_cache_alloc(radix_tree_node_cachep, gfp); ··· 362 358 if (node) { 363 359 xas->xa_alloc = NULL; 364 360 } else { 365 - node = kmem_cache_alloc(radix_tree_node_cachep, 366 - GFP_NOWAIT | __GFP_NOWARN); 361 + gfp_t gfp = GFP_NOWAIT | __GFP_NOWARN; 362 + 363 + if (xas->xa->xa_flags & XA_FLAGS_ACCOUNT) 364 + gfp |= __GFP_ACCOUNT; 365 + 366 + node = kmem_cache_alloc(radix_tree_node_cachep, gfp); 367 367 if (!node) { 368 368 xas_set_err(xas, -ENOMEM); 369 369 return NULL;
+46
tools/testing/radix-tree/idr-test.c
··· 279 279 } 280 280 } 281 281 282 + DEFINE_IDR(find_idr); 283 + 284 + static void *idr_throbber(void *arg) 285 + { 286 + time_t start = time(NULL); 287 + int id = *(int *)arg; 288 + 289 + rcu_register_thread(); 290 + do { 291 + idr_alloc(&find_idr, xa_mk_value(id), id, id + 1, GFP_KERNEL); 292 + idr_remove(&find_idr, id); 293 + } while (time(NULL) < start + 10); 294 + rcu_unregister_thread(); 295 + 296 + return NULL; 297 + } 298 + 299 + void idr_find_test_1(int anchor_id, int throbber_id) 300 + { 301 + pthread_t throbber; 302 + time_t start = time(NULL); 303 + 304 + pthread_create(&throbber, NULL, idr_throbber, &throbber_id); 305 + 306 + BUG_ON(idr_alloc(&find_idr, xa_mk_value(anchor_id), anchor_id, 307 + anchor_id + 1, GFP_KERNEL) != anchor_id); 308 + 309 + do { 310 + int id = 0; 311 + void *entry = idr_get_next(&find_idr, &id); 312 + BUG_ON(entry != xa_mk_value(id)); 313 + } while (time(NULL) < start + 11); 314 + 315 + pthread_join(throbber, NULL); 316 + 317 + idr_remove(&find_idr, anchor_id); 318 + BUG_ON(!idr_is_empty(&find_idr)); 319 + } 320 + 321 + void idr_find_test(void) 322 + { 323 + idr_find_test_1(100000, 0); 324 + idr_find_test_1(0, 100000); 325 + } 326 + 282 327 void idr_checks(void) 283 328 { 284 329 unsigned long i; ··· 405 360 idr_u32_test(1); 406 361 idr_u32_test(0); 407 362 idr_align_test(&idr); 363 + idr_find_test(); 408 364 } 409 365 410 366 #define module_init(x)