[PATCH 28/71] xfs: when replaying bmap operations, don't let unlinked inodes get reaped

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Log recovery will iget an inode to replay BUI items and iput the inode
when it's done.  Unfortunately, the iput will see that i_nlink == 0
and decide to truncate & free the inode, which prevents us from
replaying subsequent BUIs.  We can't skip the BUIs because we have to
replay all the redo items to ensure that atomic operations complete.

Since unlinked inode recovery will reap the inode anyway, we can
safely introduce a new inode flag to indicate that an inode is in this
'unlinked recovery' state and should not be auto-reaped in the
drop_inode path.

Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx>
---
 fs/xfs/xfs_bmap_item.c   |    1 +
 fs/xfs/xfs_inode.c       |    8 ++++++++
 fs/xfs/xfs_inode.h       |    6 ++++++
 fs/xfs/xfs_log_recover.c |    1 +
 4 files changed, 16 insertions(+)


diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index 9b1720c..418c012 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -492,6 +492,7 @@ xfs_bui_recover(
 	if (error)
 		goto err_inode;
 
+	xfs_iflags_set(ip, XFS_IRECOVER_UNLINKED);
 	xfs_defer_init(&dfops, &firstfsb);
 
 	/* Process deferred bmap item. */
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index e08eaea..0c25a76 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1855,6 +1855,14 @@ xfs_inactive(
 	if (mp->m_flags & XFS_MOUNT_RDONLY)
 		return;
 
+	/*
+	 * If this unlinked inode is in the middle of recovery, don't
+	 * truncate and free the inode just yet; log recovery will take
+	 * care of that.  See the comment for this inode flag.
+	 */
+	if (xfs_iflags_test(ip, XFS_IRECOVER_UNLINKED))
+		return;
+
 	if (VFS_I(ip)->i_nlink != 0) {
 		/*
 		 * force is true because we are evicting an inode from the
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 4094f2c..7283db3 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -221,6 +221,12 @@ static inline bool xfs_is_reflink_inode(struct xfs_inode *ip)
 #define __XFS_IPINNED_BIT	8	 /* wakeup key for zero pin count */
 #define XFS_IPINNED		(1 << __XFS_IPINNED_BIT)
 #define XFS_IDONTCACHE		(1 << 9) /* don't cache the inode long term */
+/*
+ * If this unlinked inode is in the middle of recovery, don't let drop_inode
+ * truncate and free the inode.  This can happen if we iget the inode during
+ * log recovery to replay a bmap operation on the inode.
+ */
+#define XFS_IRECOVER_UNLINKED	(1 << 10)
 
 /*
  * Per-lifetime flags need to be reset when re-using a reclaimable inode during
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 37673d6..c9c05b9 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -4854,6 +4854,7 @@ xlog_recover_process_one_iunlink(
 	if (error)
 		goto fail_iput;
 
+	xfs_iflags_clear(ip, XFS_IRECOVER_UNLINKED);
 	ASSERT(VFS_I(ip)->i_nlink == 0);
 	ASSERT(VFS_I(ip)->i_mode != 0);
 

_______________________________________________
xfs mailing list
xfs@xxxxxxxxxxx
http://oss.sgi.com/mailman/listinfo/xfs



[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux