Skip to contentSkip to conversation

kernel BUG at fs/dcache.c:1363 (from cgroup)

DISCUSSION Li Zefan 4 participants 5 messages Jan 14, 2011 2 messages not in the archive

lore
Share & tools
lore

Li Zefan

author
#0 lore raw

Just mount the cgroupfs:

# mount -t cgroup -o cpuset xxx /mnt
(oops!!)

The bug is caused by:

=========
commit 0df6a63f8735a7c8a877878bc215d4312e41ef81

Author: Al Viro <[email protected]>
Date:   Tue Dec 21 13:29:29 2010 -0500

switch cgroup

switching it to s_d_op allows to kill the cgroup_lookup() kludge.

=========

This line:

+ sb->s_d_op = &cgroup_dops;

will cause the dentry op be set twice, and thus trigger the bomb:

struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)

{
	...
        if (parent) {
		...
                d_set_d_op(dentry, dentry->d_sb->s_d_op);
		...
        }
	...
}

static struct dentry *d_alloc_and_lookup(struct dentry *parent,
struct qstr *name, struct nameidata *nd)

{
	...
        dentry = d_alloc(parent, name);
	...
        old = inode->i_op->lookup(inode, dentry, nd);
	...
}

simple_lookup() will call d_set_d_op()...

==============

[   90.740906] kernel BUG at fs/dcache.c:1360!
..
[   90.810321] Call Trace:
[   90.814166]  [<c04f97ad>] simple_lookup+0x26/0x3c
[   90.818015]  [<c04e86ce>] d_alloc_and_lookup+0x36/0x54
[   90.818021]  [<c04e8aa8>] __lookup_hash+0x6a/0x71
[   90.818026]  [<c04e8f33>] lookup_one_len+0x81/0x90
[   90.818034]  [<c0473083>] cgroup_add_file+0x8e/0x132
[   90.818041]  [<c0473152>] cgroup_add_files+0x2b/0x3d
[   90.818047]  [<c0473188>] cgroup_populate_dir+0x24/0xdb
[   90.818053]  [<c047360b>] cgroup_mount+0x3cc/0x431
[   90.818061]  [<c04e238d>] vfs_kern_mount+0x57/0x109
[   90.818066]  [<c047323f>] ? cgroup_mount+0x0/0x431
[   90.818072]  [<c04e248e>] do_kern_mount+0x38/0xba
[   90.818077]  [<c04f6706>] do_mount+0x5e4/0x60f
[   90.818082]  [<c04f6094>] ? copy_mount_options+0x78/0xd7
[   90.818087]  [<c04f68de>] sys_mount+0x66/0x94
[   90.818093]  [<c040329f>] sysenter_do_call+0x12/0x38
#2 lore raw
In reply to a message not in the archive
Quoted 14 lines · Li Zefan

Just mount the cgroupfs:

# mount -t cgroup -o cpuset xxx /mnt
(oops!!)

The bug is caused by:

=========
commit 0df6a63f8735a7c8a877878bc215d4312e41ef81

Author: Al Viro <viro-RmSDqhL/[email protected]>
Date:   Tue Dec 21 13:29:29 2010 -0500

switch cgroup

Quoted 8 lines

switching it to s_d_op allows to kill the cgroup_lookup() kludge.

=========

This line:

+ sb->s_d_op = &cgroup_dops;

Oh, crap... Right, it's using simple_lookup(). Let me check if anything else might be stepping on that.

Umm... There's a very strange codepath in btrfs that also might. Interesting. Fix for cgroup, AFAICS, should be this:

---

kernel/cgroup.c +16 -1
index 5c5f4cc..ffb7bba 100644
@@ -764,6 +764,7 @@ EXPORT_SYMBOL_GPL(cgroup_unlock);
  */
 
 static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+static struct dentry *cgroup_lookup(struct inode *, struct dentry *, struct nameidata *);
 static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
 static int cgroup_populate_dir(struct cgroup *cgrp);
 static const struct inode_operations cgroup_dir_inode_operations;
@@ -860,6 +861,11 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
 	iput(inode);
 }
 
