inode.c 15.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* -*- linux-c -*- --------------------------------------------------------- *
 *
 * linux/fs/devpts/inode.c
 *
 *  Copyright 1998-2004 H. Peter Anvin -- All Rights Reserved
 *
 * This file is part of the Linux kernel and is made available under
 * the terms of the GNU General Public License, version 2, or at your
 * option, any later version, incorporated herein by reference.
 *
 * ------------------------------------------------------------------------- */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/namei.h>
18
#include <linux/slab.h>
L
Linus Torvalds 已提交
19 20
#include <linux/mount.h>
#include <linux/tty.h>
21
#include <linux/mutex.h>
N
Nick Black 已提交
22
#include <linux/magic.h>
23
#include <linux/idr.h>
L
Linus Torvalds 已提交
24
#include <linux/devpts_fs.h>
25
#include <linux/parser.h>
26
#include <linux/fsnotify.h>
M
Miklos Szeredi 已提交
27
#include <linux/seq_file.h>
L
Linus Torvalds 已提交
28

M
Miklos Szeredi 已提交
29
#define DEVPTS_DEFAULT_MODE 0600
S
Sukadev Bhattiprolu 已提交
30 31 32 33 34 35 36
/*
 * ptmx is a new node in /dev/pts and will be unused in legacy (single-
 * instance) mode. To prevent surprises in user space, set permissions of
 * ptmx to 0. Use 'chmod' or remount with '-o ptmxmode' to set meaningful
 * permissions.
 */
#define DEVPTS_DEFAULT_PTMX_MODE 0000
S
Sukadev Bhattiprolu 已提交
37
#define PTMX_MINOR	2
M
Miklos Szeredi 已提交
38

39 40 41 42 43
/*
 * sysctl support for setting limits on the number of Unix98 ptys allocated.
 * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
 */
static int pty_limit = NR_UNIX98_PTY_DEFAULT;
44
static int pty_reserve = NR_UNIX98_PTY_RESERVE;
45
static int pty_limit_min;
46
static int pty_limit_max = INT_MAX;
47 48 49 50 51 52 53 54 55 56 57
static int pty_count;

static struct ctl_table pty_table[] = {
	{
		.procname	= "max",
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.data		= &pty_limit,
		.proc_handler	= proc_dointvec_minmax,
		.extra1		= &pty_limit_min,
		.extra2		= &pty_limit_max,
58 59 60 61 62 63 64 65
	}, {
		.procname	= "reserve",
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.data		= &pty_reserve,
		.proc_handler	= proc_dointvec_minmax,
		.extra1		= &pty_limit_min,
		.extra2		= &pty_limit_max,
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
	}, {
		.procname	= "nr",
		.maxlen		= sizeof(int),
		.mode		= 0444,
		.data		= &pty_count,
		.proc_handler	= proc_dointvec,
	},
	{}
};

static struct ctl_table pty_kern_table[] = {
	{
		.procname	= "pty",
		.mode		= 0555,
		.child		= pty_table,
	},
	{}
};

static struct ctl_table pty_root_table[] = {
	{
		.procname	= "kernel",
		.mode		= 0555,
		.child		= pty_kern_table,
	},
	{}
};

94 95
static DEFINE_MUTEX(allocated_ptys_lock);

L
Linus Torvalds 已提交
96 97
static struct vfsmount *devpts_mnt;

S
Sukadev Bhattiprolu 已提交
98
struct pts_mount_opts {
L
Linus Torvalds 已提交
99 100 101 102 103
	int setuid;
	int setgid;
	uid_t   uid;
	gid_t   gid;
	umode_t mode;
S
Sukadev Bhattiprolu 已提交
104
	umode_t ptmxmode;
105
	int newinstance;
106
	int max;
S
Sukadev Bhattiprolu 已提交
107
};
L
Linus Torvalds 已提交
108

109
enum {
110
	Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance,  Opt_max,
111 112 113
	Opt_err
};

114
static const match_table_t tokens = {
115 116 117
	{Opt_uid, "uid=%u"},
	{Opt_gid, "gid=%u"},
	{Opt_mode, "mode=%o"},
S
Sukadev Bhattiprolu 已提交
118 119
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
	{Opt_ptmxmode, "ptmxmode=%o"},
120
	{Opt_newinstance, "newinstance"},
121
	{Opt_max, "max=%d"},
S
Sukadev Bhattiprolu 已提交
122
#endif
123 124 125
	{Opt_err, NULL}
};

