]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - scrub/common.c
xfs_scrub: dispatch the various phases of the scrub program
[thirdparty/xfsprogs-dev.git] / scrub / common.c
1 /*
2 * Copyright (C) 2018 Oracle. All Rights Reserved.
3 *
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 *
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.
10 *
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.
15 *
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.
19 */
20 #include <stdio.h>
21 #include <pthread.h>
22 #include <stdbool.h>
23 #include "platform_defs.h"
24 #include "xfs.h"
25 #include "xfs_scrub.h"
26 #include "common.h"
27
28 /*
29 * Reporting Status to the Console
30 *
31 * We aim for a roughly standard reporting format -- the severity of the
32 * status being reported, a textual description of the object being
33 * reported, and whatever the status happens to be.
34 *
35 * Errors are the most severe and reflect filesystem corruption.
36 * Warnings indicate that something is amiss and needs the attention of
37 * the administrator, but does not constitute a corruption. Information
38 * is merely advisory.
39 */
40
41 /* Too many errors? Bail out. */
42 bool
43 xfs_scrub_excessive_errors(
44 struct scrub_ctx *ctx)
45 {
46 bool ret;
47
48 pthread_mutex_lock(&ctx->lock);
49 ret = ctx->max_errors > 0 && ctx->errors_found >= ctx->max_errors;
50 pthread_mutex_unlock(&ctx->lock);
51
52 return ret;
53 }
54
55 static const char *err_str[] = {
56 [S_ERROR] = "Error",
57 [S_WARN] = "Warning",
58 [S_INFO] = "Info",
59 };
60
61 /* Print a warning string and some warning text. */
62 void
63 __str_out(
64 struct scrub_ctx *ctx,
65 const char *descr,
66 enum error_level level,
67 int error,
68 const char *file,
69 int line,
70 const char *format,
71 ...)
72 {
73 FILE *stream = stderr;
74 va_list args;
75 char buf[DESCR_BUFSZ];
76
77 /* print strerror or format of choice but not both */
78 assert(!(error && format));
79
80 if (level >= S_INFO)
81 stream = stdout;
82
83 pthread_mutex_lock(&ctx->lock);
84 fprintf(stream, "%s: %s: ", _(err_str[level]), descr);
85 if (error) {
86 fprintf(stream, _("%s."), strerror_r(error, buf, DESCR_BUFSZ));
87 } else {
88 va_start(args, format);
89 vfprintf(stream, format, args);
90 va_end(args);
91 }
92
93 if (debug)
94 fprintf(stream, _(" (%s line %d)"), file, line);
95 fprintf(stream, "\n");
96 if (stream == stdout)
97 fflush(stream);
98
99 if (error) /* A syscall failed */
100 ctx->runtime_errors++;
101 else if (level == S_ERROR)
102 ctx->errors_found++;
103 else if (level == S_WARN)
104 ctx->warnings_found++;
105
106 pthread_mutex_unlock(&ctx->lock);
107 }
108
109 double
110 timeval_subtract(
111 struct timeval *tv1,
112 struct timeval *tv2)
113 {
114 return ((tv1->tv_sec - tv2->tv_sec) +
115 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
116 }
117
118 /* Produce human readable disk space output. */
119 double
120 auto_space_units(
121 unsigned long long bytes,
122 char **units)
123 {
124 if (debug > 1)
125 goto no_prefix;
126 if (bytes > (1ULL << 40)) {
127 *units = "TiB";
128 return (double)bytes / (1ULL << 40);
129 } else if (bytes > (1ULL << 30)) {
130 *units = "GiB";
131 return (double)bytes / (1ULL << 30);
132 } else if (bytes > (1ULL << 20)) {
133 *units = "MiB";
134 return (double)bytes / (1ULL << 20);
135 } else if (bytes > (1ULL << 10)) {
136 *units = "KiB";
137 return (double)bytes / (1ULL << 10);
138 }
139
140 no_prefix:
141 *units = "B";
142 return bytes;
143 }
144
145 /* Produce human readable discrete number output. */
146 double
147 auto_units(
148 unsigned long long number,
149 char **units)
150 {
151 if (debug > 1)
152 goto no_prefix;
153 if (number > 1000000000000ULL) {
154 *units = "T";
155 return number / 1000000000000.0;
156 } else if (number > 1000000000ULL) {
157 *units = "G";
158 return number / 1000000000.0;
159 } else if (number > 1000000ULL) {
160 *units = "M";
161 return number / 1000000.0;
162 } else if (number > 1000ULL) {
163 *units = "K";
164 return number / 1000.0;
165 }
166
167 no_prefix:
168 *units = "";
169 return number;
170 }