Commit b4a76faf authored by Al Viro's avatar Al Viro
Browse files

convert devpts



Two kinds of objects there - ptmx and everything else (pty).  The former is
created on mount and kept until the fs shutdown; the latter get created
and removed by tty layer (the references are borrowed into tty->driver_data).
The reference to ptmx dentry is also kept, but we only ever use it to
find ptmx inode on remount.

* turn d_add() into d_make_persistent() + dput()  both in mknod_ptmx() and
in devpts_pty_new().

* turn dput() to d_make_discardable() in devpts_pty_kill().

* switch mknod_ptmx() to simple_{start,done}_creating().

* instead of storing in pts_fs_info a reference to ptmx dentry, store a reference
to its inode, seeing that this is what we use it for.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent b8343156
Loading
Loading
Loading
Loading
+21 −36
Original line number Diff line number Diff line
@@ -102,7 +102,7 @@ struct pts_fs_info {
	struct ida allocated_ptys;
	struct pts_mount_opts mount_opts;
	struct super_block *sb;
	struct dentry *ptmx_dentry;
	struct inode *ptmx_inode; // borrowed
};

static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb)
@@ -259,7 +259,6 @@ static int devpts_parse_param(struct fs_context *fc, struct fs_parameter *param)
static int mknod_ptmx(struct super_block *sb, struct fs_context *fc)
{
	int mode;
	int rc = -ENOMEM;
	struct dentry *dentry;
	struct inode *inode;
	struct dentry *root = sb->s_root;
@@ -268,18 +267,10 @@ static int mknod_ptmx(struct super_block *sb, struct fs_context *fc)
	kuid_t ptmx_uid = current_fsuid();
	kgid_t ptmx_gid = current_fsgid();

	inode_lock(d_inode(root));

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

	dentry = d_alloc_name(root, "ptmx");
	if (!dentry) {
	dentry = simple_start_creating(root, "ptmx");
	if (IS_ERR(dentry)) {
		pr_err("Unable to alloc dentry for ptmx node\n");
		goto out;
		return PTR_ERR(dentry);
	}

	/*
@@ -287,9 +278,9 @@ static int mknod_ptmx(struct super_block *sb, struct fs_context *fc)
	 */
	inode = new_inode(sb);
	if (!inode) {
		simple_done_creating(dentry);
		pr_err("Unable to alloc inode for ptmx node\n");
		dput(dentry);
		goto out;
		return -ENOMEM;
	}

	inode->i_ino = 2;
@@ -299,23 +290,18 @@ static int mknod_ptmx(struct super_block *sb, struct fs_context *fc)
	init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2));
	inode->i_uid = ptmx_uid;
	inode->i_gid = ptmx_gid;
	fsi->ptmx_inode = inode;

	d_add(dentry, inode);
	d_make_persistent(dentry, inode);

	fsi->ptmx_dentry = dentry;
	rc = 0;
out:
	inode_unlock(d_inode(root));
	return rc;
	simple_done_creating(dentry);

	return 0;
}

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

static int devpts_reconfigure(struct fs_context *fc)
@@ -461,7 +447,7 @@ static void devpts_kill_sb(struct super_block *sb)
	if (fsi)
		ida_destroy(&fsi->allocated_ptys);
	kfree(fsi);
	kill_litter_super(sb);
	kill_anon_super(sb);
}

static struct file_system_type devpts_fs_type = {
@@ -534,16 +520,15 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv)
	sprintf(s, "%d", index);

	dentry = d_alloc_name(root, s);
	if (dentry) {
		dentry->d_fsdata = priv;
		d_add(dentry, inode);
		fsnotify_create(d_inode(root), dentry);
	} else {
	if (!dentry) {
		iput(inode);
		dentry = ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);
	}

	return dentry;
	dentry->d_fsdata = priv;
	d_make_persistent(dentry, inode);
	fsnotify_create(d_inode(root), dentry);
	dput(dentry);
	return dentry; // borrowed
}

/**
@@ -573,7 +558,7 @@ void devpts_pty_kill(struct dentry *dentry)
	drop_nlink(dentry->d_inode);
	d_drop(dentry);
	fsnotify_unlink(d_inode(dentry->d_parent), dentry);
	dput(dentry);	/* d_alloc_name() in devpts_pty_new() */
	d_make_discardable(dentry);
}

static int __init init_devpts_fs(void)