linux-xfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: djwong@kernel.org
Cc: linux-xfs@vger.kernel.org
Subject: [PATCH 6/6] xfs: flush speculative space allocations when we run out of space
Date: Mon, 11 Jan 2021 15:23:11 -0800	[thread overview]
Message-ID: <161040739114.1582114.73792904328533145.stgit@magnolia> (raw)
In-Reply-To: <161040735389.1582114.15084485390769234805.stgit@magnolia>

From: Darrick J. Wong <djwong@kernel.org>

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 <djwong@kernel.org>
---
 fs/xfs/xfs_bmap_util.c |   13 ++++++++++++-
 fs/xfs/xfs_file.c      |   11 ++++-------
 fs/xfs/xfs_icache.c    |   37 ++++++++++++++++++++++++++++++++++---
 fs/xfs/xfs_icache.h    |    1 +
 fs/xfs/xfs_inode.c     |   12 ++++++++++--
 fs/xfs/xfs_iomap.c     |   13 +++++++++++++
 fs/xfs/xfs_reflink.c   |   23 +++++++++++++++++++++++
 fs/xfs/xfs_trace.h     |    1 +
 8 files changed, 98 insertions(+), 13 deletions(-)


diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 437fdc8a8fbd..602011f06fb6 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -807,7 +807,18 @@ xfs_alloc_file_space(
 retry:
 		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks,
 				resrtextents, 0, &tp);
-
+		/*
+		 * We weren't able to reserve enough space to handle fallocate.
+		 * Flush any disk space that was being held in the hopes of
+		 * speeding up the filesystem.  We hold the IOLOCK so we cannot
+		 * do a synchronous scan.
+		 */
+		if (error == -ENOSPC && !cleared_space) {
+			cleared_space = true;
+			error = xfs_inode_free_blocks(ip->i_mount, false);
+			if (!error)
+				goto retry;
+		}
 		/*
 		 * Check for running out of space
 		 */
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 136fb5972acd..1333c65dd2b5 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -691,15 +691,12 @@ xfs_file_buffered_aio_write(
 			goto write_retry;
 		iolock = 0;
 	} else if (ret == -ENOSPC && !cleared_space) {
-		struct xfs_eofblocks eofb = {0};
-
-		cleared_space = true;
 		xfs_flush_inodes(ip->i_mount);
-
 		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);
+		cleared_space = true;
+		ret = xfs_inode_free_blocks(ip->i_mount, true);
+		if (ret)
+			return ret;
 		goto write_retry;
 	}
 
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index d6f7c3e85805..c3867b25e362 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -950,6 +950,21 @@ xfs_queue_eofblocks(
 	rcu_read_unlock();
 }
 
+/* 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 && error != -EAGAIN)
+		return error;
+
+	return xfs_icache_free_cowblocks(mp, eofb);
+}
+
 void
 xfs_eofblocks_worker(
 	struct work_struct *work)
@@ -1470,9 +1485,25 @@ xfs_inode_free_quota_blocks(
 
 	trace_xfs_inode_free_quota_blocks(ip->i_mount, &eofb, _RET_IP_);
 
-	xfs_icache_free_eofblocks(ip->i_mount, &eofb);
-	xfs_icache_free_cowblocks(ip->i_mount, &eofb);
-	return true;
+	return xfs_blockgc_scan(ip->i_mount, &eofb) == 0;
+}
+
+/*
+ * Try to free space in the filesystem by purging eofblocks and cowblocks.
+ */
+int
+xfs_inode_free_blocks(
+	struct xfs_mount	*mp,
+	bool			sync)
+{
+	struct xfs_eofblocks	eofb = {0};
+
+	if (sync)
+		eofb.eof_flags |= XFS_EOF_FLAGS_SYNC;
+
+	trace_xfs_inode_free_blocks(mp, &eofb, _RET_IP_);
+
+	return xfs_blockgc_scan(mp, &eofb);
 }
 
 static inline unsigned long
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index 88bbbc9f00f8..2f230d273a54 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -50,6 +50,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 sync);
+int xfs_inode_free_blocks(struct xfs_mount *mp, bool sync);
 
 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_inode.c b/fs/xfs/xfs_inode.c
index 09d97cf81f6d..0e6cc33a33ad 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1025,10 +1025,18 @@ xfs_create(
 	 */
 retry:
 	error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp);
