]>
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 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. */ |
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; | |
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. */ |
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) { | |
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. */ | |
106 | bool | |
107 | xfs_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. */ |
114 | bool | |
115 | xfs_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 | } |