linux/fs/proc/inode.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/proc/inode.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 */
   6
   7#include <linux/time.h>
   8#include <linux/proc_fs.h>
   9#include <linux/kernel.h>
  10#include <linux/mm.h>
  11#include <linux/string.h>
  12#include <linux/stat.h>
  13#include <linux/completion.h>
  14#include <linux/poll.h>
  15#include <linux/file.h>
  16#include <linux/limits.h>
  17#include <linux/init.h>
  18#include <linux/module.h>
  19#include <linux/smp_lock.h>
  20
  21#include <asm/system.h>
  22#include <asm/uaccess.h>
  23
  24#include "internal.h"
  25
  26struct proc_dir_entry *de_get(struct proc_dir_entry *de)
  27{
  28        if (de)
  29                atomic_inc(&de->count);
  30        return de;
  31}
  32
  33/*
  34 * Decrements the use count and checks for deferred deletion.
  35 */
  36void de_put(struct proc_dir_entry *de)
  37{
  38        if (de) {       
  39                lock_kernel();          
  40                if (!atomic_read(&de->count)) {
  41                        printk("de_put: entry %s already free!\n", de->name);
  42                        unlock_kernel();
  43                        return;
  44                }
  45
  46                if (atomic_dec_and_test(&de->count))
  47                        free_proc_entry(de);
  48                unlock_kernel();
  49        }
  50}
  51
  52/*
  53 * Decrement the use count of the proc_dir_entry.
  54 */
  55static void proc_delete_inode(struct inode *inode)
  56{
  57        struct proc_dir_entry *de;
  58
  59        truncate_inode_pages(&inode->i_data, 0);
  60
  61        /* Stop tracking associated processes */
  62        put_pid(PROC_I(inode)->pid);
  63
  64        /* Let go of any associated proc directory entry */
  65        de = PROC_I(inode)->pde;
  66        if (de) {
  67                if (de->owner)
  68                        module_put(de->owner);
  69                de_put(de);
  70        }
  71        clear_inode(inode);
  72}
  73
  74struct vfsmount *proc_mnt;
  75
  76static void proc_read_inode(struct inode * inode)
  77{
  78        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
  79}
  80
  81static struct kmem_cache * proc_inode_cachep;
  82
  83static struct inode *proc_alloc_inode(struct super_block *sb)
  84{
  85        struct proc_inode *ei;
  86        struct inode *inode;
  87
  88        ei = (struct proc_inode *)kmem_cache_alloc(proc_inode_cachep, GFP_KERNEL);
  89        if (!ei)
  90                return NULL;
  91        ei->pid = NULL;
  92        ei->fd = 0;
  93        ei->op.proc_get_link = NULL;
  94        ei->pde = NULL;
  95        inode = &ei->vfs_inode;
  96        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
  97        return inode;
  98}
  99
 100static void proc_destroy_inode(struct inode *inode)
 101{
 102        kmem_cache_free(proc_inode_cachep, PROC_I(inode));
 103}
 104
 105static void init_once(struct kmem_cache * cachep, void *foo)
 106{
 107        struct proc_inode *ei = (struct proc_inode *) foo;
 108
 109        inode_init_once(&ei->vfs_inode);
 110}
 111
 112int __init proc_init_inodecache(void)
 113{
 114        proc_inode_cachep = kmem_cache_create("proc_inode_cache",
 115                                             sizeof(struct proc_inode),
 116                                             0, (SLAB_RECLAIM_ACCOUNT|
 117                                                SLAB_MEM_SPREAD|SLAB_PANIC),
 118                                             init_once);
 119        return 0;
 120}
 121
 122static int proc_remount(struct super_block *sb, int *flags, char *data)
 123{
 124        *flags |= MS_NODIRATIME;
 125        return 0;
 126}
 127
 128static const struct super_operations proc_sops = {
 129        .alloc_inode    = proc_alloc_inode,
 130        .destroy_inode  = proc_destroy_inode,
 131        .read_inode     = proc_read_inode,
 132        .drop_inode     = generic_delete_inode,
 133        .delete_inode   = proc_delete_inode,
 134        .statfs         = simple_statfs,
 135        .remount_fs     = proc_remount,
 136};
 137
 138static void pde_users_dec(struct proc_dir_entry *pde)
 139{
 140        spin_lock(&pde->pde_unload_lock);
 141        pde->pde_users--;
 142        if (pde->pde_unload_completion && pde->pde_users == 0)
 143                complete(pde->pde_unload_completion);
 144        spin_unlock(&pde->pde_unload_lock);
 145}
 146
 147static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence)
 148{
 149        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 150        loff_t rv = -EINVAL;
 151        loff_t (*llseek)(struct file *, loff_t, int);
 152
 153        spin_lock(&pde->pde_unload_lock);
 154        /*
 155         * remove_proc_entry() is going to delete PDE (as part of module
 156         * cleanup sequence). No new callers into module allowed.
 157         */
 158        if (!pde->proc_fops) {
 159                spin_unlock(&pde->pde_unload_lock);
 160                return rv;
 161        }
 162        /*
 163         * Bump refcount so that remove_proc_entry will wail for ->llseek to
 164         * complete.
 165         */
 166        pde->pde_users++;
 167        /*
 168         * Save function pointer under lock, to protect against ->proc_fops
 169         * NULL'ifying right after ->pde_unload_lock is dropped.
 170         */
 171        llseek = pde->proc_fops->llseek;
 172        spin_unlock(&pde->pde_unload_lock);
 173
 174        if (!llseek)
 175                llseek = default_llseek;
 176        rv = llseek(file, offset, whence);
 177
 178        pde_users_dec(pde);
 179        return rv;
 180}
 181
 182static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 183{
 184        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 185        ssize_t rv = -EIO;
 186        ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
 187
 188        spin_lock(&pde->pde_unload_lock);
 189        if (!pde->proc_fops) {
 190                spin_unlock(&pde->pde_unload_lock);
 191                return rv;
 192        }
 193        pde->pde_users++;
 194        read = pde->proc_fops->read;
 195        spin_unlock(&pde->pde_unload_lock);
 196
 197        if (read)
 198                rv = read(file, buf, count, ppos);
 199
 200        pde_users_dec(pde);
 201        return rv;
 202}
 203
 204static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 205{
 206        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 207        ssize_t rv = -EIO;
 208        ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
 209
 210        spin_lock(&pde->pde_unload_lock);
 211        if (!pde->proc_fops) {
 212                spin_unlock(&pde->pde_unload_lock);
 213                return rv;
 214        }
 215        pde->pde_users++;
 216        write = pde->proc_fops->write;
 217        spin_unlock(&pde->pde_unload_lock);
 218
 219        if (write)
 220                rv = write(file, buf, count, ppos);
 221
 222        pde_users_dec(pde);
 223        return rv;
 224}
 225
 226static unsigned int proc_reg_poll(struct file *file, struct poll_table_struct *pts)
 227{
 228        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 229        unsigned int rv = DEFAULT_POLLMASK;
 230        unsigned int (*poll)(struct file *, struct poll_table_struct *);
 231
 232        spin_lock(&pde->pde_unload_lock);
 233        if (!pde->proc_fops) {
 234                spin_unlock(&pde->pde_unload_lock);
 235                return rv;
 236        }
 237        pde->pde_users++;
 238        poll = pde->proc_fops->poll;
 239        spin_unlock(&pde->pde_unload_lock);
 240
 241        if (poll)
 242                rv = poll(file, pts);
 243
 244        pde_users_dec(pde);
 245        return rv;
 246}
 247
 248static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 249{
 250        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 251        long rv = -ENOTTY;
 252        long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
 253        int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long);
 254
 255        spin_lock(&pde->pde_unload_lock);
 256        if (!pde->proc_fops) {
 257                spin_unlock(&pde->pde_unload_lock);
 258                return rv;
 259        }
 260        pde->pde_users++;
 261        unlocked_ioctl = pde->proc_fops->unlocked_ioctl;
 262        ioctl = pde->proc_fops->ioctl;
 263        spin_unlock(&pde->pde_unload_lock);
 264
 265        if (unlocked_ioctl) {
 266                rv = unlocked_ioctl(file, cmd, arg);
 267                if (rv == -ENOIOCTLCMD)
 268                        rv = -EINVAL;
 269        } else if (ioctl) {
 270                lock_kernel();
 271                rv = ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
 272                unlock_kernel();
 273        }
 274
 275        pde_users_dec(pde);
 276        return rv;
 277}
 278
 279#ifdef CONFIG_COMPAT
 280static long proc_reg_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 281{
 282        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 283        long rv = -ENOTTY;
 284        long (*compat_ioctl)(struct file *, unsigned int, unsigned long);
 285
 286        spin_lock(&pde->pde_unload_lock);
 287        if (!pde->proc_fops) {
 288                spin_unlock(&pde->pde_unload_lock);
 289                return rv;
 290        }
 291        pde->pde_users++;
 292        compat_ioctl = pde->proc_fops->compat_ioctl;
 293        spin_unlock(&pde->pde_unload_lock);
 294
 295        if (compat_ioctl)
 296                rv = compat_ioctl(file, cmd, arg);
 297
 298        pde_users_dec(pde);
 299        return rv;
 300}
 301#endif
 302
 303static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma)
 304{
 305        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 306        int rv = -EIO;
 307        int (*mmap)(struct file *, struct vm_area_struct *);
 308
 309        spin_lock(&pde->pde_unload_lock);
 310        if (!pde->proc_fops) {
 311                spin_unlock(&pde->pde_unload_lock);
 312                return rv;
 313        }
 314        pde->pde_users++;
 315        mmap = pde->proc_fops->mmap;
 316        spin_unlock(&pde->pde_unload_lock);
 317
 318        if (mmap)
 319                rv = mmap(file, vma);
 320
 321        pde_users_dec(pde);
 322        return rv;
 323}
 324
 325static int proc_reg_open(struct inode *inode, struct file *file)
 326{
 327        struct proc_dir_entry *pde = PDE(inode);
 328        int rv = 0;
 329        int (*open)(struct inode *, struct file *);
 330
 331        spin_lock(&pde->pde_unload_lock);
 332        if (!pde->proc_fops) {
 333                spin_unlock(&pde->pde_unload_lock);
 334                return rv;
 335        }
 336        pde->pde_users++;
 337        open = pde->proc_fops->open;
 338        spin_unlock(&pde->pde_unload_lock);
 339
 340        if (open)
 341                rv = open(inode, file);
 342
 343        pde_users_dec(pde);
 344        return rv;
 345}
 346
 347static int proc_reg_release(struct inode *inode, struct file *file)
 348{
 349        struct proc_dir_entry *pde = PDE(inode);
 350        int rv = 0;
 351        int (*release)(struct inode *, struct file *);
 352
 353        spin_lock(&pde->pde_unload_lock);
 354        if (!pde->proc_fops) {
 355                spin_unlock(&pde->pde_unload_lock);
 356                return rv;
 357        }
 358        pde->pde_users++;
 359        release = pde->proc_fops->release;
 360        spin_unlock(&pde->pde_unload_lock);
 361
 362        if (release)
 363                rv = release(inode, file);
 364
 365        pde_users_dec(pde);
 366        return rv;
 367}
 368
 369static const struct file_operations proc_reg_file_ops = {
 370        .llseek         = proc_reg_llseek,
 371        .read           = proc_reg_read,
 372        .write          = proc_reg_write,
 373        .poll           = proc_reg_poll,
 374        .unlocked_ioctl = proc_reg_unlocked_ioctl,
 375#ifdef CONFIG_COMPAT
 376        .compat_ioctl   = proc_reg_compat_ioctl,
 377#endif
 378        .mmap           = proc_reg_mmap,
 379        .open           = proc_reg_open,
 380        .release        = proc_reg_release,
 381};
 382
 383#ifdef CONFIG_COMPAT
 384static const struct file_operations proc_reg_file_ops_no_compat = {
 385        .llseek         = proc_reg_llseek,
 386        .read           = proc_reg_read,
 387        .write          = proc_reg_write,
 388        .poll           = proc_reg_poll,
 389        .unlocked_ioctl = proc_reg_unlocked_ioctl,
 390        .mmap           = proc_reg_mmap,
 391        .open           = proc_reg_open,
 392        .release        = proc_reg_release,
 393};
 394#endif
 395
 396struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
 397                                struct proc_dir_entry *de)
 398{
 399        struct inode * inode;
 400
 401        if (de != NULL && !try_module_get(de->owner))
 402                goto out_mod;
 403
 404        inode = iget(sb, ino);
 405        if (!inode)
 406                goto out_ino;
 407
 408        PROC_I(inode)->fd = 0;
 409        PROC_I(inode)->pde = de;
 410        if (de) {
 411                if (de->mode) {
 412                        inode->i_mode = de->mode;
 413                        inode->i_uid = de->uid;
 414                        inode->i_gid = de->gid;
 415                }
 416                if (de->size)
 417                        inode->i_size = de->size;
 418                if (de->nlink)
 419                        inode->i_nlink = de->nlink;
 420                if (de->proc_iops)
 421                        inode->i_op = de->proc_iops;
 422                if (de->proc_fops) {
 423                        if (S_ISREG(inode->i_mode)) {
 424#ifdef CONFIG_COMPAT
 425                                if (!de->proc_fops->compat_ioctl)
 426                                        inode->i_fop =
 427                                                &proc_reg_file_ops_no_compat;
 428                                else
 429#endif
 430                                        inode->i_fop = &proc_reg_file_ops;
 431                        }
 432                        else
 433                                inode->i_fop = de->proc_fops;
 434                }
 435        }
 436
 437        return inode;
 438
 439out_ino:
 440        if (de != NULL)
 441                module_put(de->owner);
 442out_mod:
 443        return NULL;
 444}                       
 445
 446int proc_fill_super(struct super_block *s)
 447{
 448        struct inode * root_inode;
 449
 450        s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC;
 451        s->s_blocksize = 1024;
 452        s->s_blocksize_bits = 10;
 453        s->s_magic = PROC_SUPER_MAGIC;
 454        s->s_op = &proc_sops;
 455        s->s_time_gran = 1;
 456        
 457        de_get(&proc_root);
 458        root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root);
 459        if (!root_inode)
 460                goto out_no_root;
 461        root_inode->i_uid = 0;
 462        root_inode->i_gid = 0;
 463        s->s_root = d_alloc_root(root_inode);
 464        if (!s->s_root)
 465                goto out_no_root;
 466        return 0;
 467
 468out_no_root:
 469        printk("proc_read_super: get root inode failed\n");
 470        iput(root_inode);
 471        de_put(&proc_root);
 472        return -ENOMEM;
 473}
 474MODULE_LICENSE("GPL");
 475