S
Sukadev Bhattiprolu 已提交
126 127
struct pts_fs_info {
	struct ida allocated_ptys;
S
Sukadev Bhattiprolu 已提交
128
	struct pts_mount_opts mount_opts;
S
Sukadev Bhattiprolu 已提交
129
	struct dentry *ptmx_dentry;
S
Sukadev Bhattiprolu 已提交
130 131 132 133 134 135 136
};

static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb)
{
	return sb->s_fs_info;
}

S
Sukadev Bhattiprolu 已提交
137 138
static inline struct super_block *pts_sb_from_inode(struct inode *inode)
{
139
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
S
Sukadev Bhattiprolu 已提交
140 141
	if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
		return inode->i_sb;
142
#endif
S
Sukadev Bhattiprolu 已提交
143 144 145
	return devpts_mnt->mnt_sb;
}

146 147 148
#define PARSE_MOUNT	0
#define PARSE_REMOUNT	1

149 150 151 152 153 154 155 156 157
/*
 * parse_mount_options():
 * 	Set @opts to mount options specified in @data. If an option is not
 * 	specified in @data, set it to its default value. The exception is
 * 	'newinstance' option which can only be set/cleared on a mount (i.e.
 * 	cannot be changed during remount).
 *
 * Note: @data may be NULL (in which case all options are set to default).
 */
158
static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
L
Linus Torvalds 已提交
159
{
160 161
	char *p;

S
Sukadev Bhattiprolu 已提交
162 163 164 165 166
	opts->setuid  = 0;
	opts->setgid  = 0;
	opts->uid     = 0;
	opts->gid     = 0;
	opts->mode    = DEVPTS_DEFAULT_MODE;
S
Sukadev Bhattiprolu 已提交
167
	opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
168
	opts->max     = NR_UNIX98_PTY_MAX;
169

170 171 172 173
	/* newinstance makes sense only on initial mount */
	if (op == PARSE_MOUNT)
		opts->newinstance = 0;

174 175 176 177 178 179
	while ((p = strsep(&data, ",")) != NULL) {
		substring_t args[MAX_OPT_ARGS];
		int token;
		int option;

		if (!*p)
L
Linus Torvalds 已提交
180
			continue;
181 182 183 184 185 186

		token = match_token(p, tokens, args);
		switch (token) {
		case Opt_uid:
			if (match_int(&args[0], &option))
				return -EINVAL;
S
Sukadev Bhattiprolu 已提交
187 188
			opts->uid = option;
			opts->setuid = 1;
189 190 191 192
			break;
		case Opt_gid:
			if (match_int(&args[0], &option))
				return -EINVAL;
S
Sukadev Bhattiprolu 已提交
193 194
			opts->gid = option;
			opts->setgid = 1;
195 196 197 198
			break;
		case Opt_mode:
			if (match_octal(&args[0], &option))
				return -EINVAL;
S
Sukadev Bhattiprolu 已提交
199
			opts->mode = option & S_IALLUGO;
200
			break;
S
Sukadev Bhattiprolu 已提交
201 202 203 204 205 206
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
		case Opt_ptmxmode:
			if (match_octal(&args[0], &option))
				return -EINVAL;
			opts->ptmxmode = option & S_IALLUGO;
			break;
207 208 209 210 211
		case Opt_newinstance:
			/* newinstance makes sense only on initial mount */
			if (op == PARSE_MOUNT)
				opts->newinstance = 1;
			break;
212 213 214 215 216 217
		case Opt_max:
			if (match_int(&args[0], &option) ||
			    option < 0 || option > NR_UNIX98_PTY_MAX)
				return -EINVAL;
			opts->max = option;
			break;
S
Sukadev Bhattiprolu 已提交
218
#endif
219 220
		default:
			printk(KERN_ERR "devpts: called with bogus options\n");
L
Linus Torvalds 已提交
221 222 223 224 225 226 227
			return -EINVAL;
		}
	}

	return 0;
}

