Blame view

fs/proc/inode.c 11.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
  /*
   *  linux/fs/proc/inode.c
   *
   *  Copyright (C) 1991, 1992  Linus Torvalds
   */
  
  #include <linux/time.h>
  #include <linux/proc_fs.h>
  #include <linux/kernel.h>
97412950b   Vasiliy Kulikov   procfs: parse mou...
10
  #include <linux/pid_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
  #include <linux/mm.h>
  #include <linux/string.h>
  #include <linux/stat.h>
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
14
  #include <linux/completion.h>
dd23aae4f   Alexey Dobriyan   Fix select on /pr...
15
  #include <linux/poll.h>
87ebdc00e   Andrew Morton   fs/proc: clean up...
16
  #include <linux/printk.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
  #include <linux/file.h>
  #include <linux/limits.h>
  #include <linux/init.h>
  #include <linux/module.h>
9043476f7   Al Viro   [PATCH] sanitize ...
21
  #include <linux/sysctl.h>
97412950b   Vasiliy Kulikov   procfs: parse mou...
22
  #include <linux/seq_file.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
23
  #include <linux/slab.h>
97412950b   Vasiliy Kulikov   procfs: parse mou...
24
  #include <linux/mount.h>
303eb7e2c   David Howells   Include missing l...
25
  #include <linux/magic.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  #include <asm/uaccess.h>
fee781e6c   Adrian Bunk   [PATCH] fs/proc/:...
28
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

