summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2020-02-19 17:02:45 -0800
committerDarrick J. Wong <darrick.wong@oracle.com>2020-03-03 18:47:51 -0800
commitad3c9b1c4494052a22d4244da780b45b578474db (patch)
tree85d1c0a0fc2a7d1678882160147047cbc76507c2
parent087352cc5679cf42ed5a1e4d27d2a0a1e6e876cb (diff)
xfs: disable the agi rotor for metadata inodes
Ideally, we'd put all the metadata inodes in one place if we could, so that the metadata all stay reasonably close together instead of spreading out over the disk. Furthermore, if the log is internal we'd probably prefer to keep the metadata near the log. Therefore, disable AGI rotoring for metadata inode allocations. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c48
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.h10
-rw-r--r--fs/xfs/libxfs/xfs_inode_util.c3
3 files changed, 37 insertions, 24 deletions
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 6740771f0ff5..e349c2d7a860 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -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 @@ error_cur:
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;
diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h
index 632f8ed0a228..cc854fea047b 100644
--- a/fs/xfs/libxfs/xfs_ialloc.h
+++ b/fs/xfs/libxfs/xfs_ialloc.h
@@ -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
diff --git a/fs/xfs/libxfs/xfs_inode_util.c b/fs/xfs/libxfs/xfs_inode_util.c
index f7cf64c2dee8..a2af152fecec 100644
--- a/fs/xfs/libxfs/xfs_inode_util.c
+++ b/fs/xfs/libxfs/xfs_inode_util.c
@@ -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) {