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