lkml.org 
[lkml]   [2023]   [May]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    SubjectRe: [RFC PATCH 3/3] cgroup: Do not take css_set_lock in cgroup_show_path
    From
    On 5/2/23 09:38, Michal Koutný wrote:
    > /proc/$pid/mountinfo may accumulate lots of entries (causing frequent
    > re-reads of whole file) or lots cgroupfs entries alone.
    > The cgroupfs entries rendered with cgroup_show_path() may increase/be
    > subject of css_set_lock contention causing further slowdown -- not only
    > mountinfo rendering but any other css_set_lock user.
    >
    > We leverage the fact that mountinfo reading happens with namespace_sem
    > taken and hierarchy roots thus cannot be freed concurrently.
    >
    > There are three relevant nodes for each cgroupfs entry:
    >
    > R ... cgroup hierarchy root
    > M ... mount root
    > C ... reader's cgroup NS root
    >
    > mountinfo is supposed to show path from C to M.
    >
    > Current's css_set (and linked root cgroups) are stable under
    > namespace_sem, therefore current_cgns_cgroup_from_root() doesn't need
    > css_set_lock.
    >
    > When the path is assembled in kernfs_path_from_node(), we know that:
    > - C kernfs_node is (transitively) pinned via current->nsproxy,
    > - M kernfs_node is pinned thanks to namespace_sem,
    > - path C to M is pinned via child->parent references (this holds also
    > when C and M are in distinct subtrees).
    >
    > Streamline mountinfo rendering a bit by relieving css_set_lock and add
    > careful notes about that.
    >
    > Signed-off-by: Michal Koutný <mkoutny@suse.com>
    > ---
    > kernel/cgroup/cgroup.c | 12 +++++++-----
    > 1 file changed, 7 insertions(+), 5 deletions(-)
    >
    > diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
    > index 32d693a797b9..e2ec6f0028be 100644
    > --- a/kernel/cgroup/cgroup.c
    > +++ b/kernel/cgroup/cgroup.c
    > @@ -1407,12 +1407,18 @@ static inline struct cgroup *__cset_cgroup_from_root(struct css_set *cset,
    > struct cgroup *res_cgroup = NULL;
    >
    > if (cset == &init_css_set) {
    > + /* callers must ensure root stability */
    > res_cgroup = &root->cgrp;
    > } else if (root == &cgrp_dfl_root) {
    > res_cgroup = cset->dfl_cgrp;
    > } else {
    > struct cgrp_cset_link *link;
    > - lockdep_assert_held(&css_set_lock);
    > + /* cset's cgroups are pinned unless they are root cgroups that
    > + * were unmounted. We look at links to !cgrp_dfl_root
    > + * cgroup_root, either lock ensures the list is not mutated
    > + */
    > + lockdep_assert(lockdep_is_held(&css_set_lock) ||
    > + lockdep_is_held_type(&namespace_sem, -1));
    Again lockdep_is_held(&namespace_sem) is good enough.

    >
    > list_for_each_entry(link, &cset->cgrp_links, cgrp_link) {
    > struct cgroup *c = link->cgrp;
    > @@ -1438,8 +1444,6 @@ current_cgns_cgroup_from_root(struct cgroup_root *root)
    > struct cgroup *res = NULL;
    > struct css_set *cset;
    >
    > - lockdep_assert_held(&css_set_lock);
    > -
    > /* namespace_sem ensures `root` stability on unmount */
    > lockdep_assert(lockdep_is_held_type(&namespace_sem, -1));
    >
    > @@ -1905,10 +1909,8 @@ int cgroup_show_path(struct seq_file *sf, struct kernfs_node *kf_node,
    > if (!buf)
    > return -ENOMEM;
    >
    > - spin_lock_irq(&css_set_lock);
    > ns_cgroup = current_cgns_cgroup_from_root(kf_cgroot);
    > len = kernfs_path_from_node(kf_node, ns_cgroup->kn, buf, PATH_MAX);
    > - spin_unlock_irq(&css_set_lock);
    >
    > if (len >= PATH_MAX)
    > len = -ERANGE;
    Cheers,
    Longman

    \
     
     \ /
      Last update: 2023-05-02 21:57    [W:3.188 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site