Skip to content

Commit

Permalink
xfs: detach dquots from inode if we don't need to inactivate it
Browse files Browse the repository at this point in the history
If we don't need to inactivate an inode, we can detach the dquots and
move on to reclamation.  This isn't strictly required here; it's a
preparation patch for deferred inactivation per reviewer request[1] to
move the creation of xfs_inode_needs_inactivation into a separate
change.  Eventually this !need_inactive chunk will turn into the code
path for inodes that skip xfs_inactive and go straight to memory
reclaim.

[1] https://lore.kernel.org/linux-xfs/20210609012838.GW2945738@locust/T/#mca6d958521cb88bbc1bfe1a30767203328d410b5
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
  • Loading branch information
Darrick J. Wong committed Aug 6, 2021
1 parent c6c2066 commit 62af7d5
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 1 deletion.
8 changes: 7 additions & 1 deletion fs/xfs/xfs_icache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1752,8 +1752,14 @@ xfs_inode_mark_reclaimable(
{
struct xfs_mount *mp = ip->i_mount;
struct xfs_perag *pag;
bool need_inactive = xfs_inode_needs_inactive(ip);

xfs_inactive(ip);
if (!need_inactive) {
/* Going straight to reclaim, so drop the dquots. */
xfs_qm_dqdetach(ip);
} else {
xfs_inactive(ip);
}

if (!XFS_FORCED_SHUTDOWN(mp) && ip->i_delayed_blks) {
xfs_check_delalloc(ip, XFS_DATA_FORK);
Expand Down
53 changes: 53 additions & 0 deletions fs/xfs/xfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1654,6 +1654,59 @@ xfs_inactive_ifree(
return 0;
}

/*
* 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
* the inobt if it is on the unlinked list.
*/
bool
xfs_inode_needs_inactive(
struct xfs_inode *ip)
{
struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *cow_ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);

/*
* If the inode is already free, then there can be nothing
* to clean up here.
*/
if (VFS_I(ip)->i_mode == 0)
return false;

/* If this is a read-only mount, don't do this (would generate I/O) */
if (mp->m_flags & XFS_MOUNT_RDONLY)
return false;

/* If the log isn't running, push inodes straight to reclaim. */
if (XFS_FORCED_SHUTDOWN(mp) || (mp->m_flags & XFS_MOUNT_NORECOVERY))
return false;

/* Metadata inodes require explicit resource cleanup. */
if (xfs_is_metadata_inode(ip))
return false;

/* Want to clean out the cow blocks if there are any. */
if (cow_ifp && cow_ifp->if_bytes > 0)
return true;

/* Unlinked files must be freed. */
if (VFS_I(ip)->i_nlink == 0)
return true;

/*
* This file isn't being freed, so check if there are post-eof blocks
* to free. @force is true because we are evicting an inode from the
* cache. Post-eof blocks must be freed, lest we end up with broken
* free space accounting.
*
* Note: don't bother with iolock here since lockdep complains about
* acquiring it in reclaim context. We have the only reference to the
* inode at this point anyways.
*/
return xfs_can_free_eofblocks(ip, true);
}

/*
* xfs_inactive
*
Expand Down
2 changes: 2 additions & 0 deletions fs/xfs/xfs_inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,8 @@ extern struct kmem_zone *xfs_inode_zone;
/* The default CoW extent size hint. */
#define XFS_DEFAULT_COWEXTSZ_HINT 32

bool xfs_inode_needs_inactive(struct xfs_inode *ip);

int xfs_iunlink_init(struct xfs_perag *pag);
void xfs_iunlink_destroy(struct xfs_perag *pag);

Expand Down

0 comments on commit 62af7d5

Please sign in to comment.