From ab417ddaa574dc690de577a2240af3cb3599a30e Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 3 Jul 2024 14:21:34 -0700 Subject: [PATCH] xfs: split new inode creation into two pieces There are two parts to initializing a newly allocated inode: setting up the incore structures, and initializing the new inode core based on the parent inode and the current user's environment. The initialization code is not specific to the kernel, so we would like to share that with userspace by hoisting it to libxfs. Therefore, split xfs_icreate into separate functions to prepare for the next few patches. Signed-off-by: Darrick J. Wong --- libxfs/inode.c | 51 ++++++++++++++++++++++++++------------------- libxfs/xfs_ialloc.c | 15 +++++++++++++ 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/libxfs/inode.c b/libxfs/inode.c index 3e72b25cc..206b779a8 100644 --- a/libxfs/inode.c +++ b/libxfs/inode.c @@ -91,33 +91,21 @@ libxfs_bumplink( xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); } -/* - * Initialise a newly allocated inode and return the in-core inode to the - * caller locked exclusively. - */ -static int -libxfs_icreate( +/* Initialise an inode's attributes. */ +static void +xfs_inode_init( struct xfs_trans *tp, - xfs_ino_t ino, const struct xfs_icreate_args *args, - struct xfs_inode **ipp) + struct xfs_inode *ip) { struct xfs_mount *mp = tp->t_mountp; struct xfs_inode *pip = args->pip; struct inode *dir = pip ? VFS_I(pip) : NULL; - struct inode *inode; - struct xfs_inode *ip; + struct inode *inode = VFS_I(ip); unsigned int flags; int times = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG | XFS_ICHGTIME_ACCESS; - int error; - - error = libxfs_iget(mp, tp, ino, XFS_IGET_CREATE, &ip); - if (error != 0) - return error; - ASSERT(ip != NULL); - inode = VFS_I(ip); inode->i_mode = args->mode; if (args->flags & XFS_ICREATE_TMPFILE) set_nlink(inode, 0); @@ -201,11 +189,32 @@ libxfs_icreate( } } - /* - * Log the new values stuffed into the inode. - */ - xfs_trans_ijoin(tp, ip, 0); xfs_trans_log_inode(tp, ip, flags); +} + +/* + * Initialise a newly allocated inode and return the in-core inode to the + * caller locked exclusively. + */ +static int +libxfs_icreate( + struct xfs_trans *tp, + xfs_ino_t ino, + const struct xfs_icreate_args *args, + struct xfs_inode **ipp) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_inode *ip = NULL; + int error; + + error = libxfs_iget(mp, tp, ino, XFS_IGET_CREATE, &ip); + if (error) + return error; + + ASSERT(ip != NULL); + xfs_trans_ijoin(tp, ip, 0); + xfs_inode_init(tp, args, ip); + *ipp = ip; return 0; } diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c index d8697561e..cef2819aa 100644 --- a/libxfs/xfs_ialloc.c +++ b/libxfs/xfs_ialloc.c @@ -1941,6 +1941,21 @@ retry: } return -ENOSPC; } + + /* + * Protect against obviously corrupt allocation btree records. Later + * xfs_iget checks will catch re-allocation of other active in-memory + * and on-disk inodes. If we don't catch reallocating the parent inode + * here we will deadlock in xfs_iget() so we have to do these checks + * first. + */ + if (ino == parent || !xfs_verify_dir_ino(mp, ino)) { + xfs_alert(mp, "Allocated a known in-use inode 0x%llx!", ino); + xfs_agno_mark_sick(mp, XFS_INO_TO_AGNO(mp, ino), + XFS_SICK_AG_INOBT); + return -EFSCORRUPTED; + } + *new_ino = ino; return 0; } -- 2.50.1