aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_file.c26
-rw-r--r--fs/xfs/xfs_inode.h16
-rw-r--r--fs/xfs/xfs_ioctl.c3
-rw-r--r--fs/xfs/xfs_iops.c6
-rw-r--r--fs/xfs/xfs_pnfs.c12
-rw-r--r--fs/xfs/xfs_pnfs.h5
6 files changed, 53 insertions, 15 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 35309bd046be..4774c7172ef4 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -312,7 +312,7 @@ restart:
312 if (error <= 0) 312 if (error <= 0)
313 return error; 313 return error;
314 314
315 error = xfs_break_layouts(inode, iolock); 315 error = xfs_break_layouts(inode, iolock, BREAK_WRITE);
316 if (error) 316 if (error)
317 return error; 317 return error;
318 318
@@ -718,6 +718,28 @@ buffered:
718 return ret; 718 return ret;
719} 719}
720 720
721int
722xfs_break_layouts(
723 struct inode *inode,
724 uint *iolock,
725 enum layout_break_reason reason)
726{
727 bool retry;
728
729 ASSERT(xfs_isilocked(XFS_I(inode), XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL));
730
731 switch (reason) {
732 case BREAK_UNMAP:
733 ASSERT(xfs_isilocked(XFS_I(inode), XFS_MMAPLOCK_EXCL));
734 /* fall through */
735 case BREAK_WRITE:
736 return xfs_break_leased_layouts(inode, iolock, &retry);
737 default:
738 WARN_ON_ONCE(1);
739 return -EINVAL;
740 }
741}
742
721#define XFS_FALLOC_FL_SUPPORTED \ 743#define XFS_FALLOC_FL_SUPPORTED \
722 (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | \ 744 (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | \
723 FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE | \ 745 FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE | \
@@ -744,7 +766,7 @@ xfs_file_fallocate(
744 return -EOPNOTSUPP; 766 return -EOPNOTSUPP;
745 767
746 xfs_ilock(ip, iolock); 768 xfs_ilock(ip, iolock);
747 error = xfs_break_layouts(inode, &iolock); 769 error = xfs_break_layouts(inode, &iolock, BREAK_UNMAP);
748 if (error) 770 if (error)
749 goto out_unlock; 771 goto out_unlock;
750 772
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 1eebc53df7d7..e5b849815ce1 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -379,6 +379,20 @@ static inline void xfs_ifunlock(struct xfs_inode *ip)
379 >> XFS_ILOCK_SHIFT) 379 >> XFS_ILOCK_SHIFT)
380 380
381/* 381/*
382 * Layouts are broken in the BREAK_WRITE case to ensure that
383 * layout-holders do not collide with local writes. Additionally,
384 * layouts are broken in the BREAK_UNMAP case to make sure the
385 * layout-holder has a consistent view of the file's extent map. While
386 * BREAK_WRITE breaks can be satisfied by recalling FL_LAYOUT leases,
387 * BREAK_UNMAP breaks additionally require waiting for busy dax-pages to
388 * go idle.
389 */
390enum layout_break_reason {
391 BREAK_WRITE,
392 BREAK_UNMAP,
393};
394
395/*
382 * For multiple groups support: if S_ISGID bit is set in the parent 396 * For multiple groups support: if S_ISGID bit is set in the parent
383 * directory, group of new file is set to that of the parent, and 397 * directory, group of new file is set to that of the parent, and
384 * new subdirectory gets S_ISGID bit from parent. 398 * new subdirectory gets S_ISGID bit from parent.
@@ -443,6 +457,8 @@ enum xfs_prealloc_flags {
443 457
444int xfs_update_prealloc_flags(struct xfs_inode *ip, 458int xfs_update_prealloc_flags(struct xfs_inode *ip,
445 enum xfs_prealloc_flags flags); 459 enum xfs_prealloc_flags flags);
460int xfs_break_layouts(struct inode *inode, uint *iolock,
461 enum layout_break_reason reason);
446 462
447/* from xfs_iops.c */ 463/* from xfs_iops.c */
448extern void xfs_setup_inode(struct xfs_inode *ip); 464extern void xfs_setup_inode(struct xfs_inode *ip);
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 4151fade4bb1..91e73d663099 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -39,7 +39,6 @@
39#include "xfs_icache.h" 39#include "xfs_icache.h"
40#include "xfs_symlink.h" 40#include "xfs_symlink.h"
41#include "xfs_trans.h" 41#include "xfs_trans.h"
42#include "xfs_pnfs.h"
43#include "xfs_acl.h" 42#include "xfs_acl.h"
44#include "xfs_btree.h" 43#include "xfs_btree.h"
45#include <linux/fsmap.h> 44#include <linux/fsmap.h>
@@ -644,7 +643,7 @@ xfs_ioc_space(
644 return error; 643 return error;
645 644
646 xfs_ilock(ip, iolock); 645 xfs_ilock(ip, iolock);
647 error = xfs_break_layouts(inode, &iolock); 646 error = xfs_break_layouts(inode, &iolock, BREAK_UNMAP);
648 if (error) 647 if (error)
649 goto out_unlock; 648 goto out_unlock;
650 649
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 138fb36ca875..ce0c1f9466a8 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -37,7 +37,6 @@
37#include "xfs_da_btree.h" 37#include "xfs_da_btree.h"
38#include "xfs_dir2.h" 38#include "xfs_dir2.h"
39#include "xfs_trans_space.h" 39#include "xfs_trans_space.h"
40#include "xfs_pnfs.h"
41#include "xfs_iomap.h" 40#include "xfs_iomap.h"
42 41
43#include <linux/capability.h> 42#include <linux/capability.h>
@@ -1030,13 +1029,14 @@ xfs_vn_setattr(
1030 int error; 1029 int error;
1031 1030
1032 if (iattr->ia_valid & ATTR_SIZE) { 1031 if (iattr->ia_valid & ATTR_SIZE) {
1033 struct xfs_inode *ip = XFS_I(d_inode(dentry)); 1032 struct inode *inode = d_inode(dentry);
1033 struct xfs_inode *ip = XFS_I(inode);
1034 uint iolock; 1034 uint iolock;
1035 1035
1036 xfs_ilock(ip, XFS_MMAPLOCK_EXCL); 1036 xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
1037 iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL; 1037 iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
1038 1038
1039 error = xfs_break_layouts(d_inode(dentry), &iolock); 1039 error = xfs_break_layouts(inode, &iolock, BREAK_UNMAP);
1040 if (error) { 1040 if (error) {
1041 xfs_iunlock(ip, XFS_MMAPLOCK_EXCL); 1041 xfs_iunlock(ip, XFS_MMAPLOCK_EXCL);
1042 return error; 1042 return error;
diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
index 6ea7b0b55d02..f44c3599527d 100644
--- a/fs/xfs/xfs_pnfs.c
+++ b/fs/xfs/xfs_pnfs.c
@@ -31,17 +31,17 @@
31 * rules in the page fault path we don't bother. 31 * rules in the page fault path we don't bother.
32 */ 32 */
33int 33int
34xfs_break_layouts( 34xfs_break_leased_layouts(
35 struct inode *inode, 35 struct inode *inode,
36 uint *iolock) 36 uint *iolock,
37 bool *did_unlock)
37{ 38{
38 struct xfs_inode *ip = XFS_I(inode); 39 struct xfs_inode *ip = XFS_I(inode);
39 int error; 40 int error;
40 41
41 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL));
42
43 while ((error = break_layout(inode, false) == -EWOULDBLOCK)) { 42 while ((error = break_layout(inode, false) == -EWOULDBLOCK)) {
44 xfs_iunlock(ip, *iolock); 43 xfs_iunlock(ip, *iolock);
44 *did_unlock = true;
45 error = break_layout(inode, true); 45 error = break_layout(inode, true);
46 *iolock &= ~XFS_IOLOCK_SHARED; 46 *iolock &= ~XFS_IOLOCK_SHARED;
47 *iolock |= XFS_IOLOCK_EXCL; 47 *iolock |= XFS_IOLOCK_EXCL;
@@ -121,8 +121,8 @@ xfs_fs_map_blocks(
121 * Lock out any other I/O before we flush and invalidate the pagecache, 121 * Lock out any other I/O before we flush and invalidate the pagecache,
122 * and then hand out a layout to the remote system. This is very 122 * and then hand out a layout to the remote system. This is very
123 * similar to direct I/O, except that the synchronization is much more 123 * similar to direct I/O, except that the synchronization is much more
124 * complicated. See the comment near xfs_break_layouts for a detailed 124 * complicated. See the comment near xfs_break_leased_layouts
125 * explanation. 125 * for a detailed explanation.
126 */ 126 */
127 xfs_ilock(ip, XFS_IOLOCK_EXCL); 127 xfs_ilock(ip, XFS_IOLOCK_EXCL);
128 128
diff --git a/fs/xfs/xfs_pnfs.h b/fs/xfs/xfs_pnfs.h
index bf45951e28fe..940c6c2ad88c 100644
--- a/fs/xfs/xfs_pnfs.h
+++ b/fs/xfs/xfs_pnfs.h
@@ -9,10 +9,11 @@ int xfs_fs_map_blocks(struct inode *inode, loff_t offset, u64 length,
9int xfs_fs_commit_blocks(struct inode *inode, struct iomap *maps, int nr_maps, 9int xfs_fs_commit_blocks(struct inode *inode, struct iomap *maps, int nr_maps,
10 struct iattr *iattr); 10 struct iattr *iattr);
11 11
12int xfs_break_layouts(struct inode *inode, uint *iolock); 12int xfs_break_leased_layouts(struct inode *inode, uint *iolock,
13 bool *did_unlock);
13#else 14#else
14static inline int 15static inline int
15xfs_break_layouts(struct inode *inode, uint *iolock) 16xfs_break_leased_layouts(struct inode *inode, uint *iolock, bool *did_unlock)
16{ 17{
17 return 0; 18 return 0;
18} 19}