Driver-Core: extend devnode callbacks to provide permissions
[linux-2.6.git] / drivers / base / devtmpfs.c
1 /*
2  * devtmpfs - kernel-maintained tmpfs-based /dev
3  *
4  * Copyright (C) 2009, Kay Sievers <kay.sievers@vrfy.org>
5  *
6  * During bootup, before any driver core device is registered,
7  * devtmpfs, a tmpfs-based filesystem is created. Every driver-core
8  * device which requests a device node, will add a node in this
9  * filesystem.
10  * By default, all devices are named after the the name of the
11  * device, owned by root and have a default mode of 0600. Subsystems
12  * can overwrite the default setting if needed.
13  */
14
15 #include <linux/kernel.h>
16 #include <linux/syscalls.h>
17 #include <linux/mount.h>
18 #include <linux/device.h>
19 #include <linux/genhd.h>
20 #include <linux/namei.h>
21 #include <linux/fs.h>
22 #include <linux/shmem_fs.h>
23 #include <linux/cred.h>
24 #include <linux/sched.h>
25 #include <linux/init_task.h>
26
27 static struct vfsmount *dev_mnt;
28
29 #if defined CONFIG_DEVTMPFS_MOUNT
30 static int dev_mount = 1;
31 #else
32 static int dev_mount;
33 #endif
34
35 static int __init mount_param(char *str)
36 {
37         dev_mount = simple_strtoul(str, NULL, 0);
38         return 1;
39 }
40 __setup("devtmpfs.mount=", mount_param);
41
42 static int dev_get_sb(struct file_system_type *fs_type, int flags,
43                       const char *dev_name, void *data, struct vfsmount *mnt)
44 {
45         return get_sb_single(fs_type, flags, data, shmem_fill_super, mnt);
46 }
47
48 static struct file_system_type dev_fs_type = {
49         .name = "devtmpfs",
50         .get_sb = dev_get_sb,
51         .kill_sb = kill_litter_super,
52 };
53
54 #ifdef CONFIG_BLOCK
55 static inline int is_blockdev(struct device *dev)
56 {
57         return dev->class == &block_class;
58 }
59 #else
60 static inline int is_blockdev(struct device *dev) { return 0; }
61 #endif
62
63 static int dev_mkdir(const char *name, mode_t mode)
64 {
65         struct nameidata nd;
66         struct dentry *dentry;
67         int err;
68
69         err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
70                               name, LOOKUP_PARENT, &nd);
71         if (err)
72                 return err;
73
74         dentry = lookup_create(&nd, 1);
75         if (!IS_ERR(dentry)) {
76                 err = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
77                 dput(dentry);
78         } else {
79                 err = PTR_ERR(dentry);
80         }
81         mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
82
83         path_put(&nd.path);
84         return err;
85 }
86
87 static int create_path(const char *nodepath)
88 {
89         char *path;
90         struct nameidata nd;
91         int err = 0;
92
93         path = kstrdup(nodepath, GFP_KERNEL);
94         if (!path)
95                 return -ENOMEM;
96
97         err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
98                               path, LOOKUP_PARENT, &nd);
99         if (err == 0) {
100                 struct dentry *dentry;
101
102                 /* create directory right away */
103                 dentry = lookup_create(&nd, 1);
104                 if (!IS_ERR(dentry)) {
105                         err = vfs_mkdir(nd.path.dentry->d_inode,
106                                         dentry, 0755);
107                         dput(dentry);
108                 }
109                 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
110
111                 path_put(&nd.path);
112         } else if (err == -ENOENT) {
113                 char *s;
114
115                 /* parent directories do not exist, create them */
116                 s = path;
117                 while (1) {
118                         s = strchr(s, '/');
119                         if (!s)
120                                 break;
121                         s[0] = '\0';
122                         err = dev_mkdir(path, 0755);
123                         if (err && err != -EEXIST)
124                                 break;
125                         s[0] = '/';
126                         s++;
127                 }
128         }
129
130         kfree(path);
131         return err;
132 }
133
134 int devtmpfs_create_node(struct device *dev)
135 {
136         const char *tmp = NULL;
137         const char *nodename;
138         const struct cred *curr_cred;
139         mode_t mode = 0;
140         struct nameidata nd;
141         struct dentry *dentry;
142         int err;
143
144         if (!dev_mnt)
145                 return 0;
146
147         nodename = device_get_devnode(dev, &mode, &tmp);
148         if (!nodename)
149                 return -ENOMEM;
150
151         if (mode == 0)
152                 mode = 0600;
153         if (is_blockdev(dev))
154                 mode |= S_IFBLK;
155         else
156                 mode |= S_IFCHR;
157
158         curr_cred = override_creds(&init_cred);
159         err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
160                               nodename, LOOKUP_PARENT, &nd);
161         if (err == -ENOENT) {
162                 /* create missing parent directories */
163                 create_path(nodename);
164                 err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
165                                       nodename, LOOKUP_PARENT, &nd);
166                 if (err)
167                         goto out;
168         }
169
170         dentry = lookup_create(&nd, 0);
171         if (!IS_ERR(dentry)) {
172                 int umask;
173
174                 umask = sys_umask(0000);
175                 err = vfs_mknod(nd.path.dentry->d_inode,
176                                 dentry, mode, dev->devt);
177                 sys_umask(umask);
178                 /* mark as kernel created inode */
179                 if (!err)
180                         dentry->d_inode->i_private = &dev_mnt;
181                 dput(dentry);
182         } else {
183                 err = PTR_ERR(dentry);
184         }
185         mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
186
187         path_put(&nd.path);
188 out:
189         kfree(tmp);
190         revert_creds(curr_cred);
191         return err;
192 }
193
194 static int dev_rmdir(const char *name)
195 {
196         struct nameidata nd;
197         struct dentry *dentry;
198         int err;
199
200         err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
201                               name, LOOKUP_PARENT, &nd);
202         if (err)
203                 return err;
204
205         mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
206         dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
207         if (!IS_ERR(dentry)) {
208                 if (dentry->d_inode)
209                         err = vfs_rmdir(nd.path.dentry->d_inode, dentry);
210                 else
211                         err = -ENOENT;
212                 dput(dentry);
213         } else {
214                 err = PTR_ERR(dentry);
215         }
216         mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
217
218         path_put(&nd.path);
219         return err;
220 }
221
222 static int delete_path(const char *nodepath)
223 {
224         const char *path;
225         int err = 0;
226
227         path = kstrdup(nodepath, GFP_KERNEL);
228         if (!path)
229                 return -ENOMEM;
230
231         while (1) {
232                 char *base;
233
234                 base = strrchr(path, '/');
235                 if (!base)
236                         break;
237                 base[0] = '\0';
238                 err = dev_rmdir(path);
239                 if (err)
240                         break;
241         }
242
243         kfree(path);
244         return err;
245 }
246
247 static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *stat)
248 {
249         /* did we create it */
250         if (inode->i_private != &dev_mnt)
251                 return 0;
252
253         /* does the dev_t match */
254         if (is_blockdev(dev)) {
255                 if (!S_ISBLK(stat->mode))
256                         return 0;
257         } else {
258                 if (!S_ISCHR(stat->mode))
259                         return 0;
260         }
261         if (stat->rdev != dev->devt)
262                 return 0;
263
264         /* ours */
265         return 1;
266 }
267
268 int devtmpfs_delete_node(struct device *dev)
269 {
270         const char *tmp = NULL;
271         const char *nodename;
272         const struct cred *curr_cred;
273         struct nameidata nd;
274         struct dentry *dentry;
275         struct kstat stat;
276         int deleted = 1;
277         int err;
278
279         if (!dev_mnt)
280                 return 0;
281
282         nodename = device_get_devnode(dev, NULL, &tmp);
283         if (!nodename)
284                 return -ENOMEM;
285
286         curr_cred = override_creds(&init_cred);
287         err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
288                               nodename, LOOKUP_PARENT, &nd);
289         if (err)
290                 goto out;
291
292         mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
293         dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
294         if (!IS_ERR(dentry)) {
295                 if (dentry->d_inode) {
296                         err = vfs_getattr(nd.path.mnt, dentry, &stat);
297                         if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
298                                 err = vfs_unlink(nd.path.dentry->d_inode,
299                                                  dentry);
300                                 if (!err || err == -ENOENT)
301                                         deleted = 1;
302                         }
303                 } else {
304                         err = -ENOENT;
305                 }
306                 dput(dentry);
307         } else {
308                 err = PTR_ERR(dentry);
309         }
310         mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
311
312         path_put(&nd.path);
313         if (deleted && strchr(nodename, '/'))
314                 delete_path(nodename);
315 out:
316         kfree(tmp);
317         revert_creds(curr_cred);
318         return err;
319 }
320
321 /*
322  * If configured, or requested by the commandline, devtmpfs will be
323  * auto-mounted after the kernel mounted the root filesystem.
324  */
325 int devtmpfs_mount(const char *mountpoint)
326 {
327         struct path path;
328         int err;
329
330         if (!dev_mount)
331                 return 0;
332
333         if (!dev_mnt)
334                 return 0;
335
336         err = kern_path(mountpoint, LOOKUP_FOLLOW, &path);
337         if (err)
338                 return err;
339         err = do_add_mount(dev_mnt, &path, 0, NULL);
340         if (err)
341                 printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
342         else
343                 printk(KERN_INFO "devtmpfs: mounted\n");
344         path_put(&path);
345         return err;
346 }
347
348 /*
349  * Create devtmpfs instance, driver-core devices will add their device
350  * nodes here.
351  */
352 int __init devtmpfs_init(void)
353 {
354         int err;
355         struct vfsmount *mnt;
356
357         err = register_filesystem(&dev_fs_type);
358         if (err) {
359                 printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
360                        "type %i\n", err);
361                 return err;
362         }
363
364         mnt = kern_mount(&dev_fs_type);
365         if (IS_ERR(mnt)) {
366                 err = PTR_ERR(mnt);
367                 printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
368                 unregister_filesystem(&dev_fs_type);
369                 return err;
370         }
371         dev_mnt = mnt;
372
373         printk(KERN_INFO "devtmpfs: initialized\n");
374         return 0;
375 }