]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - scrub/vfs.c
Merge tag 'scrub-fix-legalese-6.6_2024-01-11' of https://git.kernel.org/pub/scm/linux...
[thirdparty/xfsprogs-dev.git] / scrub / vfs.c
index d7c40239b677d06a222c8096a67bf14c80c5e7e9..9e459d6243fa4428dd27de192fa5935db9ee8fcf 100644 (file)
@@ -1,7 +1,7 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- * Copyright (C) 2018 Oracle.  All Rights Reserved.
- * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ * Copyright (C) 2018-2024 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
  */
 #include "xfs.h"
 #include <stdint.h>
@@ -30,7 +30,7 @@ struct scan_fs_tree {
        pthread_mutex_t         lock;
        pthread_cond_t          wakeup;
        struct stat             root_sb;
-       bool                    moveon;
+       bool                    aborted;
        scan_fs_tree_dir_fn     dir_fn;
        scan_fs_tree_dirent_fn  dirent_fn;
        void                    *arg;
@@ -97,7 +97,7 @@ queue_subdir(
        new_sftd->rootdir = is_rootdir;
 
        inc_nr_dirs(sft);
-       error = workqueue_add(wq, scan_fs_dir, 0, new_sftd);
+       error = -workqueue_add(wq, scan_fs_dir, 0, new_sftd);
        if (error) {
                dec_nr_dirs(sft);
                str_liberror(ctx, error, _("queueing directory scan work"));
@@ -138,8 +138,9 @@ scan_fs_dir(
        }
 
        /* Caller-specific directory checks. */
-       if (!sft->dir_fn(ctx, sftd->path, dir_fd, sft->arg)) {
-               sft->moveon = false;
+       error = sft->dir_fn(ctx, sftd->path, dir_fd, sft->arg);
+       if (error) {
+               sft->aborted = true;
                error = close(dir_fd);
                if (error)
                        str_errno(ctx, sftd->path);
@@ -150,11 +151,14 @@ scan_fs_dir(
        dir = fdopendir(dir_fd);
        if (!dir) {
                str_errno(ctx, sftd->path);
+               sft->aborted = true;
                close(dir_fd);
                goto out;
        }
        rewinddir(dir);
-       for (dirent = readdir(dir); dirent != NULL; dirent = readdir(dir)) {
+       for (dirent = readdir(dir);
+            !sft->aborted && dirent != NULL;
+            dirent = readdir(dir)) {
                snprintf(newpath, PATH_MAX, "%s/%s", sftd->path,
                                dirent->d_name);
 
@@ -171,14 +175,15 @@ scan_fs_dir(
                        continue;
 
                /* Caller-specific directory entry function. */
-               if (!sft->dirent_fn(ctx, newpath, dir_fd, dirent, &sb,
-                               sft->arg)) {
-                       sft->moveon = false;
+               error = sft->dirent_fn(ctx, newpath, dir_fd, dirent, &sb,
+                               sft->arg);
+               if (error) {
+                       sft->aborted = true;
                        break;
                }
 
-               if (xfs_scrub_excessive_errors(ctx)) {
-                       sft->moveon = false;
+               if (scrub_excessive_errors(ctx)) {
+                       sft->aborted = true;
                        break;
                }
 
@@ -189,7 +194,7 @@ scan_fs_dir(
                        if (error) {
                                str_liberror(ctx, error,
 _("queueing subdirectory scan"));
-                               sft->moveon = false;
+                               sft->aborted = true;
                                break;
                        }
                }
@@ -206,8 +211,11 @@ out:
        free(sftd);
 }
 
-/* Scan the entire filesystem. */
-bool
+/*
+ * Scan the entire filesystem.  This function returns 0 on success; if there
+ * are errors, this function will log them and returns nonzero.
+ */
+int
 scan_fs_tree(
        struct scrub_ctx        *ctx,
        scan_fs_tree_dir_fn     dir_fn,
@@ -215,20 +223,18 @@ scan_fs_tree(
        void                    *arg)
 {
        struct workqueue        wq;
-       struct scan_fs_tree     sft;
-       bool                    moveon = false;
+       struct scan_fs_tree     sft = {
+               .root_sb        = ctx->mnt_sb,
+               .dir_fn         = dir_fn,
+               .dirent_fn      = dirent_fn,
+               .arg            = arg,
+       };
        int                     ret;
 
-       sft.moveon = true;
-       sft.nr_dirs = 0;
-       sft.root_sb = ctx->mnt_sb;
-       sft.dir_fn = dir_fn;
-       sft.dirent_fn = dirent_fn;
-       sft.arg = arg;
        ret = pthread_mutex_init(&sft.lock, NULL);
        if (ret) {
                str_liberror(ctx, ret, _("creating directory scan lock"));
-               return false;
+               return ret;
        }
        ret = pthread_cond_init(&sft.wakeup, NULL);
        if (ret) {
@@ -236,7 +242,7 @@ scan_fs_tree(
                goto out_mutex;
        }
 
-       ret = workqueue_create(&wq, (struct xfs_mount *)ctx,
+       ret = -workqueue_create(&wq, (struct xfs_mount *)ctx,
                        scrub_nproc_workqueue(ctx));
        if (ret) {
                str_liberror(ctx, ret, _("creating directory scan workqueue"));
@@ -257,25 +263,27 @@ scan_fs_tree(
         * about to tear everything down.
         */
        pthread_mutex_lock(&sft.lock);
-       if (sft.nr_dirs)
+       while (sft.nr_dirs > 0)
                pthread_cond_wait(&sft.wakeup, &sft.lock);
        assert(sft.nr_dirs == 0);
        pthread_mutex_unlock(&sft.lock);
 
-       ret = workqueue_terminate(&wq);
+       ret = -workqueue_terminate(&wq);
        if (ret) {
                str_liberror(ctx, ret, _("finishing directory scan work"));
                goto out_wq;
        }
 
-       moveon = sft.moveon;
+       if (!ret && sft.aborted)
+               ret = -1;
+
 out_wq:
        workqueue_destroy(&wq);
 out_cond:
        pthread_cond_destroy(&sft.wakeup);
 out_mutex:
        pthread_mutex_destroy(&sft.lock);
-       return moveon;
+       return ret;
 }
 
 #ifndef FITRIM