On Thu, Feb 10, 2022 at 10:49 PM Shakeel Butt <shakeelb@xxxxxxxxxx> wrote: > > The high limit is used to throttle the workload without invoking the > oom-killer. Recently we tried to use the high limit to right size our > internal workloads. More specifically dynamically adjusting the limits > of the workload without letting the workload get oom-killed. However due > to the limitation of the implementation of high limit enforcement, we > observed the mechanism fails for some real workloads. > > The high limit is enforced on return-to-userspace i.e. the kernel let > the usage goes over the limit and when the execution returns to > userspace, the high reclaim is triggered and the process can get > throttled as well. However this mechanism fails for workloads which do > large allocations in a single kernel entry e.g. applications that > mlock() a large chunk of memory in a single syscall. Such applications > bypass the high limit and can trigger the oom-killer. > > To make high limit enforcement more robust, this patch makes the limit > enforcement synchronous only if the accumulated overcharge becomes > larger than MEMCG_CHARGE_BATCH. So, most of the allocations would still > be throttled on the return-to-userspace path but only the extreme > allocations which accumulates large amount of overcharge without > returning to the userspace will be throttled synchronously. The value > MEMCG_CHARGE_BATCH is a bit arbitrary but most of other places in the > memcg codebase uses this constant therefore for now uses the same one. > > Signed-off-by: Shakeel Butt <shakeelb@xxxxxxxxxx> Any comments or concerns on this patch? Otherwise I would ask Andrew to add this series into the mm tree. > --- > Changes since v1: > - Based on Roman's comment simply the sync enforcement and only target > the extreme cases. > > mm/memcontrol.c | 5 +++++ > 1 file changed, 5 insertions(+) > > diff --git a/mm/memcontrol.c b/mm/memcontrol.c > index 292b0b99a2c7..0da4be4798e7 100644 > --- a/mm/memcontrol.c > +++ b/mm/memcontrol.c > @@ -2703,6 +2703,11 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask, > } > } while ((memcg = parent_mem_cgroup(memcg))); > > + if (current->memcg_nr_pages_over_high > MEMCG_CHARGE_BATCH && > + !(current->flags & PF_MEMALLOC) && > + gfpflags_allow_blocking(gfp_mask)) { > + mem_cgroup_handle_over_high(); > + } > return 0; > } > > -- > 2.35.1.265.g69c8d7142f-goog >