Blame view

drivers/base/devtmpfs.c 9.16 KB
2b2af54a5   Kay Sievers   Driver Core: devt...
1
2
3
4
5
6
7
8
  /*
   * devtmpfs - kernel-maintained tmpfs-based /dev
   *
   * Copyright (C) 2009, Kay Sievers <kay.sievers@vrfy.org>
   *
   * During bootup, before any driver core device is registered,
   * devtmpfs, a tmpfs-based filesystem is created. Every driver-core
   * device which requests a device node, will add a node in this
e454cea20   Kay Sievers   Driver-Core: exte...
9
10
11
12
   * filesystem.
   * By default, all devices are named after the the name of the
   * device, owned by root and have a default mode of 0600. Subsystems
   * can overwrite the default setting if needed.
2b2af54a5   Kay Sievers   Driver Core: devt...
13
14
15
16
17
18
19
20
21
22
   */
  
  #include <linux/kernel.h>
  #include <linux/syscalls.h>
  #include <linux/mount.h>
  #include <linux/device.h>
  #include <linux/genhd.h>
  #include <linux/namei.h>
  #include <linux/fs.h>
  #include <linux/shmem_fs.h>
da5e4ef7f   Peter Korsgaard   devtmpfs: support...
23
  #include <linux/ramfs.h>
e454cea20   Kay Sievers   Driver-Core: exte...
24
  #include <linux/sched.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
25
  #include <linux/slab.h>
2780f1ff6   Al Viro   switch devtmpfs o...
26
  #include <linux/kthread.h>
2b2af54a5   Kay Sievers   Driver Core: devt...
27

2780f1ff6   Al Viro   switch devtmpfs o...
28
  static struct task_struct *thread;
2b2af54a5   Kay Sievers   Driver Core: devt...
29
30
  
  #if defined CONFIG_DEVTMPFS_MOUNT
fc14f2fef   Al Viro   convert get_sb_si...
31
  static int mount_dev = 1;
2b2af54a5   Kay Sievers   Driver Core: devt...
32
  #else
fc14f2fef   Al Viro   convert get_sb_si...
33
  static int mount_dev;
2b2af54a5   Kay Sievers   Driver Core: devt...
34
  #endif
2780f1ff6   Al Viro   switch devtmpfs o...
35
36
37
38
39
40
41
  static DEFINE_SPINLOCK(req_lock);
  
  static struct req {
  	struct req *next;
  	struct completion done;
  	int err;
  	const char *name;
2c9ede55e   Al Viro   switch device_get...
42
  	umode_t mode;	/* 0 => delete */
2780f1ff6   Al Viro   switch devtmpfs o...
43
44
  	struct device *dev;
  } *requests;
ed413ae6e   Kay Sievers   Driver core: devt...
45

2b2af54a5   Kay Sievers   Driver Core: devt...
46
47
  static int __init mount_param(char *str)
  {
fc14f2fef   Al Viro   convert get_sb_si...
48
  	mount_dev = simple_strtoul(str, NULL, 0);
2b2af54a5   Kay Sievers   Driver Core: devt...
49
50
51
  	return 1;
  }
  __setup("devtmpfs.mount=", mount_param);
fc14f2fef   Al Viro   convert get_sb_si...
52
53
  static struct dentry *dev_mount(struct file_system_type *fs_type, int flags,
  		      const char *dev_name, void *data)
2b2af54a5   Kay Sievers   Driver Core: devt...
54
  {
da5e4ef7f   Peter Korsgaard   devtmpfs: support...
55
  #ifdef CONFIG_TMPFS
fc14f2fef   Al Viro   convert get_sb_si...
56
  	return mount_single(fs_type, flags, data, shmem_fill_super);
da5e4ef7f   Peter Korsgaard   devtmpfs: support...
57
  #else
fc14f2fef   Al Viro   convert get_sb_si...
58
  	return mount_single(fs_type, flags, data, ramfs_fill_super);
da5e4ef7f   Peter Korsgaard   devtmpfs: support...
59
  #endif
2b2af54a5   Kay Sievers   Driver Core: devt...
60
61
62
63
  }
  
  static struct file_system_type dev_fs_type = {
  	.name = "devtmpfs",
fc14f2fef   Al Viro   convert get_sb_si...
64
  	.mount = dev_mount,
2b2af54a5   Kay Sievers   Driver Core: devt...
65
66
67
68
69
70
71
72
73
74
75
  	.kill_sb = kill_litter_super,
  };
  
  #ifdef CONFIG_BLOCK
  static inline int is_blockdev(struct device *dev)
  {
  	return dev->class == &block_class;
  }
  #else
  static inline int is_blockdev(struct device *dev) { return 0; }
  #endif
