]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: create incore realtime group structures
authorDarrick J. Wong <djwong@kernel.org>
Mon, 25 Nov 2024 21:14:18 +0000 (13:14 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 24 Dec 2024 02:01:28 +0000 (18:01 -0800)
Source kernel commit: 87fe4c34a383d51ec75f254240bcd08828f4ce5a

Create an incore object that will contain information about a realtime
allocation group.  This will eventually enable us to shard the realtime
section in a similar manner to how we shard the data section, but for
now just a single object for the entire RT subvolume is created.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
17 files changed:
db/block.h
db/convert.c
db/faddr.c
include/libxfs.h
include/platform_defs.h
include/xfs_mount.h
include/xfs_trace.h
libxfs/Makefile
libxfs/init.c
libxfs/libxfs_api_defs.h
libxfs/libxfs_priv.h
libxfs/xfs_format.h
libxfs/xfs_rtgroup.c [new file with mode: 0644]
libxfs/xfs_rtgroup.h [new file with mode: 0644]
libxfs/xfs_sb.c
libxfs/xfs_types.h
mkfs/xfs_mkfs.c

index 55843a6b521393884a47c47eab2ef08360232850..ed13e1590644610370961d113d38bba11eaba40f 100644 (file)
@@ -11,20 +11,4 @@ struct field;
 extern void    block_init(void);
 extern void    print_block(const struct field *fields, int argc, char **argv);
 
-static inline xfs_daddr_t
-xfs_rtb_to_daddr(
-       struct xfs_mount        *mp,
-       xfs_rtblock_t           rtb)
-{
-       return rtb << mp->m_blkbb_log;
-}
-
-static inline xfs_rtblock_t
-xfs_daddr_to_rtb(
-       struct xfs_mount        *mp,
-       xfs_daddr_t             daddr)
-{
-       return daddr >> mp->m_blkbb_log;
-}
-
 #endif /* __XFS_DB_BLOCK_H */
index 3014367e7d7652ca82a39ac78d181cbe8555897b..0c5c942150fe6fb9c5a8b701e774ca93d16b08d7 100644 (file)
@@ -8,7 +8,6 @@
 #include "command.h"
 #include "output.h"
 #include "init.h"
-#include "block.h"
 
 #define        M(A)    (1 << CT_ ## A)
 #define        agblock_to_bytes(x)     \
index e2f9587da0a67c9ae0abcc332e74608a26bb934b..bf9dd521f140686e4b6fa7b1e1e974c88d998a40 100644 (file)
@@ -15,7 +15,6 @@
 #include "bmap.h"
 #include "output.h"
 #include "init.h"
-#include "block.h"
 
 void
 fa_agblock(
index 985646e6ad89d15b898be302ad18033bf15dc45b..df38d875143ed99871c14aefe348fe2e3baf14f0 100644 (file)
@@ -97,6 +97,7 @@ struct iomap;
 #include "xfs_ag_resv.h"
 #include "xfs_metafile.h"
 #include "xfs_metadir.h"
+#include "xfs_rtgroup.h"
 
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
index a3644dea41cdef44cad14909f516f76cd5dddca7..051ee25a5b4feaa674e3b4121e71d422bc3a805c 100644 (file)
@@ -228,4 +228,37 @@ static inline size_t __ab_c_size(size_t a, size_t b, size_t c)
  */
 #define IS_ENABLED(option) __or(IS_BUILTIN(option), IS_MODULE(option))
 
+/* miscellaneous kernel routines not in user space */
+#define likely(x)              (x)
+#define unlikely(x)            (x)
+
+#define __must_check   __attribute__((__warn_unused_result__))
+
+/*
+ * Allows for effectively applying __must_check to a macro so we can have
+ * both the type-agnostic benefits of the macros while also being able to
+ * enforce that the return value is, in fact, checked.
+ */
+static inline bool __must_check __must_check_overflow(bool overflow)
+{
+       return unlikely(overflow);
+}
+
+/*
+ * For simplicity and code hygiene, the fallback code below insists on
+ * a, b and *d having the same type (similar to the min() and max()
+ * macros), whereas gcc's type-generic overflow checkers accept
+ * different types. Hence we don't just make check_add_overflow an
+ * alias for __builtin_add_overflow, but add type checks similar to
+ * below.
+ */
+#define check_add_overflow(a, b, d) __must_check_overflow(({   \
+       typeof(a) __a = (a);                    \
+       typeof(b) __b = (b);                    \
+       typeof(d) __d = (d);                    \
+       (void) (&__a == &__b);                  \
+       (void) (&__a == __d);                   \
+       __builtin_add_overflow(__a, __b, __d);  \
+}))
+
 #endif /* __XFS_PLATFORM_DEFS_H__ */
