]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - repair/phase4.c
xfs_growfs: allow mounted device node as argument
[thirdparty/xfsprogs-dev.git] / repair / phase4.c
index e234d9283e55909dca8f069b03c330e26be6fe38..e1ba778fdf56c10d985228285693eb318c389451 100644 (file)
@@ -1,19 +1,7 @@
+// 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 "libxfs.h"
@@ -134,13 +122,13 @@ quota_sb_check(xfs_mount_t *mp)
 
 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);
 
@@ -154,48 +142,118 @@ static void
 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(
-       work_queue_t    *wq,
+       struct workqueue*wq,
        xfs_agnumber_t  agno,
        void            *arg)
 {
        int             error;
 
-       error = add_fixed_ag_rmap_data(wq->mp, agno);
+       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 = fold_raw_rmaps(wq->mp, 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 = check_rmaps(wq->mp, 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 work_queue       wq;
+       struct workqueue        wq;
        xfs_agnumber_t          i;
 
-       if (!needs_rmap_work(mp))
+       if (!rmap_needs_work(mp))
                return;
 
-       create_work_queue(&wq, mp, libxfs_nproc());
+       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
@@ -213,14 +271,14 @@ phase4(xfs_mount_t *mp)
        int                     ag_hdr_block;
        int                     bstate;
 
-       if (needs_rmap_work(mp))
+       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));
@@ -334,7 +392,7 @@ phase4(xfs_mount_t *mp)
        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.
@@ -349,7 +407,9 @@ phase4(xfs_mount_t *mp)
 
        /*
         * Process all the reverse-mapping data that we collected.  This
-        * involves checking the rmap data against the btree.
+        * 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);