configfs: add missing mutex_unlock()
PATCH 1/1 configfs: add missing mutex_unlock()
From: Akinobu Mita <[email protected]>
Subject: [PATCH] configfs: add missing mutex_unlock()
Add missing mutex_unlock() on d_alloc() failure in configfs_register_subsystem().
--- fs/configfs/dir.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/configfs/dir.c +3 -1
@@ -1168,8 +1168,10 @@ int configfs_register_subsystem(struct c err = -ENOMEM ; dentry =d_alloc (configfs_sb->s_root, &name); -if (!dentry) +if (!dentry) { +mutex_unlock (&configfs_sb->s_root->d_inode->i_mutex); goto out_release; + }d_add (dentry,NULL );
Quoted 11 lines · On Sunday 04 March 2007 14:38:12 Akinobu Mita wrote:
(quoted diff) +0
-0@@ -1168,8 +1168,10 @@ int configfs_register_subsystem(struct c
err =-ENOMEM;
dentry =d_alloc(configfs_sb->s_root, &name);
- if (!dentry)
+ if (!dentry) {
+ mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex); gotoout_release;
+ }
d_add(dentry, NULL);
This should be changed to jump to a new exit point, before the mutex_unlock at the end of the function. Having multiple places in the function that release the same lock easily leads to the kind of bug you are fixing here.
Arnd <><
Quoted 16 lines · Arnd Bergmann
Quoted 11 lines · On Sunday 04 March 2007 14:38:12 Akinobu Mita wrote:
(quoted diff) +0
-0@@ -1168,8 +1168,10 @@ int configfs_register_subsystem(struct c
err =-ENOMEM;
dentry =d_alloc(configfs_sb->s_root, &name);
- if (!dentry)
+ if (!dentry) {
+ mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex); gotoout_release;
+ }
d_add(dentry, NULL);This should be changed to jump to a new exit point, before the
mutex_unlockat the end of the function. Having multiple places in the function that release the same lock easily leads to the kind of bug you are fixing here.
Agreed. Please see the patch below (untested).
fs/configfs/dir.c +12 -11
@@ -1169,25 +1169,26 @@ int configfs_register_subsystem(struct c err = -ENOMEM ; dentry =d_alloc (configfs_sb->s_root, &name);if (!dentry) - goto out_release; + goto out_unlock;d_add (dentry,NULL ); err =configfs_attach_group (sd->s_element, &group->cg_item, dentry); -if (!err) - dentry =NULL ; -else -d_delete (dentry); +if (err) + goto out_d_delete;mutex_unlock (&configfs_sb->s_root->d_inode->i_mutex); -if (dentry) { -dput (dentry); -out_release: -unlink_group (group); -configfs_release_fs (); - } +return 0 ; + +out_d_delete: +d_delete (dentry); +dput (dentry); +out_unlock: +mutex_unlock (&configfs_sb->s_root->d_inode->i_mutex); +unlink_group (group); +configfs_release_fs ();return err; }
First, thank you Akinobu for discovering the bug.
Quoted 6 lines · Akinobu Mita
Quoted 3 lines · Arnd Bergmann
This should be changed to jump to a new exit point, before the
mutex_unlockat the end of the function. Having multiple places in the function that release the same lock easily leads to the kind of bug you are fixing here.Agreed. Please see the patch below (untested).
Jumping isn't always the solution. The new patch, while better
than the first, still calls mutex_unlock() in two places. The following patch keeps it all in one code path, and keeps all dentry modification underneath a single mutex_lock()/unlock() pair. What do you think? I'm building it to test as we speak.
Joel
fs/configfs/dir.c +12 -15
@@ -1142,25 +1142,22 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) err = -ENOMEM ; dentry =d_alloc (configfs_sb->s_root, &name); -if (!dentry) - goto out_release; - -d_add (dentry,NULL ); +if (dentry) { +d_add (dentry,NULL ); - err =configfs_attach_group (sd->s_element, &group->cg_item, - dentry); -if (!err) - dentry =NULL ; -else -d_delete (dentry); + err =configfs_attach_group (sd->s_element, &group->cg_item, + dentry); +if (err) { +d_delete (dentry); +dput (dentry); + } + }mutex_unlock (&configfs_sb->s_root->d_inode->i_mutex); -if (dentry) { -dput (dentry); -out_release: -unlink_group (group); -configfs_release_fs (); +if (err) { +unlink_group (group); +configfs_release_fs (); }return err;
Signature · 10 lines
"Nobody loves me, Nobody seems to care. Troubles and worries, people, You know I've had my share." Joel Becker Principal Software Developer Oracle E-mail: [email protected] Phone: (650) 506-8127