]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - scrub/spacemap.c
2 * Copyright (C) 2018 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it would be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include <sys/statvfs.h>
26 #include "workqueue.h"
30 #include "xfs_scrub.h"
35 * Filesystem space map iterators.
37 * Logically, we call GETFSMAP to fetch a set of space map records and
38 * call a function to iterate over the records. However, that's not
39 * what actually happens -- the work is split into separate items, with
40 * each AG, the realtime device, and the log device getting their own
41 * work items. For an XFS with a realtime device and an external log,
42 * this means that we can have up to ($agcount + 2) threads running at
45 * This comes into play if we want to have per-workitem memory. Maybe.
46 * XXX: do we really need all that ?
49 #define FSMAP_NR 65536
51 /* Iterate all the fs block mappings between the two keys. */
54 struct scrub_ctx
*ctx
,
60 struct fsmap_head
*head
;
66 head
= malloc(fsmap_sizeof(FSMAP_NR
));
68 str_errno(ctx
, descr
);
72 memset(head
, 0, sizeof(*head
));
73 memcpy(head
->fmh_keys
, keys
, sizeof(struct fsmap
) * 2);
74 head
->fmh_count
= FSMAP_NR
;
76 while ((error
= ioctl(ctx
->mnt_fd
, FS_IOC_GETFSMAP
, head
)) == 0) {
77 for (i
= 0, p
= head
->fmh_recs
;
78 i
< head
->fmh_entries
;
80 moveon
= fn(ctx
, descr
, p
, arg
);
83 if (xfs_scrub_excessive_errors(ctx
)) {
89 if (head
->fmh_entries
== 0)
91 p
= &head
->fmh_recs
[head
->fmh_entries
- 1];
92 if (p
->fmr_flags
& FMR_OF_LAST
)
98 str_errno(ctx
, descr
);
106 /* GETFSMAP wrappers routines. */
107 struct xfs_scan_blocks
{
108 xfs_fsmap_iter_fn fn
;
113 /* Iterate all the reverse mappings of an AG. */
116 struct workqueue
*wq
,
120 struct scrub_ctx
*ctx
= (struct scrub_ctx
*)wq
->wq_ctx
;
121 struct xfs_scan_blocks
*sbx
= arg
;
122 char descr
[DESCR_BUFSZ
];
123 struct fsmap keys
[2];
127 bperag
= (off64_t
)ctx
->geo
.agblocks
*
128 (off64_t
)ctx
->geo
.blocksize
;
130 snprintf(descr
, DESCR_BUFSZ
, _("dev %d:%d AG %u fsmap"),
131 major(ctx
->fsinfo
.fs_datadev
),
132 minor(ctx
->fsinfo
.fs_datadev
),
135 memset(keys
, 0, sizeof(struct fsmap
) * 2);
136 keys
->fmr_device
= ctx
->fsinfo
.fs_datadev
;
137 keys
->fmr_physical
= agno
* bperag
;
138 (keys
+ 1)->fmr_device
= ctx
->fsinfo
.fs_datadev
;
139 (keys
+ 1)->fmr_physical
= ((agno
+ 1) * bperag
) - 1;
140 (keys
+ 1)->fmr_owner
= ULLONG_MAX
;
141 (keys
+ 1)->fmr_offset
= ULLONG_MAX
;
142 (keys
+ 1)->fmr_flags
= UINT_MAX
;
144 moveon
= xfs_iterate_fsmap(ctx
, descr
, keys
, sbx
->fn
, sbx
->arg
);
149 /* Iterate all the reverse mappings of a standalone device. */
152 struct scrub_ctx
*ctx
,
155 struct xfs_scan_blocks
*sbx
)
157 struct fsmap keys
[2];
158 char descr
[DESCR_BUFSZ
];
161 snprintf(descr
, DESCR_BUFSZ
, _("dev %d:%d fsmap"),
162 major(dev
), minor(dev
));
164 memset(keys
, 0, sizeof(struct fsmap
) * 2);
165 keys
->fmr_device
= dev
;
166 (keys
+ 1)->fmr_device
= dev
;
167 (keys
+ 1)->fmr_physical
= ULLONG_MAX
;
168 (keys
+ 1)->fmr_owner
= ULLONG_MAX
;
169 (keys
+ 1)->fmr_offset
= ULLONG_MAX
;
170 (keys
+ 1)->fmr_flags
= UINT_MAX
;
172 moveon
= xfs_iterate_fsmap(ctx
, descr
, keys
, sbx
->fn
, sbx
->arg
);
177 /* Iterate all the reverse mappings of the realtime device. */
180 struct workqueue
*wq
,
184 struct scrub_ctx
*ctx
= (struct scrub_ctx
*)wq
->wq_ctx
;
186 xfs_scan_dev_blocks(ctx
, agno
, ctx
->fsinfo
.fs_rtdev
, arg
);
189 /* Iterate all the reverse mappings of the log device. */
192 struct workqueue
*wq
,
196 struct scrub_ctx
*ctx
= (struct scrub_ctx
*)wq
->wq_ctx
;
198 xfs_scan_dev_blocks(ctx
, agno
, ctx
->fsinfo
.fs_logdev
, arg
);
201 /* Scan all the blocks in a filesystem. */
203 xfs_scan_all_spacemaps(
204 struct scrub_ctx
*ctx
,
205 xfs_fsmap_iter_fn fn
,
209 struct xfs_scan_blocks sbx
;
217 ret
= workqueue_create(&wq
, (struct xfs_mount
*)ctx
,
218 scrub_nproc_workqueue(ctx
));
220 str_info(ctx
, ctx
->mntpoint
, _("Could not create workqueue."));
223 if (ctx
->fsinfo
.fs_rt
) {
224 ret
= workqueue_add(&wq
, xfs_scan_rt_blocks
,
225 ctx
->geo
.agcount
+ 1, &sbx
);
228 str_info(ctx
, ctx
->mntpoint
,
229 _("Could not queue rtdev fsmap work."));
233 if (ctx
->fsinfo
.fs_log
) {
234 ret
= workqueue_add(&wq
, xfs_scan_log_blocks
,
235 ctx
->geo
.agcount
+ 2, &sbx
);
238 str_info(ctx
, ctx
->mntpoint
,
239 _("Could not queue logdev fsmap work."));
243 for (agno
= 0; agno
< ctx
->geo
.agcount
; agno
++) {
244 ret
= workqueue_add(&wq
, xfs_scan_ag_blocks
, agno
, &sbx
);
247 str_info(ctx
, ctx
->mntpoint
,
248 _("Could not queue AG %u fsmap work."), agno
);
253 workqueue_destroy(&wq
);