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.
23 #include <sys/types.h>
26 #include <sys/resource.h>
27 #include <sys/statvfs.h>
37 #include "workqueue.h"
43 #include "xfs_format.h"
46 #include "xfs_scrub.h"
51 /* Phase 1: Find filesystem geometry (and clean up after) */
53 /* Shut down the filesystem. */
56 struct scrub_ctx
*ctx
)
60 flag
= XFS_FSOP_GOING_FLAGS_LOGFLUSH
;
61 str_info(ctx
, ctx
->mntpoint
, _("Shutting down filesystem!"));
62 if (ioctl(ctx
->mnt_fd
, XFS_IOC_GOINGDOWN
, &flag
))
63 str_errno(ctx
, ctx
->mntpoint
);
66 /* Clean up the XFS-specific state data. */
69 struct scrub_ctx
*ctx
)
72 free_handle(ctx
->fshandle
, ctx
->fshandle_len
);
74 disk_close(ctx
->rtdev
);
76 disk_close(ctx
->logdev
);
78 disk_close(ctx
->datadev
);
87 * Bind to the mountpoint, read the XFS geometry, bind to the block devices.
88 * Anything we've already built will be cleaned up by xfs_cleanup_fs.
92 struct scrub_ctx
*ctx
)
98 * Open the directory with O_NOATIME. For mountpoints owned
99 * by root, this should be sufficient to ensure that we have
100 * CAP_SYS_ADMIN, which we probably need to do anything fancy
101 * with the (XFS driver) kernel.
103 ctx
->mnt_fd
= open(ctx
->mntpoint
, O_RDONLY
| O_NOATIME
| O_DIRECTORY
);
104 if (ctx
->mnt_fd
< 0) {
106 str_info(ctx
, ctx
->mntpoint
,
107 _("Must be root to run scrub."));
109 str_errno(ctx
, ctx
->mntpoint
);
113 error
= fstat(ctx
->mnt_fd
, &ctx
->mnt_sb
);
115 str_errno(ctx
, ctx
->mntpoint
);
118 error
= fstatvfs(ctx
->mnt_fd
, &ctx
->mnt_sv
);
120 str_errno(ctx
, ctx
->mntpoint
);
123 error
= fstatfs(ctx
->mnt_fd
, &ctx
->mnt_sf
);
125 str_errno(ctx
, ctx
->mntpoint
);
129 ctx
->nr_io_threads
= nproc
;
131 fprintf(stdout
, _("%s: using %d threads to scrub.\n"),
132 ctx
->mntpoint
, scrub_nproc(ctx
));
136 if (!platform_test_xfs_fd(ctx
->mnt_fd
)) {
137 str_error(ctx
, ctx
->mntpoint
,
138 _("Does not appear to be an XFS filesystem!"));
143 * Flush everything out to disk before we start checking.
144 * This seems to reduce the incidence of stale file handle
145 * errors when we open things by handle.
147 error
= syncfs(ctx
->mnt_fd
);
149 str_errno(ctx
, ctx
->mntpoint
);
153 /* Retrieve XFS geometry. */
154 error
= ioctl(ctx
->mnt_fd
, XFS_IOC_FSGEOMETRY
, &ctx
->geo
);
156 str_errno(ctx
, ctx
->mntpoint
);
160 ctx
->agblklog
= log2_roundup(ctx
->geo
.agblocks
);
161 ctx
->blocklog
= highbit32(ctx
->geo
.blocksize
);
162 ctx
->inodelog
= highbit32(ctx
->geo
.inodesize
);
163 ctx
->inopblog
= ctx
->blocklog
- ctx
->inodelog
;
165 error
= path_to_fshandle(ctx
->mntpoint
, &ctx
->fshandle
,
168 str_errno(ctx
, _("getting fshandle"));
172 /* Do we have kernel-assisted metadata scrubbing? */
173 if (!xfs_can_scrub_fs_metadata(ctx
) || !xfs_can_scrub_inode(ctx
) ||
174 !xfs_can_scrub_bmap(ctx
) || !xfs_can_scrub_dir(ctx
) ||
175 !xfs_can_scrub_attr(ctx
) || !xfs_can_scrub_symlink(ctx
) ||
176 !xfs_can_scrub_parent(ctx
)) {
177 str_error(ctx
, ctx
->mntpoint
,
178 _("Kernel metadata scrubbing facility is not available."));
182 /* Do we need kernel-assisted metadata repair? */
183 if (ctx
->mode
!= SCRUB_MODE_DRY_RUN
&& !xfs_can_repair(ctx
)) {
184 if (ctx
->mode
== SCRUB_MODE_PREEN
)
185 str_error(ctx
, ctx
->mntpoint
,
186 _("Kernel metadata optimization facility is not available. Use -n to scrub."));
188 str_error(ctx
, ctx
->mntpoint
,
189 _("Kernel metadata repair facility is not available. Use -n to scrub."));
193 /* Go find the XFS devices if we have a usable fsmap. */
194 fs_table_initialise(0, NULL
, 0, NULL
);
196 fsp
= fs_table_lookup(ctx
->mntpoint
, FS_MOUNT_POINT
);
198 str_error(ctx
, ctx
->mntpoint
,
199 _("Unable to find XFS information."));
202 memcpy(&ctx
->fsinfo
, fsp
, sizeof(struct fs_path
));
204 /* Did we find the log and rt devices, if they're present? */
205 if (ctx
->geo
.logstart
== 0 && ctx
->fsinfo
.fs_log
== NULL
) {
206 str_error(ctx
, ctx
->mntpoint
,
207 _("Unable to find log device path."));
210 if (ctx
->geo
.rtblocks
&& ctx
->fsinfo
.fs_rt
== NULL
) {
211 str_error(ctx
, ctx
->mntpoint
,
212 _("Unable to find realtime device path."));
216 /* Open the raw devices. */
217 ctx
->datadev
= disk_open(ctx
->fsinfo
.fs_name
);
219 str_errno(ctx
, ctx
->fsinfo
.fs_name
);
223 if (ctx
->fsinfo
.fs_log
) {
224 ctx
->logdev
= disk_open(ctx
->fsinfo
.fs_log
);
226 str_errno(ctx
, ctx
->fsinfo
.fs_name
);
230 if (ctx
->fsinfo
.fs_rt
) {
231 ctx
->rtdev
= disk_open(ctx
->fsinfo
.fs_rt
);
233 str_errno(ctx
, ctx
->fsinfo
.fs_name
);
239 * Everything's set up, which means any failures recorded after
240 * this point are most probably corruption errors (as opposed to
241 * purely setup errors).
243 ctx
->need_repair
= true;