xfs: separate the icreate logic around INIT_XATTRS

INIT_XATTRS is overloaded here -- it's set during the creat process when
we think that we're immediately going to set some ACL xattrs to save
time.  However, it's also used by the parent pointers code to enable the
attr fork in preparation to receive ppptr xattrs.  This results in
xfs_has_parent() branches scattered around the codebase to turn on
INIT_XATTRS.

Linkable files are created far more commonly than unlinkable temporary
files or directory tree roots, so we should centralize this logic in
xfs_inode_init.  For the three callers that don't want parent pointers
(online repiar tempfiles, unlinkable tempfiles, rootdir creation) we
provide an UNLINKABLE flag to skip attr fork initialization.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Darrick J. Wong 2024-07-02 11:22:41 -07:00
parent a9e583d34f
commit b11b11e3b7
7 changed files with 33 additions and 24 deletions

View File

@ -233,6 +233,31 @@ xfs_inode_inherit_flags2(
}
}
/*
* If we need to create attributes immediately after allocating the inode,
* initialise an empty attribute fork right now. We use the default fork offset
* for attributes here as we don't know exactly what size or how many
* attributes we might be adding. We can do this safely here because we know
* the data fork is completely empty and this saves us from needing to run a
* separate transaction to set the fork offset in the immediate future.
*
* If we have parent pointers and the caller hasn't told us that the file will
* never be linked into a directory tree, we /must/ create the attr fork.
*/
static inline bool
xfs_icreate_want_attrfork(
struct xfs_mount *mp,
const struct xfs_icreate_args *args)
{
if (args->flags & XFS_ICREATE_INIT_XATTRS)
return true;
if (!(args->flags & XFS_ICREATE_UNLINKABLE) && xfs_has_parent(mp))
return true;
return false;
}
/* Initialise an inode's attributes. */
void
xfs_inode_init(
@ -325,16 +350,7 @@ xfs_inode_init(
ASSERT(0);
}
/*
* If we need to create attributes immediately after allocating the
* inode, initialise an empty attribute fork right now. We use the
* default fork offset for attributes here as we don't know exactly what
* size or how many attributes we might be adding. We can do this
* safely here because we know the data fork is completely empty and
* this saves us from needing to run a separate transaction to set the
* fork offset in the immediate future.
*/
if (args->flags & XFS_ICREATE_INIT_XATTRS) {
if (xfs_icreate_want_attrfork(mp, args)) {
ip->i_forkoff = xfs_default_attroffset(ip) >> 3;
xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0);

View File

@ -32,6 +32,7 @@ struct xfs_icreate_args {
#define XFS_ICREATE_TMPFILE (1U << 0) /* create an unlinked file */
#define XFS_ICREATE_INIT_XATTRS (1U << 1) /* will set xattrs immediately */
#define XFS_ICREATE_UNLINKABLE (1U << 2) /* cannot link into dir tree */
uint16_t flags;
};

View File

@ -43,7 +43,7 @@ xrep_tempfile_create(
struct xfs_icreate_args args = {
.pip = sc->mp->m_rootip,
.mode = mode,
.flags = XFS_ICREATE_TMPFILE,
.flags = XFS_ICREATE_TMPFILE | XFS_ICREATE_UNLINKABLE,
};
struct xfs_mount *mp = sc->mp;
struct xfs_trans *tp = NULL;

View File

@ -2527,9 +2527,6 @@ xfs_rename_alloc_whiteout(
struct qstr name;
int error;
if (xfs_has_parent(dp->i_mount))
args.flags |= XFS_ICREATE_INIT_XATTRS;
error = xfs_create_tmpfile(&args, &tmpfile);
if (error)
return error;

View File

@ -158,8 +158,6 @@ xfs_create_need_xattr(
if (dir->i_sb->s_security)
return true;
#endif
if (xfs_has_parent(XFS_I(dir)->i_mount))
return true;
return false;
}
@ -215,12 +213,11 @@ xfs_generic_create(
args.flags |= XFS_ICREATE_TMPFILE;
/*
* If this temporary file will be linkable, set up the file
* with an attr fork to receive a parent pointer.
* If this temporary file will not be linkable, don't bother
* creating an attr fork to receive a parent pointer.
*/
if (!(tmpfile->f_flags & O_EXCL) &&
xfs_has_parent(XFS_I(dir)->i_mount))
args.flags |= XFS_ICREATE_INIT_XATTRS;
if (tmpfile->f_flags & O_EXCL)
args.flags |= XFS_ICREATE_UNLINKABLE;
error = xfs_create_tmpfile(&args, &ip);
}

View File

@ -795,6 +795,7 @@ xfs_qm_qino_alloc(
if (need_alloc) {
struct xfs_icreate_args args = {
.mode = S_IFREG,
.flags = XFS_ICREATE_UNLINKABLE,
};
xfs_ino_t ino;

View File

@ -115,9 +115,6 @@ xfs_symlink(
if (xfs_is_shutdown(mp))
return -EIO;
if (xfs_has_parent(mp))
args.flags |= XFS_ICREATE_INIT_XATTRS;
/*
* Check component lengths of the target path name.
*/