aboutsummaryrefslogtreecommitdiffstats
path: root/fs/devpts
diff options
context:
space:
mode:
Diffstat (limited to 'fs/devpts')
-rw-r--r--fs/devpts/inode.c55
1 files changed, 48 insertions, 7 deletions
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index f96e10a109fe..49d879d911b1 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -30,7 +30,6 @@
30#define PTMX_MINOR 2 30#define PTMX_MINOR 2
31 31
32extern int pty_limit; /* Config limit on Unix98 ptys */ 32extern int pty_limit; /* Config limit on Unix98 ptys */
33static DEFINE_IDA(allocated_ptys);
34static DEFINE_MUTEX(allocated_ptys_lock); 33static DEFINE_MUTEX(allocated_ptys_lock);
35 34
36static struct vfsmount *devpts_mnt; 35static struct vfsmount *devpts_mnt;
@@ -55,6 +54,15 @@ static const match_table_t tokens = {
55 {Opt_err, NULL} 54 {Opt_err, NULL}
56}; 55};
57 56
57struct pts_fs_info {
58 struct ida allocated_ptys;
59};
60
61static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb)
62{
63 return sb->s_fs_info;
64}
65
58static inline struct super_block *pts_sb_from_inode(struct inode *inode) 66static inline struct super_block *pts_sb_from_inode(struct inode *inode)
59{ 67{
60 if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) 68 if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
@@ -126,6 +134,19 @@ static const struct super_operations devpts_sops = {
126 .show_options = devpts_show_options, 134 .show_options = devpts_show_options,
127}; 135};
128 136
137static void *new_pts_fs_info(void)
138{
139 struct pts_fs_info *fsi;
140
141 fsi = kzalloc(sizeof(struct pts_fs_info), GFP_KERNEL);
142 if (!fsi)
143 return NULL;
144
145 ida_init(&fsi->allocated_ptys);
146
147 return fsi;
148}
149
129static int 150static int
130devpts_fill_super(struct super_block *s, void *data, int silent) 151devpts_fill_super(struct super_block *s, void *data, int silent)
131{ 152{
@@ -137,9 +158,13 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
137 s->s_op = &devpts_sops; 158 s->s_op = &devpts_sops;
138 s->s_time_gran = 1; 159 s->s_time_gran = 1;
139 160
161 s->s_fs_info = new_pts_fs_info();
162 if (!s->s_fs_info)
163 goto fail;
164
140 inode = new_inode(s); 165 inode = new_inode(s);
141 if (!inode) 166 if (!inode)
142 goto fail; 167 goto free_fsi;
143 inode->i_ino = 1; 168 inode->i_ino = 1;
144 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 169 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
145 inode->i_blocks = 0; 170 inode->i_blocks = 0;
@@ -155,6 +180,9 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
155 180
156 printk("devpts: get root dentry failed\n"); 181 printk("devpts: get root dentry failed\n");
157 iput(inode); 182 iput(inode);
183
184free_fsi:
185 kfree(s->s_fs_info);
158fail: 186fail:
159 return -ENOMEM; 187 return -ENOMEM;
160} 188}
@@ -165,11 +193,19 @@ static int devpts_get_sb(struct file_system_type *fs_type,
165 return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt); 193 return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt);
166} 194}
167 195
196static void devpts_kill_sb(struct super_block *sb)
197{
198 struct pts_fs_info *fsi = DEVPTS_SB(sb);
199
200 kfree(fsi);
201 kill_anon_super(sb);
202}
203
168static struct file_system_type devpts_fs_type = { 204static struct file_system_type devpts_fs_type = {
169 .owner = THIS_MODULE, 205 .owner = THIS_MODULE,
170 .name = "devpts", 206 .name = "devpts",
171 .get_sb = devpts_get_sb, 207 .get_sb = devpts_get_sb,
172 .kill_sb = kill_anon_super, 208 .kill_sb = devpts_kill_sb,
173}; 209};
174 210
175/* 211/*
@@ -179,16 +215,18 @@ static struct file_system_type devpts_fs_type = {
179 215
180int devpts_new_index(struct inode *ptmx_inode) 216int devpts_new_index(struct inode *ptmx_inode)
181{ 217{
218 struct super_block *sb = pts_sb_from_inode(ptmx_inode);
219 struct pts_fs_info *fsi = DEVPTS_SB(sb);
182 int index; 220 int index;
183 int ida_ret; 221 int ida_ret;
184 222
185retry: 223retry:
186 if (!ida_pre_get(&allocated_ptys, GFP_KERNEL)) { 224 if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL)) {
187 return -ENOMEM; 225 return -ENOMEM;
188 } 226 }
189 227
190 mutex_lock(&allocated_ptys_lock); 228 mutex_lock(&allocated_ptys_lock);
191 ida_ret = ida_get_new(&allocated_ptys, &index); 229 ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
192 if (ida_ret < 0) { 230 if (ida_ret < 0) {
193 mutex_unlock(&allocated_ptys_lock); 231 mutex_unlock(&allocated_ptys_lock);
194 if (ida_ret == -EAGAIN) 232 if (ida_ret == -EAGAIN)
@@ -197,7 +235,7 @@ retry:
197 } 235 }
198 236
199 if (index >= pty_limit) { 237 if (index >= pty_limit) {
200 ida_remove(&allocated_ptys, index); 238 ida_remove(&fsi->allocated_ptys, index);
201 mutex_unlock(&allocated_ptys_lock); 239 mutex_unlock(&allocated_ptys_lock);
202 return -EIO; 240 return -EIO;
203 } 241 }
@@ -207,8 +245,11 @@ retry:
207 245
208void devpts_kill_index(struct inode *ptmx_inode, int idx) 246void devpts_kill_index(struct inode *ptmx_inode, int idx)
209{ 247{
248 struct super_block *sb = pts_sb_from_inode(ptmx_inode);
249 struct pts_fs_info *fsi = DEVPTS_SB(sb);
250
210 mutex_lock(&allocated_ptys_lock); 251 mutex_lock(&allocated_ptys_lock);
211 ida_remove(&allocated_ptys, idx); 252 ida_remove(&fsi->allocated_ptys, idx);
212 mutex_unlock(&allocated_ptys_lock); 253 mutex_unlock(&allocated_ptys_lock);
213} 254}
214 255