Skip to content

Commit a312a8c

Browse files
committed
Merge tag 'cgroup-for-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup updates from Tejun Heo: "Nothing too interesting: - Add CONFIG_DEBUG_GROUP_REF which makes cgroup refcnt operations kprobable - A couple cpuset optimizations - Other misc changes including doc and test updates" * tag 'cgroup-for-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: cgroup: remove rcu_read_lock()/rcu_read_unlock() in critical section of spin_lock_irq() cgroup/cpuset: Improve cpuset_css_alloc() description kselftest/cgroup: Add cleanup() to test_cpuset_prs.sh cgroup/cpuset: Optimize cpuset_attach() on v2 cgroup/cpuset: Skip spread flags update on v2 kselftest/cgroup: Fix gathering number of CPUs cgroup: cgroup refcnt functions should be exported when CONFIG_DEBUG_CGROUP_REF cgroup: Implement DEBUG_CGROUP_REF
2 parents bf57ae2 + 674b745 commit a312a8c

File tree

6 files changed

+181
-98
lines changed

6 files changed

+181
-98
lines changed

include/linux/cgroup.h

Lines changed: 13 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -310,71 +310,24 @@ void css_task_iter_end(struct css_task_iter *it);
310310
* Inline functions.
311311
*/
312312

313+
#ifdef CONFIG_DEBUG_CGROUP_REF
314+
void css_get(struct cgroup_subsys_state *css);
315+
void css_get_many(struct cgroup_subsys_state *css, unsigned int n);
316+
bool css_tryget(struct cgroup_subsys_state *css);
317+
bool css_tryget_online(struct cgroup_subsys_state *css);
318+
void css_put(struct cgroup_subsys_state *css);
319+
void css_put_many(struct cgroup_subsys_state *css, unsigned int n);
320+
#else
321+
#define CGROUP_REF_FN_ATTRS static inline
322+
#define CGROUP_REF_EXPORT(fn)
323+
#include <linux/cgroup_refcnt.h>
324+
#endif
325+
313326
static inline u64 cgroup_id(const struct cgroup *cgrp)
314327
{
315328
return cgrp->kn->id;
316329
}
317330

