[PATCH v6 2/4] cgroup: revise how we re-populate root directory

2012-08-16 Thread aris
From: Li Zefan 

When remounting cgroupfs with some subsystems added to it and some
removed, cgroup will remove all the files in root directory and then
re-popluate it.

What I'm doing here is, only remove files which belong to subsystems that
are to be unbinded, and only create files for newly-added subsystems.
The purpose is to have all other files untouched.

This is a preparation for cgroup xattr support.

v6:
- no changes
v5:
- no changes
v4:
- refactored cgroup_clear_directory() to not use cgroup_rm_file()
- instead of going thru the list of files, get the file list using the
  subsystems
- use 'subsys_mask' instead of {added,removed}_bits and made
  cgroup_populate_dir() to match the parameters with cgroup_clear_directory()
v3:
- refresh patches after recent refactoring

Cc: Li Zefan 
Cc: Tejun Heo 
Cc: Hugh Dickins 
Cc: Hillf Danton 
Cc: Lennart Poettering 
Signed-off-by: Li Zefan 
Signed-off-by: Aristeu Rozanski 

---
 kernel/cgroup.c |   61 
 1 file changed, 48 insertions(+), 13 deletions(-)

Index: github/kernel/cgroup.c
===
--- github.orig/kernel/cgroup.c 2012-08-16 11:28:12.683272452 -0400
+++ github/kernel/cgroup.c  2012-08-16 11:28:42.592089681 -0400
@@ -824,7 +824,8 @@
 static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t 
mode);
 static struct dentry *cgroup_lookup(struct inode *, struct dentry *, unsigned 
int);
 static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
-static int cgroup_populate_dir(struct cgroup *cgrp);
+static int cgroup_populate_dir(struct cgroup *cgrp, bool base_files,
+  unsigned long subsys_mask);
 static const struct inode_operations cgroup_dir_inode_operations;
 static const struct file_operations proc_cgroupstats_operations;
 
@@ -963,12 +964,29 @@
return -ENOENT;
 }
 
-static void cgroup_clear_directory(struct dentry *dir)
+/**
+ * cgroup_clear_directory - selective removal of base and subsystem files
+ * @dir: directory containing the files
+ * @base_files: true if the base files should be removed
+ * @subsys_mask: mask of the subsystem ids whose files should be removed
+ */
+static void cgroup_clear_directory(struct dentry *dir, bool base_files,
+  unsigned long subsys_mask)
 {
struct cgroup *cgrp = __d_cgrp(dir);
+   struct cgroup_subsys *ss;
 
-   while (!list_empty(>files))
-   cgroup_rm_file(cgrp, NULL);
+   for_each_subsys(cgrp->root, ss) {
+   struct cftype_set *set;
+   if (!test_bit(ss->subsys_id, _mask))
+   continue;
+   list_for_each_entry(set, >cftsets, node)
+   cgroup_rm_file(cgrp, set->cfts);
+   }
+   if (base_files) {
+   while (!list_empty(>files))
+   cgroup_rm_file(cgrp, NULL);
+   }
 }
 
 /*
@@ -977,8 +995,9 @@
 static void cgroup_d_remove_dir(struct dentry *dentry)
 {
struct dentry *parent;
+   struct cgroupfs_root *root = dentry->d_sb->s_fs_info;
 
-   cgroup_clear_directory(dentry);
+   cgroup_clear_directory(dentry, true, root->subsys_bits);
 
parent = dentry->d_parent;
spin_lock(>d_lock);
@@ -1339,6 +1358,7 @@
struct cgroupfs_root *root = sb->s_fs_info;
struct cgroup *cgrp = >top_cgroup;
struct cgroup_sb_opts opts;
+   unsigned long added_bits, removed_bits;
 
mutex_lock(>dentry->d_inode->i_mutex);
mutex_lock(_mutex);
@@ -1354,6 +1374,9 @@
pr_warning("cgroup: option changes via remount are deprecated 
(pid=%d comm=%s)\n",
   task_tgid_nr(current), current->comm);
 
+   added_bits = opts.subsys_bits & ~root->subsys_bits;
+   removed_bits = root->subsys_bits & ~opts.subsys_bits;
+
/* Don't allow flags or name to change at remount */
if (opts.flags != root->flags ||
(opts.name && strcmp(opts.name, root->name))) {
@@ -1369,8 +1392,9 @@
}
 
/* clear out any existing files and repopulate subsystem files */
-   cgroup_clear_directory(cgrp->dentry);
-   cgroup_populate_dir(cgrp);
+   cgroup_clear_directory(cgrp->dentry, false, removed_bits);
+   /* re-populate subsystem files */
+   cgroup_populate_dir(cgrp, false, added_bits);
 
if (opts.release_agent)
strcpy(root->release_agent_path, opts.release_agent);
@@ -1669,7 +1693,7 @@
BUG_ON(root->number_of_cgroups != 1);
 
cred = override_creds(_cred);
-   cgroup_populate_dir(root_cgrp);
+   cgroup_populate_dir(root_cgrp, true, root->subsys_bits);
revert_creds(cred);
mutex_unlock(_root_mutex);
mutex_unlock(_mutex);
@@ -3843,18 +3867,29 @@
{ } /* terminate */
 };
 
-static int 

