summary refs log tree commit diff
path: root/fs/xfs/xfs_pnfs.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-02-16 11:59:50 +1100
committerDave Chinner <david@fromorbit.com>2015-02-16 11:59:50 +1100
commit781355c6e5ae87908de27dec3380a34918c33eee (patch)
tree9c747dd4207fae358368c3217d5e71f7d3a0af38 /fs/xfs/xfs_pnfs.c
parent527851124d10f9c50b1c578e0a56fcd49922422d (diff)
downloadlinux-781355c6e5ae87908de27dec3380a34918c33eee.tar.gz
xfs: recall pNFS layouts on conflicting access
Recall all outstanding pNFS layouts and truncates, writes and similar extent
list modifying operations.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>

Diffstat (limited to 'fs/xfs/xfs_pnfs.c')
-rw-r--r--fs/xfs/xfs_pnfs.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
index 89912b34f184..4b33ef112400 100644
--- a/fs/xfs/xfs_pnfs.c
+++ b/fs/xfs/xfs_pnfs.c
@@ -19,6 +19,36 @@
 #include "xfs_pnfs.h"
 
 /*
+ * 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)
+{
+	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);
+		error = break_layout(inode, true);
+		*iolock = XFS_IOLOCK_EXCL;
+		xfs_ilock(ip, *iolock);
+	}
+
+	return error;
+}
+
+/*
  * Get a unique ID including its location so that the client can identify
  * the exported device.
  */