]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - scrub/phase3.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>
9 #include <sys/statvfs.h>
11 #include "libfrog/paths.h"
12 #include "libfrog/workqueue.h"
13 #include "xfs_scrub.h"
21 /* Phase 3: Scan all inodes. */
24 * Run a per-file metadata scanner. We use the ino/gen interface to
25 * ensure that the inode we're checking matches what the inode scan
30 struct scrub_ctx
*ctx
,
31 bool (*fn
)(struct scrub_ctx
*, uint64_t,
32 uint32_t, int, struct xfs_action_list
*),
34 struct xfs_action_list
*alist
)
36 return fn(ctx
, bs
->bs_ino
, bs
->bs_gen
, ctx
->mnt
.fd
, alist
);
39 struct scrub_inode_ctx
{
40 struct ptcounter
*icount
;
44 /* Report a filesystem error that the vfs fed us on close. */
46 xfs_scrub_inode_vfs_error(
47 struct scrub_ctx
*ctx
,
48 struct xfs_bstat
*bstat
)
50 char descr
[DESCR_BUFSZ
];
53 int old_errno
= errno
;
55 agno
= cvt_ino_to_agno(&ctx
->mnt
, bstat
->bs_ino
);
56 agino
= cvt_ino_to_agino(&ctx
->mnt
, bstat
->bs_ino
);
57 snprintf(descr
, DESCR_BUFSZ
, _("inode %"PRIu64
" (%u/%u)"),
58 (uint64_t)bstat
->bs_ino
, agno
, agino
);
60 str_errno(ctx
, descr
);
63 /* Verify the contents, xattrs, and extent maps of an inode. */
66 struct scrub_ctx
*ctx
,
67 struct xfs_handle
*handle
,
68 struct xfs_bstat
*bstat
,
71 struct xfs_action_list alist
;
72 struct scrub_inode_ctx
*ictx
= arg
;
73 struct ptcounter
*icount
= ictx
->icount
;
79 xfs_action_list_init(&alist
);
80 agno
= cvt_ino_to_agno(&ctx
->mnt
, bstat
->bs_ino
);
83 /* Try to open the inode to pin it. */
84 if (S_ISREG(bstat
->bs_mode
)) {
85 fd
= xfs_open_handle(handle
);
86 /* Stale inode means we scan the whole cluster again. */
87 if (fd
< 0 && errno
== ESTALE
)
91 /* Scrub the inode. */
92 moveon
= xfs_scrub_fd(ctx
, xfs_scrub_inode_fields
, bstat
, &alist
);
96 moveon
= xfs_action_list_process_or_defer(ctx
, agno
, &alist
);
100 /* Scrub all block mappings. */
101 moveon
= xfs_scrub_fd(ctx
, xfs_scrub_data_fork
, bstat
, &alist
);
104 moveon
= xfs_scrub_fd(ctx
, xfs_scrub_attr_fork
, bstat
, &alist
);
107 moveon
= xfs_scrub_fd(ctx
, xfs_scrub_cow_fork
, bstat
, &alist
);
111 moveon
= xfs_action_list_process_or_defer(ctx
, agno
, &alist
);
115 if (S_ISLNK(bstat
->bs_mode
)) {
116 /* Check symlink contents. */
117 moveon
= xfs_scrub_symlink(ctx
, bstat
->bs_ino
,
118 bstat
->bs_gen
, ctx
->mnt
.fd
, &alist
);
119 } else if (S_ISDIR(bstat
->bs_mode
)) {
120 /* Check the directory entries. */
121 moveon
= xfs_scrub_fd(ctx
, xfs_scrub_dir
, bstat
, &alist
);
126 /* Check all the extended attributes. */
127 moveon
= xfs_scrub_fd(ctx
, xfs_scrub_attr
, bstat
, &alist
);
131 /* Check parent pointers. */
132 moveon
= xfs_scrub_fd(ctx
, xfs_scrub_parent
, bstat
, &alist
);
136 /* Try to repair the file while it's open. */
137 moveon
= xfs_action_list_process_or_defer(ctx
, agno
, &alist
);
142 ptcounter_add(icount
, 1);
144 xfs_action_list_defer(ctx
, agno
, &alist
);
148 xfs_scrub_inode_vfs_error(ctx
, bstat
);
151 ictx
->moveon
= false;
152 return ictx
->moveon
? 0 : XFS_ITERATE_INODES_ABORT
;
155 /* Verify all the inodes in a filesystem. */
158 struct scrub_ctx
*ctx
)
160 struct scrub_inode_ctx ictx
;
164 ictx
.icount
= ptcounter_init(scrub_nproc(ctx
));
166 str_info(ctx
, ctx
->mntpoint
, _("Could not create counter."));
170 ret
= xfs_scan_all_inodes(ctx
, xfs_scrub_inode
, &ictx
);
175 xfs_scrub_report_preen_triggers(ctx
);
176 ctx
->inodes_checked
= ptcounter_value(ictx
.icount
);
179 ptcounter_free(ictx
.icount
);
183 /* Estimate how much work we're going to do. */
185 xfs_estimate_inodes_work(
186 struct scrub_ctx
*ctx
,
188 unsigned int *nr_threads
,
191 *items
= ctx
->mnt_sv
.f_files
- ctx
->mnt_sv
.f_ffree
;
192 *nr_threads
= scrub_nproc(ctx
);