Blame view
fs/proc/inode.c
11.9 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 |
/* * linux/fs/proc/inode.c * * Copyright (C) 1991, 1992 Linus Torvalds */ |
efb1a57d9 fs/proc: use __ro... |
7 |
#include <linux/cache.h> |
1da177e4c Linux-2.6.12-rc2 |
8 9 10 |
#include <linux/time.h> #include <linux/proc_fs.h> #include <linux/kernel.h> |
97412950b procfs: parse mou... |
11 |
#include <linux/pid_namespace.h> |
1da177e4c Linux-2.6.12-rc2 |
12 13 14 |
#include <linux/mm.h> #include <linux/string.h> #include <linux/stat.h> |
786d7e161 Fix rmmod/read/wr... |
15 |
#include <linux/completion.h> |
dd23aae4f Fix select on /pr... |
16 |
#include <linux/poll.h> |
87ebdc00e fs/proc: clean up... |
17 |
#include <linux/printk.h> |
1da177e4c Linux-2.6.12-rc2 |
18 19 20 21 |
#include <linux/file.h> #include <linux/limits.h> #include <linux/init.h> #include <linux/module.h> |
9043476f7 [PATCH] sanitize ... |
22 |
#include <linux/sysctl.h> |
97412950b procfs: parse mou... |
23 |
#include <linux/seq_file.h> |
5a0e3ad6a include cleanup: ... |
24 |
#include <linux/slab.h> |
97412950b procfs: parse mou... |
25 |
#include <linux/mount.h> |
1da177e4c Linux-2.6.12-rc2 |
26 |
|
7c0f6ba68 Replace <asm/uacc... |
27 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
28 |
|
fee781e6c [PATCH] fs/proc/:... |
29 |
#include "internal.h" |
1da177e4c Linux-2.6.12-rc2 |
30 |
|
8267952b3 switch procfs to ... |
31 |
static void proc_evict_inode(struct inode *inode) |
1da177e4c Linux-2.6.12-rc2 |
32 33 |
{ struct proc_dir_entry *de; |
dfef6dcd3 unfuck proc_sysct... |
34 |
struct ctl_table_header *head; |
1da177e4c Linux-2.6.12-rc2 |
35 |
|
91b0abe36 mm + fs: store sh... |
36 |
truncate_inode_pages_final(&inode->i_data); |
dbd5768f8 vfs: Rename end_w... |
37 |
clear_inode(inode); |
fef266580 [PATCH] update fi... |
38 |
|
99f895518 [PATCH] proc: don... |
39 |
/* Stop tracking associated processes */ |
13b41b094 [PATCH] proc: Use... |
40 |
put_pid(PROC_I(inode)->pid); |
1da177e4c Linux-2.6.12-rc2 |
41 42 |
/* Let go of any associated proc directory entry */ |
6bee55f94 fs: proc: use PDE... |
43 |
de = PDE(inode); |
99b762338 proc 2/2: remove ... |
44 |
if (de) |
135d5655d proc: rename de_g... |
45 |
pde_put(de); |
d6cffbbe9 proc/sysctl: prun... |
46 |
|
dfef6dcd3 unfuck proc_sysct... |
47 48 |
head = PROC_I(inode)->sysctl; if (head) { |
1c44dbc82 fs/proc/inode.c: ... |
49 |
RCU_INIT_POINTER(PROC_I(inode)->sysctl, NULL); |
d6cffbbe9 proc/sysctl: prun... |
50 |
proc_sys_evict_inode(inode, head); |
dfef6dcd3 unfuck proc_sysct... |
51 |
} |
1da177e4c Linux-2.6.12-rc2 |
52 |
} |
efb1a57d9 fs/proc: use __ro... |
53 |
static struct kmem_cache *proc_inode_cachep __ro_after_init; |
195b8cf06 proc: move "struc... |
54 |
static struct kmem_cache *pde_opener_cache __ro_after_init; |
1da177e4c Linux-2.6.12-rc2 |
55 56 57 58 |
static struct inode *proc_alloc_inode(struct super_block *sb) { struct proc_inode *ei; |
1da177e4c Linux-2.6.12-rc2 |
59 |
|
f245e1c17 fs/proc/inode.c: ... |
60 |
ei = kmem_cache_alloc(proc_inode_cachep, GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
61 62 |
if (!ei) return NULL; |
13b41b094 [PATCH] proc: Use... |
63 |
ei->pid = NULL; |
aed7a6c47 [PATCH] proc: Rep... |
64 |
ei->fd = 0; |
1da177e4c Linux-2.6.12-rc2 |
65 66 |
ei->op.proc_get_link = NULL; ei->pde = NULL; |
9043476f7 [PATCH] sanitize ... |
67 68 |
ei->sysctl = NULL; ei->sysctl_entry = NULL; |
3d3d35b1e kill proc_ns comp... |
69 |
ei->ns_ops = NULL; |
230f72e9f fs/proc/inode.c: ... |
70 |
return &ei->vfs_inode; |
1da177e4c Linux-2.6.12-rc2 |
71 |
} |
4aa6b55c0 procfs: switch to... |
72 |
static void proc_free_inode(struct inode *inode) |
1da177e4c Linux-2.6.12-rc2 |
73 74 75 |
{ kmem_cache_free(proc_inode_cachep, PROC_I(inode)); } |
51cc50685 SL*B: drop kmem c... |
76 |
static void init_once(void *foo) |
1da177e4c Linux-2.6.12-rc2 |
77 78 |
{ struct proc_inode *ei = (struct proc_inode *) foo; |
a35afb830 Remove SLAB_CTOR_... |
79 |
inode_init_once(&ei->vfs_inode); |
1da177e4c Linux-2.6.12-rc2 |
80 |
} |
20c2df83d mm: Remove slab d... |
81 |
|
195b8cf06 proc: move "struc... |
82 |
void __init proc_init_kmemcache(void) |
1da177e4c Linux-2.6.12-rc2 |
83 84 85 |
{ proc_inode_cachep = kmem_cache_create("proc_inode_cache", sizeof(struct proc_inode), |
fffb60f93 [PATCH] cpuset me... |
86 |
0, (SLAB_RECLAIM_ACCOUNT| |
5d097056c kmemcg: account c... |
87 88 |
SLAB_MEM_SPREAD|SLAB_ACCOUNT| SLAB_PANIC), |
20c2df83d mm: Remove slab d... |
89 |
init_once); |
195b8cf06 proc: move "struc... |
90 91 |
pde_opener_cache = kmem_cache_create("pde_opener", sizeof(struct pde_opener), 0, |
2acddbe81 proc: account "st... |
92 |
SLAB_ACCOUNT|SLAB_PANIC, NULL); |
b4884f233 proc: move "struc... |
93 |
proc_dir_entry_cache = kmem_cache_create_usercopy( |
2d6e4e822 proc: fixup PDE a... |
94 95 96 97 |
"proc_dir_entry", SIZEOF_PDE, 0, SLAB_PANIC, offsetof(struct proc_dir_entry, inline_name), SIZEOF_PDE_INLINE_NAME, NULL); BUILD_BUG_ON(sizeof(struct proc_dir_entry) >= SIZEOF_PDE); |
1da177e4c Linux-2.6.12-rc2 |
98 |
} |
97412950b procfs: parse mou... |
99 100 |
static int proc_show_options(struct seq_file *seq, struct dentry *root) { |
0499680a4 procfs: add hidep... |
101 102 |
struct super_block *sb = root->d_sb; struct pid_namespace *pid = sb->s_fs_info; |
dcb0f2228 userns: Convert p... |
103 104 |
if (!gid_eq(pid->pid_gid, GLOBAL_ROOT_GID)) seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, pid->pid_gid)); |
796f571b0 procfs: use an en... |
105 |
if (pid->hide_pid != HIDEPID_OFF) |
0499680a4 procfs: add hidep... |
106 |
seq_printf(seq, ",hidepid=%u", pid->hide_pid); |
97412950b procfs: parse mou... |
107 108 |
return 0; } |
60a3c3a58 procfs: Move proc... |
109 |
const struct super_operations proc_sops = { |
1da177e4c Linux-2.6.12-rc2 |
110 |
.alloc_inode = proc_alloc_inode, |
4aa6b55c0 procfs: switch to... |
111 |
.free_inode = proc_free_inode, |
1da177e4c Linux-2.6.12-rc2 |
112 |
.drop_inode = generic_delete_inode, |
8267952b3 switch procfs to ... |
113 |
.evict_inode = proc_evict_inode, |
1da177e4c Linux-2.6.12-rc2 |
114 |
.statfs = simple_statfs, |
97412950b procfs: parse mou... |
115 |
.show_options = proc_show_options, |
1da177e4c Linux-2.6.12-rc2 |
116 |
}; |
866ad9a74 procfs: preparati... |
117 118 119 120 |
enum {BIAS = -1U<<31}; static inline int use_pde(struct proc_dir_entry *pde) { |
15b158b4e proc: spread like... |
121 |
return likely(atomic_inc_unless_negative(&pde->in_use)); |
881adb853 proc: always do -... |
122 |
} |
866ad9a74 procfs: preparati... |
123 |
static void unuse_pde(struct proc_dir_entry *pde) |
881adb853 proc: always do -... |
124 |
{ |
15b158b4e proc: spread like... |
125 |
if (unlikely(atomic_dec_return(&pde->in_use) == BIAS)) |
05c0ae21c try a saner locki... |
126 |
complete(pde->pde_unload_completion); |
786d7e161 Fix rmmod/read/wr... |
127 |
} |
2f8974243 proc: do less stu... |
128 |
/* pde is locked on entry, unlocked on exit */ |
ca469f35a deal with races b... |
129 130 |
static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo) { |
492b2da60 proc: tweak comme... |
131 132 133 134 135 136 137 138 139 140 |
/* * close() (proc_reg_release()) can't delete an entry and proceed: * ->release hook needs to be available at the right moment. * * rmmod (remove_proc_entry() et al) can't delete an entry and proceed: * "struct file" needs to be available at the right moment. * * Therefore, first process to enter this function does ->release() and * signals its completion to the other process which does nothing. */ |
05c0ae21c try a saner locki... |
141 |
if (pdeo->closing) { |
ca469f35a deal with races b... |
142 |
/* somebody else is doing that, just wait */ |
05c0ae21c try a saner locki... |
143 144 |
DECLARE_COMPLETION_ONSTACK(c); pdeo->c = &c; |
ca469f35a deal with races b... |
145 |
spin_unlock(&pde->pde_unload_lock); |
05c0ae21c try a saner locki... |
146 |
wait_for_completion(&c); |
ca469f35a deal with races b... |
147 148 |
} else { struct file *file; |
2f8974243 proc: do less stu... |
149 |
struct completion *c; |
f5887c71c proc: fix type of... |
150 |
pdeo->closing = true; |
ca469f35a deal with races b... |
151 152 |
spin_unlock(&pde->pde_unload_lock); file = pdeo->file; |
d56c0d45f proc: decouple pr... |
153 |
pde->proc_ops->proc_release(file_inode(file), file); |
ca469f35a deal with races b... |
154 |
spin_lock(&pde->pde_unload_lock); |
492b2da60 proc: tweak comme... |
155 |
/* After ->release. */ |
06a0c4175 proc: just list_d... |
156 |
list_del(&pdeo->lh); |
2f8974243 proc: do less stu... |
157 158 159 160 |
c = pdeo->c; spin_unlock(&pde->pde_unload_lock); if (unlikely(c)) complete(c); |
195b8cf06 proc: move "struc... |
161 |
kmem_cache_free(pde_opener_cache, pdeo); |
05c0ae21c try a saner locki... |
162 |
} |
ca469f35a deal with races b... |
163 |
} |
866ad9a74 procfs: preparati... |
164 |
void proc_entry_rundown(struct proc_dir_entry *de) |
786d7e161 Fix rmmod/read/wr... |
165 |
{ |
05c0ae21c try a saner locki... |
166 |
DECLARE_COMPLETION_ONSTACK(c); |
866ad9a74 procfs: preparati... |
167 |
/* Wait until all existing callers into module are done. */ |
05c0ae21c try a saner locki... |
168 169 170 |
de->pde_unload_completion = &c; if (atomic_add_return(BIAS, &de->in_use) != BIAS) wait_for_completion(&c); |
786d7e161 Fix rmmod/read/wr... |
171 |
|
492b2da60 proc: tweak comme... |
172 |
/* ->pde_openers list can't grow from now on. */ |
05c0ae21c try a saner locki... |
173 |
spin_lock(&de->pde_unload_lock); |
866ad9a74 procfs: preparati... |
174 175 |
while (!list_empty(&de->pde_openers)) { struct pde_opener *pdeo; |
866ad9a74 procfs: preparati... |
176 |
pdeo = list_first_entry(&de->pde_openers, struct pde_opener, lh); |
ca469f35a deal with races b... |
177 |
close_pdeo(de, pdeo); |
2f8974243 proc: do less stu... |
178 |
spin_lock(&de->pde_unload_lock); |
866ad9a74 procfs: preparati... |
179 180 |
} spin_unlock(&de->pde_unload_lock); |
786d7e161 Fix rmmod/read/wr... |
181 |
} |
866ad9a74 procfs: preparati... |
182 183 184 185 186 |
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)) { |
d56c0d45f proc: decouple pr... |
187 |
typeof_member(struct proc_ops, proc_lseek) lseek; |
9af27b28b fs/proc/inode.c: ... |
188 |
|
d56c0d45f proc: decouple pr... |
189 190 191 192 |
lseek = pde->proc_ops->proc_lseek; if (!lseek) lseek = default_llseek; rv = lseek(file, offset, whence); |
866ad9a74 procfs: preparati... |
193 194 |
unuse_pde(pde); } |
786d7e161 Fix rmmod/read/wr... |
195 196 |
return rv; } |
866ad9a74 procfs: preparati... |
197 |
static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) |
786d7e161 Fix rmmod/read/wr... |
198 |
{ |
496ad9aa8 new helper: file_... |
199 |
struct proc_dir_entry *pde = PDE(file_inode(file)); |
786d7e161 Fix rmmod/read/wr... |
200 |
ssize_t rv = -EIO; |
866ad9a74 procfs: preparati... |
201 |
if (use_pde(pde)) { |
d56c0d45f proc: decouple pr... |
202 |
typeof_member(struct proc_ops, proc_read) read; |
9af27b28b fs/proc/inode.c: ... |
203 |
|
d56c0d45f proc: decouple pr... |
204 |
read = pde->proc_ops->proc_read; |
866ad9a74 procfs: preparati... |
205 206 207 |
if (read) rv = read(file, buf, count, ppos); unuse_pde(pde); |
786d7e161 Fix rmmod/read/wr... |
208 |
} |
866ad9a74 procfs: preparati... |
209 210 |
return rv; } |
786d7e161 Fix rmmod/read/wr... |
211 |
|
866ad9a74 procfs: preparati... |
212 213 |
static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { |
866ad9a74 procfs: preparati... |
214 215 216 |
struct proc_dir_entry *pde = PDE(file_inode(file)); ssize_t rv = -EIO; if (use_pde(pde)) { |
d56c0d45f proc: decouple pr... |
217 |
typeof_member(struct proc_ops, proc_write) write; |
9af27b28b fs/proc/inode.c: ... |
218 |
|
d56c0d45f proc: decouple pr... |
219 |
write = pde->proc_ops->proc_write; |
866ad9a74 procfs: preparati... |
220 221 222 223 |
if (write) rv = write(file, buf, count, ppos); unuse_pde(pde); } |
786d7e161 Fix rmmod/read/wr... |
224 225 |
return rv; } |
076ccb76e fs: annotate ->po... |
226 |
static __poll_t proc_reg_poll(struct file *file, struct poll_table_struct *pts) |
786d7e161 Fix rmmod/read/wr... |
227 |
{ |
496ad9aa8 new helper: file_... |
228 |
struct proc_dir_entry *pde = PDE(file_inode(file)); |
e6c8adca2 anntotate the pla... |
229 |
__poll_t rv = DEFAULT_POLLMASK; |
866ad9a74 procfs: preparati... |
230 |
if (use_pde(pde)) { |
d56c0d45f proc: decouple pr... |
231 |
typeof_member(struct proc_ops, proc_poll) poll; |
9af27b28b fs/proc/inode.c: ... |
232 |
|
d56c0d45f proc: decouple pr... |
233 |
poll = pde->proc_ops->proc_poll; |
866ad9a74 procfs: preparati... |
234 235 236 |
if (poll) rv = poll(file, pts); unuse_pde(pde); |
786d7e161 Fix rmmod/read/wr... |
237 |
} |
786d7e161 Fix rmmod/read/wr... |
238 239 240 241 242 |
return rv; } static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { |
496ad9aa8 new helper: file_... |
243 |
struct proc_dir_entry *pde = PDE(file_inode(file)); |
786d7e161 Fix rmmod/read/wr... |
244 |
long rv = -ENOTTY; |
866ad9a74 procfs: preparati... |
245 |
if (use_pde(pde)) { |
d56c0d45f proc: decouple pr... |
246 |
typeof_member(struct proc_ops, proc_ioctl) ioctl; |
9af27b28b fs/proc/inode.c: ... |
247 |
|
d56c0d45f proc: decouple pr... |
248 |
ioctl = pde->proc_ops->proc_ioctl; |
866ad9a74 procfs: preparati... |
249 250 251 |
if (ioctl) rv = ioctl(file, cmd, arg); unuse_pde(pde); |
786d7e161 Fix rmmod/read/wr... |
252 |
} |
786d7e161 Fix rmmod/read/wr... |
253 254 255 256 257 258 |
return rv; } #ifdef CONFIG_COMPAT static long proc_reg_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { |
496ad9aa8 new helper: file_... |
259 |
struct proc_dir_entry *pde = PDE(file_inode(file)); |
786d7e161 Fix rmmod/read/wr... |
260 |
long rv = -ENOTTY; |
866ad9a74 procfs: preparati... |
261 |
if (use_pde(pde)) { |
d56c0d45f proc: decouple pr... |
262 |
typeof_member(struct proc_ops, proc_compat_ioctl) compat_ioctl; |
9af27b28b fs/proc/inode.c: ... |
263 |
|
d56c0d45f proc: decouple pr... |
264 |
compat_ioctl = pde->proc_ops->proc_compat_ioctl; |
866ad9a74 procfs: preparati... |
265 266 267 |
if (compat_ioctl) rv = compat_ioctl(file, cmd, arg); unuse_pde(pde); |
786d7e161 Fix rmmod/read/wr... |
268 |
} |
786d7e161 Fix rmmod/read/wr... |
269 270 271 272 273 274 |
return rv; } #endif static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma) { |
496ad9aa8 new helper: file_... |
275 |
struct proc_dir_entry *pde = PDE(file_inode(file)); |
786d7e161 Fix rmmod/read/wr... |
276 |
int rv = -EIO; |
866ad9a74 procfs: preparati... |
277 |
if (use_pde(pde)) { |
d56c0d45f proc: decouple pr... |
278 |
typeof_member(struct proc_ops, proc_mmap) mmap; |
9af27b28b fs/proc/inode.c: ... |
279 |
|
d56c0d45f proc: decouple pr... |
280 |
mmap = pde->proc_ops->proc_mmap; |
866ad9a74 procfs: preparati... |
281 282 283 |
if (mmap) rv = mmap(file, vma); unuse_pde(pde); |
786d7e161 Fix rmmod/read/wr... |
284 |
} |
786d7e161 Fix rmmod/read/wr... |
285 286 |
return rv; } |
5721cf84d procfs: clean up ... |
287 288 289 290 |
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 sparc: fix PCI de... |
291 292 |
{ struct proc_dir_entry *pde = PDE(file_inode(file)); |
2cbe3b0af procfs: fix unint... |
293 |
unsigned long rv = -EIO; |
ae5758a1a procfs: also fix ... |
294 |
|
c4fe24485 sparc: fix PCI de... |
295 |
if (use_pde(pde)) { |
d56c0d45f proc: decouple pr... |
296 |
typeof_member(struct proc_ops, proc_get_unmapped_area) get_area; |
ae5758a1a procfs: also fix ... |
297 |
|
d56c0d45f proc: decouple pr... |
298 |
get_area = pde->proc_ops->proc_get_unmapped_area; |
fad1a86e2 procfs: call defa... |
299 |
#ifdef CONFIG_MMU |
ae5758a1a procfs: also fix ... |
300 301 |
if (!get_area) get_area = current->mm->get_unmapped_area; |
fad1a86e2 procfs: call defa... |
302 |
#endif |
ae5758a1a procfs: also fix ... |
303 |
|
5721cf84d procfs: clean up ... |
304 305 |
if (get_area) rv = get_area(file, orig_addr, len, pgoff, flags); |
ae5758a1a procfs: also fix ... |
306 307 |
else rv = orig_addr; |
c4fe24485 sparc: fix PCI de... |
308 309 310 311 |
unuse_pde(pde); } return rv; } |
786d7e161 Fix rmmod/read/wr... |
312 313 314 315 |
static int proc_reg_open(struct inode *inode, struct file *file) { struct proc_dir_entry *pde = PDE(inode); int rv = 0; |
d56c0d45f proc: decouple pr... |
316 317 |
typeof_member(struct proc_ops, proc_open) open; typeof_member(struct proc_ops, proc_release) release; |
881adb853 proc: always do -... |
318 319 320 |
struct pde_opener *pdeo; /* |
492b2da60 proc: tweak comme... |
321 322 323 324 325 326 327 |
* Ensure that * 1) PDE's ->release hook will be called no matter what * either normally by close()/->release, or forcefully by * rmmod/remove_proc_entry. * * 2) rmmod isn't blocked by opening file in /proc and sitting on * the descriptor (including "rmmod foo </proc/foo" scenario). |
881adb853 proc: always do -... |
328 |
* |
492b2da60 proc: tweak comme... |
329 |
* Save every "struct file" with custom ->release hook. |
881adb853 proc: always do -... |
330 |
*/ |
e7a6e291e proc: faster open... |
331 |
if (!use_pde(pde)) |
d2857e79a procfs: return EN... |
332 |
return -ENOENT; |
e7a6e291e proc: faster open... |
333 |
|
d56c0d45f proc: decouple pr... |
334 |
release = pde->proc_ops->proc_release; |
e7a6e291e proc: faster open... |
335 |
if (release) { |
195b8cf06 proc: move "struc... |
336 |
pdeo = kmem_cache_alloc(pde_opener_cache, GFP_KERNEL); |
e7a6e291e proc: faster open... |
337 338 339 340 341 |
if (!pdeo) { rv = -ENOMEM; goto out_unuse; } } |
786d7e161 Fix rmmod/read/wr... |
342 |
|
d56c0d45f proc: decouple pr... |
343 |
open = pde->proc_ops->proc_open; |
786d7e161 Fix rmmod/read/wr... |
344 345 |
if (open) rv = open(inode, file); |
e7a6e291e proc: faster open... |
346 347 348 349 350 351 352 353 354 355 |
if (release) { if (rv == 0) { /* To know what to release. */ pdeo->file = file; pdeo->closing = false; pdeo->c = NULL; spin_lock(&pde->pde_unload_lock); list_add(&pdeo->lh, &pde->pde_openers); spin_unlock(&pde->pde_unload_lock); } else |
195b8cf06 proc: move "struc... |
356 |
kmem_cache_free(pde_opener_cache, pdeo); |
e7a6e291e proc: faster open... |
357 |
} |
05c0ae21c try a saner locki... |
358 |
|
e7a6e291e proc: faster open... |
359 |
out_unuse: |
05c0ae21c try a saner locki... |
360 |
unuse_pde(pde); |
786d7e161 Fix rmmod/read/wr... |
361 362 363 364 365 366 |
return rv; } static int proc_reg_release(struct inode *inode, struct file *file) { struct proc_dir_entry *pde = PDE(inode); |
881adb853 proc: always do -... |
367 |
struct pde_opener *pdeo; |
786d7e161 Fix rmmod/read/wr... |
368 |
spin_lock(&pde->pde_unload_lock); |
ca469f35a deal with races b... |
369 370 371 |
list_for_each_entry(pdeo, &pde->pde_openers, lh) { if (pdeo->file == file) { close_pdeo(pde, pdeo); |
2f8974243 proc: do less stu... |
372 |
return 0; |
ca469f35a deal with races b... |
373 |
} |
881adb853 proc: always do -... |
374 |
} |
786d7e161 Fix rmmod/read/wr... |
375 |
spin_unlock(&pde->pde_unload_lock); |
ca469f35a deal with races b... |
376 |
return 0; |
786d7e161 Fix rmmod/read/wr... |
377 378 379 380 381 382 383 384 385 386 387 388 |
} 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 sparc: fix PCI de... |
389 |
.get_unmapped_area = proc_reg_get_unmapped_area, |
786d7e161 Fix rmmod/read/wr... |
390 391 392 |
.open = proc_reg_open, .release = proc_reg_release, }; |
778f3dd5a Fix procfs compat... |
393 394 395 396 397 398 399 400 |
#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 sparc: fix PCI de... |
401 |
.get_unmapped_area = proc_reg_get_unmapped_area, |
778f3dd5a Fix procfs compat... |
402 403 404 405 |
.open = proc_reg_open, .release = proc_reg_release, }; #endif |
fceef393a switch ->get_link... |
406 407 408 409 |
static void proc_put_link(void *p) { unuse_pde(p); } |
6b2553918 replace ->follow_... |
410 |
static const char *proc_get_link(struct dentry *dentry, |
fceef393a switch ->get_link... |
411 412 |
struct inode *inode, struct delayed_call *done) |
7e0e953bb procfs: fix race ... |
413 |
{ |
6b2553918 replace ->follow_... |
414 |
struct proc_dir_entry *pde = PDE(inode); |
15b158b4e proc: spread like... |
415 |
if (!use_pde(pde)) |
7e0e953bb procfs: fix race ... |
416 |
return ERR_PTR(-EINVAL); |
fceef393a switch ->get_link... |
417 |
set_delayed_call(done, proc_put_link, pde); |
680baacbc new ->follow_link... |
418 |
return pde->data; |
7e0e953bb procfs: fix race ... |
419 |
} |
7e0e953bb procfs: fix race ... |
420 |
const struct inode_operations proc_link_inode_operations = { |
6b2553918 replace ->follow_... |
421 |
.get_link = proc_get_link, |
7e0e953bb procfs: fix race ... |
422 |
}; |
6d1b6e4ef proc: ->low_ino c... |
423 |
struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) |
1da177e4c Linux-2.6.12-rc2 |
424 |
{ |
51f0885e5 vfs,proc: guarant... |
425 |
struct inode *inode = new_inode_pseudo(sb); |
1da177e4c Linux-2.6.12-rc2 |
426 |
|
51f0885e5 vfs,proc: guarant... |
427 428 |
if (inode) { inode->i_ino = de->low_ino; |
078cd8279 fs: Replace CURRE... |
429 |
inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); |
a1d4aebbf iget: stop PROCFS... |
430 |
PROC_I(inode)->pde = de; |
5e971dce0 proc: drop severa... |
431 |
|
eb6d38d54 proc: Allow creat... |
432 433 434 435 |
if (is_empty_pde(de)) { make_empty_dir_inode(inode); return inode; } |
5e971dce0 proc: drop severa... |
436 437 438 439 440 441 442 443 |
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 filesystems: add ... |
444 |
set_nlink(inode, de->nlink); |
d56c0d45f proc: decouple pr... |
445 446 447 448 |
if (S_ISREG(inode->i_mode)) { inode->i_op = de->proc_iops; inode->i_fop = &proc_reg_file_ops; |
778f3dd5a Fix procfs compat... |
449 |
#ifdef CONFIG_COMPAT |
d56c0d45f proc: decouple pr... |
450 451 |
if (!de->proc_ops->proc_compat_ioctl) { inode->i_fop = &proc_reg_file_ops_no_compat; |
778f3dd5a Fix procfs compat... |
452 |
} |
d56c0d45f proc: decouple pr... |
453 454 455 456 457 458 459 460 461 |
#endif } else if (S_ISDIR(inode->i_mode)) { inode->i_op = de->proc_iops; inode->i_fop = de->proc_dir_ops; } else if (S_ISLNK(inode->i_mode)) { inode->i_op = de->proc_iops; inode->i_fop = NULL; } else BUG(); |
99b762338 proc 2/2: remove ... |
462 |
} else |
135d5655d proc: rename de_g... |
463 |
pde_put(de); |
1da177e4c Linux-2.6.12-rc2 |
464 |
return inode; |
d3d009cb9 saner proc_get_in... |
465 |
} |