generic.c 12.6 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * proc/fs/generic.c --- generic routines for the proc-fs
 *
 * This file contains generic proc-fs routines for handling
 * directories and files.
 * 
 * Copyright (C) 1991, 1992 Linus Torvalds.
 * Copyright (C) 1997 Theodore Ts'o
 */

#include <linux/errno.h>
#include <linux/time.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
Christoph Hellwig's avatar
Christoph Hellwig committed
15
#include <linux/mm.h>
Linus Torvalds's avatar
Linus Torvalds committed
16
#include <linux/module.h>
17
#include <linux/slab.h>
18
#include <linux/printk.h>
Linus Torvalds's avatar
Linus Torvalds committed
19 20 21 22 23
#include <linux/mount.h>
#include <linux/init.h>
#include <linux/idr.h>
#include <linux/namei.h>
#include <linux/bitops.h>
24
#include <linux/spinlock.h>
25
#include <linux/completion.h>
Linus Torvalds's avatar
Linus Torvalds committed
26 27
#include <asm/uaccess.h>

28 29
#include "internal.h"

30 31
DEFINE_SPINLOCK(proc_subdir_lock);

32
static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de)
Linus Torvalds's avatar
Linus Torvalds committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46
{
	if (de->namelen != len)
		return 0;
	return !memcmp(name, de->name, len);
}

static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
{
	struct inode *inode = dentry->d_inode;
	struct proc_dir_entry *de = PDE(inode);
	int error;

	error = inode_change_ok(inode, iattr);
	if (error)
Christoph Hellwig's avatar
Christoph Hellwig committed
47
		return error;
Linus Torvalds's avatar
Linus Torvalds committed
48

Christoph Hellwig's avatar
Christoph Hellwig committed
49 50
	setattr_copy(inode, iattr);
	mark_inode_dirty(inode);
51

Linus Torvalds's avatar
Linus Torvalds committed
52 53 54
	de->uid = inode->i_uid;
	de->gid = inode->i_gid;
	de->mode = inode->i_mode;
Christoph Hellwig's avatar
Christoph Hellwig committed
55
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
56 57
}

58 59 60 61 62 63
static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry,
			struct kstat *stat)
{
	struct inode *inode = dentry->d_inode;
	struct proc_dir_entry *de = PROC_I(inode)->pde;
	if (de && de->nlink)
64
		set_nlink(inode, de->nlink);
65 66 67 68 69

	generic_fillattr(inode, stat);
	return 0;
}

70
static const struct inode_operations proc_file_inode_operations = {
Linus Torvalds's avatar
Linus Torvalds committed
71 72 73 74 75 76 77 78
	.setattr	= proc_notify_change,
};

/*
 * This function parses a name such as "tty/driver/serial", and
 * returns the struct proc_dir_entry for "/proc/tty/driver", and
 * returns "serial" in residual.
 */
79 80
static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret,
			     const char **residual)
Linus Torvalds's avatar
Linus Torvalds committed
81 82 83
{
	const char     		*cp = name, *next;
	struct proc_dir_entry	*de;
84
	unsigned int		len;
Linus Torvalds's avatar
Linus Torvalds committed
85

86 87 88 89
	de = *ret;
	if (!de)
		de = &proc_root;

Linus Torvalds's avatar
Linus Torvalds committed
90 91 92 93 94 95 96 97 98 99
	while (1) {
		next = strchr(cp, '/');
		if (!next)
			break;

		len = next - cp;
		for (de = de->subdir; de ; de = de->next) {
			if (proc_match(len, cp, de))
				break;
		}
100 101
		if (!de) {
			WARN(1, "name '%s'\n", name);
102
			return -ENOENT;
103
		}
Linus Torvalds's avatar
Linus Torvalds committed
104 105 106 107
		cp += len + 1;
	}
	*residual = cp;
	*ret = de;
108 109 110 111 112 113 114 115 116 117
	return 0;
}

static int xlate_proc_name(const char *name, struct proc_dir_entry **ret,
			   const char **residual)
{
	int rv;

	spin_lock(&proc_subdir_lock);
	rv = __xlate_proc_name(name, ret, residual);
118
	spin_unlock(&proc_subdir_lock);
119
	return rv;
Linus Torvalds's avatar
Linus Torvalds committed
120 121
}

122
static DEFINE_IDA(proc_inum_ida);
Linus Torvalds's avatar
Linus Torvalds committed
123 124
static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */

