Commit bc7d684f authored by Dave Chinner's avatar Dave Chinner Committed by Carlos Maiolino
Browse files

xfs: rearrange code in xfs_inode_item_precommit



There are similar extsize checks and updates done inside and outside
the inode item lock, which could all be done under a single top
level logic branch outside the ili_lock. The COW extsize fixup can
potentially miss updating the XFS_ILOG_CORE in ili_fsync_fields, so
moving this code up above the ili_fsync_fields update could also be
considered a fix.

Further, to make the next change a bit cleaner, move where we
calculate the on-disk flag mask to after we attach the cluster
buffer to the the inode log item.

Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarCarlos Maiolino <cem@kernel.org>
parent fc0d1923
Loading
Loading
Loading
Loading
+29 −36
Original line number Diff line number Diff line
@@ -131,46 +131,28 @@ xfs_inode_item_precommit(
	}

	/*
	 * Inode verifiers do not check that the extent size hint is an integer
	 * multiple of the rt extent size on a directory with both rtinherit
	 * and extszinherit flags set.  If we're logging a directory that is
	 * misconfigured in this way, clear the hint.
	 * Inode verifiers do not check that the extent size hints are an
	 * integer multiple of the rt extent size on a directory with
	 * rtinherit flags set.  If we're logging a directory that is
	 * misconfigured in this way, clear the bad hints.
	 */
	if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
	    (ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) &&
	if (ip->i_diflags & XFS_DIFLAG_RTINHERIT) {
		if ((ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) &&
		    xfs_extlen_to_rtxmod(ip->i_mount, ip->i_extsize) > 0) {
			ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE |
					   XFS_DIFLAG_EXTSZINHERIT);
			ip->i_extsize = 0;
			flags |= XFS_ILOG_CORE;
		}

	/*
	 * Record the specific change for fdatasync optimisation. This allows
	 * fdatasync to skip log forces for inodes that are only timestamp
	 * dirty. Once we've processed the XFS_ILOG_IVERSION flag, convert it
	 * to XFS_ILOG_CORE so that the actual on-disk dirty tracking
	 * (ili_fields) correctly tracks that the version has changed.
	 */
	spin_lock(&iip->ili_lock);
	iip->ili_fsync_fields |= (flags & ~XFS_ILOG_IVERSION);
	if (flags & XFS_ILOG_IVERSION)
		flags = ((flags & ~XFS_ILOG_IVERSION) | XFS_ILOG_CORE);

	/*
	 * Inode verifiers do not check that the CoW extent size hint is an
	 * integer multiple of the rt extent size on a directory with both
	 * rtinherit and cowextsize flags set.  If we're logging a directory
	 * that is misconfigured in this way, clear the hint.
	 */
	if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
	    (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) &&
		if ((ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) &&
		    xfs_extlen_to_rtxmod(ip->i_mount, ip->i_cowextsize) > 0) {
			ip->i_diflags2 &= ~XFS_DIFLAG2_COWEXTSIZE;
			ip->i_cowextsize = 0;
			flags |= XFS_ILOG_CORE;
		}
	}

	spin_lock(&iip->ili_lock);
	if (!iip->ili_item.li_buf) {
		struct xfs_buf	*bp;
		int		error;
@@ -204,6 +186,17 @@ xfs_inode_item_precommit(
		xfs_trans_brelse(tp, bp);
	}

	/*
	 * Record the specific change for fdatasync optimisation. This allows
	 * fdatasync to skip log forces for inodes that are only timestamp
	 * dirty. Once we've processed the XFS_ILOG_IVERSION flag, convert it
	 * to XFS_ILOG_CORE so that the actual on-disk dirty tracking
	 * (ili_fields) correctly tracks that the version has changed.
	 */
	iip->ili_fsync_fields |= (flags & ~XFS_ILOG_IVERSION);
	if (flags & XFS_ILOG_IVERSION)
		flags = ((flags & ~XFS_ILOG_IVERSION) | XFS_ILOG_CORE);

	/*
	 * Always OR in the bits from the ili_last_fields field.  This is to
	 * coordinate with the xfs_iflush() and xfs_buf_inode_iodone() routines