]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - scrub/spacemap.c
1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2018 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
10 #include <sys/statvfs.h>
11 #include "libfrog/workqueue.h"
12 #include "libfrog/paths.h"
13 #include "xfs_scrub.h"
18 * Filesystem space map iterators.
20 * Logically, we call GETFSMAP to fetch a set of space map records and
21 * call a function to iterate over the records. However, that's not
22 * what actually happens -- the work is split into separate items, with
23 * each AG, the realtime device, and the log device getting their own
24 * work items. For an XFS with a realtime device and an external log,
25 * this means that we can have up to ($agcount + 2) threads running at
28 * This comes into play if we want to have per-workitem memory. Maybe.
29 * XXX: do we really need all that ?
32 #define FSMAP_NR 65536
34 /* Iterate all the fs block mappings between the two keys. */
37 struct scrub_ctx
*ctx
,
43 struct fsmap_head
*head
;
49 head
= malloc(fsmap_sizeof(FSMAP_NR
));
51 str_errno(ctx
, descr
);
55 memset(head
, 0, sizeof(*head
));
56 memcpy(head
->fmh_keys
, keys
, sizeof(struct fsmap
) * 2);
57 head
->fmh_count
= FSMAP_NR
;
59 while ((error
= ioctl(ctx
->mnt
.fd
, FS_IOC_GETFSMAP
, head
)) == 0) {
60 for (i
= 0, p
= head
->fmh_recs
;
61 i
< head
->fmh_entries
;
63 moveon
= fn(ctx
, descr
, p
, arg
);
66 if (xfs_scrub_excessive_errors(ctx
)) {
72 if (head
->fmh_entries
== 0)
74 p
= &head
->fmh_recs
[head
->fmh_entries
- 1];
75 if (p
->fmr_flags
& FMR_OF_LAST
)
81 str_errno(ctx
, descr
);
89 /* GETFSMAP wrappers routines. */
90 struct xfs_scan_blocks
{
96 /* Iterate all the reverse mappings of an AG. */
103 struct scrub_ctx
*ctx
= (struct scrub_ctx
*)wq
->wq_ctx
;
104 struct xfs_scan_blocks
*sbx
= arg
;
105 char descr
[DESCR_BUFSZ
];
106 struct fsmap keys
[2];
110 bperag
= (off64_t
)ctx
->mnt
.fsgeom
.agblocks
*
111 (off64_t
)ctx
->mnt
.fsgeom
.blocksize
;
113 snprintf(descr
, DESCR_BUFSZ
, _("dev %d:%d AG %u fsmap"),
114 major(ctx
->fsinfo
.fs_datadev
),
115 minor(ctx
->fsinfo
.fs_datadev
),
118 memset(keys
, 0, sizeof(struct fsmap
) * 2);
119 keys
->fmr_device
= ctx
->fsinfo
.fs_datadev
;
120 keys
->fmr_physical
= agno
* bperag
;
121 (keys
+ 1)->fmr_device
= ctx
->fsinfo
.fs_datadev
;
122 (keys
+ 1)->fmr_physical
= ((agno
+ 1) * bperag
) - 1;
123 (keys
+ 1)->fmr_owner
= ULLONG_MAX
;
124 (keys
+ 1)->fmr_offset
= ULLONG_MAX
;
125 (keys
+ 1)->fmr_flags
= UINT_MAX
;
127 moveon
= xfs_iterate_fsmap(ctx
, descr
, keys
, sbx
->fn
, sbx
->arg
);
132 /* Iterate all the reverse mappings of a standalone device. */
135 struct scrub_ctx
*ctx
,
138 struct xfs_scan_blocks
*sbx
)
140 struct fsmap keys
[2];
141 char descr
[DESCR_BUFSZ
];
144 snprintf(descr
, DESCR_BUFSZ
, _("dev %d:%d fsmap"),
145 major(dev
), minor(dev
));
147 memset(keys
, 0, sizeof(struct fsmap
) * 2);
148 keys
->fmr_device
= dev
;
149 (keys
+ 1)->fmr_device
= dev
;
150 (keys
+ 1)->fmr_physical
= ULLONG_MAX
;
151 (keys
+ 1)->fmr_owner
= ULLONG_MAX
;
152 (keys
+ 1)->fmr_offset
= ULLONG_MAX
;
153 (keys
+ 1)->fmr_flags
= UINT_MAX
;
155 moveon
= xfs_iterate_fsmap(ctx
, descr
, keys
, sbx
->fn
, sbx
->arg
);
160 /* Iterate all the reverse mappings of the realtime device. */
163 struct workqueue
*wq
,
167 struct scrub_ctx
*ctx
= (struct scrub_ctx
*)wq
->wq_ctx
;
169 xfs_scan_dev_blocks(ctx
, agno
, ctx
->fsinfo
.fs_rtdev
, arg
);
172 /* Iterate all the reverse mappings of the log device. */
175 struct workqueue
*wq
,
179 struct scrub_ctx
*ctx
= (struct scrub_ctx
*)wq
->wq_ctx
;
181 xfs_scan_dev_blocks(ctx
, agno
, ctx
->fsinfo
.fs_logdev
, arg
);
184 /* Scan all the blocks in a filesystem. */
186 xfs_scan_all_spacemaps(
187 struct scrub_ctx
*ctx
,
188 xfs_fsmap_iter_fn fn
,
192 struct xfs_scan_blocks sbx
;
200 ret
= workqueue_create(&wq
, (struct xfs_mount
*)ctx
,
201 scrub_nproc_workqueue(ctx
));
203 str_liberror(ctx
, ret
, _("creating fsmap workqueue"));
206 if (ctx
->fsinfo
.fs_rt
) {
207 ret
= workqueue_add(&wq
, xfs_scan_rt_blocks
,
208 ctx
->mnt
.fsgeom
.agcount
+ 1, &sbx
);
211 str_liberror(ctx
, ret
, _("queueing rtdev fsmap work"));
215 if (ctx
->fsinfo
.fs_log
) {
216 ret
= workqueue_add(&wq
, xfs_scan_log_blocks
,
217 ctx
->mnt
.fsgeom
.agcount
+ 2, &sbx
);
220 str_liberror(ctx
, ret
, _("queueing logdev fsmap work"));
224 for (agno
= 0; agno
< ctx
->mnt
.fsgeom
.agcount
; agno
++) {
225 ret
= workqueue_add(&wq
, xfs_scan_ag_blocks
, agno
, &sbx
);
228 str_liberror(ctx
, ret
, _("queueing per-AG fsmap work"));
233 workqueue_destroy(&wq
);