inode.c 15.1 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
	int setuid;
	int setgid;
101 102
	kuid_t   uid;
	kgid_t   gid;
L
Linus Torvalds 已提交
103
	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
	char *p;
161 162
	kuid_t uid;
	kgid_t gid;
163

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

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

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

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

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

	return 0;
}

S
Sukadev Bhattiprolu 已提交
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 293 294 295 296 297 298 299 300
#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

301 302
static int devpts_remount(struct super_block *sb, int *flags, char *data)
{
S
Sukadev Bhattiprolu 已提交
303
	int err;
304 305 306
	struct pts_fs_info *fsi = DEVPTS_SB(sb);
	struct pts_mount_opts *opts = &fsi->mount_opts;

307
	err = parse_mount_options(data, PARSE_REMOUNT, opts);
S
Sukadev Bhattiprolu 已提交
308 309 310 311 312 313 314 315 316 317

	/*
	 * 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;
318 319
}

320
static int devpts_show_options(struct seq_file *seq, struct dentry *root)
M
Miklos Szeredi 已提交
321
{
322
	struct pts_fs_info *fsi = DEVPTS_SB(root->d_sb);
S
Sukadev Bhattiprolu 已提交
323 324 325
	struct pts_mount_opts *opts = &fsi->mount_opts;

	if (opts->setuid)
326
		seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, opts->uid));
S
Sukadev Bhattiprolu 已提交
327
	if (opts->setgid)
328
		seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, opts->gid));
S
Sukadev Bhattiprolu 已提交
329
	seq_printf(seq, ",mode=%03o", opts->mode);
S
Sukadev Bhattiprolu 已提交
330 331
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
	seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode);
332 333
	if (opts->max < NR_UNIX98_PTY_MAX)
		seq_printf(seq, ",max=%d", opts->max);
S
Sukadev Bhattiprolu 已提交
334
#endif
M
Miklos Szeredi 已提交
335 336 337 338

	return 0;
}

339
static const struct super_operations devpts_sops = {
L
Linus Torvalds 已提交
340 341
	.statfs		= simple_statfs,
	.remount_fs	= devpts_remount,
M
Miklos Szeredi 已提交
342
	.show_options	= devpts_show_options,
L
Linus Torvalds 已提交
343 344
};

S
Sukadev Bhattiprolu 已提交
345 346 347 348 349 350 351 352 353
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 已提交
354
	fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE;
S
Sukadev Bhattiprolu 已提交
355
	fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
S
Sukadev Bhattiprolu 已提交
356 357 358 359

	return fsi;
}

L
Linus Torvalds 已提交
360 361 362
static int
devpts_fill_super(struct super_block *s, void *data, int silent)
{
S
Sukadev Bhattiprolu 已提交
363
	struct inode *inode;
L
Linus Torvalds 已提交
364 365 366 367 368 369 370

	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 已提交
371 372 373 374
	s->s_fs_info = new_pts_fs_info();
	if (!s->s_fs_info)
		goto fail;

L
Linus Torvalds 已提交
375 376
	inode = new_inode(s);
	if (!inode)
377
		goto fail;
L
Linus Torvalds 已提交
378 379 380 381 382
	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 已提交
383
	set_nlink(inode, 2);
L
Linus Torvalds 已提交
384

385
	s->s_root = d_make_root(inode);
L
Linus Torvalds 已提交
386 387
	if (s->s_root)
		return 0;
S
Sukadev Bhattiprolu 已提交
388

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

L
Linus Torvalds 已提交
391 392 393 394
fail:
	return -ENOMEM;
}

395
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
S
Sukadev Bhattiprolu 已提交
396 397 398 399
static int compare_init_pts_sb(struct super_block *s, void *p)
{
	if (devpts_mnt)
		return devpts_mnt->mnt_sb == s;
400 401 402 403
	return 0;
}

/*
A
Al Viro 已提交
404
 * devpts_mount()
405 406 407 408 409 410 411 412
 *
 *     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 已提交
413
 *
414 415 416 417
 *     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 已提交
418
 *     kernel mount, like mount_single().
S
Sukadev Bhattiprolu 已提交
419
 *
420
 *     Mounts with 'newinstance' option create a new, private namespace.
S
Sukadev Bhattiprolu 已提交
421
 *
422
 *     NOTE:
S
Sukadev Bhattiprolu 已提交
423
 *
A
Al Viro 已提交
424 425
 *     For single-mount semantics, devpts cannot use mount_single(),
 *     because mount_single()/sget() find and use the super-block from
S
Sukadev Bhattiprolu 已提交
426
 *     the most recent mount of devpts. But that recent mount may be a
A
Al Viro 已提交
427
 *     'newinstance' mount and mount_single() would pick the newinstance
S
Sukadev Bhattiprolu 已提交
428 429
 *     super-block instead of the initial super-block.
 */
A
Al Viro 已提交
430 431
static struct dentry *devpts_mount(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data)
L
Linus Torvalds 已提交
432
{
433 434
	int error;
	struct pts_mount_opts opts;
435
	struct super_block *s;
436

437 438
	error = parse_mount_options(data, PARSE_MOUNT, &opts);
	if (error)
A
Al Viro 已提交
439
		return ERR_PTR(error);
440

441
	if (opts.newinstance)
D
David Howells 已提交
442
		s = sget(fs_type, NULL, set_anon_super, flags, NULL);
443
	else
D
David Howells 已提交
444 445
		s = sget(fs_type, compare_init_pts_sb, set_anon_super, flags,
			 NULL);
446

447
	if (IS_ERR(s))
A
Al Viro 已提交
448
		return ERR_CAST(s);
449 450 451 452 453 454 455 456 457

	if (!s->s_root) {
		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));
458

459
	error = mknod_ptmx(s);
460
	if (error)
A
Al Viro 已提交
461
		goto out_undo_sget;
462

A
Al Viro 已提交
463
	return dget(s->s_root);
464 465

out_undo_sget:
466
	deactivate_locked_super(s);
A
Al Viro 已提交
467
	return ERR_PTR(error);
L
Linus Torvalds 已提交
468
}
469

