aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/cgroup.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/cgroup.h')
-rw-r--r--include/linux/cgroup.h81
1 files changed, 55 insertions, 26 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 5a85b3415c1b..d3f5fba2c159 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -16,6 +16,7 @@
#include <linux/prio_heap.h>
#include <linux/rwsem.h>
#include <linux/idr.h>
+#include <linux/workqueue.h>
#ifdef CONFIG_CGROUPS
@@ -76,12 +77,16 @@ struct cgroup_subsys_state {
unsigned long flags;
/* ID for this css, if possible */
struct css_id __rcu *id;
+
+ /* Used to put @cgroup->dentry on the last css_put() */
+ struct work_struct dput_work;
};
/* bits in struct cgroup_subsys_state flags field */
enum {
CSS_ROOT, /* This CSS is the root of the subsystem */
CSS_REMOVED, /* This CSS is dead */
+ CSS_CLEAR_CSS_REFS, /* @ss->__DEPRECATED_clear_css_refs */
};
/* Caller must verify that the css is not for root cgroup */
@@ -115,16 +120,12 @@ static inline bool css_is_removed(struct cgroup_subsys_state *css)
* the css has been destroyed.
*/
+extern bool __css_tryget(struct cgroup_subsys_state *css);
static inline bool css_tryget(struct cgroup_subsys_state *css)
{
if (test_bit(CSS_ROOT, &css->flags))
return true;
- while (!atomic_inc_not_zero(&css->refcnt)) {
- if (test_bit(CSS_REMOVED, &css->flags))
- return false;
- cpu_relax();
- }
- return true;
+ return __css_tryget(css);
}
/*
@@ -132,11 +133,11 @@ static inline bool css_tryget(struct cgroup_subsys_state *css)
* css_get() or css_tryget()
*/
-extern void __css_put(struct cgroup_subsys_state *css, int count);
+extern void __css_put(struct cgroup_subsys_state *css);
static inline void css_put(struct cgroup_subsys_state *css)
{
if (!test_bit(CSS_ROOT, &css->flags))
- __css_put(css, 1);
+ __css_put(css);
}
/* bits in struct cgroup flags field */
@@ -175,6 +176,7 @@ struct cgroup {
*/
struct list_head sibling; /* my parent's children */
struct list_head children; /* my children */
+ struct list_head files; /* my files */
struct cgroup *parent; /* my parent */
struct dentry __rcu *dentry; /* cgroup fs entry, RCU protected */
@@ -191,6 +193,9 @@ struct cgroup {
*/
struct list_head css_sets;
+ struct list_head allcg_node; /* cgroupfs_root->allcg_list */
+ struct list_head cft_q_node; /* used during cftype add/rm */
+
/*
* Linked list running through all cgroups that can
* potentially be reaped by the release agent. Protected by
@@ -275,11 +280,17 @@ struct cgroup_map_cb {
* - the 'cftype' of the file is file->f_dentry->d_fsdata
*/
-#define MAX_CFTYPE_NAME 64
+/* cftype->flags */
+#define CFTYPE_ONLY_ON_ROOT (1U << 0) /* only create on root cg */
+#define CFTYPE_NOT_ON_ROOT (1U << 1) /* don't create onp root cg */
+
+#define MAX_CFTYPE_NAME 64
+
struct cftype {
/*
* By convention, the name should begin with the name of the
- * subsystem, followed by a period
+ * subsystem, followed by a period. Zero length string indicates
+ * end of cftype array.
*/
char name[MAX_CFTYPE_NAME];
int private;
@@ -295,6 +306,9 @@ struct cftype {
*/
size_t max_write_len;
+ /* CFTYPE_* flags */
+ unsigned int flags;
+
int (*open)(struct inode *inode, struct file *file);
ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft,
struct file *file,
@@ -373,6 +387,16 @@ struct cftype {
struct eventfd_ctx *eventfd);
};
+/*
+ * cftype_sets describe cftypes belonging to a subsystem and are chained at
+ * cgroup_subsys->cftsets. Each cftset points to an array of cftypes
+ * terminated by zero length name.
+ */
+struct cftype_set {
+ struct list_head node; /* chained at subsys->cftsets */
+ const struct cftype *cfts;
+};
+
struct cgroup_scanner {
struct cgroup *cg;
int (*test_task)(struct task_struct *p, struct cgroup_scanner *scan);
@@ -382,21 +406,8 @@ struct cgroup_scanner {
void *data;
};
-/*
- * Add a new file to the given cgroup directory. Should only be
- * called by subsystems from within a populate() method
- */
-int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys,
- const struct cftype *cft);
-
-/*
- * Add a set of new files to the given cgroup directory. Should
- * only be called by subsystems from within a populate() method
- */
-int cgroup_add_files(struct cgroup *cgrp,
- struct cgroup_subsys *subsys,
- const struct cftype cft[],
- int count);
+int cgroup_add_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts);
+int cgroup_rm_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts);
int cgroup_is_removed(const struct cgroup *cgrp);
@@ -461,7 +472,6 @@ struct cgroup_subsys {
void (*fork)(struct task_struct *task);
void (*exit)(struct cgroup *cgrp, struct cgroup *old_cgrp,
struct task_struct *task);
- int (*populate)(struct cgroup_subsys *ss, struct cgroup *cgrp);
void (*post_clone)(struct cgroup *cgrp);
void (*bind)(struct cgroup *root);
@@ -474,6 +484,18 @@ struct cgroup_subsys {
* (not available in early_init time.)
*/
bool use_id;
+
+ /*
+ * If %true, cgroup removal will try to clear css refs by retrying
+ * ss->pre_destroy() until there's no css ref left. This behavior
+ * is strictly for backward compatibility and will be removed as
+ * soon as the current user (memcg) is updated.
+ *
+ * If %false, ss->pre_destroy() can't fail and cgroup removal won't
+ * wait for css refs to drop to zero before proceeding.
+ */
+ bool __DEPRECATED_clear_css_refs;
+
#define MAX_CGROUP_TYPE_NAMELEN 32
const char *name;
@@ -500,6 +522,13 @@ struct cgroup_subsys {
struct idr idr;
spinlock_t id_lock;
+ /* list of cftype_sets */
+ struct list_head cftsets;
+
+ /* base cftypes, automatically [de]registered with subsys itself */
+ struct cftype *base_cftypes;
+ struct cftype_set base_cftset;
+
/* should be defined only by modular subsystems */
struct module *module;
};