/* Number of inodes scanned. */
struct ptcounter *icount;
+ /* per-AG locks to protect the repair lists */
+ pthread_mutex_t *locks;
+
/* Set to true to abort all threads. */
bool aborted;
str_errno(ctx, descr);
}
+/*
+ * Defer all the repairs until phase 4, being careful about locking since the
+ * inode scrub threads are not per-AG.
+ */
+static void
+defer_inode_repair(
+ struct scrub_inode_ctx *ictx,
+ xfs_agnumber_t agno,
+ struct action_list *alist)
+{
+ if (alist->nr == 0)
+ return;
+
+ pthread_mutex_lock(&ictx->locks[agno]);
+ action_list_defer(ictx->ctx, agno, alist);
+ pthread_mutex_unlock(&ictx->locks[agno]);
+}
+
/* Run repair actions now and defer unfinished items for later. */
static int
try_inode_repair(
if (ret)
return ret;
- action_list_defer(ictx->ctx, agno, alist);
+ defer_inode_repair(ictx, agno, alist);
return 0;
}
progress_add(1);
if (!error && !ictx->aborted)
- action_list_defer(ctx, agno, &alist);
+ defer_inode_repair(ictx, agno, &alist);
if (fd >= 0) {
int err2;
return err;
}
+ ictx.locks = calloc(ctx->mnt.fsgeom.agcount, sizeof(pthread_mutex_t));
+ if (!ictx.locks) {
+ str_errno(ctx, _("creating per-AG repair list locks"));
+ err = ENOMEM;
+ goto out_ptcounter;
+ }
+
/*
* If we already have ag/fs metadata to repair from previous phases,
* we would rather not try to repair file metadata until we've tried
* to repair the space metadata.
*/
for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
+ pthread_mutex_init(&ictx.locks[agno], NULL);
+
if (!action_list_empty(&ctx->action_lists[agno]))
ictx.always_defer_repairs = true;
}
if (!err && ictx.aborted)
err = ECANCELED;
if (err)
- goto free;
+ goto out_locks;
scrub_report_preen_triggers(ctx);
err = ptcounter_value(ictx.icount, &val);
if (err) {
str_liberror(ctx, err, _("summing scanned inode counter"));
- return err;
+ goto out_locks;
}
ctx->inodes_checked = val;
-free:
+out_locks:
+ for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
+ pthread_mutex_destroy(&ictx.locks[agno]);
+ free(ictx.locks);
+out_ptcounter:
ptcounter_free(ictx.icount);
return err;
}