mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
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 <tj@kernel.org>
This commit is contained in:
parent
79a818b508
commit
6ab428604f
@ -309,71 +309,23 @@ void css_task_iter_end(struct css_task_iter *it);
|
||||
* Inline functions.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_DEBUG_CGROUP_REF
|
||||
void css_get(struct cgroup_subsys_state *css);
|
||||
void css_get_many(struct cgroup_subsys_state *css, unsigned int n);
|
||||
bool css_tryget(struct cgroup_subsys_state *css);
|
||||
bool css_tryget_online(struct cgroup_subsys_state *css);
|
||||
void css_put(struct cgroup_subsys_state *css);
|
||||
void css_put_many(struct cgroup_subsys_state *css, unsigned int n);
|
||||
#else
|
||||
#define CGROUP_REF_FN_ATTRS static inline
|
||||
#include <linux/cgroup_refcnt.h>
|
||||
#endif
|
||||
|
||||
static inline u64 cgroup_id(const struct cgroup *cgrp)
|
||||
{
|
||||
return cgrp->kn->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* css_get - obtain a reference on the specified css
|
||||
* @css: target css
|
||||
*
|
||||
* The caller must already have a reference.
|
||||
*/
|
||||
static inline void css_get(struct cgroup_subsys_state *css)
|
||||
{
|
||||
if (!(css->flags & CSS_NO_REF))
|
||||
percpu_ref_get(&css->refcnt);
|
||||
}
|
||||
|
||||
/**
|
||||
* css_get_many - obtain references on the specified css
|
||||
* @css: target css
|
||||
* @n: number of references to get
|
||||
*
|
||||
* The caller must already have a reference.
|
||||
*/
|
||||
static inline void css_get_many(struct cgroup_subsys_state *css, unsigned int n)
|
||||
{
|
||||
if (!(css->flags & CSS_NO_REF))
|
||||
percpu_ref_get_many(&css->refcnt, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* css_tryget - try to obtain a reference on the specified css
|
||||
* @css: target css
|
||||
*
|
||||
* Obtain a reference on @css unless it already has reached zero and is
|
||||
* being released. This function doesn't care whether @css is on or
|
||||
* offline. The caller naturally needs to ensure that @css is accessible
|
||||
* but doesn't have to be holding a reference on it - IOW, RCU protected
|
||||
* access is good enough for this function. Returns %true if a reference
|
||||
* count was successfully obtained; %false otherwise.
|
||||
*/
|
||||
static inline bool css_tryget(struct cgroup_subsys_state *css)
|
||||
{
|
||||
if (!(css->flags & CSS_NO_REF))
|
||||
return percpu_ref_tryget(&css->refcnt);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* css_tryget_online - try to obtain a reference on the specified css if online
|
||||
* @css: target css
|
||||
*
|
||||
* Obtain a reference on @css if it's online. The caller naturally needs
|
||||
* to ensure that @css is accessible but doesn't have to be holding a
|
||||
* reference on it - IOW, RCU protected access is good enough for this
|
||||
* function. Returns %true if a reference count was successfully obtained;
|
||||
* %false otherwise.
|
||||
*/
|
||||
static inline bool css_tryget_online(struct cgroup_subsys_state *css)
|
||||
{
|
||||
if (!(css->flags & CSS_NO_REF))
|
||||
return percpu_ref_tryget_live(&css->refcnt);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* css_is_dying - test whether the specified css is dying
|
||||
* @css: target css
|
||||
@ -394,31 +346,6 @@ static inline bool css_is_dying(struct cgroup_subsys_state *css)
|
||||
return !(css->flags & CSS_NO_REF) && percpu_ref_is_dying(&css->refcnt);
|
||||
}
|
||||
|
||||
/**
|
||||
* css_put - put a css reference
|
||||
* @css: target css
|
||||
*
|
||||
* Put a reference obtained via css_get() and css_tryget_online().
|
||||
*/
|
||||
static inline void css_put(struct cgroup_subsys_state *css)
|
||||
{
|
||||
if (!(css->flags & CSS_NO_REF))
|
||||
percpu_ref_put(&css->refcnt);
|
||||
}
|
||||
|
||||
/**
|
||||
* css_put_many - put css references
|
||||
* @css: target css
|
||||
* @n: number of references to put
|
||||
*
|
||||
* Put references obtained via css_get() and css_tryget_online().
|
||||
*/
|
||||
static inline void css_put_many(struct cgroup_subsys_state *css, unsigned int n)
|
||||
{
|
||||
if (!(css->flags & CSS_NO_REF))
|
||||
percpu_ref_put_many(&css->refcnt, n);
|
||||
}
|
||||
|
||||
static inline void cgroup_get(struct cgroup *cgrp)
|
||||
{
|
||||
css_get(&cgrp->self);
|
||||
|
90
include/linux/cgroup_refcnt.h
Normal file
90
include/linux/cgroup_refcnt.h
Normal file
@ -0,0 +1,90 @@
|
||||
/**
|
||||
* css_get - obtain a reference on the specified css
|
||||
* @css: target css
|
||||
*
|
||||
* The caller must already have a reference.
|
||||
*/
|
||||
CGROUP_REF_FN_ATTRS
|
||||
void css_get(struct cgroup_subsys_state *css)
|
||||
{
|
||||
if (!(css->flags & CSS_NO_REF))
|
||||
percpu_ref_get(&css->refcnt);
|
||||
}
|
||||
|
||||
/**
|
||||
* css_get_many - obtain references on the specified css
|
||||
* @css: target css
|
||||
* @n: number of references to get
|
||||
*
|
||||
* The caller must already have a reference.
|
||||
*/
|
||||
CGROUP_REF_FN_ATTRS
|
||||
void css_get_many(struct cgroup_subsys_state *css, unsigned int n)
|
||||
{
|
||||
if (!(css->flags & CSS_NO_REF))
|
||||
percpu_ref_get_many(&css->refcnt, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* css_tryget - try to obtain a reference on the specified css
|
||||
* @css: target css
|
||||
*
|
||||
* Obtain a reference on @css unless it already has reached zero and is
|
||||
* being released. This function doesn't care whether @css is on or
|
||||
* offline. The caller naturally needs to ensure that @css is accessible
|
||||
* but doesn't have to be holding a reference on it - IOW, RCU protected
|
||||
* access is good enough for this function. Returns %true if a reference
|
||||
* count was successfully obtained; %false otherwise.
|
||||
*/
|
||||
CGROUP_REF_FN_ATTRS
|
||||
bool css_tryget(struct cgroup_subsys_state *css)
|
||||
{
|
||||
if (!(css->flags & CSS_NO_REF))
|
||||
return percpu_ref_tryget(&css->refcnt);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* css_tryget_online - try to obtain a reference on the specified css if online
|
||||
* @css: target css
|
||||
*
|
||||
* Obtain a reference on @css if it's online. The caller naturally needs
|
||||
* to ensure that @css is accessible but doesn't have to be holding a
|
||||
* reference on it - IOW, RCU protected access is good enough for this
|
||||
* function. Returns %true if a reference count was successfully obtained;
|
||||
* %false otherwise.
|
||||
*/
|
||||
CGROUP_REF_FN_ATTRS
|
||||
bool css_tryget_online(struct cgroup_subsys_state *css)
|
||||
{
|
||||
if (!(css->flags & CSS_NO_REF))
|
||||
return percpu_ref_tryget_live(&css->refcnt);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* css_put - put a css reference
|
||||
* @css: target css
|
||||
*
|
||||
* Put a reference obtained via css_get() and css_tryget_online().
|
||||
*/
|
||||
CGROUP_REF_FN_ATTRS
|
||||
void css_put(struct cgroup_subsys_state *css)
|
||||
{
|
||||
if (!(css->flags & CSS_NO_REF))
|
||||
percpu_ref_put(&css->refcnt);
|
||||
}
|
||||
|
||||
/**
|
||||
* css_put_many - put css references
|
||||
* @css: target css
|
||||
* @n: number of references to put
|
||||
*
|
||||
* Put references obtained via css_get() and css_tryget_online().
|
||||
*/
|
||||
CGROUP_REF_FN_ATTRS
|
||||
void css_put_many(struct cgroup_subsys_state *css, unsigned int n)
|
||||
{
|
||||
if (!(css->flags & CSS_NO_REF))
|
||||
percpu_ref_put_many(&css->refcnt, n);
|
||||
}
|
@ -248,6 +248,11 @@ static int cgroup_addrm_files(struct cgroup_subsys_state *css,
|
||||
struct cgroup *cgrp, struct cftype cfts[],
|
||||
bool is_add);
|
||||
|
||||
#ifdef CONFIG_DEBUG_CGROUP_REF
|
||||
#define CGROUP_REF_FN_ATTRS noinline
|
||||
#include <linux/cgroup_refcnt.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* cgroup_ssid_enabled - cgroup subsys enabled test by subsys ID
|
||||
* @ssid: subsys ID of interest
|
||||
|
@ -1701,6 +1701,16 @@ config LATENCYTOP
|
||||
Enable this option if you want to use the LatencyTOP tool
|
||||
to find out which userspace is blocking on what kernel operations.
|
||||
|
||||
config DEBUG_CGROUP_REF
|
||||
bool "Disable inlining of cgroup css reference count functions"
|
||||
depends on DEBUG_KERNEL
|
||||
depends on CGROUPS
|
||||
depends on KPROBES
|
||||
default n
|
||||
help
|
||||
Force cgroup css reference count functions to not be inlined so
|
||||
that they can be kprobed for debugging.
|
||||
|
||||
source "kernel/trace/Kconfig"
|
||||
|
||||
config PROVIDE_OHCI1394_DMA_INIT
|
||||
|
Loading…
Reference in New Issue
Block a user