From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-oi1-f198.google.com (mail-oi1-f198.google.com [209.85.167.198]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 630BB22F01 for ; Sat, 20 Jun 2026 07:06:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.198 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781939178; cv=none; b=HdB5PzkfK/GbVCWENLW0xzjFWa/lZbDnw9dJ8/CbR4j9jHWNHw9CDHAs1c9Sm6PiFGRZDP06/H3q2+QMUbE7HKyckJBVm7pCLJFtrKDLW2BVE0aVuFUN1WmxS37FnEnHv3Gf7IzYgRChTmbvgpqxzXShMjZbkv4EeUpthlXUA/k= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781939178; c=relaxed/simple; bh=j+G+w5g3dWD7VHSlPtIRRvvzbk3QDLzvd4UePKYxBRc=; h=MIME-Version:Date:In-Reply-To:Message-ID:Subject:From:To: Content-Type; b=LyBam/bY6MF+8vSh+3E10ituFP4723zKBpndQ9SP+h1cWDrB0gIPC053Ki2ClKca72mHMYshXVuInLX1YL/4Nmkdads6RpDXwaHQ8NpXzKXNt+/4H5X6YP1uUsUNL3jGV35fQQTzUgXObhzSc6CN4TaWEC2ELKIraAGfOb65yYg= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=syzkaller.appspotmail.com; spf=pass smtp.mailfrom=M3KW2WVRGUFZ5GODRSRYTGD7.apphosting.bounces.google.com; arc=none smtp.client-ip=209.85.167.198 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=syzkaller.appspotmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=M3KW2WVRGUFZ5GODRSRYTGD7.apphosting.bounces.google.com Received: by mail-oi1-f198.google.com with SMTP id 5614622812f47-48b983c7133so26799b6e.1 for ; Sat, 20 Jun 2026 00:06:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781939176; x=1782543976; h=to:from:subject:message-id:in-reply-to:date:mime-version :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=OuNnXA2WwYOo/E8SRGw40YXJOxCtrwLmp7BisY1j8m8=; b=J44OyQbr3zr4D5Q94DtOzv6tAzKCdiSWcEGqnkma5CDf26QtiIYL7weBuEVqql8wmw EQz5UiEU+pY1UqlBmFGJ7J529+6CAJpQw2yFsYO2bjn9LrzcKfv7p3jgumU2OLDwPXj3 qRqilCd9SVcs2IWLI22xvU4eZPx/5dYqhvg8xeucYpwIUX4uJUDjr5O76PKFK/x2QSC4 YJ6a4J9JNMemF/D8VwRXj4+YAqZLv8SrQuQY08v8Eq32BRLKRKlPRsmVP8vdB7qaXOwT NW422tIWcr0acLcYxziGzvHNUk7ukP/SwpOokBNfjD4g/MxRjrNitZ1aoLja44WTRIE+ mYKg== X-Gm-Message-State: AOJu0YwHefEdG3j37aNbKTS0OT4QiczTmMxn+qrhcFjXNqAyyHs/o34z YtfidfRIhBFaH3mYN+xNyIohuLY7m23iVPEKY9f5GE+2bk4z7jSJA5yGJgwYrb0b2vXnlIIAiob HaahtnC2k799rBqlr11rL586rhsX8p3tIywGs2xzpHeUevgVCOlkw2brg/aM= Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Received: by 2002:a05:6808:c18f:b0:485:115a:3573 with SMTP id 5614622812f47-4896ac99cefmr5540991b6e.38.1781939176370; Sat, 20 Jun 2026 00:06:16 -0700 (PDT) Date: Sat, 20 Jun 2026 00:06:16 -0700 In-Reply-To: <6a36101b.be22b350.2a3e9.0002.GAE@google.com> X-Google-Appengine-App-Id: s~syzkaller X-Google-Appengine-App-Id-Alias: syzkaller Message-ID: <6a363be8.df3a8e30.5f884.0000.GAE@google.com> Subject: Forwarded: [PATCH] ocfs2: fix deadlock between dio write and orphan dir inode lock From: syzbot To: linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com Content-Type: text/plain; charset="UTF-8" For archival purposes, forwarding an incoming command email to linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com. *** Subject: [PATCH] ocfs2: fix deadlock between dio write and orphan dir inode lock Author: kartikey406@gmail.com #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master The following deadlock is detected by PREEMPT_RT's rtmutex detector: Thread 1 (pwritev2 -> ocfs2_file_write_iter): inode_lock(file_inode) <- held here ocfs2_dio_end_io_write() ocfs2_inode_lock() <- cluster lock ocfs2_del_inode_from_orphan() inode_lock(orphan_dir) <- deadlock! Thread 2 (recovery path): inode_lock(orphan_dir) <- held first inode_lock(file_inode) <- reverse order! ocfs2_file_write_iter() acquires inode_lock(file_inode) and holds it across the entire write including the synchronous DIO completion callback ocfs2_dio_end_io_write(). When dwc->dw_orphaned is set, ocfs2_dio_end_io_write() calls ocfs2_del_inode_from_orphan() which acquires inode_lock(orphan_dir_inode), creating an AB-BA lock inversion with recovery paths that acquire orphan_dir lock first. Fix this by: - Saving the orphaned state before releasing locks - Moving ocfs2_inode_unlock() and brelse(di_bh) BEFORE the call to ocfs2_del_inode_from_orphan() in ocfs2_dio_end_io_write() - Passing NULL for di_bh to ocfs2_del_inode_from_orphan() to signal it should acquire its own cluster lock and di_bh internally - In ocfs2_del_inode_from_orphan(), changing di initialization from a declaration+assignment to just a declaration, then acquiring a fresh ocfs2_inode_lock() when di_bh is NULL, and releasing it in the bail path Reported-by: syzbot+ce129763ce7d7e914739@syzkaller.appspotmail.com Link: https://syzkaller.appspot.com/bug?extid=ce129763ce7d7e914739 Signed-off-by: Deepanshu kartikey --- fs/ocfs2/aops.c | 14 ++++++++------ fs/ocfs2/namei.c | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 6ec198bdab12..d1d22019dc61 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -2280,6 +2280,7 @@ static int ocfs2_dio_end_io_write(struct inode *inode, handle_t *handle = NULL; loff_t end = offset + bytes; int ret = 0, credits = 0, batch = 0; + bool orphaned = false; ocfs2_init_dealloc_ctxt(&dealloc); @@ -2371,17 +2372,18 @@ static int ocfs2_dio_end_io_write(struct inode *inode, ocfs2_commit_trans(osb, handle); unlock: up_write(&oi->ip_alloc_sem); + orphaned = (!ret && dwc->dw_orphaned); + ocfs2_inode_unlock(inode, 1); + brelse(di_bh); + di_bh = NULL; - /* everything looks good, let's start the cleanup */ - if (!ret && dwc->dw_orphaned) { + /* everything looks good, let's start the orphan cleanup */ + if (orphaned) { BUG_ON(dwc->dw_writer_pid != task_pid_nr(current)); - - ret = ocfs2_del_inode_from_orphan(osb, inode, di_bh, 0, 0); + ret = ocfs2_del_inode_from_orphan(osb, inode, NULL, 0, 0); if (ret < 0) mlog_errno(ret); } - ocfs2_inode_unlock(inode, 1); - brelse(di_bh); out: if (data_ac) ocfs2_free_alloc_context(data_ac); diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 1277666c77cd..25bbe2a9776e 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -2712,10 +2712,21 @@ int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb, { struct inode *orphan_dir_inode = NULL; struct buffer_head *orphan_dir_bh = NULL; - struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; + struct ocfs2_dinode *di; handle_t *handle = NULL; int status = 0; + struct buffer_head *local_di_bh = NULL; + if (!di_bh) { + status = ocfs2_inode_lock(inode, &local_di_bh, 1); + if (status < 0) { + mlog_errno(status); + return status; + } + di_bh = local_di_bh; + } + + di = (struct ocfs2_dinode *)di_bh->b_data; orphan_dir_inode = ocfs2_get_system_file_inode(osb, ORPHAN_DIR_SYSTEM_INODE, le16_to_cpu(di->i_dio_orphaned_slot)); @@ -2779,6 +2790,10 @@ int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb, iput(orphan_dir_inode); bail: + if (local_di_bh) { + ocfs2_inode_unlock(inode, 1); + brelse(local_di_bh); + } return status; } -- 2.43.0