]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: rmap btree add more reserved blocks
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 10 Aug 2016 01:42:20 +0000 (11:42 +1000)
committerDave Chinner <david@fromorbit.com>
Wed, 10 Aug 2016 01:42:20 +0000 (11:42 +1000)
Source kernel commit: 8018026ef29756af6144e2e2e8dffc9c2ed0d6f7

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>
include/xfs_mount.h
libxfs/init.c
libxfs/xfs_alloc.c
libxfs/xfs_alloc.h
libxfs/xfs_format.h
mkfs/xfs_mkfs.c

index 14b05a6d0f3cbf959fde8953cade2a96ebf9b7e6..2c7c72ea9bf20a2507beeca7d09c7c08860f38cb 100644 (file)
@@ -67,6 +67,7 @@ typedef struct xfs_mount {
        uint                    m_ag_maxlevels; /* XFS_AG_MAXLEVELS */
        uint                    m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */
        uint                    m_in_maxlevels; /* XFS_IN_MAXLEVELS */
+       xfs_extlen_t            m_ag_prealloc_blocks; /* reserved ag blocks */
        struct radix_tree_root  m_perag_tree;
        uint                    m_flags;        /* global mount flags */
        uint                    m_qflags;       /* quota status flags */
index 8df29e783f8e467a97b21a7900d98d7b6007eaae..61ac80395a386d8a9d32f23c755a3c9f78b93014 100644 (file)
@@ -570,6 +570,8 @@ libxfs_initialize_perag(
 
        if (maxagi)
                *maxagi = index;
+
+       mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp);
        return 0;
 
 out_unwind:
index ee2fca1991f2fd1b25f8dba7855d42cd02997ad7..7bbd2e3972b624fc55529e529c3b6f6460db2f27 100644 (file)
@@ -46,6 +46,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 3260df8cd094ab93658ca6f88c1fdbaae8932350..9fc83bda948f36f6e7a27249a3604c33783f796a 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 8b02983198ec53bfaf4426333cceb13529308052..0852a5344b2a364295ed8a683c8a3894c1eaf710 100644 (file)
@@ -2643,7 +2643,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 
        /*
         * sb_versionnum and finobt flags must be set before we use
-        * XFS_PREALLOC_BLOCKS().
+        * xfs_prealloc_blocks().
         */
        sb_set_features(&mp->m_sb, &sb_feat, sectorsize, lsectorsize, dsunit);
 
@@ -2660,7 +2660,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
                        /* revalidate the log size is valid if we changed it */
                        validate_log_size(logblocks, blocklog, min_logblocks);
                }
-               if (logblocks > agsize - XFS_PREALLOC_BLOCKS(mp)) {
+               if (logblocks > agsize - xfs_prealloc_blocks(mp)) {
                        fprintf(stderr,
        _("internal log size %lld too large, must fit in allocation group\n"),
                                (long long)logblocks);
@@ -2677,7 +2677,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
                } else
                        logagno = (xfs_agnumber_t)(agcount / 2);
 
-               logstart = XFS_AGB_TO_FSB(mp, logagno, XFS_PREALLOC_BLOCKS(mp));
+               logstart = XFS_AGB_TO_FSB(mp, logagno, xfs_prealloc_blocks(mp));
                /*
                 * Align the logstart at stripe unit boundary.
                 */
@@ -2755,7 +2755,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
        sbp->sb_imax_pct = imaxpct;
        sbp->sb_icount = 0;
        sbp->sb_ifree = 0;
-       sbp->sb_fdblocks = dblocks - agcount * XFS_PREALLOC_BLOCKS(mp) -
+       sbp->sb_fdblocks = dblocks - agcount * xfs_prealloc_blocks(mp) -
                (loginternal ? logblocks : 0);
        sbp->sb_frextents = 0;  /* will do a free later */
        sbp->sb_uquotino = sbp->sb_gquotino = sbp->sb_pquotino = 0;
@@ -2897,7 +2897,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
                agf->agf_flfirst = 0;
                agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1);
                agf->agf_flcount = 0;
-               nbmblocks = (xfs_extlen_t)(agsize - XFS_PREALLOC_BLOCKS(mp));
+               nbmblocks = (xfs_extlen_t)(agsize - xfs_prealloc_blocks(mp));
                agf->agf_freeblks = cpu_to_be32(nbmblocks);
                agf->agf_longest = cpu_to_be32(nbmblocks);
                if (xfs_sb_version_hascrc(&mp->m_sb))
@@ -2978,7 +2978,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
                                                agno, 0);
 
                arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
-               arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
+               arec->ar_startblock = cpu_to_be32(xfs_prealloc_blocks(mp));
                if (loginternal && agno == logagno) {
                        if (lalign) {
                                /*
@@ -3033,7 +3033,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
                                                agno, 0);
 
                arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
-               arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
+               arec->ar_startblock = cpu_to_be32(xfs_prealloc_blocks(mp));
                if (loginternal && agno == logagno) {
                        if (lalign) {
                                arec->ar_blockcount = cpu_to_be32(