aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/cgroup.h4
-rw-r--r--kernel/cgroup.c25
-rw-r--r--kernel/events/core.c17
-rw-r--r--mm/memcontrol.c16
4 files changed, 26 insertions, 36 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index c86ba7ff7a7e..1ba4fc08f776 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -825,8 +825,8 @@ int css_scan_tasks(struct cgroup_subsys_state *css,
825int cgroup_attach_task_all(struct task_struct *from, struct task_struct *); 825int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
826int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from); 826int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from);
827 827
828struct cgroup_subsys_state *css_from_dir(struct dentry *dentry, 828struct cgroup_subsys_state *css_tryget_from_dir(struct dentry *dentry,
829 struct cgroup_subsys *ss); 829 struct cgroup_subsys *ss);
830 830
831#else /* !CONFIG_CGROUPS */ 831#else /* !CONFIG_CGROUPS */
832 832
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 2de8decfd99f..fc2db071d95e 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4978,28 +4978,35 @@ static int __init cgroup_disable(char *str)
4978__setup("cgroup_disable=", cgroup_disable); 4978__setup("cgroup_disable=", cgroup_disable);
4979 4979
4980/** 4980/**
4981 * css_from_dir - get corresponding css from the dentry of a cgroup dir 4981 * css_tryget_from_dir - get corresponding css from the dentry of a cgroup dir
4982 * @dentry: directory dentry of interest 4982 * @dentry: directory dentry of interest
4983 * @ss: subsystem of interest 4983 * @ss: subsystem of interest
4984 * 4984 *
4985 * Must be called under cgroup_mutex or RCU read lock. The caller is 4985 * If @dentry is a directory for a cgroup which has @ss enabled on it, try
4986 * responsible for pinning the returned css if it needs to be accessed 4986 * to get the corresponding css and return it. If such css doesn't exist
4987 * outside the critical section. 4987 * or can't be pinned, an ERR_PTR value is returned.
4988 */ 4988 */
4989struct cgroup_subsys_state *css_from_dir(struct dentry *dentry, 4989struct cgroup_subsys_state *css_tryget_from_dir(struct dentry *dentry,
4990 struct cgroup_subsys *ss) 4990 struct cgroup_subsys *ss)
4991{ 4991{
4992 struct cgroup *cgrp; 4992 struct cgroup *cgrp;
4993 4993 struct cgroup_subsys_state *css;
4994 cgroup_assert_mutex_or_rcu_locked();
4995 4994
4996 /* is @dentry a cgroup dir? */ 4995 /* is @dentry a cgroup dir? */
4997 if (!dentry->d_inode || 4996 if (!dentry->d_inode ||
4998 dentry->d_inode->i_op != &cgroup_dir_inode_operations) 4997 dentry->d_inode->i_op != &cgroup_dir_inode_operations)
4999 return ERR_PTR(-EBADF); 4998 return ERR_PTR(-EBADF);
5000 4999
5000 rcu_read_lock();
5001
5001 cgrp = __d_cgrp(dentry); 5002 cgrp = __d_cgrp(dentry);
5002 return cgroup_css(cgrp, ss) ?: ERR_PTR(-ENOENT); 5003 css = cgroup_css(cgrp, ss);
5004
5005 if (!css || !css_tryget(css))
5006 css = ERR_PTR(-ENOENT);
5007
5008 rcu_read_unlock();
5009 return css;
5003} 5010}
5004 5011
5005/** 5012/**
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 64903731d834..a3c3ab50271a 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -370,11 +370,6 @@ perf_cgroup_match(struct perf_event *event)
370 event->cgrp->css.cgroup); 370 event->cgrp->css.cgroup);
371} 371}
372 372
373static inline bool perf_tryget_cgroup(struct perf_event *event)
374{
375 return css_tryget(&event->cgrp->css);
376}
377
378static inline void perf_put_cgroup(struct perf_event *event) 373static inline void perf_put_cgroup(struct perf_event *event)
379{ 374{
380 css_put(&event->cgrp->css); 375 css_put(&event->cgrp->css);
@@ -593,9 +588,7 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event,
593 if (!f.file) 588 if (!f.file)
594 return -EBADF; 589 return -EBADF;
595 590
596 rcu_read_lock(); 591 css = css_tryget_from_dir(f.file->f_dentry, &perf_event_cgrp_subsys);
597
598 css = css_from_dir(f.file->f_dentry, &perf_event_cgrp_subsys);
599 if (IS_ERR(css)) { 592 if (IS_ERR(css)) {
600 ret = PTR_ERR(css); 593 ret = PTR_ERR(css);
601 goto out; 594 goto out;
@@ -604,13 +597,6 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event,
604 cgrp = container_of(css, struct perf_cgroup, css); 597 cgrp = container_of(css, struct perf_cgroup, css);
605 event->cgrp = cgrp; 598 event->cgrp = cgrp;
606 599
607 /* must be done before we fput() the file */
608 if (!perf_tryget_cgroup(event)) {
609 event->cgrp = NULL;
610 ret = -ENOENT;
611 goto out;
612 }
613
614 /* 600 /*
615 * all events in a group must monitor 601 * all events in a group must monitor
616 * the same cgroup because a task belongs 602 * the same cgroup because a task belongs
@@ -621,7 +607,6 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event,
621 ret = -EINVAL; 607 ret = -EINVAL;
622 } 608 }
623out: 609out:
624 rcu_read_unlock();
625 fdput(f); 610 fdput(f);
626 return ret; 611 return ret;
627} 612}
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 04a97bce2270..102ab48ffa13 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -6183,17 +6183,15 @@ static int memcg_write_event_control(struct cgroup_subsys_state *css,
6183 * automatically removed on cgroup destruction but the removal is 6183 * automatically removed on cgroup destruction but the removal is
6184 * asynchronous, so take an extra ref on @css. 6184 * asynchronous, so take an extra ref on @css.
6185 */ 6185 */
6186 rcu_read_lock(); 6186 cfile_css = css_tryget_from_dir(cfile.file->f_dentry->d_parent,
6187 6187 &memory_cgrp_subsys);
6188 ret = -EINVAL; 6188 ret = -EINVAL;
6189 cfile_css = css_from_dir(cfile.file->f_dentry->d_parent, 6189 if (IS_ERR(cfile_css))
6190 &memory_cgrp_subsys);
6191 if (cfile_css == css && css_tryget(css))
6192 ret = 0;
6193
6194 rcu_read_unlock();
6195 if (ret)
6196 goto out_put_cfile; 6190 goto out_put_cfile;
6191 if (cfile_css != css) {
6192 css_put(cfile_css);
6193 goto out_put_cfile;
6194 }
6197 6195
6198 ret = event->register_event(memcg, event->eventfd, buffer); 6196 ret = event->register_event(memcg, event->eventfd, buffer);
6199 if (ret) 6197 if (ret)