diff options
Diffstat (limited to 'fs/xfs/xfs_file.c')
| -rw-r--r-- | fs/xfs/xfs_file.c | 67 |
1 files changed, 43 insertions, 24 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 13e974e6a889..1cdba95c78cb 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
| @@ -127,6 +127,42 @@ xfs_iozero( | |||
| 127 | return (-status); | 127 | return (-status); |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | int | ||
| 131 | xfs_update_prealloc_flags( | ||
| 132 | struct xfs_inode *ip, | ||
| 133 | enum xfs_prealloc_flags flags) | ||
| 134 | { | ||
| 135 | struct xfs_trans *tp; | ||
| 136 | int error; | ||
| 137 | |||
| 138 | tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_WRITEID); | ||
| 139 | error = xfs_trans_reserve(tp, &M_RES(ip->i_mount)->tr_writeid, 0, 0); | ||
| 140 | if (error) { | ||
| 141 | xfs_trans_cancel(tp, 0); | ||
| 142 | return error; | ||
| 143 | } | ||
| 144 | |||
| 145 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
| 146 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
| 147 | |||
| 148 | if (!(flags & XFS_PREALLOC_INVISIBLE)) { | ||
| 149 | ip->i_d.di_mode &= ~S_ISUID; | ||
| 150 | if (ip->i_d.di_mode & S_IXGRP) | ||
| 151 | ip->i_d.di_mode &= ~S_ISGID; | ||
| 152 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
| 153 | } | ||
| 154 | |||
| 155 | if (flags & XFS_PREALLOC_SET) | ||
| 156 | ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; | ||
| 157 | if (flags & XFS_PREALLOC_CLEAR) | ||
| 158 | ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC; | ||
| 159 | |||
| 160 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
| 161 | if (flags & XFS_PREALLOC_SYNC) | ||
| 162 | xfs_trans_set_sync(tp); | ||
| 163 | return xfs_trans_commit(tp, 0); | ||
| 164 | } | ||
| 165 | |||
| 130 | /* | 166 | /* |
| 131 | * Fsync operations on directories are much simpler than on regular files, | 167 | * Fsync operations on directories are much simpler than on regular files, |
| 132 | * as there is no file data to flush, and thus also no need for explicit | 168 | * as there is no file data to flush, and thus also no need for explicit |
| @@ -699,7 +735,7 @@ xfs_file_buffered_aio_write( | |||
| 699 | 735 | ||
| 700 | iov_iter_truncate(from, count); | 736 | iov_iter_truncate(from, count); |
| 701 | /* We can write back this queue in page reclaim */ | 737 | /* We can write back this queue in page reclaim */ |
| 702 | current->backing_dev_info = mapping->backing_dev_info; | 738 | current->backing_dev_info = inode_to_bdi(inode); |
| 703 | 739 | ||
| 704 | write_retry: | 740 | write_retry: |
| 705 | trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, 0); | 741 | trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, 0); |
| @@ -784,8 +820,8 @@ xfs_file_fallocate( | |||
| 784 | { | 820 | { |
| 785 | struct inode *inode = file_inode(file); | 821 | struct inode *inode = file_inode(file); |
| 786 | struct xfs_inode *ip = XFS_I(inode); | 822 | struct xfs_inode *ip = XFS_I(inode); |
| 787 | struct xfs_trans *tp; | ||
| 788 | long error; | 823 | long error; |
| 824 | enum xfs_prealloc_flags flags = 0; | ||
| 789 | loff_t new_size = 0; | 825 | loff_t new_size = 0; |
| 790 | 826 | ||
| 791 | if (!S_ISREG(inode->i_mode)) | 827 | if (!S_ISREG(inode->i_mode)) |
| @@ -822,6 +858,8 @@ xfs_file_fallocate( | |||
| 822 | if (error) | 858 | if (error) |
| 823 | goto out_unlock; | 859 | goto out_unlock; |
| 824 | } else { | 860 | } else { |
| 861 | flags |= XFS_PREALLOC_SET; | ||
| 862 | |||
| 825 | if (!(mode & FALLOC_FL_KEEP_SIZE) && | 863 | if (!(mode & FALLOC_FL_KEEP_SIZE) && |
| 826 | offset + len > i_size_read(inode)) { | 864 | offset + len > i_size_read(inode)) { |
| 827 | new_size = offset + len; | 865 | new_size = offset + len; |
| @@ -839,28 +877,10 @@ xfs_file_fallocate( | |||
| 839 | goto out_unlock; | 877 | goto out_unlock; |
| 840 | } | 878 | } |
| 841 | 879 | ||
| 842 | tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_WRITEID); | ||
| 843 | error = xfs_trans_reserve(tp, &M_RES(ip->i_mount)->tr_writeid, 0, 0); | ||
| 844 | if (error) { | ||
| 845 | xfs_trans_cancel(tp, 0); | ||
| 846 | goto out_unlock; | ||
| 847 | } | ||
| 848 | |||
| 849 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
| 850 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
| 851 | ip->i_d.di_mode &= ~S_ISUID; | ||
| 852 | if (ip->i_d.di_mode & S_IXGRP) | ||
| 853 | ip->i_d.di_mode &= ~S_ISGID; | ||
| 854 | |||
| 855 | if (!(mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE))) | ||
| 856 | ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; | ||
| 857 | |||
| 858 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
| 859 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
| 860 | |||
| 861 | if (file->f_flags & O_DSYNC) | 880 | if (file->f_flags & O_DSYNC) |
| 862 | xfs_trans_set_sync(tp); | 881 | flags |= XFS_PREALLOC_SYNC; |
| 863 | error = xfs_trans_commit(tp, 0); | 882 | |
| 883 | error = xfs_update_prealloc_flags(ip, flags); | ||
| 864 | if (error) | 884 | if (error) |
| 865 | goto out_unlock; | 885 | goto out_unlock; |
| 866 | 886 | ||
| @@ -1384,5 +1404,4 @@ static const struct vm_operations_struct xfs_file_vm_ops = { | |||
| 1384 | .fault = filemap_fault, | 1404 | .fault = filemap_fault, |
| 1385 | .map_pages = filemap_map_pages, | 1405 | .map_pages = filemap_map_pages, |
| 1386 | .page_mkwrite = xfs_vm_page_mkwrite, | 1406 | .page_mkwrite = xfs_vm_page_mkwrite, |
| 1387 | .remap_pages = generic_file_remap_pages, | ||
| 1388 | }; | 1407 | }; |
