]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs: factor out rtbitmap/summary initialization helpers
authorChristoph Hellwig <hch@lst.de>
Tue, 30 Jul 2024 01:05:06 +0000 (18:05 -0700)
committerChristoph Hellwig <hch@lst.de>
Tue, 30 Jul 2024 01:07:30 +0000 (18:07 -0700)
Source kernel commit: 50eb06188e917fdc52cefbd70bbb221e4f52366a

Add helpers to libxfs that can be shared by growfs and mkfs for
initializing the rtbitmap and summary, and by passing the optional
data pointer also by repair for rebuilding them.  This will become
even more useful when the rtgroups feature adѕ a metadata header
to each block, which means even more shared code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
libxfs/xfs_rtbitmap.c
libxfs/xfs_rtbitmap.h

index fc904547147e9327d3d5eca22d453752dfcfc82c..0137c372667b548723e087f532a90a93ece88638 100644 (file)
@@ -13,6 +13,8 @@
 #include "xfs_mount.h"
 #include "xfs_inode.h"
 #include "xfs_bmap.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_trans_space.h"
 #include "xfs_trans.h"
 #include "xfs_rtbitmap.h"
 #include "xfs_health.h"
@@ -1253,3 +1255,123 @@ xfs_rtbitmap_unlock_shared(
        if (rbmlock_flags & XFS_RBMLOCK_BITMAP)
                xfs_iunlock(mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
 }
+
+static int
+xfs_rtfile_alloc_blocks(
+       struct xfs_inode        *ip,
+       xfs_fileoff_t           offset_fsb,
+       xfs_filblks_t           count_fsb,
+       struct xfs_bmbt_irec    *map)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_trans        *tp;
+       int                     nmap = 1;
+       int                     error;
+
+       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtalloc,
+                       XFS_GROWFSRT_SPACE_RES(mp, count_fsb), 0, 0, &tp);
+       if (error)
+               return error;
+
+       xfs_ilock(ip, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+
+       error = xfs_iext_count_extend(tp, ip, XFS_DATA_FORK,
+                               XFS_IEXT_ADD_NOSPLIT_CNT);
+       if (error)
+               goto out_trans_cancel;
+
+       error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
+                       XFS_BMAPI_METADATA, 0, map, &nmap);
+       if (error)
+               goto out_trans_cancel;
+
+       return xfs_trans_commit(tp);
+
+out_trans_cancel:
+       xfs_trans_cancel(tp);
+       return error;
+}
+
+/* Get a buffer for the block. */
+static int
+xfs_rtfile_initialize_block(
+       struct xfs_inode        *ip,
+       xfs_fsblock_t           fsbno,
+       void                    *data)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_trans        *tp;
+       struct xfs_buf          *bp;
+       int                     error;
+       enum xfs_blft           buf_type;
+
+       if (ip == mp->m_rsumip)
+               buf_type = XFS_BLFT_RTSUMMARY_BUF;
+       else
+               buf_type = XFS_BLFT_RTBITMAP_BUF;
+
+       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growrtzero, 0, 0, 0, &tp);
+       if (error)
+               return error;
+       xfs_ilock(ip, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+
+       error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
+                       XFS_FSB_TO_DADDR(mp, fsbno), mp->m_bsize, 0, &bp);
+       if (error) {
+               xfs_trans_cancel(tp);
+               return error;
+       }
+
+       xfs_trans_buf_set_type(tp, bp, buf_type);
+       bp->b_ops = &xfs_rtbuf_ops;
+       if (data)
+               memcpy(bp->b_addr, data, mp->m_sb.sb_blocksize);
+       else
+               memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
+       xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
+       return xfs_trans_commit(tp);
+}
+
+/*
+ * Allocate space to the bitmap or summary file, and zero it, for growfs.
+ */
+int
+xfs_rtfile_initialize_blocks(
+       struct xfs_inode        *ip,            /* inode (bitmap/summary) */
+       xfs_fileoff_t           offset_fsb,     /* offѕet to start from */
+       xfs_fileoff_t           end_fsb,        /* offѕet to allocate to */
+       void                    *data)          /* data to fill the blocks */
+{
+       struct xfs_mount        *mp = ip->i_mount;
+
+       while (offset_fsb < end_fsb) {
+               struct xfs_bmbt_irec    map;
+               xfs_filblks_t           i;
+               int                     error;
+
+               error = xfs_rtfile_alloc_blocks(ip, offset_fsb,
+                               end_fsb - offset_fsb, &map);
+               if (error)
+                       return error;
+
+               /*
+                * Now we need to clear the allocated blocks.
+                *
+                * Do this one block per transaction, to keep it simple.
+                */
+               for (i = 0; i < map.br_blockcount; i++) {
+                       error = xfs_rtfile_initialize_block(ip,
+                                       map.br_startblock + i, data);
+                       if (error)
+                               return error;
+                       if (data)
+                               data += (mp->m_blockwsize << XFS_WORDLOG);
+               }
+
+               offset_fsb = map.br_startoff + map.br_blockcount;
+       }
+
+       return 0;
+}
index e87e2099cff5e083553bc2d8dd89fdb7e38f6033..0d5ab5e2cb6a329eae5a523508c2ab744f2067dc 100644 (file)
@@ -343,6 +343,9 @@ xfs_filblks_t xfs_rtsummary_blockcount(struct xfs_mount *mp,
 unsigned long long xfs_rtsummary_wordcount(struct xfs_mount *mp,
                unsigned int rsumlevels, xfs_extlen_t rbmblocks);
 
+int xfs_rtfile_initialize_blocks(struct xfs_inode *ip,
+               xfs_fileoff_t offset_fsb, xfs_fileoff_t end_fsb, void *data);
+
 void xfs_rtbitmap_lock(struct xfs_trans *tp, struct xfs_mount *mp);
 void xfs_rtbitmap_unlock(struct xfs_mount *mp);