summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_inode.c
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2020-10-25 17:14:50 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2020-10-26 18:32:19 -0700
commitbea8e4884867e32cc2e0b6a5662228d3ae82feee (patch)
treeaee82756092ef17539306accbe8881f92b5d0fe4 /fs/xfs/xfs_inode.c
parentfe27b454611e749c3b6e3b2125a3d41ee61277b5 (diff)
xfs: track unlinked inactive inode fs summary counters
Set up counters to track the number of inodes and blocks that will be freed from inactivating unlinked inodes. We'll use this in the deferred inactivation patch to hide the effects of deferred processing. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r--fs/xfs/xfs_inode.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 0b138d2a4fa8..c0ae539f3cad 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1820,6 +1820,59 @@ xfs_inactive_ifree(
}
/*
+ * Play some accounting tricks with deferred inactivation of unlinked inodes so
+ * that it looks like the inode got freed immediately. The superblock
+ * maintains counts of the number of inodes, data blocks, and rt blocks that
+ * would be freed if we were to force inode inactivation. These counts are
+ * added to the statfs free counters outside of the regular fdblocks/ifree
+ * counters. If userspace actually demands those "free" resources we'll force
+ * an inactivation scan to free things for real.
+ *
+ * Note that we can safely skip the block accounting trickery for complicated
+ * situations (inode with blocks on both devices, inode block counts that seem
+ * wrong) since the worst that happens is that reported resource usage
+ * decreases more slowly than what was just deleted.
+ *
+ * Positive @direction means we're setting up the accounting trick and
+ * negative undoes it.
+ */
+static inline void
+xfs_inode_iadjust(
+ struct xfs_inode *ip,
+ int direction)
+{
+ struct xfs_mount *mp = ip->i_mount;
+ xfs_filblks_t iblocks;
+ int64_t inodes = 0;
+ int64_t dblocks = 0;
+ int64_t rblocks = 0;
+
+ ASSERT(direction != 0);
+
+ if (VFS_I(ip)->i_nlink != 0)
+ return;
+
+ inodes = 1;
+ iblocks = max_t(int64_t, 0, ip->i_d.di_nblocks + ip->i_delayed_blks);
+ if (!XFS_IS_REALTIME_INODE(ip))
+ dblocks = iblocks;
+ else if (!ip->i_afp || ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
+ rblocks = iblocks;
+
+ if (direction < 0) {
+ inodes = -inodes;
+ dblocks = -dblocks;
+ rblocks = -rblocks;
+ }
+
+ percpu_counter_add(&mp->m_iinactive, inodes);
+ if (dblocks)
+ percpu_counter_add(&mp->m_dinactive, dblocks);
+ if (rblocks)
+ percpu_counter_add(&mp->m_rinactive, rblocks);
+}
+
+/*
* Returns true if we need to update the on-disk metadata before we can free
* the memory used by this inode. Updates include freeing post-eof
* preallocations; freeing COW staging extents; and marking the inode free in