318-
/**
319-
* css_get - obtain a reference on the specified css
320-
* @css: target css
321-
*
322-
* The caller must already have a reference.
323-
*/
324-
static inline void css_get(struct cgroup_subsys_state *css)
325-
{
326-
if (!(css->flags & CSS_NO_REF))
327-
percpu_ref_get(&css->refcnt);
328-
}
329-
330-
/**
331-
* css_get_many - obtain references on the specified css
332-
* @css: target css
333-
* @n: number of references to get
334-
*
335-
* The caller must already have a reference.
336-
*/
337-
static inline void css_get_many(struct cgroup_subsys_state *css, unsigned int n)
338-
{
339-
if (!(css->flags & CSS_NO_REF))
340-
percpu_ref_get_many(&css->refcnt, n);
341-
}
342-
343-
/**
344-
* css_tryget - try to obtain a reference on the specified css
345-
* @css: target css
346-
*
347-
* Obtain a reference on @css unless it already has reached zero and is
348-
* being released. This function doesn't care whether @css is on or
349-
* offline. The caller naturally needs to ensure that @css is accessible
350-
* but doesn't have to be holding a reference on it - IOW, RCU protected
351-
* access is good enough for this function. Returns %true if a reference
352-
* count was successfully obtained; %false otherwise.
353-
*/
354-
static inline bool css_tryget(struct cgroup_subsys_state *css)
355-
{
356-
if (!(css->flags & CSS_NO_REF))
357-
return percpu_ref_tryget(&css->refcnt);
358-
return true;
359-
}
360-
361-
/**
362-
* css_tryget_online - try to obtain a reference on the specified css if online
363-
* @css: target css
364-
*
365-
* Obtain a reference on @css if it's online. The caller naturally needs
366-
* to ensure that @css is accessible but doesn't have to be holding a
367-
* reference on it - IOW, RCU protected access is good enough for this
368-
* function. Returns %true if a reference count was successfully obtained;
369-
* %false otherwise.
370-
*/
371-
static inline bool css_tryget_online(struct cgroup_subsys_state *css)
372-
{
373-
if (!(css->flags & CSS_NO_REF))
374-
return percpu_ref_tryget_live(&css->refcnt);
375-
return true;
376-
}
377-
378331
/**
379332
* css_is_dying - test whether the specified css is dying
380333
* @css: target css
@@ -395,31 +348,6 @@ static inline bool css_is_dying(struct cgroup_subsys_state *css)
395348
return !(css->flags & CSS_NO_REF) && percpu_ref_is_dying(&css->refcnt);
396349
}
397350

398-
/**
399-
* css_put - put a css reference
400-
* @css: target css
401-
*
402-
* Put a reference obtained via css_get() and css_tryget_online().
403-
*/
404-
static inline void css_put(struct cgroup_subsys_state *css)
405-
{
406-
if (!(css->flags & CSS_NO_REF))
407-
percpu_ref_put(&css->refcnt);
408-
}
409-
410-
/**
411-
* css_put_many - put css references
412-
* @css: target css
413-
* @n: number of references to put
414-
*
415-
* Put references obtained via css_get() and css_tryget_online().
416-
*/
417-
static inline void css_put_many(struct cgroup_subsys_state *css, unsigned int n)
418-
{
419-
if (!(css->flags & CSS_NO_REF))
420-
percpu_ref_put_many(&css->refcnt, n);
421-
}
422-
423351
static inline void cgroup_get(struct cgroup *cgrp)
424352
{
425353
css_get(&cgrp->self);

include/linux/cgroup_refcnt.h

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* css_get - obtain a reference on the specified css
3+
* @css: target css
4+
*
5+
* The caller must already have a reference.
6+
*/
7+
CGROUP_REF_FN_ATTRS
8+
void css_get(struct cgroup_subsys_state *css)
9+
{
10+
if (!(css->flags & CSS_NO_REF))
11+
percpu_ref_get(&css->refcnt);
12+
}
13+
CGROUP_REF_EXPORT(css_get)
14+
15+
/**
16+
* css_get_many - obtain references on the specified css
17+
* @css: target css
18+
* @n: number of references to get
19+
*
20+
* The caller must already have a reference.
21+
*/
22+
CGROUP_REF_FN_ATTRS
23+
void css_get_many(struct cgroup_subsys_state *css, unsigned int n)
24+
{
25+
if (!(css->flags & CSS_NO_REF))
26+
percpu_ref_get_many(&css->refcnt, n);
27+
}
28+
CGROUP_REF_EXPORT(css_get_many)
29+
30+
/**
31+
* css_tryget - try to obtain a reference on the specified css
32+
* @css: target css
33+
*
34+
* Obtain a reference on @css unless it already has reached zero and is
35+
* being released. This function doesn't care whether @css is on or
36+
* offline. The caller naturally needs to ensure that @css is accessible
37+
* but doesn't have to be holding a reference on it - IOW, RCU protected
38+
* access is good enough for this function. Returns %true if a reference
39+
* count was successfully obtained; %false otherwise.
40+
*/
41+
CGROUP_REF_FN_ATTRS
42+
bool css_tryget(struct cgroup_subsys_state *css)
43+
{
44+
if (!(css->flags & CSS_NO_REF))
45+
return percpu_ref_tryget(&css->refcnt);
46+
return true;
47+
}
48+
CGROUP_REF_EXPORT(css_tryget)
49+
50+
/**
51+
* css_tryget_online - try to obtain a reference on the specified css if online
52+
* @css: target css
53+
*
54+
* Obtain a reference on @css if it's online. The caller naturally needs
55+
* to ensure that @css is accessible but doesn't have to be holding a
56+
* reference on it - IOW, RCU protected access is good enough for this
57+
* function. Returns %true if a reference count was successfully obtained;
58+
* %false otherwise.
59+
*/
60+
CGROUP_REF_FN_ATTRS
61+
bool css_tryget_online(struct cgroup_subsys_state *css)
62+
{
63+
if (!(css->flags & CSS_NO_REF))
64+
return percpu_ref_tryget_live(&css->refcnt);
65+
return true;
66+
}
67+
CGROUP_REF_EXPORT(css_tryget_online)
68+
69+
/**
70+
* css_put - put a css reference
71+
* @css: target css
72+
*
73+
* Put a reference obtained via css_get() and css_tryget_online().
74+
*/
75+
CGROUP_REF_FN_ATTRS
76+
void css_put(struct cgroup_subsys_state *css)
77+
{
78+
if (!(css->flags & CSS_NO_REF))
79+
percpu_ref_put(&css->refcnt);
80+
}
81+
CGROUP_REF_EXPORT(css_put)
82+
83+
/**
84+
* css_put_many - put css references
85+
* @css: target css
86+
* @n: number of references to put
87+
*
88+
* Put references obtained via css_get() and css_tryget_online().
89+
*/
90+
CGROUP_REF_FN_ATTRS
91+
void css_put_many(struct cgroup_subsys_state *css, unsigned int n)
92+
{
93+
if (!(css->flags & CSS_NO_REF))
94+
percpu_ref_put_many(&css->refcnt, n);
95+
}
96+
CGROUP_REF_EXPORT(css_put_many)

kernel/cgroup/cgroup.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ static int cgroup_addrm_files(struct cgroup_subsys_state *css,
248248
struct cgroup *cgrp, struct cftype cfts[],
249249
bool is_add);
250250

251+
#ifdef CONFIG_DEBUG_CGROUP_REF
252+
#define CGROUP_REF_FN_ATTRS noinline
253+
#define CGROUP_REF_EXPORT(fn) EXPORT_SYMBOL_GPL(fn);
254+
#include <linux/cgroup_refcnt.h>
255+
#endif
256+
251257
/**
252258
* cgroup_ssid_enabled - cgroup subsys enabled test by subsys ID
253259
* @ssid: subsys ID of interest
@@ -2860,14 +2866,12 @@ int cgroup_migrate(struct task_struct *leader, bool threadgroup,
28602866
* take an rcu_read_lock.
28612867
*/
28622868
spin_lock_irq(&css_set_lock);
2863-
rcu_read_lock();
28642869
task = leader;
28652870
do {
28662871
cgroup_migrate_add_task(task, mgctx);
28672872
if (!threadgroup)
28682873
break;
28692874
} while_each_thread(leader, task);
2870-
rcu_read_unlock();
28712875
spin_unlock_irq(&css_set_lock);
28722876

28732877
return cgroup_migrate_execute(mgctx);

kernel/cgroup/cpuset.c

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -550,11 +550,15 @@ static void guarantee_online_mems(struct cpuset *cs, nodemask_t *pmask)
550550
/*
551551
* update task's spread flag if cpuset's page/slab spread flag is set
552552
*
553-
* Call with callback_lock or cpuset_rwsem held.
553+
* Call with callback_lock or cpuset_rwsem held. The check can be skipped
554+
* if on default hierarchy.
554555
*/
555-
static void cpuset_update_task_spread_flag(struct cpuset *cs,
556+
static void cpuset_update_task_spread_flags(struct cpuset *cs,
556557
struct task_struct *tsk)
557558
{
559+
if (cgroup_subsys_on_dfl(cpuset_cgrp_subsys))
560+
return;
561+
558562
if (is_spread_page(cs))
559563
task_set_spread_page(tsk);
560564
else
@@ -2153,7 +2157,7 @@ static void update_tasks_flags(struct cpuset *cs)
21532157

21542158
css_task_iter_start(&cs->css, 0, &it);
21552159
while ((task = css_task_iter_next(&it)))
2156-
cpuset_update_task_spread_flag(cs, task);
2160+
cpuset_update_task_spread_flags(cs, task);
21572161
css_task_iter_end(&it);
21582162
}
21592163

@@ -2509,12 +2513,28 @@ static void cpuset_attach(struct cgroup_taskset *tset)
25092513
struct cgroup_subsys_state *css;
25102514
struct cpuset *cs;
25112515
struct cpuset *oldcs = cpuset_attach_old_cs;
2516+
bool cpus_updated, mems_updated;
25122517

25132518
cgroup_taskset_first(tset, &css);
25142519
cs = css_cs(css);
25152520

25162521
lockdep_assert_cpus_held(); /* see cgroup_attach_lock() */
25172522
percpu_down_write(&cpuset_rwsem);
2523+
cpus_updated = !cpumask_equal(cs->effective_cpus,
2524+
oldcs->effective_cpus);
2525+
mems_updated = !nodes_equal(cs->effective_mems, oldcs->effective_mems);
2526+
2527+
/*
2528+
* In the default hierarchy, enabling cpuset in the child cgroups
2529+
* will trigger a number of cpuset_attach() calls with no change
2530+
* in effective cpus and mems. In that case, we can optimize out
2531+
* by skipping the task iteration and update.
2532+
*/
2533+
if (cgroup_subsys_on_dfl(cpuset_cgrp_subsys) &&
2534+
!cpus_updated && !mems_updated) {
2535+
cpuset_attach_nodemask_to = cs->effective_mems;
2536+
goto out;
2537+
}
25182538

25192539
guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
25202540

@@ -2530,14 +2550,19 @@ static void cpuset_attach(struct cgroup_taskset *tset)
25302550
WARN_ON_ONCE(set_cpus_allowed_ptr(task, cpus_attach));
25312551

25322552
cpuset_change_task_nodemask(task, &cpuset_attach_nodemask_to);
2533-
cpuset_update_task_spread_flag(cs, task);
2553+
cpuset_update_task_spread_flags(cs, task);
25342554
}
25352555

25362556
/*
25372557
* Change mm for all threadgroup leaders. This is expensive and may
2538-
* sleep and should be moved outside migration path proper.
2558+
* sleep and should be moved outside migration path proper. Skip it
2559+
* if there is no change in effective_mems and CS_MEMORY_MIGRATE is
2560+
* not set.
25392561
*/
25402562
cpuset_attach_nodemask_to = cs->effective_mems;
2563+
if (!is_memory_migrate(cs) && !mems_updated)
2564+
goto out;
2565+
25412566
cgroup_taskset_for_each_leader(leader, css, tset) {
25422567
struct mm_struct *mm = get_task_mm(leader);
25432568

@@ -2560,6 +2585,7 @@ static void cpuset_attach(struct cgroup_taskset *tset)
25602585
}
25612586
}
25622587

