aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/cgroup.h1
-rw-r--r--kernel/cgroup.c240
2 files changed, 182 insertions, 59 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 3a1cb265afd6..4829a577c1b9 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -350,6 +350,7 @@ struct css_set {
350 * List of csets participating in the on-going migration either as 350 * List of csets participating in the on-going migration either as
351 * source or destination. Protected by cgroup_mutex. 351 * source or destination. Protected by cgroup_mutex.
352 */ 352 */
353 struct list_head mg_preload_node;
353 struct list_head mg_node; 354 struct list_head mg_node;
354 355
355 /* 356 /*
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 23e3a8c74bd4..a93f6f1ebc69 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -644,6 +644,7 @@ static struct css_set *find_css_set(struct css_set *old_cset,
644 INIT_LIST_HEAD(&cset->cgrp_links); 644 INIT_LIST_HEAD(&cset->cgrp_links);
645 INIT_LIST_HEAD(&cset->tasks); 645 INIT_LIST_HEAD(&cset->tasks);
646 INIT_LIST_HEAD(&cset->mg_tasks); 646 INIT_LIST_HEAD(&cset->mg_tasks);
647 INIT_LIST_HEAD(&cset->mg_preload_node);
647 INIT_LIST_HEAD(&cset->mg_node); 648 INIT_LIST_HEAD(&cset->mg_node);
648 INIT_HLIST_NODE(&cset->hlist); 649 INIT_HLIST_NODE(&cset->hlist);
649 650
@@ -1755,16 +1756,137 @@ static void cgroup_task_migrate(struct cgroup *old_cgrp,
1755} 1756}
1756 1757
1757/** 1758/**
1758 * cgroup_attach_task - attach a task or a whole threadgroup to a cgroup 1759 * cgroup_migrate_finish - cleanup after attach
1759 * @cgrp: the cgroup to attach to 1760 * @preloaded_csets: list of preloaded css_sets
1760 * @leader: the task or the leader of the threadgroup to be attached
1761 * @threadgroup: attach the whole threadgroup?
1762 * 1761 *
1763 * Call holding cgroup_mutex and the group_rwsem of the leader. Will take 1762 * Undo cgroup_migrate_add_src() and cgroup_migrate_prepare_dst(). See
1764 * task_lock of @tsk or each thread in the threadgroup individually in turn. 1763 * those functions for details.
1765 */ 1764 */
1766static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *leader, 1765static void cgroup_migrate_finish(struct list_head *preloaded_csets)
1767 bool threadgroup) 1766{
1767 struct css_set *cset, *tmp_cset;
1768
1769 lockdep_assert_held(&cgroup_mutex);
1770
1771 down_write(&css_set_rwsem);
1772 list_for_each_entry_safe(cset, tmp_cset, preloaded_csets, mg_preload_node) {
1773 cset->mg_src_cgrp = NULL;
1774 cset->mg_dst_cset = NULL;
1775 list_del_init(&cset->mg_preload_node);
1776 put_css_set_locked(cset, false);
1777 }
1778 up_write(&css_set_rwsem);
1779}
1780
1781/**
1782 * cgroup_migrate_add_src - add a migration source css_set
1783 * @src_cset: the source css_set to add
1784 * @dst_cgrp: the destination cgroup
1785 * @preloaded_csets: list of preloaded css_sets
1786 *
1787 * Tasks belonging to @src_cset are about to be migrated to @dst_cgrp. Pin
1788 * @src_cset and add it to @preloaded_csets, which should later be cleaned
1789 * up by cgroup_migrate_finish().
1790 *
1791 * This function may be called without holding threadgroup_lock even if the
1792 * target is a process. Threads may be created and destroyed but as long
1793 * as cgroup_mutex is not dropped, no new css_set can be put into play and
1794 * the preloaded css_sets are guaranteed to cover all migrations.
1795 */
1796static void cgroup_migrate_add_src(struct css_set *src_cset,
1797 struct cgroup *dst_cgrp,
1798 struct list_head *preloaded_csets)
1799{
1800 struct cgroup *src_cgrp;
1801
1802 lockdep_assert_held(&cgroup_mutex);
1803 lockdep_assert_held(&css_set_rwsem);
1804
1805 src_cgrp = cset_cgroup_from_root(src_cset, dst_cgrp->root);
1806
1807 /* nothing to do if this cset already belongs to the cgroup */
1808 if (src_cgrp == dst_cgrp)
1809 return;
1810
1811 if (!list_empty(&src_cset->mg_preload_node))
1812 return;
1813
1814 WARN_ON(src_cset->mg_src_cgrp);
1815 WARN_ON(!list_empty(&src_cset->mg_tasks));
1816 WARN_ON(!list_empty(&src_cset->mg_node));
1817
1818 src_cset->mg_src_cgrp = src_cgrp;
1819 get_css_set(src_cset);
1820 list_add(&src_cset->mg_preload_node, preloaded_csets);
1821}
1822
1823/**
1824 * cgroup_migrate_prepare_dst - prepare destination css_sets for migration
1825 * @dst_cgrp: the destination cgroup
1826 * @preloaded_csets: list of preloaded source css_sets
1827 *
1828 * Tasks are about to be moved to @dst_cgrp and all the source css_sets
1829 * have been preloaded to @preloaded_csets. This function looks up and
1830 * pins all destination css_sets, links each to its source, and put them on
1831 * @preloaded_csets.
1832 *
1833 * This function must be called after cgroup_migrate_add_src() has been
1834 * called on each migration source css_set. After migration is performed
1835 * using cgroup_migrate(), cgroup_migrate_finish() must be called on
1836 * @preloaded_csets.
1837 */
1838static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp,
1839 struct list_head *preloaded_csets)
1840{
1841 LIST_HEAD(csets);
1842 struct css_set *src_cset;
1843
1844 lockdep_assert_held(&cgroup_mutex);
1845
1846 /* look up the dst cset for each src cset and link it to src */
1847 list_for_each_entry(src_cset, preloaded_csets, mg_preload_node) {
1848 struct css_set *dst_cset;
1849
1850 dst_cset = find_css_set(src_cset, dst_cgrp);
1851 if (!dst_cset)
1852 goto err;
1853
1854 WARN_ON_ONCE(src_cset->mg_dst_cset || dst_cset->mg_dst_cset);
1855 src_cset->mg_dst_cset = dst_cset;
1856
1857 if (list_empty(&dst_cset->mg_preload_node))
1858 list_add(&dst_cset->mg_preload_node, &csets);
1859 else
1860 put_css_set(dst_cset, false);
1861 }
1862
1863 list_splice(&csets, preloaded_csets);
1864 return 0;
1865err:
1866 cgroup_migrate_finish(&csets);
1867 return -ENOMEM;
1868}
1869
1870/**
1871 * cgroup_migrate - migrate a process or task to a cgroup
1872 * @cgrp: the destination cgroup
1873 * @leader: the leader of the process or the task to migrate
1874 * @threadgroup: whether @leader points to the whole process or a single task
1875 *
1876 * Migrate a process or task denoted by @leader to @cgrp. If migrating a
1877 * process, the caller must be holding threadgroup_lock of @leader. The
1878 * caller is also responsible for invoking cgroup_migrate_add_src() and
1879 * cgroup_migrate_prepare_dst() on the targets before invoking this
1880 * function and following up with cgroup_migrate_finish().
1881 *
1882 * As long as a controller's ->can_attach() doesn't fail, this function is
1883 * guaranteed to succeed. This means that, excluding ->can_attach()
1884 * failure, when migrating multiple targets, the success or failure can be
1885 * decided for all targets by invoking group_migrate_prepare_dst() before
1886 * actually starting migrating.
1887 */
1888static int cgroup_migrate(struct cgroup *cgrp, struct task_struct *leader,
1889 bool threadgroup)
1768{ 1890{
1769 struct cgroup_taskset tset = { 1891 struct cgroup_taskset tset = {
1770 .src_csets = LIST_HEAD_INIT(tset.src_csets), 1892 .src_csets = LIST_HEAD_INIT(tset.src_csets),
@@ -1785,29 +1907,17 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *leader,
1785 rcu_read_lock(); 1907 rcu_read_lock();
1786 task = leader; 1908 task = leader;
1787 do { 1909 do {
1788 struct cgroup *src_cgrp;
1789
1790 /* @task either already exited or can't exit until the end */ 1910 /* @task either already exited or can't exit until the end */
1791 if (task->flags & PF_EXITING) 1911 if (task->flags & PF_EXITING)
1792 goto next; 1912 goto next;
1793 1913
1794 cset = task_css_set(task); 1914 cset = task_css_set(task);
1795 src_cgrp = task_cgroup_from_root(task, cgrp->root); 1915 if (!cset->mg_src_cgrp)
1796
1797 /* nothing to do if this task is already in the cgroup */
1798 if (src_cgrp == cgrp)
1799 goto next; 1916 goto next;
1800 1917
1801 if (!cset->mg_src_cgrp) {
1802 WARN_ON(!list_empty(&cset->mg_tasks));
1803 WARN_ON(!list_empty(&cset->mg_node));
1804
1805 cset->mg_src_cgrp = src_cgrp;
1806 list_add(&cset->mg_node, &tset.src_csets);
1807 get_css_set(cset);
1808 }
1809
1810 list_move(&task->cg_list, &cset->mg_tasks); 1918 list_move(&task->cg_list, &cset->mg_tasks);
1919 list_move(&cset->mg_node, &tset.src_csets);
1920 list_move(&cset->mg_dst_cset->mg_node, &tset.dst_csets);
1811 next: 1921 next:
1812 if (!threadgroup) 1922 if (!threadgroup)
1813 break; 1923 break;
@@ -1819,9 +1929,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *leader,
1819 if (list_empty(&tset.src_csets)) 1929 if (list_empty(&tset.src_csets))
1820 return 0; 1930 return 0;
1821 1931
1822 /* 1932 /* check that we can legitimately attach to the cgroup */
1823 * step 1: check that we can legitimately attach to the cgroup.
1824 */
1825 for_each_css(css, i, cgrp) { 1933 for_each_css(css, i, cgrp) {
1826 if (css->ss->can_attach) { 1934 if (css->ss->can_attach) {
1827 ret = css->ss->can_attach(css, &tset); 1935 ret = css->ss->can_attach(css, &tset);
@@ -1833,30 +1941,9 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *leader,
1833 } 1941 }
1834 1942
1835 /* 1943 /*
1836 * step 2: make sure css_sets exist for all threads to be migrated. 1944 * Now that we're guaranteed success, proceed to move all tasks to
1837 * we use find_css_set, which allocates a new one if necessary. 1945 * the new cgroup. There are no failure cases after here, so this
1838 */ 1946 * is the commit point.
1839 list_for_each_entry(cset, &tset.src_csets, mg_node) {
1840 struct css_set *dst_cset;
1841
1842 dst_cset = find_css_set(cset, cgrp);
1843 if (!dst_cset) {
1844 ret = -ENOMEM;
1845 goto out_release_tset;
1846 }
1847
1848 if (list_empty(&dst_cset->mg_node))
1849 list_add(&dst_cset->mg_node, &tset.dst_csets);
1850 else
1851 put_css_set(dst_cset, false);
1852
1853 cset->mg_dst_cset = dst_cset;
1854 }
1855
1856 /*
1857 * step 3: now that we're guaranteed success wrt the css_sets,
1858 * proceed to move all tasks to the new cgroup. There are no
1859 * failure cases after here, so this is the commit point.
1860 */ 1947 */
1861 down_write(&css_set_rwsem); 1948 down_write(&css_set_rwsem);
1862 list_for_each_entry(cset, &tset.src_csets, mg_node) { 1949 list_for_each_entry(cset, &tset.src_csets, mg_node) {
@@ -1866,14 +1953,13 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *leader,
1866 } 1953 }
1867 up_write(&css_set_rwsem); 1954 up_write(&css_set_rwsem);
1868 1955
1869 /* migration is committed, all target tasks are now on dst_csets */
1870 tset.csets = &tset.dst_csets;
1871
1872 /* nothing is sensitive to fork() after this point */
1873
1874 /* 1956 /*
1875 * step 4: do subsystem attach callbacks. 1957 * Migration is committed, all target tasks are now on dst_csets.
1958 * Nothing is sensitive to fork() after this point. Notify
1959 * controllers that migration is complete.
1876 */ 1960 */
1961 tset.csets = &tset.dst_csets;
1962
1877 for_each_css(css, i, cgrp) 1963 for_each_css(css, i, cgrp)
1878 if (css->ss->attach) 1964 if (css->ss->attach)
1879 css->ss->attach(css, &tset); 1965 css->ss->attach(css, &tset);
@@ -1893,15 +1979,50 @@ out_release_tset:
1893 list_splice_init(&tset.dst_csets, &tset.src_csets); 1979 list_splice_init(&tset.dst_csets, &tset.src_csets);
1894 list_for_each_entry_safe(cset, tmp_cset, &tset.src_csets, mg_node) { 1980 list_for_each_entry_safe(cset, tmp_cset, &tset.src_csets, mg_node) {
1895 list_splice_init(&cset->mg_tasks, &cset->tasks); 1981 list_splice_init(&cset->mg_tasks, &cset->tasks);
1896 cset->mg_dst_cset = NULL;
1897 cset->mg_src_cgrp = NULL;
1898 list_del_init(&cset->mg_node); 1982 list_del_init(&cset->mg_node);
1899 put_css_set_locked(cset, false);
1900 } 1983 }
1901 up_write(&css_set_rwsem); 1984 up_write(&css_set_rwsem);
1902 return ret; 1985 return ret;
1903} 1986}
1904 1987
1988/**
1989 * cgroup_attach_task - attach a task or a whole threadgroup to a cgroup
1990 * @dst_cgrp: the cgroup to attach to
1991 * @leader: the task or the leader of the threadgroup to be attached
1992 * @threadgroup: attach the whole threadgroup?
1993 *
1994 * Call holding cgroup_mutex and the group_rwsem of the leader. Will take
1995 * task_lock of @tsk or each thread in the threadgroup individually in turn.
1996 */
1997static int cgroup_attach_task(struct cgroup *dst_cgrp,
1998 struct task_struct *leader, bool threadgroup)
1999{
2000 LIST_HEAD(preloaded_csets);
2001 struct task_struct *task;
2002 int ret;
2003
2004 /* look up all src csets */
2005 down_read(&css_set_rwsem);
2006 rcu_read_lock();
2007 task = leader;
2008 do {
2009 cgroup_migrate_add_src(task_css_set(task), dst_cgrp,
2010 &preloaded_csets);
2011 if (!threadgroup)
2012 break;
2013 } while_each_thread(leader, task);
2014 rcu_read_unlock();
2015 up_read(&css_set_rwsem);
2016
2017 /* prepare dst csets and commit */
2018 ret = cgroup_migrate_prepare_dst(dst_cgrp, &preloaded_csets);
2019 if (!ret)
2020 ret = cgroup_migrate(dst_cgrp, leader, threadgroup);
2021
2022 cgroup_migrate_finish(&preloaded_csets);
2023 return ret;
2024}
2025
1905/* 2026/*
1906 * Find the task_struct of the task to attach by vpid and pass it along to the 2027 * Find the task_struct of the task to attach by vpid and pass it along to the
1907 * function to attach either it or all tasks in its threadgroup. Will lock 2028 * function to attach either it or all tasks in its threadgroup. Will lock
@@ -3906,6 +4027,7 @@ int __init cgroup_init_early(void)
3906 INIT_LIST_HEAD(&init_css_set.cgrp_links); 4027 INIT_LIST_HEAD(&init_css_set.cgrp_links);
3907 INIT_LIST_HEAD(&init_css_set.tasks); 4028 INIT_LIST_HEAD(&init_css_set.tasks);
3908 INIT_LIST_HEAD(&init_css_set.mg_tasks); 4029 INIT_LIST_HEAD(&init_css_set.mg_tasks);
4030 INIT_LIST_HEAD(&init_css_set.mg_preload_node);
3909 INIT_LIST_HEAD(&init_css_set.mg_node); 4031 INIT_LIST_HEAD(&init_css_set.mg_node);
3910 INIT_HLIST_NODE(&init_css_set.hlist); 4032 INIT_HLIST_NODE(&init_css_set.hlist);
3911 css_set_count = 1; 4033 css_set_count = 1;