@@ -943,20 +943,21 @@ xfs_ialloc_next_ag(
*/
STATIC xfs_agnumber_t
xfs_ialloc_ag_select(
- xfs_trans_t *tp, /* transaction pointer */
- xfs_ino_t parent, /* parent directory inode number */
- umode_t mode) /* bits set to indicate file type */
+ struct xfs_trans *tp,
+ struct xfs_inode *pip,
+ umode_t mode)
{
- xfs_agnumber_t agcount; /* number of ag's in the filesystem */
- xfs_agnumber_t agno; /* current ag number */
- int flags; /* alloc buffer locking flags */
- xfs_extlen_t ineed; /* blocks needed for inode allocation */
- xfs_extlen_t longest = 0; /* longest extent available */
- xfs_mount_t *mp; /* mount point structure */
- int needspace; /* file mode implies space allocated */
- xfs_perag_t *pag; /* per allocation group data */
- xfs_agnumber_t pagno; /* parent (starting) ag number */
- int error;
+ struct xfs_mount *mp;
+ struct xfs_perag *pag;
+ xfs_ino_t parent = pip ? pip->i_ino : 0;
+ xfs_agnumber_t agcount;
+ xfs_agnumber_t agno;
+ xfs_agnumber_t pagno;
+ xfs_extlen_t ineed;
+ xfs_extlen_t longest = 0; /* longest extent available */
+ int needspace; /* file mode implies space allocated */
+ int flags;
+ int error;
/*
* Files of these types need at least one block if length > 0
@@ -965,9 +966,21 @@ xfs_ialloc_ag_select(
needspace = S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode);
mp = tp->t_mountp;
agcount = mp->m_maxagi;
- if (S_ISDIR(mode))
+ if (pip && xfs_is_metadata_inode(pip)) {
+ /*
+ * Try to squash all the metadata inodes into the parent's
+ * AG, or the one with the log if the log is internal, or
+ * AG 0 if all else fails.
+ */
+ if (xfs_verify_ino(mp, parent))
+ pagno = XFS_INO_TO_AGNO(mp, parent);
+ else if (mp->m_sb.sb_logstart != 0)
+ pagno = XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart);
+ else
+ pagno = 0;
+ } else if (S_ISDIR(mode)) {
pagno = xfs_ialloc_next_ag(mp);
- else {
+ } else {
pagno = XFS_INO_TO_AGNO(mp, parent);
if (pagno >= agcount)
pagno = 0;
@@ -1755,13 +1768,14 @@ xfs_dialloc_ag(
int
xfs_dialloc(
struct xfs_trans *tp,
- xfs_ino_t parent,
+ struct xfs_inode *pip,
umode_t mode,
struct xfs_buf **IO_agbp,
xfs_ino_t *inop)
{
struct xfs_mount *mp = tp->t_mountp;
struct xfs_buf *agbp;
+ xfs_ino_t parent = pip ? pip->i_ino : 0;
xfs_agnumber_t agno;
int error;
int ialloced;
@@ -1785,7 +1799,7 @@ xfs_dialloc(
* We do not have an agbp, so select an initial allocation
* group for inode allocation.
*/
- start_agno = xfs_ialloc_ag_select(tp, parent, mode);
+ start_agno = xfs_ialloc_ag_select(tp, pip, mode);
if (start_agno == NULLAGNUMBER) {
*inop = NULLFSINO;
return 0;
@@ -56,11 +56,11 @@ xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o)
*/
int /* error */
xfs_dialloc(
- struct xfs_trans *tp, /* transaction pointer */
- xfs_ino_t parent, /* parent inode (directory) */
- umode_t mode, /* mode bits for new inode */
- struct xfs_buf **agbp, /* buf for a.g. inode header */
- xfs_ino_t *inop); /* inode number allocated */
+ struct xfs_trans *tp, /* transaction pointer */
+ struct xfs_inode *pip, /* parent inode (directory) */
+ umode_t mode, /* mode bits for new inode */
+ struct xfs_buf **agbp, /* buf for a.g. inode header */
+ xfs_ino_t *inop); /* inode number allocated */
/*
* Free disk inode. Carefully avoids touching the incore inode, all
@@ -350,8 +350,7 @@ xfs_ialloc(
* Call the space management code to pick
* the on-disk inode to be allocated.
*/
- error = xfs_dialloc(tp, pip ? pip->i_ino : 0, args->mode,
- ialloc_context, &ino);
+ error = xfs_dialloc(tp, pip, args->mode, ialloc_context, &ino);
if (error)
return error;
if (*ialloc_context || ino == NULLFSINO) {