From patchwork Sun Feb 6 15:48:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walt Drummond X-Patchwork-Id: 12736614 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 447CEC433EF for ; Sun, 6 Feb 2022 16:00:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244257AbiBFQAI (ORCPT ); Sun, 6 Feb 2022 11:00:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33382 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237803AbiBFQAH (ORCPT ); Sun, 6 Feb 2022 11:00:07 -0500 Received: from talisker.home.drummond.us (drummond.us [74.95.14.229]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 51D5DC06173B for ; Sun, 6 Feb 2022 08:00:07 -0800 (PST) Received: from talisker.home.drummond.us (localhost [127.0.0.1]) by talisker.home.drummond.us (8.15.2/8.15.2/Debian-20) with ESMTP id 216FnCIm2355965; Sun, 6 Feb 2022 07:49:12 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=home.drummond.us; s=default; t=1644162552; bh=C0SGrdD0bHER6z6tzFAueoA7f+uAqZowOEaDKBDt4aw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DhtOVt4f61DooeJVSmXijShgM7VraTmww4/6eaVCj2rydDXgCMSB/Y13Vi1m/3xDx KV8lyPqjGDJhQlqio1792gXowICHBJEZLXO3uuC8D1VtUxCDjUnQjeKpj53jf/GA+D 20HhEk4r4bWbXrLtDH++IkNTDsNvg1gcURNN/WB/k12SBS4tqAqbHwNb7jwmEsNH7o smPrQYVQikvzCPQGnL3RjGt9NeVnXWUXstMvHQCetN1Did/caYW0cD764om3kwBCMv 5/nArkFHBskLMQijfGlWBT9yfWP/dL+CTlvoygh8VMvinOSjdc60d/T+TfuM8QiIkW Dcw5LLKBwZRCg== Received: (from walt@localhost) by talisker.home.drummond.us (8.15.2/8.15.2/Submit) id 216FnBsV2355964; Sun, 6 Feb 2022 07:49:11 -0800 From: Walt Drummond To: agordeev@linux.ibm.com, arnd@arndb.de, benh@kernel.crashing.org, borntraeger@de.ibm.com, chris@zankel.net, davem@davemloft.net, gregkh@linuxfoundation.org, hca@linux.ibm.com, deller@gmx.de, ink@jurassic.park.msu.ru, James.Bottomley@HansenPartnership.com, jirislaby@kernel.org, mattst88@gmail.com, jcmvbkbc@gmail.com, mpe@ellerman.id.au, paulus@samba.org, rth@twiddle.net, dalias@libc.org, tsbogend@alpha.franken.de, gor@linux.ibm.com, ysato@users.osdn.me Cc: linux-kernel@vger.kernel.org, ar@cs.msu.ru, walt@drummond.us, linux-alpha@vger.kernel.org, linux-arch@vger.kernel.org, linux-ia64@vger.kernel.org, linux-mips@vger.kernel.org, linux-parisc@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org, linux-sh@vger.kernel.org, linux-xtensa@linux-xtensa.org, sparclinux@vger.kernel.org Subject: [PATCH v2 1/3] vstatus: Allow the n_tty line dicipline to write to a user tty Date: Sun, 6 Feb 2022 07:48:52 -0800 Message-Id: <20220206154856.2355838-2-walt@drummond.us> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220206154856.2355838-1-walt@drummond.us> References: <20220206154856.2355838-1-walt@drummond.us> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mips@vger.kernel.org Refactor the implementation of n_tty_write() into do_n_tty_write(), and change n_tty_write() to call do_n_tty_write() after acquiring tty.termios_rwsem. This allows the n_tty line dicipline to write to a user tty via do_n_tty_write() when already holding tty.termios_rwsem. Signed-off-by: Walt Drummond --- drivers/tty/n_tty.c | 69 +++++++++++++++++++++++++++------------------ include/linux/tty.h | 2 +- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 0ec93f1a61f5..64a058a4c63b 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2231,45 +2231,24 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, return retval; } -/** - * n_tty_write - write function for tty - * @tty: tty device - * @file: file object - * @buf: userspace buffer pointer - * @nr: size of I/O - * - * Write function of the terminal device. This is serialized with - * respect to other write callers but not to termios changes, reads - * and other such events. Since the receive code will echo characters, - * thus calling driver write methods, the output_lock is used in - * the output processing functions called here as well as in the - * echo processing function to protect the column state and space - * left in the buffer. - * - * This code must be sure never to sleep through a hangup. - * - * Locking: output_lock to protect column state and space left - * (note that the process_output*() functions take this - * lock themselves) - */ - -static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, - const unsigned char *buf, size_t nr) +static ssize_t do_n_tty_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t nr) { const unsigned char *b = buf; DEFINE_WAIT_FUNC(wait, woken_wake_function); int c; ssize_t retval = 0; + lockdep_assert_held_read(&tty->termios_rwsem); + /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ - if (L_TOSTOP(tty) && file->f_op->write_iter != redirected_tty_write) { + if (L_TOSTOP(tty) && + !(file && file->f_op->write_iter != redirected_tty_write)) { retval = tty_check_change(tty); if (retval) return retval; } - down_read(&tty->termios_rwsem); - /* Write out any echoed characters that are still pending */ process_echoes(tty); @@ -2336,10 +2315,44 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, remove_wait_queue(&tty->write_wait, &wait); if (nr && tty->fasync) set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - up_read(&tty->termios_rwsem); + return (b - buf) ? b - buf : retval; } +/** + * n_tty_write - write function for tty + * @tty: tty device + * @file: file object + * @buf: userspace buffer pointer + * @nr: size of I/O + * + * Write function of the terminal device. This is serialized with + * respect to other write callers but not to termios changes, reads + * and other such events. Since the receive code will echo characters, + * thus calling driver write methods, the output_lock is used in + * the output processing functions called here as well as in the + * echo processing function to protect the column state and space + * left in the buffer. + * + * This code must be sure never to sleep through a hangup. + * + * Locking: output_lock to protect column state and space left + * (note that the process_output*() functions take this + * lock themselves) + */ + +static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t nr) +{ + ssize_t retval = 0; + + down_read(&tty->termios_rwsem); + retval = do_n_tty_write(tty, file, buf, nr); + up_read(&tty->termios_rwsem); + + return retval; +} + /** * n_tty_poll - poll method for N_TTY * @tty: terminal device diff --git a/include/linux/tty.h b/include/linux/tty.h index 168e57e40bbb..cbe5d535a69d 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -237,7 +237,7 @@ struct tty_file_private { static inline bool tty_io_nonblock(struct tty_struct *tty, struct file *file) { - return file->f_flags & O_NONBLOCK || + return (file && file->f_flags & O_NONBLOCK) || test_bit(TTY_LDISC_CHANGING, &tty->flags); } From patchwork Sun Feb 6 15:48:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walt Drummond X-Patchwork-Id: 12736616 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5C905C43217 for ; Sun, 6 Feb 2022 16:00:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237803AbiBFQA4 (ORCPT ); Sun, 6 Feb 2022 11:00:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33992 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244493AbiBFQAw (ORCPT ); Sun, 6 Feb 2022 11:00:52 -0500 Received: from talisker.home.drummond.us (drummond.us [74.95.14.229]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 05CADC043188 for ; Sun, 6 Feb 2022 08:00:50 -0800 (PST) Received: from talisker.home.drummond.us (localhost [127.0.0.1]) by talisker.home.drummond.us (8.15.2/8.15.2/Debian-20) with ESMTP id 216FnFcx2355991; Sun, 6 Feb 2022 07:49:15 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=home.drummond.us; s=default; t=1644162555; bh=7WjDICKhQyle4ios60Wujz51yzrHyAgGXW0FdAX5LKA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jEHR7t9I6Z01rIBKHMFEJWOPInp2qdkBjHW1DWmjQygEelBTBWuPBCSnJs4uhZQGC w9Ai5svPwtB0yRjx0J2JPpVMDyL+X2gFzBKvRapq8hHpXcOL/CWvvgXCfraKpEmyyx nwTQz6rkeMIHqv2Pc2iYwX6IZv9Q4iDVqnPR2dLowtQOfdkXjT4KqUXTj8+wJKEhvu HNjK8gCoPfULPg+ThGLUeRdpGIlidb5BvoTp48/Uu3cEKz3cDN18Axadfg5XShRIDJ asSxyOTKLtSibtgW4tHTnYrELjLANpK/naXJKJJTSn8lgpXXsmqwvzSUeS6g1H+zEH eNXFdrgf6RU0A== Received: (from walt@localhost) by talisker.home.drummond.us (8.15.2/8.15.2/Submit) id 216FnEuN2355990; Sun, 6 Feb 2022 07:49:14 -0800 From: Walt Drummond To: agordeev@linux.ibm.com, arnd@arndb.de, benh@kernel.crashing.org, borntraeger@de.ibm.com, chris@zankel.net, davem@davemloft.net, gregkh@linuxfoundation.org, hca@linux.ibm.com, deller@gmx.de, ink@jurassic.park.msu.ru, James.Bottomley@HansenPartnership.com, jirislaby@kernel.org, mattst88@gmail.com, jcmvbkbc@gmail.com, mpe@ellerman.id.au, paulus@samba.org, rth@twiddle.net, dalias@libc.org, tsbogend@alpha.franken.de, gor@linux.ibm.com, ysato@users.osdn.me Cc: linux-kernel@vger.kernel.org, ar@cs.msu.ru, walt@drummond.us, linux-alpha@vger.kernel.org, linux-arch@vger.kernel.org, linux-ia64@vger.kernel.org, linux-mips@vger.kernel.org, linux-parisc@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org, linux-sh@vger.kernel.org, linux-xtensa@linux-xtensa.org, sparclinux@vger.kernel.org Subject: [PATCH v2 2/3] status: Add user space API definitions for VSTATUS, NOKERNINFO and TIOCSTAT Date: Sun, 6 Feb 2022 07:48:53 -0800 Message-Id: <20220206154856.2355838-3-walt@drummond.us> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220206154856.2355838-1-walt@drummond.us> References: <20220206154856.2355838-1-walt@drummond.us> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mips@vger.kernel.org Add definitions for the VSTATUS control character, and the NOKERNINFO local control flag in the termios struct, and add an ioctl number for the ioctl TIOCSTAT. Also add a default VSTATUS character (Ctrl-T) default valuses in termios.c_cc. Do this for all architectures. Signed-off-by: Walt Drummond --- arch/alpha/include/asm/termios.h | 4 ++-- arch/alpha/include/uapi/asm/ioctls.h | 1 + arch/alpha/include/uapi/asm/termbits.h | 2 ++ arch/ia64/include/asm/termios.h | 4 ++-- arch/ia64/include/uapi/asm/termbits.h | 2 ++ arch/mips/include/asm/termios.h | 4 ++-- arch/mips/include/uapi/asm/ioctls.h | 1 + arch/mips/include/uapi/asm/termbits.h | 2 ++ arch/parisc/include/asm/termios.h | 4 ++-- arch/parisc/include/uapi/asm/ioctls.h | 1 + arch/parisc/include/uapi/asm/termbits.h | 2 ++ arch/powerpc/include/asm/termios.h | 4 ++-- arch/powerpc/include/uapi/asm/ioctls.h | 2 ++ arch/powerpc/include/uapi/asm/termbits.h | 2 ++ arch/s390/include/asm/termios.h | 4 ++-- arch/sh/include/uapi/asm/ioctls.h | 1 + arch/sparc/include/uapi/asm/ioctls.h | 1 + arch/sparc/include/uapi/asm/termbits.h | 2 ++ arch/xtensa/include/uapi/asm/ioctls.h | 1 + include/asm-generic/termios.h | 4 ++-- include/uapi/asm-generic/ioctls.h | 1 + include/uapi/asm-generic/termbits.h | 2 ++ 22 files changed, 37 insertions(+), 14 deletions(-) diff --git a/arch/alpha/include/asm/termios.h b/arch/alpha/include/asm/termios.h index b7c77bb1bfd2..d28ddc649286 100644 --- a/arch/alpha/include/asm/termios.h +++ b/arch/alpha/include/asm/termios.h @@ -8,9 +8,9 @@ werase=^W kill=^U reprint=^R sxtc=\0 intr=^C quit=^\ susp=^Z start=^Q stop=^S lnext=^V discard=^U - vmin=\1 vtime=\0 + vmin=\1 vtime=\0 status=^T */ -#define INIT_C_CC "\004\000\000\177\027\025\022\000\003\034\032\000\021\023\026\025\001\000" +#define INIT_C_CC "\004\000\000\177\027\025\022\000\003\034\032\000\021\023\026\025\001\000\024" /* * Translate a "termio" structure into a "termios". Ugh. diff --git a/arch/alpha/include/uapi/asm/ioctls.h b/arch/alpha/include/uapi/asm/ioctls.h index 971311605288..70fdeab2b5f2 100644 --- a/arch/alpha/include/uapi/asm/ioctls.h +++ b/arch/alpha/include/uapi/asm/ioctls.h @@ -124,5 +124,6 @@ #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSTAT _IO('T', 0x5E) /* display process group stats on tty */ #endif /* _ASM_ALPHA_IOCTLS_H */ diff --git a/arch/alpha/include/uapi/asm/termbits.h b/arch/alpha/include/uapi/asm/termbits.h index 4575ba34a0ea..9a1b9aa92d29 100644 --- a/arch/alpha/include/uapi/asm/termbits.h +++ b/arch/alpha/include/uapi/asm/termbits.h @@ -70,6 +70,7 @@ struct ktermios { #define VDISCARD 15 #define VMIN 16 #define VTIME 17 +#define VSTATUS 18 /* c_iflag bits */ #define IGNBRK 0000001 @@ -203,6 +204,7 @@ struct ktermios { #define PENDIN 0x20000000 #define IEXTEN 0x00000400 #define EXTPROC 0x10000000 +#define NOKERNINFO 0x40000000 /* Values for the ACTION argument to `tcflow'. */ #define TCOOFF 0 diff --git a/arch/ia64/include/asm/termios.h b/arch/ia64/include/asm/termios.h index 589c026444cc..40e83f9b6ead 100644 --- a/arch/ia64/include/asm/termios.h +++ b/arch/ia64/include/asm/termios.h @@ -15,9 +15,9 @@ eof=^D vtime=\0 vmin=\1 sxtc=\0 start=^Q stop=^S susp=^Z eol=\0 reprint=^R discard=^U werase=^W lnext=^V - eol2=\0 + eol2=\0 status=^T */ -#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0\024" /* * Translate a "termio" structure into a "termios". Ugh. diff --git a/arch/ia64/include/uapi/asm/termbits.h b/arch/ia64/include/uapi/asm/termbits.h index 000a1a297c75..0b5fea00343b 100644 --- a/arch/ia64/include/uapi/asm/termbits.h +++ b/arch/ia64/include/uapi/asm/termbits.h @@ -67,6 +67,7 @@ struct ktermios { #define VWERASE 14 #define VLNEXT 15 #define VEOL2 16 +#define VSTATUS 17 /* c_iflag bits */ #define IGNBRK 0000001 @@ -189,6 +190,7 @@ struct ktermios { #define PENDIN 0040000 #define IEXTEN 0100000 #define EXTPROC 0200000 +#define NOKERNINFO 0400000 /* tcflow() and TCXONC use these */ #define TCOOFF 0 diff --git a/arch/mips/include/asm/termios.h b/arch/mips/include/asm/termios.h index bc29eeacc55a..04729018d882 100644 --- a/arch/mips/include/asm/termios.h +++ b/arch/mips/include/asm/termios.h @@ -17,9 +17,9 @@ * vmin=\1 vtime=\0 eol2=\0 swtc=\0 * start=^Q stop=^S susp=^Z vdsusp= * reprint=^R discard=^U werase=^W lnext=^V - * eof=^D eol=\0 + * eof=^D eol=\0 status=^T */ -#define INIT_C_CC "\003\034\177\025\1\0\0\0\021\023\032\0\022\017\027\026\004\0" +#define INIT_C_CC "\003\034\177\025\1\0\0\0\021\023\032\0\022\017\027\026\004\0\024" #include diff --git a/arch/mips/include/uapi/asm/ioctls.h b/arch/mips/include/uapi/asm/ioctls.h index 16aa8a766aec..f9ec28ac38db 100644 --- a/arch/mips/include/uapi/asm/ioctls.h +++ b/arch/mips/include/uapi/asm/ioctls.h @@ -115,5 +115,6 @@ #define TIOCSERSETMULTI 0x5490 /* Set multiport config */ #define TIOCMIWAIT 0x5491 /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x5492 /* read serial port inline interrupt counts */ +#define TIOCSTAT _IO('T', 0x93) /* display process group stats on tty */ #endif /* __ASM_IOCTLS_H */ diff --git a/arch/mips/include/uapi/asm/termbits.h b/arch/mips/include/uapi/asm/termbits.h index dfeffba729b7..a10be13a6f7b 100644 --- a/arch/mips/include/uapi/asm/termbits.h +++ b/arch/mips/include/uapi/asm/termbits.h @@ -78,6 +78,7 @@ struct ktermios { #define VLNEXT 15 /* Literal-next character [IEXTEN]. */ #define VEOF 16 /* End-of-file character [ICANON]. */ #define VEOL 17 /* End-of-line character [ICANON]. */ +#define VSTATUS 18 /* c_iflag bits */ #define IGNBRK 0000001 /* Ignore break condition. */ @@ -205,6 +206,7 @@ struct ktermios { #define TOSTOP 0100000 /* Send SIGTTOU for background output. */ #define ITOSTOP TOSTOP #define EXTPROC 0200000 /* External processing on pty */ +#define NOKERNINFO 0400000 /* Disable kernel status message */ /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ diff --git a/arch/parisc/include/asm/termios.h b/arch/parisc/include/asm/termios.h index cded9dc90c1b..63c6c7edb0ff 100644 --- a/arch/parisc/include/asm/termios.h +++ b/arch/parisc/include/asm/termios.h @@ -9,9 +9,9 @@ eof=^D vtime=\0 vmin=\1 sxtc=\0 start=^Q stop=^S susp=^Z eol=\0 reprint=^R discard=^U werase=^W lnext=^V - eol2=\0 + eol2=\0 status=^T */ -#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0\024" /* * Translate a "termio" structure into a "termios". Ugh. diff --git a/arch/parisc/include/uapi/asm/ioctls.h b/arch/parisc/include/uapi/asm/ioctls.h index 82d1148c6379..1ac156dd8209 100644 --- a/arch/parisc/include/uapi/asm/ioctls.h +++ b/arch/parisc/include/uapi/asm/ioctls.h @@ -80,6 +80,7 @@ #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSTAT _IO('T', 0x5E) /* display process group stats on tty */ #define FIOQSIZE 0x5460 /* Get exact space used by quota */ #define TIOCSTART 0x5461 diff --git a/arch/parisc/include/uapi/asm/termbits.h b/arch/parisc/include/uapi/asm/termbits.h index 40e920f8d683..b449d8ea1c00 100644 --- a/arch/parisc/include/uapi/asm/termbits.h +++ b/arch/parisc/include/uapi/asm/termbits.h @@ -58,6 +58,7 @@ struct ktermios { #define VWERASE 14 #define VLNEXT 15 #define VEOL2 16 +#define VSTATUS 17 /* c_iflag bits */ @@ -182,6 +183,7 @@ struct ktermios { #define PENDIN 0040000 #define IEXTEN 0100000 #define EXTPROC 0200000 +#define NOKERNINFO 0400000 /* tcflow() and TCXONC use these */ #define TCOOFF 0 diff --git a/arch/powerpc/include/asm/termios.h b/arch/powerpc/include/asm/termios.h index 205de8f8a9d3..e5381c8f86f0 100644 --- a/arch/powerpc/include/asm/termios.h +++ b/arch/powerpc/include/asm/termios.h @@ -10,8 +10,8 @@ #include -/* ^C ^\ del ^U ^D 1 0 0 0 0 ^W ^R ^Z ^Q ^S ^V ^U */ -#define INIT_C_CC "\003\034\177\025\004\001\000\000\000\000\027\022\032\021\023\026\025" +/* ^C ^\ del ^U ^D 1 0 0 0 0 ^W ^R ^Z ^Q ^S ^V ^U ^T */ +#define INIT_C_CC "\003\034\177\025\004\001\000\000\000\000\027\022\032\021\023\026\025\024" #include diff --git a/arch/powerpc/include/uapi/asm/ioctls.h b/arch/powerpc/include/uapi/asm/ioctls.h index 2c145da3b774..0a0755863500 100644 --- a/arch/powerpc/include/uapi/asm/ioctls.h +++ b/arch/powerpc/include/uapi/asm/ioctls.h @@ -120,4 +120,6 @@ #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSTAT _IO('T', 0x5E) /* display process group stats on tty */ + #endif /* _ASM_POWERPC_IOCTLS_H */ diff --git a/arch/powerpc/include/uapi/asm/termbits.h b/arch/powerpc/include/uapi/asm/termbits.h index ed18bc61f63d..50d787d95c91 100644 --- a/arch/powerpc/include/uapi/asm/termbits.h +++ b/arch/powerpc/include/uapi/asm/termbits.h @@ -62,6 +62,7 @@ struct ktermios { #define VSTOP 14 #define VLNEXT 15 #define VDISCARD 16 +#define VSTATUS 17 /* c_iflag bits */ #define IGNBRK 0000001 @@ -191,6 +192,7 @@ struct ktermios { #define PENDIN 0x20000000 #define IEXTEN 0x00000400 #define EXTPROC 0x10000000 +#define NOKERNINFO 0x40000000 /* Values for the ACTION argument to `tcflow'. */ #define TCOOFF 0 diff --git a/arch/s390/include/asm/termios.h b/arch/s390/include/asm/termios.h index 46fa3020b41e..8d2017f4905d 100644 --- a/arch/s390/include/asm/termios.h +++ b/arch/s390/include/asm/termios.h @@ -14,9 +14,9 @@ eof=^D vtime=\0 vmin=\1 sxtc=\0 start=^Q stop=^S susp=^Z eol=\0 reprint=^R discard=^U werase=^W lnext=^V - eol2=\0 + eol2=\0 vstatus=^T */ -#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0\024" #define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2)) #define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2)) diff --git a/arch/sh/include/uapi/asm/ioctls.h b/arch/sh/include/uapi/asm/ioctls.h index 11866d4f60e1..fefef10922ec 100644 --- a/arch/sh/include/uapi/asm/ioctls.h +++ b/arch/sh/include/uapi/asm/ioctls.h @@ -112,5 +112,6 @@ #define TIOCMIWAIT _IO('T', 92) /* 0x545C */ /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSTAT _IO('T', 0x5F) /* display process group stats on tty */ #endif /* __ASM_SH_IOCTLS_H */ diff --git a/arch/sparc/include/uapi/asm/ioctls.h b/arch/sparc/include/uapi/asm/ioctls.h index 7fd2f5873c9e..9819090bd850 100644 --- a/arch/sparc/include/uapi/asm/ioctls.h +++ b/arch/sparc/include/uapi/asm/ioctls.h @@ -124,6 +124,7 @@ #define TIOCSERSETMULTI 0x545B /* Set multiport config */ #define TIOCMIWAIT 0x545C /* Wait for change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* Read serial port inline interrupt counts */ +#define TIOCSTAT _IO('T', 0x5E) /* Display process group stats on tty */ /* Kernel definitions */ diff --git a/arch/sparc/include/uapi/asm/termbits.h b/arch/sparc/include/uapi/asm/termbits.h index ce5ad5d0f105..b8441ce42278 100644 --- a/arch/sparc/include/uapi/asm/termbits.h +++ b/arch/sparc/include/uapi/asm/termbits.h @@ -80,6 +80,7 @@ struct ktermios { #define VDISCARD 13 #define VWERASE 14 #define VLNEXT 15 +#define VSTATUS 16 /* Kernel keeps vmin/vtime separated, user apps assume vmin/vtime is * shared with eof/eol @@ -224,6 +225,7 @@ struct ktermios { #define PENDIN 0x00004000 #define IEXTEN 0x00008000 #define EXTPROC 0x00010000 +#define NOKERNINFO 0x00020000 /* modem lines */ #define TIOCM_LE 0x001 diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h index 6d4a87296c95..f92fb8e5b2a5 100644 --- a/arch/xtensa/include/uapi/asm/ioctls.h +++ b/arch/xtensa/include/uapi/asm/ioctls.h @@ -126,5 +126,6 @@ #define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSTAT _IO('T', 0x5E) /* display process group stats on tty */ #endif /* _XTENSA_IOCTLS_H */ diff --git a/include/asm-generic/termios.h b/include/asm-generic/termios.h index b1398d0d4a1d..9b080e1a82d4 100644 --- a/include/asm-generic/termios.h +++ b/include/asm-generic/termios.h @@ -10,9 +10,9 @@ eof=^D vtime=\0 vmin=\1 sxtc=\0 start=^Q stop=^S susp=^Z eol=\0 reprint=^R discard=^U werase=^W lnext=^V - eol2=\0 + eol2=\0 status=^T */ -#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0\024" /* * Translate a "termio" structure into a "termios". Ugh. diff --git a/include/uapi/asm-generic/ioctls.h b/include/uapi/asm-generic/ioctls.h index cdc9f4ca8c27..02ceb990ce9b 100644 --- a/include/uapi/asm-generic/ioctls.h +++ b/include/uapi/asm-generic/ioctls.h @@ -97,6 +97,7 @@ #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCSTAT _IO('T', 0x5E) /* display process group stats on tty */ /* * Some arches already define FIOQSIZE due to a historical diff --git a/include/uapi/asm-generic/termbits.h b/include/uapi/asm-generic/termbits.h index 2fbaf9ae89dd..6219803d6f4d 100644 --- a/include/uapi/asm-generic/termbits.h +++ b/include/uapi/asm-generic/termbits.h @@ -58,6 +58,7 @@ struct ktermios { #define VWERASE 14 #define VLNEXT 15 #define VEOL2 16 +#define VSTATUS 17 /* c_iflag bits */ #define IGNBRK 0000001 @@ -180,6 +181,7 @@ struct ktermios { #define PENDIN 0040000 #define IEXTEN 0100000 #define EXTPROC 0200000 +#define NOKERNINFO 0400000 /* tcflow() and TCXONC use these */ #define TCOOFF 0 From patchwork Sun Feb 6 15:48:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Walt Drummond X-Patchwork-Id: 12736615 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5E73BC4332F for ; Sun, 6 Feb 2022 16:00:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239739AbiBFQA3 (ORCPT ); Sun, 6 Feb 2022 11:00:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33660 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237803AbiBFQA2 (ORCPT ); Sun, 6 Feb 2022 11:00:28 -0500 Received: from talisker.home.drummond.us (drummond.us [74.95.14.229]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E8209C043188 for ; Sun, 6 Feb 2022 08:00:26 -0800 (PST) Received: from talisker.home.drummond.us (localhost [127.0.0.1]) by talisker.home.drummond.us (8.15.2/8.15.2/Debian-20) with ESMTP id 216FnImH2356038; Sun, 6 Feb 2022 07:49:18 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=home.drummond.us; s=default; t=1644162558; bh=aNgt1OQUFA8f0/r3D51wP/eI84n4kfaRWwTm3a27CXw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IBLnk4LAbv4sGw2NOq3HCzWLaF46Wkffs7++cRNl9bGKKkse1q4NxLObP5U/gZnxz q2OqNmFrgPnnS0uYr0Krdi/m/t39A7YWYmVEQLWB1kowtrOnO0iNgM1HA+DvpO11Fw kazlNsBZrUDscPme1S9j/ygWRW6KWNcLZ+9hxKNfwTzq2CLFqU2bgMXMAspPIhrlvW hWH1A0Bc5RRU/MufBKXhoSNV17NP9eRcJEHv216JyhbtvUdMvdVQwRlfhH1NSZ/bE/ SzZ5TXqJCCjP9n3Jd7PdT01q+t3+C/tuKdyIdubbia60izTs/pcGrdcSsmLPeIjXxL JJPEMsgpAMPFA== Received: (from walt@localhost) by talisker.home.drummond.us (8.15.2/8.15.2/Submit) id 216FnH8P2356037; Sun, 6 Feb 2022 07:49:17 -0800 From: Walt Drummond To: agordeev@linux.ibm.com, arnd@arndb.de, benh@kernel.crashing.org, borntraeger@de.ibm.com, chris@zankel.net, davem@davemloft.net, gregkh@linuxfoundation.org, hca@linux.ibm.com, deller@gmx.de, ink@jurassic.park.msu.ru, James.Bottomley@HansenPartnership.com, jirislaby@kernel.org, mattst88@gmail.com, jcmvbkbc@gmail.com, mpe@ellerman.id.au, paulus@samba.org, rth@twiddle.net, dalias@libc.org, tsbogend@alpha.franken.de, gor@linux.ibm.com, ysato@users.osdn.me Cc: linux-kernel@vger.kernel.org, ar@cs.msu.ru, walt@drummond.us, linux-alpha@vger.kernel.org, linux-arch@vger.kernel.org, linux-ia64@vger.kernel.org, linux-mips@vger.kernel.org, linux-parisc@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org, linux-sh@vger.kernel.org, linux-xtensa@linux-xtensa.org, sparclinux@vger.kernel.org Subject: [PATCH v2 3/3] vstatus: Display an informational message when the VSTATUS character is pressed or TIOCSTAT ioctl is called. Date: Sun, 6 Feb 2022 07:48:54 -0800 Message-Id: <20220206154856.2355838-4-walt@drummond.us> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220206154856.2355838-1-walt@drummond.us> References: <20220206154856.2355838-1-walt@drummond.us> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mips@vger.kernel.org When triggered by pressing the VSTATUS key or calling the TIOCSTAT ioctl, the n_tty line discipline will display a message on the user's tty that provides basic information about the system and an 'interesting' process in the current foreground process group, eg: load: 0.58 cmd: sleep 744474 [sleeping] 0.36r 0.00u 0.00s 0% 772k The status message provides: - System load average - Command name and process id (from the perspective of the session) - Scheduler state - Total wall-clock run time - User space run time - System space run time - Percentage of on-cpu time - Resident set size The message is only displayed when the tty has the VSTATUS character set, the local flags ICANON and IEXTEN are enabled and NOKERNINFO is disabled; it is always displayed when TIOCSTAT is called regardless of tty settings. Signed-off-by: Walt Drummond --- drivers/tty/Makefile | 2 +- drivers/tty/n_tty.c | 34 +++++++ drivers/tty/n_tty_status.c | 181 +++++++++++++++++++++++++++++++++++++ drivers/tty/tty_io.c | 2 +- include/linux/tty.h | 5 + 5 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 drivers/tty/n_tty_status.c diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index a2bd75fbaaa4..3539d7ab77e5 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_TTY) += tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o \ tty_buffer.o tty_port.o tty_mutex.o \ tty_ldsem.o tty_baudrate.o tty_jobctrl.o \ - n_null.o + n_null.o n_tty_status.o obj-$(CONFIG_LEGACY_PTYS) += pty.o obj-$(CONFIG_UNIX98_PTYS) += pty.o obj-$(CONFIG_AUDIT) += tty_audit.o diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 64a058a4c63b..fd70efc333d7 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -80,6 +80,7 @@ #define ECHO_BLOCK 256 #define ECHO_DISCARD_WATERMARK N_TTY_BUF_SIZE - (ECHO_BLOCK + 32) +#define STATUS_LINE_LEN 160 /* tty status line will truncate at this length */ #undef N_TTY_TRACE #ifdef N_TTY_TRACE @@ -127,6 +128,8 @@ struct n_tty_data { struct mutex output_lock; }; +static void n_tty_status(struct tty_struct *tty); + #define MASK(x) ((x) & (N_TTY_BUF_SIZE - 1)) static inline size_t read_cnt(struct n_tty_data *ldata) @@ -1334,6 +1337,11 @@ static void n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) commit_echoes(tty); return; } + if (c == STATUS_CHAR(tty) && L_IEXTEN(tty)) { + if (!L_NOKERNINFO(tty)) + n_tty_status(tty); + return; + } if (c == '\n') { if (L_ECHO(tty) || L_ECHONL(tty)) { echo_char_raw('\n', ldata); @@ -1763,6 +1771,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) set_bit(EOF_CHAR(tty), ldata->char_map); set_bit('\n', ldata->char_map); set_bit(EOL_CHAR(tty), ldata->char_map); + set_bit(STATUS_CHAR(tty), ldata->char_map); if (L_IEXTEN(tty)) { set_bit(WERASE_CHAR(tty), ldata->char_map); set_bit(LNEXT_CHAR(tty), ldata->char_map); @@ -2413,6 +2422,26 @@ static unsigned long inq_canon(struct n_tty_data *ldata) return nr; } +static void n_tty_status(struct tty_struct *tty) +{ + struct n_tty_data *ldata = tty->disc_data; + char *msg; + size_t len; + + msg = kzalloc(STATUS_LINE_LEN, GFP_KERNEL); + + if (ldata->column != 0) { + *msg = '\n'; + len = n_tty_get_status(tty, msg + 1, STATUS_LINE_LEN - 1); + } else { + len = n_tty_get_status(tty, msg, STATUS_LINE_LEN); + } + + do_n_tty_write(tty, NULL, msg, len); + + kfree(msg); +} + static int n_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { @@ -2430,6 +2459,11 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, retval = read_cnt(ldata); up_write(&tty->termios_rwsem); return put_user(retval, (unsigned int __user *) arg); + case TIOCSTAT: + down_read(&tty->termios_rwsem); + n_tty_status(tty); + up_read(&tty->termios_rwsem); + return 0; default: return n_tty_ioctl_helper(tty, file, cmd, arg); } diff --git a/drivers/tty/n_tty_status.c b/drivers/tty/n_tty_status.c new file mode 100644 index 000000000000..f0e053651368 --- /dev/null +++ b/drivers/tty/n_tty_status.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-1.0+ +/* + * n_tty_status.c --- implements VSTATUS and TIOCSTAT from BSD + * + * Display a basic status message containing information about the + * foreground process and system load on the users tty, triggered by + * the VSTATUS character or TIOCSTAT. Ex, + * + * load: 14.11 cmd: tcsh 19623 [running] 185756.62r 88.00u 17.50s 0% 4260k + * + */ + +#include +#include +#include +#include + +/* Convert nanoseconds into centiseconds */ +static inline long ns_to_cs(long l) +{ + return l / (NSEC_PER_MSEC * 10); + +} + +/* We want the pid from the context of session */ +static inline pid_t __get_pid(struct task_struct *tsk, struct tty_struct *tty) +{ + struct pid_namespace *ns; + + spin_lock_irq(&tty->ctrl.lock); + ns = ns_of_pid(tty->ctrl.session); + spin_unlock_irq(&tty->ctrl.lock); + + return __task_pid_nr_ns(tsk, PIDTYPE_PID, ns); +} + +/* This is the same odd "bitmap" described in + * fs/proc/array.c:get_task_state(). Consistency with standard + * implementations of VSTATUS requires a different set of state + * names. + */ +static const char * const task_state_name_array[] = { + "running", + "sleeping", + "disk sleep", + "stopped", + "tracing stop", + "dead", + "zombie", + "parked", + "idle", +}; + +static inline const char *get_task_state_name(struct task_struct *tsk) +{ + BUILD_BUG_ON(1 + ilog2(TASK_REPORT_MAX) != ARRAY_SIZE(task_state_name_array)); + return task_state_name_array[task_state_index(tsk)]; +} + +static inline struct task_struct *compare(struct task_struct *new, + struct task_struct *old) +{ + unsigned int ostate, nstate; + + if (old == NULL) + return new; + + ostate = task_state_index(old); + nstate = task_state_index(new); + + if (ostate == nstate) { + if (old->start_time > new->start_time) + return old; + return new; + } + + if (ostate < nstate) + return old; + + return new; +} + +static struct task_struct *pick_process(struct tty_struct *tty) +{ + struct task_struct *new, *winner = NULL; + + read_lock(&tasklist_lock); + spin_lock_irq(&tty->ctrl.lock); + + do_each_pid_task(tty->ctrl.pgrp, PIDTYPE_PGID, new) { + winner = compare(new, winner); + } while_each_pid_task(tty->ctrl.pgrp, PIDTYPE_PGID, new); + + spin_unlock_irq(&tty->ctrl.lock); + + if (winner) + winner = get_task_struct(winner); + + read_unlock(&tasklist_lock); + + return winner; +} + +size_t n_tty_get_status(struct tty_struct *tty, char *msg, size_t msglen) +{ + struct task_struct *p; + struct mm_struct *mm; + struct rusage rusage; + unsigned long loadavg[3]; + uint64_t pcpu, cputime, wallclock; + struct timespec64 utime, stime, rtime; + char tname[TASK_COMM_LEN]; + unsigned int pid; + char *state; + unsigned long rss = 0; + size_t len = 0; + + get_avenrun(loadavg, FIXED_1/200, 0); + len = scnprintf(msg + len, msglen - len, "load: %lu.%02lu ", + LOAD_INT(loadavg[0]), LOAD_FRAC(loadavg[0])); + + if (tty->ctrl.session == NULL) { + len += scnprintf(msg + len, msglen - len, + "not a controlling terminal\n"); + goto out; + } + + if (tty->ctrl.pgrp == NULL) { + len += scnprintf(msg + len, msglen - len, + "no foreground process group\n"); + goto out; + } + + /* Note that if p is refcounted */ + p = pick_process(tty); + if (p == NULL) { + len += scnprintf(msg + len, msglen - len, + "empty foreground process group\n"); + goto out; + } + + mm = get_task_mm(p); + if (mm) { + rss = get_mm_rss(mm) * PAGE_SIZE / 1024; + mmput(mm); + } + get_task_comm(tname, p); + getrusage(p, RUSAGE_BOTH, &rusage); + pid = __get_pid(p, tty); + state = (char *) get_task_state_name(p); + wallclock = ktime_get_ns() - p->start_time; + put_task_struct(p); + + /* After this point, any of the information we have on p might + * become stale. It's OK if the status message is a little bit + * lossy. + */ + + utime.tv_sec = rusage.ru_utime.tv_sec; + utime.tv_nsec = rusage.ru_utime.tv_usec * NSEC_PER_USEC; + stime.tv_sec = rusage.ru_stime.tv_sec; + stime.tv_nsec = rusage.ru_stime.tv_usec * NSEC_PER_USEC; + rtime = ns_to_timespec64(wallclock); + + cputime = timespec64_to_ns(&utime) + timespec64_to_ns(&stime); + pcpu = div64_u64(cputime * 100, wallclock); + + len += scnprintf(msg + len, msglen - len, + /* task, PID, task state */ + "cmd: %s %d [%s] " + /* rtime, utime, stime, %cpu rss */ + "%llu.%02lur %llu.%02luu %llu.%02lus %llu%% %luk\n", + tname, pid, state, + rtime.tv_sec, ns_to_cs(rtime.tv_nsec), + utime.tv_sec, ns_to_cs(utime.tv_nsec), + stime.tv_sec, ns_to_cs(stime.tv_nsec), + pcpu, rss); + +out: + return len; +} diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 6616d4a0d41d..f2f4f48ea502 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -125,7 +125,7 @@ struct ktermios tty_std_termios = { /* for the benefit of tty drivers */ .c_oflag = OPOST | ONLCR, .c_cflag = B38400 | CS8 | CREAD | HUPCL, .c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | - ECHOCTL | ECHOKE | IEXTEN, + ECHOCTL | ECHOKE | IEXTEN | NOKERNINFO, .c_cc = INIT_C_CC, .c_ispeed = 38400, .c_ospeed = 38400, diff --git a/include/linux/tty.h b/include/linux/tty.h index cbe5d535a69d..2e483708608c 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -49,6 +49,7 @@ #define WERASE_CHAR(tty) ((tty)->termios.c_cc[VWERASE]) #define LNEXT_CHAR(tty) ((tty)->termios.c_cc[VLNEXT]) #define EOL2_CHAR(tty) ((tty)->termios.c_cc[VEOL2]) +#define STATUS_CHAR(tty) ((tty)->termios.c_cc[VSTATUS]) #define _I_FLAG(tty, f) ((tty)->termios.c_iflag & (f)) #define _O_FLAG(tty, f) ((tty)->termios.c_oflag & (f)) @@ -114,6 +115,7 @@ #define L_PENDIN(tty) _L_FLAG((tty), PENDIN) #define L_IEXTEN(tty) _L_FLAG((tty), IEXTEN) #define L_EXTPROC(tty) _L_FLAG((tty), EXTPROC) +#define L_NOKERNINFO(tty) _L_FLAG((tty), NOKERNINFO) struct device; struct signal_struct; @@ -389,6 +391,9 @@ extern void __init n_tty_init(void); static inline void n_tty_init(void) { } #endif +/* n_tty_status.c */ +size_t n_tty_get_status(struct tty_struct *tty, char *msg, size_t msglen); + /* tty_audit.c */ #ifdef CONFIG_AUDIT extern void tty_audit_exit(void);