From patchwork Fri Jan 29 02:17:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 12055003 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C15B8C43381 for ; Fri, 29 Jan 2021 02:18:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 980DF64E03 for ; Fri, 29 Jan 2021 02:18:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231237AbhA2CSP (ORCPT ); Thu, 28 Jan 2021 21:18:15 -0500 Received: from mail.kernel.org ([198.145.29.99]:57470 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231450AbhA2CSI (ORCPT ); Thu, 28 Jan 2021 21:18:08 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 7D3E864E07; Fri, 29 Jan 2021 02:17:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611886672; bh=Si8vMX+OQoXDakQd/gkDqMFJIdBapgrQcjGopok50C8=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=cghn1hHJGWaCnAIObtGkZ3u7/yWQbJbszt8YnXrUO37jvwcOwAyo6oyNy5SYweu4y nJc2H+sbHJxdOkmr3E0P+imEANeZ98KqD8y90LTpV36hzMwZZz47OKvvoiHI/DAY09 rcB8trWqoivXVdpyNVOJieSP8L0HTUpEeSx3joR4MUPPgcC7k/+hTLqsHx7C9d/oVf hSl3SHWbK8plFYSoppKLC7Zu+484jzcqjmF4SdusXlwUziYUtFpib7yWtCtQ40TE+0 DYIHoWsgAGTlQUCVmcLNrnuPdqiJPaMOqTQn0diIOQs7nU4065KIbUe2PJoHrdFegz /JffP+3WiooGA== Subject: [PATCH 01/12] xfs: trigger all block gc scans when low on quota space From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , Brian Foster , linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com, bfoster@redhat.com Date: Thu, 28 Jan 2021 18:17:52 -0800 Message-ID: <161188667210.1943978.14517115689976313523.stgit@magnolia> In-Reply-To: <161188666613.1943978.971196931920996596.stgit@magnolia> References: <161188666613.1943978.971196931920996596.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong The functions to run an eof/cowblocks scan to try to reduce quota usage are kind of a mess -- the logic repeatedly initializes an eofb structure and there are logic bugs in the code that result in the cowblocks scan never actually happening. Replace all three functions with a single function that fills out an eofb and runs both eof and cowblocks scans. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Reviewed-by: Brian Foster --- fs/xfs/xfs_file.c | 15 ++++++--------- fs/xfs/xfs_icache.c | 46 ++++++++++++++++------------------------------ fs/xfs/xfs_icache.h | 4 ++-- 3 files changed, 24 insertions(+), 41 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 5d4a66c72c78..69879237533b 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -713,7 +713,7 @@ xfs_file_buffered_write( struct inode *inode = mapping->host; struct xfs_inode *ip = XFS_I(inode); ssize_t ret; - int enospc = 0; + bool cleared_space = false; int iolock; if (iocb->ki_flags & IOCB_NOWAIT) @@ -745,19 +745,16 @@ xfs_file_buffered_write( * also behaves as a filter to prevent too many eofblocks scans from * running at the same time. */ - if (ret == -EDQUOT && !enospc) { + if (ret == -EDQUOT && !cleared_space) { xfs_iunlock(ip, iolock); - enospc = xfs_inode_free_quota_eofblocks(ip); - if (enospc) - goto write_retry; - enospc = xfs_inode_free_quota_cowblocks(ip); - if (enospc) + cleared_space = xfs_inode_free_quota_blocks(ip); + if (cleared_space) goto write_retry; iolock = 0; - } else if (ret == -ENOSPC && !enospc) { + } else if (ret == -ENOSPC && !cleared_space) { struct xfs_eofblocks eofb = {0}; - enospc = 1; + cleared_space = true; xfs_flush_inodes(ip->i_mount); xfs_iunlock(ip, iolock); diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index deb99300d171..c71eb15e3835 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -1397,33 +1397,31 @@ xfs_icache_free_eofblocks( } /* - * Run eofblocks scans on the quotas applicable to the inode. For inodes with - * multiple quotas, we don't know exactly which quota caused an allocation + * Run cow/eofblocks scans on the quotas applicable to the inode. For inodes + * with multiple quotas, we don't know exactly which quota caused an allocation * failure. We make a best effort by including each quota under low free space * conditions (less than 1% free space) in the scan. */ -static int -__xfs_inode_free_quota_eofblocks( - struct xfs_inode *ip, - int (*execute)(struct xfs_mount *mp, - struct xfs_eofblocks *eofb)) +bool +xfs_inode_free_quota_blocks( + struct xfs_inode *ip) { - int scan = 0; - struct xfs_eofblocks eofb = {0}; - struct xfs_dquot *dq; + struct xfs_eofblocks eofb = {0}; + struct xfs_dquot *dq; + bool do_work = false; /* * Run a sync scan to increase effectiveness and use the union filter to * cover all applicable quotas in a single scan. */ - eofb.eof_flags = XFS_EOF_FLAGS_UNION|XFS_EOF_FLAGS_SYNC; + eofb.eof_flags = XFS_EOF_FLAGS_UNION | XFS_EOF_FLAGS_SYNC; if (XFS_IS_UQUOTA_ENFORCED(ip->i_mount)) { dq = xfs_inode_dquot(ip, XFS_DQTYPE_USER); if (dq && xfs_dquot_lowsp(dq)) { eofb.eof_uid = VFS_I(ip)->i_uid; eofb.eof_flags |= XFS_EOF_FLAGS_UID; - scan = 1; + do_work = true; } } @@ -1432,21 +1430,16 @@ __xfs_inode_free_quota_eofblocks( if (dq && xfs_dquot_lowsp(dq)) { eofb.eof_gid = VFS_I(ip)->i_gid; eofb.eof_flags |= XFS_EOF_FLAGS_GID; - scan = 1; + do_work = true; } } - if (scan) - execute(ip->i_mount, &eofb); + if (!do_work) + return false; - return scan; -} - -int -xfs_inode_free_quota_eofblocks( - struct xfs_inode *ip) -{ - return __xfs_inode_free_quota_eofblocks(ip, xfs_icache_free_eofblocks); + xfs_icache_free_eofblocks(ip->i_mount, &eofb); + xfs_icache_free_cowblocks(ip->i_mount, &eofb); + return true; } static inline unsigned long @@ -1646,13 +1639,6 @@ xfs_icache_free_cowblocks( XFS_ICI_COWBLOCKS_TAG); } -int -xfs_inode_free_quota_cowblocks( - struct xfs_inode *ip) -{ - return __xfs_inode_free_quota_eofblocks(ip, xfs_icache_free_cowblocks); -} - void xfs_inode_set_cowblocks_tag( xfs_inode_t *ip) diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h index 3a4c8b382cd0..3f7ddbca8638 100644 --- a/fs/xfs/xfs_icache.h +++ b/fs/xfs/xfs_icache.h @@ -54,17 +54,17 @@ long xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan); void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); +bool xfs_inode_free_quota_blocks(struct xfs_inode *ip); + void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip); void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip); int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *); -int xfs_inode_free_quota_eofblocks(struct xfs_inode *ip); void xfs_eofblocks_worker(struct work_struct *); void xfs_queue_eofblocks(struct xfs_mount *); void xfs_inode_set_cowblocks_tag(struct xfs_inode *ip); void xfs_inode_clear_cowblocks_tag(struct xfs_inode *ip); int xfs_icache_free_cowblocks(struct xfs_mount *, struct xfs_eofblocks *); -int xfs_inode_free_quota_cowblocks(struct xfs_inode *ip); void xfs_cowblocks_worker(struct work_struct *); void xfs_queue_cowblocks(struct xfs_mount *); From patchwork Fri Jan 29 02:17:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 12055007 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DF0CAC4332D for ; Fri, 29 Jan 2021 02:18:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BF64E64E01 for ; Fri, 29 Jan 2021 02:18:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231450AbhA2CSQ (ORCPT ); Thu, 28 Jan 2021 21:18:16 -0500 Received: from mail.kernel.org ([198.145.29.99]:57502 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231556AbhA2CSN (ORCPT ); Thu, 28 Jan 2021 21:18:13 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 2FC6164E05; Fri, 29 Jan 2021 02:17:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611886678; bh=lj5ly+kqPX3/icV0ZJlW+tlNZgyAPlY0iUkOkNPCU1A=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=YAsQhcrV0zaKiUPFFUje2b3NfL8SAllO2GwxrXBvRhcMQjXEmKmhI4dxGyBDU927P Emres/sC3ClR2hyywBx9SGdqok4N8XmOtSdVojkYewNBbfp6xeThygVXzTAULcOj8f PGO2LelNI5OubsCxjw/SFaZR/dJi1vCQK66lgs4xp59MLi7IGOAKEejz9nEDkGiQmt gPSsuzxxprbJbgefa3jsWWONai9/IMb0rEFkTbkf/yD4K4MqkxgWdSnTQ1zwSTXRhv LnGHxe0mHxPXWypyeeQAjyeV1NBe37+wJbSutu21VfklYVDASzwFc1ymr3hNgKMbfj APWS4T/hKlJqQ== Subject: [PATCH 02/12] xfs: don't stall cowblocks scan if we can't take locks From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com, bfoster@redhat.com Date: Thu, 28 Jan 2021 18:17:57 -0800 Message-ID: <161188667779.1943978.6876657507534054316.stgit@magnolia> In-Reply-To: <161188666613.1943978.971196931920996596.stgit@magnolia> References: <161188666613.1943978.971196931920996596.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Don't stall the cowblocks scan on a locked inode if we possibly can. We'd much rather the background scanner keep moving. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_icache.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index c71eb15e3835..89f9e692fde7 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -1605,17 +1605,31 @@ xfs_inode_free_cowblocks( void *args) { struct xfs_eofblocks *eofb = args; + bool wait; int ret = 0; + wait = eofb && (eofb->eof_flags & XFS_EOF_FLAGS_SYNC); + if (!xfs_prep_free_cowblocks(ip)) return 0; if (!xfs_inode_matches_eofb(ip, eofb)) return 0; - /* Free the CoW blocks */ - xfs_ilock(ip, XFS_IOLOCK_EXCL); - xfs_ilock(ip, XFS_MMAPLOCK_EXCL); + /* + * If the caller is waiting, return -EAGAIN to keep the background + * scanner moving and revisit the inode in a subsequent pass. + */ + if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) { + if (wait) + return -EAGAIN; + return 0; + } + if (!xfs_ilock_nowait(ip, XFS_MMAPLOCK_EXCL)) { + if (wait) + ret = -EAGAIN; + goto out_iolock; + } /* * Check again, nobody else should be able to dirty blocks or change @@ -1625,6 +1639,7 @@ xfs_inode_free_cowblocks( ret = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, false); xfs_iunlock(ip, XFS_MMAPLOCK_EXCL); +out_iolock: xfs_iunlock(ip, XFS_IOLOCK_EXCL); return ret; From patchwork Fri Jan 29 02:18:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 12055019 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 70A2DC43331 for ; Fri, 29 Jan 2021 02:18:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3503664E07 for ; Fri, 29 Jan 2021 02:18:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231559AbhA2CSX (ORCPT ); Thu, 28 Jan 2021 21:18:23 -0500 Received: from mail.kernel.org ([198.145.29.99]:57504 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231562AbhA2CST (ORCPT ); Thu, 28 Jan 2021 21:18:19 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id E54A064E08; Fri, 29 Jan 2021 02:18:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611886684; bh=zcIeRXJpU8rlv7dzSb2+rlWghhHlJHh2AbARBmOZG7A=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=c/noblceNQoBBpLt2fMlb6e1Szd1tuvOQZxqTeZj2sOIWavGSi9fXrCEpOKfl2X02 JAs7IYwAuvLVN1XX7pVUYc6ivbw9N3XLi+WvKh2ujN01NfKArKlsvQ2DngUdiPOsP+ cKnXSrwSlE8glhjCtXDHJplE+Qtc1JAbFvhjfhgHW/c6ePTA7flbtkD0DxkhashtuF EGU05XoNoiNvmENhQC+E6uIm/mi7PeAgyiELP2rHnaDiyRjaKME31BVBvsMA5bfN39 +CxZrnQB5IgC9DdKJSsGs6fmn9YeI/OHH9M0W43D79OMZIBp+1s9bgtY4C+FhXrUDN jR18tMamlVH9g== Subject: [PATCH 03/12] xfs: xfs_inode_free_quota_blocks should scan project quota From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , Brian Foster , linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com, bfoster@redhat.com Date: Thu, 28 Jan 2021 18:18:03 -0800 Message-ID: <161188668347.1943978.14528129365746247716.stgit@magnolia> In-Reply-To: <161188666613.1943978.971196931920996596.stgit@magnolia> References: <161188666613.1943978.971196931920996596.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Buffered writers who have run out of quota reservation call xfs_inode_free_quota_blocks to try to free any space reservations that might reduce the quota usage. Unfortunately, the buffered write path treats "out of project quota" the same as "out of overall space" so this function has never supported scanning for space that might ease an "out of project quota" condition. We're about to start using this function for cases where we actually /can/ tell if we're out of project quota, so add in this functionality. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Reviewed-by: Brian Foster --- fs/xfs/xfs_icache.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 89f9e692fde7..10c1a0dee17d 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -1434,6 +1434,15 @@ xfs_inode_free_quota_blocks( } } + if (XFS_IS_PQUOTA_ENFORCED(ip->i_mount)) { + dq = xfs_inode_dquot(ip, XFS_DQTYPE_PROJ); + if (dq && xfs_dquot_lowsp(dq)) { + eofb.eof_prid = ip->i_d.di_projid; + eofb.eof_flags |= XFS_EOF_FLAGS_PRID; + do_work = true; + } + } + if (!do_work) return false; From patchwork Fri Jan 29 02:18:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 12055021 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BF9A4C433DB for ; Fri, 29 Jan 2021 02:18:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 80A7764E07 for ; Fri, 29 Jan 2021 02:18:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231586AbhA2CSw (ORCPT ); Thu, 28 Jan 2021 21:18:52 -0500 Received: from mail.kernel.org ([198.145.29.99]:57806 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229819AbhA2CSu (ORCPT ); Thu, 28 Jan 2021 21:18:50 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id A0FC064E02; Fri, 29 Jan 2021 02:18:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611886689; bh=WLOegPftckdrBcMYm8iE+X3h0C15q39r6oHlMJd/p2w=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=TKcspfKHrRqcg/ymToB4kl2NyMwoxqjEBid6f78iqjghmw5Sv0A6A3C4bLxc3TuZg zB/3sUvU+1ZHpwpWaNbGrUFFA7ot4TmgPqOf0qY0YJ7d2PWnw1EZwVbRyttL8ITUsj o0peY61ZEkTIIpJI6PIA6Iutl+W3X1xu1QOW4+tUHCppE4eHFqqOkVralhOmQMP7gT 1GVONMCdE1W7CP12/oby6f8OJePqwblGtTonOtPMrnDM/JpYJ/ef0CgVimyxArIAmS PdsJiNyL5jsOZ4R45HyG8b0tHmc4Paa8P3WUzFpn3wlt0C61WYZM/TAkFttwqJo575 hSIdwxvGAxBmg== Subject: [PATCH 04/12] xfs: move and rename xfs_inode_free_quota_blocks to avoid conflicts From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , Brian Foster , linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com, bfoster@redhat.com Date: Thu, 28 Jan 2021 18:18:09 -0800 Message-ID: <161188668922.1943978.16135411188719072001.stgit@magnolia> In-Reply-To: <161188666613.1943978.971196931920996596.stgit@magnolia> References: <161188666613.1943978.971196931920996596.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Move this function further down in the file so that later cleanups won't have to declare static functions. Change the name because we're about to rework all the code that performs garbage collection of speculatively allocated file blocks. No functional changes. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Reviewed-by: Brian Foster --- fs/xfs/xfs_file.c | 2 - fs/xfs/xfs_icache.c | 110 ++++++++++++++++++++++++++------------------------- fs/xfs/xfs_icache.h | 2 - 3 files changed, 57 insertions(+), 57 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 69879237533b..d69e5abcc1b4 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -747,7 +747,7 @@ xfs_file_buffered_write( */ if (ret == -EDQUOT && !cleared_space) { xfs_iunlock(ip, iolock); - cleared_space = xfs_inode_free_quota_blocks(ip); + cleared_space = xfs_blockgc_free_quota(ip); if (cleared_space) goto write_retry; iolock = 0; diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 10c1a0dee17d..aba901d5637b 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -1396,61 +1396,6 @@ xfs_icache_free_eofblocks( XFS_ICI_EOFBLOCKS_TAG); } -/* - * Run cow/eofblocks scans on the quotas applicable to the inode. For inodes - * with multiple quotas, we don't know exactly which quota caused an allocation - * failure. We make a best effort by including each quota under low free space - * conditions (less than 1% free space) in the scan. - */ -bool -xfs_inode_free_quota_blocks( - struct xfs_inode *ip) -{ - struct xfs_eofblocks eofb = {0}; - struct xfs_dquot *dq; - bool do_work = false; - - /* - * Run a sync scan to increase effectiveness and use the union filter to - * cover all applicable quotas in a single scan. - */ - eofb.eof_flags = XFS_EOF_FLAGS_UNION | XFS_EOF_FLAGS_SYNC; - - if (XFS_IS_UQUOTA_ENFORCED(ip->i_mount)) { - dq = xfs_inode_dquot(ip, XFS_DQTYPE_USER); - if (dq && xfs_dquot_lowsp(dq)) { - eofb.eof_uid = VFS_I(ip)->i_uid; - eofb.eof_flags |= XFS_EOF_FLAGS_UID; - do_work = true; - } - } - - if (XFS_IS_GQUOTA_ENFORCED(ip->i_mount)) { - dq = xfs_inode_dquot(ip, XFS_DQTYPE_GROUP); - if (dq && xfs_dquot_lowsp(dq)) { - eofb.eof_gid = VFS_I(ip)->i_gid; - eofb.eof_flags |= XFS_EOF_FLAGS_GID; - do_work = true; - } - } - - if (XFS_IS_PQUOTA_ENFORCED(ip->i_mount)) { - dq = xfs_inode_dquot(ip, XFS_DQTYPE_PROJ); - if (dq && xfs_dquot_lowsp(dq)) { - eofb.eof_prid = ip->i_d.di_projid; - eofb.eof_flags |= XFS_EOF_FLAGS_PRID; - do_work = true; - } - } - - if (!do_work) - return false; - - xfs_icache_free_eofblocks(ip->i_mount, &eofb); - xfs_icache_free_cowblocks(ip->i_mount, &eofb); - return true; -} - static inline unsigned long xfs_iflag_for_tag( int tag) @@ -1699,3 +1644,58 @@ xfs_start_block_reaping( xfs_queue_eofblocks(mp); xfs_queue_cowblocks(mp); } + +/* + * Run cow/eofblocks scans on the quotas applicable to the inode. For inodes + * with multiple quotas, we don't know exactly which quota caused an allocation + * failure. We make a best effort by including each quota under low free space + * conditions (less than 1% free space) in the scan. + */ +bool +xfs_blockgc_free_quota( + struct xfs_inode *ip) +{ + struct xfs_eofblocks eofb = {0}; + struct xfs_dquot *dq; + bool do_work = false; + + /* + * Run a sync scan to increase effectiveness and use the union filter to + * cover all applicable quotas in a single scan. + */ + eofb.eof_flags = XFS_EOF_FLAGS_UNION | XFS_EOF_FLAGS_SYNC; + + if (XFS_IS_UQUOTA_ENFORCED(ip->i_mount)) { + dq = xfs_inode_dquot(ip, XFS_DQTYPE_USER); + if (dq && xfs_dquot_lowsp(dq)) { + eofb.eof_uid = VFS_I(ip)->i_uid; + eofb.eof_flags |= XFS_EOF_FLAGS_UID; + do_work = true; + } + } + + if (XFS_IS_GQUOTA_ENFORCED(ip->i_mount)) { + dq = xfs_inode_dquot(ip, XFS_DQTYPE_GROUP); + if (dq && xfs_dquot_lowsp(dq)) { + eofb.eof_gid = VFS_I(ip)->i_gid; + eofb.eof_flags |= XFS_EOF_FLAGS_GID; + do_work = true; + } + } + + if (XFS_IS_PQUOTA_ENFORCED(ip->i_mount)) { + dq = xfs_inode_dquot(ip, XFS_DQTYPE_PROJ); + if (dq && xfs_dquot_lowsp(dq)) { + eofb.eof_prid = ip->i_d.di_projid; + eofb.eof_flags |= XFS_EOF_FLAGS_PRID; + do_work = true; + } + } + + if (!do_work) + return false; + + xfs_icache_free_eofblocks(ip->i_mount, &eofb); + xfs_icache_free_cowblocks(ip->i_mount, &eofb); + return true; +} diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h index 3f7ddbca8638..21b726a05b0d 100644 --- a/fs/xfs/xfs_icache.h +++ b/fs/xfs/xfs_icache.h @@ -54,7 +54,7 @@ long xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan); void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); -bool xfs_inode_free_quota_blocks(struct xfs_inode *ip); +bool xfs_blockgc_free_quota(struct xfs_inode *ip); void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip); void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip); From patchwork Fri Jan 29 02:18:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 12055015 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D4810C43333 for ; Fri, 29 Jan 2021 02:18:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A5D6364E01 for ; Fri, 29 Jan 2021 02:18:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231575AbhA2CSf (ORCPT ); Thu, 28 Jan 2021 21:18:35 -0500 Received: from mail.kernel.org ([198.145.29.99]:57470 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229819AbhA2CSa (ORCPT ); Thu, 28 Jan 2021 21:18:30 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 4603A64DF1; Fri, 29 Jan 2021 02:18:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611886695; bh=ClBONMnDsnLPgrBMvRzHjzGSGUDWD+5ec74bFVP200s=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=DsM7hudabEDapCCrHyYxvQkeMmix/Fk49ZZOCH9Y1OsTaOve955BWvrygXmob64u+ B7rKzR15ma2ynxx6g7bfK55QoFvZLiSGc4MSIN2ly8t56IEU7xIpA0sN2sj0kuZqt4 xyZWuAHvlMCSwoB2QkBskWeYWxj2/uSwzgsbt9Hv6SlrwoDEv4sVP8KhliDz5Y+Ali OGMCk+IZoCnZ5cMDBSbDYslaKk9CyJ7u0s+flShGlw6hqdOHPC/PaIvtmWGTca/Lzr /1rtTQ6E/lsQHYmfvejmTHy7+MPc7Je+41CNcclU+SVdZ1uMapH1Wj83n9vY3ttn3a K0azgkkpPOZPg== Subject: [PATCH 05/12] xfs: pass flags and return gc errors from xfs_blockgc_free_quota From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , Brian Foster , linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com, bfoster@redhat.com Date: Thu, 28 Jan 2021 18:18:14 -0800 Message-ID: <161188669493.1943978.3297062544493068654.stgit@magnolia> In-Reply-To: <161188666613.1943978.971196931920996596.stgit@magnolia> References: <161188666613.1943978.971196931920996596.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Change the signature of xfs_blockgc_free_quota in preparation for the next few patches. Callers can now pass EOF_FLAGS into the function to control scan parameters; and the function will now pass back any corruption errors seen while scanning, though for our retry loops we'll just try again unconditionally. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig Reviewed-by: Brian Foster --- fs/xfs/xfs_file.c | 10 +++++----- fs/xfs/xfs_icache.c | 26 +++++++++++++++++--------- fs/xfs/xfs_icache.h | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index d69e5abcc1b4..3be0b1d81325 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -743,14 +743,14 @@ xfs_file_buffered_write( * metadata space. This reduces the chances that the eofblocks scan * waits on dirty mappings. Since xfs_flush_inodes() is serialized, this * also behaves as a filter to prevent too many eofblocks scans from - * running at the same time. + * running at the same time. Use a synchronous scan to increase the + * effectiveness of the scan. */ if (ret == -EDQUOT && !cleared_space) { xfs_iunlock(ip, iolock); - cleared_space = xfs_blockgc_free_quota(ip); - if (cleared_space) - goto write_retry; - iolock = 0; + xfs_blockgc_free_quota(ip, XFS_EOF_FLAGS_SYNC); + cleared_space = true; + goto write_retry; } else if (ret == -ENOSPC && !cleared_space) { struct xfs_eofblocks eofb = {0}; diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index aba901d5637b..4a074aa12b52 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -1650,20 +1650,26 @@ xfs_start_block_reaping( * with multiple quotas, we don't know exactly which quota caused an allocation * failure. We make a best effort by including each quota under low free space * conditions (less than 1% free space) in the scan. + * + * Callers must not hold any inode's ILOCK. If requesting a synchronous scan + * (XFS_EOF_FLAGS_SYNC), the caller also must not hold any inode's IOLOCK or + * MMAPLOCK. */ -bool +int xfs_blockgc_free_quota( - struct xfs_inode *ip) + struct xfs_inode *ip, + unsigned int eof_flags) { struct xfs_eofblocks eofb = {0}; struct xfs_dquot *dq; bool do_work = false; + int error; /* - * Run a sync scan to increase effectiveness and use the union filter to - * cover all applicable quotas in a single scan. + * Run a scan to free blocks using the union filter to cover all + * applicable quotas in a single scan. */ - eofb.eof_flags = XFS_EOF_FLAGS_UNION | XFS_EOF_FLAGS_SYNC; + eofb.eof_flags = XFS_EOF_FLAGS_UNION | eof_flags; if (XFS_IS_UQUOTA_ENFORCED(ip->i_mount)) { dq = xfs_inode_dquot(ip, XFS_DQTYPE_USER); @@ -1693,9 +1699,11 @@ xfs_blockgc_free_quota( } if (!do_work) - return false; + return 0; - xfs_icache_free_eofblocks(ip->i_mount, &eofb); - xfs_icache_free_cowblocks(ip->i_mount, &eofb); - return true; + error = xfs_icache_free_eofblocks(ip->i_mount, &eofb); + if (error) + return error; + + return xfs_icache_free_cowblocks(ip->i_mount, &eofb); } diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h index 21b726a05b0d..d64ea8f5c589 100644 --- a/fs/xfs/xfs_icache.h +++ b/fs/xfs/xfs_icache.h @@ -54,7 +54,7 @@ long xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan); void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); -bool xfs_blockgc_free_quota(struct xfs_inode *ip); +int xfs_blockgc_free_quota(struct xfs_inode *ip, unsigned int eof_flags); void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip); void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip); From patchwork Fri Jan 29 02:18:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 12055023 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 63200C433DB for ; Fri, 29 Jan 2021 02:19:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2DF0264E07 for ; Fri, 29 Jan 2021 02:19:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229819AbhA2CTE (ORCPT ); Thu, 28 Jan 2021 21:19:04 -0500 Received: from mail.kernel.org ([198.145.29.99]:57870 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229757AbhA2CTC (ORCPT ); Thu, 28 Jan 2021 21:19:02 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id DCA6764E0C; Fri, 29 Jan 2021 02:18:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611886701; bh=rTYtZ3Ms2i+e7ecbSAy4uKOpFLj6N3Ofq1HXFtVzdT4=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=TmEUDv0q4iMRp0NTK381TfmPYz4g2TfS4Cn3Oz4cF/2yxnxS8HQSWAGKhFIVhc7B/ Ij6B32/FtqDxANkxY72fxGyOSQtrh25AAVspaNGMC+tOKPF/KvG//H4geocSmb+R1c a0pBTR5fHooyNBHs/n+bUSkMj5erxlHdcIhvtXhOTbCY7VP+98p4xXC+uS3uUfcfLl ab5cQh90XIEVr3eVvT8SmPzWxx3COD8yjQWilcllZXiRSrt/7SoRzKyiXxkMyutPQa lboLeQXpolmcBWVZTVV41VySKLRlGnyNuUKMkiL4V3osEMvncC1J/k6KhDbI4LVed/ 3Y5oX3AswseBw== Subject: [PATCH 06/12] xfs: try worst case space reservation upfront in xfs_reflink_remap_extent From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com, bfoster@redhat.com Date: Thu, 28 Jan 2021 18:18:20 -0800 Message-ID: <161188670052.1943978.11127149994884507361.stgit@magnolia> In-Reply-To: <161188666613.1943978.971196931920996596.stgit@magnolia> References: <161188666613.1943978.971196931920996596.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Now that we've converted xfs_reflink_remap_extent to use the new xfs_trans_alloc_inode API, we can focus on its slightly unusual behavior with regard to quota reservations. Since it's valid to remap written blocks into a hole, we must be able to increase the quota count by the number of blocks in the mapping. However, the incore space reservation process requires us to supply an asymptotic guess before we can gain exclusive access to resources. We'd like to reserve all the quota we need up front, but we also don't want to fail a written -> allocated remap operation unnecessarily. The solution is to make the remap_extents function call the transaction allocation function twice. The first time we ask to reserve enough space and quota to handle the absolute worst case situation, but if that fails, we can fall back to the old strategy: ask for the bare minimum space reservation upfront and increase the quota reservation later if we need to. Later in this patchset we change the transaction and quota code to try to reclaim space if we cannot reserve free space or quota. Restructuring the remap_extent function in this manner means that if the fallback increase fails, we can pass that back to the caller knowing that the transaction allocation already tried freeing space. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_reflink.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 27f875fa7a0d..086866f6e71f 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -991,6 +991,7 @@ xfs_reflink_remap_extent( xfs_off_t newlen; int64_t qdelta = 0; unsigned int resblks; + bool quota_reserved = true; bool smap_real; bool dmap_written = xfs_bmap_is_written_extent(dmap); int iext_delta = 0; @@ -1006,10 +1007,26 @@ xfs_reflink_remap_extent( * the same index in the bmap btree, so we only need a reservation for * one bmbt split if either thing is happening. However, we haven't * locked the inode yet, so we reserve assuming this is the case. + * + * The first allocation call tries to reserve enough space to handle + * mapping dmap into a sparse part of the file plus the bmbt split. We + * haven't locked the inode or read the existing mapping yet, so we do + * not know for sure that we need the space. This should succeed most + * of the time. + * + * If the first attempt fails, try again but reserving only enough + * space to handle a bmbt split. This is the hard minimum requirement, + * and we revisit quota reservations later when we know more about what + * we're remapping. */ resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); - error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks, 0, - false, &tp); + error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, + resblks + dmap->br_blockcount, 0, false, &tp); + if (error == -EDQUOT || error == -ENOSPC) { + quota_reserved = false; + error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, + resblks, 0, false, &tp); + } if (error) goto out; @@ -1076,7 +1093,7 @@ xfs_reflink_remap_extent( * before we started. That should have removed all the delalloc * reservations, but we code defensively. */ - if (!smap_real && dmap_written) { + if (!quota_reserved && !smap_real && dmap_written) { error = xfs_trans_reserve_quota_nblks(tp, ip, dmap->br_blockcount, 0, false); if (error) From patchwork Fri Jan 29 02:18:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 12055025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7791DC433DB for ; Fri, 29 Jan 2021 02:19:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3AEE564DF5 for ; Fri, 29 Jan 2021 02:19:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231252AbhA2CTL (ORCPT ); Thu, 28 Jan 2021 21:19:11 -0500 Received: from mail.kernel.org ([198.145.29.99]:57962 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229757AbhA2CTI (ORCPT ); Thu, 28 Jan 2021 21:19:08 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 94F5864DF5; Fri, 29 Jan 2021 02:18:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611886706; bh=LuIgLf/EMCcJy17c12HZF5qW/N+9sirXUGwSNtB0BKs=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=lRVIsjCbpFqWHOvFYRQTwXkJn9eX94PF5nxMsm0545J9MfmKTRkyLTlR9tz3SVKJl lc/jq5242fv/oUi8xRiHDute72mLBa1J/4VoBPL+e+wM7f77RJTHShwbzFm1F4E8CJ 63Ex9HrHmlhwF1wWtuGHGM7yB24rSrxC6gPY2eQS1VjwchPy1EnRliPxpezkQdqUJC A/WPsRjRhIOubInUhOOx1w3F0dSy2YlDL2wiVa2BP/xST0OSy1hSqIe4QKGjLz4xyx ifidshtFRqePg4o4+eebX2UqV7nb0rXW/fRWF9qBjxxJZpbdgPYogxgUwn55wIxAqt 5qrb95NyMR63g== Subject: [PATCH 07/12] xfs: flush eof/cowblocks if we can't reserve quota for file blocks From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com, bfoster@redhat.com Date: Thu, 28 Jan 2021 18:18:26 -0800 Message-ID: <161188670620.1943978.10940674429363795194.stgit@magnolia> In-Reply-To: <161188666613.1943978.971196931920996596.stgit@magnolia> References: <161188666613.1943978.971196931920996596.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong If a fs modification (data write, reflink, xattr set, fallocate, etc.) is unable to reserve enough quota to handle the modification, try clearing whatever space the filesystem might have been hanging onto in the hopes of speeding up the filesystem. The flushing behavior will become particularly important when we add deferred inode inactivation because that will increase the amount of space that isn't actively tied to user data. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_quota.h | 7 +++-- fs/xfs/xfs_reflink.c | 7 ++++- fs/xfs/xfs_trans.c | 12 +++++++- fs/xfs/xfs_trans_dquot.c | 69 ++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 84 insertions(+), 11 deletions(-) diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index f95a92d7ceaf..dd74a3e789bd 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -82,7 +82,8 @@ extern void xfs_trans_mod_dquot_byino(struct xfs_trans *, struct xfs_inode *, extern void xfs_trans_apply_dquot_deltas(struct xfs_trans *); extern void xfs_trans_unreserve_and_mod_dquots(struct xfs_trans *); int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp, struct xfs_inode *ip, - int64_t dblocks, int64_t rblocks, bool force); + int64_t dblocks, int64_t rblocks, bool force, + unsigned int *retry); extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, struct xfs_mount *, struct xfs_dquot *, struct xfs_dquot *, struct xfs_dquot *, int64_t, long, uint); @@ -114,7 +115,7 @@ extern void xfs_qm_unmount_quotas(struct xfs_mount *); static inline int xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t blocks) { - return xfs_trans_reserve_quota_nblks(NULL, ip, blocks, 0, false); + return xfs_trans_reserve_quota_nblks(NULL, ip, blocks, 0, false, NULL); } #else static inline int @@ -134,7 +135,7 @@ xfs_qm_vop_dqalloc(struct xfs_inode *ip, kuid_t kuid, kgid_t kgid, #define xfs_trans_unreserve_and_mod_dquots(tp) static inline int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp, struct xfs_inode *ip, int64_t dblocks, int64_t rblocks, - bool force) + bool force, unsigned int *retry) { return 0; } diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 086866f6e71f..9659adf5f182 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1092,10 +1092,15 @@ xfs_reflink_remap_extent( * count. This is suboptimal, but the VFS flushed the dest range * before we started. That should have removed all the delalloc * reservations, but we code defensively. + * + * xfs_trans_alloc_inode above already tried to grab an even larger + * quota reservation, and kicked off a blockgc scan if it couldn't. + * If we can't get a potentially smaller quota reservation now, we're + * done. */ if (!quota_reserved && !smap_real && dmap_written) { error = xfs_trans_reserve_quota_nblks(tp, ip, - dmap->br_blockcount, 0, false); + dmap->br_blockcount, 0, false, NULL); if (error) goto out_cancel; } diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 6c68635cc6ac..1217e6c41aa5 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -23,6 +23,7 @@ #include "xfs_inode.h" #include "xfs_dquot_item.h" #include "xfs_dquot.h" +#include "xfs_icache.h" kmem_zone_t *xfs_trans_zone; @@ -1046,8 +1047,10 @@ xfs_trans_alloc_inode( { struct xfs_trans *tp; struct xfs_mount *mp = ip->i_mount; + unsigned int qretry = 0; int error; +retry: error = xfs_trans_alloc(mp, resv, dblocks, rblocks / mp->m_sb.sb_rextsize, force ? XFS_TRANS_RESERVE : 0, &tp); @@ -1064,9 +1067,16 @@ xfs_trans_alloc_inode( goto out_cancel; } - error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force); + error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, force, + &qretry); if (error) goto out_cancel; + if (qretry) { + xfs_trans_cancel(tp); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + xfs_blockgc_free_quota(ip, 0); + goto retry; + } *tpp = tp; return 0; diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c index 73ef5994d09d..cb1fa4b047d6 100644 --- a/fs/xfs/xfs_trans_dquot.c +++ b/fs/xfs/xfs_trans_dquot.c @@ -770,11 +770,67 @@ xfs_trans_reserve_quota_bydquots( return error; } +/* + * Decide what to do after an attempt to reserve some quota. This will set + * the retry and error parameters as needed, and returns true if the quota + * reservation succeeded. + */ +static inline bool +reservation_success( + unsigned int qflag, + unsigned int *retry, + int *error) +{ + /* + * The caller is not interested in retries. Return whether or not we + * got an error code. + */ + if (retry == NULL) + return *error == 0; + + if (*error == -EDQUOT || *error == -ENOSPC) { + /* + * There isn't enough quota left to allow the reservation. + * + * If none of the retry bits are set, this is the first time + * that we failed a quota reservation. Zero the error code and + * set the appropriate quota flag in *retry to encourage the + * xfs_trans_reserve_quota_nblks caller to clear some space and + * call back. + * + * If any of the retry bits are set, this means that we failed + * the quota reservation once before, tried to free some quota, + * and have now failed the second quota reservation attempt. + * Pass the error back to the caller; we're done. + */ + if (!(*retry)) + *error = 0; + + *retry |= qflag; + return false; + } + + /* A non-quota error occurred; there is no retry. */ + if (*error) + return false; + + /* + * The reservation succeeded. Clear the quota flag from the retry + * state because there is nothing to retry. + */ + *retry &= ~qflag; + return true; +} /* - * Lock the dquot and change the reservation if we can. - * This doesn't change the actual usage, just the reservation. - * The inode sent in is locked. + * Lock the dquot and change the reservation if we can. This doesn't change + * the actual usage, just the reservation. The caller must hold ILOCK_EXCL on + * the inode. If @retry is not a NULL pointer, the caller must ensure that + * *retry is set to 0 before the first time this function is called. + * + * If the quota reservation fails because we hit a quota limit (and retry is + * not a NULL pointer, and *retry is zero), this function will set *retry to + * nonzero and return zero. */ int xfs_trans_reserve_quota_nblks( @@ -782,7 +838,8 @@ xfs_trans_reserve_quota_nblks( struct xfs_inode *ip, int64_t dblocks, int64_t rblocks, - bool force) + bool force, + unsigned int *retry) { struct xfs_mount *mp = ip->i_mount; unsigned int qflags = 0; @@ -801,14 +858,14 @@ xfs_trans_reserve_quota_nblks( error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot, ip->i_gdquot, ip->i_pdquot, dblocks, 0, XFS_QMOPT_RES_REGBLKS | qflags); - if (error) + if (!reservation_success(XFS_QMOPT_RES_REGBLKS, retry, &error)) return error; /* Do the same but for realtime blocks. */ error = xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot, ip->i_gdquot, ip->i_pdquot, rblocks, 0, XFS_QMOPT_RES_RTBLKS | qflags); - if (error) { + if (!reservation_success(XFS_QMOPT_RES_RTBLKS, retry, &error)) { xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot, ip->i_gdquot, ip->i_pdquot, -dblocks, 0, XFS_QMOPT_RES_REGBLKS); From patchwork Fri Jan 29 02:18:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 12055027 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 35331C433DB for ; Fri, 29 Jan 2021 02:19:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0209464DFF for ; Fri, 29 Jan 2021 02:19:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231271AbhA2CTO (ORCPT ); Thu, 28 Jan 2021 21:19:14 -0500 Received: from mail.kernel.org ([198.145.29.99]:57984 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229757AbhA2CTN (ORCPT ); Thu, 28 Jan 2021 21:19:13 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 2EECB64DFF; Fri, 29 Jan 2021 02:18:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611886712; bh=6stHRHqWHhd0qCEz3MYi00EQA3pQLKxBO9kMgnnNxAA=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=gMZd3eeOvOWEKicQmGFucnkOQhmUs0b4dYU9T/b1qkHw2TWaSREdbKAi8hTKKYK9R NgVKjO6HChmwl3ziH1Sy/OhIbe8eyc6Fd6ip7KIt4xg/2KRWXZdunS45J4cr8IDUxI /k11IgOXEObPt6/PCoZ45+VVXbozWLppxNF0cKkg94iEbMhsTIHSPGcOH8WsTluFzG XKU+BiwtPVdTemXr4ITRmtw1zsP/U9rcn4ww37hxKmUnfEfeFOetNos8luitwUIAd7 p4ge2c2IR0c1AKqGVqIn9dNF+1sC3DUfvSH4CLKaYFyF+RUTMdJk9egedPV//NlC/m DQXsEFj8f97Kw== Subject: [PATCH 08/12] xfs: flush eof/cowblocks if we can't reserve quota for inode creation From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com, bfoster@redhat.com Date: Thu, 28 Jan 2021 18:18:31 -0800 Message-ID: <161188671187.1943978.15078631305968419649.stgit@magnolia> In-Reply-To: <161188666613.1943978.971196931920996596.stgit@magnolia> References: <161188666613.1943978.971196931920996596.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong If an inode creation is unable to reserve enough quota to handle the modification, try clearing whatever space the filesystem might have been hanging onto in the hopes of speeding up the filesystem. The flushing behavior will become particularly important when we add deferred inode inactivation because that will increase the amount of space that isn't actively tied to user data. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_icache.c | 73 +++++++++++++++++++++++++++------------------- fs/xfs/xfs_icache.h | 2 + fs/xfs/xfs_quota.h | 5 ++- fs/xfs/xfs_trans.c | 10 ++++++ fs/xfs/xfs_trans_dquot.c | 19 ++++++++++-- 5 files changed, 73 insertions(+), 36 deletions(-) diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 4a074aa12b52..cd369dd48818 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -1646,64 +1646,77 @@ xfs_start_block_reaping( } /* - * Run cow/eofblocks scans on the quotas applicable to the inode. For inodes - * with multiple quotas, we don't know exactly which quota caused an allocation - * failure. We make a best effort by including each quota under low free space - * conditions (less than 1% free space) in the scan. + * Run cow/eofblocks scans on the supplied dquots. We don't know exactly which + * quota caused an allocation failure, so we make a best effort by including + * each quota under low free space conditions (less than 1% free space) in the + * scan. * * Callers must not hold any inode's ILOCK. If requesting a synchronous scan * (XFS_EOF_FLAGS_SYNC), the caller also must not hold any inode's IOLOCK or * MMAPLOCK. */ int -xfs_blockgc_free_quota( - struct xfs_inode *ip, +xfs_blockgc_free_dquots( + struct xfs_dquot *udqp, + struct xfs_dquot *gdqp, + struct xfs_dquot *pdqp, unsigned int eof_flags) { struct xfs_eofblocks eofb = {0}; - struct xfs_dquot *dq; + struct xfs_mount *mp = NULL; bool do_work = false; int error; + if (!udqp && !gdqp && !pdqp) + return 0; + if (udqp) + mp = udqp->q_mount; + if (!mp && gdqp) + mp = gdqp->q_mount; + if (!mp && pdqp) + mp = pdqp->q_mount; + /* * Run a scan to free blocks using the union filter to cover all * applicable quotas in a single scan. */ eofb.eof_flags = XFS_EOF_FLAGS_UNION | eof_flags; - if (XFS_IS_UQUOTA_ENFORCED(ip->i_mount)) { - dq = xfs_inode_dquot(ip, XFS_DQTYPE_USER); - if (dq && xfs_dquot_lowsp(dq)) { - eofb.eof_uid = VFS_I(ip)->i_uid; - eofb.eof_flags |= XFS_EOF_FLAGS_UID; - do_work = true; - } + if (XFS_IS_UQUOTA_ENFORCED(mp) && udqp && xfs_dquot_lowsp(udqp)) { + eofb.eof_uid = make_kuid(mp->m_super->s_user_ns, udqp->q_id); + eofb.eof_flags |= XFS_EOF_FLAGS_UID; + do_work = true; } - if (XFS_IS_GQUOTA_ENFORCED(ip->i_mount)) { - dq = xfs_inode_dquot(ip, XFS_DQTYPE_GROUP); - if (dq && xfs_dquot_lowsp(dq)) { - eofb.eof_gid = VFS_I(ip)->i_gid; - eofb.eof_flags |= XFS_EOF_FLAGS_GID; - do_work = true; - } + if (XFS_IS_UQUOTA_ENFORCED(mp) && gdqp && xfs_dquot_lowsp(gdqp)) { + eofb.eof_gid = make_kgid(mp->m_super->s_user_ns, gdqp->q_id); + eofb.eof_flags |= XFS_EOF_FLAGS_GID; + do_work = true; } - if (XFS_IS_PQUOTA_ENFORCED(ip->i_mount)) { - dq = xfs_inode_dquot(ip, XFS_DQTYPE_PROJ); - if (dq && xfs_dquot_lowsp(dq)) { - eofb.eof_prid = ip->i_d.di_projid; - eofb.eof_flags |= XFS_EOF_FLAGS_PRID; - do_work = true; - } + if (XFS_IS_PQUOTA_ENFORCED(mp) && pdqp && xfs_dquot_lowsp(pdqp)) { + eofb.eof_prid = pdqp->q_id; + eofb.eof_flags |= XFS_EOF_FLAGS_PRID; + do_work = true; } if (!do_work) return 0; - error = xfs_icache_free_eofblocks(ip->i_mount, &eofb); + error = xfs_icache_free_eofblocks(mp, &eofb); if (error) return error; - return xfs_icache_free_cowblocks(ip->i_mount, &eofb); + return xfs_icache_free_cowblocks(mp, &eofb); +} + +/* Run cow/eofblocks scans on the quotas attached to the inode. */ +int +xfs_blockgc_free_quota( + struct xfs_inode *ip, + unsigned int eof_flags) +{ + return xfs_blockgc_free_dquots(xfs_inode_dquot(ip, XFS_DQTYPE_USER), + xfs_inode_dquot(ip, XFS_DQTYPE_GROUP), + xfs_inode_dquot(ip, XFS_DQTYPE_PROJ), eof_flags); } diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h index d64ea8f5c589..5f520de637f6 100644 --- a/fs/xfs/xfs_icache.h +++ b/fs/xfs/xfs_icache.h @@ -54,6 +54,8 @@ long xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan); void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); +int xfs_blockgc_free_dquots(struct xfs_dquot *udqp, struct xfs_dquot *gdqp, + struct xfs_dquot *pdqp, unsigned int eof_flags); int xfs_blockgc_free_quota(struct xfs_inode *ip, unsigned int eof_flags); void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip); diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index dd74a3e789bd..4360d73a0e99 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -89,7 +89,7 @@ extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, struct xfs_dquot *, struct xfs_dquot *, int64_t, long, uint); int xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp, struct xfs_dquot *gdqp, - struct xfs_dquot *pdqp, int64_t dblocks); + struct xfs_dquot *pdqp, int64_t dblocks, unsigned int *retry); extern int xfs_qm_vop_dqalloc(struct xfs_inode *, kuid_t, kgid_t, prid_t, uint, struct xfs_dquot **, struct xfs_dquot **, @@ -155,7 +155,8 @@ xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t blocks) static inline int xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp, - struct xfs_dquot *gdqp, struct xfs_dquot *pdqp, int64_t dblocks) + struct xfs_dquot *gdqp, struct xfs_dquot *pdqp, int64_t dblocks, + unsigned int *retry) { return 0; } diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 1217e6c41aa5..b08bb5a8fb60 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -1102,17 +1102,25 @@ xfs_trans_alloc_icreate( struct xfs_trans **tpp) { struct xfs_trans *tp; + unsigned int qretry = 0; int error; +retry: error = xfs_trans_alloc(mp, resv, dblocks, 0, 0, &tp); if (error) return error; - error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, dblocks); + error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, dblocks, + &qretry); if (error) { xfs_trans_cancel(tp); return error; } + if (qretry) { + xfs_trans_cancel(tp); + xfs_blockgc_free_dquots(udqp, gdqp, pdqp, 0); + goto retry; + } *tpp = tp; return 0; diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c index cb1fa4b047d6..00b40813f77d 100644 --- a/fs/xfs/xfs_trans_dquot.c +++ b/fs/xfs/xfs_trans_dquot.c @@ -875,22 +875,35 @@ xfs_trans_reserve_quota_nblks( return 0; } -/* Change the quota reservations for an inode creation activity. */ +/* + * Change the quota reservations for an inode creation activity. This doesn't + * change the actual usage, just the reservation. If @retry is not a NULL + * pointer, the caller must ensure that *retry is set to zero before the first + * time this function is called. + * + * If the quota reservation fails because we hit a quota limit (and retry is + * not a NULL pointer, and *retry is zero), this function will set *retry to + * nonzero and return zero. + */ int xfs_trans_reserve_quota_icreate( struct xfs_trans *tp, struct xfs_dquot *udqp, struct xfs_dquot *gdqp, struct xfs_dquot *pdqp, - int64_t dblocks) + int64_t dblocks, + unsigned int *retry) { struct xfs_mount *mp = tp->t_mountp; + int error; if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp)) return 0; - return xfs_trans_reserve_quota_bydquots(tp, mp, udqp, gdqp, pdqp, + error = xfs_trans_reserve_quota_bydquots(tp, mp, udqp, gdqp, pdqp, dblocks, 1, XFS_QMOPT_RES_REGBLKS); + reservation_success(XFS_QMOPT_RES_REGBLKS, retry, &error); + return error; } /* From patchwork Fri Jan 29 02:18:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 12055029 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8F0C5C433DB for ; Fri, 29 Jan 2021 02:19:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4B59464DFF for ; Fri, 29 Jan 2021 02:19:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231470AbhA2CTU (ORCPT ); Thu, 28 Jan 2021 21:19:20 -0500 Received: from mail.kernel.org ([198.145.29.99]:58006 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229757AbhA2CTS (ORCPT ); Thu, 28 Jan 2021 21:19:18 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id C25B564E00; Fri, 29 Jan 2021 02:18:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611886717; bh=niXr62Q4dLCslVD+04nN7JVeomFpMgC1Qr/phPw9ZXY=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=EyColuTXJnjWLqaWvRl2bFVjmAN8DbZtC2mAhEZacZzYlwpz2gpXF7Ee0I/m7vvq4 KG5QdZ4r3yo1yVEO8W5Z1mm3NTsP33GZjqXbGa0HDEPBk44RRDNnIsEIggog8bZrKz Euo3TWTIXkXPCLB4KWUx3JVqvCPWHNkapMfmjffk9CKwC+MS/t2/XKA9PXj/7LzePK u6J7OM6vP2IeTLedoq/HXdopTUAdsQxvG1RMnHazhB+GFm6/OvswSXxA0+FjtgQK9b urllXl5yUeXrmQCaBZ+lLCsp72VpGSFbNQ8yQ8Wk88Pk4iI3orYQf5lQ+ldIvkiKUg M7654cLlIweFg== Subject: [PATCH 09/12] xfs: flush eof/cowblocks if we can't reserve quota for chown From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com, bfoster@redhat.com Date: Thu, 28 Jan 2021 18:18:37 -0800 Message-ID: <161188671741.1943978.420169006925452801.stgit@magnolia> In-Reply-To: <161188666613.1943978.971196931920996596.stgit@magnolia> References: <161188666613.1943978.971196931920996596.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong If a file user, group, or project change is unable to reserve enough quota to handle the modification, try clearing whatever space the filesystem might have been hanging onto in the hopes of speeding up the filesystem. The flushing behavior will become particularly important when we add deferred inode inactivation because that will increase the amount of space that isn't actively tied to user data. Note that the retry loop is open-coded here because there are only two places in the codebase where we ever change [ugp]id; and the setattr and setxattr code is already tricky enough. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_ioctl.c | 10 +++++++++- fs/xfs/xfs_iops.c | 11 ++++++++++- fs/xfs/xfs_quota.h | 4 ++-- fs/xfs/xfs_trans_dquot.c | 28 ++++++++++++++++++++++++---- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 73cfee8007a8..e945ab5cfa55 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -1436,6 +1436,7 @@ xfs_ioctl_setattr( struct xfs_trans *tp; struct xfs_dquot *pdqp = NULL; struct xfs_dquot *olddquot = NULL; + unsigned int quota_retry = 0; int code; trace_xfs_ioctl_setattr(ip); @@ -1462,6 +1463,7 @@ xfs_ioctl_setattr( xfs_ioctl_setattr_prepare_dax(ip, fa); +retry: tp = xfs_ioctl_setattr_get_trans(ip); if (IS_ERR(tp)) { code = PTR_ERR(tp); @@ -1471,9 +1473,15 @@ xfs_ioctl_setattr( if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp) && ip->i_d.di_projid != fa->fsx_projid) { code = xfs_trans_reserve_quota_chown(tp, ip, NULL, NULL, pdqp, - capable(CAP_FOWNER)); + capable(CAP_FOWNER), "a_retry); if (code) /* out of quota */ goto error_trans_cancel; + if (quota_retry) { + xfs_trans_cancel(tp); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + xfs_blockgc_free_dquots(NULL, NULL, pdqp, 0); + goto retry; + } } xfs_fill_fsxattr(ip, false, &old_fa); diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 51c877ce90bc..f5bb390b7373 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -660,6 +660,7 @@ xfs_setattr_nonsize( kgid_t gid = GLOBAL_ROOT_GID, igid = GLOBAL_ROOT_GID; struct xfs_dquot *udqp = NULL, *gdqp = NULL; struct xfs_dquot *olddquot1 = NULL, *olddquot2 = NULL; + unsigned int quota_retry = 0; ASSERT((mask & ATTR_SIZE) == 0); @@ -700,6 +701,7 @@ xfs_setattr_nonsize( return error; } +retry: error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); if (error) goto out_dqrele; @@ -731,9 +733,16 @@ xfs_setattr_nonsize( (XFS_IS_GQUOTA_ON(mp) && !gid_eq(igid, gid)))) { ASSERT(tp); error = xfs_trans_reserve_quota_chown(tp, ip, udqp, - gdqp, NULL, capable(CAP_FOWNER)); + gdqp, NULL, capable(CAP_FOWNER), + "a_retry); if (error) /* out of quota */ goto out_cancel; + if (quota_retry) { + xfs_trans_cancel(tp); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + xfs_blockgc_free_dquots(udqp, gdqp, NULL, 0); + goto retry; + } } /* diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 4360d73a0e99..f1cdd6de56ea 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -101,7 +101,7 @@ extern struct xfs_dquot *xfs_qm_vop_chown(struct xfs_trans *, struct xfs_inode *, struct xfs_dquot **, struct xfs_dquot *); int xfs_trans_reserve_quota_chown(struct xfs_trans *tp, struct xfs_inode *ip, struct xfs_dquot *udqp, struct xfs_dquot *gdqp, - struct xfs_dquot *pdqp, bool force); + struct xfs_dquot *pdqp, bool force, unsigned int *retry); extern int xfs_qm_dqattach(struct xfs_inode *); extern int xfs_qm_dqattach_locked(struct xfs_inode *ip, bool doalloc); extern void xfs_qm_dqdetach(struct xfs_inode *); @@ -167,7 +167,7 @@ xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp, static inline int xfs_trans_reserve_quota_chown(struct xfs_trans *tp, struct xfs_inode *ip, struct xfs_dquot *udqp, struct xfs_dquot *gdqp, - struct xfs_dquot *pdqp, bool force) + struct xfs_dquot *pdqp, bool force, unsigned int *retry) { return 0; } diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c index 00b40813f77d..086de621f431 100644 --- a/fs/xfs/xfs_trans_dquot.c +++ b/fs/xfs/xfs_trans_dquot.c @@ -907,7 +907,15 @@ xfs_trans_reserve_quota_icreate( } /* - * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID). + * Chagnge quota reservations for setattr(AT_UID|AT_GID|AT_PROJID). This + * doesn't change the actual usage, just the reservation. The caller must hold + * ILOCK_EXCL on the inode. If @retry is not a NULL pointer, the caller must + * ensure that *retry is set to zero before the first time this function is + * called. + * + * If the quota reservation fails because we hit a quota limit (and retry is + * not a NULL pointer, and *retry is zero), this function will set *retry to + * nonzero and return zero. */ int xfs_trans_reserve_quota_chown( @@ -916,7 +924,8 @@ xfs_trans_reserve_quota_chown( struct xfs_dquot *udqp, struct xfs_dquot *gdqp, struct xfs_dquot *pdqp, - bool force) + bool force, + unsigned int *retry) { struct xfs_mount *mp = ip->i_mount; struct xfs_dquot *udq_unres = NULL; /* old dquots */ @@ -976,7 +985,7 @@ xfs_trans_reserve_quota_chown( gdq_delblks, pdq_delblks, ip->i_d.di_nblocks, 1, qflags); if (error) - return error; + goto err; /* * Do the delayed blks reservations/unreservations now. Since, these @@ -994,13 +1003,24 @@ xfs_trans_reserve_quota_chown( udq_delblks, gdq_delblks, pdq_delblks, (xfs_qcnt_t)delblks, 0, qflags); if (error) - return error; + goto err; xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, udq_unres, gdq_unres, pdq_unres, -((xfs_qcnt_t)delblks), 0, qflags); } return 0; +err: + /* + * Handle all quota reservation failures in the same place because we + * don't want reservation_success() to clear REGBLKS from the retry + * flags after we _reserve_quota for the ondisk blocks but before we + * _reserve_quota for the delalloc blocks. If we were called with a + * nonzero *retry, that means we failed to get the quota reservation + * once before and do not want to schedule a retry on a second error. + */ + reservation_success(XFS_QMOPT_RES_REGBLKS, retry, &error); + return error; } /* From patchwork Fri Jan 29 02:18:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 12055031 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 29E46C433DB for ; Fri, 29 Jan 2021 02:19:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E01D264DFF for ; Fri, 29 Jan 2021 02:19:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231490AbhA2CTZ (ORCPT ); Thu, 28 Jan 2021 21:19:25 -0500 Received: from mail.kernel.org ([198.145.29.99]:58052 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229757AbhA2CTY (ORCPT ); Thu, 28 Jan 2021 21:19:24 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 6A1C664E03; Fri, 29 Jan 2021 02:18:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611886723; bh=jv9k7JCdWStfItBdc/gCnr0EiQJ34KKFl9txIkBXeaw=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=Z+nucafXHsA9SFbW4huFWYpGVYB0dm9Jvh13ha6b7QJ8R4G7md3cFdoZUsWTztlbw oyotuoIc6hftB7Tk1BBnIZ9B1dZESSoC60ThfwWFDb9sBZKuizttx2NsTDGB8fanx9 kpol81EBsZn0Apsvjs8zfnQQMITs9OYqH/J8Vm8ACFZJikHgpgHboUWEKNhuH5Lj/u gbeSwBFTkKkAIYiKp/MQMAoEb7L0dpqO7l0+L3wUsWI1M0D3crELEJSHn/QJBZVgSM +xGRVJhf5b8d/apBqaySfExR8yb7TbowKw7SxYbNSnpQIgEEVEi7aJcpsLwoYOORTK Xsa5+yMbix+QQ== Subject: [PATCH 10/12] xfs: add a tracepoint for blockgc scans From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com, bfoster@redhat.com Date: Thu, 28 Jan 2021 18:18:43 -0800 Message-ID: <161188672308.1943978.15587250013985486300.stgit@magnolia> In-Reply-To: <161188666613.1943978.971196931920996596.stgit@magnolia> References: <161188666613.1943978.971196931920996596.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Add some tracepoints so that we can observe when the speculative preallocation garbage collector runs. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_ioctl.c | 2 ++ fs/xfs/xfs_trace.c | 1 + fs/xfs/xfs_trace.h | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index e945ab5cfa55..992efd149248 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -2356,6 +2356,8 @@ xfs_file_ioctl( if (error) return error; + trace_xfs_ioc_free_eofblocks(mp, &keofb, _RET_IP_); + sb_start_write(mp->m_super); error = xfs_icache_free_eofblocks(mp, &keofb); sb_end_write(mp->m_super); diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c index 120398a37c2a..9b8d703dc9fd 100644 --- a/fs/xfs/xfs_trace.c +++ b/fs/xfs/xfs_trace.c @@ -29,6 +29,7 @@ #include "xfs_filestream.h" #include "xfs_fsmap.h" #include "xfs_btree_staging.h" +#include "xfs_icache.h" /* * We include this last to have the helpers above available for the trace diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 407c3a5208ab..38649e3341cb 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -37,6 +37,7 @@ struct xfs_trans_res; struct xfs_inobt_rec_incore; union xfs_btree_ptr; struct xfs_dqtrx; +struct xfs_eofblocks; #define XFS_ATTR_FILTER_FLAGS \ { XFS_ATTR_ROOT, "ROOT" }, \ @@ -3888,6 +3889,46 @@ DEFINE_EVENT(xfs_timestamp_range_class, name, \ DEFINE_TIMESTAMP_RANGE_EVENT(xfs_inode_timestamp_range); DEFINE_TIMESTAMP_RANGE_EVENT(xfs_quota_expiry_range); +DECLARE_EVENT_CLASS(xfs_eofblocks_class, + TP_PROTO(struct xfs_mount *mp, struct xfs_eofblocks *eofb, + unsigned long caller_ip), + TP_ARGS(mp, eofb, caller_ip), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(__u32, flags) + __field(uint32_t, uid) + __field(uint32_t, gid) + __field(prid_t, prid) + __field(__u64, min_file_size) + __field(unsigned long, caller_ip) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->flags = eofb ? eofb->eof_flags : 0; + __entry->uid = eofb ? from_kuid(mp->m_super->s_user_ns, + eofb->eof_uid) : 0; + __entry->gid = eofb ? from_kgid(mp->m_super->s_user_ns, + eofb->eof_gid) : 0; + __entry->prid = eofb ? eofb->eof_prid : 0; + __entry->min_file_size = eofb ? eofb->eof_min_file_size : 0; + __entry->caller_ip = caller_ip; + ), + TP_printk("dev %d:%d flags 0x%x uid %u gid %u prid %u minsize %llu caller %pS", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->flags, + __entry->uid, + __entry->gid, + __entry->prid, + __entry->min_file_size, + (char *)__entry->caller_ip) +); +#define DEFINE_EOFBLOCKS_EVENT(name) \ +DEFINE_EVENT(xfs_eofblocks_class, name, \ + TP_PROTO(struct xfs_mount *mp, struct xfs_eofblocks *eofb, \ + unsigned long caller_ip), \ + TP_ARGS(mp, eofb, caller_ip)) +DEFINE_EOFBLOCKS_EVENT(xfs_ioc_free_eofblocks); + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH From patchwork Fri Jan 29 02:18:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 12055033 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 95505C433DB for ; Fri, 29 Jan 2021 02:19:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 564D164DFF for ; Fri, 29 Jan 2021 02:19:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231517AbhA2CTe (ORCPT ); Thu, 28 Jan 2021 21:19:34 -0500 Received: from mail.kernel.org ([198.145.29.99]:58098 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231503AbhA2CTa (ORCPT ); Thu, 28 Jan 2021 21:19:30 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 1EBCF64E01; Fri, 29 Jan 2021 02:18:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611886729; bh=IkR9KkZMpbkGceud4If+C+B7p+/y2pP/T/nYjTyFVY4=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=rzd5YPU/Stwd2nvGrOKNaqjiUUiuQvGbgxCg10Zzz3MO0Of4/i3ECZwVbdG0ZGyp+ ahweR+N5kHOoKxE+68gbp+WmxJOn8S3id8iij26LrSB14vBG0MQ/socRLvmCWA0GMx MH1sV0t4IajvQt9jGuBdJ3OmyG3mjqlqKOAtgC47N3IcuYkJPqoZbz5xHOkbdOiVLz UjLF3U+CAwBcZd9y4/aeQ081dZDMvfvasarz47PNWEkaoES/S4XB9pxsHIiz1W1QjL gvK7hbTVKcI+5FIvwJQryDornaBn+0DDP3flhyWieLYTRRa1gC9qDc0r6VlAitRO5f 8hI62sHdyxQGA== Subject: [PATCH 11/12] xfs: refactor xfs_icache_free_{eof,cow}blocks call sites From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com, bfoster@redhat.com Date: Thu, 28 Jan 2021 18:18:48 -0800 Message-ID: <161188672870.1943978.6178874789730607697.stgit@magnolia> In-Reply-To: <161188666613.1943978.971196931920996596.stgit@magnolia> References: <161188666613.1943978.971196931920996596.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong In anticipation of more restructuring of the eof/cowblocks gc code, refactor calling of those two functions into a single internal helper function, then present a new standard interface to purge speculative block preallocations and start shifting higher level code to use that. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_file.c | 3 +-- fs/xfs/xfs_icache.c | 39 +++++++++++++++++++++++++++++++++------ fs/xfs/xfs_icache.h | 1 + fs/xfs/xfs_trace.h | 1 + 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 3be0b1d81325..dc91973c0b4f 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -759,8 +759,7 @@ xfs_file_buffered_write( xfs_iunlock(ip, iolock); eofb.eof_flags = XFS_EOF_FLAGS_SYNC; - xfs_icache_free_eofblocks(ip->i_mount, &eofb); - xfs_icache_free_cowblocks(ip->i_mount, &eofb); + xfs_blockgc_free_space(ip->i_mount, &eofb); goto write_retry; } diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index cd369dd48818..97c15fcdd6f7 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -1645,6 +1645,38 @@ xfs_start_block_reaping( xfs_queue_cowblocks(mp); } +/* Scan all incore inodes for block preallocations that we can remove. */ +static inline int +xfs_blockgc_scan( + struct xfs_mount *mp, + struct xfs_eofblocks *eofb) +{ + int error; + + error = xfs_icache_free_eofblocks(mp, eofb); + if (error) + return error; + + error = xfs_icache_free_cowblocks(mp, eofb); + if (error) + return error; + + return 0; +} + +/* + * Try to free space in the filesystem by purging eofblocks and cowblocks. + */ +int +xfs_blockgc_free_space( + struct xfs_mount *mp, + struct xfs_eofblocks *eofb) +{ + trace_xfs_blockgc_free_space(mp, eofb, _RET_IP_); + + return xfs_blockgc_scan(mp, eofb); +} + /* * Run cow/eofblocks scans on the supplied dquots. We don't know exactly which * quota caused an allocation failure, so we make a best effort by including @@ -1665,7 +1697,6 @@ xfs_blockgc_free_dquots( struct xfs_eofblocks eofb = {0}; struct xfs_mount *mp = NULL; bool do_work = false; - int error; if (!udqp && !gdqp && !pdqp) return 0; @@ -1703,11 +1734,7 @@ xfs_blockgc_free_dquots( if (!do_work) return 0; - error = xfs_icache_free_eofblocks(mp, &eofb); - if (error) - return error; - - return xfs_icache_free_cowblocks(mp, &eofb); + return xfs_blockgc_free_space(mp, &eofb); } /* Run cow/eofblocks scans on the quotas attached to the inode. */ diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h index 5f520de637f6..583c132ae0fb 100644 --- a/fs/xfs/xfs_icache.h +++ b/fs/xfs/xfs_icache.h @@ -57,6 +57,7 @@ void xfs_inode_set_reclaim_tag(struct xfs_inode *ip); int xfs_blockgc_free_dquots(struct xfs_dquot *udqp, struct xfs_dquot *gdqp, struct xfs_dquot *pdqp, unsigned int eof_flags); int xfs_blockgc_free_quota(struct xfs_inode *ip, unsigned int eof_flags); +int xfs_blockgc_free_space(struct xfs_mount *mp, struct xfs_eofblocks *eofb); void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip); void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip); diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 38649e3341cb..27929c6ca43a 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -3928,6 +3928,7 @@ DEFINE_EVENT(xfs_eofblocks_class, name, \ unsigned long caller_ip), \ TP_ARGS(mp, eofb, caller_ip)) DEFINE_EOFBLOCKS_EVENT(xfs_ioc_free_eofblocks); +DEFINE_EOFBLOCKS_EVENT(xfs_blockgc_free_space); #endif /* _TRACE_XFS_H */ From patchwork Fri Jan 29 02:18:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 12055035 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D34B9C433E0 for ; Fri, 29 Jan 2021 02:19:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A799C64E00 for ; Fri, 29 Jan 2021 02:19:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231513AbhA2CTg (ORCPT ); Thu, 28 Jan 2021 21:19:36 -0500 Received: from mail.kernel.org ([198.145.29.99]:58362 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229757AbhA2CTf (ORCPT ); Thu, 28 Jan 2021 21:19:35 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 4040264E02; Fri, 29 Jan 2021 02:18:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611886735; bh=SbGdaTAygv4nC81vT/tXM+peDBYFSDsdyv/zW6Qi8h0=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=M0OUxHQeIjFNBbxuOseQcHUJEPNKwRG4RII9Ff//rPkCqTV14KJ1xgBshdVAG6ro3 fomLg5SOoYG82n4Wml4RwER0OJhpYDYSgIuHKPwm+XBhdmgrk8jA1h7AUvOFXy/aZm 7GLQ3lg7gomfK0SNFtUbsjEjkKv7fqHpqRJbCE5uQ8XpLcBU9c+jomp8xVaCCBXDhe x0IwHM4NvxqdTyj4EUwUOCJ1nUnSdbpS8Jsv2Skxo8zANMPGJP3HDqmHeWO7VKDZJY +A5z0iBOEXo9XMF1kV6j16xwLT10tfPHSXIJuwxETWgeT7of9RURp5jx0WbIWSTrhW 6l2j6WIV4ZmBg== Subject: [PATCH 12/12] xfs: flush speculative space allocations when we run out of space From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com, bfoster@redhat.com Date: Thu, 28 Jan 2021 18:18:54 -0800 Message-ID: <161188673444.1943978.15159087396736987395.stgit@magnolia> In-Reply-To: <161188666613.1943978.971196931920996596.stgit@magnolia> References: <161188666613.1943978.971196931920996596.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong If a fs modification (creation, file write, reflink, etc.) is unable to reserve enough space to handle the modification, try clearing whatever space the filesystem might have been hanging onto in the hopes of speeding up the filesystem. The flushing behavior will become particularly important when we add deferred inode inactivation because that will increase the amount of space that isn't actively tied to user data. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_trans.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index b08bb5a8fb60..3c2b26a21c6d 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -289,6 +289,18 @@ xfs_trans_alloc( tp->t_firstblock = NULLFSBLOCK; error = xfs_trans_reserve(tp, resp, blocks, rtextents); + if (error == -ENOSPC) { + /* + * We weren't able to reserve enough space for the transaction. + * Flush the other speculative space allocations to free space. + * Do not perform a synchronous scan because callers can hold + * other locks. + */ + error = xfs_blockgc_free_space(mp, NULL); + if (error) + return error; + error = xfs_trans_reserve(tp, resp, blocks, rtextents); + } if (error) { xfs_trans_cancel(tp); return error;