diff options
Diffstat (limited to 'fs/devpts/inode.c')
-rw-r--r-- | fs/devpts/inode.c | 55 |
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 | ||
32 | extern int pty_limit; /* Config limit on Unix98 ptys */ | 32 | extern int pty_limit; /* Config limit on Unix98 ptys */ |
33 | static DEFINE_IDA(allocated_ptys); | ||
34 | static DEFINE_MUTEX(allocated_ptys_lock); | 33 | static DEFINE_MUTEX(allocated_ptys_lock); |
35 | 34 | ||
36 | static struct vfsmount *devpts_mnt; | 35 | static 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 | ||
57 | struct pts_fs_info { | ||
58 | struct ida allocated_ptys; | ||
59 | }; | ||
60 | |||
61 | static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb) | ||
62 | { | ||
63 | return sb->s_fs_info; | ||
64 | } | ||
65 | |||
58 | static inline struct super_block *pts_sb_from_inode(struct inode *inode) | 66 | static 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 | ||
137 | static 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 | |||
129 | static int | 150 | static int |
130 | devpts_fill_super(struct super_block *s, void *data, int silent) | 151 | devpts_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 | |||
184 | free_fsi: | ||
185 | kfree(s->s_fs_info); | ||
158 | fail: | 186 | fail: |
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 | ||
196 | static 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 | |||
168 | static struct file_system_type devpts_fs_type = { | 204 | static 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 | ||
180 | int devpts_new_index(struct inode *ptmx_inode) | 216 | int 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 | ||
185 | retry: | 223 | retry: |
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 | ||
208 | void devpts_kill_index(struct inode *ptmx_inode, int idx) | 246 | void 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 | ||