spinlock_t i_lock;
};
+static inline void
+inode_set_iversion(struct inode *inode, uint64_t version)
+{
+ inode->i_version = version;
+}
+
static inline uint32_t i_uid_read(struct inode *inode)
{
return inode->i_uid.val;
inode->i_gid.val = gid;
}
+static inline void inode_fsuid_set(struct inode *inode,
+ struct mnt_idmap *idmap)
+{
+ inode->i_uid = make_kuid(0);
+}
+
+static inline void inode_fsgid_set(struct inode *inode,
+ struct mnt_idmap *idmap)
+{
+ inode->i_gid = make_kgid(0);
+}
+
static inline void ihold(struct inode *inode)
{
inode->i_count++;
#define XFS_DEFAULT_COWEXTSZ_HINT 32
+#define XFS_INHERIT_GID(pip) (VFS_I(pip)->i_mode & S_ISGID)
+
#endif /* __XFS_INODE_H__ */
/* Propagate di_flags from a parent inode to a child inode. */
static void
-xfs_inode_propagate_flags(
+xfs_inode_inherit_flags(
struct xfs_inode *ip,
const struct xfs_inode *pip)
{
int times = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG |
XFS_ICHGTIME_ACCESS;
- inode->i_mode = args->mode;
if (args->flags & XFS_ICREATE_TMPFILE)
set_nlink(inode, 0);
else if (S_ISDIR(args->mode))
set_nlink(inode, 2);
else
set_nlink(inode, 1);
- inode->i_uid = GLOBAL_ROOT_UID;
- inode->i_gid = GLOBAL_ROOT_GID;
- ip->i_projid = 0;
+ inode->i_rdev = args->rdev;
+
+ if (!args->idmap || pip == NULL) {
+ /* creating a tree root, sb rooted, or detached file */
+ inode->i_uid = GLOBAL_ROOT_UID;
+ inode->i_gid = GLOBAL_ROOT_GID;
+ ip->i_projid = 0;
+ inode->i_mode = args->mode;
+ } else {
+ /* creating a child in the directory tree */
+ if (dir && !(dir->i_mode & S_ISGID) && xfs_has_grpid(mp)) {
+ inode_fsuid_set(inode, args->idmap);
+ inode->i_gid = dir->i_gid;
+ inode->i_mode = args->mode;
+ } else {
+ inode_init_owner(args->idmap, inode, dir, args->mode);
+ }
- if (pip && (dir->i_mode & S_ISGID)) {
- inode->i_gid = dir->i_gid;
- if (S_ISDIR(args->mode))
- inode->i_mode |= S_ISGID;
+ /*
+ * If the group ID of the new file does not match the effective
+ * group ID or one of the supplementary group IDs, the S_ISGID
+ * bit is cleared (and only if the irix_sgid_inherit
+ * compatibility variable is set).
+ */
+ if (irix_sgid_inherit && (inode->i_mode & S_ISGID) &&
+ !vfsgid_in_group_p(i_gid_into_vfsgid(args->idmap, inode)))
+ inode->i_mode &= ~S_ISGID;
+
+ ip->i_projid = pip ? xfs_get_initial_prid(pip) : 0;
}
- if (pip)
- ip->i_projid = libxfs_get_initial_prid(pip);
-
ip->i_disk_size = 0;
ip->i_df.if_nextents = 0;
ASSERT(ip->i_nblocks == 0);
+
ip->i_extsize = 0;
ip->i_diflags = 0;
- if (xfs_has_v3inodes(ip->i_mount)) {
- inode->i_version = 1;
- ip->i_diflags2 = ip->i_mount->m_ino_geo.new_diflags2;
+ if (xfs_has_v3inodes(mp)) {
+ inode_set_iversion(inode, 1);
ip->i_cowextsize = 0;
times |= XFS_ICHGTIME_CREATE;
}
case S_IFBLK:
ip->i_df.if_format = XFS_DINODE_FMT_DEV;
flags |= XFS_ILOG_DEV;
- VFS_I(ip)->i_rdev = args->rdev;
break;
case S_IFREG:
case S_IFDIR:
if (pip && (pip->i_diflags & XFS_DIFLAG_ANY))
- xfs_inode_propagate_flags(ip, pip);
+ xfs_inode_inherit_flags(ip, pip);
if (pip && (pip->i_diflags2 & XFS_DIFLAG2_ANY))
xfs_inode_inherit_flags2(ip, pip);
- /* FALLTHROUGH */
+ fallthrough;
case S_IFLNK:
ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
ip->i_df.if_bytes = 0;
VFS_I(ip)->i_count = 1;
ip->i_ino = ino;
ip->i_mount = mp;
+ ip->i_diflags2 = mp->m_ino_geo.new_diflags2;
ip->i_af.if_format = XFS_DINODE_FMT_EXTENTS;
spin_lock_init(&VFS_I(ip)->i_lock);
kmem_cache_free(xfs_inode_cache, ip);
}
}
+
+void inode_init_owner(struct mnt_idmap *idmap, struct inode *inode,
+ const struct inode *dir, umode_t mode)
+{
+ inode_fsuid_set(inode, idmap);
+ if (dir && dir->i_mode & S_ISGID) {
+ inode->i_gid = dir->i_gid;
+
+ /* Directories are special, and always inherit S_ISGID */
+ if (S_ISDIR(mode))
+ mode |= S_ISGID;
+ } else
+ inode_fsgid_set(inode, idmap);
+ inode->i_mode = mode;
+}