2588+
out:
25632589
cs->old_mems_allowed = cpuset_attach_nodemask_to;
25642590

25652591
cs->attach_in_progress--;
@@ -3046,11 +3072,15 @@ static struct cftype dfl_files[] = {
30463072
};
30473073

30483074

3049-
/*
3050-
* cpuset_css_alloc - allocate a cpuset css
3051-
* cgrp: control group that the new cpuset will be part of
3075+
/**
3076+
* cpuset_css_alloc - Allocate a cpuset css
3077+
* @parent_css: Parent css of the control group that the new cpuset will be
3078+
* part of
3079+
* Return: cpuset css on success, -ENOMEM on failure.
3080+
*
3081+
* Allocate and initialize a new cpuset css, for non-NULL @parent_css, return
3082+
* top cpuset css otherwise.
30523083
*/
3053-
30543084
static struct cgroup_subsys_state *
30553085
cpuset_css_alloc(struct cgroup_subsys_state *parent_css)
30563086
{

lib/Kconfig.debug

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,6 +1717,16 @@ config LATENCYTOP
17171717
Enable this option if you want to use the LatencyTOP tool
17181718
to find out which userspace is blocking on what kernel operations.
17191719

1720+
config DEBUG_CGROUP_REF
1721+
bool "Disable inlining of cgroup css reference count functions"
1722+
depends on DEBUG_KERNEL
1723+
depends on CGROUPS
1724+
depends on KPROBES
1725+
default n
1726+
help
1727+
Force cgroup css reference count functions to not be inlined so
1728+
that they can be kprobed for debugging.
1729+
17201730
source "kernel/trace/Kconfig"
17211731

17221732
config PROVIDE_OHCI1394_DMA_INIT

0 commit comments

Comments
 (0)