S
Sukadev Bhattiprolu 已提交
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
static int mknod_ptmx(struct super_block *sb)
{
	int mode;
	int rc = -ENOMEM;
	struct dentry *dentry;
	struct inode *inode;
	struct dentry *root = sb->s_root;
	struct pts_fs_info *fsi = DEVPTS_SB(sb);
	struct pts_mount_opts *opts = &fsi->mount_opts;

	mutex_lock(&root->d_inode->i_mutex);

	/* If we have already created ptmx node, return */
	if (fsi->ptmx_dentry) {
		rc = 0;
		goto out;
	}

	dentry = d_alloc_name(root, "ptmx");
	if (!dentry) {
		printk(KERN_NOTICE "Unable to alloc dentry for ptmx node\n");
		goto out;
	}

	/*
	 * Create a new 'ptmx' node in this mount of devpts.
	 */
	inode = new_inode(sb);
	if (!inode) {
		printk(KERN_ERR "Unable to alloc inode for ptmx node\n");
		dput(dentry);
		goto out;
	}

	inode->i_ino = 2;
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;

	mode = S_IFCHR|opts->ptmxmode;
	init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2));

	d_add(dentry, inode);

	fsi->ptmx_dentry = dentry;
	rc = 0;
out:
	mutex_unlock(&root->d_inode->i_mutex);
	return rc;
}

static void update_ptmx_mode(struct pts_fs_info *fsi)
{
	struct inode *inode;
	if (fsi->ptmx_dentry) {
		inode = fsi->ptmx_dentry->d_inode;
		inode->i_mode = S_IFCHR|fsi->mount_opts.ptmxmode;
	}
}
#else
static inline void update_ptmx_mode(struct pts_fs_info *fsi)
{
       return;
}
#endif

293 294
static int devpts_remount(struct super_block *sb, int *flags, char *data)
{
S
Sukadev Bhattiprolu 已提交
295
	int err;
296 297 298
	struct pts_fs_info *fsi = DEVPTS_SB(sb);
	struct pts_mount_opts *opts = &fsi->mount_opts;

299
	err = parse_mount_options(data, PARSE_REMOUNT, opts);
S
Sukadev Bhattiprolu 已提交
300 301 302 303 304 305 306 307 308 309

	/*
	 * parse_mount_options() restores options to default values
	 * before parsing and may have changed ptmxmode. So, update the
	 * mode in the inode too. Bogus options don't fail the remount,
	 * so do this even on error return.
	 */
	update_ptmx_mode(fsi);

	return err;
310 311
}

312
static int devpts_show_options(struct seq_file *seq, struct dentry *root)
M
Miklos Szeredi 已提交
313
{
314
	struct pts_fs_info *fsi = DEVPTS_SB(root->d_sb);
S
Sukadev Bhattiprolu 已提交
315 316 317 318 319 320 321
	struct pts_mount_opts *opts = &fsi->mount_opts;

	if (opts->setuid)
		seq_printf(seq, ",uid=%u", opts->uid);
	if (opts->setgid)
		seq_printf(seq, ",gid=%u", opts->gid);
	seq_printf(seq, ",mode=%03o", opts->mode);
S
Sukadev Bhattiprolu 已提交
322 323
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
	seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode);
324 325
	if (opts->max < NR_UNIX98_PTY_MAX)
		seq_printf(seq, ",max=%d", opts->max);
S
Sukadev Bhattiprolu 已提交
326
#endif
M
Miklos Szeredi 已提交
327 328 329 330

	return 0;
}

331
static const struct super_operations devpts_sops = {
L
Linus Torvalds 已提交
332 333
	.statfs		= simple_statfs,
	.remount_fs	= devpts_remount,
M
Miklos Szeredi 已提交
334
	.show_options	= devpts_show_options,
L
Linus Torvalds 已提交
335 336
};

S
Sukadev Bhattiprolu 已提交
337 338 339 340 341 342 343 344 345
static void *new_pts_fs_info(void)
{
	struct pts_fs_info *fsi;

	fsi = kzalloc(sizeof(struct pts_fs_info), GFP_KERNEL);
	if (!fsi)
		return NULL;

	ida_init(&fsi->allocated_ptys);
S
Sukadev Bhattiprolu 已提交
346
	fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE;
S
Sukadev Bhattiprolu 已提交
347
	fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
S
Sukadev Bhattiprolu 已提交
348 349 350 351

	return fsi;
}