125
#define PROC_DYNAMIC_FIRST 0xF0000000U
Linus Torvalds's avatar
Linus Torvalds committed
126 127 128 129 130

/*
 * Return an inode number between PROC_DYNAMIC_FIRST and
 * 0xffffffff, or zero on failure.
 */
131
int proc_alloc_inum(unsigned int *inum)
Linus Torvalds's avatar
Linus Torvalds committed
132
{
133
	unsigned int i;
Linus Torvalds's avatar
Linus Torvalds committed
134 135 136
	int error;

retry:
137 138
	if (!ida_pre_get(&proc_inum_ida, GFP_KERNEL))
		return -ENOMEM;
Linus Torvalds's avatar
Linus Torvalds committed
139

140
	spin_lock_irq(&proc_inum_lock);
141
	error = ida_get_new(&proc_inum_ida, &i);
142
	spin_unlock_irq(&proc_inum_lock);
Linus Torvalds's avatar
Linus Torvalds committed
143 144 145
	if (error == -EAGAIN)
		goto retry;
	else if (error)
146
		return error;
Linus Torvalds's avatar
Linus Torvalds committed
147

148
	if (i > UINT_MAX - PROC_DYNAMIC_FIRST) {
149
		spin_lock_irq(&proc_inum_lock);
150
		ida_remove(&proc_inum_ida, i);
151
		spin_unlock_irq(&proc_inum_lock);
152
		return -ENOSPC;
153
	}
154 155
	*inum = PROC_DYNAMIC_FIRST + i;
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
156 157
}

158
void proc_free_inum(unsigned int inum)
Linus Torvalds's avatar
Linus Torvalds committed
159
{
160 161
	unsigned long flags;
	spin_lock_irqsave(&proc_inum_lock, flags);
162
	ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
163
	spin_unlock_irqrestore(&proc_inum_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
164 165
}

166
static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
Linus Torvalds's avatar
Linus Torvalds committed
167
{
168
	nd_set_link(nd, __PDE_DATA(dentry->d_inode));
169
	return NULL;
Linus Torvalds's avatar
Linus Torvalds committed
170 171
}

172
static const struct inode_operations proc_link_inode_operations = {
Linus Torvalds's avatar
Linus Torvalds committed
173 174 175 176 177 178 179 180
	.readlink	= generic_readlink,
	.follow_link	= proc_follow_link,
};

/*
 * Don't create negative dentries here, return -ENOENT by hand
 * instead.
 */
181 182
struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
		struct dentry *dentry)
Linus Torvalds's avatar
Linus Torvalds committed
183
{
184
	struct inode *inode;
Linus Torvalds's avatar
Linus Torvalds committed
185

186
	spin_lock(&proc_subdir_lock);
187 188 189 190
	for (de = de->subdir; de ; de = de->next) {
		if (de->namelen != dentry->d_name.len)
			continue;
		if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
191
			pde_get(de);
192
			spin_unlock(&proc_subdir_lock);
193
			inode = proc_get_inode(dir->i_sb, de);
194 195
			if (!inode)
				return ERR_PTR(-ENOMEM);
196
			d_set_d_op(dentry, &simple_dentry_operations);
197 198
			d_add(dentry, inode);
			return NULL;
Linus Torvalds's avatar
Linus Torvalds committed
199 200
		}
	}
201
	spin_unlock(&proc_subdir_lock);
202
	return ERR_PTR(-ENOENT);
Linus Torvalds's avatar
Linus Torvalds committed
203 204
}

205
struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
206
		unsigned int flags)
207 208 209 210
{
	return proc_lookup_de(PDE(dir), dir, dentry);
}

Linus Torvalds's avatar
Linus Torvalds committed
211 212 213 214 215 216 217 218 219
/*
 * This returns non-zero if at EOF, so that the /proc
 * root directory can use this and check if it should
 * continue with the <pid> entries..
 *
 * Note that the VFS-layer doesn't care about the return
 * value of the readdir() call, as long as it's non-negative
 * for success..
 */
Al Viro's avatar
Al Viro committed
220 221
int proc_readdir_de(struct proc_dir_entry *de, struct file *file,
		    struct dir_context *ctx)
