aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-11-29 10:42:59 -0500
committerTejun Heo <tj@kernel.org>2013-11-29 10:42:59 -0500
commite6b817103d168a76e4044ebcdbc08225d77a81cb (patch)
tree2bb6a201b17387f933fea715253f432ef0c7bc81 /kernel
parent62236858f3cc558135d1ab6b2af44d22c489bb7f (diff)
cgroup: refactor cgroup_pidlist_find()
Rename cgroup_pidlist_find() to cgroup_pidlist_find_create() and separate out finding proper to cgroup_pidlist_find(). Also, move locking to the caller. This patch is preparation for pidlist restructure and doesn't introduce any behavior changes. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cgroup.c65
1 files changed, 38 insertions, 27 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index ef019c075d5d..d58c30d3b828 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -3575,48 +3575,50 @@ static int cmppid(const void *a, const void *b)
3575 return *(pid_t *)a - *(pid_t *)b; 3575 return *(pid_t *)a - *(pid_t *)b;
3576} 3576}
3577 3577
3578static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp,
3579 enum cgroup_filetype type)
3580{
3581 struct cgroup_pidlist *l;
3582 /* don't need task_nsproxy() if we're looking at ourself */
3583 struct pid_namespace *ns = task_active_pid_ns(current);
3584
3585 lockdep_assert_held(&cgrp->pidlist_mutex);
3586
3587 list_for_each_entry(l, &cgrp->pidlists, links)
3588 if (l->key.type == type && l->key.ns == ns)
3589 return l;
3590 return NULL;
3591}
3592
3578/* 3593/*
3579 * find the appropriate pidlist for our purpose (given procs vs tasks) 3594 * find the appropriate pidlist for our purpose (given procs vs tasks)
3580 * returns with the lock on that pidlist already held, and takes care 3595 * returns with the lock on that pidlist already held, and takes care
3581 * of the use count, or returns NULL with no locks held if we're out of 3596 * of the use count, or returns NULL with no locks held if we're out of
3582 * memory. 3597 * memory.
3583 */ 3598 */
3584static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp, 3599static struct cgroup_pidlist *cgroup_pidlist_find_create(struct cgroup *cgrp,
3585 enum cgroup_filetype type) 3600 enum cgroup_filetype type)
3586{ 3601{
3587 struct cgroup_pidlist *l; 3602 struct cgroup_pidlist *l;
3588 /* don't need task_nsproxy() if we're looking at ourself */
3589 struct pid_namespace *ns = task_active_pid_ns(current);
3590 3603
3591 /* 3604 lockdep_assert_held(&cgrp->pidlist_mutex);
3592 * We can't drop the pidlist_mutex before taking the l->rwsem in case 3605
3593 * the last ref-holder is trying to remove l from the list at the same 3606 l = cgroup_pidlist_find(cgrp, type);
3594 * time. Holding the pidlist_mutex precludes somebody taking whichever 3607 if (l)
3595 * list we find out from under us - compare release_pid_array(). 3608 return l;
3596 */ 3609
3597 mutex_lock(&cgrp->pidlist_mutex);
3598 list_for_each_entry(l, &cgrp->pidlists, links) {
3599 if (l->key.type == type && l->key.ns == ns) {
3600 /* make sure l doesn't vanish out from under us */
3601 down_write(&l->rwsem);
3602 mutex_unlock(&cgrp->pidlist_mutex);
3603 return l;
3604 }
3605 }
3606 /* entry not found; create a new one */ 3610 /* entry not found; create a new one */
3607 l = kzalloc(sizeof(struct cgroup_pidlist), GFP_KERNEL); 3611 l = kzalloc(sizeof(struct cgroup_pidlist), GFP_KERNEL);
3608 if (!l) { 3612 if (!l)
3609 mutex_unlock(&cgrp->pidlist_mutex);
3610 return l; 3613 return l;
3611 } 3614
3612 init_rwsem(&l->rwsem); 3615 init_rwsem(&l->rwsem);
3613 INIT_DELAYED_WORK(&l->destroy_dwork, cgroup_pidlist_destroy_work_fn); 3616 INIT_DELAYED_WORK(&l->destroy_dwork, cgroup_pidlist_destroy_work_fn);
3614 down_write(&l->rwsem);
3615 l->key.type = type; 3617 l->key.type = type;
3616 l->key.ns = get_pid_ns(ns); 3618 /* don't need task_nsproxy() if we're looking at ourself */
3619 l->key.ns = get_pid_ns(task_active_pid_ns(current));
3617 l->owner = cgrp; 3620 l->owner = cgrp;
3618 list_add(&l->links, &cgrp->pidlists); 3621 list_add(&l->links, &cgrp->pidlists);
3619 mutex_unlock(&cgrp->pidlist_mutex);
3620 return l; 3622 return l;
3621} 3623}
3622 3624
@@ -3662,17 +3664,26 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type,
3662 sort(array, length, sizeof(pid_t), cmppid, NULL); 3664 sort(array, length, sizeof(pid_t), cmppid, NULL);
3663 if (type == CGROUP_FILE_PROCS) 3665 if (type == CGROUP_FILE_PROCS)
3664 length = pidlist_uniq(array, length); 3666 length = pidlist_uniq(array, length);
3665 l = cgroup_pidlist_find(cgrp, type); 3667
3668 mutex_lock(&cgrp->pidlist_mutex);
3669
3670 l = cgroup_pidlist_find_create(cgrp, type);
3666 if (!l) { 3671 if (!l) {
3672 mutex_unlock(&cgrp->pidlist_mutex);
3667 pidlist_free(array); 3673 pidlist_free(array);
3668 return -ENOMEM; 3674 return -ENOMEM;
3669 } 3675 }
3670 /* store array, freeing old if necessary - lock already held */ 3676
3677 /* store array, freeing old if necessary */
3678 down_write(&l->rwsem);
3671 pidlist_free(l->list); 3679 pidlist_free(l->list);
3672 l->list = array; 3680 l->list = array;
3673 l->length = length; 3681 l->length = length;
3674 l->use_count++; 3682 l->use_count++;
3675 up_write(&l->rwsem); 3683 up_write(&l->rwsem);
3684
3685 mutex_unlock(&cgrp->pidlist_mutex);
3686
3676 *lp = l; 3687 *lp = l;
3677 return 0; 3688 return 0;
3678} 3689}