summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 11:16:51 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-10-22 16:41:02 -0700
commit5749ea123c075503d41acd30fa1a3638f93434a5 (patch)
tree221f937e101d4ea7ab891c7acbfc885f10d9d19b
parent67e20c6c7e21dafbf175d69e9776ad132c6fa92b (diff)
xfs: use realtime EFI to free extents when realtime rmap is enabled
When rmap is enabled, XFS expects a certain order of operations, which is: 1) remove the file mapping, 2) remove the reverse mapping, and then 3) free the blocks. xfs_bmap_del_extent_real tries to do 1 and 3 in the same transaction, which means that when rtrmap is enabled, we have to use realtime EFIs to maintain the expected order. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index c95a30c0bb9b..ef7772b35e6c 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -5057,7 +5057,6 @@ xfs_bmap_del_extent_real(
{
xfs_fsblock_t del_endblock=0; /* first block past del */
xfs_fileoff_t del_endoff; /* first offset past del */
- int do_fx; /* free extent at end of routine */
int error; /* error return value */
int flags = 0;/* inode logging flags */
struct xfs_bmbt_irec got; /* current extent entry */
@@ -5071,6 +5070,8 @@ xfs_bmap_del_extent_real(
uint qfield; /* quota field to update */
int state = xfs_bmap_fork_to_state(whichfork);
struct xfs_bmbt_irec old;
+ bool isrt = xfs_ifork_is_realtime(ip, whichfork);
+ bool want_free = !(bflags & XFS_BMAPI_REMAP);
mp = ip->i_mount;
XFS_STATS_INC(mp, xs_del_exlist);
@@ -5101,17 +5102,24 @@ xfs_bmap_del_extent_real(
return -ENOSPC;
flags = XFS_ILOG_CORE;
- if (xfs_ifork_is_realtime(ip, whichfork)) {
- if (!(bflags & XFS_BMAPI_REMAP)) {
+ if (isrt) {
+ /*
+ * Historically, we did not use EFIs to free realtime extents.
+ * However, when reverse mapping is enabled, we must maintain
+ * the same order of operations as the data device, which is:
+ * Remove the file mapping, remove the reverse mapping, and
+ * then free the blocks. This means that we must delay the
+ * freeing until after we've scheduled the rmap update.
+ */
+ if (want_free && !xfs_has_rtrmapbt(mp)) {
error = xfs_rtfree_blocks(tp, del->br_startblock,
del->br_blockcount);
if (error)
goto done;
+ want_free = false;
}
- do_fx = 0;
qfield = XFS_TRANS_DQ_RTBCOUNT;
} else {
- do_fx = 1;
qfield = XFS_TRANS_DQ_BCOUNT;
}
nblks = del->br_blockcount;
@@ -5286,7 +5294,7 @@ xfs_bmap_del_extent_real(
/*
* If we need to, add to list of extents to delete.
*/
- if (do_fx && !(bflags & XFS_BMAPI_REMAP)) {
+ if (want_free) {
if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) {
xfs_refcount_decrease_extent(tp, del);
} else {
@@ -5295,6 +5303,8 @@ xfs_bmap_del_extent_real(
if ((bflags & XFS_BMAPI_NODISCARD) ||
del->br_state == XFS_EXT_UNWRITTEN)
flags |= XFS_FREE_EXTENT_SKIP_DISCARD;
+ if (isrt)
+ flags |= XFS_FREE_EXTENT_REALTIME;
xfs_free_extent_later(tp, del->br_startblock,
del->br_blockcount, NULL, flags);