xref: /openbmc/linux/fs/proc/root.c (revision fee781e6)
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/config.h>
161da177e4SLinus Torvalds #include <linux/init.h>
171da177e4SLinus Torvalds #include <linux/module.h>
181da177e4SLinus Torvalds #include <linux/bitops.h>
191da177e4SLinus Torvalds #include <linux/smp_lock.h>
201da177e4SLinus Torvalds 
21fee781e6SAdrian Bunk #include "internal.h"
22fee781e6SAdrian Bunk 
231da177e4SLinus Torvalds struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds #ifdef CONFIG_SYSCTL
261da177e4SLinus Torvalds struct proc_dir_entry *proc_sys_root;
271da177e4SLinus Torvalds #endif
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds static struct super_block *proc_get_sb(struct file_system_type *fs_type,
301da177e4SLinus Torvalds 	int flags, const char *dev_name, void *data)
311da177e4SLinus Torvalds {
321da177e4SLinus Torvalds 	return get_sb_single(fs_type, flags, data, proc_fill_super);
331da177e4SLinus Torvalds }
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds static struct file_system_type proc_fs_type = {
361da177e4SLinus Torvalds 	.name		= "proc",
371da177e4SLinus Torvalds 	.get_sb		= proc_get_sb,
381da177e4SLinus Torvalds 	.kill_sb	= kill_anon_super,
391da177e4SLinus Torvalds };
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds void __init proc_root_init(void)
421da177e4SLinus Torvalds {
431da177e4SLinus Torvalds 	int err = proc_init_inodecache();
441da177e4SLinus Torvalds 	if (err)
451da177e4SLinus Torvalds 		return;
461da177e4SLinus Torvalds 	err = register_filesystem(&proc_fs_type);
471da177e4SLinus Torvalds 	if (err)
481da177e4SLinus Torvalds 		return;
491da177e4SLinus Torvalds 	proc_mnt = kern_mount(&proc_fs_type);
501da177e4SLinus Torvalds 	err = PTR_ERR(proc_mnt);
511da177e4SLinus Torvalds 	if (IS_ERR(proc_mnt)) {
521da177e4SLinus Torvalds 		unregister_filesystem(&proc_fs_type);
531da177e4SLinus Torvalds 		return;
541da177e4SLinus Torvalds 	}
551da177e4SLinus Torvalds 	proc_misc_init();
561da177e4SLinus Torvalds 	proc_net = proc_mkdir("net", NULL);
571da177e4SLinus Torvalds 	proc_net_stat = proc_mkdir("net/stat", NULL);
581da177e4SLinus Torvalds 
591da177e4SLinus Torvalds #ifdef CONFIG_SYSVIPC
601da177e4SLinus Torvalds 	proc_mkdir("sysvipc", NULL);
611da177e4SLinus Torvalds #endif
621da177e4SLinus Torvalds #ifdef CONFIG_SYSCTL
631da177e4SLinus Torvalds 	proc_sys_root = proc_mkdir("sys", NULL);
641da177e4SLinus Torvalds #endif
651da177e4SLinus Torvalds #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
661da177e4SLinus Torvalds 	proc_mkdir("sys/fs", NULL);
671da177e4SLinus Torvalds 	proc_mkdir("sys/fs/binfmt_misc", NULL);
681da177e4SLinus Torvalds #endif
691da177e4SLinus Torvalds 	proc_root_fs = proc_mkdir("fs", NULL);
701da177e4SLinus Torvalds 	proc_root_driver = proc_mkdir("driver", NULL);
711da177e4SLinus Torvalds 	proc_mkdir("fs/nfsd", NULL); /* somewhere for the nfsd filesystem to be mounted */
721da177e4SLinus Torvalds #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
731da177e4SLinus Torvalds 	/* just give it a mountpoint */
741da177e4SLinus Torvalds 	proc_mkdir("openprom", NULL);
751da177e4SLinus Torvalds #endif
761da177e4SLinus Torvalds 	proc_tty_init();
771da177e4SLinus Torvalds #ifdef CONFIG_PROC_DEVICETREE
781da177e4SLinus Torvalds 	proc_device_tree_init();
791da177e4SLinus Torvalds #endif
801da177e4SLinus Torvalds 	proc_bus = proc_mkdir("bus", NULL);
811da177e4SLinus Torvalds }
821da177e4SLinus Torvalds 
831da177e4SLinus Torvalds static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
841da177e4SLinus Torvalds {
851da177e4SLinus Torvalds 	/*
861da177e4SLinus Torvalds 	 * nr_threads is actually protected by the tasklist_lock;
871da177e4SLinus Torvalds 	 * however, it's conventional to do reads, especially for
881da177e4SLinus Torvalds 	 * reporting, without any locking whatsoever.
891da177e4SLinus Torvalds 	 */
901da177e4SLinus Torvalds 	if (dir->i_ino == PROC_ROOT_INO) /* check for safety... */
911da177e4SLinus Torvalds 		dir->i_nlink = proc_root.nlink + nr_threads;
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds 	if (!proc_lookup(dir, dentry, nd)) {
941da177e4SLinus Torvalds 		return NULL;
951da177e4SLinus Torvalds 	}
961da177e4SLinus Torvalds 
971da177e4SLinus Torvalds 	return proc_pid_lookup(dir, dentry, nd);
981da177e4SLinus Torvalds }
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds static int proc_root_readdir(struct file * filp,
1011da177e4SLinus Torvalds 	void * dirent, filldir_t filldir)
1021da177e4SLinus Torvalds {
1031da177e4SLinus Torvalds 	unsigned int nr = filp->f_pos;
1041da177e4SLinus Torvalds 	int ret;
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds 	lock_kernel();
1071da177e4SLinus Torvalds 
1081da177e4SLinus Torvalds 	if (nr < FIRST_PROCESS_ENTRY) {
1091da177e4SLinus Torvalds 		int error = proc_readdir(filp, dirent, filldir);
1101da177e4SLinus Torvalds 		if (error <= 0) {
1111da177e4SLinus Torvalds 			unlock_kernel();
1121da177e4SLinus Torvalds 			return error;
1131da177e4SLinus Torvalds 		}
1141da177e4SLinus Torvalds 		filp->f_pos = FIRST_PROCESS_ENTRY;
1151da177e4SLinus Torvalds 	}
1161da177e4SLinus Torvalds 	unlock_kernel();
1171da177e4SLinus Torvalds 
1181da177e4SLinus Torvalds 	ret = proc_pid_readdir(filp, dirent, filldir);
1191da177e4SLinus Torvalds 	return ret;
1201da177e4SLinus Torvalds }
1211da177e4SLinus Torvalds 
1221da177e4SLinus Torvalds /*
1231da177e4SLinus Torvalds  * The root /proc directory is special, as it has the
1241da177e4SLinus Torvalds  * <pid> directories. Thus we don't use the generic
1251da177e4SLinus Torvalds  * directory handling functions for that..
1261da177e4SLinus Torvalds  */
1271da177e4SLinus Torvalds static struct file_operations proc_root_operations = {
1281da177e4SLinus Torvalds 	.read		 = generic_read_dir,
1291da177e4SLinus Torvalds 	.readdir	 = proc_root_readdir,
1301da177e4SLinus Torvalds };
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds /*
1331da177e4SLinus Torvalds  * proc root can do almost nothing..
1341da177e4SLinus Torvalds  */
1351da177e4SLinus Torvalds static struct inode_operations proc_root_inode_operations = {
1361da177e4SLinus Torvalds 	.lookup		= proc_root_lookup,
1371da177e4SLinus Torvalds };
1381da177e4SLinus Torvalds 
1391da177e4SLinus Torvalds /*
1401da177e4SLinus Torvalds  * This is the root "inode" in the /proc tree..
1411da177e4SLinus Torvalds  */
1421da177e4SLinus Torvalds struct proc_dir_entry proc_root = {
1431da177e4SLinus Torvalds 	.low_ino	= PROC_ROOT_INO,
1441da177e4SLinus Torvalds 	.namelen	= 5,
1451da177e4SLinus Torvalds 	.name		= "/proc",
1461da177e4SLinus Torvalds 	.mode		= S_IFDIR | S_IRUGO | S_IXUGO,
1471da177e4SLinus Torvalds 	.nlink		= 2,
1481da177e4SLinus Torvalds 	.proc_iops	= &proc_root_inode_operations,
1491da177e4SLinus Torvalds 	.proc_fops	= &proc_root_operations,
1501da177e4SLinus Torvalds 	.parent		= &proc_root,
1511da177e4SLinus Torvalds };
1521da177e4SLinus Torvalds 
1531da177e4SLinus Torvalds EXPORT_SYMBOL(proc_symlink);
1541da177e4SLinus Torvalds EXPORT_SYMBOL(proc_mkdir);
1551da177e4SLinus Torvalds EXPORT_SYMBOL(create_proc_entry);
1561da177e4SLinus Torvalds EXPORT_SYMBOL(remove_proc_entry);
1571da177e4SLinus Torvalds EXPORT_SYMBOL(proc_root);
1581da177e4SLinus Torvalds EXPORT_SYMBOL(proc_root_fs);
1591da177e4SLinus Torvalds EXPORT_SYMBOL(proc_net);
1601da177e4SLinus Torvalds EXPORT_SYMBOL(proc_net_stat);
1611da177e4SLinus Torvalds EXPORT_SYMBOL(proc_bus);
1621da177e4SLinus Torvalds EXPORT_SYMBOL(proc_root_driver);
163