diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/tty/vt/vc_screen.c | 98 | ||||
-rw-r--r-- | drivers/tty/vt/vt.c | 12 |
2 files changed, 52 insertions, 58 deletions
diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index 3c27c4bc6040..7b3bfbe2e6de 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/mutex.h> | ||
32 | #include <linux/vt_kern.h> | 31 | #include <linux/vt_kern.h> |
33 | #include <linux/selection.h> | 32 | #include <linux/selection.h> |
34 | #include <linux/kbd_kern.h> | 33 | #include <linux/kbd_kern.h> |
@@ -51,6 +50,8 @@ | |||
51 | #undef addr | 50 | #undef addr |
52 | #define HEADER_SIZE 4 | 51 | #define HEADER_SIZE 4 |
53 | 52 | ||
53 | #define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE) | ||
54 | |||
54 | struct vcs_poll_data { | 55 | struct vcs_poll_data { |
55 | struct notifier_block notifier; | 56 | struct notifier_block notifier; |
56 | unsigned int cons_num; | 57 | unsigned int cons_num; |
@@ -131,21 +132,45 @@ vcs_poll_data_get(struct file *file) | |||
131 | return poll; | 132 | return poll; |
132 | } | 133 | } |
133 | 134 | ||
135 | /* | ||
136 | * Returns VC for inode. | ||
137 | * Must be called with console_lock. | ||
138 | */ | ||
139 | static struct vc_data* | ||
140 | vcs_vc(struct inode *inode, int *viewed) | ||
141 | { | ||
142 | unsigned int currcons = iminor(inode) & 127; | ||
143 | |||
144 | WARN_CONSOLE_UNLOCKED(); | ||
145 | |||
146 | if (currcons == 0) { | ||
147 | currcons = fg_console; | ||
148 | if (viewed) | ||
149 | *viewed = 1; | ||
150 | } else { | ||
151 | currcons--; | ||
152 | if (viewed) | ||
153 | *viewed = 0; | ||
154 | } | ||
155 | return vc_cons[currcons].d; | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * Returns size for VC carried by inode. | ||
160 | * Must be called with console_lock. | ||
161 | */ | ||
134 | static int | 162 | static int |
135 | vcs_size(struct inode *inode) | 163 | vcs_size(struct inode *inode) |
136 | { | 164 | { |
137 | int size; | 165 | int size; |
138 | int minor = iminor(inode); | 166 | int minor = iminor(inode); |
139 | int currcons = minor & 127; | ||
140 | struct vc_data *vc; | 167 | struct vc_data *vc; |
141 | 168 | ||
142 | if (currcons == 0) | 169 | WARN_CONSOLE_UNLOCKED(); |
143 | currcons = fg_console; | 170 | |
144 | else | 171 | vc = vcs_vc(inode, NULL); |
145 | currcons--; | 172 | if (!vc) |
146 | if (!vc_cons_allocated(currcons)) | ||
147 | return -ENXIO; | 173 | return -ENXIO; |
148 | vc = vc_cons[currcons].d; | ||
149 | 174 | ||
150 | size = vc->vc_rows * vc->vc_cols; | 175 | size = vc->vc_rows * vc->vc_cols; |
151 | 176 | ||
@@ -158,17 +183,13 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) | |||
158 | { | 183 | { |
159 | int size; | 184 | int size; |
160 | 185 | ||
161 | mutex_lock(&con_buf_mtx); | ||
162 | console_lock(); | 186 | console_lock(); |
163 | size = vcs_size(file->f_path.dentry->d_inode); | 187 | size = vcs_size(file->f_path.dentry->d_inode); |
164 | console_unlock(); | 188 | console_unlock(); |
165 | if (size < 0) { | 189 | if (size < 0) |
166 | mutex_unlock(&con_buf_mtx); | ||
167 | return size; | 190 | return size; |
168 | } | ||
169 | switch (orig) { | 191 | switch (orig) { |
170 | default: | 192 | default: |
171 | mutex_unlock(&con_buf_mtx); | ||
172 | return -EINVAL; | 193 | return -EINVAL; |
173 | case 2: | 194 | case 2: |
174 | offset += size; | 195 | offset += size; |
@@ -179,11 +200,9 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) | |||
179 | break; | 200 | break; |
180 | } | 201 | } |
181 | if (offset < 0 || offset > size) { | 202 | if (offset < 0 || offset > size) { |
182 | mutex_unlock(&con_buf_mtx); | ||
183 | return -EINVAL; | 203 | return -EINVAL; |
184 | } | 204 | } |
185 | file->f_pos = offset; | 205 | file->f_pos = offset; |
186 | mutex_unlock(&con_buf_mtx); | ||
187 | return file->f_pos; | 206 | return file->f_pos; |
188 | } | 207 | } |
189 | 208 | ||
@@ -196,12 +215,15 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
196 | struct vc_data *vc; | 215 | struct vc_data *vc; |
197 | struct vcs_poll_data *poll; | 216 | struct vcs_poll_data *poll; |
198 | long pos; | 217 | long pos; |
199 | long viewed, attr, read; | 218 | long attr, read; |
200 | int col, maxcol; | 219 | int col, maxcol, viewed; |
201 | unsigned short *org = NULL; | 220 | unsigned short *org = NULL; |
202 | ssize_t ret; | 221 | ssize_t ret; |
222 | char *con_buf; | ||
203 | 223 | ||
204 | mutex_lock(&con_buf_mtx); | 224 | con_buf = (char *) __get_free_page(GFP_KERNEL); |
225 | if (!con_buf) | ||
226 | return -ENOMEM; | ||
205 | 227 | ||
206 | pos = *ppos; | 228 | pos = *ppos; |
207 | 229 | ||
@@ -211,18 +233,10 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
211 | console_lock(); | 233 | console_lock(); |
212 | 234 | ||
213 | attr = (currcons & 128); | 235 | attr = (currcons & 128); |
214 | currcons = (currcons & 127); | ||
215 | if (currcons == 0) { | ||
216 | currcons = fg_console; | ||
217 | viewed = 1; | ||
218 | } else { | ||
219 | currcons--; | ||
220 | viewed = 0; | ||
221 | } | ||
222 | ret = -ENXIO; | 236 | ret = -ENXIO; |
223 | if (!vc_cons_allocated(currcons)) | 237 | vc = vcs_vc(inode, &viewed); |
238 | if (!vc) | ||
224 | goto unlock_out; | 239 | goto unlock_out; |
225 | vc = vc_cons[currcons].d; | ||
226 | 240 | ||
227 | ret = -EINVAL; | 241 | ret = -EINVAL; |
228 | if (pos < 0) | 242 | if (pos < 0) |
@@ -367,7 +381,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
367 | ret = read; | 381 | ret = read; |
368 | unlock_out: | 382 | unlock_out: |
369 | console_unlock(); | 383 | console_unlock(); |
370 | mutex_unlock(&con_buf_mtx); | 384 | free_page((unsigned long) con_buf); |
371 | return ret; | 385 | return ret; |
372 | } | 386 | } |
373 | 387 | ||
@@ -378,13 +392,16 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
378 | unsigned int currcons = iminor(inode); | 392 | unsigned int currcons = iminor(inode); |
379 | struct vc_data *vc; | 393 | struct vc_data *vc; |
380 | long pos; | 394 | long pos; |
381 | long viewed, attr, size, written; | 395 | long attr, size, written; |
382 | char *con_buf0; | 396 | char *con_buf0; |
383 | int col, maxcol; | 397 | int col, maxcol, viewed; |
384 | u16 *org0 = NULL, *org = NULL; | 398 | u16 *org0 = NULL, *org = NULL; |
385 | size_t ret; | 399 | size_t ret; |
400 | char *con_buf; | ||
386 | 401 | ||
387 | mutex_lock(&con_buf_mtx); | 402 | con_buf = (char *) __get_free_page(GFP_KERNEL); |
403 | if (!con_buf) | ||
404 | return -ENOMEM; | ||
388 | 405 | ||
389 | pos = *ppos; | 406 | pos = *ppos; |
390 | 407 | ||
@@ -394,19 +411,10 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
394 | console_lock(); | 411 | console_lock(); |
395 | 412 | ||
396 | attr = (currcons & 128); | 413 | attr = (currcons & 128); |
397 | currcons = (currcons & 127); | ||
398 | |||
399 | if (currcons == 0) { | ||
400 | currcons = fg_console; | ||
401 | viewed = 1; | ||
402 | } else { | ||
403 | currcons--; | ||
404 | viewed = 0; | ||
405 | } | ||
406 | ret = -ENXIO; | 414 | ret = -ENXIO; |
407 | if (!vc_cons_allocated(currcons)) | 415 | vc = vcs_vc(inode, &viewed); |
416 | if (!vc) | ||
408 | goto unlock_out; | 417 | goto unlock_out; |
409 | vc = vc_cons[currcons].d; | ||
410 | 418 | ||
411 | size = vcs_size(inode); | 419 | size = vcs_size(inode); |
412 | ret = -EINVAL; | 420 | ret = -EINVAL; |
@@ -561,9 +569,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
561 | 569 | ||
562 | unlock_out: | 570 | unlock_out: |
563 | console_unlock(); | 571 | console_unlock(); |
564 | 572 | free_page((unsigned long) con_buf); | |
565 | mutex_unlock(&con_buf_mtx); | ||
566 | |||
567 | return ret; | 573 | return ret; |
568 | } | 574 | } |
569 | 575 | ||
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index d5669ff72df4..798df6f89110 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c | |||
@@ -2068,18 +2068,6 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) | |||
2068 | } | 2068 | } |
2069 | } | 2069 | } |
2070 | 2070 | ||
2071 | /* This is a temporary buffer used to prepare a tty console write | ||
2072 | * so that we can easily avoid touching user space while holding the | ||
2073 | * console spinlock. It is allocated in con_init and is shared by | ||
2074 | * this code and the vc_screen read/write tty calls. | ||
2075 | * | ||
2076 | * We have to allocate this statically in the kernel data section | ||
2077 | * since console_init (and thus con_init) are called before any | ||
2078 | * kernel memory allocation is available. | ||
2079 | */ | ||
2080 | char con_buf[CON_BUF_SIZE]; | ||
2081 | DEFINE_MUTEX(con_buf_mtx); | ||
2082 | |||
2083 | /* is_double_width() is based on the wcwidth() implementation by | 2071 | /* is_double_width() is based on the wcwidth() implementation by |
2084 | * Markus Kuhn -- 2007-05-26 (Unicode 5.0) | 2072 | * Markus Kuhn -- 2007-05-26 (Unicode 5.0) |
2085 | * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c | 2073 | * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c |