blob: bec58323629c5e6a4aecbbd62bf6062bd4e1bcac [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * proc/fs/generic.c --- generic routines for the proc-fs
3 *
4 * This file contains generic proc-fs routines for handling
5 * directories and files.
6 *
7 * Copyright (C) 1991, 1992 Linus Torvalds.
8 * Copyright (C) 1997 Theodore Ts'o
9 */
10
11#include <linux/errno.h>
12#include <linux/time.h>
13#include <linux/proc_fs.h>
14#include <linux/stat.h>
Christoph Hellwig10257742010-06-04 11:30:02 +020015#include <linux/mm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <linux/module.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090017#include <linux/slab.h>
Andrew Morton87ebdc02013-02-27 17:03:16 -080018#include <linux/printk.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <linux/init.h>
21#include <linux/idr.h>
22#include <linux/namei.h>
23#include <linux/bitops.h>
Steven Rostedt64a07bd2006-03-26 01:36:55 -080024#include <linux/spinlock.h>
Alexey Dobriyan786d7e12007-07-15 23:39:00 -070025#include <linux/completion.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <asm/uaccess.h>
27
Adrian Bunkfee781e2006-01-08 01:04:16 -080028#include "internal.h"
29
Steven Rostedt64a07bd2006-03-26 01:36:55 -080030DEFINE_SPINLOCK(proc_subdir_lock);
31
Alexey Dobriyan312ec7e2011-03-23 16:42:52 -070032static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de)
Linus Torvalds1da177e2005-04-16 15:20:36 -070033{
34 if (de->namelen != len)
35 return 0;
36 return !memcmp(name, de->name, len);
37}
38
Linus Torvalds1da177e2005-04-16 15:20:36 -070039/* buffer size is one page but our output routines use some slack for overruns */
40#define PROC_BLOCK_SIZE (PAGE_SIZE - 1024)
41
Al Viro866ad9a72013-04-03 19:07:30 -040042ssize_t
Alexey Dobriyan3dec7f52009-02-20 17:04:33 +030043__proc_file_read(struct file *file, char __user *buf, size_t nbytes,
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 loff_t *ppos)
45{
Al Viro496ad9a2013-01-23 17:07:38 -050046 struct inode * inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -070047 char *page;
48 ssize_t retval=0;
49 int eof=0;
50 ssize_t n, count;
51 char *start;
52 struct proc_dir_entry * dp;
Linus Torvalds8b90db02005-12-30 08:39:10 -080053 unsigned long long pos;
54
55 /*
56 * Gaah, please just use "seq_file" instead. The legacy /proc
57 * interfaces cut loff_t down to off_t for reads, and ignore
58 * the offset entirely for writes..
59 */
60 pos = *ppos;
61 if (pos > MAX_NON_LFS)
62 return 0;
63 if (nbytes > MAX_NON_LFS - pos)
64 nbytes = MAX_NON_LFS - pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
66 dp = PDE(inode);
Mel Gormane12ba742007-10-16 01:25:52 -070067 if (!(page = (char*) __get_free_page(GFP_TEMPORARY)))
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 return -ENOMEM;
69
70 while ((nbytes > 0) && !eof) {
71 count = min_t(size_t, PROC_BLOCK_SIZE, nbytes);
72
73 start = NULL;
David Howellsad147d02013-04-04 16:32:28 +010074 if (!dp->read_proc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 break;
76
David Howellsad147d02013-04-04 16:32:28 +010077 /* How to be a proc read function
78 * ------------------------------
79 * Prototype:
80 * int f(char *buffer, char **start, off_t offset,
81 * int count, int *peof, void *dat)
82 *
83 * Assume that the buffer is "count" bytes in size.
84 *
85 * If you know you have supplied all the data you have, set
86 * *peof.
87 *
88 * You have three ways to return data:
89 *
90 * 0) Leave *start = NULL. (This is the default.) Put the
91 * data of the requested offset at that offset within the
92 * buffer. Return the number (n) of bytes there are from
93 * the beginning of the buffer up to the last byte of data.
94 * If the number of supplied bytes (= n - offset) is greater
95 * than zero and you didn't signal eof and the reader is
96 * prepared to take more data you will be called again with
97 * the requested offset advanced by the number of bytes
98 * absorbed. This interface is useful for files no larger
99 * than the buffer.
100 *
101 * 1) Set *start = an unsigned long value less than the buffer
102 * address but greater than zero. Put the data of the
103 * requested offset at the beginning of the buffer. Return
104 * the number of bytes of data placed there. If this number
105 * is greater than zero and you didn't signal eof and the
106 * reader is prepared to take more data you will be called
107 * again with the requested offset advanced by *start. This
108 * interface is useful when you have a large file consisting
109 * of a series of blocks which you want to count and return
110 * as wholes.
111 * (Hack by Paul.Russell@rustcorp.com.au)
112 *
113 * 2) Set *start = an address within the buffer. Put the data
114 * of the requested offset at *start. Return the number of
115 * bytes of data placed there. If this number is greater
116 * than zero and you didn't signal eof and the reader is
117 * prepared to take more data you will be called again with
118 * the requested offset advanced by the number of bytes
119 * absorbed.
120 */
121 n = dp->read_proc(page, &start, *ppos, count, &eof, dp->data);
122
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 if (n == 0) /* end of file */
124 break;
125 if (n < 0) { /* error */
126 if (retval == 0)
127 retval = n;
128 break;
129 }
130
131 if (start == NULL) {
Andrew Morton87ebdc02013-02-27 17:03:16 -0800132 if (n > PAGE_SIZE) /* Apparent buffer overflow */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 n = PAGE_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 n -= *ppos;
135 if (n <= 0)
136 break;
137 if (n > count)
138 n = count;
139 start = page + *ppos;
140 } else if (start < page) {
Andrew Morton87ebdc02013-02-27 17:03:16 -0800141 if (n > PAGE_SIZE) /* Apparent buffer overflow */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 n = PAGE_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143 if (n > count) {
144 /*
145 * Don't reduce n because doing so might
146 * cut off part of a data block.
147 */
Andrew Morton87ebdc02013-02-27 17:03:16 -0800148 pr_warn("proc_file_read: count exceeded\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 }
150 } else /* start >= page */ {
151 unsigned long startoff = (unsigned long)(start - page);
Andrew Morton87ebdc02013-02-27 17:03:16 -0800152 if (n > (PAGE_SIZE - startoff)) /* buffer overflow? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 n = PAGE_SIZE - startoff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154 if (n > count)
155 n = count;
156 }
157
158 n -= copy_to_user(buf, start < page ? page : start, n);
159 if (n == 0) {
160 if (retval == 0)
161 retval = -EFAULT;
162 break;
163 }
164
165 *ppos += start < page ? (unsigned long)start : n;
166 nbytes -= n;
167 buf += n;
168 retval += n;
169 }
170 free_page((unsigned long) page);
171 return retval;
172}
173
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
175{
176 struct inode *inode = dentry->d_inode;
177 struct proc_dir_entry *de = PDE(inode);
178 int error;
179
180 error = inode_change_ok(inode, iattr);
181 if (error)
Christoph Hellwig10257742010-06-04 11:30:02 +0200182 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183
Christoph Hellwig10257742010-06-04 11:30:02 +0200184 setattr_copy(inode, iattr);
185 mark_inode_dirty(inode);
Marco Stornelli46f69552012-12-15 11:48:48 +0100186
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 de->uid = inode->i_uid;
188 de->gid = inode->i_gid;
189 de->mode = inode->i_mode;
Christoph Hellwig10257742010-06-04 11:30:02 +0200190 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191}
192
Miklos Szeredi2b579be2005-09-06 15:17:18 -0700193static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry,
194 struct kstat *stat)
195{
196 struct inode *inode = dentry->d_inode;
197 struct proc_dir_entry *de = PROC_I(inode)->pde;
198 if (de && de->nlink)
Miklos Szeredibfe86842011-10-28 14:13:29 +0200199 set_nlink(inode, de->nlink);
Miklos Szeredi2b579be2005-09-06 15:17:18 -0700200
201 generic_fillattr(inode, stat);
202 return 0;
203}
204
Arjan van de Venc5ef1c42007-02-12 00:55:40 -0800205static const struct inode_operations proc_file_inode_operations = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 .setattr = proc_notify_change,
207};
208
209/*
210 * This function parses a name such as "tty/driver/serial", and
211 * returns the struct proc_dir_entry for "/proc/tty/driver", and
212 * returns "serial" in residual.
213 */
Alexey Dobriyane17a5762010-03-05 13:43:59 -0800214static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret,
215 const char **residual)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216{
217 const char *cp = name, *next;
218 struct proc_dir_entry *de;
Alexey Dobriyan312ec7e2011-03-23 16:42:52 -0700219 unsigned int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
Alexey Dobriyan7cee4e02008-04-29 01:01:40 -0700221 de = *ret;
222 if (!de)
223 de = &proc_root;
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 while (1) {
226 next = strchr(cp, '/');
227 if (!next)
228 break;
229
230 len = next - cp;
231 for (de = de->subdir; de ; de = de->next) {
232 if (proc_match(len, cp, de))
233 break;
234 }
Alexey Dobriyan12bac0d2010-03-05 13:44:00 -0800235 if (!de) {
236 WARN(1, "name '%s'\n", name);
Alexey Dobriyane17a5762010-03-05 13:43:59 -0800237 return -ENOENT;
Alexey Dobriyan12bac0d2010-03-05 13:44:00 -0800238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 cp += len + 1;
240 }
241 *residual = cp;
242 *ret = de;
Alexey Dobriyane17a5762010-03-05 13:43:59 -0800243 return 0;
244}
245
246static int xlate_proc_name(const char *name, struct proc_dir_entry **ret,
247 const char **residual)
248{
249 int rv;
250
251 spin_lock(&proc_subdir_lock);
252 rv = __xlate_proc_name(name, ret, residual);
Steven Rostedt64a07bd2006-03-26 01:36:55 -0800253 spin_unlock(&proc_subdir_lock);
Alexey Dobriyane17a5762010-03-05 13:43:59 -0800254 return rv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255}
256
Alexey Dobriyan9a185402008-07-26 11:21:37 +0400257static DEFINE_IDA(proc_inum_ida);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */
259
Alexey Dobriyan67935df2008-07-26 11:18:28 +0400260#define PROC_DYNAMIC_FIRST 0xF0000000U
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
262/*
263 * Return an inode number between PROC_DYNAMIC_FIRST and
264 * 0xffffffff, or zero on failure.
265 */
Eric W. Biederman33d6dce2011-06-17 13:33:20 -0700266int proc_alloc_inum(unsigned int *inum)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267{
Alexey Dobriyan67935df2008-07-26 11:18:28 +0400268 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 int error;
270
271retry:
Eric W. Biederman33d6dce2011-06-17 13:33:20 -0700272 if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
273 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
Eric W. Biedermandfb2ea42012-12-21 20:38:00 -0800275 spin_lock_irq(&proc_inum_lock);
Alexey Dobriyan9a185402008-07-26 11:21:37 +0400276 error = ida_get_new(&proc_inum_ida, &i);
Eric W. Biedermandfb2ea42012-12-21 20:38:00 -0800277 spin_unlock_irq(&proc_inum_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 if (error == -EAGAIN)
279 goto retry;
280 else if (error)
Eric W. Biederman33d6dce2011-06-17 13:33:20 -0700281 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
Alexey Dobriyan67935df2008-07-26 11:18:28 +0400283 if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
Eric W. Biedermandfb2ea42012-12-21 20:38:00 -0800284 spin_lock_irq(&proc_inum_lock);
Alexey Dobriyan9a185402008-07-26 11:21:37 +0400285 ida_remove(&proc_inum_ida, i);
Eric W. Biedermandfb2ea42012-12-21 20:38:00 -0800286 spin_unlock_irq(&proc_inum_lock);
Eric W. Biederman33d6dce2011-06-17 13:33:20 -0700287 return -ENOSPC;
Alexey Dobriyan67935df2008-07-26 11:18:28 +0400288 }
Eric W. Biederman33d6dce2011-06-17 13:33:20 -0700289 *inum = PROC_DYNAMIC_FIRST + i;
290 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291}
292
Eric W. Biederman33d6dce2011-06-17 13:33:20 -0700293void proc_free_inum(unsigned int inum)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294{
Eric W. Biedermandfb2ea42012-12-21 20:38:00 -0800295 unsigned long flags;
296 spin_lock_irqsave(&proc_inum_lock, flags);
Alexey Dobriyan9a185402008-07-26 11:21:37 +0400297 ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
Eric W. Biedermandfb2ea42012-12-21 20:38:00 -0800298 spin_unlock_irqrestore(&proc_inum_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299}
300
Al Viro008b1502005-08-20 00:17:39 +0100301static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302{
Al Virod9dda782013-03-31 18:16:14 -0400303 nd_set_link(nd, PDE_DATA(dentry->d_inode));
Al Viro008b1502005-08-20 00:17:39 +0100304 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305}
306
Arjan van de Venc5ef1c42007-02-12 00:55:40 -0800307static const struct inode_operations proc_link_inode_operations = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 .readlink = generic_readlink,
309 .follow_link = proc_follow_link,
310};
311
312/*
313 * As some entries in /proc are volatile, we want to
314 * get rid of unused dentries. This could be made
315 * smarter: we could keep a "volatile" flag in the
316 * inode to indicate which ones to keep.
317 */
Nick Pigginfe15ce42011-01-07 17:49:23 +1100318static int proc_delete_dentry(const struct dentry * dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319{
320 return 1;
321}
322
Al Virod72f71e2009-02-20 05:58:47 +0000323static const struct dentry_operations proc_dentry_operations =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324{
325 .d_delete = proc_delete_dentry,
326};
327
328/*
329 * Don't create negative dentries here, return -ENOENT by hand
330 * instead.
331 */
Pavel Emelyanove9720ac2008-03-07 11:08:40 -0800332struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
333 struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334{
Al Virod3d009c2013-01-25 20:11:22 -0500335 struct inode *inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
Steven Rostedt64a07bd2006-03-26 01:36:55 -0800337 spin_lock(&proc_subdir_lock);
Alexey Dobriyan5e971dc2008-04-29 01:01:41 -0700338 for (de = de->subdir; de ; de = de->next) {
339 if (de->namelen != dentry->d_name.len)
340 continue;
341 if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
Alexey Dobriyan135d5652009-12-15 16:45:39 -0800342 pde_get(de);
Alexey Dobriyan5e971dc2008-04-29 01:01:41 -0700343 spin_unlock(&proc_subdir_lock);
Alexey Dobriyan6d1b6e42011-01-12 17:00:33 -0800344 inode = proc_get_inode(dir->i_sb, de);
Al Virod3d009c2013-01-25 20:11:22 -0500345 if (!inode)
346 return ERR_PTR(-ENOMEM);
347 d_set_d_op(dentry, &proc_dentry_operations);
348 d_add(dentry, inode);
349 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 }
351 }
Steven Rostedt64a07bd2006-03-26 01:36:55 -0800352 spin_unlock(&proc_subdir_lock);
Al Virod3d009c2013-01-25 20:11:22 -0500353 return ERR_PTR(-ENOENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354}
355
Pavel Emelyanove9720ac2008-03-07 11:08:40 -0800356struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400357 unsigned int flags)
Pavel Emelyanove9720ac2008-03-07 11:08:40 -0800358{
359 return proc_lookup_de(PDE(dir), dir, dentry);
360}
361
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362/*
363 * This returns non-zero if at EOF, so that the /proc
364 * root directory can use this and check if it should
365 * continue with the <pid> entries..
366 *
367 * Note that the VFS-layer doesn't care about the return
368 * value of the readdir() call, as long as it's non-negative
369 * for success..
370 */
Pavel Emelyanove9720ac2008-03-07 11:08:40 -0800371int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
372 filldir_t filldir)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 unsigned int ino;
375 int i;
Al Viro496ad9a2013-01-23 17:07:38 -0500376 struct inode *inode = file_inode(filp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 int ret = 0;
378
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 ino = inode->i_ino;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 i = filp->f_pos;
381 switch (i) {
382 case 0:
383 if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
384 goto out;
385 i++;
386 filp->f_pos++;
387 /* fall through */
388 case 1:
389 if (filldir(dirent, "..", 2, i,
Josef "Jeff" Sipek2fddfee2006-12-08 02:36:36 -0800390 parent_ino(filp->f_path.dentry),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 DT_DIR) < 0)
392 goto out;
393 i++;
394 filp->f_pos++;
395 /* fall through */
396 default:
Steven Rostedt64a07bd2006-03-26 01:36:55 -0800397 spin_lock(&proc_subdir_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 de = de->subdir;
399 i -= 2;
400 for (;;) {
401 if (!de) {
402 ret = 1;
Steven Rostedt64a07bd2006-03-26 01:36:55 -0800403 spin_unlock(&proc_subdir_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 goto out;
405 }
406 if (!i)
407 break;
408 de = de->next;
409 i--;
410 }
411
412 do {
Darrick J. Wong59cd0cb2007-05-08 00:25:47 -0700413 struct proc_dir_entry *next;
414
Steven Rostedt64a07bd2006-03-26 01:36:55 -0800415 /* filldir passes info to user space */
Alexey Dobriyan135d5652009-12-15 16:45:39 -0800416 pde_get(de);
Steven Rostedt64a07bd2006-03-26 01:36:55 -0800417 spin_unlock(&proc_subdir_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 if (filldir(dirent, de->name, de->namelen, filp->f_pos,
Darrick J. Wong59cd0cb2007-05-08 00:25:47 -0700419 de->low_ino, de->mode >> 12) < 0) {
Alexey Dobriyan135d5652009-12-15 16:45:39 -0800420 pde_put(de);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 goto out;
Darrick J. Wong59cd0cb2007-05-08 00:25:47 -0700422 }
Steven Rostedt64a07bd2006-03-26 01:36:55 -0800423 spin_lock(&proc_subdir_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 filp->f_pos++;
Darrick J. Wong59cd0cb2007-05-08 00:25:47 -0700425 next = de->next;
Alexey Dobriyan135d5652009-12-15 16:45:39 -0800426 pde_put(de);
Darrick J. Wong59cd0cb2007-05-08 00:25:47 -0700427 de = next;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 } while (de);
Steven Rostedt64a07bd2006-03-26 01:36:55 -0800429 spin_unlock(&proc_subdir_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 }
431 ret = 1;
Alexey Dobriyanb4df2b92008-10-27 22:48:36 +0300432out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 return ret;
434}
435
Pavel Emelyanove9720ac2008-03-07 11:08:40 -0800436int proc_readdir(struct file *filp, void *dirent, filldir_t filldir)
437{
Al Viro496ad9a2013-01-23 17:07:38 -0500438 struct inode *inode = file_inode(filp);
Pavel Emelyanove9720ac2008-03-07 11:08:40 -0800439
440 return proc_readdir_de(PDE(inode), filp, dirent, filldir);
441}
442
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443/*
444 * These are the generic /proc directory operations. They
445 * use the in-memory "struct proc_dir_entry" tree to parse
446 * the /proc directory.
447 */
Arjan van de Ven00977a52007-02-12 00:55:34 -0800448static const struct file_operations proc_dir_operations = {
Alexey Dobriyanb4df2b92008-10-27 22:48:36 +0300449 .llseek = generic_file_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 .read = generic_read_dir,
451 .readdir = proc_readdir,
452};
453
454/*
455 * proc directories can do almost nothing..
456 */
Arjan van de Venc5ef1c42007-02-12 00:55:40 -0800457static const struct inode_operations proc_dir_inode_operations = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 .lookup = proc_lookup,
Miklos Szeredi2b579be2005-09-06 15:17:18 -0700459 .getattr = proc_getattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 .setattr = proc_notify_change,
461};
462
463static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
464{
Zhang Rui94413d82008-02-08 04:18:29 -0800465 struct proc_dir_entry *tmp;
Eric W. Biederman33d6dce2011-06-17 13:33:20 -0700466 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467
Eric W. Biederman33d6dce2011-06-17 13:33:20 -0700468 ret = proc_alloc_inum(&dp->low_ino);
469 if (ret)
470 return ret;
Steven Rostedt64a07bd2006-03-26 01:36:55 -0800471
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 if (S_ISDIR(dp->mode)) {
Al Virob6cdc732013-03-30 21:20:14 -0400473 dp->proc_fops = &proc_dir_operations;
474 dp->proc_iops = &proc_dir_inode_operations;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 dir->nlink++;
476 } else if (S_ISLNK(dp->mode)) {
Al Virob6cdc732013-03-30 21:20:14 -0400477 dp->proc_iops = &proc_link_inode_operations;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 } else if (S_ISREG(dp->mode)) {
479 if (dp->proc_fops == NULL)
480 dp->proc_fops = &proc_file_operations;
Al Virob6cdc732013-03-30 21:20:14 -0400481 dp->proc_iops = &proc_file_inode_operations;
482 } else {
483 WARN_ON(1);
484 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 }
Changli Gao99fc06d2007-07-15 23:40:09 -0700486
487 spin_lock(&proc_subdir_lock);
Zhang Rui94413d82008-02-08 04:18:29 -0800488
489 for (tmp = dir->subdir; tmp; tmp = tmp->next)
490 if (strcmp(tmp->name, dp->name) == 0) {
Andrew Morton87ebdc02013-02-27 17:03:16 -0800491 WARN(1, "proc_dir_entry '%s/%s' already registered\n",
Alexey Dobriyan665020c2008-09-13 02:33:06 -0700492 dir->name, dp->name);
Zhang Rui94413d82008-02-08 04:18:29 -0800493 break;
494 }
495
Changli Gao99fc06d2007-07-15 23:40:09 -0700496 dp->next = dir->subdir;
497 dp->parent = dir;
498 dir->subdir = dp;
499 spin_unlock(&proc_subdir_lock);
500
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 return 0;
502}
503
Alexey Dobriyan2d3a4e32008-02-08 04:18:37 -0800504static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 const char *name,
Al Virod161a132011-07-24 03:36:29 -0400506 umode_t mode,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 nlink_t nlink)
508{
509 struct proc_dir_entry *ent = NULL;
510 const char *fn = name;
Alexey Dobriyan312ec7e2011-03-23 16:42:52 -0700511 unsigned int len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
513 /* make sure name is valid */
yan17baa2a2012-10-04 17:15:43 -0700514 if (!name || !strlen(name))
515 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
Alexey Dobriyan7cee4e02008-04-29 01:01:40 -0700517 if (xlate_proc_name(name, parent, &fn) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 goto out;
519
520 /* At this point there must not be any '/' characters beyond *fn */
521 if (strchr(fn, '/'))
522 goto out;
523
524 len = strlen(fn);
525
yan17baa2a2012-10-04 17:15:43 -0700526 ent = kzalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
527 if (!ent)
528 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529
David Howells09570f92011-07-27 21:47:03 +0300530 memcpy(ent->name, fn, len + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 ent->namelen = len;
532 ent->mode = mode;
533 ent->nlink = nlink;
Alexey Dobriyan5a622f22007-12-04 23:45:28 -0800534 atomic_set(&ent->count, 1);
Alexey Dobriyan786d7e12007-07-15 23:39:00 -0700535 spin_lock_init(&ent->pde_unload_lock);
Alexey Dobriyan881adb82008-07-25 01:48:29 -0700536 INIT_LIST_HEAD(&ent->pde_openers);
yan17baa2a2012-10-04 17:15:43 -0700537out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 return ent;
539}
540
541struct proc_dir_entry *proc_symlink(const char *name,
542 struct proc_dir_entry *parent, const char *dest)
543{
544 struct proc_dir_entry *ent;
545
Alexey Dobriyan2d3a4e32008-02-08 04:18:37 -0800546 ent = __proc_create(&parent, name,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
548
549 if (ent) {
550 ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
551 if (ent->data) {
552 strcpy((char*)ent->data,dest);
553 if (proc_register(parent, ent) < 0) {
554 kfree(ent->data);
555 kfree(ent);
556 ent = NULL;
557 }
558 } else {
559 kfree(ent);
560 ent = NULL;
561 }
562 }
563 return ent;
564}
Helight.Xu587d4a12009-12-30 13:24:41 +0800565EXPORT_SYMBOL(proc_symlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
Al Virod161a132011-07-24 03:36:29 -0400567struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 struct proc_dir_entry *parent)
569{
570 struct proc_dir_entry *ent;
571
Alexey Dobriyan2d3a4e32008-02-08 04:18:37 -0800572 ent = __proc_create(&parent, name, S_IFDIR | mode, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 if (ent) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 if (proc_register(parent, ent) < 0) {
575 kfree(ent);
576 ent = NULL;
577 }
578 }
579 return ent;
580}
Alexey Dobriyan011159a2011-05-14 00:12:48 +0300581EXPORT_SYMBOL(proc_mkdir_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
Denis V. Lunev78e92b92008-05-02 04:12:41 -0700583struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,
584 struct proc_dir_entry *parent)
585{
586 struct proc_dir_entry *ent;
587
588 ent = __proc_create(&parent, name, S_IFDIR | S_IRUGO | S_IXUGO, 2);
589 if (ent) {
590 ent->data = net;
591 if (proc_register(parent, ent) < 0) {
592 kfree(ent);
593 ent = NULL;
594 }
595 }
596 return ent;
597}
598EXPORT_SYMBOL_GPL(proc_net_mkdir);
599
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600struct proc_dir_entry *proc_mkdir(const char *name,
601 struct proc_dir_entry *parent)
602{
603 return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
604}
Helight.Xu587d4a12009-12-30 13:24:41 +0800605EXPORT_SYMBOL(proc_mkdir);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
David Howells80e928f2013-04-04 17:02:03 +0100607struct proc_dir_entry *create_proc_read_entry(
608 const char *name, umode_t mode, struct proc_dir_entry *parent,
609 read_proc_t *read_proc, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610{
611 struct proc_dir_entry *ent;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
Al Virob6cdc732013-03-30 21:20:14 -0400613 if ((mode & S_IFMT) == 0)
614 mode |= S_IFREG;
615
616 if (!S_ISREG(mode)) {
617 WARN_ON(1); /* use proc_mkdir(), damnit */
618 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 }
620
Al Virob6cdc732013-03-30 21:20:14 -0400621 if ((mode & S_IALLUGO) == 0)
622 mode |= S_IRUGO;
623
624 ent = __proc_create(&parent, name, mode, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 if (ent) {
David Howells80e928f2013-04-04 17:02:03 +0100626 ent->read_proc = read_proc;
627 ent->data = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 if (proc_register(parent, ent) < 0) {
629 kfree(ent);
630 ent = NULL;
631 }
632 }
633 return ent;
634}
David Howells80e928f2013-04-04 17:02:03 +0100635EXPORT_SYMBOL(create_proc_read_entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
Al Virod161a132011-07-24 03:36:29 -0400637struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
Denis V. Lunev59b74352008-04-29 01:02:00 -0700638 struct proc_dir_entry *parent,
639 const struct file_operations *proc_fops,
640 void *data)
Alexey Dobriyan2d3a4e32008-02-08 04:18:37 -0800641{
642 struct proc_dir_entry *pde;
Al Virob6cdc732013-03-30 21:20:14 -0400643 if ((mode & S_IFMT) == 0)
644 mode |= S_IFREG;
Alexey Dobriyan2d3a4e32008-02-08 04:18:37 -0800645
Al Virob6cdc732013-03-30 21:20:14 -0400646 if (!S_ISREG(mode)) {
647 WARN_ON(1); /* use proc_mkdir() */
648 return NULL;
Alexey Dobriyan2d3a4e32008-02-08 04:18:37 -0800649 }
650
Al Virob6cdc732013-03-30 21:20:14 -0400651 if ((mode & S_IALLUGO) == 0)
652 mode |= S_IRUGO;
653 pde = __proc_create(&parent, name, mode, 1);
Alexey Dobriyan2d3a4e32008-02-08 04:18:37 -0800654 if (!pde)
655 goto out;
656 pde->proc_fops = proc_fops;
Denis V. Lunev59b74352008-04-29 01:02:00 -0700657 pde->data = data;
Alexey Dobriyan2d3a4e32008-02-08 04:18:37 -0800658 if (proc_register(parent, pde) < 0)
659 goto out_free;
660 return pde;
661out_free:
662 kfree(pde);
663out:
664 return NULL;
665}
Helight.Xu587d4a12009-12-30 13:24:41 +0800666EXPORT_SYMBOL(proc_create_data);
Alexey Dobriyan2d3a4e32008-02-08 04:18:37 -0800667
Alexey Dobriyan135d5652009-12-15 16:45:39 -0800668static void free_proc_entry(struct proc_dir_entry *de)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669{
Eric W. Biederman33d6dce2011-06-17 13:33:20 -0700670 proc_free_inum(de->low_ino);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671
Alexey Dobriyanfd2cbe42008-02-08 04:18:28 -0800672 if (S_ISLNK(de->mode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 kfree(de->data);
674 kfree(de);
675}
676
Alexey Dobriyan135d5652009-12-15 16:45:39 -0800677void pde_put(struct proc_dir_entry *pde)
678{
679 if (atomic_dec_and_test(&pde->count))
680 free_proc_entry(pde);
681}
682
Al Viro8ce584c2013-03-30 20:13:46 -0400683/*
684 * Remove a /proc entry and free it if it's not currently in use.
685 */
686void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
687{
688 struct proc_dir_entry **p;
689 struct proc_dir_entry *de = NULL;
690 const char *fn = name;
691 unsigned int len;
692
693 spin_lock(&proc_subdir_lock);
694 if (__xlate_proc_name(name, &parent, &fn) != 0) {
695 spin_unlock(&proc_subdir_lock);
696 return;
697 }
698 len = strlen(fn);
699
700 for (p = &parent->subdir; *p; p=&(*p)->next ) {
701 if (proc_match(len, fn, *p)) {
702 de = *p;
703 *p = de->next;
704 de->next = NULL;
705 break;
706 }
707 }
708 spin_unlock(&proc_subdir_lock);
709 if (!de) {
710 WARN(1, "name '%s'\n", name);
711 return;
712 }
713
Al Viro866ad9a72013-04-03 19:07:30 -0400714 proc_entry_rundown(de);
Alexey Dobriyan881adb82008-07-25 01:48:29 -0700715
Alexey Dobriyanf649d6d2008-04-29 01:01:39 -0700716 if (S_ISDIR(de->mode))
717 parent->nlink--;
718 de->nlink = 0;
Andrew Morton87ebdc02013-02-27 17:03:16 -0800719 WARN(de->subdir, "%s: removing non-empty directory "
720 "'%s/%s', leaking at least '%s'\n", __func__,
721 de->parent->name, de->name, de->subdir->name);
Alexey Dobriyan135d5652009-12-15 16:45:39 -0800722 pde_put(de);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723}
Helight.Xu587d4a12009-12-30 13:24:41 +0800724EXPORT_SYMBOL(remove_proc_entry);
Al Viro8ce584c2013-03-30 20:13:46 -0400725
726int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
727{
728 struct proc_dir_entry **p;
729 struct proc_dir_entry *root = NULL, *de, *next;
730 const char *fn = name;
731 unsigned int len;
732
733 spin_lock(&proc_subdir_lock);
734 if (__xlate_proc_name(name, &parent, &fn) != 0) {
735 spin_unlock(&proc_subdir_lock);
736 return -ENOENT;
737 }
738 len = strlen(fn);
739
740 for (p = &parent->subdir; *p; p=&(*p)->next ) {
741 if (proc_match(len, fn, *p)) {
742 root = *p;
743 *p = root->next;
744 root->next = NULL;
745 break;
746 }
747 }
748 if (!root) {
749 spin_unlock(&proc_subdir_lock);
750 return -ENOENT;
751 }
752 de = root;
753 while (1) {
754 next = de->subdir;
755 if (next) {
756 de->subdir = next->next;
757 next->next = NULL;
758 de = next;
759 continue;
760 }
761 spin_unlock(&proc_subdir_lock);
762
Al Viro866ad9a72013-04-03 19:07:30 -0400763 proc_entry_rundown(de);
Al Viro8ce584c2013-03-30 20:13:46 -0400764 next = de->parent;
765 if (S_ISDIR(de->mode))
766 next->nlink--;
767 de->nlink = 0;
768 if (de == root)
769 break;
770 pde_put(de);
771
772 spin_lock(&proc_subdir_lock);
773 de = next;
774 }
775 pde_put(root);
776 return 0;
777}
778EXPORT_SYMBOL(remove_proc_subtree);