diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index d354ea2b74f9..b6808c0a2868 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -49,6 +49,9 @@ struct kmem_cache *xfs_inode_cache;
 STATIC int xfs_iunlink(struct xfs_trans *, struct xfs_inode *);
 STATIC int xfs_iunlink_remove(struct xfs_trans *tp, struct xfs_perag *pag,
 	struct xfs_inode *);
+STATIC int xfs_ifree(struct xfs_trans *tp, struct xfs_inode *ip,
+		struct xfs_icluster *xic);
+STATIC void xfs_ifree_abort(struct xfs_inode *ip, struct xfs_icluster *xic);
 
 /*
  * helper function to extract extent size hint from inode
@@ -1544,6 +1547,7 @@ xfs_inactive_ifree(
 {
 	struct xfs_mount	*mp = ip->i_mount;
 	struct xfs_trans	*tp;
+	struct xfs_icluster     xic = { 0 };
 	int			error;
 
 	/*
@@ -1598,7 +1602,7 @@ xfs_inactive_ifree(
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
 	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 
-	error = xfs_ifree(tp, ip);
+	error = xfs_ifree(tp, ip, &xic);
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 	if (error) {
 		/*
@@ -1612,7 +1616,7 @@ xfs_inactive_ifree(
 			xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
 		}
 		xfs_trans_cancel(tp);
-		return error;
+		goto out_error;
 	}
 
 	/*
@@ -1625,11 +1629,19 @@ xfs_inactive_ifree(
 	 * to try to keep going. Make sure it's not a silent error.
 	 */
 	error = xfs_trans_commit(tp);
-	if (error)
+	if (error) {
 		xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
 			__func__, error);
+		goto out_error;
+	}
 
 	return 0;
+
+out_error:
+	if (xic.deleted)
+		xfs_ifree_abort(ip, &xic);
+
+	return error;
 }
 
 /*
@@ -2259,14 +2271,14 @@ xfs_ifree_cluster(
  * inodes in the AGI. We need to remove the inode from that list atomically with
  * respect to freeing it here.
  */
-int
+STATIC int
 xfs_ifree(
 	struct xfs_trans	*tp,
-	struct xfs_inode	*ip)
+	struct xfs_inode	*ip,
+	struct xfs_icluster     *xic)
 {
 	struct xfs_mount	*mp = ip->i_mount;
 	struct xfs_perag	*pag;
-	struct xfs_icluster	xic = { 0 };
 	struct xfs_inode_log_item *iip = ip->i_itemp;
 	int			error;
 
@@ -2284,7 +2296,7 @@ xfs_ifree(
 	 * makes the AGI lock -> unlinked list modification order the same as
 	 * used in O_TMPFILE creation.
 	 */
-	error = xfs_difree(tp, pag, ip->i_ino, &xic);
+	error = xfs_difree(tp, pag, ip->i_ino, xic);
 	if (error)
 		goto out;
 
@@ -2323,13 +2335,97 @@ xfs_ifree(
 	VFS_I(ip)->i_generation++;
 	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
-	if (xic.deleted)
-		error = xfs_ifree_cluster(tp, pag, ip, &xic);
+	if (xic->deleted)
+		error = xfs_ifree_cluster(tp, pag, ip, xic);
 out:
 	xfs_perag_put(pag);
 	return error;
 }
 
+static void
+xfs_ifree_abort_inode_stale(
+	struct xfs_perag	*pag,
+	xfs_ino_t		inum)
+{
+	struct xfs_mount        *mp = pag->pag_mount;
+	struct xfs_inode_log_item *iip;
+	struct xfs_inode	*ip;
+
+retry:
+	rcu_read_lock();
+	ip = radix_tree_lookup(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, inum));
+
+	/* Inode not in memory, nothing to do */
+	if (!ip) {
+		rcu_read_unlock();
+		return;
+	}
+
+	/* Skip invalid or not stale inode */
+	if (ip->i_ino != inum || !xfs_iflags_test(ip, XFS_ISTALE)) {
+		rcu_read_unlock();
+		return;
+	}
+
+	if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
+		rcu_read_unlock();
+		delay(1);
+		goto retry;
+	}
+
+	iip = ip->i_itemp;
+	if (!iip || list_empty(&iip->ili_item.li_bio_list))
+		goto out_iunlock;
+
+	if (test_bit(XFS_LI_IN_AIL, &iip->ili_item.li_flags))
+		xfs_iflush_abort(ip);
+	else
+		xfs_iflags_clear(ip, XFS_IFLUSHING);
+
+out_iunlock:
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	rcu_read_unlock();
+}
+
+/*
+ * This is called to clean up inodes marked as stale in xfs_ifree
+ */
+STATIC void
+xfs_ifree_abort(
+	struct xfs_inode	*ip,
+	struct xfs_icluster	*xic)
+{
+	struct xfs_mount	*mp = ip->i_mount;
+	struct xfs_perag        *pag;
+	struct xfs_ino_geometry	*igeo = M_IGEO(mp);
+	xfs_ino_t		inum = xic->first_ino;
+	int			nbufs;
+	int			i, j;
+	int			ioffset;
+
+	pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
+
+	nbufs = igeo->ialloc_blks / igeo->blocks_per_cluster;
+
+	for (j = 0; j < nbufs; j++, inum += igeo->inodes_per_cluster) {
+		/*
+		 * The allocation bitmap tells us which inodes of the chunk were
+		 * physically allocated. Skip the cluster if an inode falls into
+		 * a sparse region.
+		 */
+		ioffset = inum - xic->first_ino;
+		if ((xic->alloc & XFS_INOBT_MASK(ioffset)) == 0) {
+			ASSERT(ioffset % igeo->inodes_per_cluster == 0);
+			continue;
+		}
+
+		for (i = 0; i < igeo->inodes_per_cluster; i++)
+			xfs_ifree_abort_inode_stale(pag, inum + i);
+
+	}
+	xfs_perag_put(pag);
+}
+
 /*
  * This is called to unpin an inode.  The caller must have the inode locked
  * in at least shared mode so that the buffer cannot be subsequently pinned
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index fa780f08dc89..423542bf6af1 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -499,7 +499,6 @@ uint		xfs_ilock_data_map_shared(struct xfs_inode *);
 uint		xfs_ilock_attr_map_shared(struct xfs_inode *);
 
 uint		xfs_ip2xflags(struct xfs_inode *);
-int		xfs_ifree(struct xfs_trans *, struct xfs_inode *);
 int		xfs_itruncate_extents_flags(struct xfs_trans **,
 				struct xfs_inode *, int, xfs_fsize_t, int);
 void		xfs_iext_realloc(xfs_inode_t *, int, int);
