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