Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp384734imu; Wed, 2 Jan 2019 08:30:20 -0800 (PST) X-Google-Smtp-Source: AFSGD/XhXFfsfeoAqHXsaxyGdLHoAZHA0jXDu0/dyRabZ8B/N+XnaaDbCoTABcY4jMjr4D1/P7t2 X-Received: by 2002:a62:130c:: with SMTP id b12mr45325793pfj.247.1546446620035; Wed, 02 Jan 2019 08:30:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1546446620; cv=none; d=google.com; s=arc-20160816; b=Z0lsOz1xe7yJr1WyJbEyzdumhn86Xa8RK5XAWabB8KiqFs1nagRh9IVXGcfUmFFFtq DTNbDM+4KOaz/LBbr0UL91x9N/swUkP8aAIYCSWSHgI+xz+VkW1w854+ZpouGEcL7nbO IW4hri7j7ljRY49X0gRprY3q5cYoXHBi82rCjST0pQJ+NvHyiBGnO+wNdnWiEcDjaAMO 1Ijm6w+PWtGvge2uHFll9yKhqhDywNjKeDOlJ7okIx0AIFkG4NrQ+apKtHvDB/aGmODZ DhmY+OFdlO1Bl3CQ6QrxJpXIq2XqA9EYDv4vPUJNwib7AUzvcGFS54Rr0HtjMC4+uaO3 tJrA== 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 :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject; bh=Cvi3OuPHiirv3cSrjJU2lhvJEdPGzDq3Ic1sZoM/iWc=; b=apagSjgPnvtYJVg9o9rw2stFMBggRwYT9ieQaHN98u2rswdR+2noxC+cFckmnkB/65 H8U14sKMCu3JbqK22cGwGBB2CCH2OGuOJN3DcxOKbS95uH5btAw9vr5O0Zqf3ON7lE3W OWXjXW/AKhudYiLfdzaAdG3HQQh5kSIFQVLcNpuJpeKSSHf7fhCQu+e7uQCFm9rlgMXw 288AlBcPRYAuwg2tRVDR1fUVJw/XC/zmj9szIO7JGWS+/L6Fp/I2+QbAeSm4JXZpfCig Vs4VoV7zp3USeFtjZXPI1hWcO1Z84W0S1CovOsSMtXFrKHap/8SGP52i+FUY8Ua+S67y ZngA== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g9si54157555pfd.86.2019.01.02.08.29.53; Wed, 02 Jan 2019 08:30:20 -0800 (PST) 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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729836AbfABPEb (ORCPT + 99 others); Wed, 2 Jan 2019 10:04:31 -0500 Received: from www262.sakura.ne.jp ([202.181.97.72]:49528 "EHLO www262.sakura.ne.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728026AbfABPEa (ORCPT ); Wed, 2 Jan 2019 10:04:30 -0500 Received: from fsav301.sakura.ne.jp (fsav301.sakura.ne.jp [153.120.85.132]) by www262.sakura.ne.jp (8.15.2/8.15.2) with ESMTP id x02F48uL041874; Thu, 3 Jan 2019 00:04:08 +0900 (JST) (envelope-from penguin-kernel@i-love.sakura.ne.jp) Received: from www262.sakura.ne.jp (202.181.97.72) by fsav301.sakura.ne.jp (F-Secure/fsigk_smtp/530/fsav301.sakura.ne.jp); Thu, 03 Jan 2019 00:04:08 +0900 (JST) X-Virus-Status: clean(F-Secure/fsigk_smtp/530/fsav301.sakura.ne.jp) Received: from [192.168.1.8] (softbank126126163036.bbtec.net [126.126.163.36]) (authenticated bits=0) by www262.sakura.ne.jp (8.15.2/8.15.2) with ESMTPSA id x02F42bs041791 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NO); Thu, 3 Jan 2019 00:04:08 +0900 (JST) (envelope-from penguin-kernel@i-love.sakura.ne.jp) Subject: Re: [PATCH] tty/n_hdlc: fix sleep in !TASK_RUNNING state warning To: Paul Fulghum Cc: Arnd Bergmann , Alan Cox , gregkh@linuxfoundation.org, jslaby@suse.com, linux-kernel@vger.kernel.org References: <000000000000449587057e1e6f8b@google.com> <49b3b189-a51f-6a97-0e1f-bc3f2c305299@I-love.SAKURA.ne.jp> From: Tetsuo Handa Message-ID: Date: Thu, 3 Jan 2019 00:04:02 +0900 User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.4.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2019/01/01 12:11, Paul Fulghum wrote: > NAK to this patch. It causes lost wakeups in both read and write paths. > > The write path does not need changing. > > The read path can be fixed by setting current to TASK_RUNNING at the top of the if (rbuf) block > so the warning is not triggered by copy_to_user(). If this block runs the condition is satisfied > and it breaks out of the polling loop where it is already being set to TASK_RUNNING and removed > from the wait queue. This particular path just needs to account for the copy_to_user which occurs > before breaking out. > > I’ll make a patch to do this when I have the ability to test it in a day or two. > OK. Then, any chance it is rewritten using wait_event_interruptible() in order to reduce lines? ( wait_event_interruptible() automatically calls might_sleep(), but is it acceptable for you? ) --- drivers/tty/n_hdlc.c | 126 ++++++++++++--------------------------------------- 1 file changed, 30 insertions(+), 96 deletions(-) diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index 8223d02..2e4ccf9 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -562,8 +562,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, { struct n_hdlc *n_hdlc = tty2n_hdlc(tty); int ret = 0; - struct n_hdlc_buf *rbuf; - DECLARE_WAITQUEUE(wait, current); + struct n_hdlc_buf *rbuf = NULL; if (debuglevel >= DEBUG_LEVEL_INFO) printk("%s(%d)n_hdlc_tty_read() called\n",__FILE__,__LINE__); @@ -579,58 +578,26 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, return -EFAULT; } - add_wait_queue(&tty->read_wait, &wait); - - for (;;) { - if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { - ret = -EIO; - break; - } - if (tty_hung_up_p(file)) - break; - - set_current_state(TASK_INTERRUPTIBLE); - - rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list); - if (rbuf) { - if (rbuf->count > nr) { - /* too large for caller's buffer */ - ret = -EOVERFLOW; - } else { - __set_current_state(TASK_RUNNING); - if (copy_to_user(buf, rbuf->buf, rbuf->count)) - ret = -EFAULT; - else - ret = rbuf->count; - } - - if (n_hdlc->rx_free_buf_list.count > - DEFAULT_RX_BUF_COUNT) - kfree(rbuf); - else - n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf); - break; - } - - /* no data */ - if (tty_io_nonblock(tty, file)) { - ret = -EAGAIN; - break; - } - - schedule(); - - if (signal_pending(current)) { - ret = -EINTR; - break; - } + if (wait_event_interruptible(tty->read_wait, + (ret = -EIO, test_bit(TTY_OTHER_CLOSED, &tty->flags)) || + (ret = 0, tty_hung_up_p(file)) || + (rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list)) != NULL || + (ret = -EAGAIN, tty_io_nonblock(tty, file)))) + return -EINTR; + if (rbuf) { + if (rbuf->count > nr) + /* too large for caller's buffer */ + ret = -EOVERFLOW; + else if (copy_to_user(buf, rbuf->buf, rbuf->count)) + ret = -EFAULT; + else + ret = rbuf->count; + if (n_hdlc->rx_free_buf_list.count > DEFAULT_RX_BUF_COUNT) + kfree(rbuf); + else + n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf); } - - remove_wait_queue(&tty->read_wait, &wait); - __set_current_state(TASK_RUNNING); - return ret; - } /* end of n_hdlc_tty_read() */ /** @@ -645,21 +612,13 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *data, size_t count) { - struct n_hdlc *n_hdlc = tty2n_hdlc (tty); + struct n_hdlc *n_hdlc; int error = 0; - DECLARE_WAITQUEUE(wait, current); - struct n_hdlc_buf *tbuf; + struct n_hdlc_buf *tbuf = NULL; if (debuglevel >= DEBUG_LEVEL_INFO) printk("%s(%d)n_hdlc_tty_write() called count=%zd\n", __FILE__,__LINE__,count); - - /* Verify pointers */ - if (!n_hdlc) - return -EIO; - - if (n_hdlc->magic != HDLC_MAGIC) - return -EIO; /* verify frame size */ if (count > maxframe ) { @@ -670,40 +629,14 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, maxframe ); count = maxframe; } - - add_wait_queue(&tty->write_wait, &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - - tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list); - if (tbuf) - break; - - if (tty_io_nonblock(tty, file)) { - error = -EAGAIN; - break; - } - schedule(); - - n_hdlc = tty2n_hdlc (tty); - if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || - tty != n_hdlc->tty) { - printk("n_hdlc_tty_write: %p invalid after wait!\n", n_hdlc); - error = -EIO; - break; - } - - if (signal_pending(current)) { - error = -EINTR; - break; - } - } - - __set_current_state(TASK_RUNNING); - remove_wait_queue(&tty->write_wait, &wait); - - if (!error) { + if (wait_event_interruptible(tty->write_wait, + (error = -EIO, n_hdlc = tty2n_hdlc(tty), /* Verify pointers */ + !n_hdlc || n_hdlc->magic != HDLC_MAGIC || tty != n_hdlc->tty) || + (tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list)) != NULL || + (error = -EAGAIN, tty_io_nonblock(tty, file)))) + return -EINTR; + if (tbuf) { /* Retrieve the user's buffer */ memcpy(tbuf->buf, data, count); @@ -711,8 +644,9 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, tbuf->count = error = count; n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); n_hdlc_send_frames(n_hdlc,tty); + } else if (error == -EIO) { + printk("n_hdlc_tty_write: %p invalid!\n", n_hdlc); } - return error; } /* end of n_hdlc_tty_write() */ -- 1.8.3.1