diff options
| author | Thomas Hellström <thomas.hellstrom@linux.intel.com> | 2026-07-25 12:00:33 +0200 |
|---|---|---|
| committer | Maarten Lankhorst <dev@lankhorst.se> | 2026-08-06 23:38:03 +0200 |
| commit | 747c4bb450adcd8b99d3543448419e1952755832 (patch) | |
| tree | 70eced84d02c57543ce5f4e889527b3c1a736d8a /include/linux | |
| parent | e11640b9cea4e0c448df1d31b9e950fa52cf19af (diff) | |
cgroup/dmem: Add reclaim callback for lowering max below current usage
Add an optional reclaim callback to struct dmem_cgroup_region. When
dmem.max is set below the current usage of a cgroup pool, the new limit
is applied immediately (so that concurrent allocations are throttled
while reclaim is in progress) and then the driver is asked to evict
memory to bring usage back below the limit.
Reclaim is attempted up to a bounded number of times. No error is
returned to userspace if usage remains above the limit after reclaim,
and a pending signal will abort the reclaim loop early. This matches
the behavior of memory.max in the memory cgroup controller.
Also honor O_NONBLOCK so that if that flag is set during the
max value write, no reclaim is initiated. The idea is to avoid
charging the reclaim cost to the writer of the max value.
v2:
- Write max before reclaim is attempted (Maarten)
- Let signals abort the reclaim without error (Maarten)
- If a new max value is written with the O_NONBLOCK flag,
reclaim is not attempted (Maarten)
- Extract region from the pool parameter rather than
passing it explicitly to set_resource_xxx().
v3:
- Use an rw_semaphore (unregister_sem) to protect reclaim callbacks
against concurrent region unregistration: readers (reclaim) hold the
read side; dmem_cgroup_unregister_region() takes the write side to
drain in-flight callbacks before returning. (Sashiko-bot)
v5:
- Rebased on the introduction of struct dmem_cgroup_init.
- Use nonblock=true in reset_all_resource_limits() to avoid sleeping
inside rcu_read_lock() in dmemcs_offline(). (Sashiko-bot)
- Compare usage against the truncated limit value stored in cnt.max,
not the original u64. (Sashiko-bot)
- Use a DMEM_MAX_RECLAIM_RETRIES (16) retry budget instead of 5, matching
the memcg controller's MAX_RECLAIM_RETRIES. Only -ENOSPC (no progress)
counts against the retry budget; other errors terminate the loop
immediately.
v6:
- Fix dmem_cgroup_ops->reclaim docstring: -ENOSPC does not stop reclaim
immediately but is retried up to DMEM_MAX_RECLAIM_RETRIES times; only
other negative errors terminate the loop. (Sashiko-bot)
v7:
- Replace the per-region rw_semaphore with a static SRCU domain
(dmemcg_srcu). SRCU is a better fit than rwsem for this use: it
avoids the per-region lock overhead on every reclaim call, and
synchronize_srcu() at unregister time is a rare operation. (Maarten)
- Trim in-function comments to focus on what rather than how.
Assisted-by: GitHub_Copilot:claude-sonnet-4.6
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Tested-by: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
Link: https://patch.msgid.link/20260725100036.2372-4-thomas.hellstrom@linux.intel.com
Signed-off-by: Maarten Lankhorst <dev@lankhorst.se>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/cgroup_dmem.h | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/include/linux/cgroup_dmem.h b/include/linux/cgroup_dmem.h index 0575bab38d24..c6cad9501770 100644 --- a/include/linux/cgroup_dmem.h +++ b/include/linux/cgroup_dmem.h @@ -15,11 +15,33 @@ struct dmem_cgroup_pool_state; struct dmem_cgroup_region; /** + * struct dmem_cgroup_ops - Operations for a dmem cgroup region. + * @reclaim: Optional callback invoked when dmem.max is set below the current + * usage of a pool. The driver should attempt to free at least + * @target_bytes from @pool. May be called multiple times if usage + * remains above the limit after returning. + * + * Return: 0 if some progress was made (even if less than + * @target_bytes was freed), -ENOSPC if no progress could be made + * (the caller will retry up to a bounded number of times), or + * another negative error code if a fatal error occurred (stops + * further reclaim attempts immediately). + */ +struct dmem_cgroup_ops { + int (*reclaim)(struct dmem_cgroup_pool_state *pool, + u64 target_bytes, void *priv); +}; + +/** * struct dmem_cgroup_init - Initialization parameters for a dmem cgroup region. * @size: Size of the region in bytes. + * @ops: Optional operations for this region. May be NULL. + * @reclaim_priv: Opaque pointer passed to @ops->reclaim. May be NULL. */ struct dmem_cgroup_init { u64 size; + const struct dmem_cgroup_ops *ops; + void *reclaim_priv; }; #if IS_ENABLED(CONFIG_CGROUP_DMEM) |
