From patchwork Sat Jun 30 09:40:03 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "jeff.liu" X-Patchwork-Id: 168291 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 233642C01F0 for ; Sat, 30 Jun 2012 19:41:24 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753417Ab2F3JlL (ORCPT ); Sat, 30 Jun 2012 05:41:11 -0400 Received: from rcsinet15.oracle.com ([148.87.113.117]:45077 "EHLO rcsinet15.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753336Ab2F3Jkm (ORCPT ); Sat, 30 Jun 2012 05:40:42 -0400 Received: from ucsinet22.oracle.com (ucsinet22.oracle.com [156.151.31.94]) by rcsinet15.oracle.com (Sentrion-MTA-4.2.2/Sentrion-MTA-4.2.2) with ESMTP id q5U9ecpS031090 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sat, 30 Jun 2012 09:40:38 GMT Received: from acsmt358.oracle.com (acsmt358.oracle.com [141.146.40.158]) by ucsinet22.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id q5U9ebGh027157 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sat, 30 Jun 2012 09:40:37 GMT Received: from abhmt103.oracle.com (abhmt103.oracle.com [141.146.116.55]) by acsmt358.oracle.com (8.12.11.20060308/8.12.11) with ESMTP id q5U9ebca010274; Sat, 30 Jun 2012 04:40:37 -0500 Received: from [192.168.1.103] (/114.248.194.226) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sat, 30 Jun 2012 02:40:37 -0700 Message-ID: <4FEEC973.4090905@oracle.com> Date: Sat, 30 Jun 2012 17:40:03 +0800 From: Jeff Liu Reply-To: jeff.liu@oracle.com Organization: Oracle User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.28) Gecko/20120313 Thunderbird/3.1.20 MIME-Version: 1.0 To: linux-serial@vger.kernel.org CC: "linux-fsdevel@vger.kernel.org" , "linux-ext4@vger.kernel.org" , gregkh@linuxfoundation.org, Jan Kara , "Ted Ts'o" Subject: [PATCH 2/2] make both atomic_write_lock and BTM lock acquirement sleepable at tty_write_message() X-Source-IP: ucsinet22.oracle.com [156.151.31.94] Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org Avoid lockdep warn by having both lock acquirements sleepable. BTM also have to go to sleep if lock failed at the first time, otherwise it will race with tty_open()->tty_lock(). Signed-off-by: Jie Liu --- drivers/tty/tty_io.c | 35 +++++++++++++++++++++++++++++++---- 1 files changed, 31 insertions(+), 4 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index b425c79..2b4664d 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1098,12 +1098,40 @@ out: * * We must still hold the BTM and test the CLOSING flag for the moment. */ - void tty_write_message(struct tty_struct *tty, char *msg) { +retry: if (tty) { - mutex_lock(&tty->atomic_write_lock); - tty_lock(); + /* + * tty_write_message() will invoked by print_warning() + * at fs/quota/dquot.c if CONFIG_PRINT_QUOTA_WARNING + * is enabled when a user running out of disk quota limits. + * It will end up call tty_write(). Here is a potential race + * situation since tty_write() call copy_from_user() which + * might produce page faults and turn to invoke inodes dirty + * process on the underlying file systems if needed, and + * it will try to acquire JBD/JBD2 lock accordingly. This + * might make lockdep unhappy to print dead lock warning. + * To solve this issue, we have to go to sleep and relinquish + * the CPU power to another process until the atomic_write_lock + * became available. + */ + if (!mutex_trylock(&tty->atomic_write_lock)) { + DEFINE_WAIT(wait); + prepare_to_wait_exclusive(&tty->write_wait, &wait, + TASK_INTERRUPTIBLE); + schedule(); + finish_wait(&tty->write_wait, &wait); + goto retry; + } + + /* + * Call tty_lock() directly might race with tty_open() even + * if we have already got the atomic_write_lock. However, we + * must perform TTY_CLOSING check up with the BTM hold, so call + * tty_lock_wait() which is sleepable instead. + */ + tty_lock_wait(); if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { tty_unlock(); tty->ops->write(tty, msg, strlen(msg)); @@ -1114,7 +1142,6 @@ void tty_write_message(struct tty_struct *tty, char *msg) return; } - /** * tty_write - write method for tty device file * @file: tty file pointer