]>
Commit | Line | Data |
---|---|---|
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 | 11 | #include "list.h" |
42b4c8e8 | 12 | #include "libfrog/paths.h" |
56598728 | 13 | #include "libfrog/workqueue.h" |
7e36bc0f DW |
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. */ |
24 | static void | |
25 | xfs_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; | |
83d2c80b | 32 | struct action_list *alist; |
ee310b0c DW |
33 | size_t unfixed; |
34 | size_t new_unfixed; | |
35 | unsigned int flags = 0; | |
83d2c80b | 36 | int ret; |
ee310b0c DW |
37 | |
38 | alist = &ctx->action_lists[agno]; | |
83d2c80b | 39 | unfixed = action_list_length(alist); |
ee310b0c DW |
40 | |
41 | /* Repair anything broken until we fail to make progress. */ | |
42 | do { | |
83d2c80b DW |
43 | ret = action_list_process(ctx, ctx->mnt.fd, alist, flags); |
44 | if (ret) { | |
ee310b0c DW |
45 | *pmoveon = false; |
46 | return; | |
47 | } | |
83d2c80b | 48 | new_unfixed = action_list_length(alist); |
ee310b0c DW |
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; |
83d2c80b DW |
59 | ret = action_list_process(ctx, ctx->mnt.fd, alist, flags); |
60 | if (ret) | |
ee310b0c DW |
61 | *pmoveon = false; |
62 | } | |
63 | ||
7e36bc0f DW |
64 | /* Process all the action items. */ |
65 | static bool | |
66 | xfs_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) { | |
9d57cbfc | 77 | str_liberror(ctx, ret, _("creating repair workqueue")); |
ee310b0c DW |
78 | return false; |
79 | } | |
3f9efb2e | 80 | for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) { |
83d2c80b | 81 | if (action_list_length(&ctx->action_lists[agno]) > 0) { |
ee310b0c DW |
82 | ret = workqueue_add(&wq, xfs_repair_ag, agno, &moveon); |
83 | if (ret) { | |
84 | moveon = false; | |
9d57cbfc DW |
85 | str_liberror(ctx, ret, |
86 | _("queueing repair work")); | |
ee310b0c DW |
87 | break; |
88 | } | |
89 | } | |
90 | if (!moveon) | |
91 | break; | |
92 | } | |
71296cf8 DW |
93 | |
94 | ret = workqueue_terminate(&wq); | |
95 | if (ret) { | |
96 | moveon = false; | |
97 | str_liberror(ctx, ret, _("finishing repair work")); | |
98 | } | |
ee310b0c | 99 | workqueue_destroy(&wq); |
7e36bc0f DW |
100 | |
101 | pthread_mutex_lock(&ctx->lock); | |
49e05cb0 DW |
102 | if (moveon && |
103 | ctx->corruptions_found == 0 && | |
104 | ctx->unfixable_errors == 0 && | |
105 | want_fstrim) { | |
7e36bc0f | 106 | fstrim(ctx); |
ed60d210 DW |
107 | progress_add(1); |
108 | } | |
7e36bc0f DW |
109 | pthread_mutex_unlock(&ctx->lock); |
110 | ||
111 | return moveon; | |
112 | } | |
113 | ||
114 | /* Fix everything that needs fixing. */ | |
115 | bool | |
116 | xfs_repair_fs( | |
d22f2471 | 117 | struct scrub_ctx *ctx) |
7e36bc0f | 118 | { |
d22f2471 | 119 | int ret; |
cbaf1c9d DW |
120 | |
121 | /* | |
122 | * Check the summary counters early. Normally we do this during phase | |
123 | * seven, but some of the cross-referencing requires fairly-accurate | |
124 | * counters, so counter repairs have to be put on the list now so that | |
125 | * they get fixed before we stop retrying unfixed metadata repairs. | |
126 | */ | |
d22f2471 DW |
127 | ret = xfs_scrub_fs_summary(ctx, &ctx->action_lists[0]); |
128 | if (ret) | |
cbaf1c9d DW |
129 | return false; |
130 | ||
7e36bc0f DW |
131 | return xfs_process_action_items(ctx); |
132 | } | |
133 | ||
ed60d210 DW |
134 | /* Estimate how much work we're going to do. */ |
135 | bool | |
136 | xfs_estimate_repair_work( | |
137 | struct scrub_ctx *ctx, | |
138 | uint64_t *items, | |
139 | unsigned int *nr_threads, | |
140 | int *rshift) | |
141 | { | |
ee310b0c DW |
142 | xfs_agnumber_t agno; |
143 | size_t need_fixing = 0; | |
144 | ||
3f9efb2e | 145 | for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) |
83d2c80b | 146 | need_fixing += action_list_length(&ctx->action_lists[agno]); |
ee310b0c DW |
147 | need_fixing++; |
148 | *items = need_fixing; | |
149 | *nr_threads = scrub_nproc(ctx) + 1; | |
ed60d210 DW |
150 | *rshift = 0; |
151 | return true; | |
152 | } |