diff options
-rw-r--r-- | drivers/char/tty_io.c | 40 | ||||
-rw-r--r-- | fs/devpts/inode.c | 43 | ||||
-rw-r--r-- | include/linux/devpts_fs.h | 4 |
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 |
139 | extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ | 138 | extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ |
140 | extern int pty_limit; /* Config limit on Unix98 ptys */ | ||
141 | static DEFINE_IDR(allocated_ptys); | ||
142 | static DEFINE_MUTEX(allocated_ptys_lock); | ||
143 | static int ptmx_open(struct inode *, struct file *); | 139 | static 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; |
2852 | out: | 2826 | out: |
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 | ||
31 | extern int pty_limit; /* Config limit on Unix98 ptys */ | ||
32 | static DEFINE_IDR(allocated_ptys); | ||
33 | static DEFINE_MUTEX(allocated_ptys_lock); | ||
34 | |||
29 | static struct vfsmount *devpts_mnt; | 35 | static struct vfsmount *devpts_mnt; |
30 | static struct dentry *devpts_root; | 36 | static 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 | ||
180 | int devpts_new_index(void) | ||
181 | { | ||
182 | int index; | ||
183 | int idr_ret; | ||
184 | |||
185 | retry: | ||
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 | |||
208 | void 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 | |||
174 | int devpts_pty_new(struct tty_struct *tty) | 215 | int 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 | ||
20 | int devpts_new_index(void); | ||
21 | void devpts_kill_index(int idx); | ||
20 | int devpts_pty_new(struct tty_struct *tty); /* mknod in devpts */ | 22 | int devpts_pty_new(struct tty_struct *tty); /* mknod in devpts */ |
21 | struct tty_struct *devpts_get_tty(int number); /* get tty structure */ | 23 | struct tty_struct *devpts_get_tty(int number); /* get tty structure */ |
22 | void devpts_pty_kill(int number); /* unlink */ | 24 | void 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 */ |
29 | static inline int devpts_new_index(void) { return -EINVAL; } | ||
30 | static inline void devpts_kill_index(int idx) { } | ||
27 | static inline int devpts_pty_new(struct tty_struct *tty) { return -EINVAL; } | 31 | static inline int devpts_pty_new(struct tty_struct *tty) { return -EINVAL; } |
28 | static inline struct tty_struct *devpts_get_tty(int number) { return NULL; } | 32 | static inline struct tty_struct *devpts_get_tty(int number) { return NULL; } |
29 | static inline void devpts_pty_kill(int number) { } | 33 | static inline void devpts_pty_kill(int number) { } |