Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e76b7c01 authored by Sukadev Bhattiprolu's avatar Sukadev Bhattiprolu Committed by Linus Torvalds
Browse files

Per-mount allocated_ptys



To enable multiple mounts of devpts, 'allocated_ptys' must be a per-mount
variable rather than a global variable.  Move 'allocated_ptys' into the
super_block's s_fs_info.

Changelog[v2]:
	Define and use DEVPTS_SB() wrapper.

Signed-off-by: default avatarSukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 59e55e6c
Loading
Loading
Loading
Loading
+48 −7
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@
#define PTMX_MINOR	2

extern int pty_limit;			/* Config limit on Unix98 ptys */
static DEFINE_IDA(allocated_ptys);
static DEFINE_MUTEX(allocated_ptys_lock);

static struct vfsmount *devpts_mnt;
@@ -55,6 +54,15 @@ static const match_table_t tokens = {
	{Opt_err, NULL}
};

struct pts_fs_info {
	struct ida allocated_ptys;
};

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

static inline struct super_block *pts_sb_from_inode(struct inode *inode)
{
	if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
@@ -126,6 +134,19 @@ static const struct super_operations devpts_sops = {
	.show_options	= devpts_show_options,
};

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);

	return fsi;
}

static int
devpts_fill_super(struct super_block *s, void *data, int silent)
{
@@ -137,9 +158,13 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
	s->s_op = &devpts_sops;
	s->s_time_gran = 1;

	s->s_fs_info = new_pts_fs_info();
	if (!s->s_fs_info)
		goto fail;

	inode = new_inode(s);
	if (!inode)
		goto fail;
		goto free_fsi;
	inode->i_ino = 1;
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
	inode->i_blocks = 0;
@@ -155,6 +180,9 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
	
	printk("devpts: get root dentry failed\n");
	iput(inode);

free_fsi:
	kfree(s->s_fs_info);
fail:
	return -ENOMEM;
}
@@ -165,11 +193,19 @@ static int devpts_get_sb(struct file_system_type *fs_type,
	return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt);
}

static void devpts_kill_sb(struct super_block *sb)
{
	struct pts_fs_info *fsi = DEVPTS_SB(sb);

	kfree(fsi);
	kill_anon_super(sb);
}

static struct file_system_type devpts_fs_type = {
	.owner		= THIS_MODULE,
	.name		= "devpts",
	.get_sb		= devpts_get_sb,
	.kill_sb	= kill_anon_super,
	.kill_sb	= devpts_kill_sb,
};

/*
@@ -179,16 +215,18 @@ static struct file_system_type devpts_fs_type = {

int devpts_new_index(struct inode *ptmx_inode)
{
	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
	struct pts_fs_info *fsi = DEVPTS_SB(sb);
	int index;
	int ida_ret;

retry:
	if (!ida_pre_get(&allocated_ptys, GFP_KERNEL)) {
	if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL)) {
		return -ENOMEM;
	}

	mutex_lock(&allocated_ptys_lock);
	ida_ret = ida_get_new(&allocated_ptys, &index);
	ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
	if (ida_ret < 0) {
		mutex_unlock(&allocated_ptys_lock);
		if (ida_ret == -EAGAIN)
@@ -197,7 +235,7 @@ int devpts_new_index(struct inode *ptmx_inode)
	}

	if (index >= pty_limit) {
		ida_remove(&allocated_ptys, index);
		ida_remove(&fsi->allocated_ptys, index);
		mutex_unlock(&allocated_ptys_lock);
		return -EIO;
	}
@@ -207,8 +245,11 @@ int devpts_new_index(struct inode *ptmx_inode)

void devpts_kill_index(struct inode *ptmx_inode, int idx)
{
	struct super_block *sb = pts_sb_from_inode(ptmx_inode);
	struct pts_fs_info *fsi = DEVPTS_SB(sb);

	mutex_lock(&allocated_ptys_lock);
	ida_remove(&allocated_ptys, idx);
	ida_remove(&fsi->allocated_ptys, idx);
	mutex_unlock(&allocated_ptys_lock);
}