aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 01:49:20 -0500
committerNick Piggin <npiggin@kernel.dk>2011-01-07 01:50:17 -0500
commit5adcee1d8d32d7f305f6f5aaefdbf8f35adca177 (patch)
tree9292ebc9bb6a21b364a97a44d1b6857a565159c5 /kernel
parent3e880fb5e4bb6a012035e3edd0586ee2817c2e24 (diff)
cgroup fs: avoid switching ->d_op on live dentry
Switching d_op on a live dentry is racy in general, so avoid it. In this case it is a negative dentry, which is safer, but there are still concurrent ops which may be called on d_op in that case (eg. d_revalidate). So in general a filesystem may not do this. Fix cgroupfs so as not to do this. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cgroup.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 66a416b42c18..163c890f436d 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -763,6 +763,8 @@ EXPORT_SYMBOL_GPL(cgroup_unlock);
763 * -> cgroup_mkdir. 763 * -> cgroup_mkdir.
764 */ 764 */
765 765
766static struct dentry *cgroup_lookup(struct inode *dir,
767 struct dentry *dentry, struct nameidata *nd);
766static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, int mode); 768static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, int mode);
767static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry); 769static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
768static int cgroup_populate_dir(struct cgroup *cgrp); 770static int cgroup_populate_dir(struct cgroup *cgrp);
@@ -2180,7 +2182,7 @@ static const struct file_operations cgroup_file_operations = {
2180}; 2182};
2181 2183
2182static const struct inode_operations cgroup_dir_inode_operations = { 2184static const struct inode_operations cgroup_dir_inode_operations = {
2183 .lookup = simple_lookup, 2185 .lookup = cgroup_lookup,
2184 .mkdir = cgroup_mkdir, 2186 .mkdir = cgroup_mkdir,
2185 .rmdir = cgroup_rmdir, 2187 .rmdir = cgroup_rmdir,
2186 .rename = cgroup_rename, 2188 .rename = cgroup_rename,
@@ -2196,13 +2198,29 @@ static inline struct cftype *__file_cft(struct file *file)
2196 return __d_cft(file->f_dentry); 2198 return __d_cft(file->f_dentry);
2197} 2199}
2198 2200
2199static int cgroup_create_file(struct dentry *dentry, mode_t mode, 2201static int cgroup_delete_dentry(struct dentry *dentry)
2200 struct super_block *sb) 2202{
2203 return 1;
2204}
2205
2206static struct dentry *cgroup_lookup(struct inode *dir,
2207 struct dentry *dentry, struct nameidata *nd)
2201{ 2208{
2202 static const struct dentry_operations cgroup_dops = { 2209 static const struct dentry_operations cgroup_dentry_operations = {
2210 .d_delete = cgroup_delete_dentry,
2203 .d_iput = cgroup_diput, 2211 .d_iput = cgroup_diput,
2204 }; 2212 };
2205 2213
2214 if (dentry->d_name.len > NAME_MAX)
2215 return ERR_PTR(-ENAMETOOLONG);
2216 dentry->d_op = &cgroup_dentry_operations;
2217 d_add(dentry, NULL);
2218 return NULL;
2219}
2220
2221static int cgroup_create_file(struct dentry *dentry, mode_t mode,
2222 struct super_block *sb)
2223{
2206 struct inode *inode; 2224 struct inode *inode;
2207 2225
2208 if (!dentry) 2226 if (!dentry)
@@ -2228,7 +2246,6 @@ static int cgroup_create_file(struct dentry *dentry, mode_t mode,
2228 inode->i_size = 0; 2246 inode->i_size = 0;
2229 inode->i_fop = &cgroup_file_operations; 2247 inode->i_fop = &cgroup_file_operations;
2230 } 2248 }
2231 dentry->d_op = &cgroup_dops;
2232 d_instantiate(dentry, inode); 2249 d_instantiate(dentry, inode);
2233 dget(dentry); /* Extra count - pin the dentry in core */ 2250 dget(dentry); /* Extra count - pin the dentry in core */
2234 return 0; 2251 return 0;