-	if (error == -ENOSPC) {
+	/*
+	 * We weren't able to reserve enough space to add the inode.  Flush
+	 * any disk space that was being held in the hopes of speeding up the
+	 * filesystem.
+	 */
+	if (error == -ENOSPC && !cleared_space) {
+		cleared_space = true;
 		/* flush outstanding delalloc blocks and retry */
 		xfs_flush_inodes(mp);
-		error = xfs_trans_alloc(mp, tres, resblks, 0, 0, &tp);
+		error = xfs_inode_free_blocks(mp, true);
+		if (!error)
+			goto retry;
 	}
 	if (error)
 		goto out_release_inode;
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index d83ee1406cea..cf651c70f22c 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -243,6 +243,19 @@ xfs_iomap_write_direct(
 retry:
 	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, resrtextents,
 			tflags, &tp);
+	/*
+	 * We weren't able to reserve enough space for the direct write.  Flush
+	 * any disk space that was being held in the hopes of speeding up the
+	 * filesystem.  Historically, we expected callers to have preallocated
+	 * all the space before a direct write, but this is not an absolute
+	 * requirement.  We still hold the IOLOCK so we cannot do a sync scan.
+	 */
+	if (error == -ENOSPC && !cleared_space) {
+		cleared_space = true;
+		error = xfs_inode_free_blocks(ip->i_mount, false);
+		if (!error)
+			goto retry;
+	}
 	if (error)
 		return error;
 
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 7be3cd3ee9bf..749d425603ca 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -379,6 +379,18 @@ xfs_reflink_allocate_cow(
 	xfs_iunlock(ip, *lockmode);
 retry:
 	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
+	/*
+	 * We weren't able to reserve enough space to handle copy on write.
+	 * Flush any disk space that was being held in the hopes of speeding up
+	 * the filesystem.  We potentially hold the IOLOCK so we cannot do a
+	 * synchronous scan.
+	 */
+	if (error == -ENOSPC && !cleared_space) {
+		cleared_space = true;
+		error = xfs_inode_free_blocks(ip->i_mount, false);
+		if (!error)
+			goto retry;
+	}
 	*lockmode = XFS_ILOCK_EXCL;
 	xfs_ilock(ip, *lockmode);
 
@@ -1028,6 +1040,17 @@ xfs_reflink_remap_extent(
 	/* 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);
+	/*
+	 * We weren't able to reserve enough space for the remapping.  Flush
+	 * any disk space that was being held in the hopes of speeding up the
+	 * filesystem.  We still hold the IOLOCK so we cannot do a sync scan.
+	 */
+	if (error == -ENOSPC && !cleared_space) {
+		cleared_space = true;
+		error = xfs_inode_free_blocks(mp, false);
+		if (!error)
+			goto retry;
+	}
 	if (error)
 		goto out;
 
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 7b0dbbf6f4cc..9a29a5e18711 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -3927,6 +3927,7 @@ DEFINE_EVENT(xfs_eofblocks_class, name,	\
 	TP_ARGS(mp, eofb, caller_ip))
 DEFINE_EOFBLOCKS_EVENT(xfs_ioc_free_eofblocks);
 DEFINE_EOFBLOCKS_EVENT(xfs_inode_free_quota_blocks);
+DEFINE_EOFBLOCKS_EVENT(xfs_inode_free_blocks);
 
 #endif /* _TRACE_XFS_H */
 


  parent reply	other threads:[~2021-01-12  0:30 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-11 23:22 [PATCHSET v2 0/6] xfs: try harder to reclaim space when we run out Darrick J. Wong
2021-01-11 23:22 ` [PATCH 1/6] xfs: hide most of the incore inode walk interface Darrick J. Wong
2021-01-13 14:34   ` Christoph Hellwig
2021-01-18 19:50     ` Darrick J. Wong
2021-01-11 23:22 ` [PATCH 2/6] xfs: refactor messy xfs_inode_free_quota_* functions Darrick J. Wong
2021-01-13 14:37   ` Christoph Hellwig
2021-01-11 23:22 ` [PATCH 3/6] xfs: don't stall cowblocks scan if we can't take locks Darrick J. Wong
2021-01-13 14:43   ` Christoph Hellwig
2021-01-14 21:54     ` Darrick J. Wong
2021-01-18 17:34       ` Christoph Hellwig
2021-01-18 19:37         ` Darrick J. Wong
2021-01-18 19:39           ` Christoph Hellwig
2021-01-18 19:44             ` Darrick J. Wong
2021-01-18 19:51               ` Christoph Hellwig
2021-01-11 23:22 ` [PATCH 4/6] xfs: xfs_inode_free_quota_blocks should scan project quota Darrick J. Wong
2021-01-13 14:45   ` Christoph Hellwig
2021-01-11 23:23 ` [PATCH 5/6] xfs: flush speculative space allocations when we run out of quota Darrick J. Wong
2021-01-12  1:22   ` Dave Chinner
2021-01-12  1:31     ` Darrick J. Wong
2021-01-12  1:40       ` Dave Chinner
2021-01-12  2:18         ` Darrick J. Wong
2021-01-14 22:10           ` Darrick J. Wong
2021-01-11 23:23 ` Darrick J. Wong [this message]
  -- strict thread matches above, loose matches on Subject: below --
2020-01-01  1:07 [PATCH v2 0/6] xfs: try harder to reclaim space when we run out Darrick J. Wong
2020-01-01  1:07 ` [PATCH 6/6] xfs: flush speculative space allocations when we run out of space Darrick J. Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=161040739114.1582114.73792904328533145.stgit@magnolia \
    --to=djwong@kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).