Commit 53dbc27e authored by Bob Peterson's avatar Bob Peterson Committed by Andreas Gruenbacher
Browse files

gfs2: further simplify gfs2_evict_inode with new func evict_should_delete



This patch further simplifies function gfs2_evict_inode() by adding a
new function evict_should_delete. The function may also lock the inode
glock.

Signed-off-by: default avatarBob Peterson <rpeterso@redhat.com>
Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
parent 6e7e9a50
Loading
Loading
Loading
Loading
+77 −45
Original line number Diff line number Diff line
@@ -44,6 +44,12 @@
#include "xattr.h"
#include "lops.h"

enum dinode_demise {
	SHOULD_DELETE_DINODE,
	SHOULD_NOT_DELETE_DINODE,
	SHOULD_DEFER_EVICTION,
};

/**
 * gfs2_jindex_free - Clear all the journal index information
 * @sdp: The GFS2 superblock
@@ -1310,6 +1316,73 @@ static bool gfs2_upgrade_iopen_glock(struct inode *inode)
	return true;
}

/**
 * evict_should_delete - determine whether the inode is eligible for deletion
 * @inode: The inode to evict
 *
 * This function determines whether the evicted inode is eligible to be deleted
 * and locks the inode glock.
 *
 * Returns: the fate of the dinode
 */
static enum dinode_demise evict_should_delete(struct inode *inode,
					      struct gfs2_holder *gh)
{
	struct gfs2_inode *ip = GFS2_I(inode);
	struct super_block *sb = inode->i_sb;
	struct gfs2_sbd *sdp = sb->s_fs_info;
	int ret;

	if (test_bit(GIF_ALLOC_FAILED, &ip->i_flags)) {
		BUG_ON(!gfs2_glock_is_locked_by_me(ip->i_gl));
		goto should_delete;
	}

	if (test_bit(GIF_DEFERRED_DELETE, &ip->i_flags))
		return SHOULD_DEFER_EVICTION;

	/* Deletes should never happen under memory pressure anymore.  */
	if (WARN_ON_ONCE(current->flags & PF_MEMALLOC))
		return SHOULD_DEFER_EVICTION;

	/* Must not read inode block until block type has been verified */
	ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, gh);
	if (unlikely(ret)) {
		glock_clear_object(ip->i_iopen_gh.gh_gl, ip);
		ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
		gfs2_glock_dq_uninit(&ip->i_iopen_gh);
		return SHOULD_DEFER_EVICTION;
	}

	if (gfs2_inode_already_deleted(ip->i_gl, ip->i_no_formal_ino))
		return SHOULD_NOT_DELETE_DINODE;
	ret = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED);
	if (ret)
		return SHOULD_NOT_DELETE_DINODE;

	if (test_bit(GIF_INVALID, &ip->i_flags)) {
		ret = gfs2_inode_refresh(ip);
		if (ret)
			return SHOULD_NOT_DELETE_DINODE;
	}

	/*
	 * The inode may have been recreated in the meantime.
	 */
	if (inode->i_nlink)
		return SHOULD_NOT_DELETE_DINODE;

should_delete:
	if (gfs2_holder_initialized(&ip->i_iopen_gh) &&
	    test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) {
		if (!gfs2_upgrade_iopen_glock(inode)) {
			gfs2_holder_uninit(&ip->i_iopen_gh);
			return SHOULD_NOT_DELETE_DINODE;
		}
	}
	return SHOULD_DELETE_DINODE;
}

/**
 * evict_unlinked_inode - delete the pieces of an unlinked evicted inode
 * @inode: The inode to evict
@@ -1387,54 +1460,13 @@ static void gfs2_evict_inode(struct inode *inode)
	if (inode->i_nlink || sb_rdonly(sb))
		goto out;

	if (test_bit(GIF_ALLOC_FAILED, &ip->i_flags)) {
		BUG_ON(!gfs2_glock_is_locked_by_me(ip->i_gl));
	gfs2_holder_mark_uninitialized(&gh);
		goto out_delete;
	}

	if (test_bit(GIF_DEFERRED_DELETE, &ip->i_flags))
	ret = evict_should_delete(inode, &gh);
	if (ret == SHOULD_DEFER_EVICTION)
		goto out;

	/* Deletes should never happen under memory pressure anymore.  */
	if (WARN_ON_ONCE(current->flags & PF_MEMALLOC))
		goto out;

	/* Must not read inode block until block type has been verified */
	ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh);
	if (unlikely(ret)) {
		glock_clear_object(ip->i_iopen_gh.gh_gl, ip);
		ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
		gfs2_glock_dq_uninit(&ip->i_iopen_gh);
		goto out;
	}

	if (gfs2_inode_already_deleted(ip->i_gl, ip->i_no_formal_ino))
		goto out_truncate;
	ret = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED);
	if (ret)
		goto out_truncate;

	if (test_bit(GIF_INVALID, &ip->i_flags)) {
		ret = gfs2_inode_refresh(ip);
		if (ret)
	if (ret == SHOULD_NOT_DELETE_DINODE)
		goto out_truncate;
	}

	/*
	 * The inode may have been recreated in the meantime.
	 */
	if (inode->i_nlink)
		goto out_truncate;

out_delete:
	if (gfs2_holder_initialized(&ip->i_iopen_gh) &&
	    test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) {
		if (!gfs2_upgrade_iopen_glock(inode)) {
			gfs2_holder_uninit(&ip->i_iopen_gh);
			goto out_truncate;
		}
	}
	ret = evict_unlinked_inode(inode);
	goto out_unlock;