summaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_pnfs.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-02-16 01:59:50 +0100
committerDave Chinner <david@fromorbit.com>2015-02-16 01:59:50 +0100
commit781355c6e5ae87908de27dec3380a34918c33eee (patch)
tree9c747dd4207fae358368c3217d5e71f7d3a0af38 /fs/xfs/xfs_pnfs.c
parentxfs: implement pNFS export operations (diff)
downloadlinux-781355c6e5ae87908de27dec3380a34918c33eee.tar.xz
linux-781355c6e5ae87908de27dec3380a34918c33eee.zip
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.
*/