2013-04-11 16:34:43 +04:00
/* Internal procfs definitions
2005-04-17 02:20:36 +04:00
*
* Copyright ( C ) 2004 Red Hat , Inc . All Rights Reserved .
* Written by David Howells ( dhowells @ redhat . com )
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*/
# include <linux/proc_fs.h>
2013-04-11 16:34:43 +04:00
# include <linux/proc_ns.h>
# include <linux/spinlock.h>
# include <linux/atomic.h>
2013-02-28 05:03:15 +04:00
# include <linux/binfmts.h>
2005-04-17 02:20:36 +04:00
2013-04-11 16:34:43 +04:00
struct ctl_table_header ;
struct mempolicy ;
2007-02-14 11:34:12 +03:00
2013-04-11 16:34:43 +04:00
/*
* This is not completely implemented yet . The idea is to
* create an in - memory tree ( like the actual / proc filesystem
* tree ) of these proc_dir_entries , so that we can dynamically
* add new files to / proc .
*
* The " next " pointer creates a linked list of one / proc directory ,
* while parent / subdir create the directory structure ( every
* / proc file has a parent , but " subdir " is NULL for all
* non - directory entries ) .
*/
struct proc_dir_entry {
unsigned int low_ino ;
umode_t mode ;
nlink_t nlink ;
kuid_t uid ;
kgid_t gid ;
loff_t size ;
const struct inode_operations * proc_iops ;
const struct file_operations * proc_fops ;
struct proc_dir_entry * next , * parent , * subdir ;
void * data ;
atomic_t count ; /* use count */
atomic_t in_use ; /* number of callers into module in progress; */
/* negative -> it's going away RSN */
struct completion * pde_unload_completion ;
struct list_head pde_openers ; /* who did ->open, but not ->release */
spinlock_t pde_unload_lock ; /* proc_fops checks and pde_users bumps */
u8 namelen ;
char name [ ] ;
2005-04-17 02:20:36 +04:00
} ;
2013-04-11 16:34:43 +04:00
union proc_op {
int ( * proc_get_link ) ( struct dentry * , struct path * ) ;
int ( * proc_read ) ( struct task_struct * task , char * page ) ;
int ( * proc_show ) ( struct seq_file * m ,
struct pid_namespace * ns , struct pid * pid ,
struct task_struct * task ) ;
} ;
2006-06-26 11:25:55 +04:00
2013-04-11 16:34:43 +04:00
struct proc_inode {
2011-05-25 04:12:48 +04:00
struct pid * pid ;
2013-04-11 16:34:43 +04:00
int fd ;
union proc_op op ;
struct proc_dir_entry * pde ;
struct ctl_table_header * sysctl ;
struct ctl_table * sysctl_entry ;
struct proc_ns ns ;
struct inode vfs_inode ;
2011-05-25 04:12:48 +04:00
} ;
2013-04-12 21:03:36 +04:00
/*
* General functions
*/
static inline struct proc_inode * PROC_I ( const struct inode * inode )
{
return container_of ( inode , struct proc_inode , vfs_inode ) ;
}
static inline struct proc_dir_entry * PDE ( const struct inode * inode )
{
return PROC_I ( inode ) - > pde ;
}
static inline void * __PDE_DATA ( const struct inode * inode )
{
return PDE ( inode ) - > data ;
}
2006-01-08 12:04:16 +03:00
2006-06-26 11:25:56 +04:00
static inline struct pid * proc_pid ( struct inode * inode )
2006-06-26 11:25:55 +04:00
{
2006-06-26 11:25:56 +04:00
return PROC_I ( inode ) - > pid ;
2006-06-26 11:25:55 +04:00
}
static inline struct task_struct * get_proc_task ( struct inode * inode )
2005-04-17 02:20:36 +04:00
{
2006-06-26 11:25:56 +04:00
return get_pid_task ( proc_pid ( inode ) , PIDTYPE_PID ) ;
2005-04-17 02:20:36 +04:00
}
2012-08-23 14:43:24 +04:00
static inline int task_dumpable ( struct task_struct * task )
{
int dumpable = 0 ;
struct mm_struct * mm ;
task_lock ( task ) ;
mm = task - > mm ;
if ( mm )
dumpable = get_dumpable ( mm ) ;
task_unlock ( task ) ;
2013-02-28 05:03:15 +04:00
if ( dumpable = = SUID_DUMP_USER )
2012-08-23 14:43:24 +04:00
return 1 ;
return 0 ;
}
static inline unsigned name_to_int ( struct dentry * dentry )
{
const char * name = dentry - > d_name . name ;
int len = dentry - > d_name . len ;
unsigned n = 0 ;
if ( len > 1 & & * name = = ' 0 ' )
goto out ;
while ( len - - > 0 ) {
unsigned c = * name + + - ' 0 ' ;
if ( c > 9 )
goto out ;
if ( n > = ( ~ 0U - 9 ) / 10 )
goto out ;
n * = 10 ;
n + = c ;
}
return n ;
out :
return ~ 0U ;
}
2013-04-12 04:08:50 +04:00
/*
2013-04-11 16:34:43 +04:00
* Offset of the first process in the / proc root directory . .
2013-04-12 04:08:50 +04:00
*/
2013-04-11 16:34:43 +04:00
# define FIRST_PROCESS_ENTRY 256
2013-04-12 04:08:50 +04:00
2013-04-11 16:34:43 +04:00
/* Worst case buffer size needed for holding an integer. */
# define PROC_NUMBUF 13
2008-07-25 12:48:29 +04:00
2013-04-11 16:34:43 +04:00
/*
* array . c
*/
extern const struct file_operations proc_tid_children_operations ;
2009-04-07 21:19:18 +04:00
2013-04-11 16:34:43 +04:00
extern int proc_tid_stat ( struct seq_file * , struct pid_namespace * ,
struct pid * , struct task_struct * ) ;
extern int proc_tgid_stat ( struct seq_file * , struct pid_namespace * ,
struct pid * , struct task_struct * ) ;
extern int proc_pid_status ( struct seq_file * , struct pid_namespace * ,
struct pid * , struct task_struct * ) ;
extern int proc_pid_statm ( struct seq_file * , struct pid_namespace * ,
struct pid * , struct task_struct * ) ;
/*
* base . c
*/
extern const struct dentry_operations pid_dentry_operations ;
extern int pid_getattr ( struct vfsmount * , struct dentry * , struct kstat * ) ;
extern int proc_setattr ( struct dentry * , struct iattr * ) ;
extern struct inode * proc_pid_make_inode ( struct super_block * , struct task_struct * ) ;
extern int pid_revalidate ( struct dentry * , unsigned int ) ;
extern int pid_delete_dentry ( const struct dentry * ) ;
2013-05-16 20:07:31 +04:00
extern int proc_pid_readdir ( struct file * , struct dir_context * ) ;
2013-04-11 16:34:43 +04:00
extern struct dentry * proc_pid_lookup ( struct inode * , struct dentry * , unsigned int ) ;
extern loff_t mem_lseek ( struct file * , loff_t , int ) ;
2013-04-04 03:07:30 +04:00
2013-04-11 16:34:43 +04:00
/* Lookups */
2013-06-15 11:15:20 +04:00
typedef int instantiate_t ( struct inode * , struct dentry * ,
2013-04-11 16:34:43 +04:00
struct task_struct * , const void * ) ;
2013-05-16 20:07:31 +04:00
extern bool proc_fill_cache ( struct file * , struct dir_context * , const char * , int ,
2013-04-11 16:34:43 +04:00
instantiate_t , struct task_struct * , const void * ) ;
2009-04-07 21:19:18 +04:00
2013-04-11 16:34:43 +04:00
/*
* generic . c
*/
2009-04-07 21:19:18 +04:00
extern spinlock_t proc_subdir_lock ;
2013-04-11 16:34:43 +04:00
extern struct dentry * proc_lookup ( struct inode * , struct dentry * , unsigned int ) ;
extern struct dentry * proc_lookup_de ( struct proc_dir_entry * , struct inode * ,
struct dentry * ) ;
2013-05-16 20:07:31 +04:00
extern int proc_readdir ( struct file * , struct dir_context * ) ;
extern int proc_readdir_de ( struct proc_dir_entry * , struct file * , struct dir_context * ) ;
2009-04-07 21:19:18 +04:00
2009-12-16 03:45:39 +03:00
static inline struct proc_dir_entry * pde_get ( struct proc_dir_entry * pde )
{
atomic_inc ( & pde - > count ) ;
return pde ;
}
2013-04-11 16:34:43 +04:00
extern void pde_put ( struct proc_dir_entry * ) ;
2009-04-07 21:19:18 +04:00
/*
2013-04-11 16:34:43 +04:00
* inode . c
2009-04-07 21:19:18 +04:00
*/
2013-04-11 16:34:43 +04:00
struct pde_opener {
struct file * file ;
struct list_head lh ;
int closing ;
struct completion * c ;
} ;
2010-03-08 03:41:34 +03:00
2013-04-11 16:34:43 +04:00
extern const struct inode_operations proc_pid_link_inode_operations ;
2010-03-08 03:41:34 +03:00
2013-04-11 16:34:43 +04:00
extern void proc_init_inodecache ( void ) ;
extern struct inode * proc_get_inode ( struct super_block * , struct proc_dir_entry * ) ;
extern int proc_fill_super ( struct super_block * ) ;
extern void proc_entry_rundown ( struct proc_dir_entry * ) ;
2010-03-08 03:41:34 +03:00
2013-04-11 16:34:43 +04:00
/*
* proc_devtree . c
*/
# ifdef CONFIG_PROC_DEVICETREE
extern void proc_device_tree_init ( void ) ;
# endif
2010-03-08 03:41:34 +03:00
2013-04-11 16:34:43 +04:00
/*
* proc_namespaces . c
*/
2010-03-08 03:41:34 +03:00
extern const struct inode_operations proc_ns_dir_inode_operations ;
extern const struct file_operations proc_ns_dir_operations ;
2013-04-11 16:34:43 +04:00
/*
* proc_net . c
*/
extern const struct file_operations proc_net_operations ;
extern const struct inode_operations proc_net_inode_operations ;
# ifdef CONFIG_NET
extern int proc_net_init ( void ) ;
# else
static inline int proc_net_init ( void ) { return 0 ; }
# endif
/*
* proc_self . c
*/
2013-03-30 03:27:05 +04:00
extern int proc_setup_self ( struct super_block * ) ;
2013-04-12 05:29:19 +04:00
/*
2013-04-11 16:34:43 +04:00
* proc_sysctl . c
2013-04-12 05:29:19 +04:00
*/
2013-04-11 16:34:43 +04:00
# ifdef CONFIG_PROC_SYSCTL
extern int proc_sys_init ( void ) ;
extern void sysctl_head_put ( struct ctl_table_header * ) ;
# else
static inline void proc_sys_init ( void ) { }
static inline void sysctl_head_put ( struct ctl_table_header * head ) { }
# endif
2013-04-12 05:29:19 +04:00
/*
* proc_tty . c
*/
# ifdef CONFIG_TTY
extern void proc_tty_init ( void ) ;
# else
static inline void proc_tty_init ( void ) { }
# endif
2013-04-11 16:34:43 +04:00
/*
* root . c
*/
extern struct proc_dir_entry proc_root ;
extern void proc_self_init ( void ) ;
extern int proc_remount ( struct super_block * , int * , char * ) ;
/*
* task_ [ no ] mmu . c
*/
struct proc_maps_private {
struct pid * pid ;
struct task_struct * task ;
# ifdef CONFIG_MMU
struct vm_area_struct * tail_vma ;
# endif
# ifdef CONFIG_NUMA
struct mempolicy * task_mempolicy ;
# endif
} ;
extern const struct file_operations proc_pid_maps_operations ;
extern const struct file_operations proc_tid_maps_operations ;
extern const struct file_operations proc_pid_numa_maps_operations ;
extern const struct file_operations proc_tid_numa_maps_operations ;
extern const struct file_operations proc_pid_smaps_operations ;
extern const struct file_operations proc_tid_smaps_operations ;
extern const struct file_operations proc_clear_refs_operations ;
extern const struct file_operations proc_pagemap_operations ;
extern unsigned long task_vsize ( struct mm_struct * ) ;
extern unsigned long task_statm ( struct mm_struct * ,
unsigned long * , unsigned long * ,
unsigned long * , unsigned long * ) ;
extern void task_mem ( struct seq_file * , struct mm_struct * ) ;