+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "xfs/libxfs.h"
+#include "libxfs.h"
#include "threads.h"
#include "prefetch.h"
#include "avl.h"
#include "versions.h"
#include "dir2.h"
#include "progress.h"
+#include "slab.h"
+#include "rmap.h"
+bool collect_rmaps;
/*
* null out quota inode fields in sb if they point to non-existent inodes.
static void
process_ag_func(
- work_queue_t *wq,
+ struct workqueue *wq,
xfs_agnumber_t agno,
void *arg)
{
wait_for_inode_prefetch(arg);
do_log(_(" - agno = %d\n"), agno);
- process_aginodes(wq->mp, arg, agno, 0, 1, 0);
+ process_aginodes(wq->wq_ctx, arg, agno, 0, 1, 0);
+ blkmap_free_final();
cleanup_inode_prefetch(arg);
/*
process_ags(
xfs_mount_t *mp)
{
+ xfs_agnumber_t i;
+ int error;
+
do_inode_prefetch(mp, ag_stride, process_ag_func, true, false);
+ for (i = 0; i < mp->m_sb.sb_agcount; i++) {
+ error = rmap_finish_collecting_fork_recs(mp, i);
+ if (error)
+ do_error(
+_("unable to finish adding attr/data fork reverse-mapping data for AG %u.\n"),
+ i);
+ }
+}
+
+static void
+check_rmap_btrees(
+ struct workqueue*wq,
+ xfs_agnumber_t agno,
+ void *arg)
+{
+ int error;
+
+ error = rmap_add_fixed_ag_rec(wq->wq_ctx, agno);
+ if (error)
+ do_error(
+_("unable to add AG %u metadata reverse-mapping data.\n"), agno);
+
+ error = rmap_fold_raw_recs(wq->wq_ctx, agno);
+ if (error)
+ do_error(
+_("unable to merge AG %u metadata reverse-mapping data.\n"), agno);
+
+ error = rmaps_verify_btree(wq->wq_ctx, agno);
+ if (error)
+ do_error(
+_("%s while checking reverse-mappings"),
+ strerror(-error));
}
+static void
+compute_ag_refcounts(
+ struct workqueue*wq,
+ xfs_agnumber_t agno,
+ void *arg)
+{
+ int error;
+
+ error = compute_refcounts(wq->wq_ctx, agno);
+ if (error)
+ do_error(
+_("%s while computing reference count records.\n"),
+ strerror(-error));
+}
+
+static void
+process_inode_reflink_flags(
+ struct workqueue *wq,
+ xfs_agnumber_t agno,
+ void *arg)
+{
+ int error;
+
+ error = fix_inode_reflink_flags(wq->wq_ctx, agno);
+ if (error)
+ do_error(
+_("%s while fixing inode reflink flags.\n"),
+ strerror(-error));
+}
+
+static void
+check_refcount_btrees(
+ struct workqueue*wq,
+ xfs_agnumber_t agno,
+ void *arg)
+{
+ int error;
+
+ error = check_refcounts(wq->wq_ctx, agno);
+ if (error)
+ do_error(
+_("%s while checking reference counts"),
+ strerror(-error));
+}
+
+static void
+process_rmap_data(
+ struct xfs_mount *mp)
+{
+ struct workqueue wq;
+ xfs_agnumber_t i;
+
+ if (!rmap_needs_work(mp))
+ return;
+
+ create_work_queue(&wq, mp, platform_nproc());
+ for (i = 0; i < mp->m_sb.sb_agcount; i++)
+ queue_work(&wq, check_rmap_btrees, i, NULL);
+ destroy_work_queue(&wq);
+
+ if (!xfs_sb_version_hasreflink(&mp->m_sb))
+ return;
+
+ create_work_queue(&wq, mp, platform_nproc());
+ for (i = 0; i < mp->m_sb.sb_agcount; i++)
+ queue_work(&wq, compute_ag_refcounts, i, NULL);
+ destroy_work_queue(&wq);
+
+ create_work_queue(&wq, mp, platform_nproc());
+ for (i = 0; i < mp->m_sb.sb_agcount; i++) {
+ queue_work(&wq, process_inode_reflink_flags, i, NULL);
+ queue_work(&wq, check_refcount_btrees, i, NULL);
+ }
+ destroy_work_queue(&wq);
+}
void
phase4(xfs_mount_t *mp)
int ag_hdr_block;
int bstate;
+ if (rmap_needs_work(mp))
+ collect_rmaps = true;
ag_hdr_block = howmany(ag_hdr_len, mp->m_sb.sb_blocksize);
do_log(_("Phase 4 - check for duplicate blocks...\n"));
do_log(_(" - setting up duplicate extent list...\n"));
- set_progress_msg(PROG_FMT_DUP_EXTENT, (__uint64_t) glob_agcount);
+ set_progress_msg(PROG_FMT_DUP_EXTENT, (uint64_t) glob_agcount);
irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
reset_bmaps(mp);
do_log(_(" - check for inodes claiming duplicate blocks...\n"));
- set_progress_msg(PROG_FMT_DUP_BLOCKS, (__uint64_t) mp->m_sb.sb_icount);
+ set_progress_msg(PROG_FMT_DUP_BLOCKS, (uint64_t) mp->m_sb.sb_icount);
/*
* ok, now process the inodes -- signal 2-pass check per inode.
* already in phase 3.
*/
process_ags(mp);
+
+ /*
+ * Process all the reverse-mapping data that we collected. This
+ * involves checking the rmap data against the btree, computing
+ * reference counts based on the rmap data, and checking the counts
+ * against the refcount btree.
+ */
+ process_rmap_data(mp);
+
print_final_rpt();
/*