aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/devtmpfs.c
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2009-10-28 14:51:06 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 14:24:51 -0500
commited413ae6e7813d3227eef43bc6d84ca4f4fe6b21 (patch)
tree648580b63fd02a8abd55b1f84171f93c2956dbe5 /drivers/base/devtmpfs.c
parent0092699643703aefca6af0aa758a73f1624d53be (diff)
Driver core: devtmpfs: prevent concurrent subdirectory creation and removal
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base/devtmpfs.c')
-rw-r--r--drivers/base/devtmpfs.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index 48526b935682..1cf498fd2b52 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -32,6 +32,8 @@ static int dev_mount = 1;
32static int dev_mount; 32static int dev_mount;
33#endif 33#endif
34 34
35static rwlock_t dirlock;
36
35static int __init mount_param(char *str) 37static int __init mount_param(char *str)
36{ 38{
37 dev_mount = simple_strtoul(str, NULL, 0); 39 dev_mount = simple_strtoul(str, NULL, 0);
@@ -86,16 +88,12 @@ static int dev_mkdir(const char *name, mode_t mode)
86 88
87static int create_path(const char *nodepath) 89static int create_path(const char *nodepath)
88{ 90{
89 char *path;
90 struct nameidata nd; 91 struct nameidata nd;
91 int err = 0; 92 int err = 0;
92 93
93 path = kstrdup(nodepath, GFP_KERNEL); 94 read_lock(&dirlock);
94 if (!path)
95 return -ENOMEM;
96
97 err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, 95 err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
98 path, LOOKUP_PARENT, &nd); 96 nodepath, LOOKUP_PARENT, &nd);
99 if (err == 0) { 97 if (err == 0) {
100 struct dentry *dentry; 98 struct dentry *dentry;
101 99
@@ -107,14 +105,17 @@ static int create_path(const char *nodepath)
107 dput(dentry); 105 dput(dentry);
108 } 106 }
109 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 107 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
110
111 path_put(&nd.path); 108 path_put(&nd.path);
112 } else if (err == -ENOENT) { 109 } else if (err == -ENOENT) {
110 char *path;
113 char *s; 111 char *s;
114 112
115 /* parent directories do not exist, create them */ 113 /* parent directories do not exist, create them */
114 path = kstrdup(nodepath, GFP_KERNEL);
115 if (!path)
116 return -ENOMEM;
116 s = path; 117 s = path;
117 while (1) { 118 for (;;) {
118 s = strchr(s, '/'); 119 s = strchr(s, '/');
119 if (!s) 120 if (!s)
120 break; 121 break;
@@ -125,9 +126,10 @@ static int create_path(const char *nodepath)
125 s[0] = '/'; 126 s[0] = '/';
126 s++; 127 s++;
127 } 128 }
129 kfree(path);
128 } 130 }
131 read_unlock(&dirlock);
129 132
130 kfree(path);
131 return err; 133 return err;
132} 134}
133 135
@@ -234,7 +236,8 @@ static int delete_path(const char *nodepath)
234 if (!path) 236 if (!path)
235 return -ENOMEM; 237 return -ENOMEM;
236 238
237 while (1) { 239 write_lock(&dirlock);
240 for (;;) {
238 char *base; 241 char *base;
239 242
240 base = strrchr(path, '/'); 243 base = strrchr(path, '/');
@@ -245,6 +248,7 @@ static int delete_path(const char *nodepath)
245 if (err) 248 if (err)
246 break; 249 break;
247 } 250 }
251 write_unlock(&dirlock);
248 252
249 kfree(path); 253 kfree(path);
250 return err; 254 return err;
@@ -360,6 +364,8 @@ int __init devtmpfs_init(void)
360 int err; 364 int err;
361 struct vfsmount *mnt; 365 struct vfsmount *mnt;
362 366
367 rwlock_init(&dirlock);
368
363 err = register_filesystem(&dev_fs_type); 369 err = register_filesystem(&dev_fs_type);
364 if (err) { 370 if (err) {
365 printk(KERN_ERR "devtmpfs: unable to register devtmpfs " 371 printk(KERN_ERR "devtmpfs: unable to register devtmpfs "