2780f1ff6   Al Viro   switch devtmpfs o...
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
  int devtmpfs_create_node(struct device *dev)
  {
  	const char *tmp = NULL;
  	struct req req;
  
  	if (!thread)
  		return 0;
  
  	req.mode = 0;
  	req.name = device_get_devnode(dev, &req.mode, &tmp);
  	if (!req.name)
  		return -ENOMEM;
  
  	if (req.mode == 0)
  		req.mode = 0600;
  	if (is_blockdev(dev))
  		req.mode |= S_IFBLK;
  	else
  		req.mode |= S_IFCHR;
  
  	req.dev = dev;
  
  	init_completion(&req.done);
  
  	spin_lock(&req_lock);
  	req.next = requests;
  	requests = &req;
  	spin_unlock(&req_lock);
  
  	wake_up_process(thread);
  	wait_for_completion(&req.done);
  
  	kfree(tmp);
  
  	return req.err;
  }
  
  int devtmpfs_delete_node(struct device *dev)
  {
  	const char *tmp = NULL;
  	struct req req;
  
  	if (!thread)
  		return 0;
  
  	req.name = device_get_devnode(dev, NULL, &tmp);
  	if (!req.name)
  		return -ENOMEM;
  
  	req.mode = 0;
  	req.dev = dev;
  
  	init_completion(&req.done);
  
  	spin_lock(&req_lock);
  	req.next = requests;
  	requests = &req;
  	spin_unlock(&req_lock);
  
  	wake_up_process(thread);
  	wait_for_completion(&req.done);
  
  	kfree(tmp);
  	return req.err;
  }
fbd48a69a   Al Viro   switch devtmpfs t...
141
  static int dev_mkdir(const char *name, umode_t mode)
2b2af54a5   Kay Sievers   Driver Core: devt...
142
  {
2b2af54a5   Kay Sievers   Driver Core: devt...
143
  	struct dentry *dentry;
69753a0f1   Al Viro   switch devtmpfs t...
144
  	struct path path;
2b2af54a5   Kay Sievers   Driver Core: devt...
145
  	int err;
69753a0f1   Al Viro   switch devtmpfs t...
146
147
148
149
150
151
152
153
154
155
156
  	dentry = kern_path_create(AT_FDCWD, name, &path, 1);
  	if (IS_ERR(dentry))
  		return PTR_ERR(dentry);
  
  	err = vfs_mkdir(path.dentry->d_inode, dentry, mode);
  	if (!err)
  		/* mark as kernel-created inode */
  		dentry->d_inode->i_private = &thread;
  	dput(dentry);
  	mutex_unlock(&path.dentry->d_inode->i_mutex);
  	path_put(&path);
2b2af54a5   Kay Sievers   Driver Core: devt...
157
158
159
160
161
  	return err;
  }
  
  static int create_path(const char *nodepath)
  {
5da4e6894   Al Viro   devtmpfs: get rid...
162
163
  	char *path;
  	char *s;
9d108d254   Al Viro   devtmpfs: missing...
164
  	int err = 0;
2b2af54a5   Kay Sievers   Driver Core: devt...
165

5da4e6894   Al Viro   devtmpfs: get rid...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  	/* parent directories do not exist, create them */
  	path = kstrdup(nodepath, GFP_KERNEL);
  	if (!path)
  		return -ENOMEM;
  
  	s = path;
  	for (;;) {
  		s = strchr(s, '/');
  		if (!s)
  			break;
  		s[0] = '\0';
  		err = dev_mkdir(path, 0755);
  		if (err && err != -EEXIST)
  			break;
  		s[0] = '/';
  		s++;
2b2af54a5   Kay Sievers   Driver Core: devt...
182
  	}
5da4e6894   Al Viro   devtmpfs: get rid...
183
  	kfree(path);
2b2af54a5   Kay Sievers   Driver Core: devt...
184
185
  	return err;
  }
