xfs: implement online scrubbing of rtsummary info
[platform/kernel/linux-starfive.git] / fs / xfs / scrub / scrub.c
index 3d98f60..939d1d1 100644 (file)
@@ -22,6 +22,8 @@
 #include "scrub/trace.h"
 #include "scrub/repair.h"
 #include "scrub/health.h"
+#include "scrub/stats.h"
+#include "scrub/xfile.h"
 
 /*
  * Online Scrub and Repair
@@ -166,8 +168,6 @@ xchk_teardown(
        struct xfs_scrub        *sc,
        int                     error)
 {
-       struct xfs_inode        *ip_in = XFS_I(file_inode(sc->file));
-
        xchk_ag_free(sc, &sc->sa);
        if (sc->tp) {
                if (error == 0 && (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR))
@@ -178,14 +178,16 @@ xchk_teardown(
        }
        if (sc->ip) {
                if (sc->ilock_flags)
-                       xfs_iunlock(sc->ip, sc->ilock_flags);
-               if (sc->ip != ip_in &&
-                   !xfs_internal_inum(sc->mp, sc->ip->i_ino))
-                       xchk_irele(sc, sc->ip);
+                       xchk_iunlock(sc, sc->ilock_flags);
+               xchk_irele(sc, sc->ip);
                sc->ip = NULL;
        }
        if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR)
                mnt_drop_write_file(sc->file);
+       if (sc->xfile) {
+               xfile_destroy(sc->xfile);
+               sc->xfile = NULL;
+       }
        if (sc->buf) {
                if (sc->buf_cleanup)
                        sc->buf_cleanup(sc->buf);
@@ -320,14 +322,14 @@ static const struct xchk_meta_ops meta_scrub_ops[] = {
        },
        [XFS_SCRUB_TYPE_RTBITMAP] = {   /* realtime bitmap */
                .type   = ST_FS,
-               .setup  = xchk_setup_rt,
+               .setup  = xchk_setup_rtbitmap,
                .scrub  = xchk_rtbitmap,
                .has    = xfs_has_realtime,
                .repair = xrep_notsupported,
        },
        [XFS_SCRUB_TYPE_RTSUM] = {      /* realtime summary */
                .type   = ST_FS,
-               .setup  = xchk_setup_rt,
+               .setup  = xchk_setup_rtsummary,
                .scrub  = xchk_rtsummary,
                .has    = xfs_has_realtime,
                .repair = xrep_notsupported,
@@ -461,8 +463,10 @@ xfs_scrub_metadata(
        struct file                     *file,
        struct xfs_scrub_metadata       *sm)
 {
+       struct xchk_stats_run           run = { };
        struct xfs_scrub                *sc;
        struct xfs_mount                *mp = XFS_I(file_inode(file))->i_mount;
+       u64                             check_start;
        int                             error = 0;
 
        BUILD_BUG_ON(sizeof(meta_scrub_ops) !=
@@ -517,7 +521,9 @@ retry_op:
                goto out_teardown;
 
        /* Scrub for errors. */
+       check_start = xchk_stats_now();
        error = sc->ops->scrub(sc);
+       run.scrub_ns += xchk_stats_elapsed_ns(check_start);
        if (error == -EDEADLOCK && !(sc->flags & XCHK_TRY_HARDER))
                goto try_harder;
        if (error == -ECHRNG && !(sc->flags & XCHK_NEED_DRAIN))
@@ -551,7 +557,7 @@ retry_op:
                 * If it's broken, userspace wants us to fix it, and we haven't
                 * already tried to fix it, then attempt a repair.
                 */
-               error = xrep_attempt(sc);
+               error = xrep_attempt(sc, &run);
                if (error == -EAGAIN) {
                        /*
                         * Either the repair function succeeded or it couldn't
@@ -579,12 +585,15 @@ out:
                sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
                error = 0;
        }
+       if (error != -ENOENT)
+               xchk_stats_merge(mp, sm, &run);
        return error;
 need_drain:
        error = xchk_teardown(sc, 0);
        if (error)
                goto out_sc;
        sc->flags |= XCHK_NEED_DRAIN;
+       run.retries++;
        goto retry_op;
 try_harder:
        /*
@@ -596,5 +605,6 @@ try_harder:
        if (error)
                goto out_sc;
        sc->flags |= XCHK_TRY_HARDER;
+       run.retries++;
        goto retry_op;
 }