8267952b3   Al Viro   switch procfs to ...
30
  static void proc_evict_inode(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
  {
  	struct proc_dir_entry *de;
dfef6dcd3   Al Viro   unfuck proc_sysct...
33
  	struct ctl_table_header *head;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34

91b0abe36   Johannes Weiner   mm + fs: store sh...
35
  	truncate_inode_pages_final(&inode->i_data);
dbd5768f8   Jan Kara   vfs: Rename end_w...
36
  	clear_inode(inode);
fef266580   Mark Fasheh   [PATCH] update fi...
37

99f895518   Eric W. Biederman   [PATCH] proc: don...
38
  	/* Stop tracking associated processes */
13b41b094   Eric W. Biederman   [PATCH] proc: Use...
39
  	put_pid(PROC_I(inode)->pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
  
  	/* Let go of any associated proc directory entry */
6bee55f94   Alexander Kuleshov   fs: proc: use PDE...
42
  	de = PDE(inode);
99b762338   Alexey Dobriyan   proc 2/2: remove ...
43
  	if (de)
135d5655d   Alexey Dobriyan   proc: rename de_g...
44
  		pde_put(de);
dfef6dcd3   Al Viro   unfuck proc_sysct...
45
46
  	head = PROC_I(inode)->sysctl;
  	if (head) {
1c44dbc82   Monam Agarwal   fs/proc/inode.c: ...
47
  		RCU_INIT_POINTER(PROC_I(inode)->sysctl, NULL);
dfef6dcd3   Al Viro   unfuck proc_sysct...
48
49
  		sysctl_head_put(head);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
  }
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
51
  static struct kmem_cache * proc_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
55
56
  
  static struct inode *proc_alloc_inode(struct super_block *sb)
  {
  	struct proc_inode *ei;
  	struct inode *inode;
e94b17660   Christoph Lameter   [PATCH] slab: rem...
57
  	ei = (struct proc_inode *)kmem_cache_alloc(proc_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
  	if (!ei)
  		return NULL;
13b41b094   Eric W. Biederman   [PATCH] proc: Use...
60
  	ei->pid = NULL;
aed7a6c47   Eric W. Biederman   [PATCH] proc: Rep...
61
  	ei->fd = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
  	ei->op.proc_get_link = NULL;
  	ei->pde = NULL;
9043476f7   Al Viro   [PATCH] sanitize ...
64
65
  	ei->sysctl = NULL;
  	ei->sysctl_entry = NULL;
3d3d35b1e   Al Viro   kill proc_ns comp...
66
  	ei->ns_ops = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
69
70
  	inode = &ei->vfs_inode;
  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
  	return inode;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
71
  static void proc_i_callback(struct rcu_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
73
  	struct inode *inode = container_of(head, struct inode, i_rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
  	kmem_cache_free(proc_inode_cachep, PROC_I(inode));
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
76
77
78
79
  static void proc_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, proc_i_callback);
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
80
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
  {
  	struct proc_inode *ei = (struct proc_inode *) foo;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
83
  	inode_init_once(&ei->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
  }
20c2df83d   Paul Mundt   mm: Remove slab d...
85

5bcd7ff9e   Alexey Dobriyan   proc: proc_init_i...
86
  void __init proc_init_inodecache(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
88
89
  {
  	proc_inode_cachep = kmem_cache_create("proc_inode_cache",
  					     sizeof(struct proc_inode),
fffb60f93   Paul Jackson   [PATCH] cpuset me...
90
  					     0, (SLAB_RECLAIM_ACCOUNT|
5d097056c   Vladimir Davydov   kmemcg: account c...
91
92
  						SLAB_MEM_SPREAD|SLAB_ACCOUNT|
  						SLAB_PANIC),
20c2df83d   Paul Mundt   mm: Remove slab d...
93
  					     init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  }
97412950b   Vasiliy Kulikov   procfs: parse mou...
95
96
  static int proc_show_options(struct seq_file *seq, struct dentry *root)
  {
0499680a4   Vasiliy Kulikov   procfs: add hidep...
97
98
  	struct super_block *sb = root->d_sb;
  	struct pid_namespace *pid = sb->s_fs_info;
dcb0f2228   Eric W. Biederman   userns: Convert p...
99
100
  	if (!gid_eq(pid->pid_gid, GLOBAL_ROOT_GID))
  		seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, pid->pid_gid));
0499680a4   Vasiliy Kulikov   procfs: add hidep...
101
102
  	if (pid->hide_pid != 0)
  		seq_printf(seq, ",hidepid=%u", pid->hide_pid);
97412950b   Vasiliy Kulikov   procfs: parse mou...
103
104
  	return 0;
  }
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
105
  static const struct super_operations proc_sops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
  	.alloc_inode	= proc_alloc_inode,
  	.destroy_inode	= proc_destroy_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  	.drop_inode	= generic_delete_inode,
8267952b3   Al Viro   switch procfs to ...
109
  	.evict_inode	= proc_evict_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  	.statfs		= simple_statfs,
97412950b   Vasiliy Kulikov   procfs: parse mou...
111
112
  	.remount_fs	= proc_remount,
  	.show_options	= proc_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
  };
866ad9a74   Al Viro   procfs: preparati...
114
115
116
117
  enum {BIAS = -1U<<31};
  
  static inline int use_pde(struct proc_dir_entry *pde)
  {
05c0ae21c   Al Viro   try a saner locki...
118
  	return atomic_inc_unless_negative(&pde->in_use);
881adb853   Alexey Dobriyan   proc: always do -...
119
  }
866ad9a74   Al Viro   procfs: preparati...
120
  static void unuse_pde(struct proc_dir_entry *pde)
881adb853   Alexey Dobriyan   proc: always do -...
121
  {
05c0ae21c   Al Viro   try a saner locki...
122
123
  	if (atomic_dec_return(&pde->in_use) == BIAS)
  		complete(pde->pde_unload_completion);
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
124
  }
ca469f35a   Al Viro   deal with races b...
125
126
127
  /* pde is locked */
  static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo)
  {
05c0ae21c   Al Viro   try a saner locki...
128
  	if (pdeo->closing) {
ca469f35a   Al Viro   deal with races b...
129
  		/* somebody else is doing that, just wait */
05c0ae21c   Al Viro   try a saner locki...
130
131
  		DECLARE_COMPLETION_ONSTACK(c);
  		pdeo->c = &c;
ca469f35a   Al Viro   deal with races b...
132
  		spin_unlock(&pde->pde_unload_lock);
05c0ae21c   Al Viro   try a saner locki...
133
  		wait_for_completion(&c);
ca469f35a   Al Viro   deal with races b...
134
  		spin_lock(&pde->pde_unload_lock);
ca469f35a   Al Viro   deal with races b...
135
136
  	} else {
  		struct file *file;
05c0ae21c   Al Viro   try a saner locki...
137
  		pdeo->closing = 1;
ca469f35a   Al Viro   deal with races b...
138
139
140
141
142
  		spin_unlock(&pde->pde_unload_lock);
  		file = pdeo->file;
  		pde->proc_fops->release(file_inode(file), file);
  		spin_lock(&pde->pde_unload_lock);
  		list_del_init(&pdeo->lh);
05c0ae21c   Al Viro   try a saner locki...
143
144
  		if (pdeo->c)
  			complete(pdeo->c);
ca469f35a   Al Viro   deal with races b...
145
  		kfree(pdeo);
05c0ae21c   Al Viro   try a saner locki...
146
  	}
ca469f35a   Al Viro   deal with races b...
147
  }
866ad9a74   Al Viro   procfs: preparati...
148
  void proc_entry_rundown(struct proc_dir_entry *de)
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
149
  {
05c0ae21c   Al Viro   try a saner locki...
150
  	DECLARE_COMPLETION_ONSTACK(c);
866ad9a74   Al Viro   procfs: preparati...
151
  	/* Wait until all existing callers into module are done. */
05c0ae21c   Al Viro   try a saner locki...
152
153
154
  	de->pde_unload_completion = &c;
  	if (atomic_add_return(BIAS, &de->in_use) != BIAS)
  		wait_for_completion(&c);
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
155

05c0ae21c   Al Viro   try a saner locki...
156
  	spin_lock(&de->pde_unload_lock);
866ad9a74   Al Viro   procfs: preparati...
157
158
  	while (!list_empty(&de->pde_openers)) {
  		struct pde_opener *pdeo;
866ad9a74   Al Viro   procfs: preparati...
159
  		pdeo = list_first_entry(&de->pde_openers, struct pde_opener, lh);
ca469f35a   Al Viro   deal with races b...
160
  		close_pdeo(de, pdeo);
866ad9a74   Al Viro   procfs: preparati...
161
162
  	}
  	spin_unlock(&de->pde_unload_lock);
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
163
  }
866ad9a74   Al Viro   procfs: preparati...
164
165
166
167
168
169
170
171
172
173
174
175
  static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence)
  {
  	struct proc_dir_entry *pde = PDE(file_inode(file));
  	loff_t rv = -EINVAL;
  	if (use_pde(pde)) {
  		loff_t (*llseek)(struct file *, loff_t, int);
  		llseek = pde->proc_fops->llseek;
  		if (!llseek)
  			llseek = default_llseek;
  		rv = llseek(file, offset, whence);
  		unuse_pde(pde);
  	}
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
176
177
  	return rv;
  }
866ad9a74   Al Viro   procfs: preparati...
178
  static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
179
  {
866ad9a74   Al Viro   procfs: preparati...
180
  	ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
496ad9aa8   Al Viro   new helper: file_...
181
  	struct proc_dir_entry *pde = PDE(file_inode(file));
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
182
  	ssize_t rv = -EIO;
866ad9a74   Al Viro   procfs: preparati...
183
184
185
186
187
  	if (use_pde(pde)) {
  		read = pde->proc_fops->read;
  		if (read)
  			rv = read(file, buf, count, ppos);
  		unuse_pde(pde);
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
188
  	}
866ad9a74   Al Viro   procfs: preparati...
189
190
  	return rv;
  }
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
191

866ad9a74   Al Viro   procfs: preparati...
192
193
194
195
196
197
198
199
200
201
202
  static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
  {
  	ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
  	struct proc_dir_entry *pde = PDE(file_inode(file));
  	ssize_t rv = -EIO;
  	if (use_pde(pde)) {
  		write = pde->proc_fops->write;
  		if (write)
  			rv = write(file, buf, count, ppos);
  		unuse_pde(pde);
  	}
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
203
204
205
206
207
  	return rv;
  }
  
  static unsigned int proc_reg_poll(struct file *file, struct poll_table_struct *pts)
  {
496ad9aa8   Al Viro   new helper: file_...
208
  	struct proc_dir_entry *pde = PDE(file_inode(file));
dd23aae4f   Alexey Dobriyan   Fix select on /pr...
209
  	unsigned int rv = DEFAULT_POLLMASK;
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
210
  	unsigned int (*poll)(struct file *, struct poll_table_struct *);
866ad9a74   Al Viro   procfs: preparati...
211
212
213
214
215
  	if (use_pde(pde)) {
  		poll = pde->proc_fops->poll;
  		if (poll)
  			rv = poll(file, pts);
  		unuse_pde(pde);
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
216
  	}
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
217
218
219
220
221
  	return rv;
  }
  
  static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
496ad9aa8   Al Viro   new helper: file_...
222
  	struct proc_dir_entry *pde = PDE(file_inode(file));
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
223
  	long rv = -ENOTTY;
b19dd42fa   Arnd Bergmann   bkl: Remove locke...
224
  	long (*ioctl)(struct file *, unsigned int, unsigned long);
866ad9a74   Al Viro   procfs: preparati...
225
226
227
228
229
  	if (use_pde(pde)) {
  		ioctl = pde->proc_fops->unlocked_ioctl;
  		if (ioctl)
  			rv = ioctl(file, cmd, arg);
  		unuse_pde(pde);
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
230
  	}
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
231
232
233
234
235
236
  	return rv;
  }
  
  #ifdef CONFIG_COMPAT
  static long proc_reg_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
496ad9aa8   Al Viro   new helper: file_...
237
  	struct proc_dir_entry *pde = PDE(file_inode(file));
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
238
239
  	long rv = -ENOTTY;
  	long (*compat_ioctl)(struct file *, unsigned int, unsigned long);
866ad9a74   Al Viro   procfs: preparati...
240
241
242
243
244
  	if (use_pde(pde)) {
  		compat_ioctl = pde->proc_fops->compat_ioctl;
  		if (compat_ioctl)
  			rv = compat_ioctl(file, cmd, arg);
  		unuse_pde(pde);
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
245
  	}
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
246
247
248
249
250
251
  	return rv;
  }
  #endif
  
  static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma)
  {
496ad9aa8   Al Viro   new helper: file_...
252
  	struct proc_dir_entry *pde = PDE(file_inode(file));
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
253
254
  	int rv = -EIO;
  	int (*mmap)(struct file *, struct vm_area_struct *);
866ad9a74   Al Viro   procfs: preparati...
255
256
257
258
259
  	if (use_pde(pde)) {
  		mmap = pde->proc_fops->mmap;
  		if (mmap)
  			rv = mmap(file, vma);
  		unuse_pde(pde);
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
260
  	}
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
261
262
  	return rv;
  }
5721cf84d   HATAYAMA Daisuke   procfs: clean up ...
263
264
265
266
  static unsigned long
  proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr,
  			   unsigned long len, unsigned long pgoff,
  			   unsigned long flags)