[PATCH v6 2/4] cgroup: revise how we re-populate root directory

2012-08-16 Thread aris
From: Li Zefan lize...@huawei.com

When remounting cgroupfs with some subsystems added to it and some
removed, cgroup will remove all the files in root directory and then
re-popluate it.

What I'm doing here is, only remove files which belong to subsystems that
are to be unbinded, and only create files for newly-added subsystems.
The purpose is to have all other files untouched.

This is a preparation for cgroup xattr support.

v6:
- no changes
v5:
- no changes
v4:
- refactored cgroup_clear_directory() to not use cgroup_rm_file()
- instead of going thru the list of files, get the file list using the
  subsystems
- use 'subsys_mask' instead of {added,removed}_bits and made
  cgroup_populate_dir() to match the parameters with cgroup_clear_directory()
v3:
- refresh patches after recent refactoring

Cc: Li Zefan lize...@huawei.com
Cc: Tejun Heo t...@kernel.org
Cc: Hugh Dickins hu...@google.com
Cc: Hillf Danton dhi...@gmail.com
Cc: Lennart Poettering lpoet...@redhat.com
Signed-off-by: Li Zefan lize...@huawei.com
Signed-off-by: Aristeu Rozanski a...@redhat.com

---
 kernel/cgroup.c |   61 
 1 file changed, 48 insertions(+), 13 deletions(-)

Index: github/kernel/cgroup.c
===
--- github.orig/kernel/cgroup.c 2012-08-16 11:28:12.683272452 -0400
+++ github/kernel/cgroup.c  2012-08-16 11:28:42.592089681 -0400
@@ -824,7 +824,8 @@
 static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t 
mode);
 static struct dentry *cgroup_lookup(struct inode *, struct dentry *, unsigned 
int);
 static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
-static int cgroup_populate_dir(struct cgroup *cgrp);
+static int cgroup_populate_dir(struct cgroup *cgrp, bool base_files,
+  unsigned long subsys_mask);
 static const struct inode_operations cgroup_dir_inode_operations;
 static const struct file_operations proc_cgroupstats_operations;
 
@@ -963,12 +964,29 @@
return -ENOENT;
 }
 
-static void cgroup_clear_directory(struct dentry *dir)
+/**
+ * cgroup_clear_directory - selective removal of base and subsystem files
+ * @dir: directory containing the files
+ * @base_files: true if the base files should be removed
+ * @subsys_mask: mask of the subsystem ids whose files should be removed
+ */
+static void cgroup_clear_directory(struct dentry *dir, bool base_files,
+  unsigned long subsys_mask)
 {
struct cgroup *cgrp = __d_cgrp(dir);
+   struct cgroup_subsys *ss;
 
-   while (!list_empty(cgrp-files))
-   cgroup_rm_file(cgrp, NULL);
+   for_each_subsys(cgrp-root, ss) {
+   struct cftype_set *set;
+   if (!test_bit(ss-subsys_id, subsys_mask))
+   continue;
+   list_for_each_entry(set, ss-cftsets, node)
+   cgroup_rm_file(cgrp, set-cfts);
+   }
+   if (base_files) {
+   while (!list_empty(cgrp-files))
+   cgroup_rm_file(cgrp, NULL);
+   }
 }
 
 /*
@@ -977,8 +995,9 @@
 static void cgroup_d_remove_dir(struct dentry *dentry)
 {
struct dentry *parent;
+   struct cgroupfs_root *root = dentry-d_sb-s_fs_info;
 
-   cgroup_clear_directory(dentry);
+   cgroup_clear_directory(dentry, true, root-subsys_bits);
 
parent = dentry-d_parent;
spin_lock(parent-d_lock);
@@ -1339,6 +1358,7 @@
struct cgroupfs_root *root = sb-s_fs_info;
struct cgroup *cgrp = root-top_cgroup;
struct cgroup_sb_opts opts;
+   unsigned long added_bits, removed_bits;
 
mutex_lock(cgrp-dentry-d_inode-i_mutex);
mutex_lock(cgroup_mutex);
@@ -1354,6 +1374,9 @@
pr_warning(cgroup: option changes via remount are deprecated 
(pid=%d comm=%s)\n,
   task_tgid_nr(current), current-comm);
 
+   added_bits = opts.subsys_bits  ~root-subsys_bits;
+   removed_bits = root-subsys_bits  ~opts.subsys_bits;
+
/* Don't allow flags or name to change at remount */
if (opts.flags != root-flags ||
(opts.name  strcmp(opts.name, root-name))) {
@@ -1369,8 +1392,9 @@
}
 
/* clear out any existing files and repopulate subsystem files */
-   cgroup_clear_directory(cgrp-dentry);
-   cgroup_populate_dir(cgrp);
+   cgroup_clear_directory(cgrp-dentry, false, removed_bits);
+   /* re-populate subsystem files */
+   cgroup_populate_dir(cgrp, false, added_bits);
 
if (opts.release_agent)
strcpy(root-release_agent_path, opts.release_agent);
@@ -1669,7 +1693,7 @@
BUG_ON(root-number_of_cgroups != 1);
 
cred = override_creds(init_cred);
-   cgroup_populate_dir(root_cgrp);
+   cgroup_populate_dir(root_cgrp, true, root-subsys_bits);
revert_creds(cred);