linux/fs/proc/root.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/proc/root.c
   3 *
   4 *  Copyright (C) 1991, 1992 Linus Torvalds
   5 *
   6 *  proc root directory handling functions
   7 */
   8
   9#include <asm/uaccess.h>
  10
  11#include <linux/errno.h>
  12#include <linux/time.h>
  13#include <linux/proc_fs.h>
  14#include <linux/stat.h>
  15#include <linux/init.h>
  16#include <linux/sched.h>
  17#include <linux/module.h>
  18#include <linux/bitops.h>
  19#include <linux/mount.h>
  20#include <linux/pid_namespace.h>
  21
  22#include "internal.h"
  23
  24static int proc_test_super(struct super_block *sb, void *data)
  25{
  26        return sb->s_fs_info == data;
  27}
  28
  29static int proc_set_super(struct super_block *sb, void *data)
  30{
  31        int err = set_anon_super(sb, NULL);
  32        if (!err) {
  33                struct pid_namespace *ns = (struct pid_namespace *)data;
  34                sb->s_fs_info = get_pid_ns(ns);
  35        }
  36        return err;
  37}
  38
  39static struct dentry *proc_mount(struct file_system_type *fs_type,
  40        int flags, const char *dev_name, void *data)
  41{
  42        int err;
  43        struct super_block *sb;
  44        struct pid_namespace *ns;
  45        struct proc_inode *ei;
  46
  47        if (flags & MS_KERNMOUNT)
  48                ns = (struct pid_namespace *)data;
  49        else
  50                ns = current->nsproxy->pid_ns;
  51
  52        sb = sget(fs_type, proc_test_super, proc_set_super, ns);
  53        if (IS_ERR(sb))
  54                return ERR_CAST(sb);
  55
  56        if (!sb->s_root) {
  57                sb->s_flags = flags;
  58                err = proc_fill_super(sb);
  59                if (err) {
  60                        deactivate_locked_super(sb);
  61                        return ERR_PTR(err);
  62                }
  63
  64                sb->s_flags |= MS_ACTIVE;
  65        }
  66
  67        ei = PROC_I(sb->s_root->d_inode);
  68        if (!ei->pid) {
  69                rcu_read_lock();
  70                ei->pid = get_pid(find_pid_ns(1, ns));
  71                rcu_read_unlock();
  72        }
  73
  74        return dget(sb->s_root);
  75}
  76
  77static void proc_kill_sb(struct super_block *sb)
  78{
  79        struct pid_namespace *ns;
  80
  81        ns = (struct pid_namespace *)sb->s_fs_info;
  82        kill_anon_super(sb);
  83        put_pid_ns(ns);
  84}
  85
  86static struct file_system_type proc_fs_type = {
  87        .name           = "proc",
  88        .mount          = proc_mount,
  89        .kill_sb        = proc_kill_sb,
  90};
  91
  92void __init proc_root_init(void)
  93{
  94        int err;
  95
  96        proc_init_inodecache();
  97        err = register_filesystem(&proc_fs_type);
  98        if (err)
  99                return;
 100        err = pid_ns_prepare_proc(&init_pid_ns);
 101        if (err) {
 102                unregister_filesystem(&proc_fs_type);
 103                return;
 104        }
 105
 106        proc_symlink("mounts", NULL, "self/mounts");
 107
 108        proc_net_init();
 109
 110#ifdef CONFIG_SYSVIPC
 111        proc_mkdir("sysvipc", NULL);
 112#endif
 113        proc_mkdir("fs", NULL);
 114        proc_mkdir("driver", NULL);
 115        proc_mkdir("fs/nfsd", NULL); /* somewhere for the nfsd filesystem to be mounted */
 116#if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
 117        /* just give it a mountpoint */
 118        proc_mkdir("openprom", NULL);
 119#endif
 120        proc_tty_init();
 121#ifdef CONFIG_PROC_DEVICETREE
 122        proc_device_tree_init();
 123#endif
 124        proc_mkdir("bus", NULL);
 125        proc_sys_init();
 126}
 127
 128static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
 129)
 130{
 131        generic_fillattr(dentry->d_inode, stat);
 132        stat->nlink = proc_root.nlink + nr_processes();
 133        return 0;
 134}
 135
 136static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
 137{
 138        if (!proc_lookup(dir, dentry, nd)) {
 139                return NULL;
 140        }
 141        
 142        return proc_pid_lookup(dir, dentry, nd);
 143}
 144
 145static int proc_root_readdir(struct file * filp,
 146        void * dirent, filldir_t filldir)
 147{
 148        unsigned int nr = filp->f_pos;
 149        int ret;
 150
 151        if (nr < FIRST_PROCESS_ENTRY) {
 152                int error = proc_readdir(filp, dirent, filldir);
 153                if (error <= 0)
 154                        return error;
 155                filp->f_pos = FIRST_PROCESS_ENTRY;
 156        }
 157
 158        ret = proc_pid_readdir(filp, dirent, filldir);
 159        return ret;
 160}
 161
 162/*
 163 * The root /proc directory is special, as it has the
 164 * <pid> directories. Thus we don't use the generic
 165 * directory handling functions for that..
 166 */
 167static const struct file_operations proc_root_operations = {
 168        .read            = generic_read_dir,
 169        .readdir         = proc_root_readdir,
 170        .llseek         = default_llseek,
 171};
 172
 173/*
 174 * proc root can do almost nothing..
 175 */
 176static const struct inode_operations proc_root_inode_operations = {
 177        .lookup         = proc_root_lookup,
 178        .getattr        = proc_root_getattr,
 179};
 180
 181/*
 182 * This is the root "inode" in the /proc tree..
 183 */
 184struct proc_dir_entry proc_root = {
 185        .low_ino        = PROC_ROOT_INO, 
 186        .namelen        = 5, 
 187        .mode           = S_IFDIR | S_IRUGO | S_IXUGO, 
 188        .nlink          = 2, 
 189        .count          = ATOMIC_INIT(1),
 190        .proc_iops      = &proc_root_inode_operations, 
 191        .proc_fops      = &proc_root_operations,
 192        .parent         = &proc_root,
 193        .name           = "/proc",
 194};
 195
 196int pid_ns_prepare_proc(struct pid_namespace *ns)
 197{
 198        struct vfsmount *mnt;
 199
 200        mnt = kern_mount_data(&proc_fs_type, ns);
 201        if (IS_ERR(mnt))
 202                return PTR_ERR(mnt);
 203
 204        ns->proc_mnt = mnt;
 205        return 0;
 206}
 207
 208void pid_ns_release_proc(struct pid_namespace *ns)
 209{
 210        kern_unmount(ns->proc_mnt);
 211}
 212
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.