]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - scrub/common.c
c4fb3397f1d61104ec803b784216df0ce234fde5
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/statvfs.h>
24 #include "platform_defs.h"
28 #include "xfs_scrub.h"
32 * Reporting Status to the Console
34 * We aim for a roughly standard reporting format -- the severity of the
35 * status being reported, a textual description of the object being
36 * reported, and whatever the status happens to be.
38 * Errors are the most severe and reflect filesystem corruption.
39 * Warnings indicate that something is amiss and needs the attention of
40 * the administrator, but does not constitute a corruption. Information
44 /* Too many errors? Bail out. */
46 xfs_scrub_excessive_errors(
47 struct scrub_ctx
*ctx
)
51 pthread_mutex_lock(&ctx
->lock
);
52 ret
= ctx
->max_errors
> 0 && ctx
->errors_found
>= ctx
->max_errors
;
53 pthread_mutex_unlock(&ctx
->lock
);
58 static const char *err_str
[] = {
64 /* Print a warning string and some warning text. */
67 struct scrub_ctx
*ctx
,
69 enum error_level level
,
76 FILE *stream
= stderr
;
78 char buf
[DESCR_BUFSZ
];
80 /* print strerror or format of choice but not both */
81 assert(!(error
&& format
));
86 pthread_mutex_lock(&ctx
->lock
);
87 fprintf(stream
, "%s: %s: ", _(err_str
[level
]), descr
);
89 fprintf(stream
, _("%s."), strerror_r(error
, buf
, DESCR_BUFSZ
));
91 va_start(args
, format
);
92 vfprintf(stream
, format
, args
);
97 fprintf(stream
, _(" (%s line %d)"), file
, line
);
98 fprintf(stream
, "\n");
102 if (error
) /* A syscall failed */
103 ctx
->runtime_errors
++;
104 else if (level
== S_ERROR
)
106 else if (level
== S_WARN
)
107 ctx
->warnings_found
++;
109 pthread_mutex_unlock(&ctx
->lock
);
117 return ((tv1
->tv_sec
- tv2
->tv_sec
) +
118 ((float) (tv1
->tv_usec
- tv2
->tv_usec
)) / 1000000);
121 /* Produce human readable disk space output. */
124 unsigned long long bytes
,
129 if (bytes
> (1ULL << 40)) {
131 return (double)bytes
/ (1ULL << 40);
132 } else if (bytes
> (1ULL << 30)) {
134 return (double)bytes
/ (1ULL << 30);
135 } else if (bytes
> (1ULL << 20)) {
137 return (double)bytes
/ (1ULL << 20);
138 } else if (bytes
> (1ULL << 10)) {
140 return (double)bytes
/ (1ULL << 10);
148 /* Produce human readable discrete number output. */
151 unsigned long long number
,
156 if (number
> 1000000000000ULL) {
158 return number
/ 1000000000000.0;
159 } else if (number
> 1000000000ULL) {
161 return number
/ 1000000000.0;
162 } else if (number
> 1000000ULL) {
164 return number
/ 1000000.0;
165 } else if (number
> 1000ULL) {
167 return number
/ 1000.0;
175 /* How many threads to kick off? */
178 struct scrub_ctx
*ctx
)
182 return ctx
->nr_io_threads
;
186 * How many threads to kick off for a workqueue? If we only want one
187 * thread, save ourselves the overhead and just run it in the main thread.
190 scrub_nproc_workqueue(
191 struct scrub_ctx
*ctx
)
195 x
= scrub_nproc(ctx
);
202 * Check if the argument is either the device name or mountpoint of a mounted
205 #define MNTTYPE_XFS "xfs"
207 find_mountpoint_check(
213 if (S_ISDIR(sb
->st_mode
)) { /* mount point */
214 if (stat(t
->mnt_dir
, &ms
) < 0)
216 if (sb
->st_ino
!= ms
.st_ino
)
218 if (sb
->st_dev
!= ms
.st_dev
)
220 if (strcmp(t
->mnt_type
, MNTTYPE_XFS
) != 0)
222 } else { /* device */
223 if (stat(t
->mnt_fsname
, &ms
) < 0)
225 if (sb
->st_rdev
!= ms
.st_rdev
)
227 if (strcmp(t
->mnt_type
, MNTTYPE_XFS
) != 0)
230 * Make sure the mountpoint given by mtab is accessible
233 if (stat(t
->mnt_dir
, &ms
) < 0)
240 /* Check that our alleged mountpoint is in mtab */
244 struct scrub_ctx
*ctx
)
246 struct mntent_cursor cursor
;
247 struct mntent
*t
= NULL
;
250 if (platform_mntent_open(&cursor
, mtab
) != 0) {
251 fprintf(stderr
, "Error: can't get mntent entries.\n");
255 while ((t
= platform_mntent_next(&cursor
)) != NULL
) {
257 * Keep jotting down matching mount details; newer mounts are
258 * towards the end of the file (hopefully).
260 if (find_mountpoint_check(&ctx
->mnt_sb
, t
)) {
261 ctx
->mntpoint
= strdup(t
->mnt_dir
);
262 ctx
->blkdev
= strdup(t
->mnt_fsname
);
266 platform_mntent_close(&cursor
);
271 * Sleep for 100ms * however many -b we got past the initial one.
272 * This is an (albeit clumsy) way to throttle scrub activity.
275 background_sleep(void)
277 unsigned long long time
;
283 time
= 100000ULL * (bg_mode
- 1);
284 tv
.tv_sec
= time
/ 1000000;
285 tv
.tv_nsec
= time
% 1000000;
286 nanosleep(&tv
, NULL
);
290 * Return the input string with non-printing bytes escaped.
291 * Caller must free the buffer.
302 str
= malloc(strlen(in
) * 4);
305 for (p
= in
, q
= str
; *p
!= '\0'; p
++) {
310 x
= sprintf(q
, "\\x%02x", *p
);
319 * Record another naming warning, and decide if it's worth
323 should_warn_about_name(
324 struct scrub_ctx
*ctx
)
329 pthread_mutex_lock(&ctx
->lock
);
330 ctx
->naming_warnings
++;
331 whine
= ctx
->naming_warnings
== TOO_MANY_NAME_WARNINGS
;
332 res
= ctx
->naming_warnings
< TOO_MANY_NAME_WARNINGS
;
333 pthread_mutex_unlock(&ctx
->lock
);
335 if (whine
&& !(debug
|| verbose
))
336 str_info(ctx
, ctx
->mntpoint
,
337 _("More than %u naming warnings, shutting up."),
338 TOO_MANY_NAME_WARNINGS
);
340 return debug
|| verbose
|| res
;
343 /* Decide if a value is within +/- (n/d) of a desired value. */
346 struct scrub_ctx
*ctx
,
347 unsigned long long value
,
348 unsigned long long desired
,
349 unsigned long long abs_threshold
,
356 /* Don't complain if difference does not exceed an absolute value. */
357 if (value
< desired
&& desired
- value
< abs_threshold
)
359 if (value
> desired
&& value
- desired
< abs_threshold
)
362 /* Complain if the difference exceeds a certain percentage. */
363 if (value
< desired
* (d
- n
) / d
)
365 if (value
> desired
* (d
+ n
) / d
)