c4fe24485   Alexey Dobriyan   sparc: fix PCI de...
267
268
  {
  	struct proc_dir_entry *pde = PDE(file_inode(file));
2cbe3b0af   HATAYAMA Daisuke   procfs: fix unint...
269
  	unsigned long rv = -EIO;
ae5758a1a   Jan Beulich   procfs: also fix ...
270

c4fe24485   Alexey Dobriyan   sparc: fix PCI de...
271
  	if (use_pde(pde)) {
ae5758a1a   Jan Beulich   procfs: also fix ...
272
273
274
  		typeof(proc_reg_get_unmapped_area) *get_area;
  
  		get_area = pde->proc_fops->get_unmapped_area;
fad1a86e2   HATAYAMA Daisuke   procfs: call defa...
275
  #ifdef CONFIG_MMU
ae5758a1a   Jan Beulich   procfs: also fix ...
276
277
  		if (!get_area)
  			get_area = current->mm->get_unmapped_area;
fad1a86e2   HATAYAMA Daisuke   procfs: call defa...
278
  #endif
ae5758a1a   Jan Beulich   procfs: also fix ...
279

5721cf84d   HATAYAMA Daisuke   procfs: clean up ...
280
281
  		if (get_area)
  			rv = get_area(file, orig_addr, len, pgoff, flags);
ae5758a1a   Jan Beulich   procfs: also fix ...
282
283
  		else
  			rv = orig_addr;
c4fe24485   Alexey Dobriyan   sparc: fix PCI de...
284
285
286
287
  		unuse_pde(pde);
  	}
  	return rv;
  }
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
288
289
290
291
292
  static int proc_reg_open(struct inode *inode, struct file *file)
  {
  	struct proc_dir_entry *pde = PDE(inode);
  	int rv = 0;
  	int (*open)(struct inode *, struct file *);
881adb853   Alexey Dobriyan   proc: always do -...
293
294
295
296
297
298
299
300
301
302
303
304
305
  	int (*release)(struct inode *, struct file *);
  	struct pde_opener *pdeo;
  
  	/*
  	 * What for, you ask? Well, we can have open, rmmod, remove_proc_entry
  	 * sequence. ->release won't be called because ->proc_fops will be
  	 * cleared. Depending on complexity of ->release, consequences vary.
  	 *
  	 * We can't wait for mercy when close will be done for real, it's
  	 * deadlockable: rmmod foo </proc/foo . So, we're going to do ->release
  	 * by hand in remove_proc_entry(). For this, save opener's credentials
  	 * for later.
  	 */
05c0ae21c   Al Viro   try a saner locki...
306
  	pdeo = kzalloc(sizeof(struct pde_opener), GFP_KERNEL);
881adb853   Alexey Dobriyan   proc: always do -...
307
308
  	if (!pdeo)
  		return -ENOMEM;
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
309

866ad9a74   Al Viro   procfs: preparati...
310
  	if (!use_pde(pde)) {
881adb853   Alexey Dobriyan   proc: always do -...
311
  		kfree(pdeo);
d2857e79a   Daisuke Ogino   procfs: return EN...
312
  		return -ENOENT;
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
313
  	}
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
314
  	open = pde->proc_fops->open;
881adb853   Alexey Dobriyan   proc: always do -...
315
  	release = pde->proc_fops->release;
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
316
317
318
  
  	if (open)
  		rv = open(inode, file);
881adb853   Alexey Dobriyan   proc: always do -...
319
320
  	if (rv == 0 && release) {
  		/* To know what to release. */
881adb853   Alexey Dobriyan   proc: always do -...
321
322
  		pdeo->file = file;
  		/* Strictly for "too late" ->release in proc_reg_release(). */
05c0ae21c   Al Viro   try a saner locki...
323
  		spin_lock(&pde->pde_unload_lock);
881adb853   Alexey Dobriyan   proc: always do -...
324
  		list_add(&pdeo->lh, &pde->pde_openers);
05c0ae21c   Al Viro   try a saner locki...
325
  		spin_unlock(&pde->pde_unload_lock);
881adb853   Alexey Dobriyan   proc: always do -...
326
327
  	} else
  		kfree(pdeo);
05c0ae21c   Al Viro   try a saner locki...
328
329
  
  	unuse_pde(pde);
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
330
331
332
333
334
335
  	return rv;
  }
  
  static int proc_reg_release(struct inode *inode, struct file *file)
  {
  	struct proc_dir_entry *pde = PDE(inode);
881adb853   Alexey Dobriyan   proc: always do -...
336
  	struct pde_opener *pdeo;
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
337
  	spin_lock(&pde->pde_unload_lock);
ca469f35a   Al Viro   deal with races b...
338
339
340
341
342
  	list_for_each_entry(pdeo, &pde->pde_openers, lh) {
  		if (pdeo->file == file) {
  			close_pdeo(pde, pdeo);
  			break;
  		}
881adb853   Alexey Dobriyan   proc: always do -...
343
  	}
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
344
  	spin_unlock(&pde->pde_unload_lock);
ca469f35a   Al Viro   deal with races b...
345
  	return 0;
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
346
347
348
349
350
351
352
353
354
355
356
357
  }
  
  static const struct file_operations proc_reg_file_ops = {
  	.llseek		= proc_reg_llseek,
  	.read		= proc_reg_read,
  	.write		= proc_reg_write,
  	.poll		= proc_reg_poll,
  	.unlocked_ioctl	= proc_reg_unlocked_ioctl,
  #ifdef CONFIG_COMPAT
  	.compat_ioctl	= proc_reg_compat_ioctl,
  #endif
  	.mmap		= proc_reg_mmap,
c4fe24485   Alexey Dobriyan   sparc: fix PCI de...
358
  	.get_unmapped_area = proc_reg_get_unmapped_area,
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
359
360
361
  	.open		= proc_reg_open,
  	.release	= proc_reg_release,
  };
