Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'xfs-5.17-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Darrick Wong:
"I was auditing operations in XFS that clear file privileges, and
realized that XFS' fallocate implementation drops suid/sgid but
doesn't clear file capabilities the same way that file writes and
reflink do.

There are VFS helpers that do it correctly, so refactor XFS to use
them. I also noticed that we weren't flushing the log at the correct
point in the fallocate operation, so that's fixed too.

Summary:

- Fix fallocate so that it drops all file privileges when files are
modified instead of open-coding that incompletely.

- Fix fallocate to flush the log if the caller wanted synchronous
file updates"

* tag 'xfs-5.17-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
xfs: ensure log flush at the end of a synchronous fallocate call
xfs: move xfs_update_prealloc_flags() to xfs_pnfs.c
xfs: set prealloc flag in xfs_alloc_file_space()
xfs: fallocate() should call file_modified()
xfs: remove XFS_PREALLOC_SYNC
xfs: reject crazy array sizes being fed to XFS_IOC_GETBMAP*

+69 -79
+3 -6
fs/xfs/xfs_bmap_util.c
··· 850 850 rblocks = 0; 851 851 } 852 852 853 - /* 854 - * Allocate and setup the transaction. 855 - */ 856 853 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, 857 854 dblocks, rblocks, false, &tp); 858 855 if (error) ··· 866 869 if (error) 867 870 goto error; 868 871 869 - /* 870 - * Complete the transaction 871 - */ 872 + ip->i_diflags |= XFS_DIFLAG_PREALLOC; 873 + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 874 + 872 875 error = xfs_trans_commit(tp); 873 876 xfs_iunlock(ip, XFS_ILOCK_EXCL); 874 877 if (error)
+26 -60
fs/xfs/xfs_file.c
··· 66 66 return !((pos | len) & mask); 67 67 } 68 68 69 - int 70 - xfs_update_prealloc_flags( 71 - struct xfs_inode *ip, 72 - enum xfs_prealloc_flags flags) 73 - { 74 - struct xfs_trans *tp; 75 - int error; 76 - 77 - error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_writeid, 78 - 0, 0, 0, &tp); 79 - if (error) 80 - return error; 81 - 82 - xfs_ilock(ip, XFS_ILOCK_EXCL); 83 - xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); 84 - 85 - if (!(flags & XFS_PREALLOC_INVISIBLE)) { 86 - VFS_I(ip)->i_mode &= ~S_ISUID; 87 - if (VFS_I(ip)->i_mode & S_IXGRP) 88 - VFS_I(ip)->i_mode &= ~S_ISGID; 89 - xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 90 - } 91 - 92 - if (flags & XFS_PREALLOC_SET) 93 - ip->i_diflags |= XFS_DIFLAG_PREALLOC; 94 - if (flags & XFS_PREALLOC_CLEAR) 95 - ip->i_diflags &= ~XFS_DIFLAG_PREALLOC; 96 - 97 - xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 98 - if (flags & XFS_PREALLOC_SYNC) 99 - xfs_trans_set_sync(tp); 100 - return xfs_trans_commit(tp); 101 - } 102 - 103 69 /* 104 70 * Fsync operations on directories are much simpler than on regular files, 105 71 * as there is no file data to flush, and thus also no need for explicit ··· 861 895 return error; 862 896 } 863 897 898 + /* Does this file, inode, or mount want synchronous writes? */ 899 + static inline bool xfs_file_sync_writes(struct file *filp) 900 + { 901 + struct xfs_inode *ip = XFS_I(file_inode(filp)); 902 + 903 + if (xfs_has_wsync(ip->i_mount)) 904 + return true; 905 + if (filp->f_flags & (__O_SYNC | O_DSYNC)) 906 + return true; 907 + if (IS_SYNC(file_inode(filp))) 908 + return true; 909 + 910 + return false; 911 + } 912 + 864 913 #define XFS_FALLOC_FL_SUPPORTED \ 865 914 (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | \ 866 915 FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE | \ ··· 891 910 struct inode *inode = file_inode(file); 892 911 struct xfs_inode *ip = XFS_I(inode); 893 912 long error; 894 - enum xfs_prealloc_flags flags = 0; 895 913 uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL; 896 914 loff_t new_size = 0; 897 915 bool do_file_insert = false; ··· 934 954 if (error) 935 955 goto out_unlock; 936 956 } 957 + 958 + error = file_modified(file); 959 + if (error) 960 + goto out_unlock; 937 961 938 962 if (mode & FALLOC_FL_PUNCH_HOLE) { 939 963 error = xfs_free_file_space(ip, offset, len); ··· 988 1004 } 989 1005 do_file_insert = true; 990 1006 } else { 991 - flags |= XFS_PREALLOC_SET; 992 - 993 1007 if (!(mode & FALLOC_FL_KEEP_SIZE) && 994 1008 offset + len > i_size_read(inode)) { 995 1009 new_size = offset + len; ··· 1039 1057 } 1040 1058 } 1041 1059 1042 - if (file->f_flags & O_DSYNC) 1043 - flags |= XFS_PREALLOC_SYNC; 1044 - 1045 - error = xfs_update_prealloc_flags(ip, flags); 1046 - if (error) 1047 - goto out_unlock; 1048 - 1049 1060 /* Change file size if needed */ 1050 1061 if (new_size) { 1051 1062 struct iattr iattr; ··· 1057 1082 * leave shifted extents past EOF and hence losing access to 1058 1083 * the data that is contained within them. 1059 1084 */ 1060 - if (do_file_insert) 1085 + if (do_file_insert) { 1061 1086 error = xfs_insert_file_space(ip, offset, len); 1087 + if (error) 1088 + goto out_unlock; 1089 + } 1090 + 1091 + if (xfs_file_sync_writes(file)) 1092 + error = xfs_log_force_inode(ip); 1062 1093 1063 1094 out_unlock: 1064 1095 xfs_iunlock(ip, iolock); ··· 1094 1113 if (lockflags) 1095 1114 xfs_iunlock(ip, lockflags); 1096 1115 return ret; 1097 - } 1098 - 1099 - /* Does this file, inode, or mount want synchronous writes? */ 1100 - static inline bool xfs_file_sync_writes(struct file *filp) 1101 - { 1102 - struct xfs_inode *ip = XFS_I(file_inode(filp)); 1103 - 1104 - if (xfs_has_wsync(ip->i_mount)) 1105 - return true; 1106 - if (filp->f_flags & (__O_SYNC | O_DSYNC)) 1107 - return true; 1108 - if (IS_SYNC(file_inode(filp))) 1109 - return true; 1110 - 1111 - return false; 1112 1116 } 1113 1117 1114 1118 STATIC loff_t
-9
fs/xfs/xfs_inode.h
··· 462 462 } 463 463 464 464 /* from xfs_file.c */ 465 - enum xfs_prealloc_flags { 466 - XFS_PREALLOC_SET = (1 << 1), 467 - XFS_PREALLOC_CLEAR = (1 << 2), 468 - XFS_PREALLOC_SYNC = (1 << 3), 469 - XFS_PREALLOC_INVISIBLE = (1 << 4), 470 - }; 471 - 472 - int xfs_update_prealloc_flags(struct xfs_inode *ip, 473 - enum xfs_prealloc_flags flags); 474 465 int xfs_break_layouts(struct inode *inode, uint *iolock, 475 466 enum layout_break_reason reason); 476 467
+1 -1
fs/xfs/xfs_ioctl.c
··· 1464 1464 1465 1465 if (bmx.bmv_count < 2) 1466 1466 return -EINVAL; 1467 - if (bmx.bmv_count > ULONG_MAX / recsize) 1467 + if (bmx.bmv_count >= INT_MAX / recsize) 1468 1468 return -ENOMEM; 1469 1469 1470 1470 buf = kvcalloc(bmx.bmv_count, sizeof(*buf), GFP_KERNEL);
+39 -3
fs/xfs/xfs_pnfs.c
··· 71 71 } 72 72 73 73 /* 74 + * We cannot use file based VFS helpers such as file_modified() to update 75 + * inode state as we modify the data/metadata in the inode here. Hence we have 76 + * to open code the timestamp updates and SUID/SGID stripping. We also need 77 + * to set the inode prealloc flag to ensure that the extents we allocate are not 78 + * removed if the inode is reclaimed from memory before xfs_fs_block_commit() 79 + * is from the client to indicate that data has been written and the file size 80 + * can be extended. 81 + */ 82 + static int 83 + xfs_fs_map_update_inode( 84 + struct xfs_inode *ip) 85 + { 86 + struct xfs_trans *tp; 87 + int error; 88 + 89 + error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_writeid, 90 + 0, 0, 0, &tp); 91 + if (error) 92 + return error; 93 + 94 + xfs_ilock(ip, XFS_ILOCK_EXCL); 95 + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); 96 + 97 + VFS_I(ip)->i_mode &= ~S_ISUID; 98 + if (VFS_I(ip)->i_mode & S_IXGRP) 99 + VFS_I(ip)->i_mode &= ~S_ISGID; 100 + xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 101 + ip->i_diflags |= XFS_DIFLAG_PREALLOC; 102 + 103 + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 104 + return xfs_trans_commit(tp); 105 + } 106 + 107 + /* 74 108 * Get a layout for the pNFS client. 75 109 */ 76 110 int ··· 198 164 * that the blocks allocated and handed out to the client are 199 165 * guaranteed to be present even after a server crash. 200 166 */ 201 - error = xfs_update_prealloc_flags(ip, 202 - XFS_PREALLOC_SET | XFS_PREALLOC_SYNC); 167 + error = xfs_fs_map_update_inode(ip); 168 + if (!error) 169 + error = xfs_log_force_inode(ip); 203 170 if (error) 204 171 goto out_unlock; 172 + 205 173 } else { 206 174 xfs_iunlock(ip, lock_flags); 207 175 } ··· 291 255 length = end - start; 292 256 if (!length) 293 257 continue; 294 - 258 + 295 259 /* 296 260 * Make sure reads through the pagecache see the new data. 297 261 */