summaryrefslogtreecommitdiff
path: root/tools/perf/scripts/python/bin/stackcollapse-record
diff options
context:
space:
mode:
authorQiliang Yuan <odys.yuan@gmail.com>2026-09-28 20:54:40 +0800
committerJan Kara <jack@suse.cz>2026-09-29 22:55:40 +0200
commit8b1534b6c47b6f85d3eaa1f169d2e298db19de24 (patch)
tree1b81a25a54b6b9c0279c98ba7a6807d1ab03f017 /tools/perf/scripts/python/bin/stackcollapse-record
parent1e2ef9f221e142ed19d874a71b2cae7fabbaf138 (diff)
downloadlinux-8b1534b6c47b6f85d3eaa1f169d2e298db19de24.tar.gz
linux-8b1534b6c47b6f85d3eaa1f169d2e298db19de24.zip
quota: fix shrinker scan budget accounting in dqcache_shrink_scan()
The dquot cache shrinker's count_objects() callback, dqcache_shrink_count(), reports the number of unused dquot objects via the DQST_FREE_DQUOTS percpu counter (through vfs_pressure_ratio()). do_shrink_slab() reads this count exactly once per invocation and derives a one-shot scan budget (total_scan) from it, then repeatedly calls scan_objects() in fixed-size batches until that budget is exhausted. dqcache_shrink_scan() never updates sc->nr_scanned, even though include/linux/shrinker.h documents that "the callee should track its actual progress" in that field. The function already decrements sc->nr_to_scan in place as it walks free_dquots, one per dquot destroyed, and its while loop exits immediately without touching sc->nr_to_scan at all when free_dquots is already empty. Because sc->nr_scanned defaults to sc->nr_to_scan before every call, do_shrink_slab() always believes a full batch was examined regardless of what actually happened, so it has no way to tell "there was nothing to do this pass" from "a full batch was scanned and none of it was freeable", and keeps calling scan_objects() until the original, one-shot total_scan budget computed from the percpu count is drained, even though free_dquots emptied out long before that budget was used up. Compute sc->nr_scanned from the difference between the nr_to_scan value on entry and the value left behind by the reclaim loop, and return SHRINK_STOP once that difference comes back as zero, since that only happens when free_dquots was already empty and no further calls in this reclaim pass can make progress. Tested on a loop-mounted ext4 image with the quota feature enabled: chown()ing several hundred files to distinct uid:gid pairs to populate allocated dquots, then triggering "echo 2 > /proc/sys/vm/drop_caches" to let them drop to zero references and become reclaimable, while using an ad hoc kprobe pair on dqcache_shrink_scan() (this shrinker has no dedicated tracepoints) to record sc->nr_to_scan on entry and the return value on exit: total scan_objects() calls with calls freed == 0 before this patch 12 5 (42%) after this patch 5 0 The last call in the "after" run returns SHRINK_STOP (0xffffffffffffffff) instead of a fifth zero-progress attempt. This is the same missing sc->nr_scanned accounting already fixed in the analogous ext4 extents_status shrinker and the jbd2 checkpoint shrinker; dqcache_shrink_scan() was found by auditing every shrinker in the tree whose count_objects() reads a percpu_counter (the precondition for count_objects() to report a stale, still-positive value after the reclaimable list has actually drained), while ruling out the much larger set of shrinkers built on the exact list_lru atomic counters, which cannot observe this kind of staleness. Signed-off-by: Qiliang Yuan <odys.yuan@gmail.com> Link: https://patch.msgid.link/20260928-fix-dquot-shrink-scan-nr-scanned-v1-1-789c661c9dd6@gmail.com Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'tools/perf/scripts/python/bin/stackcollapse-record')
0 files changed, 0 insertions, 0 deletions