#include "repair/pptr.h"
#include "slab.h"
#include "rmap.h"
+#include "rt.h"
static xfs_ino_t orphanage_ino;
libxfs_irele(ip);
}
-static int
-fill_rbmino(xfs_mount_t *mp)
-{
- struct xfs_buf *bp;
- xfs_trans_t *tp;
- xfs_inode_t *ip;
- union xfs_rtword_raw *bmp;
- int nmap;
- int error;
- xfs_fileoff_t bno;
- xfs_bmbt_irec_t map;
-
- bmp = btmcompute;
- bno = 0;
-
- error = -libxfs_trans_alloc_rollable(mp, 10, &tp);
- if (error)
- res_failed(error);
-
- error = -libxfs_iget(mp, tp, mp->m_sb.sb_rbmino, 0, &ip);
- if (error) {
- do_error(
- _("couldn't iget realtime bitmap inode -- error - %d\n"),
- error);
- }
-
- while (bno < mp->m_sb.sb_rbmblocks) {
- struct xfs_rtalloc_args args = {
- .mp = mp,
- .tp = tp,
- };
- union xfs_rtword_raw *ondisk;
- xfs_daddr_t daddr;
-
- /*
- * fill the file one block at a time
- */
- nmap = 1;
- error = -libxfs_bmapi_write(tp, ip, bno, 1, 0, 1, &map, &nmap);
- if (error || nmap != 1) {
- do_error(
- _("couldn't map realtime bitmap block %" PRIu64 ", error = %d\n"),
- bno, error);
- }
-
- ASSERT(map.br_startblock != HOLESTARTBLOCK);
-
- daddr = XFS_FSB_TO_DADDR(mp, map.br_startblock);
- error = -libxfs_trans_read_buf(mp, tp, mp->m_dev, daddr,
- XFS_FSB_TO_BB(mp, 1), 1, &bp, NULL);
- if (error) {
- do_warn(
-_("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime bitmap inode %" PRIu64 "\n"),
- bno, map.br_startblock, mp->m_sb.sb_rbmino);
- return(1);
- }
-
- args.rbmbp = bp;
- ondisk = xfs_rbmblock_wordptr(&args, 0);
- memcpy(ondisk, bmp, mp->m_blockwsize << XFS_WORDLOG);
-
- if (xfs_has_rtgroups(mp)) {
- struct xfs_rtbuf_blkinfo *hdr = bp->b_addr;
-
- bp->b_ops = &xfs_rtbitmap_buf_ops;
- hdr->rt_magic = cpu_to_be32(XFS_RTBITMAP_MAGIC);
- hdr->rt_owner = cpu_to_be64(ip->i_ino);
- hdr->rt_lsn = 0;
- hdr->rt_blkno = cpu_to_be64(daddr);
- platform_uuid_copy(&hdr->rt_uuid,
- &mp->m_sb.sb_meta_uuid);
- }
-
- libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
-
- bmp += mp->m_blockwsize;
- bno++;
- }
-
- libxfs_trans_ijoin(tp, ip, 0);
- error = -libxfs_trans_commit(tp);
- if (error)
- do_error(_("%s: commit failed, error %d\n"), __func__, error);
- libxfs_irele(ip);
- return(0);
-}
-
-static int
-fill_rsumino(xfs_mount_t *mp)
-{
- struct xfs_buf *bp;
- xfs_trans_t *tp;
- xfs_inode_t *ip;
- union xfs_suminfo_raw *smp;
- int nmap;
- int error;
- xfs_fileoff_t bno;
- xfs_fileoff_t end_bno;
- xfs_bmbt_irec_t map;
-
- smp = sumcompute;
- bno = 0;
- end_bno = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
-
- error = -libxfs_trans_alloc_rollable(mp, 10, &tp);
- if (error)
- res_failed(error);
-
- error = -libxfs_iget(mp, tp, mp->m_sb.sb_rsumino, 0, &ip);
- if (error) {
- do_error(
- _("couldn't iget realtime summary inode -- error - %d\n"),
- error);
- }
-
- while (bno < end_bno) {
- struct xfs_rtalloc_args args = {
- .mp = mp,
- .tp = tp,
- };
- union xfs_suminfo_raw *ondisk;
- xfs_daddr_t daddr;
-
- /*
- * fill the file one block at a time
- */
- nmap = 1;
- error = -libxfs_bmapi_write(tp, ip, bno, 1, 0, 1, &map, &nmap);
- if (error || nmap != 1) {
- do_error(
- _("couldn't map realtime summary inode block %" PRIu64 ", error = %d\n"),
- bno, error);
- }
-
- ASSERT(map.br_startblock != HOLESTARTBLOCK);
-
- daddr = XFS_FSB_TO_DADDR(mp, map.br_startblock);
- error = -libxfs_trans_read_buf(mp, tp, mp->m_dev, daddr,
- XFS_FSB_TO_BB(mp, 1), 1, &bp, NULL);
-
- if (error) {
- do_warn(
-_("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime summary inode %" PRIu64 "\n"),
- bno, map.br_startblock, mp->m_sb.sb_rsumino);
- libxfs_irele(ip);
- return(1);
- }
-
- args.sumbp = bp;
- ondisk = xfs_rsumblock_infoptr(&args, 0);
- memcpy(ondisk, smp, mp->m_blockwsize << XFS_WORDLOG);
-
- if (xfs_has_rtgroups(mp)) {
- struct xfs_rtbuf_blkinfo *hdr = bp->b_addr;
-
- bp->b_ops = &xfs_rtsummary_buf_ops;
- hdr->rt_magic = cpu_to_be32(XFS_RTSUMMARY_MAGIC);
- hdr->rt_owner = cpu_to_be64(ip->i_ino);
- hdr->rt_lsn = 0;
- hdr->rt_blkno = cpu_to_be64(daddr);
- platform_uuid_copy(&hdr->rt_uuid,
- &mp->m_sb.sb_meta_uuid);
- }
-
- libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
-
- smp += mp->m_blockwsize;
- bno++;
- }
-
- libxfs_trans_ijoin(tp, ip, 0);
- error = -libxfs_trans_commit(tp);
- if (error)
- do_error(_("%s: commit failed, error %d\n"), __func__, error);
- libxfs_irele(ip);
- return(0);
-}
-
static void
mk_rsumino(
struct xfs_mount *mp)
if (!no_modify) {
do_log(
_(" - resetting contents of realtime bitmap and summary inodes\n"));
- if (fill_rbmino(mp)) {
- do_warn(
- _("Warning: realtime bitmap may be inconsistent\n"));
- }
-
- if (fill_rsumino(mp)) {
- do_warn(
- _("Warning: realtime bitmap may be inconsistent\n"));
- }
+ fill_rtino(mp, true);
+ fill_rtino(mp, false);
}
if (reserve_perag)
check_rtfile_contents(mp, false);
}
+void
+fill_rtino(
+ struct xfs_mount *mp,
+ bool is_bitmap)
+{
+ unsigned long data_size = mp->m_blockwsize << XFS_WORDLOG;
+ const struct xfs_buf_ops *buf_ops = NULL;
+ xfs_fileoff_t bno = 0;
+ struct xfs_inode *ip;
+ struct xfs_trans *tp;
+ const char *name;
+ void *data;
+ xfs_fileoff_t end_bno;
+ xfs_ino_t ino;
+ __be32 magic;
+ int error;
+
+ if (is_bitmap) {
+ ino = mp->m_sb.sb_rbmino;
+ name = "bitmap";
+ data = btmcompute;
+ end_bno = mp->m_sb.sb_rbmblocks;
+ magic = cpu_to_be32(XFS_RTBITMAP_MAGIC);
+ buf_ops = &xfs_rtbitmap_buf_ops;
+ } else {
+ ino = mp->m_sb.sb_rsumino;
+ name = "summary";
+ data = sumcompute;
+ end_bno = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
+ magic = cpu_to_be32(XFS_RTSUMMARY_MAGIC);
+ buf_ops = &xfs_rtsummary_buf_ops;
+ }
+
+ /*
+ * Nothing to do for empty files, which are the normal case if there are
+ * no RT extents.
+ */
+ if (!end_bno)
+ return;
+
+ error = -libxfs_trans_alloc_rollable(mp, 10, &tp);
+ if (error)
+ do_error(_("xfs_trans_reserve returned %d\n"), error);
+
+ error = -libxfs_iget(mp, tp, ino, 0, &ip);
+ if (error) {
+ do_error(
+ _("couldn't iget realtime %s inode -- error - %d\n"),
+ name, error);
+ }
+
+ libxfs_trans_ijoin(tp, ip, 0);
+ while (bno < end_bno) {
+ struct xfs_buf *bp;
+ struct xfs_bmbt_irec map;
+ int nmap = 1;
+ unsigned int hdr_size = 0;
+
+ /*
+ * Fill the file one block at a time.
+ */
+ error = -libxfs_bmapi_write(tp, ip, bno, 1, 0, 1, &map, &nmap);
+ if (error || nmap != 1) {
+ do_error(
+ _("couldn't map realtime %s inode block %" PRIu64 ", error = %d\n"),
+ name, bno, error);
+ }
+
+ ASSERT(map.br_startblock != HOLESTARTBLOCK);
+
+ error = -libxfs_trans_read_buf(mp, tp, mp->m_dev,
+ XFS_FSB_TO_DADDR(mp, map.br_startblock),
+ XFS_FSB_TO_BB(mp, 1), 1, &bp, NULL);
+
+ if (error) {
+ do_warn(
+_("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime %s inode %" PRIu64 "\n"),
+ bno, map.br_startblock, name, ip->i_ino);
+ goto fail;
+ }
+
+ if (xfs_has_rtgroups(mp)) {
+ struct xfs_rtbuf_blkinfo *hdr = bp->b_addr;
+
+ hdr->rt_magic = magic;
+ hdr->rt_owner = cpu_to_be64(ip->i_ino);
+ hdr->rt_lsn = 0;
+ hdr->rt_blkno = cpu_to_be64(xfs_buf_daddr(bp));
+ platform_uuid_copy(&hdr->rt_uuid,
+ &mp->m_sb.sb_meta_uuid);
+
+ bp->b_ops = buf_ops;
+ hdr_size = sizeof(*hdr);
+ }
+
+ memcpy(bp->b_addr + hdr_size, data, data_size);
+ libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
+
+ data += data_size;
+ bno++;
+ }
+
+ error = -libxfs_trans_commit(tp);
+ if (error)
+ do_error(_("%s: commit failed, error %d\n"), __func__, error);
+ libxfs_irele(ip);
+ return;
+
+fail:
+ do_warn(_("Warning: realtime bitmap may be inconsistent\n"));
+ libxfs_irele(ip);
+}
+
void
check_rtsuper(
struct xfs_mount *mp)