+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,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 "err_protos.h"
#include "dinode.h"
#include "progress.h"
+#include "bmap.h"
+#include "threads.h"
static void
process_agi_unlinked(
struct xfs_agi *agip;
xfs_agnumber_t i;
int agi_dirty = 0;
+ int error;
- bp = libxfs_readbuf(mp->m_dev,
+ error = -libxfs_buf_read(mp->m_dev,
XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
- mp->m_sb.sb_sectsize/BBSIZE, 0, &xfs_agi_buf_ops);
- if (!bp)
+ mp->m_sb.sb_sectsize / BBSIZE, LIBXFS_READBUF_SALVAGE,
+ &bp, &xfs_agi_buf_ops);
+ if (error)
do_error(_("cannot read agi block %" PRId64 " for ag %u\n"),
XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), agno);
- agip = XFS_BUF_TO_AGI(bp);
+ agip = bp->b_addr;
ASSERT(be32_to_cpu(agip->agi_seqno) == agno);
}
}
- if (agi_dirty)
- libxfs_writebuf(bp, 0);
+ if (agi_dirty) {
+ libxfs_buf_mark_dirty(bp);
+ libxfs_buf_relse(bp);
+ }
else
- libxfs_putbuf(bp);
+ libxfs_buf_relse(bp);
}
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, 1, 0, 1);
+ process_aginodes(wq->wq_ctx, arg, agno, 1, 0, 1);
+ blkmap_free_final();
cleanup_inode_prefetch(arg);
}
do_inode_prefetch(mp, ag_stride, process_ag_func, false, false);
}
+static void
+do_uncertain_aginodes(
+ struct workqueue *wq,
+ xfs_agnumber_t agno,
+ void *arg)
+{
+ int *count = arg;
+
+ *count = process_uncertain_aginodes(wq->wq_ctx, agno);
+
+#ifdef XR_INODE_TRACE
+ fprintf(stderr,
+ "\t\t phase 3 - ag %d process_uncertain_inodes returns %d\n",
+ *count, j);
+#endif
+
+ PROG_RPT_INC(prog_rpt_done[agno], 1);
+}
+
void
-phase3(xfs_mount_t *mp)
+phase3(
+ struct xfs_mount *mp,
+ int scan_threads)
{
- int i, j;
+ int i, j;
+ int *counts;
+ struct workqueue wq;
do_log(_("Phase 3 - for each AG...\n"));
if (!no_modify)
else
do_log(_(" - scan (but don't clear) agi unlinked lists...\n"));
- set_progress_msg(PROG_FMT_AGI_UNLINKED, (__uint64_t) glob_agcount);
+ set_progress_msg(PROG_FMT_AGI_UNLINKED, (uint64_t) glob_agcount);
/* first clear the agi unlinked AGI list */
if (!no_modify) {
do_log(_(
" - process known inodes and perform inode discovery...\n"));
- set_progress_msg(PROG_FMT_PROCESS_INO, (__uint64_t) mp->m_sb.sb_icount);
+ set_progress_msg(PROG_FMT_PROCESS_INO, (uint64_t) mp->m_sb.sb_icount);
process_ags(mp);
* process newly discovered inode chunks
*/
do_log(_(" - process newly discovered inodes...\n"));
- set_progress_msg(PROG_FMT_NEW_INODES, (__uint64_t) glob_agcount);
+ set_progress_msg(PROG_FMT_NEW_INODES, (uint64_t) glob_agcount);
+
+ counts = calloc(sizeof(*counts), mp->m_sb.sb_agcount);
+ if (!counts) {
+ do_abort(_("no memory for uncertain inode counts\n"));
+ return;
+ }
+
do {
/*
* have to loop until no ag has any uncertain
* inodes
*/
j = 0;
- for (i = 0; i < mp->m_sb.sb_agcount; i++) {
- j += process_uncertain_aginodes(mp, i);
-#ifdef XR_INODE_TRACE
- fprintf(stderr,
- "\t\t phase 3 - process_uncertain_inodes returns %d\n", j);
-#endif
- PROG_RPT_INC(prog_rpt_done[i], 1);
- }
+ memset(counts, 0, mp->m_sb.sb_agcount * sizeof(*counts));
+
+ create_work_queue(&wq, mp, scan_threads);
+
+ for (i = 0; i < mp->m_sb.sb_agcount; i++)
+ queue_work(&wq, do_uncertain_aginodes, i, &counts[i]);
+
+ destroy_work_queue(&wq);
+
+ /* tally up the counts */
+ for (i = 0; i < mp->m_sb.sb_agcount; i++)
+ j += counts[i];
+
} while (j != 0);
+
+ free(counts);
+
print_final_rpt();
}