]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_scrub: fix nr_dirs accounting problems
authorDarrick J. Wong <darrick.wong@oracle.com>
Thu, 26 Sep 2019 17:45:56 +0000 (13:45 -0400)
committerEric Sandeen <sandeen@sandeen.net>
Thu, 26 Sep 2019 17:45:56 +0000 (13:45 -0400)
When we're scanning the directory tree, we bump nr_dirs every time we
think we're going to queue a new directory to process, and we decrement
it every time we're finished doing something with a directory
(successful or not).  We forgot to undo a counter increment when
workqueue_add fails, so refactor the code into helpers and call them
as necessary for correct operation.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
scrub/vfs.c

index add4e81554d65e9227057b55622d3082eaa0cf2c..f8bc98c062da25f14851171a9579186fb4c41e0d 100644 (file)
@@ -45,6 +45,32 @@ struct scan_fs_tree_dir {
 
 static void scan_fs_dir(struct workqueue *wq, xfs_agnumber_t agno, void *arg);
 
+/* Increment the number of directories that are queued for processing. */
+static void
+inc_nr_dirs(
+       struct scan_fs_tree     *sft)
+{
+       pthread_mutex_lock(&sft->lock);
+       sft->nr_dirs++;
+       pthread_mutex_unlock(&sft->lock);
+}
+
+/*
+ * Decrement the number of directories that are queued for processing and if
+ * we ran out of dirs to process, wake up anyone who was waiting for processing
+ * to finish.
+ */
+static void
+dec_nr_dirs(
+       struct scan_fs_tree     *sft)
+{
+       pthread_mutex_lock(&sft->lock);
+       sft->nr_dirs--;
+       if (sft->nr_dirs == 0)
+               pthread_cond_signal(&sft->wakeup);
+       pthread_mutex_unlock(&sft->lock);
+}
+
 /* Queue a directory for scanning. */
 static bool
 queue_subdir(
@@ -72,15 +98,10 @@ queue_subdir(
        new_sftd->sft = sft;
        new_sftd->rootdir = is_rootdir;
 
-       pthread_mutex_lock(&sft->lock);
-       sft->nr_dirs++;
-       pthread_mutex_unlock(&sft->lock);
+       inc_nr_dirs(sft);
        error = workqueue_add(wq, scan_fs_dir, 0, new_sftd);
        if (error) {
-               /*
-                * XXX: need to decrement nr_dirs here; will do that in the
-                * next patch.
-                */
+               dec_nr_dirs(sft);
                str_info(ctx, ctx->mntpoint,
 _("Could not queue subdirectory scan work."));
                goto out_path;
@@ -180,12 +201,7 @@ scan_fs_dir(
                str_errno(ctx, sftd->path);
 
 out:
-       pthread_mutex_lock(&sft->lock);
-       sft->nr_dirs--;
-       if (sft->nr_dirs == 0)
-               pthread_cond_signal(&sft->wakeup);
-       pthread_mutex_unlock(&sft->lock);
-
+       dec_nr_dirs(sft);
        free(sftd->path);
        free(sftd);
 }