]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - scrub/progress.c
xfs_scrub: handle spurious wakeups in scan_fs_tree
[thirdparty/xfsprogs-dev.git] / scrub / progress.c
index d0afe90a27e8b7514ab905e3706e261c4e7ccc82..a3d096f98e2c8548d9583aebd4f476ce30d9215e 100644 (file)
@@ -8,7 +8,7 @@
 #include <pthread.h>
 #include <sys/statvfs.h>
 #include <time.h>
-#include "path.h"
+#include "libfrog/paths.h"
 #include "disk.h"
 #include "read_verify.h"
 #include "xfs_scrub.h"
@@ -110,15 +110,17 @@ progress_report(
        fflush(pt.fp);
 }
 
-#define NSEC_PER_SEC   (1000000000)
 static void *
 progress_report_thread(void *arg)
 {
        struct timespec         abstime;
        int                     ret;
 
+       rcu_register_thread();
        pthread_mutex_lock(&pt.lock);
        while (1) {
+               uint64_t        progress_val;
+
                /* Every half second. */
                ret = clock_gettime(CLOCK_REALTIME, &abstime);
                if (ret)
@@ -128,12 +130,17 @@ progress_report_thread(void *arg)
                        abstime.tv_sec++;
                        abstime.tv_nsec -= NSEC_PER_SEC;
                }
-               pthread_cond_timedwait(&pt.wakeup, &pt.lock, &abstime);
+               ret = pthread_cond_timedwait(&pt.wakeup, &pt.lock, &abstime);
+               if (ret && ret != ETIMEDOUT)
+                       break;
                if (pt.terminate)
                        break;
-               progress_report(ptcounter_value(pt.ptc));
+               ret = ptcounter_value(pt.ptc, &progress_val);
+               if (!ret)
+                       progress_report(progress_val);
        }
        pthread_mutex_unlock(&pt.lock);
+       rcu_unregister_thread();
        return NULL;
 }
 
@@ -161,8 +168,11 @@ progress_end_phase(void)
        pt.fp = NULL;
 }
 
-/* Set ourselves up to report progress. */
-bool
+/*
+ * Set ourselves up to report progress.  If errors are encountered, this
+ * function will log them and return nonzero.
+ */
+int
 progress_init_phase(
        struct scrub_ctx        *ctx,
        FILE                    *fp,
@@ -176,7 +186,7 @@ progress_init_phase(
        assert(pt.fp == NULL);
        if (fp == NULL || max == 0) {
                pt.fp = NULL;
-               return true;
+               return 0;
        }
        pt.fp = fp;
        pt.isatty = isatty(fileno(fp));
@@ -187,15 +197,19 @@ progress_init_phase(
        pt.twiddle = 0;
        pt.terminate = false;
 
-       pt.ptc = ptcounter_init(nr_threads);
-       if (!pt.ptc)
+       ret = ptcounter_alloc(nr_threads, &pt.ptc);
+       if (ret) {
+               str_liberror(ctx, ret, _("allocating progress counter"));
                goto out_max;
+       }
 
        ret = pthread_create(&pt.thread, NULL, progress_report_thread, NULL);
-       if (ret)
+       if (ret) {
+               str_liberror(ctx, ret, _("creating progress reporting thread"));
                goto out_ptcounter;
+       }
 
-       return true;
+       return 0;
 
 out_ptcounter:
        ptcounter_free(pt.ptc);
@@ -203,5 +217,5 @@ out_ptcounter:
 out_max:
        pt.max = 0;
        pt.fp = NULL;
-       return false;
+       return ret;
 }