From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-ot1-f72.google.com (mail-ot1-f72.google.com [209.85.210.72]) (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 B718CE54B for ; Sat, 20 Jun 2026 05:30:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.72 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781933447; cv=none; b=GiD6FV1VG6H1h19qmSA/Cb0ltOhdPDSB/UO+k08QnjirmO+PfkD3zKdYMASEYGHKQiesS7arW/ByDdfxjC9teaM4gRb+WkE17aongMen/r2GsTdlXRRYfTYCqOq9uV1/Z16mneC6bNXVmopdgDafZabfSYoz6GlkLE6TiFSteGo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781933447; c=relaxed/simple; bh=j+G+w5g3dWD7VHSlPtIRRvvzbk3QDLzvd4UePKYxBRc=; h=MIME-Version:Date:In-Reply-To:Message-ID:Subject:From:To: Content-Type; b=V8YAVXtxhnjH/pa5r/BEfSveDsngaKXI73LOYKKK5D7CC4krr+Jjo9rZcMPRYT2kl9AZs2vQzrqGJGWKKR1BxWS6fS73mtzOA+z1YRjR7AamXx2PrLstFh1XboKjMhBE60LbIesIa1YrD6BRDZJbW44pm/zBV48RBu8O0VU1/uQ= 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.210.72 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-ot1-f72.google.com with SMTP id 46e09a7af769-7e713779405so4904081a34.3 for ; Fri, 19 Jun 2026 22:30:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781933445; x=1782538245; 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=PGbgCpDKpwepbUrwOZMEgxt2RES13GLhq29DcEC5qMK5iDhEw1uaShGPhnOOSd/F8r IDJYJfxYBUCWy5CWbBAwwWLnlzx00GgD5yFwfxj8mjr7FMCJkT1ZEEq/XCzeRaGv2Ki6 9zYFFTXD3LKUe/eBsUwPDNZAVh67u6KX52oCUW8pwYbO9kBeodSv3uE0fJSwpi3WSfbI HYiTz+e1FEItpYiulcX+DOXOSM+6xXIEmRTspvDsMXUH+/LaBdgdvwCbOnGaItvqJEBG 0V6TfQlpPoswWEQ+rzDKOmWpXTGWd+qYZO2D3vs5c1PMFvPY4sJ568ilUflb9QJDfMYd xm8w== X-Gm-Message-State: AOJu0YxtsHte/URXdmQlkMvlJxx8MJ8ISG2ighnLWDsCdsWmNyVbEyWE 8baxSKTsVlNCuDH3YOMH0eD431bgJ/Iqpl1xKWvbVntgRj9ijusti24nd1WI4TLJzDSidx0SvTp +xrg35AVMO/Nq4b1dGhWDlia6xkX29ZVA8hIvE4r5A8YWpT36vymOBH2NfKc= 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:170f:b0:467:1212:46fd with SMTP id 5614622812f47-4896ac4a92amr5488933b6e.33.1781933444841; Fri, 19 Jun 2026 22:30:44 -0700 (PDT) Date: Fri, 19 Jun 2026 22:30:44 -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: <6a362584.0b6cad66.2ee056.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