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