Linus Torvalds's avatar
Linus Torvalds committed
222 223
{
	int i;
Al Viro's avatar
Al Viro committed
224 225 226 227 228 229 230 231 232

	if (!dir_emit_dots(file, ctx))
		return 0;

	spin_lock(&proc_subdir_lock);
	de = de->subdir;
	i = ctx->pos - 2;
	for (;;) {
		if (!de) {
233
			spin_unlock(&proc_subdir_lock);
Al Viro's avatar
Al Viro committed
234 235 236 237 238 239
			return 0;
		}
		if (!i)
			break;
		de = de->next;
		i--;
Linus Torvalds's avatar
Linus Torvalds committed
240
	}
Al Viro's avatar
Al Viro committed
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257

	do {
		struct proc_dir_entry *next;
		pde_get(de);
		spin_unlock(&proc_subdir_lock);
		if (!dir_emit(ctx, de->name, de->namelen,
			    de->low_ino, de->mode >> 12)) {
			pde_put(de);
			return 0;
		}
		spin_lock(&proc_subdir_lock);
		ctx->pos++;
		next = de->next;
		pde_put(de);
		de = next;
	} while (de);
	spin_unlock(&proc_subdir_lock);
258
	return 1;
Linus Torvalds's avatar
Linus Torvalds committed
259 260
}

Al Viro's avatar
Al Viro committed
261
int proc_readdir(struct file *file, struct dir_context *ctx)
262
{
Al Viro's avatar
Al Viro committed
263
	struct inode *inode = file_inode(file);
264

Al Viro's avatar
Al Viro committed
265
	return proc_readdir_de(PDE(inode), file, ctx);
266 267
}

Linus Torvalds's avatar
Linus Torvalds committed
268 269 270 271 272
/*
 * These are the generic /proc directory operations. They
 * use the in-memory "struct proc_dir_entry" tree to parse
 * the /proc directory.
 */
273
static const struct file_operations proc_dir_operations = {
Alexey Dobriyan's avatar
Alexey Dobriyan committed
274
	.llseek			= generic_file_llseek,
Linus Torvalds's avatar
Linus Torvalds committed
275
	.read			= generic_read_dir,
Al Viro's avatar
Al Viro committed
276
	.iterate		= proc_readdir,
Linus Torvalds's avatar
Linus Torvalds committed
277 278 279 280 281
};

/*
 * proc directories can do almost nothing..
 */
282
static const struct inode_operations proc_dir_inode_operations = {
Linus Torvalds's avatar
Linus Torvalds committed
283
	.lookup		= proc_lookup,
284
	.getattr	= proc_getattr,
Linus Torvalds's avatar
Linus Torvalds committed
285 286 287 288 289
	.setattr	= proc_notify_change,
};

static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
{
290
	struct proc_dir_entry *tmp;
291
	int ret;
Linus Torvalds's avatar
Linus Torvalds committed
292
	
293 294 295
	ret = proc_alloc_inum(&dp->low_ino);
	if (ret)
		return ret;
296

Linus Torvalds's avatar
Linus Torvalds committed
297
	if (S_ISDIR(dp->mode)) {
298 299
		dp->proc_fops = &proc_dir_operations;
		dp->proc_iops = &proc_dir_inode_operations;
Linus Torvalds's avatar
Linus Torvalds committed
300 301
		dir->nlink++;
	} else if (S_ISLNK(dp->mode)) {
302
		dp->proc_iops = &proc_link_inode_operations;
Linus Torvalds's avatar
Linus Torvalds committed
303
	} else if (S_ISREG(dp->mode)) {
304
		BUG_ON(dp->proc_fops == NULL);
305 306 307 308
		dp->proc_iops = &proc_file_inode_operations;
	} else {
		WARN_ON(1);
		return -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
309
	}
310 311

	spin_lock(&proc_subdir_lock);
312 313 314

	for (tmp = dir->subdir; tmp; tmp = tmp->next)
		if (strcmp(tmp->name, dp->name) == 0) {
315
			WARN(1, "proc_dir_entry '%s/%s' already registered\n",
316
				dir->name, dp->name);
317 318 319
			break;
		}

320 321 322 323 324
	dp->next = dir->subdir;
	dp->parent = dir;
	dir->subdir = dp;
	spin_unlock(&proc_subdir_lock);

Linus Torvalds's avatar
Linus Torvalds committed
325 326 327
	return 0;
}

328
static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
Linus Torvalds's avatar
Linus Torvalds committed
329
					  const char *name,
Al Viro's avatar
Al Viro committed
330
					  umode_t mode,