778f3dd5a   David Miller   Fix procfs compat...
362
363
364
365
366
367
368
369
  #ifdef CONFIG_COMPAT
  static const struct file_operations proc_reg_file_ops_no_compat = {
  	.llseek		= proc_reg_llseek,
  	.read		= proc_reg_read,
  	.write		= proc_reg_write,
  	.poll		= proc_reg_poll,
  	.unlocked_ioctl	= proc_reg_unlocked_ioctl,
  	.mmap		= proc_reg_mmap,
c4fe24485   Alexey Dobriyan   sparc: fix PCI de...
370
  	.get_unmapped_area = proc_reg_get_unmapped_area,
778f3dd5a   David Miller   Fix procfs compat...
371
372
373
374
  	.open		= proc_reg_open,
  	.release	= proc_reg_release,
  };
  #endif
fceef393a   Al Viro   switch ->get_link...
375
376
377
378
  static void proc_put_link(void *p)
  {
  	unuse_pde(p);
  }
6b2553918   Al Viro   replace ->follow_...
379
  static const char *proc_get_link(struct dentry *dentry,
fceef393a   Al Viro   switch ->get_link...
380
381
  				 struct inode *inode,
  				 struct delayed_call *done)
7e0e953bb   Al Viro   procfs: fix race ...
382
  {
6b2553918   Al Viro   replace ->follow_...
383
  	struct proc_dir_entry *pde = PDE(inode);
7e0e953bb   Al Viro   procfs: fix race ...
384
385
  	if (unlikely(!use_pde(pde)))
  		return ERR_PTR(-EINVAL);
fceef393a   Al Viro   switch ->get_link...
386
  	set_delayed_call(done, proc_put_link, pde);
680baacbc   Al Viro   new ->follow_link...
387
  	return pde->data;
7e0e953bb   Al Viro   procfs: fix race ...
388
  }