index 6daf3f01ffa9cf683dadbb0964369b9957177321..987ffea19d1586a7cc825b49a8e248ddcad8b880 100644 (file)
@@ -82,6 +82,7 @@ typedef struct xfs_mount {
         struct xfs_ino_geometry        m_ino_geo;      /* inode geometry */
        uint                    m_rsumlevels;   /* rt summary levels */
        xfs_filblks_t           m_rsumblocks;   /* size of rt summary, FSBs */
+       uint32_t                m_rgblocks;     /* size of rtgroup in rtblocks */
        /*
         * Optional cache of rt summary level per bitmap block with the
         * invariant that m_rsum_cache[bbno] <= the minimum i for which
@@ -104,6 +105,7 @@ typedef struct xfs_mount {
        uint8_t                 m_sectbb_log;   /* sectorlog - BBSHIFT */
        uint8_t                 m_agno_log;     /* log #ag's */
        int8_t                  m_rtxblklog;    /* log2 of rextsize, if possible */
+       int8_t                  m_rgblklog;     /* log2 of rt group sz if possible */
        uint                    m_blockmask;    /* sb_blocksize-1 */
        uint                    m_blockwsize;   /* sb_blocksize in words */
        uint                    m_blockwmask;   /* blockwsize-1 */
@@ -127,6 +129,7 @@ typedef struct xfs_mount {
        uint64_t                m_features;     /* active filesystem features */
        uint64_t                m_low_space[XFS_LOWSP_MAX];
        uint64_t                m_rtxblkmask;   /* rt extent block mask */
+       uint64_t                m_rgblkmask;    /* rt group block mask */
        unsigned long           m_opstate;      /* dynamic state flags */
        bool                    m_finobt_nores; /* no per-AG finobt resv. */
        uint                    m_qflags;       /* quota status flags */
@@ -250,6 +253,17 @@ __XFS_HAS_FEAT(large_extent_counts, NREXT64)
 __XFS_HAS_FEAT(exchange_range, EXCHANGE_RANGE)
 __XFS_HAS_FEAT(metadir, METADIR)
 
+
+static inline bool xfs_has_rtgroups(struct xfs_mount *mp)
+{
+       return false;
+}
+
+static inline bool xfs_has_rtsb(struct xfs_mount *mp)
+{
+       return false;
+}
+
 /* Kernel mount features that we don't support */
 #define __XFS_UNSUPP_FEAT(name) \
 static inline bool xfs_has_ ## name (struct xfs_mount *mp) \
@@ -269,6 +283,7 @@ __XFS_UNSUPP_FEAT(grpid)
 #define XFS_OPSTATE_DEBUGGER           1       /* is this the debugger? */
 #define XFS_OPSTATE_REPORT_CORRUPTION  2       /* report buffer corruption? */
 #define XFS_OPSTATE_PERAG_DATA_LOADED  3       /* per-AG data initialized? */
+#define XFS_OPSTATE_RTGROUP_DATA_LOADED        4       /* rtgroup data initialized? */
 
 #define __XFS_IS_OPSTATE(name, NAME) \
 static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
@@ -294,6 +309,7 @@ __XFS_IS_OPSTATE(inode32, INODE32)
 __XFS_IS_OPSTATE(debugger, DEBUGGER)
 __XFS_IS_OPSTATE(reporting_corruption, REPORT_CORRUPTION)
 __XFS_IS_OPSTATE(perag_data_loaded, PERAG_DATA_LOADED)
+__XFS_IS_OPSTATE(rtgroup_data_loaded, RTGROUP_DATA_LOADED)
 
 #define __XFS_UNSUPP_OPSTATE(name) \
 static inline bool xfs_is_ ## name (struct xfs_mount *mp) \
index f3e531ef118d05768d9cefe8332782de8fdd367f..a53ce092c8ea3be7a7beafecc575f1cce418f14f 100644 (file)
 #define trace_xfs_exchmaps_overhead(...)       ((void) 0)
 #define trace_xfs_exchmaps_update_inode_size(...) ((void) 0)
 
+/* set c = c to avoid unused var warnings */
+#define trace_xfs_rtgroup_get(a,b)             ((a) = (a))
+#define trace_xfs_rtgroup_hold(a,b)            ((a) = (a))
+#define trace_xfs_rtgroup_put(a,b)             ((a) = (a))
+#define trace_xfs_rtgroup_grab(a,b)            ((a) = (a))
+#define trace_xfs_rtgroup_rele(a,b)            ((a) = (a))
+
 #define trace_xfs_fs_mark_healthy(a,b)         ((void) 0)
 
 #define trace_xlog_intent_recovery_failed(...) ((void) 0)
index c8267841e77b01600d0fadeb360ad97b1b35ee5f..42c9f3cc439dc5ed4bac254a559bb07364b32837 100644 (file)
@@ -64,6 +64,7 @@ HFILES = \
        xfs_rmap.h \
        xfs_rmap_btree.h \
        xfs_rtbitmap.h \
+       xfs_rtgroup.h \
        xfs_sb.h \
        xfs_shared.h \
        xfs_trans_resv.h \
@@ -124,6 +125,7 @@ CFILES = buf_mem.c \
        xfs_rmap.c \
        xfs_rmap_btree.c \
        xfs_rtbitmap.c \
+       xfs_rtgroup.c \
        xfs_sb.c \
        xfs_symlink_remote.c \
        xfs_trans_inode.c \
index bf488c5d8533b1144186760bd0c3924a1d67ce63..b47d8eaf4f468cf6d5f75cc57a94cda0925081f4 100644 (file)
@@ -32,6 +32,7 @@
 #include "xfs_ondisk.h"
 
 #include "libxfs.h"            /* for now */
+#include "xfs_rtgroup.h"
 
 #ifndef HAVE_LIBURCU_ATOMIC64
 pthread_mutex_t        atomic64_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -670,6 +671,7 @@ libxfs_mount(
 {
        struct xfs_buf          *bp;
        struct xfs_sb           *sbp;
+       struct xfs_rtgroup      *rtg = NULL;
        xfs_daddr_t             d;
        int                     i;
        int                     error;
@@ -824,6 +826,19 @@ libxfs_mount(
        if (xfs_has_metadir(mp))
                libxfs_mount_setup_metadir(mp);
 
+       error = libxfs_initialize_rtgroups(mp, 0, sbp->sb_rgcount,
+                       sbp->sb_rextents);
+       if (error) {
+               fprintf(stderr, _("%s: rtgroup init failed\n"),
+                       progname);
+               exit(1);
+       }
+
+       while ((rtg = xfs_rtgroup_next(mp, rtg)))
+               rtg->rtg_extents = xfs_rtgroup_extents(mp, rtg_rgno(rtg));
+
+       xfs_set_rtgroup_data_loaded(mp);
+
        return mp;
 out_da:
        xfs_da_unmount(mp);
@@ -957,6 +972,8 @@ libxfs_umount(
         * Only try to free the per-AG structures if we set them up in the
         * first place.
         */
+       if (xfs_is_rtgroup_data_loaded(mp))
+               libxfs_free_rtgroups(mp, 0, mp->m_sb.sb_rgcount);
        if (xfs_is_perag_data_loaded(mp))
                libxfs_free_perag_range(mp, 0, mp->m_sb.sb_agcount);
 
index 2f218296688477356f90f4a7a34ece6dd68ec63b..c4f42754c311fcac7e9a2ed39b2fe83a81d00463 100644 (file)
 #define xfs_free_extent                        libxfs_free_extent
 #define xfs_free_extent_later          libxfs_free_extent_later
 #define xfs_free_perag_range           libxfs_free_perag_range
+#define xfs_free_rtgroups              libxfs_free_rtgroups
 #define xfs_fs_geometry                        libxfs_fs_geometry
 #define xfs_gbno_to_fsb                        libxfs_gbno_to_fsb
 #define xfs_get_initial_prid           libxfs_get_initial_prid
 
 #define xfs_initialize_perag           libxfs_initialize_perag
 #define xfs_initialize_perag_data      libxfs_initialize_perag_data
+#define xfs_initialize_rtgroups                libxfs_initialize_rtgroups
 #define xfs_init_local_fork            libxfs_init_local_fork
 
 #define xfs_inobt_init_cursor          libxfs_inobt_init_cursor
 #define xfs_rtbitmap_setword           libxfs_rtbitmap_setword
 #define xfs_rtbitmap_wordcount         libxfs_rtbitmap_wordcount
 
+#define xfs_rtgroup_alloc              libxfs_rtgroup_alloc
+
 #define xfs_suminfo_add                        libxfs_suminfo_add
 #define xfs_suminfo_get                        libxfs_suminfo_get
 #define xfs_rtsummary_wordcount                libxfs_rtsummary_wordcount
index 631abf266ad52639175f28072c921f7b1c17484a..620cd13b8ef79645536546f9f686e4f10464fe39 100644 (file)
@@ -204,10 +204,6 @@ enum ce { CE_DEBUG, CE_CONT, CE_NOTE, CE_WARN, CE_ALERT, CE_PANIC };
 #define xfs_info_once(dev, fmt, ...)                           \
        xfs_printk_once(xfs_info, dev, fmt, ##__VA_ARGS__)
 
-/* miscellaneous kernel routines not in user space */
-#define likely(x)              (x)
-#define unlikely(x)            (x)
-
 /* Need to be able to handle this bare or in control flow */
 static inline bool WARN_ON(bool expr) {
        return (expr);
@@ -238,35 +234,6 @@ struct mnt_idmap;
 void inode_init_owner(struct mnt_idmap *idmap, struct inode *inode,
                      const struct inode *dir, umode_t mode);
 
-#define __must_check   __attribute__((__warn_unused_result__))
-
-/*
- * Allows for effectively applying __must_check to a macro so we can have
- * both the type-agnostic benefits of the macros while also being able to
- * enforce that the return value is, in fact, checked.
- */
-static inline bool __must_check __must_check_overflow(bool overflow)
-{
-       return unlikely(overflow);
-}
-
-/*
- * For simplicity and code hygiene, the fallback code below insists on
- * a, b and *d having the same type (similar to the min() and max()
- * macros), whereas gcc's type-generic overflow checkers accept
- * different types. Hence we don't just make check_add_overflow an
- * alias for __builtin_add_overflow, but add type checks similar to
- * below.
- */
-#define check_add_overflow(a, b, d) __must_check_overflow(({   \
-       typeof(a) __a = (a);                    \
-       typeof(b) __b = (b);                    \
-       typeof(d) __d = (d);                    \
-       (void) (&__a == &__b);                  \
-       (void) (&__a == __d);                   \
-       __builtin_add_overflow(__a, __b, __d);  \
-}))
-
 #define min_t(type,x,y) \
        ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
 #define max_t(type,x,y) \
index 616f81045921b74a5d00ec528371abd1e08800ee..867060d60e85830ecfa43ea16fd98cbd38d6b14f 100644 (file)
@@ -176,6 +176,9 @@ typedef struct xfs_sb {
 
        xfs_ino_t       sb_metadirino;  /* metadata directory tree root */
 
+       xfs_rgnumber_t  sb_rgcount;     /* number of realtime groups */
+       xfs_rtxlen_t    sb_rgextents;   /* size of a realtime group in rtx */
+
        /* must be padded to 64 bit alignment */
 } xfs_sb_t;
 
diff --git a/libxfs/xfs_rtgroup.c b/libxfs/xfs_rtgroup.c
new file mode 100644 (file)
index 0000000..88f3138
--- /dev/null
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022-2024 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#include "libxfs_priv.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "xfs_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_bit.h"
+#include "xfs_sb.h"
+#include "xfs_mount.h"
+#include "xfs_btree.h"
+#include "xfs_alloc_btree.h"
+#include "xfs_rmap_btree.h"
+#include "xfs_alloc.h"
+#include "xfs_ialloc.h"
+#include "xfs_rmap.h"
+#include "xfs_ag.h"
+#include "xfs_ag_resv.h"
+#include "xfs_health.h"
+#include "xfs_bmap.h"
+#include "xfs_defer.h"
+#include "xfs_log_format.h"
+#include "xfs_trans.h"
+#include "xfs_trace.h"
+#include "xfs_inode.h"
+#include "xfs_rtgroup.h"
+#include "xfs_rtbitmap.h"
+
+int
+xfs_rtgroup_alloc(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          rgno,
+       xfs_rgnumber_t          rgcount,
+       xfs_rtbxlen_t           rextents)
+{
+       struct xfs_rtgroup      *rtg;
+       int                     error;
+
+       rtg = kzalloc(sizeof(struct xfs_rtgroup), GFP_KERNEL);
+       if (!rtg)
+               return -ENOMEM;
+
+       error = xfs_group_insert(mp, rtg_group(rtg), rgno, XG_TYPE_RTG);
+       if (error)
+               goto out_free_rtg;
+       return 0;
+
+out_free_rtg:
+       kfree(rtg);
+       return error;
+}
+
+void
+xfs_rtgroup_free(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          rgno)
+{
+       xfs_group_free(mp, rgno, XG_TYPE_RTG, NULL);
+}
+
+/* Free a range of incore rtgroup objects. */
+void
+xfs_free_rtgroups(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          first_rgno,
+       xfs_rgnumber_t          end_rgno)
+{
+       xfs_rgnumber_t          rgno;
+
+       for (rgno = first_rgno; rgno < end_rgno; rgno++)
+               xfs_rtgroup_free(mp, rgno);
+}
+
+/* Initialize some range of incore rtgroup objects. */
+int
+xfs_initialize_rtgroups(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          first_rgno,
+       xfs_rgnumber_t          end_rgno,
+       xfs_rtbxlen_t           rextents)
+{
+       xfs_rgnumber_t          index;
+       int                     error;
+
+       if (first_rgno >= end_rgno)
+               return 0;
+
+       for (index = first_rgno; index < end_rgno; index++) {
+               error = xfs_rtgroup_alloc(mp, index, end_rgno, rextents);
+               if (error)
+                       goto out_unwind_new_rtgs;
+       }
+
+       return 0;
+
+out_unwind_new_rtgs:
+       xfs_free_rtgroups(mp, first_rgno, index);
+       return error;
+}
+
+/* Compute the number of rt extents in this realtime group. */
+xfs_rtxnum_t
+__xfs_rtgroup_extents(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          rgno,
+       xfs_rgnumber_t          rgcount,
+       xfs_rtbxlen_t           rextents)
+{
+       ASSERT(rgno < rgcount);
+       if (rgno == rgcount - 1)
+               return rextents - ((xfs_rtxnum_t)rgno * mp->m_sb.sb_rgextents);
+
+       ASSERT(xfs_has_rtgroups(mp));
+       return mp->m_sb.sb_rgextents;
+}
+
+xfs_rtxnum_t
+xfs_rtgroup_extents(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          rgno)
+{
+       return __xfs_rtgroup_extents(mp, rgno, mp->m_sb.sb_rgcount,
+                       mp->m_sb.sb_rextents);
+}
+
+/*
+ * Update the rt extent count of the previous tail rtgroup if it changed during
+ * recovery (i.e. recovery of a growfs).
+ */
+int
+xfs_update_last_rtgroup_size(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          prev_rgcount)
+{
+       struct xfs_rtgroup      *rtg;
+
+       ASSERT(prev_rgcount > 0);
+
+       rtg = xfs_rtgroup_grab(mp, prev_rgcount - 1);
+       if (!rtg)
+               return -EFSCORRUPTED;
+       rtg->rtg_extents = __xfs_rtgroup_extents(mp, prev_rgcount - 1,
+                       mp->m_sb.sb_rgcount, mp->m_sb.sb_rextents);
+       xfs_rtgroup_rele(rtg);
+       return 0;
+}
diff --git a/libxfs/xfs_rtgroup.h b/libxfs/xfs_rtgroup.h
new file mode 100644 (file)
index 0000000..8872c27
--- /dev/null
@@ -0,0 +1,217 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2022-2024 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#ifndef __LIBXFS_RTGROUP_H
+#define __LIBXFS_RTGROUP_H 1
+
+#include "xfs_group.h"
+
+struct xfs_mount;
+struct xfs_trans;
+
+/*
+ * Realtime group incore structure, similar to the per-AG structure.
+ */
+struct xfs_rtgroup {
+       struct xfs_group        rtg_group;
+
+       /* Number of blocks in this group */
+       xfs_rtxnum_t            rtg_extents;
+};
+
+static inline struct xfs_rtgroup *to_rtg(struct xfs_group *xg)
+{
+       return container_of(xg, struct xfs_rtgroup, rtg_group);
+}
+
+static inline struct xfs_group *rtg_group(struct xfs_rtgroup *rtg)
+{
+       return &rtg->rtg_group;
+}
+
+static inline struct xfs_mount *rtg_mount(const struct xfs_rtgroup *rtg)
+{
+       return rtg->rtg_group.xg_mount;
+}
+
+static inline xfs_rgnumber_t rtg_rgno(const struct xfs_rtgroup *rtg)
+{
+       return rtg->rtg_group.xg_gno;
+}
+
+/* Passive rtgroup references */
+static inline struct xfs_rtgroup *
+xfs_rtgroup_get(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          rgno)
+{
+       return to_rtg(xfs_group_get(mp, rgno, XG_TYPE_RTG));
+}
+
+static inline struct xfs_rtgroup *
+xfs_rtgroup_hold(
+       struct xfs_rtgroup      *rtg)
+{
+       return to_rtg(xfs_group_hold(rtg_group(rtg)));
+}
+
+static inline void
+xfs_rtgroup_put(
+       struct xfs_rtgroup      *rtg)
+{
+       xfs_group_put(rtg_group(rtg));
+}
+
+/* Active rtgroup references */
+static inline struct xfs_rtgroup *
+xfs_rtgroup_grab(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          rgno)
+{
+       return to_rtg(xfs_group_grab(mp, rgno, XG_TYPE_RTG));
+}
+
+static inline void
+xfs_rtgroup_rele(
+       struct xfs_rtgroup      *rtg)
+{
+       xfs_group_rele(rtg_group(rtg));
+}
+
+static inline struct xfs_rtgroup *
+xfs_rtgroup_next_range(
+       struct xfs_mount        *mp,
+       struct xfs_rtgroup      *rtg,
+       xfs_rgnumber_t          start_rgno,
+       xfs_rgnumber_t          end_rgno)
+{
+       return to_rtg(xfs_group_next_range(mp, rtg ? rtg_group(rtg) : NULL,
+                       start_rgno, end_rgno, XG_TYPE_RTG));
+}
+
+static inline struct xfs_rtgroup *
+xfs_rtgroup_next(
+       struct xfs_mount        *mp,
+       struct xfs_rtgroup      *rtg)
+{
+       return xfs_rtgroup_next_range(mp, rtg, 0, mp->m_sb.sb_rgcount - 1);
+}
+
+static inline xfs_rtblock_t
+xfs_rgno_start_rtb(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          rgno)
+{
+       if (mp->m_rgblklog >= 0)
+               return ((xfs_rtblock_t)rgno << mp->m_rgblklog);
+       return ((xfs_rtblock_t)rgno * mp->m_rgblocks);
+}
+
+static inline xfs_rtblock_t
+__xfs_rgbno_to_rtb(
+       struct xfs_mount        *mp,
+       xfs_rgnumber_t          rgno,
+       xfs_rgblock_t           rgbno)
+{
+       return xfs_rgno_start_rtb(mp, rgno) + rgbno;
+}
+
+static inline xfs_rtblock_t
+xfs_rgbno_to_rtb(
+       struct xfs_rtgroup      *rtg,
+       xfs_rgblock_t           rgbno)
+{
+       return __xfs_rgbno_to_rtb(rtg_mount(rtg), rtg_rgno(rtg), rgbno);
+}
+
+static inline xfs_rgnumber_t
+xfs_rtb_to_rgno(
+       struct xfs_mount        *mp,
+       xfs_rtblock_t           rtbno)
+{
+       if (!xfs_has_rtgroups(mp))
+               return 0;
+
+       if (mp->m_rgblklog >= 0)
+               return rtbno >> mp->m_rgblklog;
+
+       return div_u64(rtbno, mp->m_rgblocks);
+}
+
+static inline uint64_t
+__xfs_rtb_to_rgbno(
+       struct xfs_mount        *mp,
+       xfs_rtblock_t           rtbno)
+{
+       uint32_t                rem;
+
+       if (!xfs_has_rtgroups(mp))
+               return rtbno;
+
+       if (mp->m_rgblklog >= 0)
+               return rtbno & mp->m_rgblkmask;
+
+       div_u64_rem(rtbno, mp->m_rgblocks, &rem);
+       return rem;
+}
+
+static inline xfs_rgblock_t
+xfs_rtb_to_rgbno(
+       struct xfs_mount        *mp,
+       xfs_rtblock_t           rtbno)
+{
+       return __xfs_rtb_to_rgbno(mp, rtbno);
+}
+
+static inline xfs_daddr_t
+xfs_rtb_to_daddr(
+       struct xfs_mount        *mp,
+       xfs_rtblock_t           rtbno)
+{
+       return rtbno << mp->m_blkbb_log;
+}
+
+static inline xfs_rtblock_t
+xfs_daddr_to_rtb(
+       struct xfs_mount        *mp,
+       xfs_daddr_t             daddr)
+{
+       return daddr >> mp->m_blkbb_log;
+}
+
+#ifdef CONFIG_XFS_RT
+int xfs_rtgroup_alloc(struct xfs_mount *mp, xfs_rgnumber_t rgno,
+               xfs_rgnumber_t rgcount, xfs_rtbxlen_t rextents);
+void xfs_rtgroup_free(struct xfs_mount *mp, xfs_rgnumber_t rgno);
+
+void xfs_free_rtgroups(struct xfs_mount *mp, xfs_rgnumber_t first_rgno,
+               xfs_rgnumber_t end_rgno);
+int xfs_initialize_rtgroups(struct xfs_mount *mp, xfs_rgnumber_t first_rgno,
+               xfs_rgnumber_t end_rgno, xfs_rtbxlen_t rextents);
+
+xfs_rtxnum_t __xfs_rtgroup_extents(struct xfs_mount *mp, xfs_rgnumber_t rgno,
+               xfs_rgnumber_t rgcount, xfs_rtbxlen_t rextents);
+xfs_rtxnum_t xfs_rtgroup_extents(struct xfs_mount *mp, xfs_rgnumber_t rgno);
+
+int xfs_update_last_rtgroup_size(struct xfs_mount *mp,
+               xfs_rgnumber_t prev_rgcount);
+#else
+static inline void xfs_free_rtgroups(struct xfs_mount *mp,
+               xfs_rgnumber_t first_rgno, xfs_rgnumber_t end_rgno)
+{
+}
+
+static inline int xfs_initialize_rtgroups(struct xfs_mount *mp,
+               xfs_rgnumber_t first_rgno, xfs_rgnumber_t end_rgno,
+               xfs_rtbxlen_t rextents)
+{
+       return 0;
+}
+
+# define xfs_rtgroup_extents(mp, rgno)         (0)
+# define xfs_update_last_rtgroup_size(mp, rgno)        (-EOPNOTSUPP)
+#endif /* CONFIG_XFS_RT */
+
+#endif /* __LIBXFS_RTGROUP_H */
index 4ca57d592be8fa40aa529c77078ecab2c1eac39a..2a5368c266ee91fe0b71018a31f64ccf842b5ebd 100644 (file)
@@ -707,6 +707,9 @@ __xfs_sb_from_disk(
                to->sb_metadirino = be64_to_cpu(from->sb_metadirino);
        else
                to->sb_metadirino = NULLFSINO;
+
+       to->sb_rgcount = 1;
+       to->sb_rgextents = 0;
 }
 
 void
@@ -991,8 +994,18 @@ xfs_mount_sb_set_rextsize(
        struct xfs_mount        *mp,
        struct xfs_sb           *sbp)
 {
+       struct xfs_groups       *rgs = &mp->m_groups[XG_TYPE_RTG];
+
        mp->m_rtxblklog = log2_if_power2(sbp->sb_rextsize);
        mp->m_rtxblkmask = mask64_if_power2(sbp->sb_rextsize);
+
+       mp->m_rgblocks = 0;
+       mp->m_rgblklog = 0;
+       mp->m_rgblkmask = (uint64_t)-1;
+
+       rgs->blocks = 0;
+       rgs->blklog = 0;
+       rgs->blkmask = (uint64_t)-1;
 }
 
 /*
index 25053a66c225ed257e099a1e7f26f00bc6827f1c..bf33c2b1e43e5f029cbfa7e67585b5e688bb23b7 100644 (file)
@@ -9,10 +9,12 @@
 typedef uint32_t       prid_t;         /* project ID */
 
 typedef uint32_t       xfs_agblock_t;  /* blockno in alloc. group */
+typedef uint32_t       xfs_rgblock_t;  /* blockno in realtime group */
 typedef uint32_t       xfs_agino_t;    /* inode # within allocation grp */
 typedef uint32_t       xfs_extlen_t;   /* extent length in blocks */
 typedef uint32_t       xfs_rtxlen_t;   /* file extent length in rtextents */
 typedef uint32_t       xfs_agnumber_t; /* allocation group number */
+typedef uint32_t       xfs_rgnumber_t; /* realtime group number */
 typedef uint64_t       xfs_extnum_t;   /* # of extents in a file */
 typedef uint32_t       xfs_aextnum_t;  /* # extents in an attribute fork */
 typedef int64_t                xfs_fsize_t;    /* bytes in a file */
@@ -53,7 +55,9 @@ typedef void *                xfs_failaddr_t;
 #define        NULLFILEOFF     ((xfs_fileoff_t)-1)
 
 #define        NULLAGBLOCK     ((xfs_agblock_t)-1)
+#define NULLRGBLOCK    ((xfs_rgblock_t)-1)
 #define        NULLAGNUMBER    ((xfs_agnumber_t)-1)
+#define        NULLRGNUMBER    ((xfs_rgnumber_t)-1)
 
 #define NULLCOMMITLSN  ((xfs_lsn_t)-1)
 
@@ -214,11 +218,13 @@ enum xbtree_recpacking {
 
 enum xfs_group_type {
        XG_TYPE_AG,
+       XG_TYPE_RTG,
        XG_TYPE_MAX,
 } __packed;
 
 #define XG_TYPE_STRINGS \
-       { XG_TYPE_AG,   "ag" }
+       { XG_TYPE_AG,   "ag" }, \
+       { XG_TYPE_RTG,  "rtg" }
 
 /*
  * Type verifier functions
index 4e51caead9dac2aef147238224264cfade246b6e..2549a636568d1b1ad344a4838d2637d42e944995 100644 (file)
@@ -3592,6 +3592,14 @@ sb_set_features(
        if (!fp->metadir)
                sbp->sb_bad_features2 = sbp->sb_features2;
 
+       /*
+        * This will be overriden later for real rtgroup file systems.  For
+        * !rtgroups filesystems, we pretend that there's one huge group, just
+        * like __xfs_sb_from_disk does.
+        */
+       sbp->sb_rgcount = 1;
+       sbp->sb_rgextents = 0;
+
        if (!fp->crcs_enabled)
                return;