Linus Torvalds's avatar
Linus Torvalds committed
331 332 333 334
					  nlink_t nlink)
{
	struct proc_dir_entry *ent = NULL;
	const char *fn = name;
335
	unsigned int len;
Linus Torvalds's avatar
Linus Torvalds committed
336 337

	/* make sure name is valid */
338 339
	if (!name || !strlen(name))
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
340

341
	if (xlate_proc_name(name, parent, &fn) != 0)
Linus Torvalds's avatar
Linus Torvalds committed
342 343 344 345 346 347 348 349
		goto out;

	/* At this point there must not be any '/' characters beyond *fn */
	if (strchr(fn, '/'))
		goto out;

	len = strlen(fn);

350 351 352
	ent = kzalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
	if (!ent)
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
353

354
	memcpy(ent->name, fn, len + 1);
Linus Torvalds's avatar
Linus Torvalds committed
355 356 357
	ent->namelen = len;
	ent->mode = mode;
	ent->nlink = nlink;
358
	atomic_set(&ent->count, 1);
359
	spin_lock_init(&ent->pde_unload_lock);
360
	INIT_LIST_HEAD(&ent->pde_openers);
361
out:
Linus Torvalds's avatar
Linus Torvalds committed
362 363 364 365 366 367 368 369
	return ent;
}

struct proc_dir_entry *proc_symlink(const char *name,
		struct proc_dir_entry *parent, const char *dest)
{
	struct proc_dir_entry *ent;

370
	ent = __proc_create(&parent, name,
Linus Torvalds's avatar
Linus Torvalds committed
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
			  (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);

	if (ent) {
		ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
		if (ent->data) {
			strcpy((char*)ent->data,dest);
			if (proc_register(parent, ent) < 0) {
				kfree(ent->data);
				kfree(ent);
				ent = NULL;
			}
		} else {
			kfree(ent);
			ent = NULL;
		}
	}
	return ent;
}
Helight.Xu's avatar
Helight.Xu committed
389
EXPORT_SYMBOL(proc_symlink);
Linus Torvalds's avatar
Linus Torvalds committed
390

391 392
struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
		struct proc_dir_entry *parent, void *data)
Linus Torvalds's avatar
Linus Torvalds committed
393 394 395
{
	struct proc_dir_entry *ent;

396 397 398
	if (mode == 0)
		mode = S_IRUGO | S_IXUGO;

399
	ent = __proc_create(&parent, name, S_IFDIR | mode, 2);
Linus Torvalds's avatar
Linus Torvalds committed
400
	if (ent) {
401
		ent->data = data;
Linus Torvalds's avatar
Linus Torvalds committed
402 403 404 405 406 407 408
		if (proc_register(parent, ent) < 0) {
			kfree(ent);
			ent = NULL;
		}
	}
	return ent;
}
409
EXPORT_SYMBOL_GPL(proc_mkdir_data);
Linus Torvalds's avatar
Linus Torvalds committed
410

411 412
struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
				       struct proc_dir_entry *parent)
413
{
414
	return proc_mkdir_data(name, mode, parent, NULL);
415
}
416
EXPORT_SYMBOL(proc_mkdir_mode);
417

Linus Torvalds's avatar
Linus Torvalds committed
418 419 420
struct proc_dir_entry *proc_mkdir(const char *name,
		struct proc_dir_entry *parent)
{
421
	return proc_mkdir_data(name, 0, parent, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
422
}
Helight.Xu's avatar
Helight.Xu committed
423
EXPORT_SYMBOL(proc_mkdir);
Linus Torvalds's avatar
Linus Torvalds committed
424

Al Viro's avatar
Al Viro committed
425
struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
426 427 428
					struct proc_dir_entry *parent,
					const struct file_operations *proc_fops,
					void *data)
429 430
{
	struct proc_dir_entry *pde;
431 432
	if ((mode & S_IFMT) == 0)
		mode |= S_IFREG;
433

434 435 436
	if (!S_ISREG(mode)) {
		WARN_ON(1);	/* use proc_mkdir() */
		return NULL;
437 438
	}

439 440 441
	if ((mode & S_IALLUGO) == 0)
		mode |= S_IRUGO;
	pde = __proc_create(&parent, name, mode, 1);
442 443 444
	if (!pde)
		goto out;
	pde->proc_fops = proc_fops;
445
	pde->data = data;
446 447 448 449 450 451 452 453
	if (proc_register(parent, pde) < 0)
		goto out_free;
	return pde;
out_free:
	kfree(pde);
out:
	return NULL;
}
Helight.Xu's avatar
Helight.Xu committed
454
EXPORT_SYMBOL(proc_create_data);
455 456 457 458 459 460 461 462 463 464 465 466 467
 
