Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tty,vcs removing con_buf/conf_buf_mtx

seems there's no longer need for using con_buf/conf_buf_mtx
as vcs_read/vcs_write buffer for user's data.

The do_con_write function, that was the other user of this,
is currently using its own kmalloc-ed buffer.

Not sure when this got changed, as I was able to find this code
in 2.6.9, but it's already gone as far as current git history
goes - 2.6.12-rc2.

AFAICS there's a behaviour change with the current change.
The lseek is not completely mutually exclusive with the
vcs_read/vcs_write - the file->f_pos might get updated
via lseek callback during the vcs_read/vcs_write processing.

I tried to find out if the prefered behaviour is to keep
this in sync within read/write/lseek functions, but I did
not find any pattern on different places.

I guess if user end up calling write/lseek from different
threads she should know what she's doing. If needed we
could use dedicated fd mutex/buffer.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Jiri Olsa and committed by
Greg Kroah-Hartman
fcdba07e dc1892c4

+52 -66
+52 -46
drivers/tty/vt/vc_screen.c
··· 28 28 #include <linux/interrupt.h> 29 29 #include <linux/mm.h> 30 30 #include <linux/init.h> 31 - #include <linux/mutex.h> 32 31 #include <linux/vt_kern.h> 33 32 #include <linux/selection.h> 34 33 #include <linux/kbd_kern.h> ··· 49 50 #undef org 50 51 #undef addr 51 52 #define HEADER_SIZE 4 53 + 54 + #define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE) 52 55 53 56 struct vcs_poll_data { 54 57 struct notifier_block notifier; ··· 132 131 return poll; 133 132 } 134 133 134 + /* 135 + * Returns VC for inode. 136 + * Must be called with console_lock. 137 + */ 138 + static struct vc_data* 139 + vcs_vc(struct inode *inode, int *viewed) 140 + { 141 + unsigned int currcons = iminor(inode) & 127; 142 + 143 + WARN_CONSOLE_UNLOCKED(); 144 + 145 + if (currcons == 0) { 146 + currcons = fg_console; 147 + if (viewed) 148 + *viewed = 1; 149 + } else { 150 + currcons--; 151 + if (viewed) 152 + *viewed = 0; 153 + } 154 + return vc_cons[currcons].d; 155 + } 156 + 157 + /* 158 + * Returns size for VC carried by inode. 159 + * Must be called with console_lock. 160 + */ 135 161 static int 136 162 vcs_size(struct inode *inode) 137 163 { 138 164 int size; 139 165 int minor = iminor(inode); 140 - int currcons = minor & 127; 141 166 struct vc_data *vc; 142 167 143 - if (currcons == 0) 144 - currcons = fg_console; 145 - else 146 - currcons--; 147 - if (!vc_cons_allocated(currcons)) 168 + WARN_CONSOLE_UNLOCKED(); 169 + 170 + vc = vcs_vc(inode, NULL); 171 + if (!vc) 148 172 return -ENXIO; 149 - vc = vc_cons[currcons].d; 150 173 151 174 size = vc->vc_rows * vc->vc_cols; 152 175 ··· 183 158 { 184 159 int size; 185 160 186 - mutex_lock(&con_buf_mtx); 187 161 console_lock(); 188 162 size = vcs_size(file->f_path.dentry->d_inode); 189 163 console_unlock(); 190 - if (size < 0) { 191 - mutex_unlock(&con_buf_mtx); 164 + if (size < 0) 192 165 return size; 193 - } 194 166 switch (orig) { 195 167 default: 196 - mutex_unlock(&con_buf_mtx); 197 168 return -EINVAL; 198 169 case 2: 199 170 offset += size; ··· 200 179 break; 201 180 } 202 181 if (offset < 0 || offset > size) { 203 - mutex_unlock(&con_buf_mtx); 204 182 return -EINVAL; 205 183 } 206 184 file->f_pos = offset; 207 - mutex_unlock(&con_buf_mtx); 208 185 return file->f_pos; 209 186 } 210 187 ··· 215 196 struct vc_data *vc; 216 197 struct vcs_poll_data *poll; 217 198 long pos; 218 - long viewed, attr, read; 219 - int col, maxcol; 199 + long attr, read; 200 + int col, maxcol, viewed; 220 201 unsigned short *org = NULL; 221 202 ssize_t ret; 203 + char *con_buf; 222 204 223 - mutex_lock(&con_buf_mtx); 205 + con_buf = (char *) __get_free_page(GFP_KERNEL); 206 + if (!con_buf) 207 + return -ENOMEM; 224 208 225 209 pos = *ppos; 226 210 ··· 233 211 console_lock(); 234 212 235 213 attr = (currcons & 128); 236 - currcons = (currcons & 127); 237 - if (currcons == 0) { 238 - currcons = fg_console; 239 - viewed = 1; 240 - } else { 241 - currcons--; 242 - viewed = 0; 243 - } 244 214 ret = -ENXIO; 245 - if (!vc_cons_allocated(currcons)) 215 + vc = vcs_vc(inode, &viewed); 216 + if (!vc) 246 217 goto unlock_out; 247 - vc = vc_cons[currcons].d; 248 218 249 219 ret = -EINVAL; 250 220 if (pos < 0) ··· 381 367 ret = read; 382 368 unlock_out: 383 369 console_unlock(); 384 - mutex_unlock(&con_buf_mtx); 370 + free_page((unsigned long) con_buf); 385 371 return ret; 386 372 } 387 373 ··· 392 378 unsigned int currcons = iminor(inode); 393 379 struct vc_data *vc; 394 380 long pos; 395 - long viewed, attr, size, written; 381 + long attr, size, written; 396 382 char *con_buf0; 397 - int col, maxcol; 383 + int col, maxcol, viewed; 398 384 u16 *org0 = NULL, *org = NULL; 399 385 size_t ret; 386 + char *con_buf; 400 387 401 - mutex_lock(&con_buf_mtx); 388 + con_buf = (char *) __get_free_page(GFP_KERNEL); 389 + if (!con_buf) 390 + return -ENOMEM; 402 391 403 392 pos = *ppos; 404 393 ··· 411 394 console_lock(); 412 395 413 396 attr = (currcons & 128); 414 - currcons = (currcons & 127); 415 - 416 - if (currcons == 0) { 417 - currcons = fg_console; 418 - viewed = 1; 419 - } else { 420 - currcons--; 421 - viewed = 0; 422 - } 423 397 ret = -ENXIO; 424 - if (!vc_cons_allocated(currcons)) 398 + vc = vcs_vc(inode, &viewed); 399 + if (!vc) 425 400 goto unlock_out; 426 - vc = vc_cons[currcons].d; 427 401 428 402 size = vcs_size(inode); 429 403 ret = -EINVAL; ··· 569 561 570 562 unlock_out: 571 563 console_unlock(); 572 - 573 - mutex_unlock(&con_buf_mtx); 574 - 564 + free_page((unsigned long) con_buf); 575 565 return ret; 576 566 } 577 567
-12
drivers/tty/vt/vt.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 2071 /* is_double_width() is based on the wcwidth() implementation by 2084 2072 * Markus Kuhn -- 2007-05-26 (Unicode 5.0) 2085 2073 * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
-8
include/linux/vt_kern.h
··· 142 142 return false; 143 143 } 144 144 145 - /* 146 - * vc_screen.c shares this temporary buffer with the console write code so that 147 - * we can easily avoid touching user space while holding the console spinlock. 148 - */ 149 - 150 - #define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE) 151 - extern char con_buf[CON_BUF_SIZE]; 152 - extern struct mutex con_buf_mtx; 153 145 extern char vt_dont_switch; 154 146 extern int default_utf8; 155 147 extern int global_cursor_default;