L
Linus Torvalds 已提交
352 353 354
static int
devpts_fill_super(struct super_block *s, void *data, int silent)
{
S
Sukadev Bhattiprolu 已提交
355
	struct inode *inode;
L
Linus Torvalds 已提交
356 357 358 359 360 361 362

	s->s_blocksize = 1024;
	s->s_blocksize_bits = 10;
	s->s_magic = DEVPTS_SUPER_MAGIC;
	s->s_op = &devpts_sops;
	s->s_time_gran = 1;

S
Sukadev Bhattiprolu 已提交
363 364 365 366
	s->s_fs_info = new_pts_fs_info();
	if (!s->s_fs_info)
		goto fail;

L
Linus Torvalds 已提交
367 368
	inode = new_inode(s);
	if (!inode)
369
		goto fail;
L
Linus Torvalds 已提交
370 371 372 373 374
	inode->i_ino = 1;
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
	inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
	inode->i_op = &simple_dir_inode_operations;
	inode->i_fop = &simple_dir_operations;
M
Miklos Szeredi 已提交
375
	set_nlink(inode, 2);
L
Linus Torvalds 已提交
376

377
	s->s_root = d_make_root(inode);
L
Linus Torvalds 已提交
378 379
	if (s->s_root)
		return 0;
S
Sukadev Bhattiprolu 已提交
380

A
Alan Cox 已提交
381
	printk(KERN_ERR "devpts: get root dentry failed\n");
S
Sukadev Bhattiprolu 已提交
382

L
Linus Torvalds 已提交
383 384 385 386
fail:
	return -ENOMEM;
}

387
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
S
Sukadev Bhattiprolu 已提交
388 389 390 391
static int compare_init_pts_sb(struct super_block *s, void *p)
{
	if (devpts_mnt)
		return devpts_mnt->mnt_sb == s;
392 393 394 395
	return 0;
}

/*
A
Al Viro 已提交
396
 * devpts_mount()
397 398 399 400 401 402 403 404
 *
 *     If the '-o newinstance' mount option was specified, mount a new
 *     (private) instance of devpts.  PTYs created in this instance are
 *     independent of the PTYs in other devpts instances.
 *
 *     If the '-o newinstance' option was not specified, mount/remount the
 *     initial kernel mount of devpts.  This type of mount gives the
 *     legacy, single-instance semantics.
S
Sukadev Bhattiprolu 已提交
405
 *
406 407 408 409
 *     The 'newinstance' option is needed to support multiple namespace
 *     semantics in devpts while preserving backward compatibility of the
 *     current 'single-namespace' semantics. i.e all mounts of devpts
 *     without the 'newinstance' mount option should bind to the initial
A
Al Viro 已提交
410
 *     kernel mount, like mount_single().
S
Sukadev Bhattiprolu 已提交
411
 *
412
 *     Mounts with 'newinstance' option create a new, private namespace.
S
Sukadev Bhattiprolu 已提交
413
 *
414
 *     NOTE:
S
Sukadev Bhattiprolu 已提交
415
 *
A
Al Viro 已提交
416 417
 *     For single-mount semantics, devpts cannot use mount_single(),
 *     because mount_single()/sget() find and use the super-block from
S
Sukadev Bhattiprolu 已提交
418
 *     the most recent mount of devpts. But that recent mount may be a
A
Al Viro 已提交
419
 *     'newinstance' mount and mount_single() would pick the newinstance
S
Sukadev Bhattiprolu 已提交
420 421
 *     super-block instead of the initial super-block.
 */
A
Al Viro 已提交
422 423
static struct dentry *devpts_mount(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data)
L
Linus Torvalds 已提交
424
{
425 426
	int error;
	struct pts_mount_opts opts;
427
	struct super_block *s;
428

429 430
	error = parse_mount_options(data, PARSE_MOUNT, &opts);
	if (error)
A
Al Viro 已提交
431
		return ERR_PTR(error);
432

433
	if (opts.newinstance)
434
		s = sget(fs_type, NULL, set_anon_super, NULL);
435
	else
436
		s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL);
437

438
	if (IS_ERR(s))
A
Al Viro 已提交
439
		return ERR_CAST(s);
440 441 442 443 444 445 446 447 448 449

	if (!s->s_root) {
		s->s_flags = flags;
		error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
		if (error)
			goto out_undo_sget;
		s->s_flags |= MS_ACTIVE;
	}

	memcpy(&(DEVPTS_SB(s))->mount_opts, &opts, sizeof(opts));
450

451
	error = mknod_ptmx(s);
452
	if (error)
A
Al Viro 已提交
453
		goto out_undo_sget;
454

A
Al Viro 已提交
455
	return dget(s->s_root);
456 457

out_undo_sget:
458
	deactivate_locked_super(s);
