xfs: rmap btree add more reserved blocks
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 3 Aug 2016 01:31:47 +0000 (11:31 +1000)
committerDave Chinner <david@fromorbit.com>
Wed, 3 Aug 2016 01:31:47 +0000 (11:31 +1000)
Originally-From: Dave Chinner <dchinner@redhat.com>

XFS reserves a small amount of space in each AG for the minimum
number of free blocks needed for operation. Adding the rmap btree
increases the number of reserved blocks, but it also increases the
complexity of the calculation as the free inode btree is optional
(like the rmbt).

Rather than calculate the prealloc blocks every time we need to
check it, add a function to calculate it at mount time and store it
in the struct xfs_mount, and convert the XFS_PREALLOC_BLOCKS macro
just to use the xfs-mount variable directly.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/libxfs/xfs_alloc.h
fs/xfs/libxfs/xfs_format.h
fs/xfs/xfs_fsops.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.h

index c02d8e8419ce52e4cf620bb412ba4c4d31f23610..43c7e53a6a8ee85a345730c49e097355593eabfb 100644 (file)
@@ -50,6 +50,17 @@ STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *);
 STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *,
                xfs_btree_cur_t *, xfs_agblock_t *, xfs_extlen_t *, int *);
 
+xfs_extlen_t
+xfs_prealloc_blocks(
+       struct xfs_mount        *mp)
+{
+       if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+               return XFS_RMAP_BLOCK(mp) + 1;
+       if (xfs_sb_version_hasfinobt(&mp->m_sb))
+               return XFS_FIBT_BLOCK(mp) + 1;
+       return XFS_IBT_BLOCK(mp) + 1;
+}
+
 /*
  * Lookup the record equal to [bno, len] in the btree given by cur.
  */
index cf268b2d0b6c2035aaad4b781d43e2cebeedcd54..20b54aa870266e234ca3ef868bc790eab5ef88c9 100644 (file)
@@ -232,4 +232,6 @@ int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags);
 int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno,
                struct xfs_buf **agbp);
 
+xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp);
+
 #endif /* __XFS_ALLOC_H__ */
index 74f4d3da598c6d7281b43cb237848256b7c924ce..3dbed011c29a4ee6936cc220b1c7701abb8b0345 100644 (file)
@@ -1319,18 +1319,11 @@ typedef __be32 xfs_inobt_ptr_t;
  */
 #define        XFS_RMAP_CRC_MAGIC      0x524d4233      /* 'RMB3' */
 
-/*
- * The first data block of an AG depends on whether the filesystem was formatted
- * with the finobt feature. If so, account for the finobt reserved root btree
- * block.
- */
-#define XFS_PREALLOC_BLOCKS(mp) \
+#define        XFS_RMAP_BLOCK(mp) \
        (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \
         XFS_FIBT_BLOCK(mp) + 1 : \
         XFS_IBT_BLOCK(mp) + 1)
 
-
-
 /*
  * BMAP Btree format definitions
  *
index 4c191d2194e82f36863ce7e61e67fae493b08b16..0a3b822d9f8c87fc77b22245921ccd473696f5a5 100644 (file)
@@ -243,7 +243,7 @@ xfs_growfs_data_private(
                agf->agf_flfirst = cpu_to_be32(1);
                agf->agf_fllast = 0;
                agf->agf_flcount = 0;
-               tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp);
+               tmpsize = agsize - mp->m_ag_prealloc_blocks;
                agf->agf_freeblks = cpu_to_be32(tmpsize);
                agf->agf_longest = cpu_to_be32(tmpsize);
                if (xfs_sb_version_hascrc(&mp->m_sb))
@@ -340,7 +340,7 @@ xfs_growfs_data_private(
                                                agno, 0);
 
                arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);
-               arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
+               arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks);
                arec->ar_blockcount = cpu_to_be32(
                        agsize - be32_to_cpu(arec->ar_startblock));
 
@@ -369,7 +369,7 @@ xfs_growfs_data_private(
                                                agno, 0);
 
                arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);
-               arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
+               arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks);
                arec->ar_blockcount = cpu_to_be32(
                        agsize - be32_to_cpu(arec->ar_startblock));
                nfree += be32_to_cpu(arec->ar_blockcount);
index 5f3ba88985d5e3ce666629be4543fdc7f352895c..24ae96b4078ff6a76e06d8cc9a1021ceb7a09a7d 100644 (file)
@@ -231,6 +231,8 @@ xfs_initialize_perag(
 
        if (maxagi)
                *maxagi = index;
+
+       mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp);
        return 0;
 
 out_unwind:
index c1b798c7212618462ee2130814eac8544c691bf0..0537b1f28f9032c2d58323594bd9f302b5c206bb 100644 (file)
@@ -119,6 +119,7 @@ typedef struct xfs_mount {
        uint                    m_ag_maxlevels; /* XFS_AG_MAXLEVELS */
        uint                    m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */
        uint                    m_in_maxlevels; /* max inobt btree levels. */
+       xfs_extlen_t            m_ag_prealloc_blocks; /* reserved ag blocks */
        struct radix_tree_root  m_perag_tree;   /* per-ag accounting info */
        spinlock_t              m_perag_lock;   /* lock for m_perag_tree */
        struct mutex            m_growlock;     /* growfs mutex */