]>
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.
24 #include <sys/statvfs.h>
25 #include "workqueue.h"
27 #include "xfs_scrub.h"
32 * Filesystem space map iterators.
34 * Logically, we call GETFSMAP to fetch a set of space map records and
35 * call a function to iterate over the records. However, that's not
36 * what actually happens -- the work is split into separate items, with
37 * each AG, the realtime device, and the log device getting their own
38 * work items. For an XFS with a realtime device and an external log,
39 * this means that we can have up to ($agcount + 2) threads running at
42 * This comes into play if we want to have per-workitem memory. Maybe.
43 * XXX: do we really need all that ?
46 #define FSMAP_NR 65536
48 /* Iterate all the fs block mappings between the two keys. */
51 struct scrub_ctx
*ctx
,
57 struct fsmap_head
*head
;
63 head
= malloc(fsmap_sizeof(FSMAP_NR
));
65 str_errno(ctx
, descr
);
69 memset(head
, 0, sizeof(*head
));
70 memcpy(head
->fmh_keys
, keys
, sizeof(struct fsmap
) * 2);
71 head
->fmh_count
= FSMAP_NR
;
73 while ((error
= ioctl(ctx
->mnt_fd
, FS_IOC_GETFSMAP
, head
)) == 0) {
74 for (i
= 0, p
= head
->fmh_recs
;
75 i
< head
->fmh_entries
;
77 moveon
= fn(ctx
, descr
, p
, arg
);
80 if (xfs_scrub_excessive_errors(ctx
)) {
86 if (head
->fmh_entries
== 0)
88 p
= &head
->fmh_recs
[head
->fmh_entries
- 1];
89 if (p
->fmr_flags
& FMR_OF_LAST
)
95 str_errno(ctx
, descr
);
103 /* GETFSMAP wrappers routines. */
104 struct xfs_scan_blocks
{
105 xfs_fsmap_iter_fn fn
;
110 /* Iterate all the reverse mappings of an AG. */
113 struct workqueue
*wq
,
117 struct scrub_ctx
*ctx
= (struct scrub_ctx
*)wq
->wq_ctx
;
118 struct xfs_scan_blocks
*sbx
= arg
;
119 char descr
[DESCR_BUFSZ
];
120 struct fsmap keys
[2];
124 bperag
= (off64_t
)ctx
->geo
.agblocks
*
125 (off64_t
)ctx
->geo
.blocksize
;
127 snprintf(descr
, DESCR_BUFSZ
, _("dev %d:%d AG %u fsmap"),
128 major(ctx
->fsinfo
.fs_datadev
),
129 minor(ctx
->fsinfo
.fs_datadev
),
132 memset(keys
, 0, sizeof(struct fsmap
) * 2);
133 keys
->fmr_device
= ctx
->fsinfo
.fs_datadev
;
134 keys
->fmr_physical
= agno
* bperag
;
135 (keys
+ 1)->fmr_device
= ctx
->fsinfo
.fs_datadev
;
136 (keys
+ 1)->fmr_physical
= ((agno
+ 1) * bperag
) - 1;
137 (keys
+ 1)->fmr_owner
= ULLONG_MAX
;
138 (keys
+ 1)->fmr_offset
= ULLONG_MAX
;
139 (keys
+ 1)->fmr_flags
= UINT_MAX
;
141 moveon
= xfs_iterate_fsmap(ctx
, descr
, keys
, sbx
->fn
, sbx
->arg
);
146 /* Iterate all the reverse mappings of a standalone device. */
149 struct scrub_ctx
*ctx
,
152 struct xfs_scan_blocks
*sbx
)
154 struct fsmap keys
[2];
155 char descr
[DESCR_BUFSZ
];
158 snprintf(descr
, DESCR_BUFSZ
, _("dev %d:%d fsmap"),
159 major(dev
), minor(dev
));
161 memset(keys
, 0, sizeof(struct fsmap
) * 2);
162 keys
->fmr_device
= dev
;
163 (keys
+ 1)->fmr_device
= dev
;
164 (keys
+ 1)->fmr_physical
= ULLONG_MAX
;
165 (keys
+ 1)->fmr_owner
= ULLONG_MAX
;
166 (keys
+ 1)->fmr_offset
= ULLONG_MAX
;
167 (keys
+ 1)->fmr_flags
= UINT_MAX
;
169 moveon
= xfs_iterate_fsmap(ctx
, descr
, keys
, sbx
->fn
, sbx
->arg
);
174 /* Iterate all the reverse mappings of the realtime device. */
177 struct workqueue
*wq
,
181 struct scrub_ctx
*ctx
= (struct scrub_ctx
*)wq
->wq_ctx
;
183 xfs_scan_dev_blocks(ctx
, agno
, ctx
->fsinfo
.fs_rtdev
, arg
);
186 /* Iterate all the reverse mappings of the log device. */
189 struct workqueue
*wq
,
193 struct scrub_ctx
*ctx
= (struct scrub_ctx
*)wq
->wq_ctx
;
195 xfs_scan_dev_blocks(ctx
, agno
, ctx
->fsinfo
.fs_logdev
, arg
);
198 /* Scan all the blocks in a filesystem. */
200 xfs_scan_all_spacemaps(
201 struct scrub_ctx
*ctx
,
202 xfs_fsmap_iter_fn fn
,
206 struct xfs_scan_blocks sbx
;
214 ret
= workqueue_create(&wq
, (struct xfs_mount
*)ctx
,
215 scrub_nproc_workqueue(ctx
));
217 str_info(ctx
, ctx
->mntpoint
, _("Could not create workqueue."));
220 if (ctx
->fsinfo
.fs_rt
) {
221 ret
= workqueue_add(&wq
, xfs_scan_rt_blocks
,
222 ctx
->geo
.agcount
+ 1, &sbx
);
225 str_info(ctx
, ctx
->mntpoint
,
226 _("Could not queue rtdev fsmap work."));
230 if (ctx
->fsinfo
.fs_log
) {
231 ret
= workqueue_add(&wq
, xfs_scan_log_blocks
,
232 ctx
->geo
.agcount
+ 2, &sbx
);
235 str_info(ctx
, ctx
->mntpoint
,
236 _("Could not queue logdev fsmap work."));
240 for (agno
= 0; agno
< ctx
->geo
.agcount
; agno
++) {
241 ret
= workqueue_add(&wq
, xfs_scan_ag_blocks
, agno
, &sbx
);
244 str_info(ctx
, ctx
->mntpoint
,
245 _("Could not queue AG %u fsmap work."), agno
);
250 workqueue_destroy(&wq
);