7e0e953bb   Al Viro   procfs: fix race ...
389
390
  const struct inode_operations proc_link_inode_operations = {
  	.readlink	= generic_readlink,
6b2553918   Al Viro   replace ->follow_...
391
  	.get_link	= proc_get_link,
7e0e953bb   Al Viro   procfs: fix race ...
392
  };
6d1b6e4ef   Alexey Dobriyan   proc: ->low_ino c...
393
  struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
  {
51f0885e5   Linus Torvalds   vfs,proc: guarant...
395
  	struct inode *inode = new_inode_pseudo(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396

51f0885e5   Linus Torvalds   vfs,proc: guarant...
397
398
  	if (inode) {
  		inode->i_ino = de->low_ino;
a1d4aebbf   David Howells   iget: stop PROCFS...
399
  		inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
a1d4aebbf   David Howells   iget: stop PROCFS...
400
  		PROC_I(inode)->pde = de;
5e971dce0   Alexey Dobriyan   proc: drop severa...
401

eb6d38d54   Eric W. Biederman   proc: Allow creat...
402
403
404
405
  		if (is_empty_pde(de)) {
  			make_empty_dir_inode(inode);
  			return inode;
  		}
5e971dce0   Alexey Dobriyan   proc: drop severa...
406
407
408
409
410
411
412
413
  		if (de->mode) {
  			inode->i_mode = de->mode;
  			inode->i_uid = de->uid;
  			inode->i_gid = de->gid;
  		}
  		if (de->size)
  			inode->i_size = de->size;
  		if (de->nlink)
bfe868486   Miklos Szeredi   filesystems: add ...
414
  			set_nlink(inode, de->nlink);
b6cdc7310   Al Viro   procfs: don't all...
415
416
  		WARN_ON(!de->proc_iops);
  		inode->i_op = de->proc_iops;
5e971dce0   Alexey Dobriyan   proc: drop severa...
417
418
  		if (de->proc_fops) {
  			if (S_ISREG(inode->i_mode)) {
778f3dd5a   David Miller   Fix procfs compat...
419
  #ifdef CONFIG_COMPAT
5e971dce0   Alexey Dobriyan   proc: drop severa...
420
421
422
423
  				if (!de->proc_fops->compat_ioctl)
  					inode->i_fop =
  						&proc_reg_file_ops_no_compat;
  				else
778f3dd5a   David Miller   Fix procfs compat...
424
  #endif
5e971dce0   Alexey Dobriyan   proc: drop severa...
425
426
427
  					inode->i_fop = &proc_reg_file_ops;
  			} else {
  				inode->i_fop = de->proc_fops;
778f3dd5a   David Miller   Fix procfs compat...
428
  			}
786d7e161   Alexey Dobriyan   Fix rmmod/read/wr...
429
  		}
99b762338   Alexey Dobriyan   proc 2/2: remove ...
430
  	} else
135d5655d   Alexey Dobriyan   proc: rename de_g...
431
  	       pde_put(de);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
  	return inode;
d3d009cb9   Al Viro   saner proc_get_in...
433
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434

07543f5c7   Pavel Emelyanov   pid namespaces: m...
435
  int proc_fill_super(struct super_block *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
  {
87e0aab37   Maxim Patlasov   proc: avoid extra...
437
  	struct inode *root_inode;
0097875bd   Eric W. Biederman   proc: Implement /...
438
  	int ret;
87e0aab37   Maxim Patlasov   proc: avoid extra...
439

92d032855   Linus Torvalds   Mark /proc MS_NOS...
440
  	s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
443
444
445
446
  	s->s_blocksize = 1024;
  	s->s_blocksize_bits = 10;
  	s->s_magic = PROC_SUPER_MAGIC;
  	s->s_op = &proc_sops;
  	s->s_time_gran = 1;
  	
135d5655d   Alexey Dobriyan   proc: rename de_g...
447
  	pde_get(&proc_root);
87e0aab37   Maxim Patlasov   proc: avoid extra...
448
449
  	root_inode = proc_get_inode(s, &proc_root);
  	if (!root_inode) {
87ebdc00e   Andrew Morton   fs/proc: clean up...
450
451
  		pr_err("proc_fill_super: get root inode failed
  ");
87e0aab37   Maxim Patlasov   proc: avoid extra...
452
453
  		return -ENOMEM;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454

87e0aab37   Maxim Patlasov   proc: avoid extra...
455
456
  	s->s_root = d_make_root(root_inode);
  	if (!s->s_root) {
87ebdc00e   Andrew Morton   fs/proc: clean up...
457
458
  		pr_err("proc_fill_super: allocate dentry failed
  ");
87e0aab37   Maxim Patlasov   proc: avoid extra...
459
460
  		return -ENOMEM;
  	}
0097875bd   Eric W. Biederman   proc: Implement /...
461
462
463
464
465
  	ret = proc_setup_self(s);
  	if (ret) {
  		return ret;
  	}
  	return proc_setup_thread_self(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
  }