]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - scrub/vfs.c
xfs_scrub: move to mallinfo2 when available
[thirdparty/xfsprogs-dev.git] / scrub / vfs.c
index 0cff2e3f0801ed8d5ce429b91b4d2fbe83477e4d..577eb6dc3e868729dd3cb92c732c1e7a8a78b1c8 100644 (file)
@@ -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;
@@ -72,7 +72,7 @@ dec_nr_dirs(
 }
 
 /* Queue a directory for scanning. */
-static bool
+static int
 queue_subdir(
        struct scrub_ctx        *ctx,
        struct scan_fs_tree     *sft,
@@ -84,14 +84,12 @@ queue_subdir(
        int                     error;
 
        new_sftd = malloc(sizeof(struct scan_fs_tree_dir));
-       if (!new_sftd) {
-               str_errno(ctx, _("creating directory scan context"));
-               return false;
-       }
+       if (!new_sftd)
+               return errno;
 
        new_sftd->path = strdup(path);
        if (!new_sftd->path) {
-               str_errno(ctx, _("creating directory scan path"));
+               error = errno;
                goto out_sftd;
        }
 
@@ -99,19 +97,19 @@ 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"));
                goto out_path;
        }
 
-       return true;
+       return 0;
 out_path:
        free(new_sftd->path);
 out_sftd:
        free(new_sftd);
-       return false;
+       return error;
 }
 
 /* Scan a directory sub tree. */
@@ -140,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);
@@ -152,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);
 
@@ -173,24 +175,28 @@ 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;
                }
 
                /* If directory, call ourselves recursively. */
                if (S_ISDIR(sb.st_mode) && strcmp(".", dirent->d_name) &&
                    strcmp("..", dirent->d_name)) {
-                       sft->moveon = queue_subdir(ctx, sft, wq, newpath,
-                                       false);
-                       if (!sft->moveon)
+                       error = queue_subdir(ctx, sft, wq, newpath, false);
+                       if (error) {
+                               str_liberror(ctx, error,
+_("queueing subdirectory scan"));
+                               sft->aborted = true;
                                break;
+                       }
                }
        }
 
@@ -205,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,
@@ -214,28 +223,37 @@ scan_fs_tree(
        void                    *arg)
 {
        struct workqueue        wq;
-       struct scan_fs_tree     sft;
+       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;
-       pthread_mutex_init(&sft.lock, NULL);
-       pthread_cond_init(&sft.wakeup, NULL);
+       ret = pthread_mutex_init(&sft.lock, NULL);
+       if (ret) {
+               str_liberror(ctx, ret, _("creating directory scan lock"));
+               return ret;
+       }
+       ret = pthread_cond_init(&sft.wakeup, NULL);
+       if (ret) {
+               str_liberror(ctx, ret, _("creating directory scan signal"));
+               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_info(ctx, ctx->mntpoint, _("Could not create workqueue."));
-               return false;
+               str_liberror(ctx, ret, _("creating directory scan workqueue"));
+               goto out_cond;
        }
 
-       sft.moveon = queue_subdir(ctx, &sft, &wq, ctx->mntpoint, true);
-       if (!sft.moveon)
+       ret = queue_subdir(ctx, &sft, &wq, ctx->mntpoint, true);
+       if (ret) {
+               str_liberror(ctx, ret, _("queueing directory scan"));
                goto out_wq;
+       }
 
        /*
         * Wait for the wakeup to trigger, which should only happen when the
@@ -250,9 +268,22 @@ scan_fs_tree(
        assert(sft.nr_dirs == 0);
        pthread_mutex_unlock(&sft.lock);
 
+       ret = -workqueue_terminate(&wq);
+       if (ret) {
+               str_liberror(ctx, ret, _("finishing directory scan work"));
+               goto out_wq;
+       }
+
+       if (!ret && sft.aborted)
+               ret = -1;
+
 out_wq:
        workqueue_destroy(&wq);
-       return sft.moveon;
+out_cond:
+       pthread_cond_destroy(&sft.wakeup);
+out_mutex:
+       pthread_mutex_destroy(&sft.lock);
+       return ret;
 }
 
 #ifndef FITRIM