aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/tty_io.c40
-rw-r--r--fs/devpts/inode.c43
-rw-r--r--include/linux/devpts_fs.h4
3 files changed, 52 insertions, 35 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index edcb7e471f02..1d298c2cf930 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -91,7 +91,6 @@
91#include <linux/module.h> 91#include <linux/module.h>
92#include <linux/smp_lock.h> 92#include <linux/smp_lock.h>
93#include <linux/device.h> 93#include <linux/device.h>
94#include <linux/idr.h>
95#include <linux/wait.h> 94#include <linux/wait.h>
96#include <linux/bitops.h> 95#include <linux/bitops.h>
97#include <linux/delay.h> 96#include <linux/delay.h>
@@ -137,9 +136,6 @@ EXPORT_SYMBOL(tty_mutex);
137 136
138#ifdef CONFIG_UNIX98_PTYS 137#ifdef CONFIG_UNIX98_PTYS
139extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ 138extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */
140extern int pty_limit; /* Config limit on Unix98 ptys */
141static DEFINE_IDR(allocated_ptys);
142static DEFINE_MUTEX(allocated_ptys_lock);
143static int ptmx_open(struct inode *, struct file *); 139static int ptmx_open(struct inode *, struct file *);
144#endif 140#endif
145 141
@@ -2639,15 +2635,9 @@ static void release_dev(struct file *filp)
2639 */ 2635 */
2640 release_tty(tty, idx); 2636 release_tty(tty, idx);
2641 2637
2642#ifdef CONFIG_UNIX98_PTYS
2643 /* Make this pty number available for reallocation */ 2638 /* Make this pty number available for reallocation */
2644 if (devpts) { 2639 if (devpts)
2645 mutex_lock(&allocated_ptys_lock); 2640 devpts_kill_index(idx);
2646 idr_remove(&allocated_ptys, idx);
2647 mutex_unlock(&allocated_ptys_lock);
2648 }
2649#endif
2650
2651} 2641}
2652 2642
2653/** 2643/**
@@ -2803,29 +2793,13 @@ static int ptmx_open(struct inode *inode, struct file *filp)
2803 struct tty_struct *tty; 2793 struct tty_struct *tty;
2804 int retval; 2794 int retval;
2805 int index; 2795 int index;
2806 int idr_ret;
2807 2796
2808 nonseekable_open(inode, filp); 2797 nonseekable_open(inode, filp);
2809 2798
2810 /* find a device that is not in use. */ 2799 /* find a device that is not in use. */
2811 mutex_lock(&allocated_ptys_lock); 2800 index = devpts_new_index();
2812 if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { 2801 if (index < 0)
2813 mutex_unlock(&allocated_ptys_lock); 2802 return index;
2814 return -ENOMEM;
2815 }
2816 idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
2817 if (idr_ret < 0) {
2818 mutex_unlock(&allocated_ptys_lock);
2819 if (idr_ret == -EAGAIN)
2820 return -ENOMEM;
2821 return -EIO;
2822 }
2823 if (index >= pty_limit) {
2824 idr_remove(&allocated_ptys, index);
2825 mutex_unlock(&allocated_ptys_lock);
2826 return -EIO;
2827 }
2828 mutex_unlock(&allocated_ptys_lock);
2829 2803
2830 mutex_lock(&tty_mutex); 2804 mutex_lock(&tty_mutex);
2831 retval = init_dev(ptm_driver, index, &tty); 2805 retval = init_dev(ptm_driver, index, &tty);
@@ -2850,9 +2824,7 @@ out1:
2850 release_dev(filp); 2824 release_dev(filp);
2851 return retval; 2825 return retval;
2852out: 2826out:
2853 mutex_lock(&allocated_ptys_lock); 2827 devpts_kill_index(index);
2854 idr_remove(&allocated_ptys, index);
2855 mutex_unlock(&allocated_ptys_lock);
2856 return retval; 2828 return retval;
2857} 2829}
2858#endif 2830#endif
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index f120e1207874..285b64a8b06e 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -17,6 +17,8 @@
17#include <linux/namei.h> 17#include <linux/namei.h>
18#include <linux/mount.h> 18#include <linux/mount.h>
19#include <linux/tty.h> 19#include <linux/tty.h>
20#include <linux/mutex.h>
21#include <linux/idr.h>
20#include <linux/devpts_fs.h> 22#include <linux/devpts_fs.h>
21#include <linux/parser.h> 23#include <linux/parser.h>
22#include <linux/fsnotify.h> 24#include <linux/fsnotify.h>
@@ -26,6 +28,10 @@
26 28
27#define DEVPTS_DEFAULT_MODE 0600 29#define DEVPTS_DEFAULT_MODE 0600
28 30
31extern int pty_limit; /* Config limit on Unix98 ptys */
32static DEFINE_IDR(allocated_ptys);
33static DEFINE_MUTEX(allocated_ptys_lock);
34
29static struct vfsmount *devpts_mnt; 35static struct vfsmount *devpts_mnt;
30static struct dentry *devpts_root; 36static struct dentry *devpts_root;
31 37
@@ -171,9 +177,44 @@ static struct dentry *get_node(int num)
171 return lookup_one_len(s, root, sprintf(s, "%d", num)); 177 return lookup_one_len(s, root, sprintf(s, "%d", num));
172} 178}
173 179
180int devpts_new_index(void)
181{
182 int index;
183 int idr_ret;
184
185retry:
186 if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
187 return -ENOMEM;
188 }
189
190 mutex_lock(&allocated_ptys_lock);
191 idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
192 if (idr_ret < 0) {
193 mutex_unlock(&allocated_ptys_lock);
194 if (idr_ret == -EAGAIN)
195 goto retry;
196 return -EIO;
197 }
198
199 if (index >= pty_limit) {
200 idr_remove(&allocated_ptys, index);
201 mutex_unlock(&allocated_ptys_lock);
202 return -EIO;
203 }
204 mutex_unlock(&allocated_ptys_lock);
205 return index;
206}
207
208void devpts_kill_index(int idx)
209{
210 mutex_lock(&allocated_ptys_lock);
211 idr_remove(&allocated_ptys, idx);
212 mutex_unlock(&allocated_ptys_lock);
213}
214
174int devpts_pty_new(struct tty_struct *tty) 215int devpts_pty_new(struct tty_struct *tty)
175{ 216{
176 int number = tty->index; 217 int number = tty->index; /* tty layer puts index from devpts_new_index() in here */
177 struct tty_driver *driver = tty->driver; 218 struct tty_driver *driver = tty->driver;
178 dev_t device = MKDEV(driver->major, driver->minor_start+number); 219 dev_t device = MKDEV(driver->major, driver->minor_start+number);
179 struct dentry *dentry; 220 struct dentry *dentry;
diff --git a/include/linux/devpts_fs.h b/include/linux/devpts_fs.h
index b672ddc00735..154769cad3f3 100644
--- a/include/linux/devpts_fs.h
+++ b/include/linux/devpts_fs.h
@@ -17,6 +17,8 @@
17 17
18#ifdef CONFIG_UNIX98_PTYS 18#ifdef CONFIG_UNIX98_PTYS
19 19
20int devpts_new_index(void);
21void devpts_kill_index(int idx);
20int devpts_pty_new(struct tty_struct *tty); /* mknod in devpts */ 22int devpts_pty_new(struct tty_struct *tty); /* mknod in devpts */
21struct tty_struct *devpts_get_tty(int number); /* get tty structure */ 23struct tty_struct *devpts_get_tty(int number); /* get tty structure */
22void devpts_pty_kill(int number); /* unlink */ 24void devpts_pty_kill(int number); /* unlink */
@@ -24,6 +26,8 @@ void devpts_pty_kill(int number); /* unlink */
24#else 26#else
25 27
26/* Dummy stubs in the no-pty case */ 28/* Dummy stubs in the no-pty case */
29static inline int devpts_new_index(void) { return -EINVAL; }
30static inline void devpts_kill_index(int idx) { }
27static inline int devpts_pty_new(struct tty_struct *tty) { return -EINVAL; } 31static inline int devpts_pty_new(struct tty_struct *tty) { return -EINVAL; }
28static inline struct tty_struct *devpts_get_tty(int number) { return NULL; } 32static inline struct tty_struct *devpts_get_tty(int number) { return NULL; }
29static inline void devpts_pty_kill(int number) { } 33static inline void devpts_pty_kill(int number) { }