]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - repair/phase3.c
xfsprogs: Release v6.8.0
[thirdparty/xfsprogs-dev.git] / repair / phase3.c
index 4751e56b94af551fb1f821fbedef140985bb93a6..ca4dbee47434c8032191a25cf40cf205d4a72bf7 100644 (file)
@@ -1,22 +1,10 @@
+// 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"
@@ -27,6 +15,8 @@
 #include "err_protos.h"
 #include "dinode.h"
 #include "progress.h"
+#include "bmap.h"
+#include "threads.h"
 
 static void
 process_agi_unlinked(
@@ -37,15 +27,17 @@ 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);
 
@@ -56,15 +48,17 @@ process_agi_unlinked(
                }
        }
 
-       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)
 {
@@ -74,7 +68,8 @@ process_ag_func(
         */
        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);
 }
 
@@ -85,10 +80,33 @@ process_ags(
        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)
@@ -96,7 +114,7 @@ phase3(xfs_mount_t *mp)
        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) {
@@ -116,7 +134,7 @@ phase3(xfs_mount_t *mp)
        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);
 
@@ -126,21 +144,36 @@ phase3(xfs_mount_t *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();
 }