From patchwork Sat Jan 23 18:52:05 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: 12041795 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.2 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 647B1C433DB for ; Sat, 23 Jan 2021 18:52:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 36674230FC for ; Sat, 23 Jan 2021 18:52:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726204AbhAWSw5 (ORCPT ); Sat, 23 Jan 2021 13:52:57 -0500 Received: from mail.kernel.org ([198.145.29.99]:35258 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726198AbhAWSw4 (ORCPT ); Sat, 23 Jan 2021 13:52:56 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 9FBB0230FC; Sat, 23 Jan 2021 18:52:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611427923; bh=5JOT6OHeTqWxFqllxHKNl2iq6FJlv1sKfQWBVzs+3qk=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=kYEqrjkyqGWEs+T5Pt9VMcUI0anv9rNBYMhveR9w3Fm2tjidQu6q1s2g8dUqSnr1Y aY9QDqiQQcPGGBU/GFig96026XUXQT3MuRCpdNp2Nl14Cs+TBwCzcAV6QFkFpduuQG 95PP3s4Y6TOC9JeMRt/gkZ7OeFcewlD2Ybdj3pgTekDOXkIMfyeWR9k20yu3h9kWDC o+g/J78tVRi9WgTMYnLPSjIQKCntOQBolqSz4YsegGVX+lhZ/DR/1tBKdrnp9jDUpB DOUB4c42tKqGjQMkgpvMJQg6bf9Qa+EJjAqCMJjCG9nKsZ42ni1/Iu9jwuUvXeZ/r6 cvStvCx9DPKtw== Subject: [PATCH 01/11] xfs: refactor messy xfs_inode_free_quota_* functions From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com Date: Sat, 23 Jan 2021 10:52:05 -0800 Message-ID: <161142792524.2171939.13857715099603482377.stgit@magnolia> In-Reply-To: <161142791950.2171939.3320927557987463636.stgit@magnolia> References: <161142791950.2171939.3320927557987463636.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 if we're low on quota 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 Sat Jan 23 18:52:10 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: 12041797 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.2 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 D2BDDC433E0 for ; Sat, 23 Jan 2021 18:53:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 940A722B40 for ; Sat, 23 Jan 2021 18:53:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726308AbhAWSxI (ORCPT ); Sat, 23 Jan 2021 13:53:08 -0500 Received: from mail.kernel.org ([198.145.29.99]:35290 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726198AbhAWSxE (ORCPT ); Sat, 23 Jan 2021 13:53:04 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 303932310A; Sat, 23 Jan 2021 18:52:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611427929; bh=lj5ly+kqPX3/icV0ZJlW+tlNZgyAPlY0iUkOkNPCU1A=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=YMYRZNJamIwTbLI9hYqQpbgkiXl0efRdkr/cMyIAmycVRRK0EFyECBm/vTuNkgLs4 Ov3g5hTRHygswnxOLGhzwg9RuXATG35C47bI9Gly7RH2863YJuwwoal+oeavAIUAuS 9x5JHXpob0+CMw6BrRxWVDxUBzU31yV3yMpkxWhOxezEUxY5dA0QJ3W07E3H9mroDd zoVkvAdml1aa267ZEs4JHW41M3vF7qQ+vxAMTw2aV4seRj/jKYgaat5/grOfOpc7vO 4O55FGzdMUTQcN0TDdBtvxPBwwAVCuQQxso5AAtPbV1FtIXOE6PN4mzjt3mWy44+Kk 1jbHEywIUC87g== Subject: [PATCH 02/11] 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 Date: Sat, 23 Jan 2021 10:52:10 -0800 Message-ID: <161142793080.2171939.11486862758521454210.stgit@magnolia> In-Reply-To: <161142791950.2171939.3320927557987463636.stgit@magnolia> References: <161142791950.2171939.3320927557987463636.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 Sat Jan 23 18:52:16 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: 12041799 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.2 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 53D1AC433E0 for ; Sat, 23 Jan 2021 18:53:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1F17F2313E for ; Sat, 23 Jan 2021 18:53:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726198AbhAWSxJ (ORCPT ); Sat, 23 Jan 2021 13:53:09 -0500 Received: from mail.kernel.org ([198.145.29.99]:35292 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726232AbhAWSxE (ORCPT ); Sat, 23 Jan 2021 13:53:04 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id B24A22312F; Sat, 23 Jan 2021 18:52:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611427934; bh=HkV+v1+M13RtbXFKFshv0TMII3eJb5vlu+TTekC5Bqc=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=cBIWP0vvpLFKZiHPegc9c3jyiJePft8ggnGB5hmnmXLTdTvvIl+0y7BZPPBniDa79 Cfgl2ULKXZhN3RD5/PM/d9JcnWqUmzwmLR5aBLOCwcyrNrXjtL7/aCH58LWNZ/x/89 DktnQuS10FwfI0Pnlo08ZhTwbZVve2WFAPy5cSDJF8/gQg3KhUqu/0tvw7vEf/tUBB Q5MY2ZvBaW7taHFqR8+sM2XsWAeZqDeBdStkdn2yv2qF0/07aievg4M7jrDgPz2mHa zV/2sidQFlFfM/PYoZy0oPj++OK7Rt9G8ilXYi8KZ/3vVtx9WTYedO1gVYCKWBhicT qKI34vgU+Tkog== Subject: [PATCH 03/11] xfs: xfs_inode_free_quota_blocks should scan project quota From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com Date: Sat, 23 Jan 2021 10:52:16 -0800 Message-ID: <161142793633.2171939.2299668448645740426.stgit@magnolia> In-Reply-To: <161142791950.2171939.3320927557987463636.stgit@magnolia> References: <161142791950.2171939.3320927557987463636.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 Sat Jan 23 18:52:21 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: 12041803 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.2 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 CB490C433E6 for ; Sat, 23 Jan 2021 18:53:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A1D8C2313E for ; Sat, 23 Jan 2021 18:53:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726268AbhAWSxS (ORCPT ); Sat, 23 Jan 2021 13:53:18 -0500 Received: from mail.kernel.org ([198.145.29.99]:35348 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726288AbhAWSxI (ORCPT ); Sat, 23 Jan 2021 13:53:08 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 40F5B2313E; Sat, 23 Jan 2021 18:52:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611427940; bh=TGf5itlRIBgei1WQVEfN6gqyNUbYcaiULoAE1qIbCis=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=FEXqzjdnBSaXtR9WWUf5AW/K+75ouReP6pLdi4UX8wAuO5LMw2ASw21sGiSte5AIP 6qMkHQjnXGWUTVCFU9kfiG91ho/waDeQkAOJg6zHoNcPcRSaF0fera/ZEXpl+t1Qfr LAWHvsecWECBgfDT+UihvOJtTdldvtneKaGyjy5BDrMqWFs3F9r+eususOXONBss1T uilqxTZ8yl6dPsXjLrCN+RK3T+/SeIMMNxIgWVuUE2RyDje6bEi3fUPx3sJE1+WqOa osiU0LyDDMzQJ031m8A9szzOXPPFMdzaMxzdiyiSIOam2t8WBGc9xmA4HAbYVgsAhg CJ2QpjCqlDGAQ== Subject: [PATCH 04/11] xfs: move and rename xfs_inode_free_quota_blocks to avoid conflicts From: "Darrick J. Wong" To: djwong@kernel.org Cc: Christoph Hellwig , linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com Date: Sat, 23 Jan 2021 10:52:21 -0800 Message-ID: <161142794187.2171939.6923227097082598204.stgit@magnolia> In-Reply-To: <161142791950.2171939.3320927557987463636.stgit@magnolia> References: <161142791950.2171939.3320927557987463636.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 Sat Jan 23 18:52:27 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: 12041801 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.2 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 E265BC433DB for ; Sat, 23 Jan 2021 18:53:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BB26123358 for ; Sat, 23 Jan 2021 18:53:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726288AbhAWSxS (ORCPT ); Sat, 23 Jan 2021 13:53:18 -0500 Received: from mail.kernel.org ([198.145.29.99]:35350 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726298AbhAWSxI (ORCPT ); Sat, 23 Jan 2021 13:53:08 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id C443C224DE; Sat, 23 Jan 2021 18:52:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611427945; bh=8uX6T3eVn0nrimK/vR+YaFj2VETD5VK3f+EVwQ0Q43M=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=RsgteMT21+0BYdNNUvQcOb1xO+hdg9VQHPcf+Vr+hrnNLMQQfq/4hjVaq1ARJYa0E AA8ox5NTScckYbrA0vgnYIJrRm4rZy7VhslcaTZFWFsBXxGbXrjc/F2BDVrLBvNpVq gP8I2nJHNlhdQUY0XUteXgrGxP5RxG7lA4M/7O4evNiuF8poKQlN/hOUEU1STbkTs8 aPhkBFwzhahTie1Ne5G75t669PpsvfrzmES8gHgjmOGOZ1d4MApP4FSwT85dN0b7vh +Wi/jRBdm5doFcFlcGtfTeMXo9ol/y4F2LqWxPCWlqovvtH4c9I8r2PoYZ/wb9iOqP addTqBfzJAUWw== Subject: [PATCH 05/11] xfs: pass flags and return gc errors from xfs_blockgc_free_quota From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com Date: Sat, 23 Jan 2021 10:52:27 -0800 Message-ID: <161142794741.2171939.10175775024910240954.stgit@magnolia> In-Reply-To: <161142791950.2171939.3320927557987463636.stgit@magnolia> References: <161142791950.2171939.3320927557987463636.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 | 7 +++---- fs/xfs/xfs_icache.c | 20 ++++++++++++-------- fs/xfs/xfs_icache.h | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index d69e5abcc1b4..57086838a676 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -747,10 +747,9 @@ xfs_file_buffered_write( */ 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..68b6f72593dc 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -1651,19 +1651,21 @@ xfs_start_block_reaping( * failure. We make a best effort by including each quota under low free space * conditions (less than 1% free space) in the scan. */ -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 + * Run a 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 | eof_flags; if (XFS_IS_UQUOTA_ENFORCED(ip->i_mount)) { dq = xfs_inode_dquot(ip, XFS_DQTYPE_USER); @@ -1693,9 +1695,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 Sat Jan 23 18:52:33 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: 12041819 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.2 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 B6064C433E0 for ; Sat, 23 Jan 2021 18:53:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7D4F922EBE for ; Sat, 23 Jan 2021 18:53:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726324AbhAWSxs (ORCPT ); Sat, 23 Jan 2021 13:53:48 -0500 Received: from mail.kernel.org ([198.145.29.99]:35494 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726298AbhAWSx2 (ORCPT ); Sat, 23 Jan 2021 13:53:28 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 4946822D2B; Sat, 23 Jan 2021 18:52:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611427951; bh=OgDyN8OaGFlJ/OXdm36/gXOI3XN0MYZxrZvevNJZ+L0=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=CfDAy0lZu202yRUO80P3Qp43eMxRSA4r60EnhqnEBjcmdkx1dO3Zzdmlfbe8gIh5C NSCQO8Waquwa0OPg6joZpxguFoSsFMZetP0mnBPcaQLYb4JsxZ9YJlPIOtYSuAnUbc nkFcE3gPTbPKgZ95UtD4eoA+GeT+Jd1NKT2T1VrmTD+VyYoPEh/24LgGmtrdrjwqAP D1SC/Y3zz+x+3bH2FUBTWAX32ZPA/1YuOADewPpWpJpdgkAOrLB7PCu0DWH3MRSt0U GfRNO7yNI7ZmehNGWQKFjIu9zu7QXtBz+QBVeqIXWetdJ+C3HPc1P9Ooh6avMLgDg/ icrxOpeWZpw2A== Subject: [PATCH 06/11] 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 Date: Sat, 23 Jan 2021 10:52:33 -0800 Message-ID: <161142795294.2171939.2305516748220731694.stgit@magnolia> In-Reply-To: <161142791950.2171939.3320927557987463636.stgit@magnolia> References: <161142791950.2171939.3320927557987463636.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/libxfs/xfs_attr.c | 8 +++++- fs/xfs/libxfs/xfs_bmap.c | 8 +++++- fs/xfs/xfs_bmap_util.c | 17 ++++++++++---- fs/xfs/xfs_iomap.c | 19 ++++++++++++--- fs/xfs/xfs_quota.h | 20 ++++++++++------ fs/xfs/xfs_reflink.c | 16 ++++++++++--- fs/xfs/xfs_trans_dquot.c | 57 ++++++++++++++++++++++++++++++++++++---------- 7 files changed, 108 insertions(+), 37 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index be51e7068dcd..af835ea0ca80 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -395,6 +395,7 @@ xfs_attr_set( struct xfs_mount *mp = dp->i_mount; struct xfs_trans_res tres; bool rsvd = (args->attr_filter & XFS_ATTR_ROOT); + bool quota_retry = false; int error, local; int rmt_blks = 0; unsigned int total; @@ -458,6 +459,7 @@ xfs_attr_set( * Root fork attributes can use reserved data blocks for this * operation if necessary */ +retry: error = xfs_trans_alloc(mp, &tres, total, 0, rsvd ? XFS_TRANS_RESERVE : 0, &args->trans); if (error) @@ -478,10 +480,12 @@ xfs_attr_set( if (rsvd) quota_flags |= XFS_QMOPT_FORCE_RES; - error = xfs_trans_reserve_quota_nblks(args->trans, dp, - args->total, 0, quota_flags); + error = xfs_trans_reserve_quota_nblks(&args->trans, dp, + args->total, 0, quota_flags, "a_retry); if (error) goto out_trans_cancel; + if (quota_retry) + goto retry; error = xfs_has_attr(args); if (error == -EEXIST && (args->attr_flags & XATTR_CREATE)) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 908b7d49da60..0247763dfac3 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -1070,6 +1070,7 @@ xfs_bmap_add_attrfork( int blks; /* space reservation */ int version = 1; /* superblock attr version */ int logflags; /* logging flags */ + bool quota_retry = false; int error; /* error return value */ ASSERT(XFS_IFORK_Q(ip) == 0); @@ -1079,17 +1080,20 @@ xfs_bmap_add_attrfork( blks = XFS_ADDAFORK_SPACE_RES(mp); +retry: error = xfs_trans_alloc(mp, &M_RES(mp)->tr_addafork, blks, 0, rsvd ? XFS_TRANS_RESERVE : 0, &tp); if (error) return error; xfs_ilock(ip, XFS_ILOCK_EXCL); - error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ? + error = xfs_trans_reserve_quota_nblks(&tp, ip, blks, 0, rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : - XFS_QMOPT_RES_REGBLKS); + XFS_QMOPT_RES_REGBLKS, "a_retry); if (error) goto trans_cancel; + if (quota_retry) + goto retry; if (XFS_IFORK_Q(ip)) goto trans_cancel; diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 792809debaaa..6eaf92bf8fc6 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -761,6 +761,7 @@ xfs_alloc_file_space( */ while (allocatesize_fsb && !error) { xfs_fileoff_t s, e; + bool quota_retry = false; /* * Determine space reservations for data/realtime. @@ -803,6 +804,7 @@ xfs_alloc_file_space( /* * Allocate and setup the transaction. */ +retry: error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, resrtextents, 0, &tp); @@ -817,10 +819,12 @@ xfs_alloc_file_space( break; } xfs_ilock(ip, XFS_ILOCK_EXCL); - error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks, - 0, quota_flag); + error = xfs_trans_reserve_quota_nblks(&tp, ip, qblocks, 0, + quota_flag, "a_retry); if (error) goto error1; + if (quota_retry) + goto retry; error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, XFS_IEXT_ADD_NOSPLIT_CNT); @@ -858,7 +862,6 @@ xfs_alloc_file_space( error0: /* unlock inode, unreserve quota blocks, cancel trans */ xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag); - error1: /* Just cancel transaction */ xfs_trans_cancel(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); @@ -875,8 +878,10 @@ xfs_unmap_extent( struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; uint resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); + bool quota_retry = false; int error; +retry: error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); if (error) { ASSERT(error == -ENOSPC || XFS_FORCED_SHUTDOWN(mp)); @@ -884,10 +889,12 @@ xfs_unmap_extent( } xfs_ilock(ip, XFS_ILOCK_EXCL); - error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, - XFS_QMOPT_RES_REGBLKS); + error = xfs_trans_reserve_quota_nblks(&tp, ip, resblks, 0, + XFS_QMOPT_RES_REGBLKS, "a_retry); if (error) goto out_trans_cancel; + if (quota_retry) + goto retry; xfs_trans_ijoin(tp, ip, 0); diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 514e6ae010e0..294d819c30c6 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -27,7 +27,7 @@ #include "xfs_dquot_item.h" #include "xfs_dquot.h" #include "xfs_reflink.h" - +#include "xfs_icache.h" #define XFS_ALLOC_ALIGN(mp, off) \ (((off) >> mp->m_allocsize_log) << mp->m_allocsize_log) @@ -197,6 +197,7 @@ xfs_iomap_write_direct( int quota_flag; uint qblocks, resblks; unsigned int resrtextents = 0; + bool quota_retry = false; int error; int bmapi_flags = XFS_BMAPI_PREALLOC; uint tflags = 0; @@ -239,6 +240,7 @@ xfs_iomap_write_direct( resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1; } } +retry: error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, resrtextents, tflags, &tp); if (error) @@ -246,9 +248,12 @@ xfs_iomap_write_direct( xfs_ilock(ip, XFS_ILOCK_EXCL); - error = xfs_trans_reserve_quota_nblks(tp, ip, qblocks, 0, quota_flag); + error = xfs_trans_reserve_quota_nblks(&tp, ip, qblocks, 0, quota_flag, + "a_retry); if (error) goto out_trans_cancel; + if (quota_retry) + goto retry; error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, XFS_IEXT_ADD_NOSPLIT_CNT); @@ -544,6 +549,8 @@ xfs_iomap_write_unwritten( return error; do { + bool quota_retry = false; + /* * Set up a transaction to convert the range of extents * from unwritten to real. Do allocations in a loop until @@ -553,6 +560,7 @@ xfs_iomap_write_unwritten( * here as we might be asked to write out the same inode that we * complete here and might deadlock on the iolock. */ +retry: error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, XFS_TRANS_RESERVE, &tp); if (error) @@ -561,10 +569,13 @@ xfs_iomap_write_unwritten( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); - error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, - XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES); + error = xfs_trans_reserve_quota_nblks(&tp, ip, resblks, 0, + XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES, + "a_retry); if (error) goto error_on_bmapi_transaction; + if (quota_retry) + goto retry; error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, XFS_IEXT_WRITE_UNWRITTEN_CNT); diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 16a2e7adf4da..1c083b5267d9 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -81,8 +81,9 @@ extern void xfs_trans_mod_dquot_byino(struct xfs_trans *, struct xfs_inode *, uint, int64_t); extern void xfs_trans_apply_dquot_deltas(struct xfs_trans *); extern void xfs_trans_unreserve_and_mod_dquots(struct xfs_trans *); -extern int xfs_trans_reserve_quota_nblks(struct xfs_trans *, - struct xfs_inode *, int64_t, long, uint); +int xfs_trans_reserve_quota_nblks(struct xfs_trans **tpp, struct xfs_inode *ip, + int64_t nblocks, long ninos, unsigned int flags, + bool *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,8 +115,11 @@ extern void xfs_qm_unmount_quotas(struct xfs_mount *); static inline int xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t nblks, bool isrt) { - return xfs_trans_reserve_quota_nblks(NULL, ip, nblks, 0, - isrt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); + struct xfs_trans *tp = NULL; + + return xfs_trans_reserve_quota_nblks(&tp, ip, nblks, 0, + isrt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS, + NULL); } #else static inline int @@ -133,8 +137,9 @@ xfs_qm_vop_dqalloc(struct xfs_inode *ip, kuid_t kuid, kgid_t kgid, #define xfs_trans_mod_dquot_byino(tp, ip, fields, delta) #define xfs_trans_apply_dquot_deltas(tp) #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 nblks, long ninos, uint flags) +static inline int xfs_trans_reserve_quota_nblks(struct xfs_trans **tpp, + struct xfs_inode *ip, int64_t nblks, long ninos, + unsigned int flags, bool *retry) { return 0; } @@ -179,7 +184,8 @@ static inline int xfs_trans_unreserve_quota_nblks(struct xfs_trans *tp, struct xfs_inode *ip, int64_t nblks, long ninos, unsigned int flags) { - return xfs_trans_reserve_quota_nblks(tp, ip, -nblks, -ninos, flags); + return xfs_trans_reserve_quota_nblks(&tp, ip, -nblks, -ninos, flags, + NULL); } static inline int diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 0da1a603b7d8..0afd74f35ab7 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -355,6 +355,7 @@ xfs_reflink_allocate_cow( xfs_filblks_t count_fsb = imap->br_blockcount; struct xfs_trans *tp; int nimaps, error = 0; + bool quota_retry = false; bool found; xfs_filblks_t resaligned; xfs_extlen_t resblks = 0; @@ -376,6 +377,7 @@ xfs_reflink_allocate_cow( resblks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned); xfs_iunlock(ip, *lockmode); +retry: error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); *lockmode = XFS_ILOCK_EXCL; xfs_ilock(ip, *lockmode); @@ -398,10 +400,12 @@ xfs_reflink_allocate_cow( goto convert; } - error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, - XFS_QMOPT_RES_REGBLKS); + error = xfs_trans_reserve_quota_nblks(&tp, ip, resblks, 0, + XFS_QMOPT_RES_REGBLKS, "a_retry); if (error) goto out_trans_cancel; + if (quota_retry) + goto retry; xfs_trans_ijoin(tp, ip, 0); @@ -1006,10 +1010,12 @@ xfs_reflink_remap_extent( unsigned int resblks; bool smap_real; bool dmap_written = xfs_bmap_is_written_extent(dmap); + bool quota_retry = false; int iext_delta = 0; int nimaps; int error; +retry: /* Start a rolling transaction to switch the mappings */ resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); @@ -1094,10 +1100,12 @@ xfs_reflink_remap_extent( if (!smap_real && dmap_written) qres += dmap->br_blockcount; if (qres > 0) { - error = xfs_trans_reserve_quota_nblks(tp, ip, qres, 0, - XFS_QMOPT_RES_REGBLKS); + error = xfs_trans_reserve_quota_nblks(&tp, ip, qres, 0, + XFS_QMOPT_RES_REGBLKS, "a_retry); if (error) goto out_cancel; + if (quota_retry) + goto retry; } if (smap_real) diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c index 3315498a6fa1..adc7331ff182 100644 --- a/fs/xfs/xfs_trans_dquot.c +++ b/fs/xfs/xfs_trans_dquot.c @@ -16,6 +16,7 @@ #include "xfs_quota.h" #include "xfs_qm.h" #include "xfs_trace.h" +#include "xfs_icache.h" STATIC void xfs_trans_alloc_dqinfo(xfs_trans_t *); @@ -770,21 +771,38 @@ xfs_trans_reserve_quota_bydquots( return error; } - /* - * 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 false 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 false), this function will try to invoke + * the speculative preallocation gc scanner to reduce quota usage. In order to + * do that, we cancel the transaction, NULL out tpp, drop the ILOCK, and set + * *retry to true. + * + * This function ends one of two ways: + * + * 1) To signal the caller to try again, *retry is set to true; *tpp is + * cancelled and set to NULL; the inode is unlocked; and the return value + * is zero. + * + * 2) Otherwise, *tpp is still set; the inode is still locked; and the return + * value is zero or the usual negative error code. */ int xfs_trans_reserve_quota_nblks( - struct xfs_trans *tp, + struct xfs_trans **tpp, struct xfs_inode *ip, int64_t nblks, long ninos, - uint flags) + unsigned int flags, + bool *retry) { struct xfs_mount *mp = ip->i_mount; + int error; if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp)) return 0; @@ -795,13 +813,26 @@ xfs_trans_reserve_quota_nblks( ASSERT((flags & ~(XFS_QMOPT_FORCE_RES)) == XFS_TRANS_DQ_RES_RTBLKS || (flags & ~(XFS_QMOPT_FORCE_RES)) == XFS_TRANS_DQ_RES_BLKS); - /* - * Reserve nblks against these dquots, with trans as the mediator. - */ - return xfs_trans_reserve_quota_bydquots(tp, mp, - ip->i_udquot, ip->i_gdquot, - ip->i_pdquot, - nblks, ninos, flags); + /* Reserve nblks against these dquots, with trans as the mediator. */ + error = xfs_trans_reserve_quota_bydquots(*tpp, mp, ip->i_udquot, + ip->i_gdquot, ip->i_pdquot, nblks, ninos, flags); + if (retry == NULL) + return error; + /* We only allow one retry for EDQUOT/ENOSPC. */ + if (*retry || (error != -EDQUOT && error != -ENOSPC)) { + *retry = false; + return error; + } + + /* Release resources, prepare for scan. */ + xfs_trans_cancel(*tpp); + *tpp = NULL; + xfs_iunlock(ip, XFS_ILOCK_EXCL); + + /* Try to free some quota for this file's dquots. */ + *retry = true; + xfs_blockgc_free_quota(ip, 0); + return 0; } /* Change the quota reservations for an inode creation activity. */ From patchwork Sat Jan 23 18:52:38 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: 12041815 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.2 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 240ABC433E6 for ; Sat, 23 Jan 2021 18:53:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D1DD022D57 for ; Sat, 23 Jan 2021 18:53:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726356AbhAWSxp (ORCPT ); Sat, 23 Jan 2021 13:53:45 -0500 Received: from mail.kernel.org ([198.145.29.99]:35496 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726322AbhAWSx2 (ORCPT ); Sat, 23 Jan 2021 13:53:28 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id CC91622D50; Sat, 23 Jan 2021 18:52:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611427956; bh=r6bXUGmLicXUaNpeuRMboTO+HJyN2ZgQ6qaAcoX50Wo=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=DeXwPyyEXmNHpxsCaOmeAnIZcJiuvwhDKi+P59dlfmyZDswpme2Jc/ElSPzjgdDoM 6FOBeYSaVlrIOBjXXEsj5rVBrxAivGwB1qqoSyDuhvMYcvCJnwKkczfWTEOlKo2N+G 8xx4/XirV+WxNAyMqGWCnA5QCRiPLE2wk4ukDWA15Eb+IEfSI8JbNmWtf24USDKSKh zh0O05lJtYzkIp8axuXQtWttD6Hps6BA8m6Fnr7zoEYXopaxxaZXnsbWY8yb+YheDE 98xCBCSiNEuzNQmBmVI/BAG5bJx5RPKNWDQuJBJ0oCPZ2HsEGnBF4FJ1yX7+pglk8B Fy3yqJGUiD++g== Subject: [PATCH 07/11] 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 Date: Sat, 23 Jan 2021 10:52:38 -0800 Message-ID: <161142795846.2171939.1839413303968531400.stgit@magnolia> In-Reply-To: <161142791950.2171939.3320927557987463636.stgit@magnolia> References: <161142791950.2171939.3320927557987463636.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 | 78 ++++++++++++++++++++++++++++------------------ fs/xfs/xfs_icache.h | 2 + fs/xfs/xfs_inode.c | 17 ++++++++-- fs/xfs/xfs_quota.h | 13 ++++---- fs/xfs/xfs_symlink.c | 8 ++++- fs/xfs/xfs_trans_dquot.c | 52 ++++++++++++++++++++++++++++--- 6 files changed, 124 insertions(+), 46 deletions(-) diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 68b6f72593dc..7f999f9dd80a 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -1646,60 +1646,78 @@ 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. */ 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 increase effectiveness and use 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 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. + */ +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_inode.c b/fs/xfs/xfs_inode.c index e909da05cd28..a3072c3f5028 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -990,6 +990,7 @@ xfs_create( struct xfs_dquot *gdqp = NULL; struct xfs_dquot *pdqp = NULL; struct xfs_trans_res *tres; + bool quota_retry = false; uint resblks; trace_xfs_create(dp, name); @@ -1022,6 +1023,7 @@ xfs_create( * the case we'll drop the one we have and get a more * appropriate transaction later. */ +retry: error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp); if (error == -ENOSPC) { /* flush outstanding delalloc blocks and retry */ @@ -1037,10 +1039,12 @@ xfs_create( /* * Reserve disk quota and the inode. */ - error = xfs_trans_reserve_quota_icreate(tp, dp, udqp, gdqp, pdqp, - resblks); + error = xfs_trans_reserve_quota_icreate(&tp, dp, &unlock_dp_on_error, + udqp, gdqp, pdqp, resblks, "a_retry); if (error) goto out_trans_cancel; + if (quota_retry) + goto retry; error = xfs_iext_count_may_overflow(dp, XFS_DATA_FORK, XFS_IEXT_DIR_MANIP_CNT(mp)); @@ -1146,6 +1150,8 @@ xfs_create_tmpfile( struct xfs_dquot *gdqp = NULL; struct xfs_dquot *pdqp = NULL; struct xfs_trans_res *tres; + bool locked = false; + bool quota_retry = false; uint resblks; if (XFS_FORCED_SHUTDOWN(mp)) @@ -1165,14 +1171,17 @@ xfs_create_tmpfile( resblks = XFS_IALLOC_SPACE_RES(mp); tres = &M_RES(mp)->tr_create_tmpfile; +retry: error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp); if (error) goto out_release_inode; - error = xfs_trans_reserve_quota_icreate(tp, dp, udqp, gdqp, pdqp, - resblks); + error = xfs_trans_reserve_quota_icreate(&tp, dp, &locked, udqp, gdqp, + pdqp, resblks, "a_retry); if (error) goto out_trans_cancel; + if (quota_retry) + goto retry; error = xfs_dir_ialloc(&tp, dp, mode, 0, 0, prid, &ip); if (error) diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 1c083b5267d9..c4d02252e36f 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -87,9 +87,10 @@ int xfs_trans_reserve_quota_nblks(struct xfs_trans **tpp, struct xfs_inode *ip, 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); -int xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_inode *dp, - struct xfs_dquot *udqp, struct xfs_dquot *gdqp, - struct xfs_dquot *pdqp, int64_t nblks); +int xfs_trans_reserve_quota_icreate(struct xfs_trans **tpp, + struct xfs_inode *dp, bool *dp_locked, struct xfs_dquot *udqp, + struct xfs_dquot *gdqp, struct xfs_dquot *pdqp, int64_t nblks, + bool *retry); extern int xfs_qm_vop_dqalloc(struct xfs_inode *, kuid_t, kgid_t, prid_t, uint, struct xfs_dquot **, struct xfs_dquot **, @@ -158,9 +159,9 @@ xfs_quota_reserve_blkres(struct xfs_inode *ip, int64_t nblks, bool isrt) } static inline int -xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_inode *dp, - struct xfs_dquot *udqp, struct xfs_dquot *gdqp, - struct xfs_dquot *pdqp, int64_t nblks) +xfs_trans_reserve_quota_icreate(struct xfs_trans **tpp, struct xfs_inode *dp, + bool *dp_locked, struct xfs_dquot *udqp, struct xfs_dquot *gdqp, + struct xfs_dquot *pdqp, int64_t nblks, bool *retry) { return 0; } diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index f8bfa51bdeef..20c150ad699f 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -159,6 +159,7 @@ xfs_symlink( struct xfs_dquot *udqp = NULL; struct xfs_dquot *gdqp = NULL; struct xfs_dquot *pdqp = NULL; + bool quota_retry = false; uint resblks; *ipp = NULL; @@ -197,6 +198,7 @@ xfs_symlink( fs_blocks = xfs_symlink_blocks(mp, pathlen); resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks); +retry: error = xfs_trans_alloc(mp, &M_RES(mp)->tr_symlink, resblks, 0, 0, &tp); if (error) goto out_release_inode; @@ -215,10 +217,12 @@ xfs_symlink( /* * Reserve disk quota : blocks and inode. */ - error = xfs_trans_reserve_quota_icreate(tp, dp, udqp, gdqp, pdqp, - resblks); + error = xfs_trans_reserve_quota_icreate(&tp, dp, &unlock_dp_on_error, + udqp, gdqp, pdqp, resblks, "a_retry); if (error) goto out_trans_cancel; + if (quota_retry) + goto retry; error = xfs_iext_count_may_overflow(dp, XFS_DATA_FORK, XFS_IEXT_DIR_MANIP_CNT(mp)); diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c index adc7331ff182..340c066f8ef1 100644 --- a/fs/xfs/xfs_trans_dquot.c +++ b/fs/xfs/xfs_trans_dquot.c @@ -835,25 +835,69 @@ 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. The caller may hold + * ILOCK_EXCL on the inode. If @retry is not a NULL pointer, the caller must + * ensure that *retry is set to false 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 false), this function will try to invoke + * the speculative preallocation gc scanner to reduce quota usage. In order to + * do that, we cancel the transaction, NULL out tpp, drop the ILOCK and update + * *dp_locked if dp_locked is not NULL, and set *retry to true. + * + * This function ends one of two ways: + * + * 1) To signal the caller to try again, *retry is set to true; *tpp is + * cancelled and set to NULL; if *dp_locked is true, the inode is unlocked + * and *dp_locked is set to false; and the return value is zero. + * + * 2) Otherwise, *tpp is still set; the inode is still locked; and the return + * value is zero or the usual negative error code. + */ int xfs_trans_reserve_quota_icreate( - struct xfs_trans *tp, + struct xfs_trans **tpp, struct xfs_inode *dp, + bool *dp_locked, struct xfs_dquot *udqp, struct xfs_dquot *gdqp, struct xfs_dquot *pdqp, - int64_t nblks) + int64_t nblks, + bool *retry) { struct xfs_mount *mp = dp->i_mount; + int error; if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp)) return 0; ASSERT(!xfs_is_quota_inode(&mp->m_sb, dp->i_ino)); - return xfs_trans_reserve_quota_bydquots(tp, dp->i_mount, udqp, gdqp, + error = xfs_trans_reserve_quota_bydquots(*tpp, dp->i_mount, udqp, gdqp, pdqp, nblks, 1, XFS_QMOPT_RES_REGBLKS); + if (retry == NULL) + return error; + /* We only allow one retry for EDQUOT/ENOSPC. */ + if (*retry || (error != -EDQUOT && error != -ENOSPC)) { + *retry = false; + return error; + } + + /* Release resources, prepare for scan. */ + xfs_trans_cancel(*tpp); + *tpp = NULL; + if (*dp_locked) { + xfs_iunlock(dp, XFS_ILOCK_EXCL); + *dp_locked = false; + } + + /* Try to free some quota for the supplied dquots. */ + *retry = true; + xfs_blockgc_free_dquots(udqp, gdqp, pdqp, 0); + return 0; } /* From patchwork Sat Jan 23 18:52:44 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: 12041817 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.2 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 89C84C433E9 for ; Sat, 23 Jan 2021 18:53:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5E11422EBE for ; Sat, 23 Jan 2021 18:53:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726315AbhAWSxr (ORCPT ); Sat, 23 Jan 2021 13:53:47 -0500 Received: from mail.kernel.org ([198.145.29.99]:35498 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726324AbhAWSx2 (ORCPT ); Sat, 23 Jan 2021 13:53:28 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 61C6023159; Sat, 23 Jan 2021 18:52:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611427962; bh=wb/gijJacXZUBU83NHvEtkoWx4yWCoaWNsn84sDOmGA=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=ttoi15NUY8Ak2Nq11O9O+rX5fQ48u44q3J8Na8FbN1PTSEOrgFPR3hegYU/VQ0Uh5 SzLw+5AroFUdGTE7+9C7jr5W36NE3wWhRBfP7tSdJs8sNu1qyPDlrwAIbDEj80SK0M 3N6Slej+S7b5PeNJxaSvwH2qd3eSLJyi97GmAf9/Cx0AVhC9C7YljsTSnAH3eH+UW4 UV2oKZETIqU1z78mqWisehsIY8N9X2zbZLjq7FbFgJ0Cirw6qXzifBeFlQzzsaTA8Z skVI6TEXdIdRmkPy8LueNVxX7LaXUyh/MobM4a1Ri23rApJe+9qkZDrOMfHXe657Bo 3Cl48phtR4ZWA== Subject: [PATCH 08/11] 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 Date: Sat, 23 Jan 2021 10:52:44 -0800 Message-ID: <161142796398.2171939.8342732885181707528.stgit@magnolia> In-Reply-To: <161142791950.2171939.3320927557987463636.stgit@magnolia> References: <161142791950.2171939.3320927557987463636.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. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_ioctl.c | 12 ++++++++++-- fs/xfs/xfs_iops.c | 13 ++++++++++--- fs/xfs/xfs_qm.c | 34 ++++++++++++++++++++++++++-------- fs/xfs/xfs_quota.h | 8 ++++---- 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 3fbd98f61ea5..952eca338807 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; + bool quota_retry = false; 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); @@ -1470,10 +1472,16 @@ xfs_ioctl_setattr( if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp) && ip->i_d.di_projid != fa->fsx_projid) { - code = xfs_qm_vop_chown_reserve(tp, ip, NULL, NULL, pdqp, - capable(CAP_FOWNER) ? XFS_QMOPT_FORCE_RES : 0); + unsigned int flags = 0; + + if (capable(CAP_FOWNER)) + flags |= XFS_QMOPT_FORCE_RES; + code = xfs_qm_vop_chown_reserve(&tp, ip, NULL, NULL, pdqp, + flags, "a_retry); if (code) /* out of quota */ goto error_trans_cancel; + if (quota_retry) + goto retry; } xfs_fill_fsxattr(ip, false, &old_fa); diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index f1e21b6cfa48..d43c2b008be8 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; + bool quota_retry = false; 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; @@ -729,12 +731,17 @@ xfs_setattr_nonsize( if (XFS_IS_QUOTA_RUNNING(mp) && ((XFS_IS_UQUOTA_ON(mp) && !uid_eq(iuid, uid)) || (XFS_IS_GQUOTA_ON(mp) && !gid_eq(igid, gid)))) { + unsigned int flags = 0; + + if (capable(CAP_FOWNER)) + flags |= XFS_QMOPT_FORCE_RES; ASSERT(tp); - error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, - NULL, capable(CAP_FOWNER) ? - XFS_QMOPT_FORCE_RES : 0); + error = xfs_qm_vop_chown_reserve(&tp, ip, udqp, gdqp, + NULL, flags, "a_retry); if (error) /* out of quota */ goto out_cancel; + if (quota_retry) + goto retry; } /* diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index c134eb4aeaa8..3b481f69a913 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -1795,24 +1795,26 @@ xfs_qm_vop_chown( } /* - * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID). + * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID). This function has + * the same return behavior as xfs_trans_reserve_quota_nblks. */ int xfs_qm_vop_chown_reserve( - struct xfs_trans *tp, + struct xfs_trans **tpp, struct xfs_inode *ip, struct xfs_dquot *udqp, struct xfs_dquot *gdqp, struct xfs_dquot *pdqp, - uint flags) + unsigned int flags, + bool *retry) { struct xfs_mount *mp = ip->i_mount; uint64_t delblks; unsigned int blkflags; - struct xfs_dquot *udq_unres = NULL; + struct xfs_dquot *udq_unres = NULL; /* old dquots */ struct xfs_dquot *gdq_unres = NULL; struct xfs_dquot *pdq_unres = NULL; - struct xfs_dquot *udq_delblks = NULL; + struct xfs_dquot *udq_delblks = NULL; /* new dquots */ struct xfs_dquot *gdq_delblks = NULL; struct xfs_dquot *pdq_delblks = NULL; int error; @@ -1856,11 +1858,11 @@ xfs_qm_vop_chown_reserve( } } - error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, + error = xfs_trans_reserve_quota_bydquots(*tpp, ip->i_mount, udq_delblks, gdq_delblks, pdq_delblks, ip->i_d.di_nblocks, 1, flags | blkflags); if (error) - return error; + goto err; /* * Do the delayed blks reservations/unreservations now. Since, these @@ -1878,12 +1880,28 @@ xfs_qm_vop_chown_reserve( udq_delblks, gdq_delblks, pdq_delblks, (xfs_qcnt_t)delblks, 0, flags | blkflags); 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, blkflags); } + return 0; +err: + /* We only allow one retry for EDQUOT/ENOSPC. */ + if (*retry || (error != -EDQUOT && error != -ENOSPC)) { + *retry = false; + return error; + } + + /* Release resources, prepare for scan. */ + xfs_trans_cancel(*tpp); + *tpp = NULL; + xfs_iunlock(ip, XFS_ILOCK_EXCL); + + /* Try to free some quota in the new dquots. */ + *retry = true; + xfs_blockgc_free_dquots(udq_delblks, gdq_delblks, pdq_delblks, 0); return 0; } diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index c4d02252e36f..ce65f6ac57a9 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -100,9 +100,9 @@ extern void xfs_qm_vop_create_dqattach(struct xfs_trans *, struct xfs_inode *, extern int xfs_qm_vop_rename_dqattach(struct xfs_inode **); extern struct xfs_dquot *xfs_qm_vop_chown(struct xfs_trans *, struct xfs_inode *, struct xfs_dquot **, struct xfs_dquot *); -extern int xfs_qm_vop_chown_reserve(struct xfs_trans *, struct xfs_inode *, - struct xfs_dquot *, struct xfs_dquot *, - struct xfs_dquot *, uint); +int xfs_qm_vop_chown_reserve(struct xfs_trans **tpp, struct xfs_inode *ip, + struct xfs_dquot *udqp, struct xfs_dquot *gdqp, + struct xfs_dquot *pdqp, unsigned int flags, bool *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 *); @@ -169,7 +169,7 @@ xfs_trans_reserve_quota_icreate(struct xfs_trans **tpp, struct xfs_inode *dp, #define xfs_qm_vop_create_dqattach(tp, ip, u, g, p) #define xfs_qm_vop_rename_dqattach(it) (0) #define xfs_qm_vop_chown(tp, ip, old, new) (NULL) -#define xfs_qm_vop_chown_reserve(tp, ip, u, g, p, fl) (0) +#define xfs_qm_vop_chown_reserve(tpp, ip, u, g, p, fl, retry) (0) #define xfs_qm_dqattach(ip) (0) #define xfs_qm_dqattach_locked(ip, fl) (0) #define xfs_qm_dqdetach(ip) From patchwork Sat Jan 23 18:52:49 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: 12041809 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.4 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 73317C433E6 for ; Sat, 23 Jan 2021 18:53:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4899A22D57 for ; Sat, 23 Jan 2021 18:53:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726232AbhAWSxi (ORCPT ); Sat, 23 Jan 2021 13:53:38 -0500 Received: from mail.kernel.org ([198.145.29.99]:35512 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726315AbhAWSxa (ORCPT ); Sat, 23 Jan 2021 13:53:30 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id E7D4622D57; Sat, 23 Jan 2021 18:52:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611427968; bh=EfoxJg0PLIHVAdCt5QHuZeGuq37WQSQ53hfcypS3fU4=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=E4Lz3JETleSNTp3xskUMy0BlPo3M6qZ8527Jzbngn+nAe6hXZmAza3eWyN3gpm+Ph TcSXn35ibygKOH6m/0WljYPXk8hN8JNaDDrxbSR8wajb6EFUiig1xsqobIgE/JzH0V 4BV/28uUnnp/Rfd249Yg6orRdfIxomOVx8l5K4HNXAYI3KGtm7YYe4WOr6aqMiuZMl IDu1sDreIBOeg3RtTpUWrmfmGGvxrRjdnvKm11q9E+8yqyqUpI5670CrvJCO6OYDvC FLgdtQ8e2EAcKCswLVw/4i7xoikw2TGPfuHZ+nGahYM2xED79D59tEWv9x72BBn4Gu OYNIRT4bQ8CYw== Subject: [PATCH 09/11] 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 Date: Sat, 23 Jan 2021 10:52:49 -0800 Message-ID: <161142796954.2171939.15250362023143903757.stgit@magnolia> In-Reply-To: <161142791950.2171939.3320927557987463636.stgit@magnolia> References: <161142791950.2171939.3320927557987463636.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 Reviewed-by: Brian Foster --- fs/xfs/xfs_ioctl.c | 2 ++ fs/xfs/xfs_trace.c | 1 + fs/xfs/xfs_trace.h | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 952eca338807..da407934364c 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..4cbf446bae9a 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,44 @@ 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->eof_flags; + __entry->uid = from_kuid(mp->m_super->s_user_ns, eofb->eof_uid); + __entry->gid = from_kgid(mp->m_super->s_user_ns, eofb->eof_gid); + __entry->prid = eofb->eof_prid; + __entry->min_file_size = eofb->eof_min_file_size; + __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 Sat Jan 23 18:52:55 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: 12041805 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.2 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 A01A7C433E9 for ; Sat, 23 Jan 2021 18:53:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 665042313E for ; Sat, 23 Jan 2021 18:53:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726291AbhAWSxT (ORCPT ); Sat, 23 Jan 2021 13:53:19 -0500 Received: from mail.kernel.org ([198.145.29.99]:35256 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726232AbhAWSxM (ORCPT ); Sat, 23 Jan 2021 13:53:12 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 8009122DBF; Sat, 23 Jan 2021 18:52:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611427973; bh=4I9YvxI6NwO7tm4WxT8v3pPRkckY9yYDphLA/GpSjLs=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=MIihBoSFPwuKDDxqunELfqnIlWR84Km5lkVL/p266s8iUgn6HrDNylnNZCyutgmtd wiKPlVNnczqysWe3vDgSC9/qbfQOagqShyt1xf86pgwDit9/gc0VPUZ3lSYqZ0enBc V69wpyiCJAa/KUbubDTjOwHt5gGwfZPZHYtwEKoMqiFWZ7bsnxIwom1uCe5EAamrb4 tHNNowP7dQQh4rflaS22OAGRcYPxdigeA7n2hCKP2BqyC9p8rlzedshNEVm5telUe8 6vTE1Lf2MK+dg2gHEG8vZgbCWXNy7eVC9Hu/OmQj8QKOu1PixUkRwle1hyxJsV9zEK k/lZo0JdDG7dQ== Subject: [PATCH 10/11] xfs: refactor xfs_icache_free_{eof,cow}blocks call sites From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com Date: Sat, 23 Jan 2021 10:52:55 -0800 Message-ID: <161142797509.2171939.4924852652653930954.stgit@magnolia> In-Reply-To: <161142791950.2171939.3320927557987463636.stgit@magnolia> References: <161142791950.2171939.3320927557987463636.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 57086838a676..a766ad4477c5 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -758,8 +758,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 7f999f9dd80a..0d228a5e879f 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 @@ -1661,7 +1693,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; @@ -1699,11 +1730,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); } /* 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 4cbf446bae9a..c3fd344aaf5b 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -3926,6 +3926,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 Sat Jan 23 18:53:00 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: 12041813 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.2 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 781FFC433DB for ; Sat, 23 Jan 2021 18:53:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3F5A622EBE for ; Sat, 23 Jan 2021 18:53:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726322AbhAWSxq (ORCPT ); Sat, 23 Jan 2021 13:53:46 -0500 Received: from mail.kernel.org ([198.145.29.99]:35602 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726339AbhAWSxj (ORCPT ); Sat, 23 Jan 2021 13:53:39 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 1058922EBE; Sat, 23 Jan 2021 18:52:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611427979; bh=EsVW9I/Z1RASz1E0NSCfC62YI+ixBZ0eYhG9lFyw2T8=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=rLm9l+Q2yRD6Cx6u3EtyQgsaeuIPhJuhUXiaVbDUIOuMDkbRPlBxEgzxmWje5YPLc meF50tEWKiQ5vmH3b9R3FwUbdf/F2ELFwNQTNHNW0jDxgy56pdBWq7SScRDT2njyeI bUwNICapcepwTr6mbr/owYsZcPh4JFl+hfpUZ5G8xhRTwSZUxRLDkpgRYTe6ddliHy vAr3hc6LT7/bFYfXvokDHOCqU2WGvSt7YZIdhUdNyJIDw0zbYxXn1TrvFO21HhIZ/f lPSV96sLCymqowNazYKNXz7WxcM9BSkJL7B3AxOGTTdYZMv9JNgnLg2T/bQNUU14NT z3QIzaa8RQ6FA== Subject: [PATCH 11/11] xfs: flush speculative space allocations when we run out of space From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@infradead.org, david@fromorbit.com Date: Sat, 23 Jan 2021 10:53:00 -0800 Message-ID: <161142798066.2171939.9311024588681972086.stgit@magnolia> In-Reply-To: <161142791950.2171939.3320927557987463636.stgit@magnolia> References: <161142791950.2171939.3320927557987463636.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 --- fs/xfs/xfs_trans.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index e72730f85af1..2b92a4084bb8 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -20,6 +20,8 @@ #include "xfs_trace.h" #include "xfs_error.h" #include "xfs_defer.h" +#include "xfs_inode.h" +#include "xfs_icache.h" kmem_zone_t *xfs_trans_zone; @@ -256,8 +258,10 @@ xfs_trans_alloc( struct xfs_trans **tpp) { struct xfs_trans *tp; + unsigned int tries = 1; int error; +retry: /* * Allocate the handle before we do our freeze accounting and setting up * GFP_NOFS allocation context so that we avoid lockdep false positives @@ -285,6 +289,22 @@ xfs_trans_alloc( tp->t_firstblock = NULLFSBLOCK; error = xfs_trans_reserve(tp, resp, blocks, rtextents); + if (error == -ENOSPC && tries > 0) { + xfs_trans_cancel(tp); + + /* + * 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; + + tries--; + goto retry; + } if (error) { xfs_trans_cancel(tp); return error;