[PATCH 2/2] make both atomic_write_lock and BTM lock acquirement sleepable at tty_write_message()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <jeff.liu@xxxxxxxxxx>

---
 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
-- 
1.7.9
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux