]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/init.c
xfs_io: add crc32 self test
[thirdparty/xfsprogs-dev.git] / io / init.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
5 */
6
7 #include <pthread.h>
8 #include "platform_defs.h"
9 #include "command.h"
10 #include "input.h"
11 #include "init.h"
12 #include "io.h"
13
14 char *progname;
15 int exitcode;
16 int expert;
17 static int idlethread;
18 size_t pagesize;
19 struct timeval stopwatch;
20
21 static void
22 usage(void)
23 {
24 fprintf(stderr,
25 _("Usage: %s [-adfinrRstVx] [-m mode] [-p prog] [[-c|-C] cmd]... file\n"),
26 progname);
27 exit(1);
28 }
29
30 void
31 init_cvtnum(
32 size_t *blocksize,
33 size_t *sectsize)
34 {
35 if (!file || (file->flags & IO_FOREIGN)) {
36 *blocksize = 4096;
37 *sectsize = 512;
38 } else {
39 *blocksize = file->geom.blocksize;
40 *sectsize = file->geom.sectsize;
41 }
42 }
43
44 static void
45 init_commands(void)
46 {
47 attr_init();
48 bmap_init();
49 copy_range_init();
50 cowextsize_init();
51 encrypt_init();
52 fadvise_init();
53 fiemap_init();
54 file_init();
55 flink_init();
56 freeze_init();
57 fsmap_init();
58 fsync_init();
59 getrusage_init();
60 help_init();
61 imap_init();
62 inject_init();
63 label_init();
64 log_writes_init();
65 madvise_init();
66 mincore_init();
67 mmap_init();
68 open_init();
69 parent_init();
70 pread_init();
71 prealloc_init();
72 pwrite_init();
73 quit_init();
74 readdir_init();
75 reflink_init();
76 repair_init();
77 resblks_init();
78 scrub_init();
79 seek_init();
80 sendfile_init();
81 shutdown_init();
82 stat_init();
83 swapext_init();
84 sync_init();
85 sync_range_init();
86 truncate_init();
87 utimes_init();
88 crc32cselftest_init();
89 }
90
91 /*
92 * This allows xfs_io commands specified on the command line to be run on every
93 * open file in the file table. Commands that should not be iterated across all
94 * open files need to specify CMD_FLAG_ONESHOT in their command flags.
95 */
96 static int
97 filetable_iterator(
98 int index)
99 {
100 if (index >= filecount)
101 return 0;
102 file = &filetable[index++];
103 return index;
104 }
105
106 static int
107 init_check_command(
108 const cmdinfo_t *ct)
109 {
110 if (!file && !(ct->flags & CMD_NOFILE_OK)) {
111 fprintf(stderr, _("no files are open, try 'help open'\n"));
112 return 0;
113 }
114 if (!mapping && !(ct->flags & CMD_NOMAP_OK)) {
115 fprintf(stderr, _("no mapped regions, try 'help mmap'\n"));
116 return 0;
117 }
118 if (file && !(ct->flags & CMD_FOREIGN_OK) &&
119 (file->flags & IO_FOREIGN)) {
120 fprintf(stderr,
121 _("foreign file active, %s command is for XFS filesystems only\n"),
122 ct->name);
123 return 0;
124 }
125 return 1;
126 }
127
128 static void
129 init(
130 int argc,
131 char **argv)
132 {
133 int c, flags = 0;
134 char *sp;
135 mode_t mode = 0600;
136 xfs_fsop_geom_t geometry = { 0 };
137 struct fs_path fsp;
138
139 progname = basename(argv[0]);
140 setlocale(LC_ALL, "");
141 bindtextdomain(PACKAGE, LOCALEDIR);
142 textdomain(PACKAGE);
143
144 pagesize = getpagesize();
145 gettimeofday(&stopwatch, NULL);
146
147 fs_table_initialise(0, NULL, 0, NULL);
148 while ((c = getopt(argc, argv, "ac:C:dFfiLm:p:PnrRstTVx")) != EOF) {
149 switch (c) {
150 case 'a':
151 flags |= IO_APPEND;
152 break;
153 case 'c':
154 add_user_command(optarg);
155 break;
156 case 'C':
157 add_oneshot_user_command(optarg);
158 break;
159 case 'd':
160 flags |= IO_DIRECT;
161 break;
162 case 'F':
163 /* Ignored / deprecated now, handled automatically */
164 break;
165 case 'f':
166 flags |= IO_CREAT;
167 break;
168 case 'i':
169 idlethread = 1;
170 break;
171 case 'm':
172 mode = strtoul(optarg, &sp, 0);
173 if (!sp || sp == optarg) {
174 fprintf(stderr, _("non-numeric mode -- %s\n"),
175 optarg);
176 exit(1);
177 }
178 break;
179 case 'n':
180 flags |= IO_NONBLOCK;
181 break;
182 case 'p':
183 progname = optarg;
184 break;
185 case 'r':
186 flags |= IO_READONLY;
187 break;
188 case 's':
189 flags |= IO_OSYNC;
190 break;
191 case 't':
192 flags |= IO_TRUNC;
193 break;
194 case 'P':
195 flags |= IO_PATH;
196 break;
197 case 'L':
198 flags |= IO_NOFOLLOW;
199 break;
200 case 'R':
201 flags |= IO_REALTIME;
202 break;
203 case 'T':
204 flags |= IO_TMPFILE;
205 break;
206 case 'x':
207 expert = 1;
208 break;
209 case 'V':
210 printf(_("%s version %s\n"), progname, VERSION);
211 exit(0);
212 default:
213 usage();
214 }
215 }
216
217 while (optind < argc) {
218 c = openfile(argv[optind], &geometry, flags, mode, &fsp);
219 if (c < 0)
220 exit(1);
221 if (!platform_test_xfs_fd(c))
222 flags |= IO_FOREIGN;
223 if (addfile(argv[optind], c, &geometry, flags, &fsp) < 0)
224 exit(1);
225 optind++;
226 }
227
228 init_commands();
229 add_command_iterator(filetable_iterator);
230 add_check_command(init_check_command);
231 }
232
233 /*
234 * The purpose of this idle thread is to test io from a multi threaded process.
235 * With single threaded process, the file table is not shared and file structs
236 * are not reference counted. Spawning an idle thread can help detecting file
237 * struct reference leaks.
238 */
239 static void *
240 idle_loop(void *arg)
241 {
242 for (;;)
243 pause();
244 return NULL;
245 }
246
247 static void
248 start_idle_thread(void)
249 {
250 pthread_t t;
251
252 if (pthread_create(&t, NULL, idle_loop, NULL)) {
253 fprintf(stderr, "Error creating idle thread\n");
254 exit(1);
255 }
256 }
257
258 int
259 main(
260 int argc,
261 char **argv)
262 {
263 init(argc, argv);
264 if (idlethread)
265 start_idle_thread();
266 command_loop();
267 return exitcode;
268 }