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