Received: by 2002:ac0:98c7:0:0:0:0:0 with SMTP id g7-v6csp203989imd; Wed, 31 Oct 2018 17:25:44 -0700 (PDT) X-Google-Smtp-Source: AJdET5cBhO6Z7qrExhfoYt1yWBjfY78vQzX4ouqM1mSmC71Ac3SXvfCT7KlJxqyLPggUeu3wIgU3 X-Received: by 2002:a17:902:2924:: with SMTP id g33-v6mr5541157plb.76.1541031944322; Wed, 31 Oct 2018 17:25:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1541031944; cv=none; d=google.com; s=arc-20160816; b=q10ey6oklTSTJXGjLvoCFZLEmLLDOxiKrLijorCJjZVqhOtBg8eZQeY7XLrONXUv4W X3H80da8nDWBp8UesDND2bMkHtBWKMNu4C20/4Q2hFXvFZ3gM4g2tglqA7kDufJGY6Ae vt9oUrxbM7NCmWDmmmQzdfA9l0sAJkgIf0DJVK3kTZewbrBPeLv1CpH8LsoHLliYu82R dh3LEDZArBjuuKd5aeCTLuOjcKtcg2XV4uotP93ofO9n/G0DthddAe7RMl32V/ggP2lW U2Kk4mJNea/K1TSD95YuoZJJLYCZuAmUNwTz+jxk2kt/cn4WBx2IMSK4LPZ4LAcgta0f pqZw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=vXTWl8A4VzfUjFkIUP0VHJzOn4CYUXUd72JEuznvemU=; b=oWSYh3Ym4Zghv5YcWHHcDnccU886Ylr3zslWWS+0+wx6A8U1+aAs1jUDigM3AFcze9 wNnNsLD+FYL3Fjfv6YcmMmUjlRKbpKnxUbsvX5CvrmhWNbaeUal8L2mMqZVicsQDxFrC 2T9bm//qBntvy3xHhKBxAVg5AHl+VPLq97URsV4OFkmnYhkk5BUg+YgAUblxA92+nOjp 7fEaDz9dLWKByA/ZFbR3FJwQ6m10mKct37bqh689ZdjZLKxQerV5vKw1nC77vwLXzkyK XmdbcukpRiy4VLMtraDLbMvbXO2Yx/hsyp1o+EQnvjo6oRW2D7Phub2lgaeIflR6pWlb uofQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@arista.com header.s=googlenew header.b=IjMLk3J0; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=REJECT dis=NONE) header.from=arista.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p31-v6si24117834pgl.408.2018.10.31.17.25.29; Wed, 31 Oct 2018 17:25:44 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@arista.com header.s=googlenew header.b=IjMLk3J0; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=REJECT dis=NONE) header.from=arista.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727417AbeKAJZg (ORCPT + 99 others); Thu, 1 Nov 2018 05:25:36 -0400 Received: from mail-ed1-f67.google.com ([209.85.208.67]:40426 "EHLO mail-ed1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726012AbeKAJZe (ORCPT ); Thu, 1 Nov 2018 05:25:34 -0400 Received: by mail-ed1-f67.google.com with SMTP id z12-v6so9411255edp.7 for ; Wed, 31 Oct 2018 17:25:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=arista.com; s=googlenew; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=vXTWl8A4VzfUjFkIUP0VHJzOn4CYUXUd72JEuznvemU=; b=IjMLk3J0onJR0Bao6zT9Kbt1uO+SQMVmt/vWGvjqkhnksytozcJkH1M2YfLykRk0f3 8LyTYcUvGuzPWmHFHVYjwDyN2hpGFkLhFTKgHqtJqklYCrnkmSKQWPM9PjSdL/ibufoi 2Sq+xRC9JYro14l6rfXHPhZusEOqGbtNVSpT89zfobP3Y6rT0CRHaJWLGBkaQPItszvn 5Vy9NDwKdmfUVbhLPcpvOPncZoNUlMViBDb6nRhdGxlG68c0Ewzjs8xrw0EEC379MmpE x0AfrRyPBbqRhQLPU+P6MW16McROmEUcB16m/wQnYGRrwPAw/MgNT3S1IXmoXKZZOUL/ 8NJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=vXTWl8A4VzfUjFkIUP0VHJzOn4CYUXUd72JEuznvemU=; b=PPfHO9jg/TDqmyPTq9LeatWj7j9+VP7u7UR5EuYyugwZAELgxrO2kKqQh7DDYIrM9W 8I0m2nIUh1NMOw+zq3+JuP9bUEeJ/x3vm3Kwp1FWqTMy7vFljUPuQkzVBCr3IlVORMlq alp7B0uJRwvQgHkvN9uGwwTUB7AHimA/FdYdDkuVdrpWgzyjgwPO7ydFlWX6ILdrflMy WHqL456qbuEro7e6Sg9SeQenLgrxFDbrbbipsUOF6oYWFe8gdy+wUTvm/iXtWyZV1gsB ugwlHfk6k2ai9QAPWaUJAS9QkdFjaBukA9LGu8NJIhDK4vZjbYQJ4Jn8ofQA5JQwXT7i vG4g== X-Gm-Message-State: AGRZ1gKSb1pUH/5yoTaFg6bvXTFiaW9cFWmGLi1BHbUJai2zPvn/TF0G arN9PmOSJqGX6mXMN7zRw/07SLPKtdY= X-Received: by 2002:a50:b0e5:: with SMTP id j92-v6mr3625632edd.294.1541031899757; Wed, 31 Oct 2018 17:24:59 -0700 (PDT) Received: from Mindolluin.ire.aristanetworks.com ([217.173.96.166]) by smtp.gmail.com with ESMTPSA id s12-v6sm10188175edd.39.2018.10.31.17.24.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 31 Oct 2018 17:24:58 -0700 (PDT) From: Dmitry Safonov To: linux-kernel@vger.kernel.org Cc: Dmitry Safonov <0x7f454c46@gmail.com>, Dmitry Safonov , Daniel Axtens , Dmitry Vyukov , Mark Rutland , Michael Neuling , Mikulas Patocka , Nathan March , =?UTF-8?q?Pasi=20K=C3=A4rkk=C3=A4inen?= , Peter Hurley , Peter Zijlstra , "Rong, Chen" , Sergey Senozhatsky , Tan Xiaojun , Tetsuo Handa , Greg Kroah-Hartman , Jiri Slaby Subject: [PATCHv6 3/7] tty: Don't block on IO when ldisc change is pending Date: Thu, 1 Nov 2018 00:24:48 +0000 Message-Id: <20181101002452.5483-4-dima@arista.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181101002452.5483-1-dima@arista.com> References: <20181101002452.5483-1-dima@arista.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org There might be situations where tty_ldisc_lock() has blocked, but there is already IO on tty and it prevents line discipline changes. It might theoretically turn into dead-lock. Basically, provide more priority to pending tty_ldisc_lock() than to servicing reads/writes over tty. User-visible issue was reported by Mikulas where on pa-risc with Debian 5 reboot took either 80 seconds, 3 minutes or 3:25 after proper locking in tty_reopen(). Cc: Greg Kroah-Hartman Cc: Jiri Slaby Reported-by: Mikulas Patocka Signed-off-by: Dmitry Safonov --- drivers/tty/n_hdlc.c | 4 ++-- drivers/tty/n_r3964.c | 2 +- drivers/tty/n_tty.c | 8 ++++---- drivers/tty/tty_ldisc.c | 7 +++++++ include/linux/tty.h | 7 +++++++ 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index dabb391909aa..99460af61b77 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -612,7 +612,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, } /* no data */ - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { ret = -EAGAIN; break; } @@ -679,7 +679,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, if (tbuf) break; - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { error = -EAGAIN; break; } diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 749a608c40b0..f75696f0ee2d 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -1085,7 +1085,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, pMsg = remove_msg(pInfo, pClient); if (pMsg == NULL) { /* no messages available. */ - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { ret = -EAGAIN; goto unlock; } diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 3ad460219fd6..5dc9686697cf 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1702,7 +1702,7 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, down_read(&tty->termios_rwsem); - while (1) { + do { /* * When PARMRK is set, each input char may take up to 3 chars * in the read buf; reduce the buffer space avail by 3x @@ -1744,7 +1744,7 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, fp += n; count -= n; rcvd += n; - } + } while (!test_bit(TTY_LDISC_CHANGING, &tty->flags)); tty->receive_room = room; @@ -2211,7 +2211,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, break; if (!timeout) break; - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { retval = -EAGAIN; break; } @@ -2365,7 +2365,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, } if (!nr) break; - if (file->f_flags & O_NONBLOCK) { + if (tty_io_nonblock(tty, file)) { retval = -EAGAIN; break; } diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index fc4c97cae01e..9434d20cf3ca 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -327,6 +327,11 @@ int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) { int ret; + /* Kindly asking blocked readers to release the read side */ + set_bit(TTY_LDISC_CHANGING, &tty->flags); + wake_up_interruptible_all(&tty->read_wait); + wake_up_interruptible_all(&tty->write_wait); + ret = __tty_ldisc_lock(tty, timeout); if (!ret) return -EBUSY; @@ -337,6 +342,8 @@ int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) void tty_ldisc_unlock(struct tty_struct *tty) { clear_bit(TTY_LDISC_HALTED, &tty->flags); + /* Can be cleared here - ldisc_unlock will wake up writers firstly */ + clear_bit(TTY_LDISC_CHANGING, &tty->flags); __tty_ldisc_unlock(tty); } diff --git a/include/linux/tty.h b/include/linux/tty.h index 414db2bce715..80ae5528ef8e 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -366,6 +366,7 @@ struct tty_file_private { #define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */ #define TTY_HUPPED 18 /* Post driver->hangup() */ #define TTY_HUPPING 19 /* Hangup in progress */ +#define TTY_LDISC_CHANGING 20 /* Change pending - non-block IO */ #define TTY_LDISC_HALTED 22 /* Line discipline is halted */ /* Values for tty->flow_change */ @@ -383,6 +384,12 @@ static inline void tty_set_flow_change(struct tty_struct *tty, int val) smp_mb(); } +static inline bool tty_io_nonblock(struct tty_struct *tty, struct file *file) +{ + return file->f_flags & O_NONBLOCK || + test_bit(TTY_LDISC_CHANGING, &tty->flags); +} + static inline bool tty_io_error(struct tty_struct *tty) { return test_bit(TTY_IO_ERROR, &tty->flags); -- 2.19.1