Browse Source

xfs: fix double ijoin in xfs_inactive_symlink_rmt()

xfs_inactive_symlink_rmt() does something nasty - it joins an inode
into a transaction it is already joined to. This means the inode can
have multiple log item descriptors attached to the transaction for
it. This breaks teh 1:1 mapping that is supposed to exist
between the log item and log item descriptor.

This results in the log item being processed twice during
transaction commit and CIL formatting, and there are lots of other
potential issues tha arise from double processing of log items in
the transaction commit state machine.

In this case, the inode is already held by the rolling transaction
returned from xfs_defer_finish(), so there's no need to join it
again.

Signed-Off-By: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Dave Chinner 7 years ago
parent
commit
3565b660e5
1 changed files with 2 additions and 7 deletions
  1. 2 7
      fs/xfs/xfs_symlink.c

+ 2 - 7
fs/xfs/xfs_symlink.c

@@ -489,16 +489,11 @@ xfs_inactive_symlink_rmt(
 	error = xfs_defer_finish(&tp, &dfops);
 	error = xfs_defer_finish(&tp, &dfops);
 	if (error)
 	if (error)
 		goto error_bmap_cancel;
 		goto error_bmap_cancel;
-	/*
-	 * The first xact was committed, so add the inode to the new one.
-	 * Mark it dirty so it will be logged and moved forward in the log as
-	 * part of every commit.
-	 */
-	xfs_trans_ijoin(tp, ip, 0);
-	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
 	/*
 	/*
 	 * Commit the transaction containing extent freeing and EFDs.
 	 * Commit the transaction containing extent freeing and EFDs.
 	 */
 	 */
+	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 	error = xfs_trans_commit(tp);
 	error = xfs_trans_commit(tp);
 	if (error) {
 	if (error) {
 		ASSERT(XFS_FORCED_SHUTDOWN(mp));
 		ASSERT(XFS_FORCED_SHUTDOWN(mp));