fbd48a69a   Al Viro   switch devtmpfs t...
186
  static int handle_create(const char *nodename, umode_t mode, struct device *dev)
2b2af54a5   Kay Sievers   Driver Core: devt...
187
  {
2b2af54a5   Kay Sievers   Driver Core: devt...
188
  	struct dentry *dentry;
69753a0f1   Al Viro   switch devtmpfs t...
189
  	struct path path;
2b2af54a5   Kay Sievers   Driver Core: devt...
190
  	int err;
69753a0f1   Al Viro   switch devtmpfs t...
191
192
  	dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
  	if (dentry == ERR_PTR(-ENOENT)) {
2b2af54a5   Kay Sievers   Driver Core: devt...
193
  		create_path(nodename);
69753a0f1   Al Viro   switch devtmpfs t...
194
  		dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
2b2af54a5   Kay Sievers   Driver Core: devt...
195
  	}
69753a0f1   Al Viro   switch devtmpfs t...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
  	if (IS_ERR(dentry))
  		return PTR_ERR(dentry);
  
  	err = vfs_mknod(path.dentry->d_inode,
  			dentry, mode, dev->devt);
  	if (!err) {
  		struct iattr newattrs;
  
  		/* fixup possibly umasked mode */
  		newattrs.ia_mode = mode;
  		newattrs.ia_valid = ATTR_MODE;
  		mutex_lock(&dentry->d_inode->i_mutex);
  		notify_change(dentry, &newattrs);
  		mutex_unlock(&dentry->d_inode->i_mutex);
  
  		/* mark as kernel-created inode */
  		dentry->d_inode->i_private = &thread;
2b2af54a5   Kay Sievers   Driver Core: devt...
213
  	}
69753a0f1   Al Viro   switch devtmpfs t...
214
  	dput(dentry);
2b2af54a5   Kay Sievers   Driver Core: devt...
215

69753a0f1   Al Viro   switch devtmpfs t...
216
217
  	mutex_unlock(&path.dentry->d_inode->i_mutex);
  	path_put(&path);
2b2af54a5   Kay Sievers   Driver Core: devt...
218
219
220
221
222
223
224
225
  	return err;
  }
  
  static int dev_rmdir(const char *name)
  {
  	struct nameidata nd;
  	struct dentry *dentry;
  	int err;
2780f1ff6   Al Viro   switch devtmpfs o...
226
  	err = kern_path_parent(name, &nd);
2b2af54a5   Kay Sievers   Driver Core: devt...
227
228
229
230
231
232
  	if (err)
  		return err;
  
  	mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
  	dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
  	if (!IS_ERR(dentry)) {
015bf43b0   Kay Sievers   Driver Core: devt...
233
  		if (dentry->d_inode) {
2780f1ff6   Al Viro   switch devtmpfs o...
234
  			if (dentry->d_inode->i_private == &thread)
015bf43b0   Kay Sievers   Driver Core: devt...
235
236
237
238
239
  				err = vfs_rmdir(nd.path.dentry->d_inode,
  						dentry);
  			else
  				err = -EPERM;
  		} else {
2b2af54a5   Kay Sievers   Driver Core: devt...
240
  			err = -ENOENT;
015bf43b0   Kay Sievers   Driver Core: devt...
241
  		}
2b2af54a5   Kay Sievers   Driver Core: devt...
242
243
244
245
  		dput(dentry);
  	} else {
  		err = PTR_ERR(dentry);
  	}
2b2af54a5   Kay Sievers   Driver Core: devt...
246

015bf43b0   Kay Sievers   Driver Core: devt...
247
  	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
2b2af54a5   Kay Sievers   Driver Core: devt...
248
249
250
251
252
253
254
255
256
257
258
259
  	path_put(&nd.path);
  	return err;
  }
  
  static int delete_path(const char *nodepath)
  {
  	const char *path;
  	int err = 0;
  
  	path = kstrdup(nodepath, GFP_KERNEL);
  	if (!path)
  		return -ENOMEM;
ed413ae6e   Kay Sievers   Driver core: devt...
260
  	for (;;) {
2b2af54a5   Kay Sievers   Driver Core: devt...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  		char *base;
  
  		base = strrchr(path, '/');
  		if (!base)
  			break;
  		base[0] = '\0';
  		err = dev_rmdir(path);
  		if (err)
  			break;
  	}
  
  	kfree(path);
  	return err;
  }
  
  static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *stat)
  {
  	/* did we create it */
2780f1ff6   Al Viro   switch devtmpfs o...
279
  	if (inode->i_private != &thread)
2b2af54a5   Kay Sievers   Driver Core: devt...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
  		return 0;
  
  	/* does the dev_t match */
  	if (is_blockdev(dev)) {
  		if (!S_ISBLK(stat->mode))
  			return 0;
  	} else {
  		if (!S_ISCHR(stat->mode))
  			return 0;
  	}
  	if (stat->rdev != dev->devt)
  		return 0;
  
  	/* ours */
  	return 1;
  }
