Commit d2c292d8 authored by Jan Kara's avatar Jan Kara
Browse files

xfs: Convert double locking of MMAPLOCK to use VFS helpers



Convert places in XFS that take MMAPLOCK for two inodes to use helper
VFS provides for it (filemap_invalidate_down_write_two()). Note that
this changes lock ordering for MMAPLOCK from inode number based ordering
to pointer based ordering VFS generally uses.

CC: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 2433480a
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -1626,7 +1626,6 @@ xfs_swap_extents(
	struct xfs_bstat	*sbp = &sxp->sx_stat;
	int			src_log_flags, target_log_flags;
	int			error = 0;
	int			lock_flags;
	uint64_t		f;
	int			resblks = 0;
	unsigned int		flags = 0;
@@ -1638,8 +1637,8 @@ xfs_swap_extents(
	 * do the rest of the checks.
	 */
	lock_two_nondirectories(VFS_I(ip), VFS_I(tip));
	lock_flags = XFS_MMAPLOCK_EXCL;
	xfs_lock_two_inodes(ip, XFS_MMAPLOCK_EXCL, tip, XFS_MMAPLOCK_EXCL);
	filemap_invalidate_lock_two(VFS_I(ip)->i_mapping,
				    VFS_I(tip)->i_mapping);

	/* Verify that both files have the same format */
	if ((VFS_I(ip)->i_mode & S_IFMT) != (VFS_I(tip)->i_mode & S_IFMT)) {
@@ -1711,7 +1710,6 @@ xfs_swap_extents(
	 * or cancel will unlock the inodes from this point onwards.
	 */
	xfs_lock_two_inodes(ip, XFS_ILOCK_EXCL, tip, XFS_ILOCK_EXCL);
	lock_flags |= XFS_ILOCK_EXCL;
	xfs_trans_ijoin(tp, ip, 0);
	xfs_trans_ijoin(tp, tip, 0);

@@ -1830,13 +1828,16 @@ xfs_swap_extents(
	trace_xfs_swap_extent_after(ip, 0);
	trace_xfs_swap_extent_after(tip, 1);

out_unlock_ilock:
	xfs_iunlock(ip, XFS_ILOCK_EXCL);
	xfs_iunlock(tip, XFS_ILOCK_EXCL);
out_unlock:
	xfs_iunlock(ip, lock_flags);
	xfs_iunlock(tip, lock_flags);
	filemap_invalidate_unlock_two(VFS_I(ip)->i_mapping,
				      VFS_I(tip)->i_mapping);
	unlock_two_nondirectories(VFS_I(ip), VFS_I(tip));
	return error;

out_trans_cancel:
	xfs_trans_cancel(tp);
	goto out_unlock;
	goto out_unlock_ilock;
}
+11 −26
Original line number Diff line number Diff line
@@ -552,12 +552,10 @@ xfs_lock_inodes(
}

/*
 * xfs_lock_two_inodes() can only be used to lock one type of lock at a time -
 * the mmaplock or the ilock, but not more than one type at a time. If we lock
 * more than one at a time, lockdep will report false positives saying we have
 * violated locking orders.  The iolock must be double-locked separately since
 * we use i_rwsem for that.  We now support taking one lock EXCL and the other
 * SHARED.
 * xfs_lock_two_inodes() can only be used to lock ilock. The iolock and
 * mmaplock must be double-locked separately since we use i_rwsem and
 * invalidate_lock for that. We now support taking one lock EXCL and the
 * other SHARED.
 */
void
xfs_lock_two_inodes(
@@ -575,15 +573,8 @@ xfs_lock_two_inodes(
	ASSERT(hweight32(ip1_mode) == 1);
	ASSERT(!(ip0_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)));
	ASSERT(!(ip1_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)));
	ASSERT(!(ip0_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL)) ||
	       !(ip0_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)));
	ASSERT(!(ip1_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL)) ||
	       !(ip1_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)));
	ASSERT(!(ip1_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL)) ||
	       !(ip0_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)));
	ASSERT(!(ip0_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL)) ||
	       !(ip1_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)));

	ASSERT(!(ip0_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL)));
	ASSERT(!(ip1_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL)));
	ASSERT(ip0->i_ino != ip1->i_ino);

	if (ip0->i_ino > ip1->i_ino) {
@@ -3748,11 +3739,8 @@ xfs_ilock2_io_mmap(
	ret = xfs_iolock_two_inodes_and_break_layout(VFS_I(ip1), VFS_I(ip2));
	if (ret)
		return ret;
	if (ip1 == ip2)
		xfs_ilock(ip1, XFS_MMAPLOCK_EXCL);
	else
		xfs_lock_two_inodes(ip1, XFS_MMAPLOCK_EXCL,
				    ip2, XFS_MMAPLOCK_EXCL);
	filemap_invalidate_lock_two(VFS_I(ip1)->i_mapping,
				    VFS_I(ip2)->i_mapping);
	return 0;
}

@@ -3762,12 +3750,9 @@ xfs_iunlock2_io_mmap(
	struct xfs_inode	*ip1,
	struct xfs_inode	*ip2)
{
	bool			same_inode = (ip1 == ip2);

	xfs_iunlock(ip2, XFS_MMAPLOCK_EXCL);
	if (!same_inode)
		xfs_iunlock(ip1, XFS_MMAPLOCK_EXCL);
	filemap_invalidate_unlock_two(VFS_I(ip1)->i_mapping,
				      VFS_I(ip2)->i_mapping);
	inode_unlock(VFS_I(ip2));
	if (!same_inode)
	if (ip1 != ip2)
		inode_unlock(VFS_I(ip1));
}