Skip to content

Commit 6ab4286

Browse files
committed
cgroup: Implement DEBUG_CGROUP_REF
It's really difficult to debug when cgroup or css refs leak. Let's add a debug option to force the refcnt function to not be inlined so that they can be kprobed for debugging. Signed-off-by: Tejun Heo <[email protected]>
1 parent 79a818b commit 6ab4286

File tree

4 files changed

+117
-85
lines changed

4 files changed

+117
-85
lines changed

include/linux/cgroup.h

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

312+
#ifdef CONFIG_DEBUG_CGROUP_REF
313+
void css_get(struct cgroup_subsys_state *css);
314+
void css_get_many(struct cgroup_subsys_state *css, unsigned int n);
315+
bool css_tryget(struct cgroup_subsys_state *css);
316+
bool css_tryget_online(struct cgroup_subsys_state *css);
317+
void css_put(struct cgroup_subsys_state *css);
318+
void css_put_many(struct cgroup_subsys_state *css, unsigned int n);
319+
#else
320+
#define CGROUP_REF_FN_ATTRS static inline
321+
#include <linux/cgroup_refcnt.h>
322+
#endif
323+
312324
static inline u64 cgroup_id(const struct cgroup *cgrp)
313325
{
314326
return cgrp->kn->id;
315327
}
316328

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

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

include/linux/cgroup_refcnt.h

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

kernel/cgroup/cgroup.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ 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+
#include <linux/cgroup_refcnt.h>
254+
#endif
255+
251256
/**
252257
* cgroup_ssid_enabled - cgroup subsys enabled test by subsys ID
253258
* @ssid: subsys ID of interest

lib/Kconfig.debug

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

1704+
config DEBUG_CGROUP_REF
1705+
bool "Disable inlining of cgroup css reference count functions"
1706+
depends on DEBUG_KERNEL
1707+
depends on CGROUPS
1708+
depends on KPROBES
1709+
default n
1710+
help
1711+
Force cgroup css reference count functions to not be inlined so
1712+
that they can be kprobed for debugging.
1713+
17041714
source "kernel/trace/Kconfig"
17051715

17061716
config PROVIDE_OHCI1394_DMA_INIT

0 commit comments

Comments
 (0)