xref: /openbmc/linux/fs/proc/root.c (revision 00977a59)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  linux/fs/proc/root.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *  Copyright (C) 1991, 1992 Linus Torvalds
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  *  proc root directory handling functions
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds 
91da177e4SLinus Torvalds #include <asm/uaccess.h>
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds #include <linux/errno.h>
121da177e4SLinus Torvalds #include <linux/time.h>
131da177e4SLinus Torvalds #include <linux/proc_fs.h>
141da177e4SLinus Torvalds #include <linux/stat.h>
151da177e4SLinus Torvalds #include <linux/init.h>
16914e2637SAl Viro #include <linux/sched.h>
171da177e4SLinus Torvalds #include <linux/module.h>
181da177e4SLinus Torvalds #include <linux/bitops.h>
191da177e4SLinus Torvalds #include <linux/smp_lock.h>
20f6c7a1f3SEric W. Biederman #include <linux/mount.h>
211da177e4SLinus Torvalds 
22fee781e6SAdrian Bunk #include "internal.h"
23fee781e6SAdrian Bunk 
241da177e4SLinus Torvalds struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
251da177e4SLinus Torvalds 
261da177e4SLinus Torvalds #ifdef CONFIG_SYSCTL
271da177e4SLinus Torvalds struct proc_dir_entry *proc_sys_root;
281da177e4SLinus Torvalds #endif
291da177e4SLinus Torvalds 
30454e2398SDavid Howells static int proc_get_sb(struct file_system_type *fs_type,
31454e2398SDavid Howells 	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
321da177e4SLinus Torvalds {
33f6c7a1f3SEric W. Biederman 	if (proc_mnt) {
34f6c7a1f3SEric W. Biederman 		/* Seed the root directory with a pid so it doesn't need
35f6c7a1f3SEric W. Biederman 		 * to be special in base.c.  I would do this earlier but
36f6c7a1f3SEric W. Biederman 		 * the only task alive when /proc is mounted the first time
37f6c7a1f3SEric W. Biederman 		 * is the init_task and it doesn't have any pids.
38f6c7a1f3SEric W. Biederman 		 */
39f6c7a1f3SEric W. Biederman 		struct proc_inode *ei;
40f6c7a1f3SEric W. Biederman 		ei = PROC_I(proc_mnt->mnt_sb->s_root->d_inode);
41f6c7a1f3SEric W. Biederman 		if (!ei->pid)
42f6c7a1f3SEric W. Biederman 			ei->pid = find_get_pid(1);
43f6c7a1f3SEric W. Biederman 	}
44454e2398SDavid Howells 	return get_sb_single(fs_type, flags, data, proc_fill_super, mnt);
451da177e4SLinus Torvalds }
461da177e4SLinus Torvalds 
471da177e4SLinus Torvalds static struct file_system_type proc_fs_type = {
481da177e4SLinus Torvalds 	.name		= "proc",
491da177e4SLinus Torvalds 	.get_sb		= proc_get_sb,
501da177e4SLinus Torvalds 	.kill_sb	= kill_anon_super,
511da177e4SLinus Torvalds };
521da177e4SLinus Torvalds 
531da177e4SLinus Torvalds void __init proc_root_init(void)
541da177e4SLinus Torvalds {
551da177e4SLinus Torvalds 	int err = proc_init_inodecache();
561da177e4SLinus Torvalds 	if (err)
571da177e4SLinus Torvalds 		return;
581da177e4SLinus Torvalds 	err = register_filesystem(&proc_fs_type);
591da177e4SLinus Torvalds 	if (err)
601da177e4SLinus Torvalds 		return;
611da177e4SLinus Torvalds 	proc_mnt = kern_mount(&proc_fs_type);
621da177e4SLinus Torvalds 	err = PTR_ERR(proc_mnt);
631da177e4SLinus Torvalds 	if (IS_ERR(proc_mnt)) {
641da177e4SLinus Torvalds 		unregister_filesystem(&proc_fs_type);
651da177e4SLinus Torvalds 		return;
661da177e4SLinus Torvalds 	}
671da177e4SLinus Torvalds 	proc_misc_init();
681da177e4SLinus Torvalds 	proc_net = proc_mkdir("net", NULL);
691da177e4SLinus Torvalds 	proc_net_stat = proc_mkdir("net/stat", NULL);
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds #ifdef CONFIG_SYSVIPC
721da177e4SLinus Torvalds 	proc_mkdir("sysvipc", NULL);
731da177e4SLinus Torvalds #endif
741da177e4SLinus Torvalds #ifdef CONFIG_SYSCTL
751da177e4SLinus Torvalds 	proc_sys_root = proc_mkdir("sys", NULL);
761da177e4SLinus Torvalds #endif
771da177e4SLinus Torvalds #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
781da177e4SLinus Torvalds 	proc_mkdir("sys/fs", NULL);
791da177e4SLinus Torvalds 	proc_mkdir("sys/fs/binfmt_misc", NULL);
801da177e4SLinus Torvalds #endif
811da177e4SLinus Torvalds 	proc_root_fs = proc_mkdir("fs", NULL);
821da177e4SLinus Torvalds 	proc_root_driver = proc_mkdir("driver", NULL);
831da177e4SLinus Torvalds 	proc_mkdir("fs/nfsd", NULL); /* somewhere for the nfsd filesystem to be mounted */
841da177e4SLinus Torvalds #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
851da177e4SLinus Torvalds 	/* just give it a mountpoint */
861da177e4SLinus Torvalds 	proc_mkdir("openprom", NULL);
871da177e4SLinus Torvalds #endif
881da177e4SLinus Torvalds 	proc_tty_init();
891da177e4SLinus Torvalds #ifdef CONFIG_PROC_DEVICETREE
901da177e4SLinus Torvalds 	proc_device_tree_init();
911da177e4SLinus Torvalds #endif
921da177e4SLinus Torvalds 	proc_bus = proc_mkdir("bus", NULL);
931da177e4SLinus Torvalds }
941da177e4SLinus Torvalds 
9576b6159bSAl Viro static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
9676b6159bSAl Viro )
9776b6159bSAl Viro {
9876b6159bSAl Viro 	generic_fillattr(dentry->d_inode, stat);
9976b6159bSAl Viro 	stat->nlink = proc_root.nlink + nr_processes();
10076b6159bSAl Viro 	return 0;
10176b6159bSAl Viro }
10276b6159bSAl Viro 
1031da177e4SLinus Torvalds static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
1041da177e4SLinus Torvalds {
1051da177e4SLinus Torvalds 	if (!proc_lookup(dir, dentry, nd)) {
1061da177e4SLinus Torvalds 		return NULL;
1071da177e4SLinus Torvalds 	}
1081da177e4SLinus Torvalds 
1091da177e4SLinus Torvalds 	return proc_pid_lookup(dir, dentry, nd);
1101da177e4SLinus Torvalds }
1111da177e4SLinus Torvalds 
1121da177e4SLinus Torvalds static int proc_root_readdir(struct file * filp,
1131da177e4SLinus Torvalds 	void * dirent, filldir_t filldir)
1141da177e4SLinus Torvalds {
1151da177e4SLinus Torvalds 	unsigned int nr = filp->f_pos;
1161da177e4SLinus Torvalds 	int ret;
1171da177e4SLinus Torvalds 
1181da177e4SLinus Torvalds 	lock_kernel();
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds 	if (nr < FIRST_PROCESS_ENTRY) {
1211da177e4SLinus Torvalds 		int error = proc_readdir(filp, dirent, filldir);
1221da177e4SLinus Torvalds 		if (error <= 0) {
1231da177e4SLinus Torvalds 			unlock_kernel();
1241da177e4SLinus Torvalds 			return error;
1251da177e4SLinus Torvalds 		}
1261da177e4SLinus Torvalds 		filp->f_pos = FIRST_PROCESS_ENTRY;
1271da177e4SLinus Torvalds 	}
1281da177e4SLinus Torvalds 	unlock_kernel();
1291da177e4SLinus Torvalds 
1301da177e4SLinus Torvalds 	ret = proc_pid_readdir(filp, dirent, filldir);
1311da177e4SLinus Torvalds 	return ret;
1321da177e4SLinus Torvalds }
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds /*
1351da177e4SLinus Torvalds  * The root /proc directory is special, as it has the
1361da177e4SLinus Torvalds  * <pid> directories. Thus we don't use the generic
1371da177e4SLinus Torvalds  * directory handling functions for that..
1381da177e4SLinus Torvalds  */
13900977a59SArjan van de Ven static const struct file_operations proc_root_operations = {
1401da177e4SLinus Torvalds 	.read		 = generic_read_dir,
1411da177e4SLinus Torvalds 	.readdir	 = proc_root_readdir,
1421da177e4SLinus Torvalds };
1431da177e4SLinus Torvalds 
1441da177e4SLinus Torvalds /*
1451da177e4SLinus Torvalds  * proc root can do almost nothing..
1461da177e4SLinus Torvalds  */
1471da177e4SLinus Torvalds static struct inode_operations proc_root_inode_operations = {
1481da177e4SLinus Torvalds 	.lookup		= proc_root_lookup,
14976b6159bSAl Viro 	.getattr	= proc_root_getattr,
1501da177e4SLinus Torvalds };
1511da177e4SLinus Torvalds 
1521da177e4SLinus Torvalds /*
1531da177e4SLinus Torvalds  * This is the root "inode" in the /proc tree..
1541da177e4SLinus Torvalds  */
1551da177e4SLinus Torvalds struct proc_dir_entry proc_root = {
1561da177e4SLinus Torvalds 	.low_ino	= PROC_ROOT_INO,
1571da177e4SLinus Torvalds 	.namelen	= 5,
1581da177e4SLinus Torvalds 	.name		= "/proc",
1591da177e4SLinus Torvalds 	.mode		= S_IFDIR | S_IRUGO | S_IXUGO,
1601da177e4SLinus Torvalds 	.nlink		= 2,
1611da177e4SLinus Torvalds 	.proc_iops	= &proc_root_inode_operations,
1621da177e4SLinus Torvalds 	.proc_fops	= &proc_root_operations,
1631da177e4SLinus Torvalds 	.parent		= &proc_root,
1641da177e4SLinus Torvalds };
1651da177e4SLinus Torvalds 
1661da177e4SLinus Torvalds EXPORT_SYMBOL(proc_symlink);
1671da177e4SLinus Torvalds EXPORT_SYMBOL(proc_mkdir);
1681da177e4SLinus Torvalds EXPORT_SYMBOL(create_proc_entry);
1691da177e4SLinus Torvalds EXPORT_SYMBOL(remove_proc_entry);
1701da177e4SLinus Torvalds EXPORT_SYMBOL(proc_root);
1711da177e4SLinus Torvalds EXPORT_SYMBOL(proc_root_fs);
1721da177e4SLinus Torvalds EXPORT_SYMBOL(proc_net);
1731da177e4SLinus Torvalds EXPORT_SYMBOL(proc_net_stat);
1741da177e4SLinus Torvalds EXPORT_SYMBOL(proc_bus);
1751da177e4SLinus Torvalds EXPORT_SYMBOL(proc_root_driver);
176