A
Al Viro 已提交
459
	return ERR_PTR(error);
L
Linus Torvalds 已提交
460
}
461

462 463 464 465 466
#else
/*
 * This supports only the legacy single-instance semantics (no
 * multiple-instance semantics)
 */
A
Al Viro 已提交
467 468
static struct dentry *devpts_mount(struct file_system_type *fs_type, int flags,
		const char *dev_name, void *data)
469
{
A
Al Viro 已提交
470
	return mount_single(fs_type, flags, data, devpts_fill_super);
471 472
}
#endif
L
Linus Torvalds 已提交
473

S
Sukadev Bhattiprolu 已提交
474 475 476 477 478
static void devpts_kill_sb(struct super_block *sb)
{
	struct pts_fs_info *fsi = DEVPTS_SB(sb);

	kfree(fsi);
S
Sukadev Bhattiprolu 已提交
479
	kill_litter_super(sb);
S
Sukadev Bhattiprolu 已提交
480 481
}

L
Linus Torvalds 已提交
482 483
static struct file_system_type devpts_fs_type = {
	.name		= "devpts",
A
Al Viro 已提交
484
	.mount		= devpts_mount,
S
Sukadev Bhattiprolu 已提交
485
	.kill_sb	= devpts_kill_sb,
L
Linus Torvalds 已提交
486 487 488 489 490 491 492
};

/*
 * The normal naming convention is simply /dev/pts/<number>; this conforms
 * to the System V naming convention
 */

493
int devpts_new_index(struct inode *ptmx_inode)
494
{
S
Sukadev Bhattiprolu 已提交
495 496
	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
	struct pts_fs_info *fsi = DEVPTS_SB(sb);
497
	int index;
A
Alexey Dobriyan 已提交
498
	int ida_ret;
499 500

retry:
A
Alan Cox 已提交
501
	if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL))
502 503 504
		return -ENOMEM;

	mutex_lock(&allocated_ptys_lock);
505 506 507 508 509 510
	if (pty_count >= pty_limit -
			(fsi->mount_opts.newinstance ? pty_reserve : 0)) {
		mutex_unlock(&allocated_ptys_lock);
		return -ENOSPC;
	}

S
Sukadev Bhattiprolu 已提交
511
	ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
A
Alexey Dobriyan 已提交
512
	if (ida_ret < 0) {
513
		mutex_unlock(&allocated_ptys_lock);
A
Alexey Dobriyan 已提交
514
		if (ida_ret == -EAGAIN)
515 516 517 518
			goto retry;
		return -EIO;
	}

519
	if (index >= fsi->mount_opts.max) {
S
Sukadev Bhattiprolu 已提交
520
		ida_remove(&fsi->allocated_ptys, index);
521
		mutex_unlock(&allocated_ptys_lock);
522
		return -ENOSPC;
523
	}
524
	pty_count++;
525 526 527 528
	mutex_unlock(&allocated_ptys_lock);
	return index;
}

529
void devpts_kill_index(struct inode *ptmx_inode, int idx)
530
{
S
Sukadev Bhattiprolu 已提交
531 532 533
	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
	struct pts_fs_info *fsi = DEVPTS_SB(sb);

534
	mutex_lock(&allocated_ptys_lock);
S
Sukadev Bhattiprolu 已提交
535
	ida_remove(&fsi->allocated_ptys, idx);
536
	pty_count--;
537 538 539
	mutex_unlock(&allocated_ptys_lock);
}

