]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - scrub/phase4.c
libfrog: introduce xfs_fd to wrap an fd to a file on an xfs filesystem
[thirdparty/xfsprogs-dev.git] / scrub / phase4.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0+
7e36bc0f
DW
2/*
3 * Copyright (C) 2018 Oracle. All Rights Reserved.
7e36bc0f 4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
7e36bc0f 5 */
a440f877 6#include "xfs.h"
7e36bc0f 7#include <stdint.h>
7e36bc0f
DW
8#include <dirent.h>
9#include <sys/types.h>
7e36bc0f 10#include <sys/statvfs.h>
7e36bc0f
DW
11#include "list.h"
12#include "path.h"
13#include "workqueue.h"
14#include "xfs_scrub.h"
15#include "common.h"
ed60d210 16#include "progress.h"
7e36bc0f 17#include "scrub.h"
ee310b0c 18#include "repair.h"
7e36bc0f
DW
19#include "vfs.h"
20
21/* Phase 4: Repair filesystem. */
22
ee310b0c
DW
23/* Fix all the problems in our per-AG list. */
24static void
25xfs_repair_ag(
26 struct workqueue *wq,
27 xfs_agnumber_t agno,
28 void *priv)
29{
30 struct scrub_ctx *ctx = (struct scrub_ctx *)wq->wq_ctx;
31 bool *pmoveon = priv;
32 struct xfs_action_list *alist;
33 size_t unfixed;
34 size_t new_unfixed;
35 unsigned int flags = 0;
36 bool moveon;
37
38 alist = &ctx->action_lists[agno];
39 unfixed = xfs_action_list_length(alist);
40
41 /* Repair anything broken until we fail to make progress. */
42 do {
3f9efb2e 43 moveon = xfs_action_list_process(ctx, ctx->mnt.fd, alist, flags);
ee310b0c
DW
44 if (!moveon) {
45 *pmoveon = false;
46 return;
47 }
48 new_unfixed = xfs_action_list_length(alist);
49 if (new_unfixed == unfixed)
50 break;
51 unfixed = new_unfixed;
52 } while (unfixed > 0 && *pmoveon);
53
54 if (!*pmoveon)
55 return;
56
57 /* Try once more, but this time complain if we can't fix things. */
06e49f3e 58 flags |= ALP_COMPLAIN_IF_UNFIXED;
3f9efb2e 59 moveon = xfs_action_list_process(ctx, ctx->mnt.fd, alist, flags);
ee310b0c
DW
60 if (!moveon)
61 *pmoveon = false;
62}
63
7e36bc0f
DW
64/* Process all the action items. */
65static bool
66xfs_process_action_items(
67 struct scrub_ctx *ctx)
68{
ee310b0c
DW
69 struct workqueue wq;
70 xfs_agnumber_t agno;
7e36bc0f 71 bool moveon = true;
ee310b0c
DW
72 int ret;
73
74 ret = workqueue_create(&wq, (struct xfs_mount *)ctx,
75 scrub_nproc_workqueue(ctx));
76 if (ret) {
77 str_error(ctx, ctx->mntpoint, _("Could not create workqueue."));
78 return false;
79 }
3f9efb2e 80 for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
ee310b0c
DW
81 if (xfs_action_list_length(&ctx->action_lists[agno]) > 0) {
82 ret = workqueue_add(&wq, xfs_repair_ag, agno, &moveon);
83 if (ret) {
84 moveon = false;
85 str_error(ctx, ctx->mntpoint,
86_("Could not queue repair work."));
87 break;
88 }
89 }
90 if (!moveon)
91 break;
92 }
93 workqueue_destroy(&wq);
7e36bc0f
DW
94
95 pthread_mutex_lock(&ctx->lock);
ed60d210 96 if (moveon && ctx->errors_found == 0 && want_fstrim) {
7e36bc0f 97 fstrim(ctx);
ed60d210
DW
98 progress_add(1);
99 }
7e36bc0f
DW
100 pthread_mutex_unlock(&ctx->lock);
101
102 return moveon;
103}
104
105/* Fix everything that needs fixing. */
106bool
107xfs_repair_fs(
108 struct scrub_ctx *ctx)
109{
110 return xfs_process_action_items(ctx);
111}
112
ed60d210
DW
113/* Estimate how much work we're going to do. */
114bool
115xfs_estimate_repair_work(
116 struct scrub_ctx *ctx,
117 uint64_t *items,
118 unsigned int *nr_threads,
119 int *rshift)
120{
ee310b0c
DW
121 xfs_agnumber_t agno;
122 size_t need_fixing = 0;
123
3f9efb2e 124 for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
ee310b0c
DW
125 need_fixing += xfs_action_list_length(&ctx->action_lists[agno]);
126 need_fixing++;
127 *items = need_fixing;
128 *nr_threads = scrub_nproc(ctx) + 1;
ed60d210
DW
129 *rshift = 0;
130 return true;
131}