Source kernel commit:
712bae96631852c1a1822ee4f57a08ccd843358b
xfs_{add,dec}_freecounter already handles the block and RT extent
percpu counters, but it currently hardcodes the passed in counter.
Add a freecounter abstraction that uses an enum to designate the counter
and add wrappers that hide the actual percpu_counters. This will allow
expanding the reserved block handling to the RT extent counter in the
next step, and also prepares for adding yet another such counter that
can share the code. Both these additions will be needed for the zoned
allocator.
Also switch the flooring of the frextents counter to 0 in statfs for the
rthinherit case to a manual min_t call to match the handling of the
fdblocks counter for normal file systems.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
xfs_sb_t m_sb; /* copy of fs superblock */
#define m_icount m_sb.sb_icount
#define m_ifree m_sb.sb_ifree
-#define m_fdblocks m_sb.sb_fdblocks
-#define m_frextents m_sb.sb_frextents
spinlock_t m_sb_lock;
/*
__XFS_UNSUPP_OPSTATE(readonly)
__XFS_UNSUPP_OPSTATE(shutdown)
+static inline int64_t xfs_sum_freecounter(struct xfs_mount *mp,
+ enum xfs_free_counter ctr)
+{
+ if (ctr == XC_FREE_RTEXTENTS)
+ return mp->m_sb.sb_frextents;
+ return mp->m_sb.sb_fdblocks;
+}
+
+static inline int64_t xfs_estimate_freecounter(struct xfs_mount *mp,
+ enum xfs_free_counter ctr)
+{
+ return xfs_sum_freecounter(mp, ctr);
+}
+
+static inline int xfs_compare_freecounter(struct xfs_mount *mp,
+ enum xfs_free_counter ctr, int64_t rhs, int32_t batch)
+{
+ uint64_t count;
+
+ if (ctr == XC_FREE_RTEXTENTS)
+ count = mp->m_sb.sb_frextents;
+ else
+ count = mp->m_sb.sb_fdblocks;
+ if (count > rhs)
+ return 1;
+ else if (count < rhs)
+ return -1;
+ return 0;
+}
+
/* don't fail on device size or AG count checks */
#define LIBXFS_MOUNT_DEBUGGER (1U << 0)
/* report metadata corruption to stdout */
}
#define WARN_ON_ONCE(e) WARN_ON(e)
-#define percpu_counter_read(x) (*x)
+
#define percpu_counter_read_positive(x) ((*x) > 0 ? (*x) : 0)
#define percpu_counter_sum_positive(x) ((*x) > 0 ? (*x) : 0)
#define get_random_u32() (0)
#endif
-static inline int
-__percpu_counter_compare(uint64_t *count, int64_t rhs, int32_t batch)
-{
- if (*count > rhs)
- return 1;
- else if (*count < rhs)
- return -1;
- return 0;
-}
-
-
#define PAGE_SIZE getpagesize()
extern unsigned int PAGE_SHIFT;
* that we can immediately allocate, but then we allow allocation on the
* second pass if we fail to find an AG with free inodes in it.
*/
- if (percpu_counter_read_positive(&mp->m_fdblocks) <
+ if (xfs_estimate_freecounter(mp, XC_FREE_BLOCKS) <
mp->m_low_space[XFS_LOWSP_1_PCNT]) {
ok_alloc = false;
low_space = true;
* There aren't enough blocks left in the inode's reservation, but it
* isn't critical unless there also isn't enough free space.
*/
- return __percpu_counter_compare(&ip->i_mount->m_fdblocks,
+ return xfs_compare_freecounter(ip->i_mount, XC_FREE_BLOCKS,
rhs - ip->i_delayed_blks, 2048) >= 0;
}
mp->m_sb.sb_ifree = min_t(uint64_t,
percpu_counter_sum_positive(&mp->m_ifree),
mp->m_sb.sb_icount);
- mp->m_sb.sb_fdblocks =
- percpu_counter_sum_positive(&mp->m_fdblocks);
+ mp->m_sb.sb_fdblocks = xfs_sum_freecounter(mp, XC_FREE_BLOCKS);
}
/*
* we handle nearly-lockless reservations, so we must use the _positive
* variant here to avoid writing out nonsense frextents.
*/
- if (xfs_has_rtgroups(mp))
+ if (xfs_has_rtgroups(mp)) {
mp->m_sb.sb_frextents =
- percpu_counter_sum_positive(&mp->m_frextents);
+ xfs_sum_freecounter(mp, XC_FREE_RTEXTENTS);
+ }
xfs_sb_to_disk(bp->b_addr, &mp->m_sb);
xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);
{ XG_TYPE_AG, "ag" }, \
{ XG_TYPE_RTG, "rtg" }
+enum xfs_free_counter {
+ /*
+ * Number of free blocks on the data device.
+ */
+ XC_FREE_BLOCKS,
+
+ /*
+ * Number of free RT extents on the RT device.
+ */
+ XC_FREE_RTEXTENTS,
+ XC_FREE_NR,
+};
+
+#define XFS_FREECOUNTER_STR \
+ { XC_FREE_BLOCKS, "blocks" }, \
+ { XC_FREE_RTEXTENTS, "rtextents" }
+
/*
* Type verifier functions
*/