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: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
59e55e6cf8
commit
e76b7c01e5
1 changed files with 48 additions and 7 deletions
|
@ -30,7 +30,6 @@
|
||||||
#define PTMX_MINOR 2
|
#define PTMX_MINOR 2
|
||||||
|
|
||||||
extern int pty_limit; /* Config limit on Unix98 ptys */
|
extern int pty_limit; /* Config limit on Unix98 ptys */
|
||||||
static DEFINE_IDA(allocated_ptys);
|
|
||||||
static DEFINE_MUTEX(allocated_ptys_lock);
|
static DEFINE_MUTEX(allocated_ptys_lock);
|
||||||
|
|
||||||
static struct vfsmount *devpts_mnt;
|
static struct vfsmount *devpts_mnt;
|
||||||
|
@ -55,6 +54,15 @@ static const match_table_t tokens = {
|
||||||
{Opt_err, NULL}
|
{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)
|
static inline struct super_block *pts_sb_from_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
|
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,
|
.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
|
static int
|
||||||
devpts_fill_super(struct super_block *s, void *data, int silent)
|
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_op = &devpts_sops;
|
||||||
s->s_time_gran = 1;
|
s->s_time_gran = 1;
|
||||||
|
|
||||||
|
s->s_fs_info = new_pts_fs_info();
|
||||||
|
if (!s->s_fs_info)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
inode = new_inode(s);
|
inode = new_inode(s);
|
||||||
if (!inode)
|
if (!inode)
|
||||||
goto fail;
|
goto free_fsi;
|
||||||
inode->i_ino = 1;
|
inode->i_ino = 1;
|
||||||
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
|
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
|
||||||
inode->i_blocks = 0;
|
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");
|
printk("devpts: get root dentry failed\n");
|
||||||
iput(inode);
|
iput(inode);
|
||||||
|
|
||||||
|
free_fsi:
|
||||||
|
kfree(s->s_fs_info);
|
||||||
fail:
|
fail:
|
||||||
return -ENOMEM;
|
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);
|
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 = {
|
static struct file_system_type devpts_fs_type = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.name = "devpts",
|
.name = "devpts",
|
||||||
.get_sb = devpts_get_sb,
|
.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)
|
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 index;
|
||||||
int ida_ret;
|
int ida_ret;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
if (!ida_pre_get(&allocated_ptys, GFP_KERNEL)) {
|
if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL)) {
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&allocated_ptys_lock);
|
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) {
|
if (ida_ret < 0) {
|
||||||
mutex_unlock(&allocated_ptys_lock);
|
mutex_unlock(&allocated_ptys_lock);
|
||||||
if (ida_ret == -EAGAIN)
|
if (ida_ret == -EAGAIN)
|
||||||
|
@ -197,7 +235,7 @@ int devpts_new_index(struct inode *ptmx_inode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index >= pty_limit) {
|
if (index >= pty_limit) {
|
||||||
ida_remove(&allocated_ptys, index);
|
ida_remove(&fsi->allocated_ptys, index);
|
||||||
mutex_unlock(&allocated_ptys_lock);
|
mutex_unlock(&allocated_ptys_lock);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -207,8 +245,11 @@ int devpts_new_index(struct inode *ptmx_inode)
|
||||||
|
|
||||||
void devpts_kill_index(struct inode *ptmx_inode, int idx)
|
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);
|
mutex_lock(&allocated_ptys_lock);
|
||||||
ida_remove(&allocated_ptys, idx);
|
ida_remove(&fsi->allocated_ptys, idx);
|
||||||
mutex_unlock(&allocated_ptys_lock);
|
mutex_unlock(&allocated_ptys_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue