Re: [PATCH 4/5] mm: workingset: move the stats flush into workingset_test_recent()

From: Yosry Ahmed
Date: Thu Sep 21 2023 - 17:27:34 EST


On Thu, Sep 21, 2023 at 4:06 AM kernel test robot <lkp@xxxxxxxxx> wrote:
>
> Hi Yosry,
>
> kernel test robot noticed the following build errors:
>
> [auto build test ERROR on akpm-mm/mm-everything]
>
> url: https://github.com/intel-lab-lkp/linux/commits/Yosry-Ahmed/mm-memcg-change-flush_next_time-to-flush_last_time/20230921-161246
> base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
> patch link: https://lore.kernel.org/r/20230921081057.3440885-5-yosryahmed%40google.com
> patch subject: [PATCH 4/5] mm: workingset: move the stats flush into workingset_test_recent()
> config: powerpc-allnoconfig (https://download.01.org/0day-ci/archive/20230921/202309211829.Efuqg8NE-lkp@xxxxxxxxx/config)
> compiler: powerpc-linux-gcc (GCC) 13.2.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230921/202309211829.Efuqg8NE-lkp@xxxxxxxxx/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@xxxxxxxxx>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202309211829.Efuqg8NE-lkp@xxxxxxxxx/
>
> All errors (new ones prefixed by >>):
>
> mm/workingset.c: In function 'workingset_test_recent':
> >> mm/workingset.c:461:32: error: invalid use of undefined type 'struct mem_cgroup'
> 461 | css_get(&eviction_memcg->css);
> | ^~
>

Ah yes, I cannot dereference the memcg pointer here. I think we want
mem_cgroup_get_from_id (a getter version of mem_cgroup_from_id) or
mem_cgroup_get (similar to mem_cgroup_put) to have stubs when
!CONFIG_MEMCG. I will do this change in the next version, but I'll
wait for feedback on this version first.

>
> vim +461 mm/workingset.c
>
> 405
> 406 /**
> 407 * workingset_test_recent - tests if the shadow entry is for a folio that was
> 408 * recently evicted. Also fills in @workingset with the value unpacked from
> 409 * shadow.
> 410 * @shadow: the shadow entry to be tested.
> 411 * @file: whether the corresponding folio is from the file lru.
> 412 * @workingset: where the workingset value unpacked from shadow should
> 413 * be stored.
> 414 *
> 415 * Return: true if the shadow is for a recently evicted folio; false otherwise.
> 416 */
> 417 bool workingset_test_recent(void *shadow, bool file, bool *workingset)
> 418 {
> 419 struct mem_cgroup *eviction_memcg;
> 420 struct lruvec *eviction_lruvec;
> 421 unsigned long refault_distance;
> 422 unsigned long workingset_size;
> 423 unsigned long refault;
> 424 int memcgid;
> 425 struct pglist_data *pgdat;
> 426 unsigned long eviction;
> 427
> 428 rcu_read_lock();
> 429
> 430 if (lru_gen_enabled()) {
> 431 bool recent = lru_gen_test_recent(shadow, file,
> 432 &eviction_lruvec, &eviction,
> 433 workingset);
> 434 rcu_read_unlock();
> 435 return recent;
> 436 }
> 437
> 438 unpack_shadow(shadow, &memcgid, &pgdat, &eviction, workingset);
> 439 eviction <<= bucket_order;
> 440
> 441 /*
> 442 * Look up the memcg associated with the stored ID. It might
> 443 * have been deleted since the folio's eviction.
> 444 *
> 445 * Note that in rare events the ID could have been recycled
> 446 * for a new cgroup that refaults a shared folio. This is
> 447 * impossible to tell from the available data. However, this
> 448 * should be a rare and limited disturbance, and activations
> 449 * are always speculative anyway. Ultimately, it's the aging
> 450 * algorithm's job to shake out the minimum access frequency
> 451 * for the active cache.
> 452 *
> 453 * XXX: On !CONFIG_MEMCG, this will always return NULL; it
> 454 * would be better if the root_mem_cgroup existed in all
> 455 * configurations instead.
> 456 */
> 457 eviction_memcg = mem_cgroup_from_id(memcgid);
> 458 if (!mem_cgroup_disabled() && !eviction_memcg)
> 459 return false;
> 460
> > 461 css_get(&eviction_memcg->css);
> 462 rcu_read_unlock();
> 463
> 464 /* Flush stats (and potentially sleep) outside the RCU read section */
> 465 mem_cgroup_flush_stats_ratelimited();
> 466
> 467 eviction_lruvec = mem_cgroup_lruvec(eviction_memcg, pgdat);
> 468 refault = atomic_long_read(&eviction_lruvec->nonresident_age);
> 469
> 470 /*
> 471 * Calculate the refault distance
> 472 *
> 473 * The unsigned subtraction here gives an accurate distance
> 474 * across nonresident_age overflows in most cases. There is a
> 475 * special case: usually, shadow entries have a short lifetime
> 476 * and are either refaulted or reclaimed along with the inode
> 477 * before they get too old. But it is not impossible for the
> 478 * nonresident_age to lap a shadow entry in the field, which
> 479 * can then result in a false small refault distance, leading
> 480 * to a false activation should this old entry actually
> 481 * refault again. However, earlier kernels used to deactivate
> 482 * unconditionally with *every* reclaim invocation for the
> 483 * longest time, so the occasional inappropriate activation
> 484 * leading to pressure on the active list is not a problem.
> 485 */
> 486 refault_distance = (refault - eviction) & EVICTION_MASK;
> 487
> 488 /*
> 489 * Compare the distance to the existing workingset size. We
> 490 * don't activate pages that couldn't stay resident even if
> 491 * all the memory was available to the workingset. Whether
> 492 * workingset competition needs to consider anon or not depends
> 493 * on having free swap space.
> 494 */
> 495 workingset_size = lruvec_page_state(eviction_lruvec, NR_ACTIVE_FILE);
> 496 if (!file) {
> 497 workingset_size += lruvec_page_state(eviction_lruvec,
> 498 NR_INACTIVE_FILE);
> 499 }
> 500 if (mem_cgroup_get_nr_swap_pages(eviction_memcg) > 0) {
> 501 workingset_size += lruvec_page_state(eviction_lruvec,
> 502 NR_ACTIVE_ANON);
> 503 if (file) {
> 504 workingset_size += lruvec_page_state(eviction_lruvec,
> 505 NR_INACTIVE_ANON);
> 506 }
> 507 }
> 508
> 509 mem_cgroup_put(eviction_memcg);
> 510 return refault_distance <= workingset_size;
> 511 }
> 512
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki