diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-10 13:23:43 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-10 13:25:27 -0500 |
commit | 5a22e30def8b9539576ff047adb14455ca559f07 (patch) | |
tree | e1e76efd73b28e7ae8124383c263fcf92bcc11e0 /fs | |
parent | 19e00f2f1d5273dbc52eab0ebc315cae3aa44b2a (diff) | |
parent | 418a936e84e8f346da322c2e839992aa9df108d4 (diff) |
Merge tag 'tty-3.3-rc3' tty-next
This is needed to handle the 8250 file merge mess properly for future
patches.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/devpts/inode.c | 85 |
1 files changed, 81 insertions, 4 deletions
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index c4e2a58a2e82..1c6f908e38ca 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c | |||
@@ -36,7 +36,61 @@ | |||
36 | #define DEVPTS_DEFAULT_PTMX_MODE 0000 | 36 | #define DEVPTS_DEFAULT_PTMX_MODE 0000 |
37 | #define PTMX_MINOR 2 | 37 | #define PTMX_MINOR 2 |
38 | 38 | ||
39 | extern int pty_limit; /* Config limit on Unix98 ptys */ | 39 | /* |
40 | * sysctl support for setting limits on the number of Unix98 ptys allocated. | ||
41 | * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. | ||
42 | */ | ||
43 | static int pty_limit = NR_UNIX98_PTY_DEFAULT; | ||
44 | static int pty_reserve = NR_UNIX98_PTY_RESERVE; | ||
45 | static int pty_limit_min; | ||
46 | static int pty_limit_max = INT_MAX; | ||
47 | static int pty_count; | ||
48 | |||
49 | static struct ctl_table pty_table[] = { | ||
50 | { | ||
51 | .procname = "max", | ||
52 | .maxlen = sizeof(int), | ||
53 | .mode = 0644, | ||
54 | .data = &pty_limit, | ||
55 | .proc_handler = proc_dointvec_minmax, | ||
56 | .extra1 = &pty_limit_min, | ||
57 | .extra2 = &pty_limit_max, | ||
58 | }, { | ||
59 | .procname = "reserve", | ||
60 | .maxlen = sizeof(int), | ||
61 | .mode = 0644, | ||
62 | .data = &pty_reserve, | ||
63 | .proc_handler = proc_dointvec_minmax, | ||
64 | .extra1 = &pty_limit_min, | ||
65 | .extra2 = &pty_limit_max, | ||
66 | }, { | ||
67 | .procname = "nr", | ||
68 | .maxlen = sizeof(int), | ||
69 | .mode = 0444, | ||
70 | .data = &pty_count, | ||
71 | .proc_handler = proc_dointvec, | ||
72 | }, | ||
73 | {} | ||
74 | }; | ||
75 | |||
76 | static struct ctl_table pty_kern_table[] = { | ||
77 | { | ||
78 | .procname = "pty", | ||
79 | .mode = 0555, | ||
80 | .child = pty_table, | ||
81 | }, | ||
82 | {} | ||
83 | }; | ||
84 | |||
85 | static struct ctl_table pty_root_table[] = { | ||
86 | { | ||
87 | .procname = "kernel", | ||
88 | .mode = 0555, | ||
89 | .child = pty_kern_table, | ||
90 | }, | ||
91 | {} | ||
92 | }; | ||
93 | |||
40 | static DEFINE_MUTEX(allocated_ptys_lock); | 94 | static DEFINE_MUTEX(allocated_ptys_lock); |
41 | 95 | ||
42 | static struct vfsmount *devpts_mnt; | 96 | static struct vfsmount *devpts_mnt; |
@@ -49,10 +103,11 @@ struct pts_mount_opts { | |||
49 | umode_t mode; | 103 | umode_t mode; |
50 | umode_t ptmxmode; | 104 | umode_t ptmxmode; |
51 | int newinstance; | 105 | int newinstance; |
106 | int max; | ||
52 | }; | 107 | }; |
53 | 108 | ||
54 | enum { | 109 | enum { |
55 | Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, | 110 | Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, Opt_max, |
56 | Opt_err | 111 | Opt_err |
57 | }; | 112 | }; |
58 | 113 | ||
@@ -63,6 +118,7 @@ static const match_table_t tokens = { | |||
63 | #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES | 118 | #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES |
64 | {Opt_ptmxmode, "ptmxmode=%o"}, | 119 | {Opt_ptmxmode, "ptmxmode=%o"}, |
65 | {Opt_newinstance, "newinstance"}, | 120 | {Opt_newinstance, "newinstance"}, |
121 | {Opt_max, "max=%d"}, | ||
66 | #endif | 122 | #endif |
67 | {Opt_err, NULL} | 123 | {Opt_err, NULL} |
68 | }; | 124 | }; |
@@ -109,6 +165,7 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts) | |||
109 | opts->gid = 0; | 165 | opts->gid = 0; |
110 | opts->mode = DEVPTS_DEFAULT_MODE; | 166 | opts->mode = DEVPTS_DEFAULT_MODE; |
111 | opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; | 167 | opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; |
168 | opts->max = NR_UNIX98_PTY_MAX; | ||
112 | 169 | ||
113 | /* newinstance makes sense only on initial mount */ | 170 | /* newinstance makes sense only on initial mount */ |
114 | if (op == PARSE_MOUNT) | 171 | if (op == PARSE_MOUNT) |
@@ -152,6 +209,12 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts) | |||
152 | if (op == PARSE_MOUNT) | 209 | if (op == PARSE_MOUNT) |
153 | opts->newinstance = 1; | 210 | opts->newinstance = 1; |
154 | break; | 211 | break; |
212 | case Opt_max: | ||
213 | if (match_int(&args[0], &option) || | ||
214 | option < 0 || option > NR_UNIX98_PTY_MAX) | ||
215 | return -EINVAL; | ||
216 | opts->max = option; | ||
217 | break; | ||
155 | #endif | 218 | #endif |
156 | default: | 219 | default: |
157 | printk(KERN_ERR "devpts: called with bogus options\n"); | 220 | printk(KERN_ERR "devpts: called with bogus options\n"); |
@@ -258,6 +321,8 @@ static int devpts_show_options(struct seq_file *seq, struct dentry *root) | |||
258 | seq_printf(seq, ",mode=%03o", opts->mode); | 321 | seq_printf(seq, ",mode=%03o", opts->mode); |
259 | #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES | 322 | #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES |
260 | seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode); | 323 | seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode); |
324 | if (opts->max < NR_UNIX98_PTY_MAX) | ||
325 | seq_printf(seq, ",max=%d", opts->max); | ||
261 | #endif | 326 | #endif |
262 | 327 | ||
263 | return 0; | 328 | return 0; |
@@ -438,6 +503,12 @@ retry: | |||
438 | return -ENOMEM; | 503 | return -ENOMEM; |
439 | 504 | ||
440 | mutex_lock(&allocated_ptys_lock); | 505 | mutex_lock(&allocated_ptys_lock); |
506 | if (pty_count >= pty_limit - | ||
507 | (fsi->mount_opts.newinstance ? pty_reserve : 0)) { | ||
508 | mutex_unlock(&allocated_ptys_lock); | ||
509 | return -ENOSPC; | ||
510 | } | ||
511 | |||
441 | ida_ret = ida_get_new(&fsi->allocated_ptys, &index); | 512 | ida_ret = ida_get_new(&fsi->allocated_ptys, &index); |
442 | if (ida_ret < 0) { | 513 | if (ida_ret < 0) { |
443 | mutex_unlock(&allocated_ptys_lock); | 514 | mutex_unlock(&allocated_ptys_lock); |
@@ -446,11 +517,12 @@ retry: | |||
446 | return -EIO; | 517 | return -EIO; |
447 | } | 518 | } |
448 | 519 | ||
449 | if (index >= pty_limit) { | 520 | if (index >= fsi->mount_opts.max) { |
450 | ida_remove(&fsi->allocated_ptys, index); | 521 | ida_remove(&fsi->allocated_ptys, index); |
451 | mutex_unlock(&allocated_ptys_lock); | 522 | mutex_unlock(&allocated_ptys_lock); |
452 | return -EIO; | 523 | return -ENOSPC; |
453 | } | 524 | } |
525 | pty_count++; | ||
454 | mutex_unlock(&allocated_ptys_lock); | 526 | mutex_unlock(&allocated_ptys_lock); |
455 | return index; | 527 | return index; |
456 | } | 528 | } |
@@ -462,6 +534,7 @@ void devpts_kill_index(struct inode *ptmx_inode, int idx) | |||
462 | 534 | ||
463 | mutex_lock(&allocated_ptys_lock); | 535 | mutex_lock(&allocated_ptys_lock); |
464 | ida_remove(&fsi->allocated_ptys, idx); | 536 | ida_remove(&fsi->allocated_ptys, idx); |
537 | pty_count--; | ||
465 | mutex_unlock(&allocated_ptys_lock); | 538 | mutex_unlock(&allocated_ptys_lock); |
466 | } | 539 | } |
467 | 540 | ||
@@ -558,11 +631,15 @@ void devpts_pty_kill(struct tty_struct *tty) | |||
558 | static int __init init_devpts_fs(void) | 631 | static int __init init_devpts_fs(void) |
559 | { | 632 | { |
560 | int err = register_filesystem(&devpts_fs_type); | 633 | int err = register_filesystem(&devpts_fs_type); |
634 | struct ctl_table_header *table; | ||
635 | |||
561 | if (!err) { | 636 | if (!err) { |
637 | table = register_sysctl_table(pty_root_table); | ||
562 | devpts_mnt = kern_mount(&devpts_fs_type); | 638 | devpts_mnt = kern_mount(&devpts_fs_type); |
563 | if (IS_ERR(devpts_mnt)) { | 639 | if (IS_ERR(devpts_mnt)) { |
564 | err = PTR_ERR(devpts_mnt); | 640 | err = PTR_ERR(devpts_mnt); |
565 | unregister_filesystem(&devpts_fs_type); | 641 | unregister_filesystem(&devpts_fs_type); |
642 | unregister_sysctl_table(table); | ||
566 | } | 643 | } |
567 | } | 644 | } |
568 | return err; | 645 | return err; |