470 471 472 473 474
#else
/*
 * This supports only the legacy single-instance semantics (no
 * multiple-instance semantics)
 */
A
Al Viro 已提交
475 476
static struct dentry *devpts_mount(struct file_system_type *fs_type, int flags,
		const char *dev_name, void *data)
477
{
A
Al Viro 已提交
478
	return mount_single(fs_type, flags, data, devpts_fill_super);
479 480
}
#endif
L
Linus Torvalds 已提交
481

S
Sukadev Bhattiprolu 已提交
482 483 484 485 486
static void devpts_kill_sb(struct super_block *sb)
{
	struct pts_fs_info *fsi = DEVPTS_SB(sb);

	kfree(fsi);
S
Sukadev Bhattiprolu 已提交
487
	kill_litter_super(sb);
S
Sukadev Bhattiprolu 已提交
488 489
}

L
Linus Torvalds 已提交
490 491
static struct file_system_type devpts_fs_type = {
	.name		= "devpts",
A
Al Viro 已提交
492
	.mount		= devpts_mount,
S
Sukadev Bhattiprolu 已提交
493
	.kill_sb	= devpts_kill_sb,
L
Linus Torvalds 已提交
494 495 496 497 498 499 500
};

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

501
int devpts_new_index(struct inode *ptmx_inode)
502
{
S
Sukadev Bhattiprolu 已提交
503 504
	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
	struct pts_fs_info *fsi = DEVPTS_SB(sb);
505
	int index;
A
Alexey Dobriyan 已提交
506
	int ida_ret;
507 508

retry:
A
Alan Cox 已提交
509
	if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL))
510 511 512
		return -ENOMEM;

	mutex_lock(&allocated_ptys_lock);
513 514 515 516 517 518
	if (pty_count >= pty_limit -
			(fsi->mount_opts.newinstance ? pty_reserve : 0)) {
		mutex_unlock(&allocated_ptys_lock);
		return -ENOSPC;
	}

S
Sukadev Bhattiprolu 已提交
519
	ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
A
Alexey Dobriyan 已提交
520
	if (ida_ret < 0) {
521
		mutex_unlock(&allocated_ptys_lock);
A
Alexey Dobriyan 已提交
522
		if (ida_ret == -EAGAIN)
523 524 525 526
			goto retry;
		return -EIO;
	}

527
	if (index >= fsi->mount_opts.max) {
S
Sukadev Bhattiprolu 已提交
528
		ida_remove(&fsi->allocated_ptys, index);
529
		mutex_unlock(&allocated_ptys_lock);
530
		return -ENOSPC;
531
	}
532
	pty_count++;
533 534 535 536
	mutex_unlock(&allocated_ptys_lock);
	return index;
}

537
void devpts_kill_index(struct inode *ptmx_inode, int idx)
538
{
S
Sukadev Bhattiprolu 已提交
539 540 541
	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
	struct pts_fs_info *fsi = DEVPTS_SB(sb);

542
	mutex_lock(&allocated_ptys_lock);
S
Sukadev Bhattiprolu 已提交
543
	ida_remove(&fsi->allocated_ptys, idx);
544
	pty_count--;
545 546 547
	mutex_unlock(&allocated_ptys_lock);
}

J
Jiri Slaby 已提交
548 549
struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
		void *priv)
L
Linus Torvalds 已提交
550 551
{
	struct dentry *dentry;
S
Sukadev Bhattiprolu 已提交
552
	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
553
	struct inode *inode;
S
Sukadev Bhattiprolu 已提交
554
	struct dentry *root = sb->s_root;
S
Sukadev Bhattiprolu 已提交
555 556
	struct pts_fs_info *fsi = DEVPTS_SB(sb);
	struct pts_mount_opts *opts = &fsi->mount_opts;
S
Sukadev Bhattiprolu 已提交
557
	char s[12];
L
Linus Torvalds 已提交
558

559
	inode = new_inode(sb);
L
Linus Torvalds 已提交
560
	if (!inode)
561
		return ERR_PTR(-ENOMEM);
L
Linus Torvalds 已提交
562

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

J
Jiri Slaby 已提交
570
	sprintf(s, "%d", index);
S
Sukadev Bhattiprolu 已提交
571

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
	} else {
		iput(inode);
580
		inode = ERR_PTR(-ENOMEM);
581
	}
L
Linus Torvalds 已提交
582

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

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

588
void *devpts_get_priv(struct inode *pts_inode)
L
Linus Torvalds 已提交
589
{
590
	struct dentry *dentry;
591
	void *priv = NULL;
592

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

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

S
Sukadev Bhattiprolu 已提交
600
	if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
601
		priv = pts_inode->i_private;
602 603 604

	dput(dentry);

605
	return priv;
L
Linus Torvalds 已提交
606 607
}

J
Jiri Slaby 已提交
608
void devpts_pty_kill(struct inode *inode)
L
Linus Torvalds 已提交
609
{
S
Sukadev Bhattiprolu 已提交
610 611
	struct super_block *sb = pts_sb_from_inode(inode);
	struct dentry *root = sb->s_root;
S
Sukadev Bhattiprolu 已提交
612
	struct dentry *dentry;
L
Linus Torvalds 已提交
613

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

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

	dentry = d_find_alias(inode);

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

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

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

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