Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753186AbcCLO1H (ORCPT ); Sat, 12 Mar 2016 09:27:07 -0500 Received: from mail-lb0-f182.google.com ([209.85.217.182]:36217 "EHLO mail-lb0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752964AbcCLO05 (ORCPT ); Sat, 12 Mar 2016 09:26:57 -0500 Date: Sat, 12 Mar 2016 17:18:30 +0300 From: Cyrill Gorcunov To: LKML Cc: Jiri Slaby , Peter Hurley , Greg Kroah-Hartman , Andrey Vagin , Pavel Emelianov , Vladimir Davydov , Konstantin Khorenko Subject: [RFC] tty: n_tty -- Add new TIOCPEEKRAW ioctl to peek unread data Message-ID: <20160312141830.GM1989@uranus.lan> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.24 (2015-08-30) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3623 Lines: 98 Currently when we checkpoint PTY connections we ignore data queued inside read buffer of ldisk, such data us barely lost after the restore. So we would like to improve the situation and being able to dump and restore it as well. Here is a new ioctl code which simply copies data from read buffer into the userspace without any additional processing (just like terminal is sitting in a raw mode). The idea behind is when we checkpointing PTY pair we peek this unread data into images on disk and on restore phase we find the linked peer and write it back thus reading peer will obtain it then. I tried several approaches (including simply reuse of canon_copy_from_read_buf and copy_from_read_buf) but it not always do the trick: for example if data queued doesn't have \n symbol the input_available_p helper returns false and I shouldn't call for the helpers above. Another proposal was to try to implement something like sys_tee but for tty layer (proposed by xemul@) but I drop this idea because it will require a lot of rework as far as I can say (including moving read buffer outside of the n_tty_data structure and such). Still this ioctl looks somewhat ugly to me so if someone has better idea how to fetch queued data from ldisk this would be awesome, please share. _Any_ comments are highly appreciated. Signed-off-by: Cyrill Gorcunov CC: Jiri Slaby CC: Peter Hurley CC: Greg Kroah-Hartman CC: Andrey Vagin CC: Pavel Emelianov CC: Vladimir Davydov CC: Konstantin Khorenko --- drivers/tty/n_tty.c | 22 ++++++++++++++++++++++ include/uapi/asm-generic/ioctls.h | 1 + 2 files changed, 23 insertions(+) Index: linux-ml.git/drivers/tty/n_tty.c =================================================================== --- linux-ml.git.orig/drivers/tty/n_tty.c +++ linux-ml.git/drivers/tty/n_tty.c @@ -2485,6 +2485,26 @@ static unsigned long inq_canon(struct n_ return nr; } +static ssize_t n_tty_peek_raw(struct tty_struct *tty, unsigned char __user *buf) +{ + struct n_tty_data *ldata = tty->disc_data; + ssize_t retval; + + if (!mutex_trylock(&ldata->atomic_read_lock)) + return -EAGAIN; + + down_read(&tty->termios_rwsem); + retval = read_cnt(ldata); + if (retval) { + const unsigned char *from = read_buf_addr(ldata, ldata->read_tail); + if (copy_to_user(buf, from, retval)) + retval = -EFAULT; + } + up_read(&tty->termios_rwsem); + mutex_unlock(&ldata->atomic_read_lock); + return retval; +} + static int n_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { @@ -2502,6 +2522,8 @@ static int n_tty_ioctl(struct tty_struct retval = read_cnt(ldata); up_write(&tty->termios_rwsem); return put_user(retval, (unsigned int __user *) arg); + case TIOCPEEKRAW: + return n_tty_peek_raw(tty, (unsigned char __user *) arg); default: return n_tty_ioctl_helper(tty, file, cmd, arg); } Index: linux-ml.git/include/uapi/asm-generic/ioctls.h =================================================================== --- linux-ml.git.orig/include/uapi/asm-generic/ioctls.h +++ linux-ml.git/include/uapi/asm-generic/ioctls.h @@ -77,6 +77,7 @@ #define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */ #define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */ #define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */ +#define TIOCPEEKRAW _IOR('T', 0x41, void *) #define FIONCLEX 0x5450 #define FIOCLEX 0x5451