2780f1ff6   Al Viro   switch devtmpfs o...
296
  static int handle_remove(const char *nodename, struct device *dev)
2b2af54a5   Kay Sievers   Driver Core: devt...
297
  {
2b2af54a5   Kay Sievers   Driver Core: devt...
298
299
300
301
302
  	struct nameidata nd;
  	struct dentry *dentry;
  	struct kstat stat;
  	int deleted = 1;
  	int err;
2780f1ff6   Al Viro   switch devtmpfs o...
303
  	err = kern_path_parent(nodename, &nd);
2b2af54a5   Kay Sievers   Driver Core: devt...
304
  	if (err)
2780f1ff6   Al Viro   switch devtmpfs o...
305
  		return err;
2b2af54a5   Kay Sievers   Driver Core: devt...
306
307
308
309
310
311
312
  
  	mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
  	dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
  	if (!IS_ERR(dentry)) {
  		if (dentry->d_inode) {
  			err = vfs_getattr(nd.path.mnt, dentry, &stat);
  			if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
5e31d76f2   Kay Sievers   Driver-Core: devt...
313
314
315
316
317
318
319
320
321
322
323
324
325
  				struct iattr newattrs;
  				/*
  				 * before unlinking this node, reset permissions
  				 * of possible references like hardlinks
  				 */
  				newattrs.ia_uid = 0;
  				newattrs.ia_gid = 0;
  				newattrs.ia_mode = stat.mode & ~0777;
  				newattrs.ia_valid =
  					ATTR_UID|ATTR_GID|ATTR_MODE;
  				mutex_lock(&dentry->d_inode->i_mutex);
  				notify_change(dentry, &newattrs);
  				mutex_unlock(&dentry->d_inode->i_mutex);
2b2af54a5   Kay Sievers   Driver Core: devt...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
  				err = vfs_unlink(nd.path.dentry->d_inode,
  						 dentry);
  				if (!err || err == -ENOENT)
  					deleted = 1;
  			}
  		} else {
  			err = -ENOENT;
  		}
  		dput(dentry);
  	} else {
  		err = PTR_ERR(dentry);
  	}
  	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
  
  	path_put(&nd.path);
  	if (deleted && strchr(nodename, '/'))
  		delete_path(nodename);
2b2af54a5   Kay Sievers   Driver Core: devt...
343
344
345
346
347
348
349
  	return err;
  }
  
  /*
   * If configured, or requested by the commandline, devtmpfs will be
   * auto-mounted after the kernel mounted the root filesystem.
   */
073120cc2   Kay Sievers   Driver Core: devt...
350
  int devtmpfs_mount(const char *mntdir)