void proc_set_size(struct proc_dir_entry *de, loff_t size)
{
	de->size = size;
}
EXPORT_SYMBOL(proc_set_size);

void proc_set_user(struct proc_dir_entry *de, kuid_t uid, kgid_t gid)
{
	de->uid = uid;
	de->gid = gid;
}
EXPORT_SYMBOL(proc_set_user);
468

469
static void free_proc_entry(struct proc_dir_entry *de)
Linus Torvalds's avatar
Linus Torvalds committed
470
{
471
	proc_free_inum(de->low_ino);
Linus Torvalds's avatar
Linus Torvalds committed
472

473
	if (S_ISLNK(de->mode))
Linus Torvalds's avatar
Linus Torvalds committed
474 475 476 477
		kfree(de->data);
	kfree(de);
}

478 479 480 481 482 483
void pde_put(struct proc_dir_entry *pde)
{
	if (atomic_dec_and_test(&pde->count))
		free_proc_entry(pde);
}

484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
/*
 * Remove a /proc entry and free it if it's not currently in use.
 */
void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
{
	struct proc_dir_entry **p;
	struct proc_dir_entry *de = NULL;
	const char *fn = name;
	unsigned int len;

	spin_lock(&proc_subdir_lock);
	if (__xlate_proc_name(name, &parent, &fn) != 0) {
		spin_unlock(&proc_subdir_lock);
		return;
	}
	len = strlen(fn);

	for (p = &parent->subdir; *p; p=&(*p)->next ) {
		if (proc_match(len, fn, *p)) {
			de = *p;
			*p = de->next;
			de->next = NULL;
			break;
		}
	}
	spin_unlock(&proc_subdir_lock);
	if (!de) {
		WARN(1, "name '%s'\n", name);
		return;
	}

515
	proc_entry_rundown(de);
516

517 518 519
	if (S_ISDIR(de->mode))
		parent->nlink--;
	de->nlink = 0;
520 521 522
	WARN(de->subdir, "%s: removing non-empty directory "
			 "'%s/%s', leaking at least '%s'\n", __func__,
			 de->parent->name, de->name, de->subdir->name);
523
	pde_put(de);
Linus Torvalds's avatar
Linus Torvalds committed
524
}
Helight.Xu's avatar
Helight.Xu committed
525
EXPORT_SYMBOL(remove_proc_entry);
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563

int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
{
	struct proc_dir_entry **p;
	struct proc_dir_entry *root = NULL, *de, *next;
	const char *fn = name;
	unsigned int len;

	spin_lock(&proc_subdir_lock);
	if (__xlate_proc_name(name, &parent, &fn) != 0) {
		spin_unlock(&proc_subdir_lock);
		return -ENOENT;
	}
	len = strlen(fn);

	for (p = &parent->subdir; *p; p=&(*p)->next ) {
		if (proc_match(len, fn, *p)) {
			root = *p;
			*p = root->next;
			root->next = NULL;
			break;
		}
	}
	if (!root) {
		spin_unlock(&proc_subdir_lock);
		return -ENOENT;
	}
	de = root;
	while (1) {
		next = de->subdir;
		if (next) {
			de->subdir = next->next;
			next->next = NULL;
			de = next;
			continue;
		}
		spin_unlock(&proc_subdir_lock);

564
		proc_entry_rundown(de);
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
		next = de->parent;
		if (S_ISDIR(de->mode))
			next->nlink--;
		de->nlink = 0;
		if (de == root)
			break;
		pde_put(de);

		spin_lock(&proc_subdir_lock);
		de = next;
	}
	pde_put(root);
	return 0;
}
EXPORT_SYMBOL(remove_proc_subtree);
580 581 582 583 584 585 586

void *proc_get_parent_data(const struct inode *inode)
{
	struct proc_dir_entry *de = PDE(inode);
	return de->parent->data;
}
EXPORT_SYMBOL_GPL(proc_get_parent_data);
587 588 589 590 591 592 593

void proc_remove(struct proc_dir_entry *de)
{
	if (de)
		remove_proc_subtree(de->name, de->parent);
}
EXPORT_SYMBOL(proc_remove);
594 595 596 597 598 599

void *PDE_DATA(const struct inode *inode)
{
	return __PDE_DATA(inode);
}
EXPORT_SYMBOL(PDE_DATA);