Re: [PATCH 04/27] Driver core: devtmpfs: prevent concurrent subdirectory creation and removal

From: Kirill A. Shutemov
Date: Mon Dec 21 2009 - 08:37:58 EST


v2.6.33-rc1-96-gdd59f6c:

...
[ 0.868406] sched: BUG: sleeping function called from invalid
context at kernel/mutex.c:94
[ 0.868635] sched: in_atomic(): 1, irqs_disabled(): 0, pid: 642,
name: modprobe
[ 0.868858] Pid: 642, comm: modprobe Not tainted 2.6.33-rc1 #39
[ 0.868998] Call Trace:
[ 0.869157] [<c1024f88>] __might_sleep+0xef/0xf7
[ 0.869313] [<c129b6a3>] mutex_lock+0x1f/0x39
[ 0.869469] [<c10ca984>] do_lookup+0x87/0x139
[ 0.869615] [<c10cb02f>] link_path_walk+0x22b/0x520
[ 0.869755] [<c10cb435>] path_walk+0x3f/0x89
[ 0.869895] [<c10cb608>] vfs_path_lookup+0x53/0x99
[ 0.870038] [<c11e6a9b>] dev_mkdir.clone.0+0x23/0x8d
[ 0.870195] [<c10ca6ef>] ? mntput+0x18/0x1a
[ 0.870371] [<c10ca7d3>] ? path_put+0x1a/0x1d
[ 0.870522] [<c10cb63f>] ? vfs_path_lookup+0x8a/0x99
[ 0.870668] [<c129ee99>] ? add_preempt_count+0x8/0x75
[ 0.870808] [<c11e6bbc>] devtmpfs_create_node+0xb7/0x1f3
[ 0.870950] [<c10ffc78>] ? sysfs_find_dirent+0x1b/0x2c
[ 0.871091] [<c10fff50>] ? __sysfs_add_one+0x2a/0x78
[ 0.871249] [<c1100313>] ? sysfs_addrm_finish+0x1e/0x93
[ 0.871402] [<c11004d0>] ? sysfs_add_one+0x18/0xe1
[ 0.871542] [<c1100886>] ? sysfs_do_create_link+0xbc/0x109
[ 0.871683] [<c11008f3>] ? sysfs_create_link+0xf/0x14
[ 0.871823] [<c11e1e69>] device_add+0x141/0x44d
[ 0.871963] [<c1003935>] ? arch_irq_stat_cpu+0x5d/0xc8
[ 0.872137] [<c11e218c>] device_register+0x17/0x1a
[ 0.872290] [<c11e2206>] device_create_vargs+0x77/0x98
[ 0.872435] [<f8045000>] ? dm_init+0x0/0x3b [dm_mod]
[ 0.872574] [<c11e2247>] device_create+0x20/0x22
[ 0.872715] [<c11c96dc>] misc_register+0x9d/0xf1
[ 0.872859] [<f804521a>] dm_interface_init+0x36/0x74 [dm_mod]
[ 0.873003] [<f8045011>] dm_init+0x11/0x3b [dm_mod]
[ 0.873144] [<c1001143>] do_one_initcall+0x51/0x13f
[ 0.873311] [<c105c0db>] sys_init_module+0xac/0x1e0
[ 0.873456] [<c129c820>] syscall_call+0x7/0xb
....
[ 13.438106] sched: BUG: sleeping function called from invalid
context at kernel/mutex.c:94
[ 13.438110] sched: in_atomic(): 1, irqs_disabled(): 0, pid: 18387,
name: modprobe
[ 13.438114] Pid: 18387, comm: modprobe Not tainted 2.6.33-rc1 #39
[ 13.438116] Call Trace:
[ 13.438124] [<c1024f88>] __might_sleep+0xef/0xf7
[ 13.438129] [<c129b6a3>] mutex_lock+0x1f/0x39
[ 13.438133] [<c10ca984>] do_lookup+0x87/0x139
[ 13.438136] [<c10cb02f>] link_path_walk+0x22b/0x520
[ 13.438140] [<c10cb435>] path_walk+0x3f/0x89
[ 13.438143] [<c10cb608>] vfs_path_lookup+0x53/0x99
[ 13.438147] [<c11e6a9b>] dev_mkdir.clone.0+0x23/0x8d
[ 13.438150] [<c10ca6ef>] ? mntput+0x18/0x1a
[ 13.438153] [<c10ca7d3>] ? path_put+0x1a/0x1d
[ 13.438156] [<c10cb63f>] ? vfs_path_lookup+0x8a/0x99
[ 13.438159] [<c129ee99>] ? add_preempt_count+0x8/0x75
[ 13.438162] [<c11e6bbc>] devtmpfs_create_node+0xb7/0x1f3
[ 13.438166] [<c10ffc78>] ? sysfs_find_dirent+0x1b/0x2c
[ 13.438168] [<c10fff50>] ? __sysfs_add_one+0x2a/0x78
[ 13.438171] [<c1100313>] ? sysfs_addrm_finish+0x1e/0x93
[ 13.438173] [<c11004d0>] ? sysfs_add_one+0x18/0xe1
[ 13.438176] [<c1100886>] ? sysfs_do_create_link+0xbc/0x109
[ 13.438179] [<c11008f3>] ? sysfs_create_link+0xf/0x14
[ 13.438183] [<c11e1e69>] device_add+0x141/0x44d
[ 13.438187] [<c100323a>] ? do_stack_segment+0x33/0x5c
[ 13.438190] [<c11e218c>] device_register+0x17/0x1a
[ 13.438193] [<c11e2206>] device_create_vargs+0x77/0x98
[ 13.438196] [<c11e2247>] device_create+0x20/0x22
[ 13.438203] [<f9ea153a>] snd_register_device_for_dev+0xfa/0x158 [snd]
[ 13.438208] [<fa2150d5>] alsa_timer_init+0xd5/0x129 [snd_timer]
[ 13.438213] [<fa215000>] ? alsa_timer_init+0x0/0x129 [snd_timer]
[ 13.438216] [<c1001143>] do_one_initcall+0x51/0x13f
[ 13.438220] [<c105c0db>] sys_init_module+0xac/0x1e0
[ 13.438223] [<c129c820>] syscall_call+0x7/0xb
....
[ 56.108746] Call Trace:
[ 56.108754] [<c1024f88>] __might_sleep+0xef/0xf7
[ 56.108758] [<c129b6a3>] mutex_lock+0x1f/0x39
[ 56.108762] [<c10ca984>] do_lookup+0x87/0x139
[ 56.108765] [<c10cb02f>] link_path_walk+0x22b/0x520
[ 56.108768] [<c10cb435>] path_walk+0x3f/0x89
[ 56.108771] [<c10cb608>] vfs_path_lookup+0x53/0x99
[ 56.108775] [<c11e6a9b>] dev_mkdir.clone.0+0x23/0x8d
[ 56.108778] [<c10ca6ef>] ? mntput+0x18/0x1a
[ 56.108780] [<c10ca7d3>] ? path_put+0x1a/0x1d
[ 56.108783] [<c10cb63f>] ? vfs_path_lookup+0x8a/0x99
[ 56.108786] [<c129ee99>] ? add_preempt_count+0x8/0x75
[ 56.108789] [<c11e6bbc>] devtmpfs_create_node+0xb7/0x1f3
[ 56.108792] [<c10ffc78>] ? sysfs_find_dirent+0x1b/0x2c
[ 56.108795] [<c10fff50>] ? __sysfs_add_one+0x2a/0x78
[ 56.108797] [<c1100313>] ? sysfs_addrm_finish+0x1e/0x93
[ 56.108800] [<c11004d0>] ? sysfs_add_one+0x18/0xe1
[ 56.108803] [<c1100886>] ? sysfs_do_create_link+0xbc/0x109
[ 56.108805] [<c11008f3>] ? sysfs_create_link+0xf/0x14
[ 56.108809] [<c11e1e69>] device_add+0x141/0x44d
[ 56.108813] [<c100303a>] ? do_spurious_interrupt_bug+0xa/0x2a
[ 56.108816] [<c11e218c>] device_register+0x17/0x1a
[ 56.108827] [<f818d4e9>] drm_sysfs_device_add+0x71/0x94 [drm]
[ 56.108837] [<f818b6eb>] drm_get_minor+0x1a5/0x216 [drm]
[ 56.108846] [<f818ba1b>] drm_get_dev+0x2bf/0x3bc [drm]
[ 56.108850] [<c11721b8>] ? kobject_get+0x12/0x17
[ 56.108858] [<f81874ea>] drm_init+0x81/0xba [drm]
[ 56.108875] [<f81b9000>] ? radeon_init+0x0/0xae [radeon]
[ 56.108891] [<f81b90ac>] radeon_init+0xac/0xae [radeon]
[ 56.108893] [<c1001143>] do_one_initcall+0x51/0x13f
[ 56.108898] [<c105c0db>] sys_init_module+0xac/0x1e0
[ 56.108900] [<c129c820>] syscall_call+0x7/0xb


