lkml.org 
[lkml]   [2021]   [Nov]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    Subject[PATCH v4 0/4] Deterministic charging of shared memory
    From
    Problem:
    Currently shared memory is charged to the memcg of the allocating
    process. This makes memory usage of processes accessing shared memory
    a bit unpredictable since whichever process accesses the memory first
    will get charged. We have a number of use cases where our userspace
    would like deterministic charging of shared memory:

    1. System services allocating memory for client jobs:
    We have services (namely a network access service[1]) that provide
    functionality for clients running on the machine and allocate memory
    to carry out these services. The memory usage of these services
    depends on the number of jobs running on the machine and the nature of
    the requests made to the service, which makes the memory usage of
    these services hard to predict and thus hard to limit via memory.max.
    These system services would like a way to allocate memory and instruct
    the kernel to charge this memory to the client’s memcg.

    2. Shared filesystem between subtasks of a large job
    Our infrastructure has large meta jobs such as kubernetes which spawn
    multiple subtasks which share a tmpfs mount. These jobs and its
    subtasks use that tmpfs mount for various purposes such as data
    sharing or persistent data between the subtask restarts. In kubernetes
    terminology, the meta job is similar to pods and subtasks are
    containers under pods. We want the shared memory to be
    deterministically charged to the kubernetes's pod and independent to
    the lifetime of containers under the pod.

    3. Shared libraries and language runtimes shared between independent jobs.
    We’d like to optimize memory usage on the machine by sharing libraries
    and language runtimes of many of the processes running on our machines
    in separate memcgs. This produces a side effect that one job may be
    unlucky to be the first to access many of the libraries and may get
    oom killed as all the cached files get charged to it.

    Design:
    My rough proposal to solve this problem is to simply add a
    ‘memcg=/path/to/memcg’ mount option for filesystems:
    directing all the memory of the file system to be ‘remote charged’ to
    cgroup provided by that memcg= option.

    Caveats:

    1. One complication to address is the behavior when the target memcg
    hits its memory.max limit because of remote charging. In this case the
    oom-killer will be invoked, but the oom-killer may not find anything
    to kill in the target memcg being charged. Thera are a number of considerations
    in this case:

    1. It's not great to kill the allocating process since the allocating process
    is not running in the memcg under oom, and killing it will not free memory
    in the memcg under oom.
    2. Pagefaults may hit the memcg limit, and we need to handle the pagefault
    somehow. If not, the process will forever loop the pagefault in the upstream
    kernel.

    In this case, I propose simply failing the remote charge and returning an ENOSPC
    to the caller. This will cause will cause the process executing the remote
    charge to get an ENOSPC in non-pagefault paths, and get a SIGBUS on the pagefault
    path. This will be documented behavior of remote charging, and this feature is
    opt-in. Users can:
    - Not opt-into the feature if they want.
    - Opt-into the feature and accept the risk of received ENOSPC or SIGBUS and
    abort if they desire.
    - Gracefully handle any resulting ENOSPC or SIGBUS errors and continue their
    operation without executing the remote charge if possible.

    2. Only processes allowed the enter cgroup at mount time can mount a
    tmpfs with memcg=<cgroup>. This is to prevent intential DoS of random cgroups
    on the machine. However, once a filesysetem is mounted with memcg=<cgroup>, any
    process with write access to this mount point will be able to charge memory to
    <cgroup>. This is largely a non-issue because in configurations where there is
    untrusted code running on the machine, mount point access needs to be
    restricted to the intended users only regardless of whether the mount point
    memory is deterministly charged or not.

    [1] https://research.google/pubs/pub48630

    Cc: Jonathan Corbet <corbet@lwn.net>
    Cc: Alexander Viro <viro@zeniv.linux.org.uk>
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Cc: Johannes Weiner <hannes@cmpxchg.org>
    Cc: Michal Hocko <mhocko@kernel.org>
    Cc: Vladimir Davydov <vdavydov.dev@gmail.com>
    Cc: Hugh Dickins <hughd@google.com>
    Cc: Shuah Khan <shuah@kernel.org>
    Cc: Shakeel Butt <shakeelb@google.com>
    Cc: Greg Thelen <gthelen@google.com>
    Cc: Dave Chinner <david@fromorbit.com>
    Cc: Matthew Wilcox <willy@infradead.org>
    Cc: Roman Gushchin <guro@fb.com>
    Cc: Theodore Ts'o <tytso@mit.edu>
    Cc: linux-kernel@vger.kernel.org
    Cc: linux-fsdevel@vger.kernel.org
    Cc: linux-mm@kvack.org

    Mina Almasry (4):
    mm: support deterministic memory charging of filesystems
    mm/oom: handle remote ooms
    mm, shmem: add filesystem memcg= option documentation
    mm, shmem, selftests: add tmpfs memcg= mount option tests

    Documentation/filesystems/tmpfs.rst | 28 ++++
    fs/fs_context.c | 27 ++++
    fs/proc_namespace.c | 4 +
    fs/super.c | 9 ++
    include/linux/fs.h | 5 +
    include/linux/fs_context.h | 2 +
    include/linux/memcontrol.h | 38 +++++
    mm/filemap.c | 2 +-
    mm/khugepaged.c | 3 +-
    mm/memcontrol.c | 171 ++++++++++++++++++++++
    mm/oom_kill.c | 9 ++
    mm/shmem.c | 3 +-
    tools/testing/selftests/vm/.gitignore | 1 +
    tools/testing/selftests/vm/mmap_write.c | 103 +++++++++++++
    tools/testing/selftests/vm/tmpfs-memcg.sh | 116 +++++++++++++++
    15 files changed, 518 insertions(+), 3 deletions(-)
    create mode 100644 tools/testing/selftests/vm/mmap_write.c
    create mode 100755 tools/testing/selftests/vm/tmpfs-memcg.sh

    --
    2.34.0.rc2.393.gf8c9666880-goog

    \
     
     \ /
      Last update: 2021-11-20 05:51    [W:3.232 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site