Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/base/devtmpfs.c
15109 views
1
/*
2
* devtmpfs - kernel-maintained tmpfs-based /dev
3
*
4
* Copyright (C) 2009, Kay Sievers <[email protected]>
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/ramfs.h>
24
#include <linux/cred.h>
25
#include <linux/sched.h>
26
#include <linux/init_task.h>
27
#include <linux/slab.h>
28
29
static struct vfsmount *dev_mnt;
30
31
#if defined CONFIG_DEVTMPFS_MOUNT
32
static int mount_dev = 1;
33
#else
34
static int mount_dev;
35
#endif
36
37
static DEFINE_MUTEX(dirlock);
38
39
static int __init mount_param(char *str)
40
{
41
mount_dev = simple_strtoul(str, NULL, 0);
42
return 1;
43
}
44
__setup("devtmpfs.mount=", mount_param);
45
46
static struct dentry *dev_mount(struct file_system_type *fs_type, int flags,
47
const char *dev_name, void *data)
48
{
49
#ifdef CONFIG_TMPFS
50
return mount_single(fs_type, flags, data, shmem_fill_super);
51
#else
52
return mount_single(fs_type, flags, data, ramfs_fill_super);
53
#endif
54
}
55
56
static struct file_system_type dev_fs_type = {
57
.name = "devtmpfs",
58
.mount = dev_mount,
59
.kill_sb = kill_litter_super,
60
};
61
62
#ifdef CONFIG_BLOCK
63
static inline int is_blockdev(struct device *dev)
64
{
65
return dev->class == &block_class;
66
}
67
#else
68
static inline int is_blockdev(struct device *dev) { return 0; }
69
#endif
70
71
static int dev_mkdir(const char *name, mode_t mode)
72
{
73
struct nameidata nd;
74
struct dentry *dentry;
75
int err;
76
77
err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
78
name, LOOKUP_PARENT, &nd);
79
if (err)
80
return err;
81
82
dentry = lookup_create(&nd, 1);
83
if (!IS_ERR(dentry)) {
84
err = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
85
if (!err)
86
/* mark as kernel-created inode */
87
dentry->d_inode->i_private = &dev_mnt;
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;
96
}
97
98
static int create_path(const char *nodepath)
99
{
100
int err;
101
102
mutex_lock(&dirlock);
103
err = dev_mkdir(nodepath, 0755);
104
if (err == -ENOENT) {
105
char *path;
106
char *s;
107
108
/* parent directories do not exist, create them */
109
path = kstrdup(nodepath, GFP_KERNEL);
110
if (!path) {
111
err = -ENOMEM;
112
goto out;
113
}
114
s = path;
115
for (;;) {
116
s = strchr(s, '/');
117
if (!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
}
128
out:
129
mutex_unlock(&dirlock);
130
return err;
131
}
132
133
int devtmpfs_create_node(struct device *dev)
134
{
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;
141
int err;
142
143
if (!dev_mnt)
144
return 0;
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);
163
err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
164
nodename, LOOKUP_PARENT, &nd);
165
}
166
if (err)
167
goto out;
168
169
dentry = lookup_create(&nd, 0);
170
if (!IS_ERR(dentry)) {
171
err = vfs_mknod(nd.path.dentry->d_inode,
172
dentry, mode, dev->devt);
173
if (!err) {
174
struct iattr newattrs;
175
176
/* fixup possibly umasked mode */
177
newattrs.ia_mode = mode;
178
newattrs.ia_valid = ATTR_MODE;
179
mutex_lock(&dentry->d_inode->i_mutex);
180
notify_change(dentry, &newattrs);
181
mutex_unlock(&dentry->d_inode->i_mutex);
182
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
}
190
191
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
192
path_put(&nd.path);
193
out:
194
kfree(tmp);
195
revert_creds(curr_cred);
196
return err;
197
}
198
199
static int dev_rmdir(const char *name)
200
{
201
struct nameidata nd;
202
struct dentry *dentry;
203
int err;
204
205
err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
206
name, LOOKUP_PARENT, &nd);
207
if (err)
208
return err;
209
210
mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
211
dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
212
if (!IS_ERR(dentry)) {
213
if (dentry->d_inode) {
214
if (dentry->d_inode->i_private == &dev_mnt)
215
err = vfs_rmdir(nd.path.dentry->d_inode,
216
dentry);
217
else
218
err = -EPERM;
219
} else {
220
err = -ENOENT;
221
}
222
dput(dentry);
223
} else {
224
err = PTR_ERR(dentry);
225
}
226
227
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
228
path_put(&nd.path);
229
return err;
230
}
231
232
static int delete_path(const char *nodepath)
233
{
234
const char *path;
235
int err = 0;
236
237
path = kstrdup(nodepath, GFP_KERNEL);
238
if (!path)
239
return -ENOMEM;
240
241
mutex_lock(&dirlock);
242
for (;;) {
243
char *base;
244
245
base = strrchr(path, '/');
246
if (!base)
247
break;
248
base[0] = '\0';
249
err = dev_rmdir(path);
250
if (err)
251
break;
252
}
253
mutex_unlock(&dirlock);
254
255
kfree(path);
256
return err;
257
}
258
259
static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *stat)
260
{
261
/* did we create it */
262
if (inode->i_private != &dev_mnt)
263
return 0;
264
265
/* does the dev_t match */
266
if (is_blockdev(dev)) {
267
if (!S_ISBLK(stat->mode))
268
return 0;
269
} else {
270
if (!S_ISCHR(stat->mode))
271
return 0;
272
}
273
if (stat->rdev != dev->devt)
274
return 0;
275
276
/* ours */
277
return 1;
278
}
279
280
int devtmpfs_delete_node(struct device *dev)
281
{
282
const char *tmp = NULL;
283
const char *nodename;
284
const struct cred *curr_cred;
285
struct nameidata nd;
286
struct dentry *dentry;
287
struct kstat stat;
288
int deleted = 1;
289
int err;
290
291
if (!dev_mnt)
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)
302
goto out;
303
304
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);
306
if (!IS_ERR(dentry)) {
307
if (dentry->d_inode) {
308
err = vfs_getattr(nd.path.mnt, dentry, &stat);
309
if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
310
struct iattr newattrs;
311
/*
312
* before unlinking this node, reset permissions
313
* of possible references like hardlinks
314
*/
315
newattrs.ia_uid = 0;
316
newattrs.ia_gid = 0;
317
newattrs.ia_mode = stat.mode & ~0777;
318
newattrs.ia_valid =
319
ATTR_UID|ATTR_GID|ATTR_MODE;
320
mutex_lock(&dentry->d_inode->i_mutex);
321
notify_change(dentry, &newattrs);
322
mutex_unlock(&dentry->d_inode->i_mutex);
323
err = vfs_unlink(nd.path.dentry->d_inode,
324
dentry);
325
if (!err || err == -ENOENT)
326
deleted = 1;
327
}
328
} else {
329
err = -ENOENT;
330
}
331
dput(dentry);
332
} else {
333
err = PTR_ERR(dentry);
334
}
335
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
336
337
path_put(&nd.path);
338
if (deleted && strchr(nodename, '/'))
339
delete_path(nodename);
340
out:
341
kfree(tmp);
342
revert_creds(curr_cred);
343
return err;
344
}
345
346
/*
347
* If configured, or requested by the commandline, devtmpfs will be
348
* auto-mounted after the kernel mounted the root filesystem.
349
*/
350
int devtmpfs_mount(const char *mntdir)
351
{
352
int err;
353
354
if (!mount_dev)
355
return 0;
356
357
if (!dev_mnt)
358
return 0;
359
360
err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL);
361
if (err)
362
printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
363
else
364
printk(KERN_INFO "devtmpfs: mounted\n");
365
return err;
366
}
367
368
/*
369
* Create devtmpfs instance, driver-core devices will add their device
370
* nodes here.
371
*/
372
int __init devtmpfs_init(void)
373
{
374
int err;
375
struct vfsmount *mnt;
376
char options[] = "mode=0755";
377
378
err = register_filesystem(&dev_fs_type);
379
if (err) {
380
printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
381
"type %i\n", err);
382
return err;
383
}
384
385
mnt = kern_mount_data(&dev_fs_type, options);
386
if (IS_ERR(mnt)) {
387
err = PTR_ERR(mnt);
388
printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
389
unregister_filesystem(&dev_fs_type);
390
return err;
391
}
392
dev_mnt = mnt;
393
394
printk(KERN_INFO "devtmpfs: initialized\n");
395
return 0;
396
}
397
398