+static int cgroup_delete(const struct dentry *d)
+{
+	return 1;
+}
+
 static void remove_dir(struct dentry *d)
 {
 	struct dentry *parent = dget(d->d_parent);
@@ -1451,6 +1457,7 @@ static int cgroup_get_rootdir(struct super_block *sb)
 {
 	static const struct dentry_operations cgroup_dops = {
 		.d_iput = cgroup_diput,
+		.d_delete = cgroup_delete,
 	};
 
 	struct inode *inode =
@@ -2195,12 +2202,20 @@ static const struct file_operations cgroup_file_operations = {
 };
 
 static const struct inode_operations cgroup_dir_inode_operations = {
-	.lookup = simple_lookup,
+	.lookup = cgroup_lookup,
 	.mkdir = cgroup_mkdir,
 	.rmdir = cgroup_rmdir,
 	.rename = cgroup_rename,
 };
 
+static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+{
+	if (dentry->d_name.len > NAME_MAX)
+		return ERR_PTR(-ENAMETOOLONG);
+	d_add(dentry, NULL);
+	return NULL;
+}
+
 /*
  * Check if a file is a control file
  */
#3 lore raw
In reply to Li Zefan
Quoted 14 lines · Li Zefan

Just mount the cgroupfs:

# mount -t cgroup -o cpuset xxx /mnt
(oops!!)

The bug is caused by:

=========
commit 0df6a63f8735a7c8a877878bc215d4312e41ef81

Author: Al Viro <[email protected]>
Date:   Tue Dec 21 13:29:29 2010 -0500

switch cgroup

Quoted 8 lines

switching it to s_d_op allows to kill the cgroup_lookup() kludge.

=========

This line:

+ sb->s_d_op = &cgroup_dops;

Oh, crap... Right, it's using simple_lookup(). Let me check if anything else might be stepping on that.

Umm... There's a very strange codepath in btrfs that also might. Interesting. Fix for cgroup, AFAICS, should be this:

---

kernel/cgroup.c +16 -1
index 5c5f4cc..ffb7bba 100644
@@ -764,6 +764,7 @@ EXPORT_SYMBOL_GPL(cgroup_unlock);
  */
 
 static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+static struct dentry *cgroup_lookup(struct inode *, struct dentry *, struct nameidata *);
 static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
 static int cgroup_populate_dir(struct cgroup *cgrp);
 static const struct inode_operations cgroup_dir_inode_operations;
@@ -860,6 +861,11 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
 	iput(inode);
 }
 
+static int cgroup_delete(const struct dentry *d)
+{
+	return 1;
+}
+
 static void remove_dir(struct dentry *d)
 {
 	struct dentry *parent = dget(d->d_parent);
@@ -1451,6 +1457,7 @@ static int cgroup_get_rootdir(struct super_block *sb)
 {
 	static const struct dentry_operations cgroup_dops = {
 		.d_iput = cgroup_diput,
+		.d_delete = cgroup_delete,
 	};
 
 	struct inode *inode =
@@ -2195,12 +2202,20 @@ static const struct file_operations cgroup_file_operations = {
 };
 
 static const struct inode_operations cgroup_dir_inode_operations = {
-	.lookup = simple_lookup,
+	.lookup = cgroup_lookup,
 	.mkdir = cgroup_mkdir,
 	.rmdir = cgroup_rmdir,
 	.rename = cgroup_rename,
 };
 
+static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+{
+	if (dentry->d_name.len > NAME_MAX)
+		return ERR_PTR(-ENAMETOOLONG);
+	d_add(dentry, NULL);
+	return NULL;
+}
+
 /*
  * Check if a file is a control file
  */
author
#4 lore raw
Quoted 22 lines · Al Viro
Quoted 21 lines · Li Zefan

Just mount the cgroupfs:

# mount -t cgroup -o cpuset xxx /mnt
(oops!!)

The bug is caused by:

=========
commit 0df6a63f8735a7c8a877878bc215d4312e41ef81

Author: Al Viro <[email protected]>
Date:   Tue Dec 21 13:29:29 2010 -0500

switch cgroup

switching it to s_d_op allows to kill the cgroup_lookup() kludge.

=========

This line:

Quoted 8 lines
Quoted 1 line

+ sb->s_d_op = &cgroup_dops;

Oh, crap... Right, it's using simple_lookup(). Let me check if anything else might be stepping on that.

Umm... There's a very strange codepath in btrfs that also might. Interesting. Fix for cgroup, AFAICS, should be this:

patch tested. thanks!

#6 lore raw
In reply to a message not in the archive
Quoted 22 lines · Al Viro
Quoted 21 lines · Li Zefan

Just mount the cgroupfs:

# mount -t cgroup -o cpuset xxx /mnt
(oops!!)

The bug is caused by:

=========
commit 0df6a63f8735a7c8a877878bc215d4312e41ef81

Author: Al Viro <viro-RmSDqhL/[email protected]>
Date:   Tue Dec 21 13:29:29 2010 -0500

switch cgroup

switching it to s_d_op allows to kill the cgroup_lookup() kludge.

=========

This line:

Quoted 8 lines
Quoted 1 line

+ sb->s_d_op = &cgroup_dops;

Oh, crap... Right, it's using simple_lookup(). Let me check if anything else might be stepping on that.

Umm... There's a very strange codepath in btrfs that also might. Interesting. Fix for cgroup, AFAICS, should be this:

patch tested. thanks!