@@ -73,28 +73,17 @@ xfs_inode_inherit_flags2(
ip->i_diflags2 |= XFS_DIFLAG2_DAX;
}
-/*
- * 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_inode *pip = args->pip;
- struct xfs_inode *ip;
unsigned int flags;
int times = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG |
XFS_ICHGTIME_ACCESS;
- int error;
-
- error = libxfs_iget(tp->t_mountp, tp, ino, 0, &ip);
- if (error != 0)
- return error;
- ASSERT(ip != NULL);
VFS_I(ip)->i_mode = args->mode;
set_nlink(VFS_I(ip), args->nlink);
@@ -154,7 +143,28 @@ libxfs_icreate(
*/
xfs_trans_ijoin(tp, ip, 0);
xfs_trans_log_inode(tp, ip, flags);
- *ipp = ip;
+}
+
+/*
+ * 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;
+ int error;
+
+ error = libxfs_iget(mp, tp, ino, 0, ipp);
+ if (error)
+ return error;
+
+ ASSERT(*ipp != NULL);
+ xfs_inode_init(tp, args, *ipp);
return 0;
}
@@ -1865,9 +1865,25 @@ xfs_dialloc(
}
xfs_perag_put(pag);
}
+ if (error)
+ goto out;
- if (!error)
- *new_ino = ino;
+ /*
+ * 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_ag_mark_sick(pag, XFS_SICK_AG_INOBT);
+ error = -EFSCORRUPTED;
+ goto out;
+ }
+
+ *new_ino = ino;
+out:
xfs_perag_put(pag);
return error;
}