diff options
| -rw-r--r-- | fs/xfs/xfs_file.c | 14 | ||||
| -rw-r--r-- | fs/xfs/xfs_ioctl.c | 9 | ||||
| -rw-r--r-- | fs/xfs/xfs_iops.c | 11 | ||||
| -rw-r--r-- | fs/xfs/xfs_pnfs.c | 30 | ||||
| -rw-r--r-- | fs/xfs/xfs_pnfs.h | 7 |
5 files changed, 64 insertions, 7 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 712d312d8e3e..56dcfce8d7d6 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include "xfs_trace.h" | 36 | #include "xfs_trace.h" |
| 37 | #include "xfs_log.h" | 37 | #include "xfs_log.h" |
| 38 | #include "xfs_icache.h" | 38 | #include "xfs_icache.h" |
| 39 | #include "xfs_pnfs.h" | ||
| 39 | 40 | ||
| 40 | #include <linux/aio.h> | 41 | #include <linux/aio.h> |
| 41 | #include <linux/dcache.h> | 42 | #include <linux/dcache.h> |
| @@ -554,6 +555,10 @@ restart: | |||
| 554 | if (error) | 555 | if (error) |
| 555 | return error; | 556 | return error; |
| 556 | 557 | ||
| 558 | error = xfs_break_layouts(inode, iolock); | ||
| 559 | if (error) | ||
| 560 | return error; | ||
| 561 | |||
| 557 | /* | 562 | /* |
| 558 | * If the offset is beyond the size of the file, we need to zero any | 563 | * If the offset is beyond the size of the file, we need to zero any |
| 559 | * blocks that fall between the existing EOF and the start of this | 564 | * blocks that fall between the existing EOF and the start of this |
| @@ -822,6 +827,7 @@ xfs_file_fallocate( | |||
| 822 | struct xfs_inode *ip = XFS_I(inode); | 827 | struct xfs_inode *ip = XFS_I(inode); |
| 823 | long error; | 828 | long error; |
| 824 | enum xfs_prealloc_flags flags = 0; | 829 | enum xfs_prealloc_flags flags = 0; |
| 830 | uint iolock = XFS_IOLOCK_EXCL; | ||
| 825 | loff_t new_size = 0; | 831 | loff_t new_size = 0; |
| 826 | 832 | ||
| 827 | if (!S_ISREG(inode->i_mode)) | 833 | if (!S_ISREG(inode->i_mode)) |
| @@ -830,7 +836,11 @@ xfs_file_fallocate( | |||
| 830 | FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE)) | 836 | FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE)) |
| 831 | return -EOPNOTSUPP; | 837 | return -EOPNOTSUPP; |
| 832 | 838 | ||
| 833 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | 839 | xfs_ilock(ip, iolock); |
| 840 | error = xfs_break_layouts(inode, &iolock); | ||
| 841 | if (error) | ||
| 842 | goto out_unlock; | ||
| 843 | |||
| 834 | if (mode & FALLOC_FL_PUNCH_HOLE) { | 844 | if (mode & FALLOC_FL_PUNCH_HOLE) { |
| 835 | error = xfs_free_file_space(ip, offset, len); | 845 | error = xfs_free_file_space(ip, offset, len); |
| 836 | if (error) | 846 | if (error) |
| @@ -894,7 +904,7 @@ xfs_file_fallocate( | |||
| 894 | } | 904 | } |
| 895 | 905 | ||
| 896 | out_unlock: | 906 | out_unlock: |
| 897 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 907 | xfs_iunlock(ip, iolock); |
| 898 | return error; | 908 | return error; |
| 899 | } | 909 | } |
| 900 | 910 | ||
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index f7afb86c9148..bf70a2affb05 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
| @@ -39,6 +39,7 @@ | |||
| 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" | ||
| 42 | 43 | ||
| 43 | #include <linux/capability.h> | 44 | #include <linux/capability.h> |
| 44 | #include <linux/dcache.h> | 45 | #include <linux/dcache.h> |
| @@ -608,6 +609,7 @@ xfs_ioc_space( | |||
| 608 | { | 609 | { |
| 609 | struct iattr iattr; | 610 | struct iattr iattr; |
| 610 | enum xfs_prealloc_flags flags = 0; | 611 | enum xfs_prealloc_flags flags = 0; |
| 612 | uint iolock = XFS_IOLOCK_EXCL; | ||
| 611 | int error; | 613 | int error; |
| 612 | 614 | ||
| 613 | /* | 615 | /* |
| @@ -636,7 +638,10 @@ xfs_ioc_space( | |||
| 636 | if (error) | 638 | if (error) |
| 637 | return error; | 639 | return error; |
| 638 | 640 | ||
| 639 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | 641 | xfs_ilock(ip, iolock); |
| 642 | error = xfs_break_layouts(inode, &iolock); | ||
| 643 | if (error) | ||
| 644 | goto out_unlock; | ||
| 640 | 645 | ||
| 641 | switch (bf->l_whence) { | 646 | switch (bf->l_whence) { |
| 642 | case 0: /*SEEK_SET*/ | 647 | case 0: /*SEEK_SET*/ |
| @@ -725,7 +730,7 @@ xfs_ioc_space( | |||
| 725 | error = xfs_update_prealloc_flags(ip, flags); | 730 | error = xfs_update_prealloc_flags(ip, flags); |
| 726 | 731 | ||
| 727 | out_unlock: | 732 | out_unlock: |
| 728 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 733 | xfs_iunlock(ip, iolock); |
| 729 | mnt_drop_write_file(filp); | 734 | mnt_drop_write_file(filp); |
| 730 | return error; | 735 | return error; |
| 731 | } | 736 | } |
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index e5e2ea0d0b25..d919ad7b16bf 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
| @@ -37,6 +37,7 @@ | |||
| 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" | ||
| 40 | 41 | ||
| 41 | #include <linux/capability.h> | 42 | #include <linux/capability.h> |
| 42 | #include <linux/xattr.h> | 43 | #include <linux/xattr.h> |
| @@ -979,9 +980,13 @@ xfs_vn_setattr( | |||
| 979 | int error; | 980 | int error; |
| 980 | 981 | ||
| 981 | if (iattr->ia_valid & ATTR_SIZE) { | 982 | if (iattr->ia_valid & ATTR_SIZE) { |
| 982 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | 983 | uint iolock = XFS_IOLOCK_EXCL; |
| 983 | error = xfs_setattr_size(ip, iattr); | 984 | |
| 984 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 985 | xfs_ilock(ip, iolock); |
| 986 | error = xfs_break_layouts(dentry->d_inode, &iolock); | ||
| 987 | if (!error) | ||
| 988 | error = xfs_setattr_size(ip, iattr); | ||
| 989 | xfs_iunlock(ip, iolock); | ||
| 985 | } else { | 990 | } else { |
| 986 | error = xfs_setattr_nonsize(ip, iattr, 0); | 991 | error = xfs_setattr_nonsize(ip, iattr, 0); |
| 987 | } | 992 | } |
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 @@ | |||
| 19 | #include "xfs_pnfs.h" | 19 | #include "xfs_pnfs.h" |
| 20 | 20 | ||
| 21 | /* | 21 | /* |
| 22 | * Ensure that we do not have any outstanding pNFS layouts that can be used by | ||
| 23 | * clients to directly read from or write to this inode. This must be called | ||
| 24 | * before every operation that can remove blocks from the extent map. | ||
| 25 | * Additionally we call it during the write operation, where aren't concerned | ||
| 26 | * about exposing unallocated blocks but just want to provide basic | ||
| 27 | * synchronization between a local writer and pNFS clients. mmap writes would | ||
| 28 | * also benefit from this sort of synchronization, but due to the tricky locking | ||
| 29 | * rules in the page fault path we don't bother. | ||
| 30 | */ | ||
| 31 | int | ||
| 32 | xfs_break_layouts( | ||
| 33 | struct inode *inode, | ||
| 34 | uint *iolock) | ||
| 35 | { | ||
| 36 | struct xfs_inode *ip = XFS_I(inode); | ||
| 37 | int error; | ||
| 38 | |||
| 39 | ASSERT(xfs_isilocked(ip, XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)); | ||
| 40 | |||
| 41 | while ((error = break_layout(inode, false) == -EWOULDBLOCK)) { | ||
| 42 | xfs_iunlock(ip, *iolock); | ||
| 43 | error = break_layout(inode, true); | ||
| 44 | *iolock = XFS_IOLOCK_EXCL; | ||
| 45 | xfs_ilock(ip, *iolock); | ||
| 46 | } | ||
| 47 | |||
| 48 | return error; | ||
| 49 | } | ||
| 50 | |||
| 51 | /* | ||
| 22 | * Get a unique ID including its location so that the client can identify | 52 | * Get a unique ID including its location so that the client can identify |
| 23 | * the exported device. | 53 | * the exported device. |
| 24 | */ | 54 | */ |
diff --git a/fs/xfs/xfs_pnfs.h b/fs/xfs/xfs_pnfs.h index 0d91255a89ae..b7fbfce660f6 100644 --- a/fs/xfs/xfs_pnfs.h +++ b/fs/xfs/xfs_pnfs.h | |||
| @@ -7,5 +7,12 @@ int xfs_fs_map_blocks(struct inode *inode, loff_t offset, u64 length, | |||
| 7 | struct iomap *iomap, bool write, u32 *device_generation); | 7 | struct iomap *iomap, bool write, u32 *device_generation); |
| 8 | int xfs_fs_commit_blocks(struct inode *inode, struct iomap *maps, int nr_maps, | 8 | int xfs_fs_commit_blocks(struct inode *inode, struct iomap *maps, int nr_maps, |
| 9 | struct iattr *iattr); | 9 | struct iattr *iattr); |
| 10 | |||
| 11 | int xfs_break_layouts(struct inode *inode, uint *iolock); | ||
| 12 | #else | ||
| 13 | static inline int xfs_break_layouts(struct inode *inode, uint *iolock) | ||
| 14 | { | ||
| 15 | return 0; | ||
| 16 | } | ||
| 10 | #endif /* CONFIG_NFSD_PNFS */ | 17 | #endif /* CONFIG_NFSD_PNFS */ |
| 11 | #endif /* _XFS_PNFS_H */ | 18 | #endif /* _XFS_PNFS_H */ |