I guess it can be related to this commit.

Config attached.


On Sat, Dec 12, 2009 at 12:24 AM, Greg Kroah-Hartman <gregkh@xxxxxxx> wrote:
> From: Kay Sievers <kay.sievers@xxxxxxxx>
>
> Signed-off-by: Kay Sievers <kay.sievers@xxxxxxxx>
> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
> ---
> Âdrivers/base/devtmpfs.c | Â 26 ++++++++++++++++----------
> Â1 files changed, 16 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
> index 48526b9..1cf498f 100644
> --- a/drivers/base/devtmpfs.c
> +++ b/drivers/base/devtmpfs.c
> @@ -32,6 +32,8 @@ static int dev_mount = 1;
> Âstatic int dev_mount;
> Â#endif
>
> +static rwlock_t dirlock;
> +
> Âstatic int __init mount_param(char *str)
> Â{
> Â Â Â Âdev_mount = simple_strtoul(str, NULL, 0);
> @@ -86,16 +88,12 @@ static int dev_mkdir(const char *name, mode_t mode)
>
> Âstatic int create_path(const char *nodepath)
> Â{
> - Â Â Â char *path;
> Â Â Â Âstruct nameidata nd;
> Â Â Â Âint err = 0;
>
> - Â Â Â path = kstrdup(nodepath, GFP_KERNEL);
> - Â Â Â if (!path)
> - Â Â Â Â Â Â Â return -ENOMEM;
> -
> + Â Â Â read_lock(&dirlock);
> Â Â Â Âerr = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
> - Â Â Â Â Â Â Â Â Â Â Â Â Â Â path, LOOKUP_PARENT, &nd);
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â nodepath, LOOKUP_PARENT, &nd);
> Â Â Â Âif (err == 0) {
> Â Â Â Â Â Â Â Âstruct dentry *dentry;
>
> @@ -107,14 +105,17 @@ static int create_path(const char *nodepath)
> Â Â Â Â Â Â Â Â Â Â Â Âdput(dentry);
> Â Â Â Â Â Â Â Â}
> Â Â Â Â Â Â Â Âmutex_unlock(&nd.path.dentry->d_inode->i_mutex);
> -
> Â Â Â Â Â Â Â Âpath_put(&nd.path);
> Â Â Â Â} else if (err == -ENOENT) {
> + Â Â Â Â Â Â Â char *path;
> Â Â Â Â Â Â Â Âchar *s;
>
> Â Â Â Â Â Â Â Â/* parent directories do not exist, create them */
> + Â Â Â Â Â Â Â path = kstrdup(nodepath, GFP_KERNEL);
> + Â Â Â Â Â Â Â if (!path)
> + Â Â Â Â Â Â Â Â Â Â Â return -ENOMEM;
> Â Â Â Â Â Â Â Âs = path;
> - Â Â Â Â Â Â Â while (1) {
> + Â Â Â Â Â Â Â for (;;) {
> Â Â Â Â Â Â Â Â Â Â Â Âs = strchr(s, '/');
> Â Â Â Â Â Â Â Â Â Â Â Âif (!s)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âbreak;
> @@ -125,9 +126,10 @@ static int create_path(const char *nodepath)
> Â Â Â Â Â Â Â Â Â Â Â Âs[0] = '/';
> Â Â Â Â Â Â Â Â Â Â Â Âs++;
> Â Â Â Â Â Â Â Â}
> + Â Â Â Â Â Â Â kfree(path);
> Â Â Â Â}
> + Â Â Â read_unlock(&dirlock);
>
> - Â Â Â kfree(path);
> Â Â Â Âreturn err;
> Â}
>
> @@ -234,7 +236,8 @@ static int delete_path(const char *nodepath)
> Â Â Â Âif (!path)
> Â Â Â Â Â Â Â Âreturn -ENOMEM;
>
> - Â Â Â while (1) {
> + Â Â Â write_lock(&dirlock);
> + Â Â Â for (;;) {
> Â Â Â Â Â Â Â Âchar *base;
>
> Â Â Â Â Â Â Â Âbase = strrchr(path, '/');
> @@ -245,6 +248,7 @@ static int delete_path(const char *nodepath)
> Â Â Â Â Â Â Â Âif (err)
> Â Â Â Â Â Â Â Â Â Â Â Âbreak;
> Â Â Â Â}
> + Â Â Â write_unlock(&dirlock);
>
> Â Â Â Âkfree(path);
> Â Â Â Âreturn err;
> @@ -360,6 +364,8 @@ int __init devtmpfs_init(void)
> Â Â Â Âint err;
> Â Â Â Âstruct vfsmount *mnt;
>
> + Â Â Â rwlock_init(&dirlock);
> +
> Â Â Â Âerr = register_filesystem(&dev_fs_type);
> Â Â Â Âif (err) {
> Â Â Â Â Â Â Â Âprintk(KERN_ERR "devtmpfs: unable to register devtmpfs "
> --
> 1.6.5.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at Âhttp://vger.kernel.org/majordomo-info.html
> Please read the FAQ at Âhttp://www.tux.org/lkml/
>

Attachment: .config
Description: Binary data