aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-22 22:02:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-22 22:02:39 -0400
commitbbd9d6f7fbb0305c9a592bf05a32e87eb364a4ff (patch)
tree12b2bb4202b05f6ae6a43c6ce830a0472043dbe5 /drivers/base
parent8e204874db000928e37199c2db82b7eb8966cc3c (diff)
parent5a9a43646cf709312d71eca71cef90ad802f28f9 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (107 commits) vfs: use ERR_CAST for err-ptr tossing in lookup_instantiate_filp isofs: Remove global fs lock jffs2: fix IN_DELETE_SELF on overwriting rename() killing a directory fix IN_DELETE_SELF on overwriting rename() on ramfs et.al. mm/truncate.c: fix build for CONFIG_BLOCK not enabled fs:update the NOTE of the file_operations structure Remove dead code in dget_parent() AFS: Fix silly characters in a comment switch d_add_ci() to d_splice_alias() in "found negative" case as well simplify gfs2_lookup() jfs_lookup(): don't bother with . or .. get rid of useless dget_parent() in btrfs rename() and link() get rid of useless dget_parent() in fs/btrfs/ioctl.c fs: push i_mutex and filemap_write_and_wait down into ->fsync() handlers drivers: fix up various ->llseek() implementations fs: handle SEEK_HOLE/SEEK_DATA properly in all fs's that define their own llseek Ext4: handle SEEK_HOLE/SEEK_DATA generically Btrfs: implement our own ->llseek fs: add SEEK_HOLE and SEEK_DATA flags reiserfs: make reiserfs default to barrier=flush ... Fix up trivial conflicts in fs/xfs/linux-2.6/xfs_super.c due to the new shrinker callout for the inode cache, that clashed with the xfs code to start the periodic workers later.
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/devtmpfs.c337
1 files changed, 198 insertions, 139 deletions
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index 82bbb5967aa9..6d678c99512e 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -21,12 +21,11 @@
21#include <linux/fs.h> 21#include <linux/fs.h>
22#include <linux/shmem_fs.h> 22#include <linux/shmem_fs.h>
23#include <linux/ramfs.h> 23#include <linux/ramfs.h>
24#include <linux/cred.h>
25#include <linux/sched.h> 24#include <linux/sched.h>
26#include <linux/init_task.h>
27#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/kthread.h>
28 27
29static struct vfsmount *dev_mnt; 28static struct task_struct *thread;
30 29
31#if defined CONFIG_DEVTMPFS_MOUNT 30#if defined CONFIG_DEVTMPFS_MOUNT
32static int mount_dev = 1; 31static int mount_dev = 1;
@@ -34,7 +33,16 @@ static int mount_dev = 1;
34static int mount_dev; 33static int mount_dev;
35#endif 34#endif
36 35
37static DEFINE_MUTEX(dirlock); 36static DEFINE_SPINLOCK(req_lock);
37
38static struct req {
39 struct req *next;
40 struct completion done;
41 int err;
42 const char *name;
43 mode_t mode; /* 0 => delete */
44 struct device *dev;
45} *requests;
38 46
39static int __init mount_param(char *str) 47static int __init mount_param(char *str)
40{ 48{
@@ -68,131 +76,152 @@ static inline int is_blockdev(struct device *dev)
68static inline int is_blockdev(struct device *dev) { return 0; } 76static inline int is_blockdev(struct device *dev) { return 0; }
69#endif 77#endif
70 78
79int devtmpfs_create_node(struct device *dev)
80{
81 const char *tmp = NULL;
82 struct req req;
83
84 if (!thread)
85 return 0;
86
87 req.mode = 0;
88 req.name = device_get_devnode(dev, &req.mode, &tmp);
89 if (!req.name)
90 return -ENOMEM;
91
92 if (req.mode == 0)
93 req.mode = 0600;
94 if (is_blockdev(dev))
95 req.mode |= S_IFBLK;
96 else
97 req.mode |= S_IFCHR;
98
99 req.dev = dev;
100
101 init_completion(&req.done);
102
103 spin_lock(&req_lock);
104 req.next = requests;
105 requests = &req;
106 spin_unlock(&req_lock);
107
108 wake_up_process(thread);
109 wait_for_completion(&req.done);
110
111 kfree(tmp);
112
113 return req.err;
114}
115
116int devtmpfs_delete_node(struct device *dev)
117{
118 const char *tmp = NULL;
119 struct req req;
120
121 if (!thread)
122 return 0;
123
124 req.name = device_get_devnode(dev, NULL, &tmp);
125 if (!req.name)
126 return -ENOMEM;
127
128 req.mode = 0;
129 req.dev = dev;
130
131 init_completion(&req.done);
132
133 spin_lock(&req_lock);
134 req.next = requests;
135 requests = &req;
136 spin_unlock(&req_lock);
137
138 wake_up_process(thread);
139 wait_for_completion(&req.done);
140
141 kfree(tmp);
142 return req.err;
143}
144
71static int dev_mkdir(const char *name, mode_t mode) 145static int dev_mkdir(const char *name, mode_t mode)
72{ 146{
73 struct nameidata nd;
74 struct dentry *dentry; 147 struct dentry *dentry;
148 struct path path;
75 int err; 149 int err;
76 150
77 err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, 151 dentry = kern_path_create(AT_FDCWD, name, &path, 1);
78 name, LOOKUP_PARENT, &nd); 152 if (IS_ERR(dentry))
79 if (err) 153 return PTR_ERR(dentry);
80 return err; 154
81 155 err = vfs_mkdir(path.dentry->d_inode, dentry, mode);
82 dentry = lookup_create(&nd, 1); 156 if (!err)
83 if (!IS_ERR(dentry)) { 157 /* mark as kernel-created inode */
84 err = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); 158 dentry->d_inode->i_private = &thread;
85 if (!err) 159 dput(dentry);
86 /* mark as kernel-created inode */ 160 mutex_unlock(&path.dentry->d_inode->i_mutex);
87 dentry->d_inode->i_private = &dev_mnt; 161 path_put(&path);
88 dput(dentry);
89 } else {
90 err = PTR_ERR(dentry);
91 }
92
93 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
94 path_put(&nd.path);
95 return err; 162 return err;
96} 163}
97 164
98static int create_path(const char *nodepath) 165static int create_path(const char *nodepath)
99{ 166{
167 char *path;
168 char *s;
100 int err; 169 int err;
101 170
102 mutex_lock(&dirlock); 171 /* parent directories do not exist, create them */
103 err = dev_mkdir(nodepath, 0755); 172 path = kstrdup(nodepath, GFP_KERNEL);
104 if (err == -ENOENT) { 173 if (!path)
105 char *path; 174 return -ENOMEM;
106 char *s; 175
107 176 s = path;
108 /* parent directories do not exist, create them */ 177 for (;;) {
109 path = kstrdup(nodepath, GFP_KERNEL); 178 s = strchr(s, '/');
110 if (!path) { 179 if (!s)
111 err = -ENOMEM; 180 break;
112 goto out; 181 s[0] = '\0';
113 } 182 err = dev_mkdir(path, 0755);
114 s = path; 183 if (err && err != -EEXIST)
115 for (;;) { 184 break;
116 s = strchr(s, '/'); 185 s[0] = '/';
117 if (!s) 186 s++;
118 break;
119 s[0] = '\0';
120 err = dev_mkdir(path, 0755);
121 if (err && err != -EEXIST)
122 break;
123 s[0] = '/';
124 s++;
125 }
126 kfree(path);
127 } 187 }
128out: 188 kfree(path);
129 mutex_unlock(&dirlock);
130 return err; 189 return err;
131} 190}
132 191
133int devtmpfs_create_node(struct device *dev) 192static int handle_create(const char *nodename, mode_t mode, struct device *dev)
134{ 193{
135 const char *tmp = NULL;
136 const char *nodename;
137 const struct cred *curr_cred;
138 mode_t mode = 0;
139 struct nameidata nd;
140 struct dentry *dentry; 194 struct dentry *dentry;
195 struct path path;
141 int err; 196 int err;
142 197
143 if (!dev_mnt) 198 dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
144 return 0; 199 if (dentry == ERR_PTR(-ENOENT)) {
145
146 nodename = device_get_devnode(dev, &mode, &tmp);
147 if (!nodename)
148 return -ENOMEM;
149
150 if (mode == 0)
151 mode = 0600;
152 if (is_blockdev(dev))
153 mode |= S_IFBLK;
154 else
155 mode |= S_IFCHR;
156
157 curr_cred = override_creds(&init_cred);
158
159 err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
160 nodename, LOOKUP_PARENT, &nd);
161 if (err == -ENOENT) {
162 create_path(nodename); 200 create_path(nodename);
163 err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, 201 dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
164 nodename, LOOKUP_PARENT, &nd);
165 } 202 }
166 if (err) 203 if (IS_ERR(dentry))
167 goto out; 204 return PTR_ERR(dentry);
168 205
169 dentry = lookup_create(&nd, 0); 206 err = vfs_mknod(path.dentry->d_inode,
170 if (!IS_ERR(dentry)) { 207 dentry, mode, dev->devt);
171 err = vfs_mknod(nd.path.dentry->d_inode, 208 if (!err) {
172 dentry, mode, dev->devt); 209 struct iattr newattrs;
173 if (!err) { 210
174 struct iattr newattrs; 211 /* fixup possibly umasked mode */
175 212 newattrs.ia_mode = mode;
176 /* fixup possibly umasked mode */ 213 newattrs.ia_valid = ATTR_MODE;
177 newattrs.ia_mode = mode; 214 mutex_lock(&dentry->d_inode->i_mutex);
178 newattrs.ia_valid = ATTR_MODE; 215 notify_change(dentry, &newattrs);
179 mutex_lock(&dentry->d_inode->i_mutex); 216 mutex_unlock(&dentry->d_inode->i_mutex);
180 notify_change(dentry, &newattrs); 217
181 mutex_unlock(&dentry->d_inode->i_mutex); 218 /* mark as kernel-created inode */
182 219 dentry->d_inode->i_private = &thread;
183 /* mark as kernel-created inode */
184 dentry->d_inode->i_private = &dev_mnt;
185 }
186 dput(dentry);
187 } else {
188 err = PTR_ERR(dentry);
189 } 220 }
221 dput(dentry);
190 222
191 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 223 mutex_unlock(&path.dentry->d_inode->i_mutex);
192 path_put(&nd.path); 224 path_put(&path);
193out:
194 kfree(tmp);
195 revert_creds(curr_cred);
196 return err; 225 return err;
197} 226}
198 227
@@ -202,8 +231,7 @@ static int dev_rmdir(const char *name)
202 struct dentry *dentry; 231 struct dentry *dentry;
203 int err; 232 int err;
204 233
205 err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, 234 err = kern_path_parent(name, &nd);
206 name, LOOKUP_PARENT, &nd);
207 if (err) 235 if (err)
208 return err; 236 return err;
209 237
@@ -211,7 +239,7 @@ static int dev_rmdir(const char *name)
211 dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); 239 dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
212 if (!IS_ERR(dentry)) { 240 if (!IS_ERR(dentry)) {
213 if (dentry->d_inode) { 241 if (dentry->d_inode) {
214 if (dentry->d_inode->i_private == &dev_mnt) 242 if (dentry->d_inode->i_private == &thread)
215 err = vfs_rmdir(nd.path.dentry->d_inode, 243 err = vfs_rmdir(nd.path.dentry->d_inode,
216 dentry); 244 dentry);
217 else 245 else
@@ -238,7 +266,6 @@ static int delete_path(const char *nodepath)
238 if (!path) 266 if (!path)
239 return -ENOMEM; 267 return -ENOMEM;
240 268
241 mutex_lock(&dirlock);
242 for (;;) { 269 for (;;) {
243 char *base; 270 char *base;
244 271
@@ -250,7 +277,6 @@ static int delete_path(const char *nodepath)
250 if (err) 277 if (err)
251 break; 278 break;
252 } 279 }
253 mutex_unlock(&dirlock);
254 280
255 kfree(path); 281 kfree(path);
256 return err; 282 return err;
@@ -259,7 +285,7 @@ static int delete_path(const char *nodepath)
259static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *stat) 285static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *stat)
260{ 286{
261 /* did we create it */ 287 /* did we create it */
262 if (inode->i_private != &dev_mnt) 288 if (inode->i_private != &thread)
263 return 0; 289 return 0;
264 290
265 /* does the dev_t match */ 291 /* does the dev_t match */
@@ -277,29 +303,17 @@ static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *sta
277 return 1; 303 return 1;
278} 304}
279 305
280int devtmpfs_delete_node(struct device *dev) 306static int handle_remove(const char *nodename, struct device *dev)
281{ 307{
282 const char *tmp = NULL;
283 const char *nodename;
284 const struct cred *curr_cred;
285 struct nameidata nd; 308 struct nameidata nd;
286 struct dentry *dentry; 309 struct dentry *dentry;
287 struct kstat stat; 310 struct kstat stat;
288 int deleted = 1; 311 int deleted = 1;
289 int err; 312 int err;
290 313
291 if (!dev_mnt) 314 err = kern_path_parent(nodename, &nd);
292 return 0;
293
294 nodename = device_get_devnode(dev, NULL, &tmp);
295 if (!nodename)
296 return -ENOMEM;
297
298 curr_cred = override_creds(&init_cred);
299 err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
300 nodename, LOOKUP_PARENT, &nd);
301 if (err) 315 if (err)
302 goto out; 316 return err;
303 317
304 mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); 318 mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
305 dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); 319 dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
@@ -337,9 +351,6 @@ int devtmpfs_delete_node(struct device *dev)
337 path_put(&nd.path); 351 path_put(&nd.path);
338 if (deleted && strchr(nodename, '/')) 352 if (deleted && strchr(nodename, '/'))
339 delete_path(nodename); 353 delete_path(nodename);
340out:
341 kfree(tmp);
342 revert_creds(curr_cred);
343 return err; 354 return err;
344} 355}
345 356
@@ -354,7 +365,7 @@ int devtmpfs_mount(const char *mntdir)
354 if (!mount_dev) 365 if (!mount_dev)
355 return 0; 366 return 0;
356 367
357 if (!dev_mnt) 368 if (!thread)
358 return 0; 369 return 0;
359 370
360 err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL); 371 err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL);
@@ -365,31 +376,79 @@ int devtmpfs_mount(const char *mntdir)
365 return err; 376 return err;
366} 377}
367 378
379static __initdata DECLARE_COMPLETION(setup_done);
380
381static int handle(const char *name, mode_t mode, struct device *dev)
382{
383 if (mode)
384 return handle_create(name, mode, dev);
385 else
386 return handle_remove(name, dev);
387}
388
389static int devtmpfsd(void *p)
390{
391 char options[] = "mode=0755";
392 int *err = p;
393 *err = sys_unshare(CLONE_NEWNS);
394 if (*err)
395 goto out;
396 *err = sys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, options);
397 if (*err)
398 goto out;
399 sys_chdir("/.."); /* will traverse into overmounted root */
400 sys_chroot(".");
401 complete(&setup_done);
402 while (1) {
403 spin_lock(&req_lock);
404 while (requests) {
405 struct req *req = requests;
406 requests = NULL;
407 spin_unlock(&req_lock);
408 while (req) {
409 req->err = handle(req->name, req->mode, req->dev);
410 complete(&req->done);
411 req = req->next;
412 }
413 spin_lock(&req_lock);
414 }
415 set_current_state(TASK_INTERRUPTIBLE);
416 spin_unlock(&req_lock);
417 schedule();
418 __set_current_state(TASK_RUNNING);
419 }
420 return 0;
421out:
422 complete(&setup_done);
423 return *err;
424}
425
368/* 426/*
369 * Create devtmpfs instance, driver-core devices will add their device 427 * Create devtmpfs instance, driver-core devices will add their device
370 * nodes here. 428 * nodes here.
371 */ 429 */
372int __init devtmpfs_init(void) 430int __init devtmpfs_init(void)
373{ 431{
374 int err; 432 int err = register_filesystem(&dev_fs_type);
375 struct vfsmount *mnt;
376 char options[] = "mode=0755";
377
378 err = register_filesystem(&dev_fs_type);
379 if (err) { 433 if (err) {
380 printk(KERN_ERR "devtmpfs: unable to register devtmpfs " 434 printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
381 "type %i\n", err); 435 "type %i\n", err);
382 return err; 436 return err;
383 } 437 }
384 438
385 mnt = kern_mount_data(&dev_fs_type, options); 439 thread = kthread_run(devtmpfsd, &err, "kdevtmpfs");
386 if (IS_ERR(mnt)) { 440 if (!IS_ERR(thread)) {
387 err = PTR_ERR(mnt); 441 wait_for_completion(&setup_done);
442 } else {
443 err = PTR_ERR(thread);
444 thread = NULL;
445 }
446
447 if (err) {
388 printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err); 448 printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
389 unregister_filesystem(&dev_fs_type); 449 unregister_filesystem(&dev_fs_type);
390 return err; 450 return err;
391 } 451 }
392 dev_mnt = mnt;
393 452
394 printk(KERN_INFO "devtmpfs: initialized\n"); 453 printk(KERN_INFO "devtmpfs: initialized\n");
395 return 0; 454 return 0;