1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * proc/fs/generic.c --- generic routines for the proc-fs
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * This file contains generic proc-fs routines for handling
6*4882a593Smuzhiyun * directories and files.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Copyright (C) 1991, 1992 Linus Torvalds.
9*4882a593Smuzhiyun * Copyright (C) 1997 Theodore Ts'o
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/cache.h>
13*4882a593Smuzhiyun #include <linux/errno.h>
14*4882a593Smuzhiyun #include <linux/time.h>
15*4882a593Smuzhiyun #include <linux/proc_fs.h>
16*4882a593Smuzhiyun #include <linux/stat.h>
17*4882a593Smuzhiyun #include <linux/mm.h>
18*4882a593Smuzhiyun #include <linux/module.h>
19*4882a593Smuzhiyun #include <linux/namei.h>
20*4882a593Smuzhiyun #include <linux/slab.h>
21*4882a593Smuzhiyun #include <linux/printk.h>
22*4882a593Smuzhiyun #include <linux/mount.h>
23*4882a593Smuzhiyun #include <linux/init.h>
24*4882a593Smuzhiyun #include <linux/idr.h>
25*4882a593Smuzhiyun #include <linux/bitops.h>
26*4882a593Smuzhiyun #include <linux/spinlock.h>
27*4882a593Smuzhiyun #include <linux/completion.h>
28*4882a593Smuzhiyun #include <linux/uaccess.h>
29*4882a593Smuzhiyun #include <linux/seq_file.h>
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #include "internal.h"
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun static DEFINE_RWLOCK(proc_subdir_lock);
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun struct kmem_cache *proc_dir_entry_cache __ro_after_init;
36*4882a593Smuzhiyun
pde_free(struct proc_dir_entry * pde)37*4882a593Smuzhiyun void pde_free(struct proc_dir_entry *pde)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun if (S_ISLNK(pde->mode))
40*4882a593Smuzhiyun kfree(pde->data);
41*4882a593Smuzhiyun if (pde->name != pde->inline_name)
42*4882a593Smuzhiyun kfree(pde->name);
43*4882a593Smuzhiyun kmem_cache_free(proc_dir_entry_cache, pde);
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun
proc_match(const char * name,struct proc_dir_entry * de,unsigned int len)46*4882a593Smuzhiyun static int proc_match(const char *name, struct proc_dir_entry *de, unsigned int len)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun if (len < de->namelen)
49*4882a593Smuzhiyun return -1;
50*4882a593Smuzhiyun if (len > de->namelen)
51*4882a593Smuzhiyun return 1;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun return memcmp(name, de->name, len);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
pde_subdir_first(struct proc_dir_entry * dir)56*4882a593Smuzhiyun static struct proc_dir_entry *pde_subdir_first(struct proc_dir_entry *dir)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun return rb_entry_safe(rb_first(&dir->subdir), struct proc_dir_entry,
59*4882a593Smuzhiyun subdir_node);
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
pde_subdir_next(struct proc_dir_entry * dir)62*4882a593Smuzhiyun static struct proc_dir_entry *pde_subdir_next(struct proc_dir_entry *dir)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun return rb_entry_safe(rb_next(&dir->subdir_node), struct proc_dir_entry,
65*4882a593Smuzhiyun subdir_node);
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
pde_subdir_find(struct proc_dir_entry * dir,const char * name,unsigned int len)68*4882a593Smuzhiyun static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir,
69*4882a593Smuzhiyun const char *name,
70*4882a593Smuzhiyun unsigned int len)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun struct rb_node *node = dir->subdir.rb_node;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun while (node) {
75*4882a593Smuzhiyun struct proc_dir_entry *de = rb_entry(node,
76*4882a593Smuzhiyun struct proc_dir_entry,
77*4882a593Smuzhiyun subdir_node);
78*4882a593Smuzhiyun int result = proc_match(name, de, len);
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun if (result < 0)
81*4882a593Smuzhiyun node = node->rb_left;
82*4882a593Smuzhiyun else if (result > 0)
83*4882a593Smuzhiyun node = node->rb_right;
84*4882a593Smuzhiyun else
85*4882a593Smuzhiyun return de;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun return NULL;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
pde_subdir_insert(struct proc_dir_entry * dir,struct proc_dir_entry * de)90*4882a593Smuzhiyun static bool pde_subdir_insert(struct proc_dir_entry *dir,
91*4882a593Smuzhiyun struct proc_dir_entry *de)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun struct rb_root *root = &dir->subdir;
94*4882a593Smuzhiyun struct rb_node **new = &root->rb_node, *parent = NULL;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun /* Figure out where to put new node */
97*4882a593Smuzhiyun while (*new) {
98*4882a593Smuzhiyun struct proc_dir_entry *this = rb_entry(*new,
99*4882a593Smuzhiyun struct proc_dir_entry,
100*4882a593Smuzhiyun subdir_node);
101*4882a593Smuzhiyun int result = proc_match(de->name, this, de->namelen);
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun parent = *new;
104*4882a593Smuzhiyun if (result < 0)
105*4882a593Smuzhiyun new = &(*new)->rb_left;
106*4882a593Smuzhiyun else if (result > 0)
107*4882a593Smuzhiyun new = &(*new)->rb_right;
108*4882a593Smuzhiyun else
109*4882a593Smuzhiyun return false;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun /* Add new node and rebalance tree. */
113*4882a593Smuzhiyun rb_link_node(&de->subdir_node, parent, new);
114*4882a593Smuzhiyun rb_insert_color(&de->subdir_node, root);
115*4882a593Smuzhiyun return true;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun
proc_notify_change(struct dentry * dentry,struct iattr * iattr)118*4882a593Smuzhiyun static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun struct inode *inode = d_inode(dentry);
121*4882a593Smuzhiyun struct proc_dir_entry *de = PDE(inode);
122*4882a593Smuzhiyun int error;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun error = setattr_prepare(dentry, iattr);
125*4882a593Smuzhiyun if (error)
126*4882a593Smuzhiyun return error;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun setattr_copy(inode, iattr);
129*4882a593Smuzhiyun mark_inode_dirty(inode);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun proc_set_user(de, inode->i_uid, inode->i_gid);
132*4882a593Smuzhiyun de->mode = inode->i_mode;
133*4882a593Smuzhiyun return 0;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
proc_getattr(const struct path * path,struct kstat * stat,u32 request_mask,unsigned int query_flags)136*4882a593Smuzhiyun static int proc_getattr(const struct path *path, struct kstat *stat,
137*4882a593Smuzhiyun u32 request_mask, unsigned int query_flags)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun struct inode *inode = d_inode(path->dentry);
140*4882a593Smuzhiyun struct proc_dir_entry *de = PDE(inode);
141*4882a593Smuzhiyun if (de) {
142*4882a593Smuzhiyun nlink_t nlink = READ_ONCE(de->nlink);
143*4882a593Smuzhiyun if (nlink > 0) {
144*4882a593Smuzhiyun set_nlink(inode, nlink);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun generic_fillattr(inode, stat);
149*4882a593Smuzhiyun return 0;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun static const struct inode_operations proc_file_inode_operations = {
153*4882a593Smuzhiyun .setattr = proc_notify_change,
154*4882a593Smuzhiyun };
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun /*
157*4882a593Smuzhiyun * This function parses a name such as "tty/driver/serial", and
158*4882a593Smuzhiyun * returns the struct proc_dir_entry for "/proc/tty/driver", and
159*4882a593Smuzhiyun * returns "serial" in residual.
160*4882a593Smuzhiyun */
__xlate_proc_name(const char * name,struct proc_dir_entry ** ret,const char ** residual)161*4882a593Smuzhiyun static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret,
162*4882a593Smuzhiyun const char **residual)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun const char *cp = name, *next;
165*4882a593Smuzhiyun struct proc_dir_entry *de;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun de = *ret;
168*4882a593Smuzhiyun if (!de)
169*4882a593Smuzhiyun de = &proc_root;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun while (1) {
172*4882a593Smuzhiyun next = strchr(cp, '/');
173*4882a593Smuzhiyun if (!next)
174*4882a593Smuzhiyun break;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun de = pde_subdir_find(de, cp, next - cp);
177*4882a593Smuzhiyun if (!de) {
178*4882a593Smuzhiyun WARN(1, "name '%s'\n", name);
179*4882a593Smuzhiyun return -ENOENT;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun cp = next + 1;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun *residual = cp;
184*4882a593Smuzhiyun *ret = de;
185*4882a593Smuzhiyun return 0;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
xlate_proc_name(const char * name,struct proc_dir_entry ** ret,const char ** residual)188*4882a593Smuzhiyun static int xlate_proc_name(const char *name, struct proc_dir_entry **ret,
189*4882a593Smuzhiyun const char **residual)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun int rv;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun read_lock(&proc_subdir_lock);
194*4882a593Smuzhiyun rv = __xlate_proc_name(name, ret, residual);
195*4882a593Smuzhiyun read_unlock(&proc_subdir_lock);
196*4882a593Smuzhiyun return rv;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun static DEFINE_IDA(proc_inum_ida);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun #define PROC_DYNAMIC_FIRST 0xF0000000U
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun /*
204*4882a593Smuzhiyun * Return an inode number between PROC_DYNAMIC_FIRST and
205*4882a593Smuzhiyun * 0xffffffff, or zero on failure.
206*4882a593Smuzhiyun */
proc_alloc_inum(unsigned int * inum)207*4882a593Smuzhiyun int proc_alloc_inum(unsigned int *inum)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun int i;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun i = ida_simple_get(&proc_inum_ida, 0, UINT_MAX - PROC_DYNAMIC_FIRST + 1,
212*4882a593Smuzhiyun GFP_KERNEL);
213*4882a593Smuzhiyun if (i < 0)
214*4882a593Smuzhiyun return i;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun *inum = PROC_DYNAMIC_FIRST + (unsigned int)i;
217*4882a593Smuzhiyun return 0;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
proc_free_inum(unsigned int inum)220*4882a593Smuzhiyun void proc_free_inum(unsigned int inum)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun ida_simple_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
proc_misc_d_revalidate(struct dentry * dentry,unsigned int flags)225*4882a593Smuzhiyun static int proc_misc_d_revalidate(struct dentry *dentry, unsigned int flags)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun if (flags & LOOKUP_RCU)
228*4882a593Smuzhiyun return -ECHILD;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun if (atomic_read(&PDE(d_inode(dentry))->in_use) < 0)
231*4882a593Smuzhiyun return 0; /* revalidate */
232*4882a593Smuzhiyun return 1;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
proc_misc_d_delete(const struct dentry * dentry)235*4882a593Smuzhiyun static int proc_misc_d_delete(const struct dentry *dentry)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun return atomic_read(&PDE(d_inode(dentry))->in_use) < 0;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun static const struct dentry_operations proc_misc_dentry_ops = {
241*4882a593Smuzhiyun .d_revalidate = proc_misc_d_revalidate,
242*4882a593Smuzhiyun .d_delete = proc_misc_d_delete,
243*4882a593Smuzhiyun };
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun /*
246*4882a593Smuzhiyun * Don't create negative dentries here, return -ENOENT by hand
247*4882a593Smuzhiyun * instead.
248*4882a593Smuzhiyun */
proc_lookup_de(struct inode * dir,struct dentry * dentry,struct proc_dir_entry * de)249*4882a593Smuzhiyun struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
250*4882a593Smuzhiyun struct proc_dir_entry *de)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun struct inode *inode;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun read_lock(&proc_subdir_lock);
255*4882a593Smuzhiyun de = pde_subdir_find(de, dentry->d_name.name, dentry->d_name.len);
256*4882a593Smuzhiyun if (de) {
257*4882a593Smuzhiyun pde_get(de);
258*4882a593Smuzhiyun read_unlock(&proc_subdir_lock);
259*4882a593Smuzhiyun inode = proc_get_inode(dir->i_sb, de);
260*4882a593Smuzhiyun if (!inode)
261*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
262*4882a593Smuzhiyun d_set_d_op(dentry, de->proc_dops);
263*4882a593Smuzhiyun return d_splice_alias(inode, dentry);
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun read_unlock(&proc_subdir_lock);
266*4882a593Smuzhiyun return ERR_PTR(-ENOENT);
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
proc_lookup(struct inode * dir,struct dentry * dentry,unsigned int flags)269*4882a593Smuzhiyun struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
270*4882a593Smuzhiyun unsigned int flags)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun struct proc_fs_info *fs_info = proc_sb_info(dir->i_sb);
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun if (fs_info->pidonly == PROC_PIDONLY_ON)
275*4882a593Smuzhiyun return ERR_PTR(-ENOENT);
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun return proc_lookup_de(dir, dentry, PDE(dir));
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun /*
281*4882a593Smuzhiyun * This returns non-zero if at EOF, so that the /proc
282*4882a593Smuzhiyun * root directory can use this and check if it should
283*4882a593Smuzhiyun * continue with the <pid> entries..
284*4882a593Smuzhiyun *
285*4882a593Smuzhiyun * Note that the VFS-layer doesn't care about the return
286*4882a593Smuzhiyun * value of the readdir() call, as long as it's non-negative
287*4882a593Smuzhiyun * for success..
288*4882a593Smuzhiyun */
proc_readdir_de(struct file * file,struct dir_context * ctx,struct proc_dir_entry * de)289*4882a593Smuzhiyun int proc_readdir_de(struct file *file, struct dir_context *ctx,
290*4882a593Smuzhiyun struct proc_dir_entry *de)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun int i;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun if (!dir_emit_dots(file, ctx))
295*4882a593Smuzhiyun return 0;
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun i = ctx->pos - 2;
298*4882a593Smuzhiyun read_lock(&proc_subdir_lock);
299*4882a593Smuzhiyun de = pde_subdir_first(de);
300*4882a593Smuzhiyun for (;;) {
301*4882a593Smuzhiyun if (!de) {
302*4882a593Smuzhiyun read_unlock(&proc_subdir_lock);
303*4882a593Smuzhiyun return 0;
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun if (!i)
306*4882a593Smuzhiyun break;
307*4882a593Smuzhiyun de = pde_subdir_next(de);
308*4882a593Smuzhiyun i--;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun do {
312*4882a593Smuzhiyun struct proc_dir_entry *next;
313*4882a593Smuzhiyun pde_get(de);
314*4882a593Smuzhiyun read_unlock(&proc_subdir_lock);
315*4882a593Smuzhiyun if (!dir_emit(ctx, de->name, de->namelen,
316*4882a593Smuzhiyun de->low_ino, de->mode >> 12)) {
317*4882a593Smuzhiyun pde_put(de);
318*4882a593Smuzhiyun return 0;
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun ctx->pos++;
321*4882a593Smuzhiyun read_lock(&proc_subdir_lock);
322*4882a593Smuzhiyun next = pde_subdir_next(de);
323*4882a593Smuzhiyun pde_put(de);
324*4882a593Smuzhiyun de = next;
325*4882a593Smuzhiyun } while (de);
326*4882a593Smuzhiyun read_unlock(&proc_subdir_lock);
327*4882a593Smuzhiyun return 1;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
proc_readdir(struct file * file,struct dir_context * ctx)330*4882a593Smuzhiyun int proc_readdir(struct file *file, struct dir_context *ctx)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun struct inode *inode = file_inode(file);
333*4882a593Smuzhiyun struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb);
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun if (fs_info->pidonly == PROC_PIDONLY_ON)
336*4882a593Smuzhiyun return 1;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun return proc_readdir_de(file, ctx, PDE(inode));
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun /*
342*4882a593Smuzhiyun * These are the generic /proc directory operations. They
343*4882a593Smuzhiyun * use the in-memory "struct proc_dir_entry" tree to parse
344*4882a593Smuzhiyun * the /proc directory.
345*4882a593Smuzhiyun */
346*4882a593Smuzhiyun static const struct file_operations proc_dir_operations = {
347*4882a593Smuzhiyun .llseek = generic_file_llseek,
348*4882a593Smuzhiyun .read = generic_read_dir,
349*4882a593Smuzhiyun .iterate_shared = proc_readdir,
350*4882a593Smuzhiyun };
351*4882a593Smuzhiyun
proc_net_d_revalidate(struct dentry * dentry,unsigned int flags)352*4882a593Smuzhiyun static int proc_net_d_revalidate(struct dentry *dentry, unsigned int flags)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun return 0;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun const struct dentry_operations proc_net_dentry_ops = {
358*4882a593Smuzhiyun .d_revalidate = proc_net_d_revalidate,
359*4882a593Smuzhiyun .d_delete = always_delete_dentry,
360*4882a593Smuzhiyun };
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun /*
363*4882a593Smuzhiyun * proc directories can do almost nothing..
364*4882a593Smuzhiyun */
365*4882a593Smuzhiyun static const struct inode_operations proc_dir_inode_operations = {
366*4882a593Smuzhiyun .lookup = proc_lookup,
367*4882a593Smuzhiyun .getattr = proc_getattr,
368*4882a593Smuzhiyun .setattr = proc_notify_change,
369*4882a593Smuzhiyun };
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun /* returns the registered entry, or frees dp and returns NULL on failure */
proc_register(struct proc_dir_entry * dir,struct proc_dir_entry * dp)372*4882a593Smuzhiyun struct proc_dir_entry *proc_register(struct proc_dir_entry *dir,
373*4882a593Smuzhiyun struct proc_dir_entry *dp)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun if (proc_alloc_inum(&dp->low_ino))
376*4882a593Smuzhiyun goto out_free_entry;
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun write_lock(&proc_subdir_lock);
379*4882a593Smuzhiyun dp->parent = dir;
380*4882a593Smuzhiyun if (pde_subdir_insert(dir, dp) == false) {
381*4882a593Smuzhiyun WARN(1, "proc_dir_entry '%s/%s' already registered\n",
382*4882a593Smuzhiyun dir->name, dp->name);
383*4882a593Smuzhiyun write_unlock(&proc_subdir_lock);
384*4882a593Smuzhiyun goto out_free_inum;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun dir->nlink++;
387*4882a593Smuzhiyun write_unlock(&proc_subdir_lock);
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun return dp;
390*4882a593Smuzhiyun out_free_inum:
391*4882a593Smuzhiyun proc_free_inum(dp->low_ino);
392*4882a593Smuzhiyun out_free_entry:
393*4882a593Smuzhiyun pde_free(dp);
394*4882a593Smuzhiyun return NULL;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
__proc_create(struct proc_dir_entry ** parent,const char * name,umode_t mode,nlink_t nlink)397*4882a593Smuzhiyun static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
398*4882a593Smuzhiyun const char *name,
399*4882a593Smuzhiyun umode_t mode,
400*4882a593Smuzhiyun nlink_t nlink)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun struct proc_dir_entry *ent = NULL;
403*4882a593Smuzhiyun const char *fn;
404*4882a593Smuzhiyun struct qstr qstr;
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun if (xlate_proc_name(name, parent, &fn) != 0)
407*4882a593Smuzhiyun goto out;
408*4882a593Smuzhiyun qstr.name = fn;
409*4882a593Smuzhiyun qstr.len = strlen(fn);
410*4882a593Smuzhiyun if (qstr.len == 0 || qstr.len >= 256) {
411*4882a593Smuzhiyun WARN(1, "name len %u\n", qstr.len);
412*4882a593Smuzhiyun return NULL;
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun if (qstr.len == 1 && fn[0] == '.') {
415*4882a593Smuzhiyun WARN(1, "name '.'\n");
416*4882a593Smuzhiyun return NULL;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun if (qstr.len == 2 && fn[0] == '.' && fn[1] == '.') {
419*4882a593Smuzhiyun WARN(1, "name '..'\n");
420*4882a593Smuzhiyun return NULL;
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun if (*parent == &proc_root && name_to_int(&qstr) != ~0U) {
423*4882a593Smuzhiyun WARN(1, "create '/proc/%s' by hand\n", qstr.name);
424*4882a593Smuzhiyun return NULL;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun if (is_empty_pde(*parent)) {
427*4882a593Smuzhiyun WARN(1, "attempt to add to permanently empty directory");
428*4882a593Smuzhiyun return NULL;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun ent = kmem_cache_zalloc(proc_dir_entry_cache, GFP_KERNEL);
432*4882a593Smuzhiyun if (!ent)
433*4882a593Smuzhiyun goto out;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun if (qstr.len + 1 <= SIZEOF_PDE_INLINE_NAME) {
436*4882a593Smuzhiyun ent->name = ent->inline_name;
437*4882a593Smuzhiyun } else {
438*4882a593Smuzhiyun ent->name = kmalloc(qstr.len + 1, GFP_KERNEL);
439*4882a593Smuzhiyun if (!ent->name) {
440*4882a593Smuzhiyun pde_free(ent);
441*4882a593Smuzhiyun return NULL;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun memcpy(ent->name, fn, qstr.len + 1);
446*4882a593Smuzhiyun ent->namelen = qstr.len;
447*4882a593Smuzhiyun ent->mode = mode;
448*4882a593Smuzhiyun ent->nlink = nlink;
449*4882a593Smuzhiyun ent->subdir = RB_ROOT;
450*4882a593Smuzhiyun refcount_set(&ent->refcnt, 1);
451*4882a593Smuzhiyun spin_lock_init(&ent->pde_unload_lock);
452*4882a593Smuzhiyun INIT_LIST_HEAD(&ent->pde_openers);
453*4882a593Smuzhiyun proc_set_user(ent, (*parent)->uid, (*parent)->gid);
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun ent->proc_dops = &proc_misc_dentry_ops;
456*4882a593Smuzhiyun /* Revalidate everything under /proc/${pid}/net */
457*4882a593Smuzhiyun if ((*parent)->proc_dops == &proc_net_dentry_ops)
458*4882a593Smuzhiyun pde_force_lookup(ent);
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun out:
461*4882a593Smuzhiyun return ent;
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun
proc_symlink(const char * name,struct proc_dir_entry * parent,const char * dest)464*4882a593Smuzhiyun struct proc_dir_entry *proc_symlink(const char *name,
465*4882a593Smuzhiyun struct proc_dir_entry *parent, const char *dest)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun struct proc_dir_entry *ent;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun ent = __proc_create(&parent, name,
470*4882a593Smuzhiyun (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun if (ent) {
473*4882a593Smuzhiyun ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
474*4882a593Smuzhiyun if (ent->data) {
475*4882a593Smuzhiyun strcpy((char*)ent->data,dest);
476*4882a593Smuzhiyun ent->proc_iops = &proc_link_inode_operations;
477*4882a593Smuzhiyun ent = proc_register(parent, ent);
478*4882a593Smuzhiyun } else {
479*4882a593Smuzhiyun pde_free(ent);
480*4882a593Smuzhiyun ent = NULL;
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun return ent;
484*4882a593Smuzhiyun }
485*4882a593Smuzhiyun EXPORT_SYMBOL(proc_symlink);
486*4882a593Smuzhiyun
_proc_mkdir(const char * name,umode_t mode,struct proc_dir_entry * parent,void * data,bool force_lookup)487*4882a593Smuzhiyun struct proc_dir_entry *_proc_mkdir(const char *name, umode_t mode,
488*4882a593Smuzhiyun struct proc_dir_entry *parent, void *data, bool force_lookup)
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun struct proc_dir_entry *ent;
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun if (mode == 0)
493*4882a593Smuzhiyun mode = S_IRUGO | S_IXUGO;
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun ent = __proc_create(&parent, name, S_IFDIR | mode, 2);
496*4882a593Smuzhiyun if (ent) {
497*4882a593Smuzhiyun ent->data = data;
498*4882a593Smuzhiyun ent->proc_dir_ops = &proc_dir_operations;
499*4882a593Smuzhiyun ent->proc_iops = &proc_dir_inode_operations;
500*4882a593Smuzhiyun if (force_lookup) {
501*4882a593Smuzhiyun pde_force_lookup(ent);
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun ent = proc_register(parent, ent);
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun return ent;
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(_proc_mkdir);
508*4882a593Smuzhiyun
proc_mkdir_data(const char * name,umode_t mode,struct proc_dir_entry * parent,void * data)509*4882a593Smuzhiyun struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
510*4882a593Smuzhiyun struct proc_dir_entry *parent, void *data)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun return _proc_mkdir(name, mode, parent, data, false);
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(proc_mkdir_data);
515*4882a593Smuzhiyun
proc_mkdir_mode(const char * name,umode_t mode,struct proc_dir_entry * parent)516*4882a593Smuzhiyun struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
517*4882a593Smuzhiyun struct proc_dir_entry *parent)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun return proc_mkdir_data(name, mode, parent, NULL);
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun EXPORT_SYMBOL(proc_mkdir_mode);
522*4882a593Smuzhiyun
proc_mkdir(const char * name,struct proc_dir_entry * parent)523*4882a593Smuzhiyun struct proc_dir_entry *proc_mkdir(const char *name,
524*4882a593Smuzhiyun struct proc_dir_entry *parent)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun return proc_mkdir_data(name, 0, parent, NULL);
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun EXPORT_SYMBOL(proc_mkdir);
529*4882a593Smuzhiyun
proc_create_mount_point(const char * name)530*4882a593Smuzhiyun struct proc_dir_entry *proc_create_mount_point(const char *name)
531*4882a593Smuzhiyun {
532*4882a593Smuzhiyun umode_t mode = S_IFDIR | S_IRUGO | S_IXUGO;
533*4882a593Smuzhiyun struct proc_dir_entry *ent, *parent = NULL;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun ent = __proc_create(&parent, name, mode, 2);
536*4882a593Smuzhiyun if (ent) {
537*4882a593Smuzhiyun ent->data = NULL;
538*4882a593Smuzhiyun ent->proc_dir_ops = NULL;
539*4882a593Smuzhiyun ent->proc_iops = NULL;
540*4882a593Smuzhiyun ent = proc_register(parent, ent);
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun return ent;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun EXPORT_SYMBOL(proc_create_mount_point);
545*4882a593Smuzhiyun
proc_create_reg(const char * name,umode_t mode,struct proc_dir_entry ** parent,void * data)546*4882a593Smuzhiyun struct proc_dir_entry *proc_create_reg(const char *name, umode_t mode,
547*4882a593Smuzhiyun struct proc_dir_entry **parent, void *data)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun struct proc_dir_entry *p;
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun if ((mode & S_IFMT) == 0)
552*4882a593Smuzhiyun mode |= S_IFREG;
553*4882a593Smuzhiyun if ((mode & S_IALLUGO) == 0)
554*4882a593Smuzhiyun mode |= S_IRUGO;
555*4882a593Smuzhiyun if (WARN_ON_ONCE(!S_ISREG(mode)))
556*4882a593Smuzhiyun return NULL;
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun p = __proc_create(parent, name, mode, 1);
559*4882a593Smuzhiyun if (p) {
560*4882a593Smuzhiyun p->proc_iops = &proc_file_inode_operations;
561*4882a593Smuzhiyun p->data = data;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun return p;
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun
pde_set_flags(struct proc_dir_entry * pde)566*4882a593Smuzhiyun static inline void pde_set_flags(struct proc_dir_entry *pde)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun if (pde->proc_ops->proc_flags & PROC_ENTRY_PERMANENT)
569*4882a593Smuzhiyun pde->flags |= PROC_ENTRY_PERMANENT;
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun
proc_create_data(const char * name,umode_t mode,struct proc_dir_entry * parent,const struct proc_ops * proc_ops,void * data)572*4882a593Smuzhiyun struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
573*4882a593Smuzhiyun struct proc_dir_entry *parent,
574*4882a593Smuzhiyun const struct proc_ops *proc_ops, void *data)
575*4882a593Smuzhiyun {
576*4882a593Smuzhiyun struct proc_dir_entry *p;
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun p = proc_create_reg(name, mode, &parent, data);
579*4882a593Smuzhiyun if (!p)
580*4882a593Smuzhiyun return NULL;
581*4882a593Smuzhiyun p->proc_ops = proc_ops;
582*4882a593Smuzhiyun pde_set_flags(p);
583*4882a593Smuzhiyun return proc_register(parent, p);
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun EXPORT_SYMBOL(proc_create_data);
586*4882a593Smuzhiyun
proc_create(const char * name,umode_t mode,struct proc_dir_entry * parent,const struct proc_ops * proc_ops)587*4882a593Smuzhiyun struct proc_dir_entry *proc_create(const char *name, umode_t mode,
588*4882a593Smuzhiyun struct proc_dir_entry *parent,
589*4882a593Smuzhiyun const struct proc_ops *proc_ops)
590*4882a593Smuzhiyun {
591*4882a593Smuzhiyun return proc_create_data(name, mode, parent, proc_ops, NULL);
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun EXPORT_SYMBOL(proc_create);
594*4882a593Smuzhiyun
proc_seq_open(struct inode * inode,struct file * file)595*4882a593Smuzhiyun static int proc_seq_open(struct inode *inode, struct file *file)
596*4882a593Smuzhiyun {
597*4882a593Smuzhiyun struct proc_dir_entry *de = PDE(inode);
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun if (de->state_size)
600*4882a593Smuzhiyun return seq_open_private(file, de->seq_ops, de->state_size);
601*4882a593Smuzhiyun return seq_open(file, de->seq_ops);
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun
proc_seq_release(struct inode * inode,struct file * file)604*4882a593Smuzhiyun static int proc_seq_release(struct inode *inode, struct file *file)
605*4882a593Smuzhiyun {
606*4882a593Smuzhiyun struct proc_dir_entry *de = PDE(inode);
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun if (de->state_size)
609*4882a593Smuzhiyun return seq_release_private(inode, file);
610*4882a593Smuzhiyun return seq_release(inode, file);
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun static const struct proc_ops proc_seq_ops = {
614*4882a593Smuzhiyun /* not permanent -- can call into arbitrary seq_operations */
615*4882a593Smuzhiyun .proc_open = proc_seq_open,
616*4882a593Smuzhiyun .proc_read_iter = seq_read_iter,
617*4882a593Smuzhiyun .proc_lseek = seq_lseek,
618*4882a593Smuzhiyun .proc_release = proc_seq_release,
619*4882a593Smuzhiyun };
620*4882a593Smuzhiyun
proc_create_seq_private(const char * name,umode_t mode,struct proc_dir_entry * parent,const struct seq_operations * ops,unsigned int state_size,void * data)621*4882a593Smuzhiyun struct proc_dir_entry *proc_create_seq_private(const char *name, umode_t mode,
622*4882a593Smuzhiyun struct proc_dir_entry *parent, const struct seq_operations *ops,
623*4882a593Smuzhiyun unsigned int state_size, void *data)
624*4882a593Smuzhiyun {
625*4882a593Smuzhiyun struct proc_dir_entry *p;
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun p = proc_create_reg(name, mode, &parent, data);
628*4882a593Smuzhiyun if (!p)
629*4882a593Smuzhiyun return NULL;
630*4882a593Smuzhiyun p->proc_ops = &proc_seq_ops;
631*4882a593Smuzhiyun p->seq_ops = ops;
632*4882a593Smuzhiyun p->state_size = state_size;
633*4882a593Smuzhiyun return proc_register(parent, p);
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun EXPORT_SYMBOL(proc_create_seq_private);
636*4882a593Smuzhiyun
proc_single_open(struct inode * inode,struct file * file)637*4882a593Smuzhiyun static int proc_single_open(struct inode *inode, struct file *file)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun struct proc_dir_entry *de = PDE(inode);
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun return single_open(file, de->single_show, de->data);
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun static const struct proc_ops proc_single_ops = {
645*4882a593Smuzhiyun /* not permanent -- can call into arbitrary ->single_show */
646*4882a593Smuzhiyun .proc_open = proc_single_open,
647*4882a593Smuzhiyun .proc_read_iter = seq_read_iter,
648*4882a593Smuzhiyun .proc_lseek = seq_lseek,
649*4882a593Smuzhiyun .proc_release = single_release,
650*4882a593Smuzhiyun };
651*4882a593Smuzhiyun
proc_create_single_data(const char * name,umode_t mode,struct proc_dir_entry * parent,int (* show)(struct seq_file *,void *),void * data)652*4882a593Smuzhiyun struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
653*4882a593Smuzhiyun struct proc_dir_entry *parent,
654*4882a593Smuzhiyun int (*show)(struct seq_file *, void *), void *data)
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun struct proc_dir_entry *p;
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun p = proc_create_reg(name, mode, &parent, data);
659*4882a593Smuzhiyun if (!p)
660*4882a593Smuzhiyun return NULL;
661*4882a593Smuzhiyun p->proc_ops = &proc_single_ops;
662*4882a593Smuzhiyun p->single_show = show;
663*4882a593Smuzhiyun return proc_register(parent, p);
664*4882a593Smuzhiyun }
665*4882a593Smuzhiyun EXPORT_SYMBOL(proc_create_single_data);
666*4882a593Smuzhiyun
proc_set_size(struct proc_dir_entry * de,loff_t size)667*4882a593Smuzhiyun void proc_set_size(struct proc_dir_entry *de, loff_t size)
668*4882a593Smuzhiyun {
669*4882a593Smuzhiyun de->size = size;
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun EXPORT_SYMBOL(proc_set_size);
672*4882a593Smuzhiyun
proc_set_user(struct proc_dir_entry * de,kuid_t uid,kgid_t gid)673*4882a593Smuzhiyun void proc_set_user(struct proc_dir_entry *de, kuid_t uid, kgid_t gid)
674*4882a593Smuzhiyun {
675*4882a593Smuzhiyun de->uid = uid;
676*4882a593Smuzhiyun de->gid = gid;
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun EXPORT_SYMBOL(proc_set_user);
679*4882a593Smuzhiyun
pde_put(struct proc_dir_entry * pde)680*4882a593Smuzhiyun void pde_put(struct proc_dir_entry *pde)
681*4882a593Smuzhiyun {
682*4882a593Smuzhiyun if (refcount_dec_and_test(&pde->refcnt)) {
683*4882a593Smuzhiyun proc_free_inum(pde->low_ino);
684*4882a593Smuzhiyun pde_free(pde);
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun /*
689*4882a593Smuzhiyun * Remove a /proc entry and free it if it's not currently in use.
690*4882a593Smuzhiyun */
remove_proc_entry(const char * name,struct proc_dir_entry * parent)691*4882a593Smuzhiyun void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
692*4882a593Smuzhiyun {
693*4882a593Smuzhiyun struct proc_dir_entry *de = NULL;
694*4882a593Smuzhiyun const char *fn = name;
695*4882a593Smuzhiyun unsigned int len;
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun write_lock(&proc_subdir_lock);
698*4882a593Smuzhiyun if (__xlate_proc_name(name, &parent, &fn) != 0) {
699*4882a593Smuzhiyun write_unlock(&proc_subdir_lock);
700*4882a593Smuzhiyun return;
701*4882a593Smuzhiyun }
702*4882a593Smuzhiyun len = strlen(fn);
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun de = pde_subdir_find(parent, fn, len);
705*4882a593Smuzhiyun if (de) {
706*4882a593Smuzhiyun if (unlikely(pde_is_permanent(de))) {
707*4882a593Smuzhiyun WARN(1, "removing permanent /proc entry '%s'", de->name);
708*4882a593Smuzhiyun de = NULL;
709*4882a593Smuzhiyun } else {
710*4882a593Smuzhiyun rb_erase(&de->subdir_node, &parent->subdir);
711*4882a593Smuzhiyun if (S_ISDIR(de->mode))
712*4882a593Smuzhiyun parent->nlink--;
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun }
715*4882a593Smuzhiyun write_unlock(&proc_subdir_lock);
716*4882a593Smuzhiyun if (!de) {
717*4882a593Smuzhiyun WARN(1, "name '%s'\n", name);
718*4882a593Smuzhiyun return;
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun proc_entry_rundown(de);
722*4882a593Smuzhiyun
723*4882a593Smuzhiyun WARN(pde_subdir_first(de),
724*4882a593Smuzhiyun "%s: removing non-empty directory '%s/%s', leaking at least '%s'\n",
725*4882a593Smuzhiyun __func__, de->parent->name, de->name, pde_subdir_first(de)->name);
726*4882a593Smuzhiyun pde_put(de);
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun EXPORT_SYMBOL(remove_proc_entry);
729*4882a593Smuzhiyun
remove_proc_subtree(const char * name,struct proc_dir_entry * parent)730*4882a593Smuzhiyun int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
731*4882a593Smuzhiyun {
732*4882a593Smuzhiyun struct proc_dir_entry *root = NULL, *de, *next;
733*4882a593Smuzhiyun const char *fn = name;
734*4882a593Smuzhiyun unsigned int len;
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun write_lock(&proc_subdir_lock);
737*4882a593Smuzhiyun if (__xlate_proc_name(name, &parent, &fn) != 0) {
738*4882a593Smuzhiyun write_unlock(&proc_subdir_lock);
739*4882a593Smuzhiyun return -ENOENT;
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun len = strlen(fn);
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun root = pde_subdir_find(parent, fn, len);
744*4882a593Smuzhiyun if (!root) {
745*4882a593Smuzhiyun write_unlock(&proc_subdir_lock);
746*4882a593Smuzhiyun return -ENOENT;
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun if (unlikely(pde_is_permanent(root))) {
749*4882a593Smuzhiyun write_unlock(&proc_subdir_lock);
750*4882a593Smuzhiyun WARN(1, "removing permanent /proc entry '%s/%s'",
751*4882a593Smuzhiyun root->parent->name, root->name);
752*4882a593Smuzhiyun return -EINVAL;
753*4882a593Smuzhiyun }
754*4882a593Smuzhiyun rb_erase(&root->subdir_node, &parent->subdir);
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun de = root;
757*4882a593Smuzhiyun while (1) {
758*4882a593Smuzhiyun next = pde_subdir_first(de);
759*4882a593Smuzhiyun if (next) {
760*4882a593Smuzhiyun if (unlikely(pde_is_permanent(next))) {
761*4882a593Smuzhiyun write_unlock(&proc_subdir_lock);
762*4882a593Smuzhiyun WARN(1, "removing permanent /proc entry '%s/%s'",
763*4882a593Smuzhiyun next->parent->name, next->name);
764*4882a593Smuzhiyun return -EINVAL;
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun rb_erase(&next->subdir_node, &de->subdir);
767*4882a593Smuzhiyun de = next;
768*4882a593Smuzhiyun continue;
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun next = de->parent;
771*4882a593Smuzhiyun if (S_ISDIR(de->mode))
772*4882a593Smuzhiyun next->nlink--;
773*4882a593Smuzhiyun write_unlock(&proc_subdir_lock);
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun proc_entry_rundown(de);
776*4882a593Smuzhiyun if (de == root)
777*4882a593Smuzhiyun break;
778*4882a593Smuzhiyun pde_put(de);
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun write_lock(&proc_subdir_lock);
781*4882a593Smuzhiyun de = next;
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun pde_put(root);
784*4882a593Smuzhiyun return 0;
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun EXPORT_SYMBOL(remove_proc_subtree);
787*4882a593Smuzhiyun
proc_get_parent_data(const struct inode * inode)788*4882a593Smuzhiyun void *proc_get_parent_data(const struct inode *inode)
789*4882a593Smuzhiyun {
790*4882a593Smuzhiyun struct proc_dir_entry *de = PDE(inode);
791*4882a593Smuzhiyun return de->parent->data;
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(proc_get_parent_data);
794*4882a593Smuzhiyun
proc_remove(struct proc_dir_entry * de)795*4882a593Smuzhiyun void proc_remove(struct proc_dir_entry *de)
796*4882a593Smuzhiyun {
797*4882a593Smuzhiyun if (de)
798*4882a593Smuzhiyun remove_proc_subtree(de->name, de->parent);
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun EXPORT_SYMBOL(proc_remove);
801*4882a593Smuzhiyun
PDE_DATA(const struct inode * inode)802*4882a593Smuzhiyun void *PDE_DATA(const struct inode *inode)
803*4882a593Smuzhiyun {
804*4882a593Smuzhiyun return __PDE_DATA(inode);
805*4882a593Smuzhiyun }
806*4882a593Smuzhiyun EXPORT_SYMBOL(PDE_DATA);
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun /*
809*4882a593Smuzhiyun * Pull a user buffer into memory and pass it to the file's write handler if
810*4882a593Smuzhiyun * one is supplied. The ->write() method is permitted to modify the
811*4882a593Smuzhiyun * kernel-side buffer.
812*4882a593Smuzhiyun */
proc_simple_write(struct file * f,const char __user * ubuf,size_t size,loff_t * _pos)813*4882a593Smuzhiyun ssize_t proc_simple_write(struct file *f, const char __user *ubuf, size_t size,
814*4882a593Smuzhiyun loff_t *_pos)
815*4882a593Smuzhiyun {
816*4882a593Smuzhiyun struct proc_dir_entry *pde = PDE(file_inode(f));
817*4882a593Smuzhiyun char *buf;
818*4882a593Smuzhiyun int ret;
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun if (!pde->write)
821*4882a593Smuzhiyun return -EACCES;
822*4882a593Smuzhiyun if (size == 0 || size > PAGE_SIZE - 1)
823*4882a593Smuzhiyun return -EINVAL;
824*4882a593Smuzhiyun buf = memdup_user_nul(ubuf, size);
825*4882a593Smuzhiyun if (IS_ERR(buf))
826*4882a593Smuzhiyun return PTR_ERR(buf);
827*4882a593Smuzhiyun ret = pde->write(f, buf, size);
828*4882a593Smuzhiyun kfree(buf);
829*4882a593Smuzhiyun return ret == 0 ? size : ret;
830*4882a593Smuzhiyun }
831