Exemplo n.º 1
0
/*
 * Grab the exclusive iolock for a data copy from src to dest, making
 * sure to abide vfs locking order (lowest pointer value goes first) and
 * breaking the pnfs layout leases on dest before proceeding.  The loop
 * is needed because we cannot call the blocking break_layout() with the
 * src iolock held, and therefore have to back out both locks.
 */
static int
xfs_iolock_two_inodes_and_break_layout(
	struct inode		*src,
	struct inode		*dest)
{
	int			error;

retry:
	if (src < dest) {
		inode_lock_shared(src);
		inode_lock_nested(dest, I_MUTEX_NONDIR2);
	} else {
		/* src >= dest */
		inode_lock(dest);
	}

	error = break_layout(dest, false);
	if (error == -EWOULDBLOCK) {
		inode_unlock(dest);
		if (src < dest)
			inode_unlock_shared(src);
		error = break_layout(dest, true);
		if (error)
			return error;
		goto retry;
	}
	if (error) {
		inode_unlock(dest);
		if (src < dest)
			inode_unlock_shared(src);
		return error;
	}
	if (src > dest)
		inode_lock_shared_nested(src, I_MUTEX_NONDIR2);
	return 0;
}
Exemplo n.º 2
0
/*
 * Ensure that we do not have any outstanding pNFS layouts that can be used by
 * clients to directly read from or write to this inode.  This must be called
 * before every operation that can remove blocks from the extent map.
 * Additionally we call it during the write operation, where aren't concerned
 * about exposing unallocated blocks but just want to provide basic
 * synchronization between a local writer and pNFS clients.  mmap writes would
 * also benefit from this sort of synchronization, but due to the tricky locking
 * rules in the page fault path we don't bother.
 */
int
xfs_break_layouts(
	struct inode		*inode,
	uint			*iolock,
	bool			with_imutex)
{
	struct xfs_inode	*ip = XFS_I(inode);
	int			error;

	ASSERT(xfs_isilocked(ip, XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL));

	while ((error = break_layout(inode, false) == -EWOULDBLOCK)) {
		xfs_iunlock(ip, *iolock);
		if (with_imutex && (*iolock & XFS_IOLOCK_EXCL))
			inode_unlock(inode);
		error = break_layout(inode, true);
		*iolock = XFS_IOLOCK_EXCL;
		if (with_imutex)
			inode_lock(inode);
		xfs_ilock(ip, *iolock);
	}

	return error;
}