aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/tty/vt/vc_screen.c98
-rw-r--r--drivers/tty/vt/vt.c12
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
54struct vcs_poll_data { 55struct 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 */
139static struct vc_data*
140vcs_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 */
134static int 162static int
135vcs_size(struct inode *inode) 163vcs_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;
368unlock_out: 382unlock_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
562unlock_out: 570unlock_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 */
2080char con_buf[CON_BUF_SIZE];
2081DEFINE_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