From patchwork Tue Feb 5 03:24:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10796841 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D9A9B159A for ; Tue, 5 Feb 2019 03:24:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BB3E02AD66 for ; Tue, 5 Feb 2019 03:24:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B8F132B837; Tue, 5 Feb 2019 03:24:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AA8FE2A9F7 for ; Tue, 5 Feb 2019 03:24:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726861AbfBEDYS (ORCPT ); Mon, 4 Feb 2019 22:24:18 -0500 Received: from ipmail01.adl6.internode.on.net ([150.101.137.136]:54782 "EHLO ipmail01.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725855AbfBEDYR (ORCPT ); Mon, 4 Feb 2019 22:24:17 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail01.adl6.internode.on.net with ESMTP; 05 Feb 2019 13:54:14 +1030 Received: from discord.disaster.area ([192.168.1.111]) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1gqrLJ-0000kL-TK; Tue, 05 Feb 2019 14:24:13 +1100 Received: from dave by discord.disaster.area with local (Exim 4.92-RC4) (envelope-from ) id 1gqrLJ-0004By-Rq; Tue, 05 Feb 2019 14:24:13 +1100 From: Dave Chinner To: linux-xfs@vger.kernel.org Cc: arekm@maven.pl Subject: [PATCH] libxfs: fix repair deadlock due to failed inode flushes. Date: Tue, 5 Feb 2019 14:24:13 +1100 Message-Id: <20190205032413.16075-1-david@fromorbit.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner If inode_item_done() fails to flush an inode after we've grabbed a reference to the underlying buffer during a transaction commit, we fail to put the buffer and hence leak it. We then deadlock on the next lookup ofthe inode buffer as it is still locked and no-one owns it. To fix it, put the buffer on error so that it gets unlocked and can be recovered appropriately in a later phase of repair. Reported-by: Arkadiusz Miskiewicz Fixes: d15188a1ec14 ("xfs: rework the inline directory verifiers") Signed-off-by: Dave Chinner Reviewed-by: Brian Foster --- libxfs/trans.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/libxfs/trans.c b/libxfs/trans.c index 46ff8b4ae798..10a35dd47b01 100644 --- a/libxfs/trans.c +++ b/libxfs/trans.c @@ -824,8 +824,10 @@ _("Transaction block reservation exceeded! %u > %u\n"), /* * Transaction commital code follows (i.e. write to disk in libxfs) + * + * XXX (dgc): should failure to flush the inode (e.g. due to uncorrected + * corruption) result in transaction commit failure w/ EFSCORRUPTED? */ - static void inode_item_done( xfs_inode_log_item_t *iip) @@ -856,17 +858,24 @@ inode_item_done( return; } + /* + * Flush the inode and disassociate it from the transaction regardless + * of whether the flush succeed or not. If we fail the flush, make sure + * we still release the buffer reference we currently hold. + */ bp->b_log_item = iip; error = libxfs_iflush_int(ip, bp); + ip->i_transp = NULL; /* disassociate from transaction */ + bp->b_log_item = NULL; /* remove log item */ + bp->b_transp = NULL; /* remove xact ptr */ + if (error) { fprintf(stderr, _("%s: warning - iflush_int failed (%d)\n"), progname, error); + libxfs_putbuf(bp); return; } - ip->i_transp = NULL; /* disassociate from transaction */ - bp->b_log_item = NULL; /* remove log item */ - bp->b_transp = NULL; /* remove xact ptr */ libxfs_writebuf(bp, 0); #ifdef XACT_DEBUG fprintf(stderr, "flushing dirty inode %llu, buffer %p\n",