diff options
Diffstat (limited to 'fs/xfs/xfs_file.c')
-rw-r--r-- | fs/xfs/xfs_file.c | 54 |
1 files changed, 41 insertions, 13 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 64b48eade91d..830c1c937b88 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -155,7 +155,7 @@ xfs_dir_fsync( | |||
155 | 155 | ||
156 | if (!lsn) | 156 | if (!lsn) |
157 | return 0; | 157 | return 0; |
158 | return _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL); | 158 | return -_xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL); |
159 | } | 159 | } |
160 | 160 | ||
161 | STATIC int | 161 | STATIC int |
@@ -295,7 +295,7 @@ xfs_file_aio_read( | |||
295 | xfs_rw_ilock(ip, XFS_IOLOCK_EXCL); | 295 | xfs_rw_ilock(ip, XFS_IOLOCK_EXCL); |
296 | 296 | ||
297 | if (inode->i_mapping->nrpages) { | 297 | if (inode->i_mapping->nrpages) { |
298 | ret = -filemap_write_and_wait_range( | 298 | ret = filemap_write_and_wait_range( |
299 | VFS_I(ip)->i_mapping, | 299 | VFS_I(ip)->i_mapping, |
300 | pos, -1); | 300 | pos, -1); |
301 | if (ret) { | 301 | if (ret) { |
@@ -679,7 +679,7 @@ xfs_file_dio_aio_write( | |||
679 | goto out; | 679 | goto out; |
680 | 680 | ||
681 | if (mapping->nrpages) { | 681 | if (mapping->nrpages) { |
682 | ret = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping, | 682 | ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, |
683 | pos, -1); | 683 | pos, -1); |
684 | if (ret) | 684 | if (ret) |
685 | goto out; | 685 | goto out; |
@@ -699,7 +699,7 @@ xfs_file_dio_aio_write( | |||
699 | 699 | ||
700 | trace_xfs_file_direct_write(ip, count, iocb->ki_pos, 0); | 700 | trace_xfs_file_direct_write(ip, count, iocb->ki_pos, 0); |
701 | ret = generic_file_direct_write(iocb, iovp, | 701 | ret = generic_file_direct_write(iocb, iovp, |
702 | &nr_segs, pos, &iocb->ki_pos, count, ocount); | 702 | &nr_segs, pos, count, ocount); |
703 | 703 | ||
704 | out: | 704 | out: |
705 | xfs_rw_iunlock(ip, iolock); | 705 | xfs_rw_iunlock(ip, iolock); |
@@ -715,7 +715,7 @@ xfs_file_buffered_aio_write( | |||
715 | const struct iovec *iovp, | 715 | const struct iovec *iovp, |
716 | unsigned long nr_segs, | 716 | unsigned long nr_segs, |
717 | loff_t pos, | 717 | loff_t pos, |
718 | size_t ocount) | 718 | size_t count) |
719 | { | 719 | { |
720 | struct file *file = iocb->ki_filp; | 720 | struct file *file = iocb->ki_filp; |
721 | struct address_space *mapping = file->f_mapping; | 721 | struct address_space *mapping = file->f_mapping; |
@@ -724,7 +724,7 @@ xfs_file_buffered_aio_write( | |||
724 | ssize_t ret; | 724 | ssize_t ret; |
725 | int enospc = 0; | 725 | int enospc = 0; |
726 | int iolock = XFS_IOLOCK_EXCL; | 726 | int iolock = XFS_IOLOCK_EXCL; |
727 | size_t count = ocount; | 727 | struct iov_iter from; |
728 | 728 | ||
729 | xfs_rw_ilock(ip, iolock); | 729 | xfs_rw_ilock(ip, iolock); |
730 | 730 | ||
@@ -732,14 +732,15 @@ xfs_file_buffered_aio_write( | |||
732 | if (ret) | 732 | if (ret) |
733 | goto out; | 733 | goto out; |
734 | 734 | ||
735 | iov_iter_init(&from, iovp, nr_segs, count, 0); | ||
735 | /* We can write back this queue in page reclaim */ | 736 | /* We can write back this queue in page reclaim */ |
736 | current->backing_dev_info = mapping->backing_dev_info; | 737 | current->backing_dev_info = mapping->backing_dev_info; |
737 | 738 | ||
738 | write_retry: | 739 | write_retry: |
739 | trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, 0); | 740 | trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, 0); |
740 | ret = generic_file_buffered_write(iocb, iovp, nr_segs, | 741 | ret = generic_perform_write(file, &from, pos); |
741 | pos, &iocb->ki_pos, count, 0); | 742 | if (likely(ret >= 0)) |
742 | 743 | iocb->ki_pos = pos + ret; | |
743 | /* | 744 | /* |
744 | * If we just got an ENOSPC, try to write back all dirty inodes to | 745 | * If we just got an ENOSPC, try to write back all dirty inodes to |
745 | * convert delalloc space to free up some of the excess reserved | 746 | * convert delalloc space to free up some of the excess reserved |
@@ -823,7 +824,8 @@ xfs_file_fallocate( | |||
823 | 824 | ||
824 | if (!S_ISREG(inode->i_mode)) | 825 | if (!S_ISREG(inode->i_mode)) |
825 | return -EINVAL; | 826 | return -EINVAL; |
826 | if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) | 827 | if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | |
828 | FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE)) | ||
827 | return -EOPNOTSUPP; | 829 | return -EOPNOTSUPP; |
828 | 830 | ||
829 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | 831 | xfs_ilock(ip, XFS_IOLOCK_EXCL); |
@@ -831,6 +833,28 @@ xfs_file_fallocate( | |||
831 | error = xfs_free_file_space(ip, offset, len); | 833 | error = xfs_free_file_space(ip, offset, len); |
832 | if (error) | 834 | if (error) |
833 | goto out_unlock; | 835 | goto out_unlock; |
836 | } else if (mode & FALLOC_FL_COLLAPSE_RANGE) { | ||
837 | unsigned blksize_mask = (1 << inode->i_blkbits) - 1; | ||
838 | |||
839 | if (offset & blksize_mask || len & blksize_mask) { | ||
840 | error = EINVAL; | ||
841 | goto out_unlock; | ||
842 | } | ||
843 | |||
844 | /* | ||
845 | * There is no need to overlap collapse range with EOF, | ||
846 | * in which case it is effectively a truncate operation | ||
847 | */ | ||
848 | if (offset + len >= i_size_read(inode)) { | ||
849 | error = EINVAL; | ||
850 | goto out_unlock; | ||
851 | } | ||
852 | |||
853 | new_size = i_size_read(inode) - len; | ||
854 | |||
855 | error = xfs_collapse_file_space(ip, offset, len); | ||
856 | if (error) | ||
857 | goto out_unlock; | ||
834 | } else { | 858 | } else { |
835 | if (!(mode & FALLOC_FL_KEEP_SIZE) && | 859 | if (!(mode & FALLOC_FL_KEEP_SIZE) && |
836 | offset + len > i_size_read(inode)) { | 860 | offset + len > i_size_read(inode)) { |
@@ -840,8 +864,11 @@ xfs_file_fallocate( | |||
840 | goto out_unlock; | 864 | goto out_unlock; |
841 | } | 865 | } |
842 | 866 | ||
843 | error = xfs_alloc_file_space(ip, offset, len, | 867 | if (mode & FALLOC_FL_ZERO_RANGE) |
844 | XFS_BMAPI_PREALLOC); | 868 | error = xfs_zero_file_space(ip, offset, len); |
869 | else | ||
870 | error = xfs_alloc_file_space(ip, offset, len, | ||
871 | XFS_BMAPI_PREALLOC); | ||
845 | if (error) | 872 | if (error) |
846 | goto out_unlock; | 873 | goto out_unlock; |
847 | } | 874 | } |
@@ -859,7 +886,7 @@ xfs_file_fallocate( | |||
859 | if (ip->i_d.di_mode & S_IXGRP) | 886 | if (ip->i_d.di_mode & S_IXGRP) |
860 | ip->i_d.di_mode &= ~S_ISGID; | 887 | ip->i_d.di_mode &= ~S_ISGID; |
861 | 888 | ||
862 | if (!(mode & FALLOC_FL_PUNCH_HOLE)) | 889 | if (!(mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE))) |
863 | ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; | 890 | ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; |
864 | 891 | ||
865 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 892 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
@@ -1465,6 +1492,7 @@ const struct file_operations xfs_dir_file_operations = { | |||
1465 | 1492 | ||
1466 | static const struct vm_operations_struct xfs_file_vm_ops = { | 1493 | static const struct vm_operations_struct xfs_file_vm_ops = { |
1467 | .fault = filemap_fault, | 1494 | .fault = filemap_fault, |
1495 | .map_pages = filemap_map_pages, | ||
1468 | .page_mkwrite = xfs_vm_page_mkwrite, | 1496 | .page_mkwrite = xfs_vm_page_mkwrite, |
1469 | .remap_pages = generic_file_remap_pages, | 1497 | .remap_pages = generic_file_remap_pages, |
1470 | }; | 1498 | }; |