540
int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
L
Linus Torvalds 已提交
541
{
A
Alan Cox 已提交
542 543
	/* tty layer puts index from devpts_new_index() in here */
	int number = tty->index;
L
Linus Torvalds 已提交
544 545 546
	struct tty_driver *driver = tty->driver;
	dev_t device = MKDEV(driver->major, driver->minor_start+number);
	struct dentry *dentry;
S
Sukadev Bhattiprolu 已提交
547 548 549
	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
	struct inode *inode = new_inode(sb);
	struct dentry *root = sb->s_root;
S
Sukadev Bhattiprolu 已提交
550 551
	struct pts_fs_info *fsi = DEVPTS_SB(sb);
	struct pts_mount_opts *opts = &fsi->mount_opts;
552
	int ret = 0;
S
Sukadev Bhattiprolu 已提交
553
	char s[12];
L
Linus Torvalds 已提交
554 555 556 557 558 559 560 561

	/* We're supposed to be given the slave end of a pty */
	BUG_ON(driver->type != TTY_DRIVER_TYPE_PTY);
	BUG_ON(driver->subtype != PTY_TYPE_SLAVE);

	if (!inode)
		return -ENOMEM;

562 563 564
	inode->i_ino = number + 3;
	inode->i_uid = opts->setuid ? opts->uid : current_fsuid();
	inode->i_gid = opts->setgid ? opts->gid : current_fsgid();
L
Linus Torvalds 已提交
565
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
S
Sukadev Bhattiprolu 已提交
566
	init_special_inode(inode, S_IFCHR|opts->mode, device);
567
	inode->i_private = tty;
S
Sukadev Bhattiprolu 已提交
568
	tty->driver_data = inode;
L
Linus Torvalds 已提交
569

S
Sukadev Bhattiprolu 已提交
570 571
	sprintf(s, "%d", number);

S
Sukadev Bhattiprolu 已提交
572
	mutex_lock(&root->d_inode->i_mutex);
S
Sukadev Bhattiprolu 已提交
573

S
Sukadev Bhattiprolu 已提交
574
	dentry = d_alloc_name(root, s);
575
	if (dentry) {
S
Sukadev Bhattiprolu 已提交
576
		d_add(dentry, inode);
S
Sukadev Bhattiprolu 已提交
577
		fsnotify_create(root->d_inode, dentry);
578 579 580
	} else {
		iput(inode);
		ret = -ENOMEM;
581
	}
L
Linus Torvalds 已提交
582

S
Sukadev Bhattiprolu 已提交
583
	mutex_unlock(&root->d_inode->i_mutex);
L
Linus Torvalds 已提交
584

585
	return ret;
L
Linus Torvalds 已提交
586 587
}

588
struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number)
L
Linus Torvalds 已提交
589
{
590 591 592
	struct dentry *dentry;
	struct tty_struct *tty;

S
Sukadev Bhattiprolu 已提交
593
	BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
L
Linus Torvalds 已提交
594

595 596 597 598 599 600
	/* Ensure dentry has not been deleted by devpts_pty_kill() */
	dentry = d_find_alias(pts_inode);
	if (!dentry)
		return NULL;

	tty = NULL;
S
Sukadev Bhattiprolu 已提交
601
	if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
602 603 604 605 606
		tty = (struct tty_struct *)pts_inode->i_private;

	dput(dentry);

	return tty;
L
Linus Torvalds 已提交
607 608
}

609
void devpts_pty_kill(struct tty_struct *tty)
L
Linus Torvalds 已提交
610
{
S
Sukadev Bhattiprolu 已提交
611
	struct inode *inode = tty->driver_data;
S
Sukadev Bhattiprolu 已提交
612 613
	struct super_block *sb = pts_sb_from_inode(inode);
	struct dentry *root = sb->s_root;
S
Sukadev Bhattiprolu 已提交
614
	struct dentry *dentry;
L
Linus Torvalds 已提交
615

S
Sukadev Bhattiprolu 已提交
616 617
	BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));

S
Sukadev Bhattiprolu 已提交
618
	mutex_lock(&root->d_inode->i_mutex);
S
Sukadev Bhattiprolu 已提交
619 620 621

	dentry = d_find_alias(inode);

622
	drop_nlink(inode);
623 624
	d_delete(dentry);
	dput(dentry);	/* d_alloc_name() in devpts_pty_new() */
A
Alan Cox 已提交
625
	dput(dentry);		/* d_find_alias above */
626

S
Sukadev Bhattiprolu 已提交
627
	mutex_unlock(&root->d_inode->i_mutex);
L
Linus Torvalds 已提交
628 629 630 631 632
}

static int __init init_devpts_fs(void)
{
	int err = register_filesystem(&devpts_fs_type);
633 634
	struct ctl_table_header *table;

L
Linus Torvalds 已提交
635
	if (!err) {
636
		table = register_sysctl_table(pty_root_table);
L
Linus Torvalds 已提交
637
		devpts_mnt = kern_mount(&devpts_fs_type);
638
		if (IS_ERR(devpts_mnt)) {
L
Linus Torvalds 已提交
639
			err = PTR_ERR(devpts_mnt);
640
			unregister_filesystem(&devpts_fs_type);
641
			unregister_sysctl_table(table);
642
		}
L
Linus Torvalds 已提交
643 644 645 646
	}
	return err;
}
module_init(init_devpts_fs)