1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2000-2006 Silicon Graphics, Inc. 4 * All Rights Reserved. 5 */ 6 #include <linux/iversion.h> 7 #include "xfs.h" 8 #include "xfs_fs.h" 9 #include "xfs_shared.h" 10 #include "xfs_format.h" 11 #include "xfs_log_format.h" 12 #include "xfs_trans_resv.h" 13 #include "xfs_sb.h" 14 #include "xfs_mount.h" 15 #include "xfs_inode.h" 16 #include "xfs_inode_util.h" 17 #include "xfs_trans.h" 18 #include "xfs_ialloc.h" 19 #include "xfs_health.h" 20 #include "xfs_bmap.h" 21 22 uint16_t 23 xfs_flags2diflags( 24 struct xfs_inode *ip, 25 unsigned int xflags) 26 { 27 /* can't set PREALLOC this way, just preserve it */ 28 uint16_t di_flags = 29 (ip->i_diflags & XFS_DIFLAG_PREALLOC); 30 31 if (xflags & FS_XFLAG_IMMUTABLE) 32 di_flags |= XFS_DIFLAG_IMMUTABLE; 33 if (xflags & FS_XFLAG_APPEND) 34 di_flags |= XFS_DIFLAG_APPEND; 35 if (xflags & FS_XFLAG_SYNC) 36 di_flags |= XFS_DIFLAG_SYNC; 37 if (xflags & FS_XFLAG_NOATIME) 38 di_flags |= XFS_DIFLAG_NOATIME; 39 if (xflags & FS_XFLAG_NODUMP) 40 di_flags |= XFS_DIFLAG_NODUMP; 41 if (xflags & FS_XFLAG_NODEFRAG) 42 di_flags |= XFS_DIFLAG_NODEFRAG; 43 if (xflags & FS_XFLAG_FILESTREAM) 44 di_flags |= XFS_DIFLAG_FILESTREAM; 45 if (S_ISDIR(VFS_I(ip)->i_mode)) { 46 if (xflags & FS_XFLAG_RTINHERIT) 47 di_flags |= XFS_DIFLAG_RTINHERIT; 48 if (xflags & FS_XFLAG_NOSYMLINKS) 49 di_flags |= XFS_DIFLAG_NOSYMLINKS; 50 if (xflags & FS_XFLAG_EXTSZINHERIT) 51 di_flags |= XFS_DIFLAG_EXTSZINHERIT; 52 if (xflags & FS_XFLAG_PROJINHERIT) 53 di_flags |= XFS_DIFLAG_PROJINHERIT; 54 } else if (S_ISREG(VFS_I(ip)->i_mode)) { 55 if (xflags & FS_XFLAG_REALTIME) 56 di_flags |= XFS_DIFLAG_REALTIME; 57 if (xflags & FS_XFLAG_EXTSIZE) 58 di_flags |= XFS_DIFLAG_EXTSIZE; 59 } 60 61 return di_flags; 62 } 63 64 uint64_t 65 xfs_flags2diflags2( 66 struct xfs_inode *ip, 67 unsigned int xflags) 68 { 69 uint64_t di_flags2 = 70 (ip->i_diflags2 & (XFS_DIFLAG2_REFLINK | 71 XFS_DIFLAG2_BIGTIME | 72 XFS_DIFLAG2_NREXT64)); 73 74 if (xflags & FS_XFLAG_DAX) 75 di_flags2 |= XFS_DIFLAG2_DAX; 76 if (xflags & FS_XFLAG_COWEXTSIZE) 77 di_flags2 |= XFS_DIFLAG2_COWEXTSIZE; 78 79 return di_flags2; 80 } 81 82 uint32_t 83 xfs_ip2xflags( 84 struct xfs_inode *ip) 85 { 86 uint32_t flags = 0; 87 88 if (ip->i_diflags & XFS_DIFLAG_ANY) { 89 if (ip->i_diflags & XFS_DIFLAG_REALTIME) 90 flags |= FS_XFLAG_REALTIME; 91 if (ip->i_diflags & XFS_DIFLAG_PREALLOC) 92 flags |= FS_XFLAG_PREALLOC; 93 if (ip->i_diflags & XFS_DIFLAG_IMMUTABLE) 94 flags |= FS_XFLAG_IMMUTABLE; 95 if (ip->i_diflags & XFS_DIFLAG_APPEND) 96 flags |= FS_XFLAG_APPEND; 97 if (ip->i_diflags & XFS_DIFLAG_SYNC) 98 flags |= FS_XFLAG_SYNC; 99 if (ip->i_diflags & XFS_DIFLAG_NOATIME) 100 flags |= FS_XFLAG_NOATIME; 101 if (ip->i_diflags & XFS_DIFLAG_NODUMP) 102 flags |= FS_XFLAG_NODUMP; 103 if (ip->i_diflags & XFS_DIFLAG_RTINHERIT) 104 flags |= FS_XFLAG_RTINHERIT; 105 if (ip->i_diflags & XFS_DIFLAG_PROJINHERIT) 106 flags |= FS_XFLAG_PROJINHERIT; 107 if (ip->i_diflags & XFS_DIFLAG_NOSYMLINKS) 108 flags |= FS_XFLAG_NOSYMLINKS; 109 if (ip->i_diflags & XFS_DIFLAG_EXTSIZE) 110 flags |= FS_XFLAG_EXTSIZE; 111 if (ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) 112 flags |= FS_XFLAG_EXTSZINHERIT; 113 if (ip->i_diflags & XFS_DIFLAG_NODEFRAG) 114 flags |= FS_XFLAG_NODEFRAG; 115 if (ip->i_diflags & XFS_DIFLAG_FILESTREAM) 116 flags |= FS_XFLAG_FILESTREAM; 117 } 118 119 if (ip->i_diflags2 & XFS_DIFLAG2_ANY) { 120 if (ip->i_diflags2 & XFS_DIFLAG2_DAX) 121 flags |= FS_XFLAG_DAX; 122 if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) 123 flags |= FS_XFLAG_COWEXTSIZE; 124 } 125 126 if (xfs_inode_has_attr_fork(ip)) 127 flags |= FS_XFLAG_HASATTR; 128 return flags; 129 } 130 131 prid_t 132 xfs_get_initial_prid(struct xfs_inode *dp) 133 { 134 if (dp->i_diflags & XFS_DIFLAG_PROJINHERIT) 135 return dp->i_projid; 136 137 /* Assign to the root project by default. */ 138 return 0; 139 } 140 141 /* Propagate di_flags from a parent inode to a child inode. */ 142 static inline void 143 xfs_inode_inherit_flags( 144 struct xfs_inode *ip, 145 const struct xfs_inode *pip) 146 { 147 unsigned int di_flags = 0; 148 xfs_failaddr_t failaddr; 149 umode_t mode = VFS_I(ip)->i_mode; 150 151 if (S_ISDIR(mode)) { 152 if (pip->i_diflags & XFS_DIFLAG_RTINHERIT) 153 di_flags |= XFS_DIFLAG_RTINHERIT; 154 if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) { 155 di_flags |= XFS_DIFLAG_EXTSZINHERIT; 156 ip->i_extsize = pip->i_extsize; 157 } 158 if (pip->i_diflags & XFS_DIFLAG_PROJINHERIT) 159 di_flags |= XFS_DIFLAG_PROJINHERIT; 160 } else if (S_ISREG(mode)) { 161 if ((pip->i_diflags & XFS_DIFLAG_RTINHERIT) && 162 xfs_has_realtime(ip->i_mount)) 163 di_flags |= XFS_DIFLAG_REALTIME; 164 if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) { 165 di_flags |= XFS_DIFLAG_EXTSIZE; 166 ip->i_extsize = pip->i_extsize; 167 } 168 } 169 if ((pip->i_diflags & XFS_DIFLAG_NOATIME) && 170 xfs_inherit_noatime) 171 di_flags |= XFS_DIFLAG_NOATIME; 172 if ((pip->i_diflags & XFS_DIFLAG_NODUMP) && 173 xfs_inherit_nodump) 174 di_flags |= XFS_DIFLAG_NODUMP; 175 if ((pip->i_diflags & XFS_DIFLAG_SYNC) && 176 xfs_inherit_sync) 177 di_flags |= XFS_DIFLAG_SYNC; 178 if ((pip->i_diflags & XFS_DIFLAG_NOSYMLINKS) && 179 xfs_inherit_nosymlinks) 180 di_flags |= XFS_DIFLAG_NOSYMLINKS; 181 if ((pip->i_diflags & XFS_DIFLAG_NODEFRAG) && 182 xfs_inherit_nodefrag) 183 di_flags |= XFS_DIFLAG_NODEFRAG; 184 if (pip->i_diflags & XFS_DIFLAG_FILESTREAM) 185 di_flags |= XFS_DIFLAG_FILESTREAM; 186 187 ip->i_diflags |= di_flags; 188 189 /* 190 * Inode verifiers on older kernels only check that the extent size 191 * hint is an integer multiple of the rt extent size on realtime files. 192 * They did not check the hint alignment on a directory with both 193 * rtinherit and extszinherit flags set. If the misaligned hint is 194 * propagated from a directory into a new realtime file, new file 195 * allocations will fail due to math errors in the rt allocator and/or 196 * trip the verifiers. Validate the hint settings in the new file so 197 * that we don't let broken hints propagate. 198 */ 199 failaddr = xfs_inode_validate_extsize(ip->i_mount, ip->i_extsize, 200 VFS_I(ip)->i_mode, ip->i_diflags); 201 if (failaddr) { 202 ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE | 203 XFS_DIFLAG_EXTSZINHERIT); 204 ip->i_extsize = 0; 205 } 206 } 207 208 /* Propagate di_flags2 from a parent inode to a child inode. */ 209 static inline void 210 xfs_inode_inherit_flags2( 211 struct xfs_inode *ip, 212 const struct xfs_inode *pip) 213 { 214 xfs_failaddr_t failaddr; 215 216 if (pip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) { 217 ip->i_diflags2 |= XFS_DIFLAG2_COWEXTSIZE; 218 ip->i_cowextsize = pip->i_cowextsize; 219 } 220 if (pip->i_diflags2 & XFS_DIFLAG2_DAX) 221 ip->i_diflags2 |= XFS_DIFLAG2_DAX; 222 223 /* Don't let invalid cowextsize hints propagate. */ 224 failaddr = xfs_inode_validate_cowextsize(ip->i_mount, ip->i_cowextsize, 225 VFS_I(ip)->i_mode, ip->i_diflags, ip->i_diflags2); 226 if (failaddr) { 227 ip->i_diflags2 &= ~XFS_DIFLAG2_COWEXTSIZE; 228 ip->i_cowextsize = 0; 229 } 230 } 231 232 /* Initialise an inode's attributes. */ 233 void 234 xfs_inode_init( 235 struct xfs_trans *tp, 236 const struct xfs_icreate_args *args, 237 struct xfs_inode *ip) 238 { 239 struct xfs_inode *pip = args->pip; 240 struct inode *dir = pip ? VFS_I(pip) : NULL; 241 struct xfs_mount *mp = tp->t_mountp; 242 struct inode *inode = VFS_I(ip); 243 unsigned int flags; 244 int times = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG | 245 XFS_ICHGTIME_ACCESS; 246 247 if (args->flags & XFS_ICREATE_TMPFILE) 248 set_nlink(inode, 0); 249 else if (S_ISDIR(args->mode)) 250 set_nlink(inode, 2); 251 else 252 set_nlink(inode, 1); 253 inode->i_rdev = args->rdev; 254 255 if (!args->idmap || pip == NULL) { 256 /* creating a tree root, sb rooted, or detached file */ 257 inode->i_uid = GLOBAL_ROOT_UID; 258 inode->i_gid = GLOBAL_ROOT_GID; 259 ip->i_projid = 0; 260 inode->i_mode = args->mode; 261 } else { 262 /* creating a child in the directory tree */ 263 if (dir && !(dir->i_mode & S_ISGID) && xfs_has_grpid(mp)) { 264 inode_fsuid_set(inode, args->idmap); 265 inode->i_gid = dir->i_gid; 266 inode->i_mode = args->mode; 267 } else { 268 inode_init_owner(args->idmap, inode, dir, args->mode); 269 } 270 271 /* 272 * If the group ID of the new file does not match the effective 273 * group ID or one of the supplementary group IDs, the S_ISGID 274 * bit is cleared (and only if the irix_sgid_inherit 275 * compatibility variable is set). 276 */ 277 if (irix_sgid_inherit && (inode->i_mode & S_ISGID) && 278 !vfsgid_in_group_p(i_gid_into_vfsgid(args->idmap, inode))) 279 inode->i_mode &= ~S_ISGID; 280 281 ip->i_projid = pip ? xfs_get_initial_prid(pip) : 0; 282 } 283 284 ip->i_disk_size = 0; 285 ip->i_df.if_nextents = 0; 286 ASSERT(ip->i_nblocks == 0); 287 288 ip->i_extsize = 0; 289 ip->i_diflags = 0; 290 291 if (xfs_has_v3inodes(mp)) { 292 inode_set_iversion(inode, 1); 293 ip->i_cowextsize = 0; 294 times |= XFS_ICHGTIME_CREATE; 295 } 296 297 xfs_trans_ichgtime(tp, ip, times); 298 299 flags = XFS_ILOG_CORE; 300 switch (args->mode & S_IFMT) { 301 case S_IFIFO: 302 case S_IFCHR: 303 case S_IFBLK: 304 case S_IFSOCK: 305 ip->i_df.if_format = XFS_DINODE_FMT_DEV; 306 flags |= XFS_ILOG_DEV; 307 break; 308 case S_IFREG: 309 case S_IFDIR: 310 if (pip && (pip->i_diflags & XFS_DIFLAG_ANY)) 311 xfs_inode_inherit_flags(ip, pip); 312 if (pip && (pip->i_diflags2 & XFS_DIFLAG2_ANY)) 313 xfs_inode_inherit_flags2(ip, pip); 314 fallthrough; 315 case S_IFLNK: 316 ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS; 317 ip->i_df.if_bytes = 0; 318 ip->i_df.if_data = NULL; 319 break; 320 default: 321 ASSERT(0); 322 } 323 324 /* 325 * If we need to create attributes immediately after allocating the 326 * inode, initialise an empty attribute fork right now. We use the 327 * default fork offset for attributes here as we don't know exactly what 328 * size or how many attributes we might be adding. We can do this 329 * safely here because we know the data fork is completely empty and 330 * this saves us from needing to run a separate transaction to set the 331 * fork offset in the immediate future. 332 */ 333 if (args->flags & XFS_ICREATE_INIT_XATTRS) { 334 ip->i_forkoff = xfs_default_attroffset(ip) >> 3; 335 xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0); 336 337 if (!xfs_has_attr(mp)) { 338 spin_lock(&mp->m_sb_lock); 339 xfs_add_attr(mp); 340 spin_unlock(&mp->m_sb_lock); 341 xfs_log_sb(tp); 342 } 343 } 344 345 xfs_trans_log_inode(tp, ip, flags); 346 } 347