2b2af54a5   Kay Sievers   Driver Core: devt...
351
  {
2b2af54a5   Kay Sievers   Driver Core: devt...
352
  	int err;
fc14f2fef   Al Viro   convert get_sb_si...
353
  	if (!mount_dev)
2b2af54a5   Kay Sievers   Driver Core: devt...
354
  		return 0;
2780f1ff6   Al Viro   switch devtmpfs o...
355
  	if (!thread)
2b2af54a5   Kay Sievers   Driver Core: devt...
356
  		return 0;
073120cc2   Kay Sievers   Driver Core: devt...
357
  	err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL);
2b2af54a5   Kay Sievers   Driver Core: devt...
358
359
360
361
362
363
  	if (err)
  		printk(KERN_INFO "devtmpfs: error mounting %i
  ", err);
  	else
  		printk(KERN_INFO "devtmpfs: mounted
  ");
2b2af54a5   Kay Sievers   Driver Core: devt...
364
365
  	return err;
  }
f9e0b159d   Arnaud Lacombe   drivers/base/devt...
366
  static DECLARE_COMPLETION(setup_done);
2780f1ff6   Al Viro   switch devtmpfs o...
367

fbd48a69a   Al Viro   switch devtmpfs t...
368
  static int handle(const char *name, umode_t mode, struct device *dev)
2780f1ff6   Al Viro   switch devtmpfs o...
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
  {
  	if (mode)
  		return handle_create(name, mode, dev);
  	else
  		return handle_remove(name, dev);
  }
  
  static int devtmpfsd(void *p)
  {
  	char options[] = "mode=0755";
  	int *err = p;
  	*err = sys_unshare(CLONE_NEWNS);
  	if (*err)
  		goto out;
  	*err = sys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, options);
  	if (*err)
  		goto out;
  	sys_chdir("/.."); /* will traverse into overmounted root */
  	sys_chroot(".");
  	complete(&setup_done);
  	while (1) {
  		spin_lock(&req_lock);
  		while (requests) {
  			struct req *req = requests;
  			requests = NULL;
  			spin_unlock(&req_lock);
  			while (req) {
e13889bab   Al Viro   fix devtmpfs race
396
  				struct req *next = req->next;
2780f1ff6   Al Viro   switch devtmpfs o...
397
398
  				req->err = handle(req->name, req->mode, req->dev);
  				complete(&req->done);
e13889bab   Al Viro   fix devtmpfs race
399
  				req = next;
2780f1ff6   Al Viro   switch devtmpfs o...
400
401
402
  			}
  			spin_lock(&req_lock);
  		}
65e6757be   Kautuk Consul   devtmpfsd: fix ta...
403
  		__set_current_state(TASK_INTERRUPTIBLE);
2780f1ff6   Al Viro   switch devtmpfs o...
404
405
  		spin_unlock(&req_lock);
  		schedule();
2780f1ff6   Al Viro   switch devtmpfs o...
406
407
408
409
410
411
  	}
  	return 0;
  out:
  	complete(&setup_done);
  	return *err;
  }
2b2af54a5   Kay Sievers   Driver Core: devt...
412
413
414
415
416
417
  /*
   * Create devtmpfs instance, driver-core devices will add their device
   * nodes here.
   */
  int __init devtmpfs_init(void)
  {
2780f1ff6   Al Viro   switch devtmpfs o...
418
  	int err = register_filesystem(&dev_fs_type);
2b2af54a5   Kay Sievers   Driver Core: devt...
419
420
421
422
423
424
  	if (err) {
  		printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
  		       "type %i
  ", err);
  		return err;
  	}
2780f1ff6   Al Viro   switch devtmpfs o...
425
426
427
428
429
430
431
432
433
  	thread = kthread_run(devtmpfsd, &err, "kdevtmpfs");
  	if (!IS_ERR(thread)) {
  		wait_for_completion(&setup_done);
  	} else {
  		err = PTR_ERR(thread);
  		thread = NULL;
  	}
  
  	if (err) {
2b2af54a5   Kay Sievers   Driver Core: devt...
434
435
436
437
438
  		printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i
  ", err);
  		unregister_filesystem(&dev_fs_type);
  		return err;
  	}
2b2af54a5   Kay Sievers   Driver Core: devt...
439
440
441
442
443
  
  	printk(KERN_INFO "devtmpfs: initialized
  ");
  	return 0;
  }