]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - repair/phase7.c
libxfs: refactor manage_zones()
[thirdparty/xfsprogs-dev.git] / repair / phase7.c
index b1e3a5527a81b454123400266b17f14bdfc01859..c2996470cf1e651612ce7e7518e4af01b0abddd3 100644 (file)
@@ -1,19 +1,7 @@
+// 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 "libxfs.h"
 #include "dinode.h"
 #include "versions.h"
 #include "progress.h"
-
-/* dinoc is a pointer to the IN-CORE dinode core */
-static void
-set_nlinks(
-       xfs_icdinode_t          *dinoc,
-       xfs_ino_t               ino,
-       __uint32_t              nrefs,
-       int                     *dirty)
-{
-       if (dinoc->di_nlink == nrefs)
-               return;
-
-       if (!no_modify) {
-               *dirty = 1;
-               do_warn(_("resetting inode %" PRIu64 " nlinks from %u to %u\n"),
-                       ino, dinoc->di_nlink, nrefs);
-
-               ASSERT(dinoc->di_version > 1);
-               dinoc->di_nlink = nrefs;
-       } else  {
-               do_warn(
-_("would have reset inode %" PRIu64 " nlinks from %u to %u\n"),
-                       ino, dinoc->di_nlink, nrefs);
-       }
-}
+#include "threads.h"
 
 static void
 update_inode_nlinks(
        xfs_mount_t             *mp,
        xfs_ino_t               ino,
-       __uint32_t              nlinks)
+       uint32_t                nlinks)
 {
        xfs_trans_t             *tp;
        xfs_inode_t             *ip;
@@ -64,14 +28,11 @@ update_inode_nlinks(
        int                     dirty;
        int                     nres;
 
-       tp = libxfs_trans_alloc(mp, XFS_TRANS_REMOVE);
-
        nres = no_modify ? 0 : 10;
-       error = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_remove, nres, 0);
+       error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp);
        ASSERT(error == 0);
 
-       error = -libxfs_trans_iget(mp, tp, ino, 0, 0, &ip);
-
+       error = -libxfs_iget(mp, tp, ino, 0, &ip, &xfs_default_ifork_ops);
        if (error)  {
                if (!no_modify)
                        do_error(
@@ -87,14 +48,25 @@ update_inode_nlinks(
 
        dirty = 0;
 
-       /*
-        * compare and set links for all inodes
-        */
-       set_nlinks(&ip->i_d, ino, nlinks, &dirty);
+       /* compare and set links if they differ.  */
+       if (VFS_I(ip)->i_nlink != nlinks) {
+               if (!no_modify) {
+                       do_warn(
+       _("resetting inode %" PRIu64 " nlinks from %u to %u\n"),
+                               ino, VFS_I(ip)->i_nlink, nlinks);
+                       set_nlink(VFS_I(ip), nlinks);
+                       dirty = 1;
+               } else {
+                       do_warn(
+       _("would have reset inode %" PRIu64 " nlinks from %u to %u\n"),
+                               ino, VFS_I(ip)->i_nlink, nlinks);
+               }
+       }
 
        if (!dirty)  {
                libxfs_trans_cancel(tp);
        } else  {
+               libxfs_trans_ijoin(tp, ip, 0);
                libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
                /*
                 * no need to do a bmap finish since
@@ -105,48 +77,69 @@ update_inode_nlinks(
 
                ASSERT(error == 0);
        }
-       IRELE(ip);
+       libxfs_irele(ip);
 }
 
-void
-phase7(xfs_mount_t *mp)
+/*
+ * for each ag, look at each inode 1 at a time. If the number of
+ * links is bad, reset it, log the inode core, commit the transaction
+ */
+static void
+do_link_updates(
+       struct workqueue        *wq,
+       xfs_agnumber_t          agno,
+       void                    *arg)
 {
+       struct xfs_mount        *mp = wq->wq_ctx;
        ino_tree_node_t         *irec;
-       int                     i;
        int                     j;
-       __uint32_t              nrefs;
+       uint32_t                nrefs;
+
+       for (irec = findfirst_inode_rec(agno); irec;
+            irec = next_ino_rec(irec)) {
+               for (j = 0; j < XFS_INODES_PER_CHUNK; j++)  {
+                       ASSERT(is_inode_confirmed(irec, j));
+
+                       if (is_inode_free(irec, j))
+                               continue;
+
+                       ASSERT(no_modify || is_inode_reached(irec, j));
+
+                       nrefs = num_inode_references(irec, j);
+                       ASSERT(no_modify || nrefs > 0);
+
+                       if (get_inode_disk_nlinks(irec, j) != nrefs)
+                               update_inode_nlinks(wq->wq_ctx,
+                                       XFS_AGINO_TO_INO(mp, agno,
+                                               irec->ino_startnum + j),
+                                       nrefs);
+               }
+       }
+
+       PROG_RPT_INC(prog_rpt_done[agno], 1);
+}
+
+void
+phase7(
+       struct xfs_mount        *mp,
+       int                     scan_threads)
+{
+       struct workqueue        wq;
+       int                     agno;
 
        if (!no_modify)
                do_log(_("Phase 7 - verify and correct link counts...\n"));
        else
                do_log(_("Phase 7 - verify link counts...\n"));
 
-       /*
-        * for each ag, look at each inode 1 at a time. If the number of
-        * links is bad, reset it, log the inode core, commit the transaction
-        */
-       for (i = 0; i < glob_agcount; i++)  {
-               irec = findfirst_inode_rec(i);
-
-               while (irec != NULL)  {
-                       for (j = 0; j < XFS_INODES_PER_CHUNK; j++)  {
-                               ASSERT(is_inode_confirmed(irec, j));
+       set_progress_msg(PROGRESS_FMT_CORR_LINK, (uint64_t) glob_agcount);
 
-                               if (is_inode_free(irec, j))
-                                       continue;
+       create_work_queue(&wq, mp, scan_threads);
 
-                               ASSERT(no_modify || is_inode_reached(irec, j));
+       for (agno = 0; agno < mp->m_sb.sb_agcount; agno++)
+               queue_work(&wq, do_link_updates, agno, NULL);
 
-                               nrefs = num_inode_references(irec, j);
-                               ASSERT(no_modify || nrefs > 0);
+       destroy_work_queue(&wq);
 
-                               if (get_inode_disk_nlinks(irec, j) != nrefs)
-                                       update_inode_nlinks(mp,
-                                               XFS_AGINO_TO_INO(mp, i,
-                                                       irec->ino_startnum + j),
-                                               nrefs);
-                       }
-                       irec = next_ino_rec(irec);
-               }
-       }
+       print_final_rpt();
 }