]> git.saurik.com Git - apple/system_cmds.git/blob - fs_usage.tproj/fs_usage.c
f9e02c1355404b215ac642bc337c9f96c1e94f54
[apple/system_cmds.git] / fs_usage.tproj / fs_usage.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 /*
26 cc -I. -DPRIVATE -D__APPLE_PRIVATE -O -o fs_usage fs_usage.c
27 */
28
29 #define Default_DELAY 1 /* default delay interval */
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <signal.h>
34 #include <strings.h>
35 #include <nlist.h>
36 #include <fcntl.h>
37 #include <aio.h>
38 #include <string.h>
39 #include <dirent.h>
40
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include <sys/time.h>
44
45 #include <libc.h>
46 #include <termios.h>
47 #include <sys/ioctl.h>
48 #include <sys/socket.h>
49 #include <sys/mman.h>
50
51 #ifndef KERNEL_PRIVATE
52 #define KERNEL_PRIVATE
53 #include <sys/kdebug.h>
54 #undef KERNEL_PRIVATE
55 #else
56 #include <sys/kdebug.h>
57 #endif /*KERNEL_PRIVATE*/
58
59 #include <sys/sysctl.h>
60 #include <sys/disk.h>
61 #include <errno.h>
62 #import <mach/clock_types.h>
63 #import <mach/mach_time.h>
64 #include <err.h>
65 #include <libutil.h>
66
67 #define F_OPENFROM 56 /* SPI: open a file relative to fd (must be a dir) */
68 #define F_UNLINKFROM 57 /* SPI: open a file relative to fd (must be a dir) */
69 #define F_CHECK_OPENEVT 58 /* SPI: if a process is marked OPENEVT, or in O_EVTONLY on opens of this vnode */
70
71
72 #define MAXINDEX 2048
73
74 typedef struct LibraryRange {
75 uint64_t b_address;
76 uint64_t e_address;
77 } LibraryRange;
78
79 LibraryRange framework32;
80 LibraryRange framework64;
81
82
83 #define TEXT_R 0
84 #define DATA_R 1
85 #define OBJC_R 2
86 #define IMPORT_R 3
87 #define UNICODE_R 4
88 #define IMAGE_R 5
89 #define LINKEDIT_R 6
90
91
92 char *frameworkType[] = {
93 "<TEXT> ",
94 "<DATA> ",
95 "<OBJC> ",
96 "<IMPORT> ",
97 "<UNICODE> ",
98 "<IMAGE> ",
99 "<LINKEDIT>",
100 };
101
102
103 typedef struct LibraryInfo {
104 uint64_t b_address;
105 uint64_t e_address;
106 int r_type;
107 char *name;
108 } LibraryInfo;
109
110 LibraryInfo frameworkInfo[MAXINDEX];
111 int numFrameworks = 0;
112
113 void lookup_name(uint64_t user_addr, char **type, char **name);
114
115
116 /*
117 MAXCOLS controls when extra data kicks in.
118 MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path.
119 If NUMPARMS changes to match the kernel, it will automatically
120 get reflected in the -w mode output.
121 */
122 #define NUMPARMS 23
123 #define PATHLENGTH (NUMPARMS*sizeof(uintptr_t))
124 #define MAXCOLS 132
125 #define MAX_WIDE_MODE_COLS (PATHLENGTH + 80)
126 #define MAXWIDTH MAX_WIDE_MODE_COLS + 64
127
128 struct th_info {
129 int my_index;
130 int in_filemgr;
131 uintptr_t thread;
132 int pid;
133 int type;
134 int arg1;
135 int arg2;
136 int arg3;
137 int arg4;
138 int arg5;
139 int arg6;
140 int arg7;
141 int arg8;
142 uintptr_t child_thread;
143 int waited;
144 double stime;
145 uintptr_t *pathptr;
146 uintptr_t pathname[NUMPARMS + 1]; /* add room for null terminator */
147 };
148
149 #define MAX_THREADS 1024
150 struct th_info th_state[MAX_THREADS];
151
152 kd_threadmap *last_map = NULL;
153 int last_thread = 0;
154 int map_is_the_same = 0;
155
156 int filemgr_in_progress = 0;
157 int execs_in_progress = 0;
158 int cur_start = 0;
159 int cur_max = 0;
160 int need_new_map = 1;
161 int bias_secs = 0;
162 long last_time;
163 int wideflag = 0;
164 int columns = 0;
165 int select_pid_mode = 0; /* Flag set indicates that output is restricted
166 to selected pids or commands */
167
168 int one_good_pid = 0; /* Used to fail gracefully when bad pids given */
169
170 char *arguments = 0;
171 int argmax = 0;
172
173
174 #define USLEEP_MIN 1
175 #define USLEEP_BEHIND 2
176 #define USLEEP_MAX 32
177 int usleep_ms = USLEEP_MIN;
178
179 /*
180 * Network only or filesystem only output filter
181 * Default of zero means report all activity - no filtering
182 */
183 #define FILESYS_FILTER 0x01
184 #define NETWORK_FILTER 0x02
185 #define CACHEHIT_FILTER 0x04
186 #define EXEC_FILTER 0x08
187 #define PATHNAME_FILTER 0x10
188 #define DEFAULT_DO_NOT_FILTER 0x00
189
190 int filter_mode = CACHEHIT_FILTER;
191
192 #define NFS_DEV -1
193
194 struct diskrec {
195 struct diskrec *next;
196 char *diskname;
197 int dev;
198 };
199
200 struct diskio {
201 struct diskio *next;
202 struct diskio *prev;
203 int type;
204 int bp;
205 int dev;
206 int blkno;
207 int iosize;
208 int io_errno;
209 uintptr_t issuing_thread;
210 uintptr_t completion_thread;
211 char issuing_command[MAXCOMLEN];
212 double issued_time;
213 double completed_time;
214 };
215
216 struct diskrec *disk_list = NULL;
217 struct diskio *free_diskios = NULL;
218 struct diskio *busy_diskios = NULL;
219
220
221
222 struct diskio *insert_diskio();
223 struct diskio *complete_diskio();
224 void free_diskio();
225 void print_diskio();
226 void format_print(struct th_info *, char *, uintptr_t, int, int, int, int, int, int, double, double, int, char *, struct diskio *);
227 void enter_syscall_now(uintptr_t, int, kd_buf *, char *, double);
228 void enter_syscall(uintptr_t, int, kd_buf *, char *, double);
229 void exit_syscall(char *, uintptr_t, int, int, int, int, int, int, double);
230 void extend_syscall(uintptr_t, int, kd_buf *);
231 char *find_disk_name();
232 void cache_disk_names();
233 void recache_disk_names();
234 int ReadSharedCacheMap(const char *, LibraryRange *, char *);
235 void SortFrameworkAddresses();
236 void mark_thread_waited(uintptr_t);
237 int check_filter_mode(struct th_info *, int, int, int, char *);
238 void fs_usage_fd_set(unsigned int, unsigned int);
239 int fs_usage_fd_isset(unsigned int, unsigned int);
240 void fs_usage_fd_clear(unsigned int, unsigned int);
241 void init_arguments_buffer();
242 int get_real_command_name(int, char *, int);
243 void create_map_entry(uintptr_t, int, char *);
244 void kill_thread_map(uintptr_t);
245
246 #define CLASS_MASK 0xff000000
247 #define CSC_MASK 0xffff0000
248 #define BSC_INDEX(type) ((type >> 2) & 0x3fff)
249
250
251 #define TRACE_DATA_NEWTHREAD 0x07000004
252 #define TRACE_DATA_EXEC 0x07000008
253 #define TRACE_STRING_NEWTHREAD 0x07010004
254 #define TRACE_STRING_EXEC 0x07010008
255
256 #define MACH_vmfault 0x01300008
257 #define MACH_pageout 0x01300004
258 #define MACH_sched 0x01400000
259 #define MACH_stkhandoff 0x01400008
260 #define MACH_idle 0x01400024
261 #define VFS_LOOKUP 0x03010090
262 #define BSC_exit 0x040C0004
263
264 #define SPEC_ioctl 0x3060000
265
266 #define P_DISKIO 0x03020000
267 #define P_DISKIO_DONE 0x03020004
268 #define P_DISKIO_MASK (CSC_MASK | 0x4)
269
270 #define P_WrData 0x03020000
271 #define P_RdData 0x03020008
272 #define P_WrMeta 0x03020020
273 #define P_RdMeta 0x03020028
274 #define P_PgOut 0x03020040
275 #define P_PgIn 0x03020048
276 #define P_WrDataAsync 0x03020010
277 #define P_RdDataAsync 0x03020018
278 #define P_WrMetaAsync 0x03020030
279 #define P_RdMetaAsync 0x03020038
280 #define P_PgOutAsync 0x03020050
281 #define P_PgInAsync 0x03020058
282
283 #define P_WrDataDone 0x03020004
284 #define P_RdDataDone 0x0302000C
285 #define P_WrMetaDone 0x03020024
286 #define P_RdMetaDone 0x0302002C
287 #define P_PgOutDone 0x03020044
288 #define P_PgInDone 0x0302004C
289 #define P_WrDataAsyncDone 0x03020014
290 #define P_RdDataAsyncDone 0x0302001C
291 #define P_WrMetaAsyncDone 0x03020034
292 #define P_RdMetaAsyncDone 0x0302003C
293 #define P_PgOutAsyncDone 0x03020054
294 #define P_PgInAsyncDone 0x0302005C
295
296
297 #define MSC_map_fd 0x010c00ac
298
299 #define BSC_BASE 0x040C0000
300 #define MSC_BASE 0x010C0000
301
302 // Network related codes
303 #define BSC_recvmsg 0x040C006C
304 #define BSC_sendmsg 0x040C0070
305 #define BSC_recvfrom 0x040C0074
306 #define BSC_accept 0x040C0078
307 #define BSC_select 0x040C0174
308 #define BSC_socket 0x040C0184
309 #define BSC_connect 0x040C0188
310 #define BSC_bind 0x040C01A0
311 #define BSC_listen 0x040C01A8
312 #define BSC_sendto 0x040C0214
313 #define BSC_socketpair 0x040C021C
314
315 #define BSC_read 0x040C000C
316 #define BSC_write 0x040C0010
317 #define BSC_open 0x040C0014
318 #define BSC_close 0x040C0018
319 #define BSC_link 0x040C0024
320 #define BSC_unlink 0x040C0028
321 #define BSC_chdir 0x040c0030
322 #define BSC_fchdir 0x040c0034
323 #define BSC_mknod 0x040C0038
324 #define BSC_chmod 0x040C003C
325 #define BSC_chown 0x040C0040
326 #define BSC_getfsstat 0x040C0048
327 #define BSC_access 0x040C0084
328 #define BSC_chflags 0x040C0088
329 #define BSC_fchflags 0x040C008C
330 #define BSC_sync 0x040C0090
331 #define BSC_dup 0x040C00A4
332 #define BSC_ioctl 0x040C00D8
333 #define BSC_revoke 0x040C00E0
334 #define BSC_symlink 0x040C00E4
335 #define BSC_readlink 0x040C00E8
336 #define BSC_execve 0x040C00EC
337 #define BSC_umask 0x040C00F0
338 #define BSC_chroot 0x040C00F4
339 #define BSC_msync 0x040C0104
340 #define BSC_dup2 0x040C0168
341 #define BSC_fcntl 0x040C0170
342 #define BSC_fsync 0x040C017C
343 #define BSC_readv 0x040C01E0
344 #define BSC_writev 0x040C01E4
345 #define BSC_fchown 0x040C01EC
346 #define BSC_fchmod 0x040C01F0
347 #define BSC_rename 0x040C0200
348 #define BSC_mkfifo 0x040c0210
349 #define BSC_mkdir 0x040C0220
350 #define BSC_rmdir 0x040C0224
351 #define BSC_utimes 0x040C0228
352 #define BSC_futimes 0x040C022C
353 #define BSC_pread 0x040C0264
354 #define BSC_pwrite 0x040C0268
355 #define BSC_statfs 0x040C0274
356 #define BSC_fstatfs 0x040C0278
357 #define BSC_stat 0x040C02F0
358 #define BSC_fstat 0x040C02F4
359 #define BSC_lstat 0x040C02F8
360 #define BSC_pathconf 0x040C02FC
361 #define BSC_fpathconf 0x040C0300
362 #define BSC_getdirentries 0x040C0310
363 #define BSC_mmap 0x040c0314
364 #define BSC_lseek 0x040c031c
365 #define BSC_truncate 0x040C0320
366 #define BSC_ftruncate 0x040C0324
367 #define BSC_undelete 0x040C0334
368 #define BSC_statv 0x040C0364
369 #define BSC_lstatv 0x040C0368
370 #define BSC_fstatv 0x040C036C
371 #define BSC_mkcomplex 0x040C0360
372 #define BSC_getattrlist 0x040C0370
373 #define BSC_setattrlist 0x040C0374
374 #define BSC_getdirentriesattr 0x040C0378
375 #define BSC_exchangedata 0x040C037C
376 #define BSC_checkuseraccess 0x040C0380
377 #define BSC_searchfs 0x040C0384
378 #define BSC_delete 0x040C0388
379 #define BSC_copyfile 0x040C038C
380 #define BSC_getxattr 0x040C03A8
381 #define BSC_fgetxattr 0x040C03AC
382 #define BSC_setxattr 0x040C03B0
383 #define BSC_fsetxattr 0x040C03B4
384 #define BSC_removexattr 0x040C03B8
385 #define BSC_fremovexattr 0x040C03BC
386 #define BSC_listxattr 0x040C03C0
387 #define BSC_flistxattr 0x040C03C4
388 #define BSC_fsctl 0x040C03C8
389 #define BSC_open_extended 0x040C0454
390 #define BSC_stat_extended 0x040C045C
391 #define BSC_lstat_extended 0x040C0460
392 #define BSC_fstat_extended 0x040C0464
393 #define BSC_chmod_extended 0x040C0468
394 #define BSC_fchmod_extended 0x040C046C
395 #define BSC_access_extended 0x040C0470
396 #define BSC_mkfifo_extended 0x040C048C
397 #define BSC_mkdir_extended 0x040C0490
398 #define BSC_load_shared_file 0x040C04A0
399 #define BSC_aio_fsync 0x040C04E4
400 #define BSC_aio_return 0x040C04E8
401 #define BSC_aio_suspend 0x040C04EC
402 #define BSC_aio_cancel 0x040C04F0
403 #define BSC_aio_error 0x040C04F4
404 #define BSC_aio_read 0x040C04F8
405 #define BSC_aio_write 0x040C04FC
406 #define BSC_lio_listio 0x040C0500
407 #define BSC_sendfile 0x040C0544
408 #define BSC_stat64 0x040C0548
409 #define BSC_fstat64 0x040C054C
410 #define BSC_lstat64 0x040C0550
411 #define BSC_stat64_extended 0x040C0554
412 #define BSC_lstat64_extended 0x040C0558
413 #define BSC_fstat64_extended 0x040C055C
414 #define BSC_getdirentries64 0x040C0560
415 #define BSC_statfs64 0x040C0564
416 #define BSC_fstatfs64 0x040C0568
417 #define BSC_getfsstat64 0x040C056C
418 #define BSC_pthread_chdir 0x040C0570
419 #define BSC_pthread_fchdir 0x040C0574
420 #define BSC_lchown 0x040C05B0
421
422 #define BSC_read_nocancel 0x040c0630
423 #define BSC_write_nocancel 0x040c0634
424 #define BSC_open_nocancel 0x040c0638
425 #define BSC_close_nocancel 0x040c063c
426 #define BSC_recvmsg_nocancel 0x040c0644
427 #define BSC_sendmsg_nocancel 0x040c0648
428 #define BSC_recvfrom_nocancel 0x040c064c
429 #define BSC_accept_nocancel 0x040c0650
430 #define BSC_msync_nocancel 0x040c0654
431 #define BSC_fcntl_nocancel 0x040c0658
432 #define BSC_select_nocancel 0x040c065c
433 #define BSC_fsync_nocancel 0x040c0660
434 #define BSC_connect_nocancel 0x040c0664
435 #define BSC_readv_nocancel 0x040c066c
436 #define BSC_writev_nocancel 0x040c0670
437 #define BSC_sendto_nocancel 0x040c0674
438 #define BSC_pread_nocancel 0x040c0678
439 #define BSC_pwrite_nocancel 0x040c067c
440 #define BSC_aio_suspend_nocancel 0x40c0694
441
442 #define BSC_msync_extended 0x040e0104
443 #define BSC_pread_extended 0x040e0264
444 #define BSC_pwrite_extended 0x040e0268
445 #define BSC_mmap_extended 0x040e0314
446 #define BSC_mmap_extended2 0x040f0314
447
448 // Carbon File Manager support
449 #define FILEMGR_PBGETCATALOGINFO 0x1e000020
450 #define FILEMGR_PBGETCATALOGINFOBULK 0x1e000024
451 #define FILEMGR_PBCREATEFILEUNICODE 0x1e000028
452 #define FILEMGR_PBCREATEDIRECTORYUNICODE 0x1e00002c
453 #define FILEMGR_PBCREATEFORK 0x1e000030
454 #define FILEMGR_PBDELETEFORK 0x1e000034
455 #define FILEMGR_PBITERATEFORK 0x1e000038
456 #define FILEMGR_PBOPENFORK 0x1e00003c
457 #define FILEMGR_PBREADFORK 0x1e000040
458 #define FILEMGR_PBWRITEFORK 0x1e000044
459 #define FILEMGR_PBALLOCATEFORK 0x1e000048
460 #define FILEMGR_PBDELETEOBJECT 0x1e00004c
461 #define FILEMGR_PBEXCHANGEOBJECT 0x1e000050
462 #define FILEMGR_PBGETFORKCBINFO 0x1e000054
463 #define FILEMGR_PBGETVOLUMEINFO 0x1e000058
464 #define FILEMGR_PBMAKEFSREF 0x1e00005c
465 #define FILEMGR_PBMAKEFSREFUNICODE 0x1e000060
466 #define FILEMGR_PBMOVEOBJECT 0x1e000064
467 #define FILEMGR_PBOPENITERATOR 0x1e000068
468 #define FILEMGR_PBRENAMEUNICODE 0x1e00006c
469 #define FILEMGR_PBSETCATALOGINFO 0x1e000070
470 #define FILEMGR_PBSETVOLUMEINFO 0x1e000074
471 #define FILEMGR_FSREFMAKEPATH 0x1e000078
472 #define FILEMGR_FSPATHMAKEREF 0x1e00007c
473
474 #define FILEMGR_PBGETCATINFO 0x1e010000
475 #define FILEMGR_PBGETCATINFOLITE 0x1e010004
476 #define FILEMGR_PBHGETFINFO 0x1e010008
477 #define FILEMGR_PBXGETVOLINFO 0x1e01000c
478 #define FILEMGR_PBHCREATE 0x1e010010
479 #define FILEMGR_PBHOPENDF 0x1e010014
480 #define FILEMGR_PBHOPENRF 0x1e010018
481 #define FILEMGR_PBHGETDIRACCESS 0x1e01001c
482 #define FILEMGR_PBHSETDIRACCESS 0x1e010020
483 #define FILEMGR_PBHMAPID 0x1e010024
484 #define FILEMGR_PBHMAPNAME 0x1e010028
485 #define FILEMGR_PBCLOSE 0x1e01002c
486 #define FILEMGR_PBFLUSHFILE 0x1e010030
487 #define FILEMGR_PBGETEOF 0x1e010034
488 #define FILEMGR_PBSETEOF 0x1e010038
489 #define FILEMGR_PBGETFPOS 0x1e01003c
490 #define FILEMGR_PBREAD 0x1e010040
491 #define FILEMGR_PBWRITE 0x1e010044
492 #define FILEMGR_PBGETFCBINFO 0x1e010048
493 #define FILEMGR_PBSETFINFO 0x1e01004c
494 #define FILEMGR_PBALLOCATE 0x1e010050
495 #define FILEMGR_PBALLOCCONTIG 0x1e010054
496 #define FILEMGR_PBSETFPOS 0x1e010058
497 #define FILEMGR_PBSETCATINFO 0x1e01005c
498 #define FILEMGR_PBGETVOLPARMS 0x1e010060
499 #define FILEMGR_PBSETVINFO 0x1e010064
500 #define FILEMGR_PBMAKEFSSPEC 0x1e010068
501 #define FILEMGR_PBHGETVINFO 0x1e01006c
502 #define FILEMGR_PBCREATEFILEIDREF 0x1e010070
503 #define FILEMGR_PBDELETEFILEIDREF 0x1e010074
504 #define FILEMGR_PBRESOLVEFILEIDREF 0x1e010078
505 #define FILEMGR_PBFLUSHVOL 0x1e01007c
506 #define FILEMGR_PBHRENAME 0x1e010080
507 #define FILEMGR_PBCATMOVE 0x1e010084
508 #define FILEMGR_PBEXCHANGEFILES 0x1e010088
509 #define FILEMGR_PBHDELETE 0x1e01008c
510 #define FILEMGR_PBDIRCREATE 0x1e010090
511 #define FILEMGR_PBCATSEARCH 0x1e010094
512 #define FILEMGR_PBHSETFLOCK 0x1e010098
513 #define FILEMGR_PBHRSTFLOCK 0x1e01009c
514 #define FILEMGR_PBLOCKRANGE 0x1e0100a0
515 #define FILEMGR_PBUNLOCKRANGE 0x1e0100a4
516
517
518 #define FILEMGR_CLASS 0x1e
519 #define FILEMGR_BASE 0x1e000000
520
521 #define FMT_DEFAULT 0
522 #define FMT_FD 1
523 #define FMT_FD_IO 2
524 #define FMT_FD_2 3
525 #define FMT_SOCKET 4
526 #define FMT_PGIN 5
527 #define FMT_PGOUT 6
528 #define FMT_CACHEHIT 7
529 #define FMT_DISKIO 8
530 #define FMT_LSEEK 9
531 #define FMT_PREAD 10
532 #define FMT_FTRUNC 11
533 #define FMT_TRUNC 12
534 #define FMT_SELECT 13
535 #define FMT_OPEN 14
536 #define FMT_AIO_FSYNC 15
537 #define FMT_AIO_RETURN 16
538 #define FMT_AIO_SUSPEND 17
539 #define FMT_AIO_CANCEL 18
540 #define FMT_AIO 19
541 #define FMT_LIO_LISTIO 20
542 #define FMT_MSYNC 21
543 #define FMT_FCNTL 22
544 #define FMT_ACCESS 23
545 #define FMT_CHMOD 24
546 #define FMT_FCHMOD 25
547 #define FMT_CHMOD_EXT 26
548 #define FMT_FCHMOD_EXT 27
549 #define FMT_CHFLAGS 28
550 #define FMT_FCHFLAGS 29
551 #define FMT_IOCTL 30
552 #define FMT_MMAP 31
553 #define FMT_UMASK 32
554 #define FMT_SENDFILE 33
555 #define FMT_SPEC_IOCTL 34
556
557 #define MAX_BSD_SYSCALL 512
558
559 struct bsd_syscall {
560 char *sc_name;
561 int sc_format;
562 } bsd_syscalls[MAX_BSD_SYSCALL];
563
564
565 int bsd_syscall_types[] = {
566 BSC_recvmsg,
567 BSC_recvmsg_nocancel,
568 BSC_sendmsg,
569 BSC_sendmsg_nocancel,
570 BSC_recvfrom,
571 BSC_recvfrom_nocancel,
572 BSC_accept,
573 BSC_accept_nocancel,
574 BSC_select,
575 BSC_select_nocancel,
576 BSC_socket,
577 BSC_connect,
578 BSC_connect_nocancel,
579 BSC_bind,
580 BSC_listen,
581 BSC_sendto,
582 BSC_sendto_nocancel,
583 BSC_socketpair,
584 BSC_read,
585 BSC_read_nocancel,
586 BSC_write,
587 BSC_write_nocancel,
588 BSC_open,
589 BSC_open_nocancel,
590 BSC_close,
591 BSC_close_nocancel,
592 BSC_link,
593 BSC_unlink,
594 BSC_chdir,
595 BSC_fchdir,
596 BSC_mknod,
597 BSC_chmod,
598 BSC_chown,
599 BSC_access,
600 BSC_chflags,
601 BSC_fchflags,
602 BSC_sync,
603 BSC_dup,
604 BSC_revoke,
605 BSC_symlink,
606 BSC_readlink,
607 BSC_execve,
608 BSC_umask,
609 BSC_chroot,
610 BSC_dup2,
611 BSC_fsync,
612 BSC_fsync_nocancel,
613 BSC_readv,
614 BSC_readv_nocancel,
615 BSC_writev,
616 BSC_writev_nocancel,
617 BSC_fchown,
618 BSC_fchmod,
619 BSC_rename,
620 BSC_mkfifo,
621 BSC_mkdir,
622 BSC_rmdir,
623 BSC_utimes,
624 BSC_futimes,
625 BSC_pread,
626 BSC_pread_nocancel,
627 BSC_pwrite,
628 BSC_pwrite_nocancel,
629 BSC_statfs,
630 BSC_fstatfs,
631 BSC_stat,
632 BSC_fstat,
633 BSC_lstat,
634 BSC_pathconf,
635 BSC_fpathconf,
636 BSC_getdirentries,
637 BSC_mmap,
638 BSC_lseek,
639 BSC_truncate,
640 BSC_ftruncate,
641 BSC_undelete,
642 BSC_statv,
643 BSC_lstatv,
644 BSC_fstatv,
645 BSC_mkcomplex,
646 BSC_getattrlist,
647 BSC_setattrlist,
648 BSC_getdirentriesattr,
649 BSC_exchangedata,
650 BSC_checkuseraccess,
651 BSC_searchfs,
652 BSC_delete,
653 BSC_copyfile,
654 BSC_getxattr,
655 BSC_fgetxattr,
656 BSC_setxattr,
657 BSC_fsetxattr,
658 BSC_removexattr,
659 BSC_fremovexattr,
660 BSC_listxattr,
661 BSC_flistxattr,
662 BSC_fsctl,
663 BSC_open_extended,
664 BSC_stat_extended,
665 BSC_lstat_extended,
666 BSC_fstat_extended,
667 BSC_chmod_extended,
668 BSC_fchmod_extended,
669 BSC_access_extended,
670 BSC_mkfifo_extended,
671 BSC_mkdir_extended,
672 BSC_load_shared_file,
673 BSC_aio_fsync,
674 BSC_aio_return,
675 BSC_aio_suspend,
676 BSC_aio_suspend_nocancel,
677 BSC_aio_cancel,
678 BSC_aio_error,
679 BSC_aio_read,
680 BSC_aio_write,
681 BSC_lio_listio,
682 BSC_lchown,
683 BSC_sendfile,
684 BSC_msync,
685 BSC_msync_nocancel,
686 BSC_fcntl,
687 BSC_fcntl_nocancel,
688 BSC_ioctl,
689 BSC_stat64,
690 BSC_fstat64,
691 BSC_lstat64,
692 BSC_stat64_extended,
693 BSC_lstat64_extended,
694 BSC_fstat64_extended,
695 BSC_getdirentries64,
696 BSC_statfs64,
697 BSC_fstatfs64,
698 BSC_pthread_chdir,
699 BSC_pthread_fchdir,
700 BSC_getfsstat,
701 BSC_getfsstat64,
702 0
703 };
704
705
706 #define MAX_FILEMGR 512
707
708 struct filemgr_call {
709 char *fm_name;
710 } filemgr_calls[MAX_FILEMGR];
711
712
713 int filemgr_call_types[] = {
714 FILEMGR_PBGETCATALOGINFO,
715 FILEMGR_PBGETCATALOGINFOBULK,
716 FILEMGR_PBCREATEFILEUNICODE,
717 FILEMGR_PBCREATEDIRECTORYUNICODE,
718 FILEMGR_PBCREATEFORK,
719 FILEMGR_PBDELETEFORK,
720 FILEMGR_PBITERATEFORK,
721 FILEMGR_PBOPENFORK,
722 FILEMGR_PBREADFORK,
723 FILEMGR_PBWRITEFORK,
724 FILEMGR_PBALLOCATEFORK,
725 FILEMGR_PBDELETEOBJECT,
726 FILEMGR_PBEXCHANGEOBJECT,
727 FILEMGR_PBGETFORKCBINFO,
728 FILEMGR_PBGETVOLUMEINFO,
729 FILEMGR_PBMAKEFSREF,
730 FILEMGR_PBMAKEFSREFUNICODE,
731 FILEMGR_PBMOVEOBJECT,
732 FILEMGR_PBOPENITERATOR,
733 FILEMGR_PBRENAMEUNICODE,
734 FILEMGR_PBSETCATALOGINFO,
735 FILEMGR_PBSETVOLUMEINFO,
736 FILEMGR_FSREFMAKEPATH,
737 FILEMGR_FSPATHMAKEREF,
738
739 FILEMGR_PBGETCATINFO,
740 FILEMGR_PBGETCATINFOLITE,
741 FILEMGR_PBHGETFINFO,
742 FILEMGR_PBXGETVOLINFO,
743 FILEMGR_PBHCREATE,
744 FILEMGR_PBHOPENDF,
745 FILEMGR_PBHOPENRF,
746 FILEMGR_PBHGETDIRACCESS,
747 FILEMGR_PBHSETDIRACCESS,
748 FILEMGR_PBHMAPID,
749 FILEMGR_PBHMAPNAME,
750 FILEMGR_PBCLOSE,
751 FILEMGR_PBFLUSHFILE,
752 FILEMGR_PBGETEOF,
753 FILEMGR_PBSETEOF,
754 FILEMGR_PBGETFPOS,
755 FILEMGR_PBREAD,
756 FILEMGR_PBWRITE,
757 FILEMGR_PBGETFCBINFO,
758 FILEMGR_PBSETFINFO,
759 FILEMGR_PBALLOCATE,
760 FILEMGR_PBALLOCCONTIG,
761 FILEMGR_PBSETFPOS,
762 FILEMGR_PBSETCATINFO,
763 FILEMGR_PBGETVOLPARMS,
764 FILEMGR_PBSETVINFO,
765 FILEMGR_PBMAKEFSSPEC,
766 FILEMGR_PBHGETVINFO,
767 FILEMGR_PBCREATEFILEIDREF,
768 FILEMGR_PBDELETEFILEIDREF,
769 FILEMGR_PBRESOLVEFILEIDREF,
770 FILEMGR_PBFLUSHVOL,
771 FILEMGR_PBHRENAME,
772 FILEMGR_PBCATMOVE,
773 FILEMGR_PBEXCHANGEFILES,
774 FILEMGR_PBHDELETE,
775 FILEMGR_PBDIRCREATE,
776 FILEMGR_PBCATSEARCH,
777 FILEMGR_PBHSETFLOCK,
778 FILEMGR_PBHRSTFLOCK,
779 FILEMGR_PBLOCKRANGE,
780 FILEMGR_PBUNLOCKRANGE,
781 0
782 };
783
784
785
786 #define MAX_PIDS 256
787 int pids[MAX_PIDS];
788
789 int num_of_pids = 0;
790 int exclude_pids = 0;
791 int exclude_default_pids = 1;
792
793
794 struct kinfo_proc *kp_buffer = 0;
795 int kp_nentries = 0;
796
797 int num_cpus;
798
799 #define EVENT_BASE 60000
800
801 int num_events = EVENT_BASE;
802
803
804 #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END)
805 #define DBG_FUNC_MASK 0xfffffffc
806
807 double divisor = 0.0; /* Trace divisor converts to microseconds */
808
809 int mib[6];
810 size_t needed;
811 char *my_buffer;
812
813 kbufinfo_t bufinfo = {0, 0, 0, 0, 0};
814
815 int total_threads = 0;
816 kd_threadmap *mapptr = 0; /* pointer to list of threads */
817
818 /* defines for tracking file descriptor state */
819 #define FS_USAGE_FD_SETSIZE 256 /* Initial number of file descriptors per
820 thread that we will track */
821
822 #define FS_USAGE_NFDBITS (sizeof (unsigned long) * 8)
823 #define FS_USAGE_NFDBYTES(n) (((n) / FS_USAGE_NFDBITS) * sizeof (unsigned long))
824
825 typedef struct {
826 unsigned int fd_valid; /* set if this is a valid entry */
827 uintptr_t fd_thread;
828 unsigned int fd_setsize; /* this is a bit count */
829 unsigned long *fd_setptr; /* file descripter bitmap */
830 } fd_threadmap;
831
832 fd_threadmap *fdmapptr = 0; /* pointer to list of threads for fd tracking */
833
834 int trace_enabled = 0;
835 int set_remove_flag = 1;
836
837 char *RAW_file = (char *)0;
838 int RAW_flag = 0;
839 int RAW_fd = 0;
840 double bias_now = 0.0;
841 double start_time = 0.0;
842 double end_time = 99999999999.9;
843
844
845 void set_numbufs();
846 void set_init();
847 void set_enable();
848 void sample_sc();
849 int quit();
850
851 /*
852 * signal handlers
853 */
854
855 void leave() /* exit under normal conditions -- INT handler */
856 {
857 int i;
858 void set_enable();
859 void set_pidcheck();
860 void set_pidexclude();
861 void set_remove();
862
863 fflush(0);
864
865 set_enable(0);
866
867 if (exclude_pids == 0) {
868 for (i = 0; i < num_of_pids; i++)
869 set_pidcheck(pids[i], 0);
870 }
871 else {
872 for (i = 0; i < num_of_pids; i++)
873 set_pidexclude(pids[i], 0);
874 }
875 set_remove();
876 exit(0);
877 }
878
879
880 void get_screenwidth()
881 {
882 struct winsize size;
883
884 columns = MAXCOLS;
885
886 if (isatty(1)) {
887 if (ioctl(1, TIOCGWINSZ, &size) != -1) {
888 columns = size.ws_col;
889
890 if (columns > MAXWIDTH)
891 columns = MAXWIDTH;
892 }
893 }
894 }
895
896
897 void sigwinch()
898 {
899 if (!wideflag)
900 get_screenwidth();
901 }
902
903 int
904 exit_usage(char *myname) {
905
906 fprintf(stderr, "Usage: %s [-e] [-w] [-f mode] [pid | cmd [pid | cmd]....]\n", myname);
907 fprintf(stderr, " -e exclude the specified list of pids from the sample\n");
908 fprintf(stderr, " and exclude fs_usage by default\n");
909 fprintf(stderr, " -w force wider, detailed, output\n");
910 fprintf(stderr, " -f Output is based on the mode provided\n");
911 fprintf(stderr, " mode = \"network\" Show only network related output\n");
912 fprintf(stderr, " mode = \"filesys\" Show only file system related output\n");
913 fprintf(stderr, " mode = \"pathname\" Show only pathname related output\n");
914 fprintf(stderr, " mode = \"exec\" Show only execs\n");
915 fprintf(stderr, " mode = \"cachehit\" In addition, show cachehits\n");
916 fprintf(stderr, " pid selects process(s) to sample\n");
917 fprintf(stderr, " cmd selects process(s) matching command string to sample\n");
918 fprintf(stderr, "\n%s will handle a maximum list of %d pids.\n\n", myname, MAX_PIDS);
919 fprintf(stderr, "By default (no options) the following processes are excluded from the output:\n");
920 fprintf(stderr, "fs_usage, Terminal, telnetd, sshd, rlogind, tcsh, csh, sh\n\n");
921
922 exit(1);
923 }
924
925
926 int filemgr_index(type) {
927
928 if (type & 0x10000)
929 return (((type >> 2) & 0x3fff) + 256);
930
931 return (((type >> 2) & 0x3fff));
932 }
933
934
935 void init_tables(void)
936 { int i;
937 int type;
938 int code;
939
940 for (i = 0; i < MAX_THREADS; i++)
941 th_state[i].my_index = i;
942
943 for (i = 0; i < MAX_BSD_SYSCALL; i++) {
944 bsd_syscalls[i].sc_name = NULL;
945 bsd_syscalls[i].sc_format = FMT_DEFAULT;
946 }
947
948 for (i = 0; i < MAX_FILEMGR; i++) {
949 filemgr_calls[i].fm_name = NULL;
950 }
951
952 for (i = 0; (type = bsd_syscall_types[i]); i++) {
953
954 code = BSC_INDEX(type);
955
956 if (code >= MAX_BSD_SYSCALL) {
957 printf("BSD syscall init (%x): type exceeds table size\n", type);
958 continue;
959 }
960 switch (type) {
961
962 case BSC_sendfile:
963 bsd_syscalls[code].sc_name = "sendfile";
964 bsd_syscalls[code].sc_format = FMT_FD; /* this should be changed to FMT_SENDFILE */
965 break; /* once we add an extended info trace event */
966
967 case BSC_recvmsg:
968 case BSC_recvmsg_nocancel:
969 bsd_syscalls[code].sc_name = "recvmsg";
970 bsd_syscalls[code].sc_format = FMT_FD_IO;
971 break;
972
973 case BSC_sendmsg:
974 case BSC_sendmsg_nocancel:
975 bsd_syscalls[code].sc_name = "sendmsg";
976 bsd_syscalls[code].sc_format = FMT_FD_IO;
977 break;
978
979 case BSC_recvfrom:
980 case BSC_recvfrom_nocancel:
981 bsd_syscalls[code].sc_name = "recvfrom";
982 bsd_syscalls[code].sc_format = FMT_FD_IO;
983 break;
984
985 case BSC_sendto:
986 case BSC_sendto_nocancel:
987 bsd_syscalls[code].sc_name = "sendto";
988 bsd_syscalls[code].sc_format = FMT_FD_IO;
989 break;
990
991 case BSC_select:
992 case BSC_select_nocancel:
993 bsd_syscalls[code].sc_name = "select";
994 bsd_syscalls[code].sc_format = FMT_SELECT;
995 break;
996
997 case BSC_accept:
998 case BSC_accept_nocancel:
999 bsd_syscalls[code].sc_name = "accept";
1000 bsd_syscalls[code].sc_format = FMT_FD_2;
1001 break;
1002
1003 case BSC_socket:
1004 bsd_syscalls[code].sc_name = "socket";
1005 bsd_syscalls[code].sc_format = FMT_SOCKET;
1006 break;
1007
1008 case BSC_connect:
1009 case BSC_connect_nocancel:
1010 bsd_syscalls[code].sc_name = "connect";
1011 bsd_syscalls[code].sc_format = FMT_FD;
1012 break;
1013
1014 case BSC_bind:
1015 bsd_syscalls[code].sc_name = "bind";
1016 bsd_syscalls[code].sc_format = FMT_FD;
1017 break;
1018
1019 case BSC_listen:
1020 bsd_syscalls[code].sc_name = "listen";
1021 bsd_syscalls[code].sc_format = FMT_FD;
1022 break;
1023
1024 case BSC_mmap:
1025 bsd_syscalls[code].sc_name = "mmap";
1026 bsd_syscalls[code].sc_format = FMT_MMAP;
1027 break;
1028
1029 case BSC_socketpair:
1030 bsd_syscalls[code].sc_name = "socketpair";
1031 break;
1032
1033 case BSC_getxattr:
1034 bsd_syscalls[code].sc_name = "getxattr";
1035 break;
1036
1037 case BSC_setxattr:
1038 bsd_syscalls[code].sc_name = "setxattr";
1039 break;
1040
1041 case BSC_removexattr:
1042 bsd_syscalls[code].sc_name = "removexattr";
1043 break;
1044
1045 case BSC_listxattr:
1046 bsd_syscalls[code].sc_name = "listxattr";
1047 break;
1048
1049 case BSC_stat:
1050 bsd_syscalls[code].sc_name = "stat";
1051 break;
1052
1053 case BSC_stat64:
1054 bsd_syscalls[code].sc_name = "stat64";
1055 break;
1056
1057 case BSC_stat_extended:
1058 bsd_syscalls[code].sc_name = "stat_extended";
1059 break;
1060
1061 case BSC_stat64_extended:
1062 bsd_syscalls[code].sc_name = "stat_extended64";
1063 break;
1064
1065 case BSC_execve:
1066 bsd_syscalls[code].sc_name = "execve";
1067 break;
1068
1069 case BSC_load_shared_file:
1070 bsd_syscalls[code].sc_name = "load_sf";
1071 break;
1072
1073 case BSC_open:
1074 case BSC_open_nocancel:
1075 bsd_syscalls[code].sc_name = "open";
1076 bsd_syscalls[code].sc_format = FMT_OPEN;
1077 break;
1078
1079 case BSC_open_extended:
1080 bsd_syscalls[code].sc_name = "open_extended";
1081 bsd_syscalls[code].sc_format = FMT_OPEN;
1082 break;
1083
1084 case BSC_dup:
1085 bsd_syscalls[code].sc_name = "dup";
1086 bsd_syscalls[code].sc_format = FMT_FD_2;
1087 break;
1088
1089 case BSC_dup2:
1090 bsd_syscalls[code].sc_name = "dup2";
1091 bsd_syscalls[code].sc_format = FMT_FD_2;
1092 break;
1093
1094 case BSC_close:
1095 case BSC_close_nocancel:
1096 bsd_syscalls[code].sc_name = "close";
1097 bsd_syscalls[code].sc_format = FMT_FD;
1098 break;
1099
1100 case BSC_read:
1101 case BSC_read_nocancel:
1102 bsd_syscalls[code].sc_name = "read";
1103 bsd_syscalls[code].sc_format = FMT_FD_IO;
1104 break;
1105
1106 case BSC_write:
1107 case BSC_write_nocancel:
1108 bsd_syscalls[code].sc_name = "write";
1109 bsd_syscalls[code].sc_format = FMT_FD_IO;
1110 break;
1111
1112 case BSC_fgetxattr:
1113 bsd_syscalls[code].sc_name = "fgetxattr";
1114 bsd_syscalls[code].sc_format = FMT_FD;
1115 break;
1116
1117 case BSC_fsetxattr:
1118 bsd_syscalls[code].sc_name = "fsetxattr";
1119 bsd_syscalls[code].sc_format = FMT_FD;
1120 break;
1121
1122 case BSC_fremovexattr:
1123 bsd_syscalls[code].sc_name = "fremovexattr";
1124 bsd_syscalls[code].sc_format = FMT_FD;
1125 break;
1126
1127 case BSC_flistxattr:
1128 bsd_syscalls[code].sc_name = "flistxattr";
1129 bsd_syscalls[code].sc_format = FMT_FD;
1130 break;
1131
1132 case BSC_fstat:
1133 bsd_syscalls[code].sc_name = "fstat";
1134 bsd_syscalls[code].sc_format = FMT_FD;
1135 break;
1136
1137 case BSC_fstat64:
1138 bsd_syscalls[code].sc_name = "fstat64";
1139 bsd_syscalls[code].sc_format = FMT_FD;
1140 break;
1141
1142 case BSC_fstat_extended:
1143 bsd_syscalls[code].sc_name = "fstat_extended";
1144 bsd_syscalls[code].sc_format = FMT_FD;
1145 break;
1146
1147 case BSC_fstat64_extended:
1148 bsd_syscalls[code].sc_name = "fstat64_extended";
1149 bsd_syscalls[code].sc_format = FMT_FD;
1150 break;
1151
1152 case BSC_lstat:
1153 bsd_syscalls[code].sc_name = "lstat";
1154 break;
1155
1156 case BSC_lstat64:
1157 bsd_syscalls[code].sc_name = "lstat64";
1158 break;
1159
1160 case BSC_lstat_extended:
1161 bsd_syscalls[code].sc_name = "lstat_extended";
1162 break;
1163
1164 case BSC_lstat64_extended:
1165 bsd_syscalls[code].sc_name = "lstat_extended64";
1166 break;
1167
1168 case BSC_lstatv:
1169 bsd_syscalls[code].sc_name = "lstatv";
1170 break;
1171
1172 case BSC_link:
1173 bsd_syscalls[code].sc_name = "link";
1174 break;
1175
1176 case BSC_unlink:
1177 bsd_syscalls[code].sc_name = "unlink";
1178 break;
1179
1180 case BSC_mknod:
1181 bsd_syscalls[code].sc_name = "mknod";
1182 break;
1183
1184 case BSC_umask:
1185 bsd_syscalls[code].sc_name = "umask";
1186 bsd_syscalls[code].sc_format = FMT_UMASK;
1187 break;
1188
1189 case BSC_chmod:
1190 bsd_syscalls[code].sc_name = "chmod";
1191 bsd_syscalls[code].sc_format = FMT_CHMOD;
1192 break;
1193
1194 case BSC_chmod_extended:
1195 bsd_syscalls[code].sc_name = "chmod_extended";
1196 bsd_syscalls[code].sc_format = FMT_CHMOD_EXT;
1197 break;
1198
1199 case BSC_fchmod:
1200 bsd_syscalls[code].sc_name = "fchmod";
1201 bsd_syscalls[code].sc_format = FMT_FCHMOD;
1202 break;
1203
1204 case BSC_fchmod_extended:
1205 bsd_syscalls[code].sc_name = "fchmod_extended";
1206 bsd_syscalls[code].sc_format = FMT_FCHMOD_EXT;
1207 break;
1208
1209 case BSC_chown:
1210 bsd_syscalls[code].sc_name = "chown";
1211 break;
1212
1213 case BSC_lchown:
1214 bsd_syscalls[code].sc_name = "lchown";
1215 break;
1216
1217 case BSC_fchown:
1218 bsd_syscalls[code].sc_name = "fchown";
1219 bsd_syscalls[code].sc_format = FMT_FD;
1220 break;
1221
1222 case BSC_access:
1223 bsd_syscalls[code].sc_name = "access";
1224 bsd_syscalls[code].sc_format = FMT_ACCESS;
1225 break;
1226
1227 case BSC_access_extended:
1228 bsd_syscalls[code].sc_name = "access_extended";
1229 break;
1230
1231 case BSC_chdir:
1232 bsd_syscalls[code].sc_name = "chdir";
1233 break;
1234
1235 case BSC_pthread_chdir:
1236 bsd_syscalls[code].sc_name = "pthread_chdir";
1237 break;
1238
1239 case BSC_chroot:
1240 bsd_syscalls[code].sc_name = "chroot";
1241 break;
1242
1243 case BSC_utimes:
1244 bsd_syscalls[code].sc_name = "utimes";
1245 break;
1246
1247 case BSC_delete:
1248 bsd_syscalls[code].sc_name = "delete-Carbon";
1249 break;
1250
1251 case BSC_undelete:
1252 bsd_syscalls[code].sc_name = "undelete";
1253 break;
1254
1255 case BSC_revoke:
1256 bsd_syscalls[code].sc_name = "revoke";
1257 break;
1258
1259 case BSC_fsctl:
1260 bsd_syscalls[code].sc_name = "fsctl";
1261 break;
1262
1263 case BSC_chflags:
1264 bsd_syscalls[code].sc_name = "chflags";
1265 bsd_syscalls[code].sc_format = FMT_CHFLAGS;
1266 break;
1267
1268 case BSC_fchflags:
1269 bsd_syscalls[code].sc_name = "fchflags";
1270 bsd_syscalls[code].sc_format = FMT_FCHFLAGS;
1271 break;
1272
1273 case BSC_fchdir:
1274 bsd_syscalls[code].sc_name = "fchdir";
1275 bsd_syscalls[code].sc_format = FMT_FD;
1276 break;
1277
1278 case BSC_pthread_fchdir:
1279 bsd_syscalls[code].sc_name = "pthread_fchdir";
1280 bsd_syscalls[code].sc_format = FMT_FD;
1281 break;
1282
1283 case BSC_futimes:
1284 bsd_syscalls[code].sc_name = "futimes";
1285 bsd_syscalls[code].sc_format = FMT_FD;
1286 break;
1287
1288 case BSC_sync:
1289 bsd_syscalls[code].sc_name = "sync";
1290 break;
1291
1292 case BSC_symlink:
1293 bsd_syscalls[code].sc_name = "symlink";
1294 break;
1295
1296 case BSC_readlink:
1297 bsd_syscalls[code].sc_name = "readlink";
1298 break;
1299
1300 case BSC_fsync:
1301 case BSC_fsync_nocancel:
1302 bsd_syscalls[code].sc_name = "fsync";
1303 bsd_syscalls[code].sc_format = FMT_FD;
1304 break;
1305
1306 case BSC_readv:
1307 case BSC_readv_nocancel:
1308 bsd_syscalls[code].sc_name = "readv";
1309 bsd_syscalls[code].sc_format = FMT_FD_IO;
1310 break;
1311
1312 case BSC_writev:
1313 case BSC_writev_nocancel:
1314 bsd_syscalls[code].sc_name = "writev";
1315 bsd_syscalls[code].sc_format = FMT_FD_IO;
1316 break;
1317
1318 case BSC_pread:
1319 case BSC_pread_nocancel:
1320 bsd_syscalls[code].sc_name = "pread";
1321 bsd_syscalls[code].sc_format = FMT_PREAD;
1322 break;
1323
1324 case BSC_pwrite:
1325 case BSC_pwrite_nocancel:
1326 bsd_syscalls[code].sc_name = "pwrite";
1327 bsd_syscalls[code].sc_format = FMT_PREAD;
1328 break;
1329
1330 case BSC_mkdir:
1331 bsd_syscalls[code].sc_name = "mkdir";
1332 break;
1333
1334 case BSC_mkdir_extended:
1335 bsd_syscalls[code].sc_name = "mkdir_extended";
1336 break;
1337
1338 case BSC_mkfifo:
1339 bsd_syscalls[code].sc_name = "mkfifo";
1340 break;
1341
1342 case BSC_mkfifo_extended:
1343 bsd_syscalls[code].sc_name = "mkfifo_extended";
1344 break;
1345
1346 case BSC_rmdir:
1347 bsd_syscalls[code].sc_name = "rmdir";
1348 break;
1349
1350 case BSC_statfs:
1351 bsd_syscalls[code].sc_name = "statfs";
1352 break;
1353
1354 case BSC_statfs64:
1355 bsd_syscalls[code].sc_name = "statfs64";
1356 break;
1357
1358 case BSC_getfsstat:
1359 bsd_syscalls[code].sc_name = "getfsstat";
1360 break;
1361
1362 case BSC_getfsstat64:
1363 bsd_syscalls[code].sc_name = "getfsstat64";
1364 break;
1365
1366 case BSC_fstatfs:
1367 bsd_syscalls[code].sc_name = "fstatfs";
1368 bsd_syscalls[code].sc_format = FMT_FD;
1369 break;
1370
1371 case BSC_fstatfs64:
1372 bsd_syscalls[code].sc_name = "fstatfs64";
1373 bsd_syscalls[code].sc_format = FMT_FD;
1374 break;
1375
1376 case BSC_pathconf:
1377 bsd_syscalls[code].sc_name = "pathconf";
1378 break;
1379
1380 case BSC_fpathconf:
1381 bsd_syscalls[code].sc_name = "fpathconf";
1382 bsd_syscalls[code].sc_format = FMT_FD;
1383 break;
1384
1385 case BSC_getdirentries:
1386 bsd_syscalls[code].sc_name = "getdirentries";
1387 bsd_syscalls[code].sc_format = FMT_FD_IO;
1388 break;
1389
1390 case BSC_getdirentries64:
1391 bsd_syscalls[code].sc_name = "getdirentries64";
1392 bsd_syscalls[code].sc_format = FMT_FD_IO;
1393 break;
1394
1395 case BSC_lseek:
1396 bsd_syscalls[code].sc_name = "lseek";
1397 bsd_syscalls[code].sc_format = FMT_LSEEK;
1398 break;
1399
1400 case BSC_truncate:
1401 bsd_syscalls[code].sc_name = "truncate";
1402 bsd_syscalls[code].sc_format = FMT_TRUNC;
1403 break;
1404
1405 case BSC_ftruncate:
1406 bsd_syscalls[code].sc_name = "ftruncate";
1407 bsd_syscalls[code].sc_format = FMT_FTRUNC;
1408 break;
1409
1410 case BSC_statv:
1411 bsd_syscalls[code].sc_name = "statv";
1412 break;
1413
1414 case BSC_fstatv:
1415 bsd_syscalls[code].sc_name = "fstatv";
1416 bsd_syscalls[code].sc_format = FMT_FD;
1417 break;
1418
1419 case BSC_mkcomplex:
1420 bsd_syscalls[code].sc_name = "mkcomplex";
1421 break;
1422
1423 case BSC_getattrlist:
1424 bsd_syscalls[code].sc_name = "getattrlist";
1425 break;
1426
1427 case BSC_setattrlist:
1428 bsd_syscalls[code].sc_name = "setattrlist";
1429 break;
1430
1431 case BSC_getdirentriesattr:
1432 bsd_syscalls[code].sc_name = "getdirentriesattr";
1433 bsd_syscalls[code].sc_format = FMT_FD;
1434 break;
1435
1436 case BSC_exchangedata:
1437 bsd_syscalls[code].sc_name = "exchangedata";
1438 break;
1439
1440 case BSC_rename:
1441 bsd_syscalls[code].sc_name = "rename";
1442 break;
1443
1444 case BSC_copyfile:
1445 bsd_syscalls[code].sc_name = "copyfile";
1446 break;
1447
1448 case BSC_checkuseraccess:
1449 bsd_syscalls[code].sc_name = "checkuseraccess";
1450 break;
1451
1452 case BSC_searchfs:
1453 bsd_syscalls[code].sc_name = "searchfs";
1454 break;
1455
1456 case BSC_aio_fsync:
1457 bsd_syscalls[code].sc_name = "aio_fsync";
1458 bsd_syscalls[code].sc_format = FMT_AIO_FSYNC;
1459 break;
1460
1461 case BSC_aio_return:
1462 bsd_syscalls[code].sc_name = "aio_return";
1463 bsd_syscalls[code].sc_format = FMT_AIO_RETURN;
1464 break;
1465
1466 case BSC_aio_suspend:
1467 case BSC_aio_suspend_nocancel:
1468 bsd_syscalls[code].sc_name = "aio_suspend";
1469 bsd_syscalls[code].sc_format = FMT_AIO_SUSPEND;
1470 break;
1471
1472 case BSC_aio_cancel:
1473 bsd_syscalls[code].sc_name = "aio_cancel";
1474 bsd_syscalls[code].sc_format = FMT_AIO_CANCEL;
1475 break;
1476
1477 case BSC_aio_error:
1478 bsd_syscalls[code].sc_name = "aio_error";
1479 bsd_syscalls[code].sc_format = FMT_AIO;
1480 break;
1481
1482 case BSC_aio_read:
1483 bsd_syscalls[code].sc_name = "aio_read";
1484 bsd_syscalls[code].sc_format = FMT_AIO;
1485 break;
1486
1487 case BSC_aio_write:
1488 bsd_syscalls[code].sc_name = "aio_write";
1489 bsd_syscalls[code].sc_format = FMT_AIO;
1490 break;
1491
1492 case BSC_lio_listio:
1493 bsd_syscalls[code].sc_name = "lio_listio";
1494 bsd_syscalls[code].sc_format = FMT_LIO_LISTIO;
1495 break;
1496
1497 case BSC_msync:
1498 case BSC_msync_nocancel:
1499 bsd_syscalls[code].sc_name = "msync";
1500 bsd_syscalls[code].sc_format = FMT_MSYNC;
1501 break;
1502
1503 case BSC_fcntl:
1504 case BSC_fcntl_nocancel:
1505 bsd_syscalls[code].sc_name = "fcntl";
1506 bsd_syscalls[code].sc_format = FMT_FCNTL;
1507 break;
1508
1509 case BSC_ioctl:
1510 bsd_syscalls[code].sc_name = "ioctl";
1511 bsd_syscalls[code].sc_format = FMT_IOCTL;
1512 break;
1513 }
1514 }
1515
1516 for (i = 0; (type = filemgr_call_types[i]); i++) {
1517 char * p;
1518
1519 code = filemgr_index(type);
1520
1521 if (code >= MAX_FILEMGR) {
1522 printf("FILEMGR call init (%x): type exceeds table size\n", type);
1523 continue;
1524 }
1525 switch (type) {
1526
1527 case FILEMGR_PBGETCATALOGINFO:
1528 p = "GetCatalogInfo";
1529 break;
1530
1531 case FILEMGR_PBGETCATALOGINFOBULK:
1532 p = "GetCatalogInfoBulk";
1533 break;
1534
1535 case FILEMGR_PBCREATEFILEUNICODE:
1536 p = "CreateFileUnicode";
1537 break;
1538
1539 case FILEMGR_PBCREATEDIRECTORYUNICODE:
1540 p = "CreateDirectoryUnicode";
1541 break;
1542
1543 case FILEMGR_PBCREATEFORK:
1544 p = "PBCreateFork";
1545 break;
1546
1547 case FILEMGR_PBDELETEFORK:
1548 p = "PBDeleteFork";
1549 break;
1550
1551 case FILEMGR_PBITERATEFORK:
1552 p = "PBIterateFork";
1553 break;
1554
1555 case FILEMGR_PBOPENFORK:
1556 p = "PBOpenFork";
1557 break;
1558
1559 case FILEMGR_PBREADFORK:
1560 p = "PBReadFork";
1561 break;
1562
1563 case FILEMGR_PBWRITEFORK:
1564 p = "PBWriteFork";
1565 break;
1566
1567 case FILEMGR_PBALLOCATEFORK:
1568 p = "PBAllocateFork";
1569 break;
1570
1571 case FILEMGR_PBDELETEOBJECT:
1572 p = "PBDeleteObject";
1573 break;
1574
1575 case FILEMGR_PBEXCHANGEOBJECT:
1576 p = "PBExchangeObject";
1577 break;
1578
1579 case FILEMGR_PBGETFORKCBINFO:
1580 p = "PBGetForkCBInfo";
1581 break;
1582
1583 case FILEMGR_PBGETVOLUMEINFO:
1584 p = "PBGetVolumeInfo";
1585 break;
1586
1587 case FILEMGR_PBMAKEFSREF:
1588 p = "PBMakeFSRef";
1589 break;
1590
1591 case FILEMGR_PBMAKEFSREFUNICODE:
1592 p = "PBMakeFSRefUnicode";
1593 break;
1594
1595 case FILEMGR_PBMOVEOBJECT:
1596 p = "PBMoveObject";
1597 break;
1598
1599 case FILEMGR_PBOPENITERATOR:
1600 p = "PBOpenIterator";
1601 break;
1602
1603 case FILEMGR_PBRENAMEUNICODE:
1604 p = "PBRenameUnicode";
1605 break;
1606
1607 case FILEMGR_PBSETCATALOGINFO:
1608 p = "SetCatalogInfo";
1609 break;
1610
1611 case FILEMGR_PBSETVOLUMEINFO:
1612 p = "SetVolumeInfo";
1613 break;
1614
1615 case FILEMGR_FSREFMAKEPATH:
1616 p = "FSRefMakePath";
1617 break;
1618
1619 case FILEMGR_FSPATHMAKEREF:
1620 p = "FSPathMakeRef";
1621 break;
1622
1623 case FILEMGR_PBGETCATINFO:
1624 p = "GetCatInfo";
1625 break;
1626
1627 case FILEMGR_PBGETCATINFOLITE:
1628 p = "GetCatInfoLite";
1629 break;
1630
1631 case FILEMGR_PBHGETFINFO:
1632 p = "PBHGetFInfo";
1633 break;
1634
1635 case FILEMGR_PBXGETVOLINFO:
1636 p = "PBXGetVolInfo";
1637 break;
1638
1639 case FILEMGR_PBHCREATE:
1640 p = "PBHCreate";
1641 break;
1642
1643 case FILEMGR_PBHOPENDF:
1644 p = "PBHOpenDF";
1645 break;
1646
1647 case FILEMGR_PBHOPENRF:
1648 p = "PBHOpenRF";
1649 break;
1650
1651 case FILEMGR_PBHGETDIRACCESS:
1652 p = "PBHGetDirAccess";
1653 break;
1654
1655 case FILEMGR_PBHSETDIRACCESS:
1656 p = "PBHSetDirAccess";
1657 break;
1658
1659 case FILEMGR_PBHMAPID:
1660 p = "PBHMapID";
1661 break;
1662
1663 case FILEMGR_PBHMAPNAME:
1664 p = "PBHMapName";
1665 break;
1666
1667 case FILEMGR_PBCLOSE:
1668 p = "PBClose";
1669 break;
1670
1671 case FILEMGR_PBFLUSHFILE:
1672 p = "PBFlushFile";
1673 break;
1674
1675 case FILEMGR_PBGETEOF:
1676 p = "PBGetEOF";
1677 break;
1678
1679 case FILEMGR_PBSETEOF:
1680 p = "PBSetEOF";
1681 break;
1682
1683 case FILEMGR_PBGETFPOS:
1684 p = "PBGetFPos";
1685 break;
1686
1687 case FILEMGR_PBREAD:
1688 p = "PBRead";
1689 break;
1690
1691 case FILEMGR_PBWRITE:
1692 p = "PBWrite";
1693 break;
1694
1695 case FILEMGR_PBGETFCBINFO:
1696 p = "PBGetFCBInfo";
1697 break;
1698
1699 case FILEMGR_PBSETFINFO:
1700 p = "PBSetFInfo";
1701 break;
1702
1703 case FILEMGR_PBALLOCATE:
1704 p = "PBAllocate";
1705 break;
1706
1707 case FILEMGR_PBALLOCCONTIG:
1708 p = "PBAllocContig";
1709 break;
1710
1711 case FILEMGR_PBSETFPOS:
1712 p = "PBSetFPos";
1713 break;
1714
1715 case FILEMGR_PBSETCATINFO:
1716 p = "PBSetCatInfo";
1717 break;
1718
1719 case FILEMGR_PBGETVOLPARMS:
1720 p = "PBGetVolParms";
1721 break;
1722
1723 case FILEMGR_PBSETVINFO:
1724 p = "PBSetVInfo";
1725 break;
1726
1727 case FILEMGR_PBMAKEFSSPEC:
1728 p = "PBMakeFSSpec";
1729 break;
1730
1731 case FILEMGR_PBHGETVINFO:
1732 p = "PBHGetVInfo";
1733 break;
1734
1735 case FILEMGR_PBCREATEFILEIDREF:
1736 p = "PBCreateFileIDRef";
1737 break;
1738
1739 case FILEMGR_PBDELETEFILEIDREF:
1740 p = "PBDeleteFileIDRef";
1741 break;
1742
1743 case FILEMGR_PBRESOLVEFILEIDREF:
1744 p = "PBResolveFileIDRef";
1745 break;
1746
1747 case FILEMGR_PBFLUSHVOL:
1748 p = "PBFlushVol";
1749 break;
1750
1751 case FILEMGR_PBHRENAME:
1752 p = "PBHRename";
1753 break;
1754
1755 case FILEMGR_PBCATMOVE:
1756 p = "PBCatMove";
1757 break;
1758
1759 case FILEMGR_PBEXCHANGEFILES:
1760 p = "PBExchangeFiles";
1761 break;
1762
1763 case FILEMGR_PBHDELETE:
1764 p = "PBHDelete";
1765 break;
1766
1767 case FILEMGR_PBDIRCREATE:
1768 p = "PBDirCreate";
1769 break;
1770
1771 case FILEMGR_PBCATSEARCH:
1772 p = "PBCatSearch";
1773 break;
1774
1775 case FILEMGR_PBHSETFLOCK:
1776 p = "PBHSetFlock";
1777 break;
1778
1779 case FILEMGR_PBHRSTFLOCK:
1780 p = "PBHRstFLock";
1781 break;
1782
1783 case FILEMGR_PBLOCKRANGE:
1784 p = "PBLockRange";
1785 break;
1786
1787 case FILEMGR_PBUNLOCKRANGE:
1788 p = "PBUnlockRange";
1789 break;
1790
1791 default:
1792 p = NULL;
1793 break;
1794 }
1795 filemgr_calls[code].fm_name = p;
1796 }
1797 }
1798
1799
1800
1801 int
1802 main(argc, argv)
1803 int argc;
1804 char *argv[];
1805 {
1806 char *myname = "fs_usage";
1807 int i;
1808 char ch;
1809 struct sigaction osa;
1810 void getdivisor();
1811 void argtopid();
1812 void set_remove();
1813 void set_pidcheck();
1814 void set_pidexclude();
1815 int quit();
1816
1817 if (0 != reexec_to_match_kernel()) {
1818 fprintf(stderr, "Could not re-execute: %d\n", errno);
1819 exit(1);
1820 }
1821
1822 get_screenwidth();
1823
1824 /* get our name */
1825 if (argc > 0) {
1826 if ((myname = rindex(argv[0], '/')) == 0) {
1827 myname = argv[0];
1828 }
1829 else {
1830 myname++;
1831 }
1832 }
1833
1834 while ((ch = getopt(argc, argv, "ewf:R:S:E:")) != EOF) {
1835
1836 switch(ch) {
1837
1838 case 'e':
1839 exclude_pids = 1;
1840 exclude_default_pids = 0;
1841 break;
1842
1843 case 'w':
1844 wideflag = 1;
1845 if ((uint)columns < MAX_WIDE_MODE_COLS)
1846 columns = MAX_WIDE_MODE_COLS;
1847 break;
1848
1849 case 'f':
1850 if (!strcmp(optarg, "network"))
1851 filter_mode |= NETWORK_FILTER;
1852 else if (!strcmp(optarg, "filesys"))
1853 filter_mode |= FILESYS_FILTER;
1854 else if (!strcmp(optarg, "cachehit"))
1855 filter_mode &= ~CACHEHIT_FILTER; /* turns on CACHE_HIT */
1856 else if (!strcmp(optarg, "exec"))
1857 filter_mode |= EXEC_FILTER;
1858 else if (!strcmp(optarg, "pathname"))
1859 filter_mode |= PATHNAME_FILTER;
1860 break;
1861
1862 case 'R':
1863 RAW_flag = 1;
1864 RAW_file = optarg;
1865 break;
1866
1867 case 'S':
1868 start_time = atof(optarg);
1869 break;
1870
1871 case 'E':
1872 end_time = atof(optarg);
1873 break;
1874
1875 default:
1876 exit_usage(myname);
1877 }
1878 }
1879 if (!RAW_flag) {
1880 if ( geteuid() != 0 ) {
1881 fprintf(stderr, "'fs_usage' must be run as root...\n");
1882 exit(1);
1883 }
1884 }
1885 argc -= optind;
1886 argv += optind;
1887
1888 /*
1889 * when excluding, fs_usage should be the first in line for pids[]
1890 *
1891 * the !exclude_pids && argc == 0 catches the exclude_default_pids
1892 * case below where exclude_pids is later set and the fs_usage PID
1893 * needs to make it into pids[]
1894 */
1895 if (exclude_pids || (!exclude_pids && argc == 0))
1896 {
1897 if (num_of_pids < (MAX_PIDS - 1))
1898 pids[num_of_pids++] = getpid();
1899 }
1900
1901 /* If we process any list of pids/cmds, then turn off the defaults */
1902 if (argc > 0)
1903 exclude_default_pids = 0;
1904
1905 while (argc > 0 && num_of_pids < (MAX_PIDS - 1)) {
1906 select_pid_mode++;
1907 argtopid(argv[0]);
1908 argc--;
1909 argv++;
1910 }
1911
1912 /* Exclude a set of default pids */
1913 if (exclude_default_pids)
1914 {
1915 argtopid("Terminal");
1916 argtopid("telnetd");
1917 argtopid("telnet");
1918 argtopid("sshd");
1919 argtopid("rlogind");
1920 argtopid("tcsh");
1921 argtopid("csh");
1922 argtopid("sh");
1923 exclude_pids = 1;
1924 }
1925
1926 #if 0
1927 for (i = 0; i < num_of_pids; i++)
1928 {
1929 if (exclude_pids)
1930 fprintf(stderr, "exclude pid %d\n", pids[i]);
1931 else
1932 fprintf(stderr, "pid %d\n", pids[i]);
1933 }
1934 #endif
1935 if (!RAW_flag) {
1936
1937 /* set up signal handlers */
1938 signal(SIGINT, leave);
1939 signal(SIGQUIT, leave);
1940
1941 sigaction(SIGHUP, (struct sigaction *)NULL, &osa);
1942
1943 if (osa.sa_handler == SIG_DFL)
1944 signal(SIGHUP, leave);
1945 signal(SIGTERM, leave);
1946
1947 /* grab the number of cpus */
1948 size_t len;
1949 mib[0] = CTL_HW;
1950 mib[1] = HW_NCPU;
1951 mib[2] = 0;
1952 len = sizeof(num_cpus);
1953 sysctl(mib, 2, &num_cpus, &len, NULL, 0);
1954 num_events = EVENT_BASE * num_cpus;
1955 }
1956 signal(SIGWINCH, sigwinch);
1957
1958 if ((my_buffer = malloc(num_events * sizeof(kd_buf))) == (char *)0)
1959 quit("can't allocate memory for tracing info\n");
1960
1961 if (ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_i386.map", &framework32, "/var/db/dyld/dyld_shared_cache_i386")) {
1962 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64.map", &framework64, "/var/db/dyld/dyld_shared_cache_x86_64");
1963 } else {
1964 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc.map", &framework32, "/var/db/dyld/dyld_shared_cache_ppc");
1965 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc64.map", &framework64, "/var/db/dyld/dyld_shared_cache_ppc64");
1966 }
1967 SortFrameworkAddresses();
1968
1969 cache_disk_names();
1970
1971 if (!RAW_flag) {
1972
1973 set_remove();
1974 set_numbufs(num_events);
1975 set_init();
1976
1977 if (exclude_pids == 0) {
1978 for (i = 0; i < num_of_pids; i++)
1979 set_pidcheck(pids[i], 1);
1980 } else {
1981 for (i = 0; i < num_of_pids; i++)
1982 set_pidexclude(pids[i], 1);
1983 }
1984
1985 if (select_pid_mode && !one_good_pid)
1986 {
1987 /*
1988 An attempt to restrict output to a given
1989 pid or command has failed. Exit gracefully
1990 */
1991 set_remove();
1992 exit_usage(myname);
1993 }
1994
1995 set_enable(1);
1996 init_arguments_buffer();
1997 }
1998 getdivisor();
1999
2000 init_tables();
2001
2002 /* main loop */
2003
2004 while (1) {
2005 if (!RAW_flag)
2006 usleep(1000 * usleep_ms);
2007
2008 sample_sc();
2009
2010 last_time = time((long *)0);
2011 }
2012 }
2013
2014 void
2015 find_proc_names()
2016 {
2017 size_t bufSize = 0;
2018 struct kinfo_proc *kp;
2019 int quit();
2020
2021 mib[0] = CTL_KERN;
2022 mib[1] = KERN_PROC;
2023 mib[2] = KERN_PROC_ALL;
2024 mib[3] = 0;
2025
2026 if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0)
2027 quit("trace facility failure, KERN_PROC_ALL\n");
2028
2029 if((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0)
2030 quit("can't allocate memory for proc buffer\n");
2031
2032 if (sysctl(mib, 4, kp, &bufSize, NULL, 0) < 0)
2033 quit("trace facility failure, KERN_PROC_ALL\n");
2034
2035 kp_nentries = bufSize/ sizeof(struct kinfo_proc);
2036 kp_buffer = kp;
2037 }
2038
2039
2040 void destroy_thread(struct th_info *ti) {
2041
2042 ti->child_thread = 0;
2043 ti->thread = 0;
2044 ti->pid = 0;
2045
2046 if (ti->my_index < cur_start)
2047 cur_start = ti->my_index;
2048
2049 if (ti->my_index == cur_max) {
2050 while (ti >= &th_state[0]) {
2051 if (ti->thread)
2052 break;
2053 ti--;
2054 }
2055 cur_max = ti->my_index;
2056 }
2057 }
2058
2059
2060 struct th_info *find_empty(void) {
2061 struct th_info *ti;
2062
2063 for (ti = &th_state[cur_start]; ti < &th_state[MAX_THREADS]; ti++, cur_start++) {
2064 if (ti->thread == 0) {
2065 if (cur_start > cur_max)
2066 cur_max = cur_start;
2067 cur_start++;
2068
2069 return (ti);
2070 }
2071 }
2072 return ((struct th_info *)0);
2073
2074 }
2075
2076
2077 struct th_info *find_thread(uintptr_t thread, int type) {
2078 struct th_info *ti;
2079
2080 for (ti = &th_state[0]; ti <= &th_state[cur_max]; ti++) {
2081 if (ti->thread == thread) {
2082 if (type == ti->type)
2083 return(ti);
2084 if (ti->in_filemgr) {
2085 if (type == -1)
2086 return(ti);
2087 continue;
2088 }
2089 if (type == 0)
2090 return(ti);
2091 }
2092 }
2093 return ((struct th_info *)0);
2094 }
2095
2096
2097 void
2098 mark_thread_waited(uintptr_t thread) {
2099 struct th_info *ti;
2100
2101 for (ti = th_state; ti <= &th_state[cur_max]; ti++) {
2102 if (ti->thread == thread) {
2103 ti->waited = 1;
2104 }
2105 }
2106 }
2107
2108
2109 void
2110 set_enable(int val)
2111 {
2112 mib[0] = CTL_KERN;
2113 mib[1] = KERN_KDEBUG;
2114 mib[2] = KERN_KDENABLE; /* protocol */
2115 mib[3] = val;
2116 mib[4] = 0;
2117 mib[5] = 0; /* no flags */
2118 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
2119 quit("trace facility failure, KERN_KDENABLE\n");
2120
2121 if (val)
2122 trace_enabled = 1;
2123 else
2124 trace_enabled = 0;
2125 }
2126
2127 void
2128 set_numbufs(int nbufs)
2129 {
2130 mib[0] = CTL_KERN;
2131 mib[1] = KERN_KDEBUG;
2132 mib[2] = KERN_KDSETBUF;
2133 mib[3] = nbufs;
2134 mib[4] = 0;
2135 mib[5] = 0; /* no flags */
2136 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
2137 quit("trace facility failure, KERN_KDSETBUF\n");
2138
2139 mib[0] = CTL_KERN;
2140 mib[1] = KERN_KDEBUG;
2141 mib[2] = KERN_KDSETUP;
2142 mib[3] = 0;
2143 mib[4] = 0;
2144 mib[5] = 0; /* no flags */
2145 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
2146 quit("trace facility failure, KERN_KDSETUP\n");
2147 }
2148
2149 void
2150 set_pidcheck(int pid, int on_off)
2151 {
2152 kd_regtype kr;
2153
2154 kr.type = KDBG_TYPENONE;
2155 kr.value1 = pid;
2156 kr.value2 = on_off;
2157 needed = sizeof(kd_regtype);
2158 mib[0] = CTL_KERN;
2159 mib[1] = KERN_KDEBUG;
2160 mib[2] = KERN_KDPIDTR;
2161 mib[3] = 0;
2162 mib[4] = 0;
2163 mib[5] = 0;
2164
2165 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
2166 if (on_off == 1)
2167 fprintf(stderr, "pid %d does not exist\n", pid);
2168 }
2169 else {
2170 one_good_pid++;
2171 }
2172 }
2173
2174 /*
2175 on_off == 0 turns off pid exclusion
2176 on_off == 1 turns on pid exclusion
2177 */
2178 void
2179 set_pidexclude(int pid, int on_off)
2180 {
2181 kd_regtype kr;
2182
2183 one_good_pid++;
2184
2185 kr.type = KDBG_TYPENONE;
2186 kr.value1 = pid;
2187 kr.value2 = on_off;
2188 needed = sizeof(kd_regtype);
2189 mib[0] = CTL_KERN;
2190 mib[1] = KERN_KDEBUG;
2191 mib[2] = KERN_KDPIDEX;
2192 mib[3] = 0;
2193 mib[4] = 0;
2194 mib[5] = 0;
2195
2196 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
2197 if (on_off == 1)
2198 fprintf(stderr, "pid %d does not exist\n", pid);
2199 }
2200 }
2201
2202 void
2203 get_bufinfo(kbufinfo_t *val)
2204 {
2205 needed = sizeof (*val);
2206 mib[0] = CTL_KERN;
2207 mib[1] = KERN_KDEBUG;
2208 mib[2] = KERN_KDGETBUF;
2209 mib[3] = 0;
2210 mib[4] = 0;
2211 mib[5] = 0; /* no flags */
2212
2213 if (sysctl(mib, 3, val, &needed, 0, 0) < 0)
2214 quit("trace facility failure, KERN_KDGETBUF\n");
2215
2216 }
2217
2218 void
2219 set_remove()
2220 {
2221 errno = 0;
2222
2223 mib[0] = CTL_KERN;
2224 mib[1] = KERN_KDEBUG;
2225 mib[2] = KERN_KDREMOVE; /* protocol */
2226 mib[3] = 0;
2227 mib[4] = 0;
2228 mib[5] = 0; /* no flags */
2229 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
2230 {
2231 set_remove_flag = 0;
2232
2233 if (errno == EBUSY)
2234 quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n");
2235 else
2236 quit("trace facility failure, KERN_KDREMOVE\n");
2237 }
2238 }
2239
2240 void
2241 set_init()
2242 { kd_regtype kr;
2243
2244 kr.type = KDBG_RANGETYPE;
2245 kr.value1 = 0;
2246 kr.value2 = -1;
2247 needed = sizeof(kd_regtype);
2248 mib[0] = CTL_KERN;
2249 mib[1] = KERN_KDEBUG;
2250 mib[2] = KERN_KDSETREG;
2251 mib[3] = 0;
2252 mib[4] = 0;
2253 mib[5] = 0; /* no flags */
2254
2255 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
2256 quit("trace facility failure, KERN_KDSETREG\n");
2257
2258 mib[0] = CTL_KERN;
2259 mib[1] = KERN_KDEBUG;
2260 mib[2] = KERN_KDSETUP;
2261 mib[3] = 0;
2262 mib[4] = 0;
2263 mib[5] = 0; /* no flags */
2264
2265 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
2266 quit("trace facility failure, KERN_KDSETUP\n");
2267 }
2268
2269 void
2270 sample_sc()
2271 {
2272 kd_buf *kd;
2273 int i, count;
2274 size_t needed;
2275 uint32_t my_buffer_size = 0;
2276 void read_command_map();
2277 void create_map_entry();
2278
2279 if (!RAW_flag) {
2280 /* Get kernel buffer information */
2281 get_bufinfo(&bufinfo);
2282 } else {
2283 my_buffer_size = num_events * sizeof(kd_buf);
2284 }
2285 if (need_new_map) {
2286 read_command_map();
2287 need_new_map = 0;
2288 }
2289 if (!RAW_flag) {
2290 needed = bufinfo.nkdbufs * sizeof(kd_buf);
2291 mib[0] = CTL_KERN;
2292 mib[1] = KERN_KDEBUG;
2293 mib[2] = KERN_KDREADTR;
2294 mib[3] = 0;
2295 mib[4] = 0;
2296 mib[5] = 0; /* no flags */
2297
2298 if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0)
2299 quit("trace facility failure, KERN_KDREADTR\n");
2300 count = needed;
2301
2302 if (count > (num_events / 8)) {
2303 if (usleep_ms > USLEEP_BEHIND)
2304 usleep_ms = USLEEP_BEHIND;
2305 else if (usleep_ms > USLEEP_MIN)
2306 usleep_ms /= 2;
2307
2308 } else if (count < (num_events / 16)) {
2309 if (usleep_ms < USLEEP_MAX)
2310 usleep_ms *= 2;
2311 }
2312
2313 if (bufinfo.flags & KDBG_WRAPPED) {
2314 fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly: %d\n", count);
2315
2316 for (i = 0; i <= cur_max; i++) {
2317 th_state[i].thread = 0;
2318 th_state[i].pid = 0;
2319 th_state[i].pathptr = (uintptr_t *)NULL;
2320 th_state[i].pathname[0] = 0;
2321 }
2322 cur_max = 0;
2323 cur_start = 0;
2324 need_new_map = 1;
2325 map_is_the_same = 0;
2326
2327 set_enable(0);
2328 set_enable(1);
2329 }
2330 } else {
2331 int bytes_read;
2332
2333 if ((bytes_read = read(RAW_fd, my_buffer, my_buffer_size)) < sizeof(kd_buf))
2334 exit(0);
2335 count = bytes_read / sizeof(kd_buf);
2336 }
2337 kd = (kd_buf *)my_buffer;
2338 #if 0
2339 fprintf(stderr, "READTR returned %d items\n", count);
2340 #endif
2341 for (i = 0; i < count; i++) {
2342 uint32_t debugid;
2343 uintptr_t thread;
2344 int type;
2345 int index;
2346 uintptr_t *sargptr;
2347 uint64_t now;
2348 long long l_usecs;
2349 int secs;
2350 long curr_time;
2351 struct th_info *ti;
2352 struct diskio *dio;
2353
2354
2355 thread = kd[i].arg5;
2356 debugid = kd[i].debugid;
2357 type = kd[i].debugid & DBG_FUNC_MASK;
2358
2359 now = kdbg_get_timestamp(&kd[i]);
2360
2361 if (i == 0 && !RAW_flag)
2362 {
2363 curr_time = time((long *)0);
2364 /*
2365 * Compute bias seconds after each trace buffer read.
2366 * This helps resync timestamps with the system clock
2367 * in the event of a system sleep.
2368 */
2369 if (bias_secs == 0 || curr_time < last_time || curr_time > (last_time + 2)) {
2370 l_usecs = (long long)(now / divisor);
2371 secs = l_usecs / 1000000;
2372 bias_secs = curr_time - secs;
2373 }
2374 }
2375 if (RAW_flag && bias_now == 0.0)
2376 bias_now = now;
2377
2378 if ((type & P_DISKIO_MASK) == P_DISKIO) {
2379 insert_diskio(type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, thread, (double)now);
2380 continue;
2381 }
2382 if ((type & P_DISKIO_MASK) == P_DISKIO_DONE) {
2383 if ((dio = complete_diskio(kd[i].arg1, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
2384 print_diskio(dio);
2385 free_diskio(dio);
2386 }
2387 continue;
2388 }
2389
2390 switch (type) {
2391
2392 case TRACE_DATA_NEWTHREAD:
2393
2394 if ((ti = find_empty()) == NULL)
2395 continue;
2396
2397 ti->thread = thread;
2398 ti->child_thread = kd[i].arg1;
2399 ti->pid = kd[i].arg2;
2400 continue;
2401
2402 case TRACE_STRING_NEWTHREAD:
2403 if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
2404 continue;
2405 if (ti->child_thread == 0)
2406 continue;
2407 create_map_entry(ti->child_thread, ti->pid, (char *)&kd[i].arg1);
2408
2409 destroy_thread(ti);
2410
2411 continue;
2412
2413 case TRACE_DATA_EXEC:
2414
2415 if ((ti = find_empty()) == NULL)
2416 continue;
2417
2418 ti->thread = thread;
2419 ti->pid = kd[i].arg1;
2420 continue;
2421
2422 case TRACE_STRING_EXEC:
2423 if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
2424 {
2425 /* this is for backwards compatibility */
2426 create_map_entry(thread, 0, (char *)&kd[i].arg1);
2427 }
2428 else
2429 {
2430 create_map_entry(thread, ti->pid, (char *)&kd[i].arg1);
2431
2432 destroy_thread(ti);
2433 }
2434 continue;
2435
2436 case BSC_exit:
2437 kill_thread_map(thread);
2438 continue;
2439
2440 case BSC_mmap:
2441 if (kd[i].arg4 & MAP_ANON)
2442 continue;
2443 break;
2444
2445 case MACH_idle:
2446 case MACH_sched:
2447 case MACH_stkhandoff:
2448 mark_thread_waited(thread);
2449 continue;
2450
2451 case VFS_LOOKUP:
2452 if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
2453 continue;
2454
2455 if (ti->pathptr == NULL) {
2456 sargptr = ti->pathname;
2457 *sargptr++ = kd[i].arg2;
2458 *sargptr++ = kd[i].arg3;
2459 *sargptr++ = kd[i].arg4;
2460 /*
2461 * NULL terminate the 'string'
2462 */
2463 *sargptr = 0;
2464 ti->pathptr = sargptr;
2465 } else {
2466 sargptr = ti->pathptr;
2467
2468 /*
2469 * We don't want to overrun our pathname buffer if the
2470 * kernel sends us more VFS_LOOKUP entries than we can
2471 * handle.
2472 */
2473 if ((uintptr_t)sargptr >= (uintptr_t)&ti->pathname[NUMPARMS]) {
2474 continue;
2475 }
2476
2477 /*
2478 * We need to detect consecutive vfslookup entries.
2479 * So, if we get here and find a START entry,
2480 * fake the pathptr so we can bypass all further
2481 * vfslookup entries.
2482 */
2483 if (debugid & DBG_FUNC_START) {
2484 ti->pathptr = &ti->pathname[NUMPARMS];
2485 continue;
2486 }
2487 *sargptr++ = kd[i].arg1;
2488 *sargptr++ = kd[i].arg2;
2489 *sargptr++ = kd[i].arg3;
2490 *sargptr++ = kd[i].arg4;
2491 /*
2492 * NULL terminate the 'string'
2493 */
2494 *sargptr = 0;
2495 ti->pathptr = sargptr;
2496 }
2497 continue;
2498 }
2499
2500 if (debugid & DBG_FUNC_START) {
2501 char * p;
2502
2503 if ((type & CLASS_MASK) == FILEMGR_BASE) {
2504
2505 index = filemgr_index(type);
2506
2507 if (index >= MAX_FILEMGR)
2508 continue;
2509
2510 if ((p = filemgr_calls[index].fm_name) == NULL)
2511 continue;
2512 } else
2513 p = NULL;
2514
2515 enter_syscall(thread, type, &kd[i], p, (double)now);
2516 continue;
2517 }
2518
2519 switch (type) {
2520
2521 case SPEC_ioctl:
2522 if (kd[i].arg2 == DKIOCSYNCHRONIZECACHE)
2523 exit_syscall("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_SPEC_IOCTL, (double)now);
2524 else {
2525 if ((ti = find_thread(thread, type))) {
2526 destroy_thread(ti);
2527 }
2528 }
2529 continue;
2530
2531 case MACH_pageout:
2532 if (kd[i].arg2)
2533 exit_syscall("PAGE_OUT_ANON", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now);
2534 else
2535 exit_syscall("PAGE_OUT_FILE", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now);
2536 continue;
2537
2538 case MACH_vmfault:
2539 if (kd[i].arg4 == DBG_PAGEIN_FAULT)
2540 exit_syscall("PAGE_IN", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
2541 else if (kd[i].arg4 == DBG_PAGEINV_FAULT)
2542 exit_syscall("PAGE_IN_FILE", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
2543 else if (kd[i].arg4 == DBG_PAGEIND_FAULT)
2544 exit_syscall("PAGE_IN_ANON", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
2545 else if (kd[i].arg4 == DBG_CACHE_HIT_FAULT)
2546 exit_syscall("CACHE_HIT", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_CACHEHIT, (double)now);
2547 else {
2548 if ((ti = find_thread(thread, type))) {
2549 destroy_thread(ti);
2550 }
2551 }
2552 continue;
2553
2554 case MSC_map_fd:
2555 exit_syscall("map_fd", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_FD, (double)now);
2556 continue;
2557
2558 case BSC_mmap_extended:
2559 case BSC_mmap_extended2:
2560 case BSC_msync_extended:
2561 case BSC_pread_extended:
2562 case BSC_pwrite_extended:
2563 extend_syscall(thread, type, &kd[i]);
2564 continue;
2565 }
2566
2567 if ((type & CSC_MASK) == BSC_BASE) {
2568
2569 index = BSC_INDEX(type);
2570
2571 if (index >= MAX_BSD_SYSCALL)
2572 continue;
2573
2574 if (bsd_syscalls[index].sc_name == NULL)
2575 continue;
2576
2577 if (type == BSC_execve)
2578 execs_in_progress--;
2579
2580 exit_syscall(bsd_syscalls[index].sc_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
2581 bsd_syscalls[index].sc_format, (double)now);
2582
2583 continue;
2584 }
2585
2586 if ((type & CLASS_MASK) == FILEMGR_BASE) {
2587
2588 index = filemgr_index(type);
2589
2590 if (index >= MAX_FILEMGR)
2591 continue;
2592
2593 if (filemgr_calls[index].fm_name == NULL)
2594 continue;
2595
2596 exit_syscall(filemgr_calls[index].fm_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
2597 FMT_DEFAULT, (double)now);
2598 }
2599 }
2600 fflush(0);
2601 }
2602
2603
2604
2605
2606 void
2607 enter_syscall_now(uintptr_t thread, int type, kd_buf *kd, char *name, double now)
2608 {
2609 struct th_info *ti;
2610 int secs;
2611 int usecs;
2612 long long l_usecs;
2613 long curr_time;
2614 kd_threadmap *map;
2615 kd_threadmap *find_thread_map();
2616 int clen = 0;
2617 int tsclen = 0;
2618 int nmclen = 0;
2619 int argsclen = 0;
2620 char buf[MAXWIDTH];
2621
2622 if (execs_in_progress) {
2623 if ((ti = find_thread(thread, BSC_execve))) {
2624 if (ti->pathptr) {
2625 exit_syscall("execve", thread, BSC_execve, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
2626 execs_in_progress--;
2627 }
2628 }
2629 }
2630 if ((ti = find_empty()) == NULL)
2631 return;
2632
2633 if ((type & CLASS_MASK) == FILEMGR_BASE &&
2634 (!RAW_flag || (now >= start_time && now <= end_time))) {
2635
2636 filemgr_in_progress++;
2637 ti->in_filemgr = 1;
2638
2639 if (RAW_flag) {
2640 l_usecs = (long long)((now - bias_now) / divisor);
2641 l_usecs += ((long long)8 * (long long)3600 * (long long)1000000);
2642 } else
2643 l_usecs = (long long)(now / divisor);
2644 secs = l_usecs / 1000000;
2645 curr_time = bias_secs + secs;
2646
2647 sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
2648 tsclen = strlen(buf);
2649
2650 if (columns > MAXCOLS || wideflag) {
2651 usecs = l_usecs - (long long)((long long)secs * 1000000);
2652 sprintf(&buf[tsclen], ".%03ld", (long)usecs / 1000);
2653 tsclen = strlen(buf);
2654 }
2655
2656 /*
2657 * Print timestamp column
2658 */
2659 printf("%s", buf);
2660
2661 map = find_thread_map(thread);
2662 if (map) {
2663 sprintf(buf, " %-25.25s ", name);
2664 nmclen = strlen(buf);
2665 printf("%s", buf);
2666
2667 sprintf(buf, "(%d, 0x%lx, 0x%lx, 0x%lx)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
2668 argsclen = strlen(buf);
2669
2670 /*
2671 * Calculate white space out to command
2672 */
2673 if (columns > MAXCOLS || wideflag) {
2674 clen = columns - (tsclen + nmclen + argsclen + 20);
2675 } else
2676 clen = columns - (tsclen + nmclen + argsclen + 12);
2677
2678 if (clen > 0) {
2679 printf("%s", buf); /* print the kdargs */
2680 memset(buf, ' ', clen);
2681 buf[clen] = '\0';
2682 printf("%s", buf);
2683 }
2684 else if ((argsclen + clen) > 0) {
2685 /*
2686 * no room so wipe out the kdargs
2687 */
2688 memset(buf, ' ', (argsclen + clen));
2689 buf[argsclen + clen] = '\0';
2690 printf("%s", buf);
2691 }
2692 if (columns > MAXCOLS || wideflag)
2693 printf("%-20.20s\n", map->command);
2694 else
2695 printf("%-12.12s\n", map->command);
2696 } else
2697 printf(" %-24.24s (%5d, %#lx, 0x%lx, 0x%lx)\n", name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
2698 }
2699 ti->thread = thread;
2700 ti->waited = 0;
2701 ti->type = type;
2702 ti->stime = now;
2703 ti->arg1 = kd->arg1;
2704 ti->arg2 = kd->arg2;
2705 ti->arg3 = kd->arg3;
2706 ti->arg4 = kd->arg4;
2707 ti->pathptr = (uintptr_t *)NULL;
2708 ti->pathname[0] = 0;
2709 }
2710
2711
2712 void
2713 enter_syscall(uintptr_t thread, int type, kd_buf *kd, char *name, double now)
2714 {
2715 int index;
2716
2717 if (type == MACH_pageout || type == MACH_vmfault || type == MSC_map_fd || type == SPEC_ioctl) {
2718 enter_syscall_now(thread, type, kd, name, now);
2719 return;
2720 }
2721 if ((type & CSC_MASK) == BSC_BASE) {
2722
2723 index = BSC_INDEX(type);
2724
2725 if (index >= MAX_BSD_SYSCALL)
2726 return;
2727
2728 if (type == BSC_execve)
2729 execs_in_progress++;
2730
2731 if (bsd_syscalls[index].sc_name)
2732 enter_syscall_now(thread, type, kd, name, now);
2733
2734 return;
2735 }
2736 if ((type & CLASS_MASK) == FILEMGR_BASE) {
2737
2738 index = filemgr_index(type);
2739
2740 if (index >= MAX_FILEMGR)
2741 return;
2742
2743 if (filemgr_calls[index].fm_name)
2744 enter_syscall_now(thread, type, kd, name, now);
2745 }
2746 }
2747
2748 /*
2749 * Handle system call extended trace data.
2750 * pread and pwrite:
2751 * Wipe out the kd args that were collected upon syscall_entry
2752 * because it is the extended info that we really want, and it
2753 * is all we really need.
2754 */
2755
2756 void
2757 extend_syscall(uintptr_t thread, int type, kd_buf *kd)
2758 {
2759 struct th_info *ti;
2760
2761 switch (type) {
2762 case BSC_mmap_extended:
2763 if ((ti = find_thread(thread, BSC_mmap)) == (struct th_info *)0)
2764 return;
2765 ti->arg8 = ti->arg3; /* save protection */
2766 ti->arg1 = kd->arg1; /* the fd */
2767 ti->arg3 = kd->arg2; /* bottom half address */
2768 ti->arg5 = kd->arg3; /* bottom half size */
2769 break;
2770 case BSC_mmap_extended2:
2771 if ((ti = find_thread(thread, BSC_mmap)) == (struct th_info *)0)
2772 return;
2773 ti->arg2 = kd->arg1; /* top half address */
2774 ti->arg4 = kd->arg2; /* top half size */
2775 ti->arg6 = kd->arg3; /* top half file offset */
2776 ti->arg7 = kd->arg4; /* bottom half file offset */
2777 break;
2778 case BSC_msync_extended:
2779 if ((ti = find_thread(thread, BSC_msync)) == (struct th_info *)0) {
2780 if ((ti = find_thread(thread, BSC_msync_nocancel)) == (struct th_info *)0)
2781 return;
2782 }
2783 ti->arg4 = kd->arg1; /* top half address */
2784 ti->arg5 = kd->arg2; /* top half size */
2785 break;
2786 case BSC_pread_extended:
2787 if ((ti = find_thread(thread, BSC_pread)) == (struct th_info *)0) {
2788 if ((ti = find_thread(thread, BSC_pread_nocancel)) == (struct th_info *)0)
2789 return;
2790 }
2791 ti->arg1 = kd->arg1; /* the fd */
2792 ti->arg2 = kd->arg2; /* nbytes */
2793 ti->arg3 = kd->arg3; /* top half offset */
2794 ti->arg4 = kd->arg4; /* bottom half offset */
2795 break;
2796 case BSC_pwrite_extended:
2797 if ((ti = find_thread(thread, BSC_pwrite)) == (struct th_info *)0) {
2798 if ((ti = find_thread(thread, BSC_pwrite_nocancel)) == (struct th_info *)0)
2799 return;
2800 }
2801 ti->arg1 = kd->arg1; /* the fd */
2802 ti->arg2 = kd->arg2; /* nbytes */
2803 ti->arg3 = kd->arg3; /* top half offset */
2804 ti->arg4 = kd->arg4; /* bottom half offset */
2805 break;
2806 default:
2807 return;
2808 }
2809 }
2810
2811
2812 void
2813 exit_syscall(char *sc_name, uintptr_t thread, int type, int arg1, int arg2, int arg3, int arg4,
2814 int format, double now)
2815 {
2816 struct th_info *ti;
2817
2818 if ((ti = find_thread(thread, type)) == (struct th_info *)0)
2819 return;
2820
2821 if (check_filter_mode(ti, type, arg1, arg2, sc_name))
2822 format_print(ti, sc_name, thread, type, arg1, arg2, arg3, arg4, format, now, ti->stime, ti->waited, (char *)ti->pathname, NULL);
2823
2824 if ((type & CLASS_MASK) == FILEMGR_BASE) {
2825 ti->in_filemgr = 0;
2826
2827 if (filemgr_in_progress > 0)
2828 filemgr_in_progress--;
2829 }
2830 destroy_thread(ti);
2831 }
2832
2833
2834 void
2835 get_mode_nibble(char * buf, int smode, int special, char x_on, char x_off)
2836 {
2837 if (smode & 04)
2838 buf[0] = 'r';
2839 if (smode & 02)
2840 buf[1] = 'w';
2841 if (smode & 01) {
2842 if (special)
2843 buf[2] = x_on;
2844 else
2845 buf[2] = 'x';
2846 } else {
2847 if (special)
2848 buf[2] = x_off;
2849 }
2850 }
2851
2852
2853 void
2854 get_mode_string(int mode, char *buf)
2855 {
2856 memset(buf, '-', 9);
2857 buf[9] = '\0';
2858
2859 get_mode_nibble(&buf[6], mode, (mode & 01000), 't', 'T');
2860 get_mode_nibble(&buf[3], (mode>>3), (mode & 02000), 's', 'S');
2861 get_mode_nibble(&buf[0], (mode>>6), (mode & 04000), 's', 'S');
2862 }
2863
2864
2865 int clip_64bit(char *s, uint64_t value)
2866 {
2867 int clen = 0;
2868
2869 if ( (value & 0xff00000000000000LL) )
2870 clen = printf("%s0x%16.16qx", s, value);
2871 else if ( (value & 0x00ff000000000000LL) )
2872 clen = printf("%s0x%14.14qx ", s, value);
2873 else if ( (value & 0x0000ff0000000000LL) )
2874 clen = printf("%s0x%12.12qx ", s, value);
2875 else if ( (value & 0x000000ff00000000LL) )
2876 clen = printf("%s0x%10.10qx ", s, value);
2877 else
2878 clen = printf("%s0x%8.8qx ", s, value);
2879
2880 return (clen);
2881 }
2882
2883
2884 void
2885 format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, int arg1, int arg2, int arg3, int arg4,
2886 int format, double now, double stime, int waited, char *pathname, struct diskio *dio)
2887 {
2888 int secs;
2889 int usecs;
2890 int nopadding = 0;
2891 long long l_usecs;
2892 long curr_time;
2893 char *command_name;
2894 kd_threadmap *map;
2895 kd_threadmap *find_thread_map();
2896 int in_filemgr = 0;
2897 int len = 0;
2898 int clen = 0;
2899 int tlen = 0;
2900 int class;
2901 uint64_t user_addr;
2902 uint64_t user_size;
2903 char *framework_name;
2904 char *framework_type;
2905 char *p1;
2906 char *p2;
2907 char buf[MAXWIDTH];
2908 command_name = "";
2909 int need_msec_update = 0;
2910 static char timestamp[32];
2911 static int last_timestamp = -1;
2912 static int timestamp_len = 0;
2913 static int last_msec = 0;
2914
2915
2916 if (RAW_flag) {
2917 l_usecs = (long long)((now - bias_now) / divisor);
2918
2919 if ((double)l_usecs < start_time || (double)l_usecs > end_time)
2920 return;
2921 l_usecs += ((long long)8 * (long long)3600 * (long long)1000000);
2922 } else
2923 l_usecs = (long long)(now / divisor);
2924 secs = l_usecs / 1000000;
2925 curr_time = bias_secs + secs;
2926
2927 class = type >> 24;
2928
2929 if (dio)
2930 command_name = dio->issuing_command;
2931 else {
2932 if (map_is_the_same && thread == last_thread)
2933 map = last_map;
2934 else {
2935 if ((map = find_thread_map(thread))) {
2936 last_map = map;
2937 last_thread = thread;
2938 map_is_the_same = 1;
2939 }
2940 }
2941 if (map)
2942 command_name = map->command;
2943 }
2944 if (last_timestamp != curr_time) {
2945 timestamp_len = sprintf(timestamp, "%-8.8s", &(ctime(&curr_time)[11]));
2946 last_timestamp = curr_time;
2947 need_msec_update = 1;
2948 }
2949 if (columns > MAXCOLS || wideflag) {
2950 int msec;
2951
2952 tlen = timestamp_len;
2953 nopadding = 0;
2954 msec = (l_usecs - (long long)((long long)secs * 1000000)) / 1000;
2955
2956 if (msec != last_msec || need_msec_update) {
2957 sprintf(&timestamp[tlen], ".%03ld", (long)msec);
2958 last_msec = msec;
2959 }
2960 tlen += 4;
2961
2962 timestamp[tlen] = '\0';
2963
2964 if (filemgr_in_progress) {
2965 if (class != FILEMGR_CLASS) {
2966 if (find_thread(thread, -1)) {
2967 in_filemgr = 1;
2968 }
2969 }
2970 }
2971 } else
2972 nopadding = 1;
2973
2974 if ((class == FILEMGR_CLASS) && (columns > MAXCOLS || wideflag))
2975 clen = printf("%s %-20.20s", timestamp, sc_name);
2976 else if (in_filemgr)
2977 clen = printf("%s %-15.15s", timestamp, sc_name);
2978 else
2979 clen = printf("%s %-17.17s", timestamp, sc_name);
2980
2981
2982 framework_name = NULL;
2983
2984 if (columns > MAXCOLS || wideflag) {
2985
2986 off_t offset_reassembled = 0LL;
2987
2988 switch (format) {
2989
2990 case FMT_DEFAULT:
2991 /*
2992 * pathname based system calls or
2993 * calls with no fd or pathname (i.e. sync)
2994 */
2995 if (arg1)
2996 clen += printf(" [%3d] ", arg1);
2997 else
2998 clen += printf(" ");
2999 break;
3000
3001 case FMT_FD:
3002 /*
3003 * fd based system call... no I/O
3004 */
3005 if (arg1)
3006 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3007 else
3008 clen += printf(" F=%-3d", ti->arg1);
3009 break;
3010
3011 case FMT_FD_2:
3012 /*
3013 * accept, dup, dup2
3014 */
3015 if (arg1)
3016 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3017 else
3018 clen += printf(" F=%-3d F=%-3d", ti->arg1, arg2);
3019 break;
3020
3021 case FMT_FD_IO:
3022 /*
3023 * system calls with fd's that return an I/O completion count
3024 */
3025 if (arg1)
3026 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3027 else
3028 clen += printf(" F=%-3d B=0x%-6x", ti->arg1, arg2);
3029 break;
3030
3031 case FMT_PGIN:
3032 /*
3033 * pagein
3034 */
3035 user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3;
3036
3037 lookup_name(user_addr, &framework_type, &framework_name);
3038 clen += clip_64bit(" A=", user_addr);
3039 break;
3040
3041 case FMT_CACHEHIT:
3042 /*
3043 * cache hit
3044 */
3045 user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3;
3046
3047 lookup_name(user_addr, &framework_type, &framework_name);
3048 clen += clip_64bit(" A=", user_addr);
3049 break;
3050
3051 case FMT_PGOUT:
3052 /*
3053 * pageout
3054 */
3055 clen += printf(" B=0x%-8x", arg2);
3056 break;
3057
3058 case FMT_DISKIO:
3059 /*
3060 * physical disk I/O
3061 */
3062 if (dio->io_errno)
3063 clen += printf(" D=0x%8.8x [%3d]", dio->blkno, dio->io_errno);
3064 else
3065 clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s", dio->blkno, dio->iosize, find_disk_name(dio->dev));
3066 break;
3067
3068 case FMT_MSYNC:
3069 {
3070 /*
3071 * msync
3072 */
3073 int mlen = 0;
3074
3075 buf[0] = '\0';
3076
3077 if (ti->arg3 & MS_ASYNC)
3078 mlen += sprintf(&buf[mlen], "MS_ASYNC | ");
3079 else
3080 mlen += sprintf(&buf[mlen], "MS_SYNC | ");
3081
3082 if (ti->arg3 & MS_INVALIDATE)
3083 mlen += sprintf(&buf[mlen], "MS_INVALIDATE | ");
3084 if (ti->arg3 & MS_KILLPAGES)
3085 mlen += sprintf(&buf[mlen], "MS_KILLPAGES | ");
3086 if (ti->arg3 & MS_DEACTIVATE)
3087 mlen += sprintf(&buf[mlen], "MS_DEACTIVATE | ");
3088
3089 if (ti->arg3 & ~(MS_ASYNC | MS_SYNC | MS_INVALIDATE | MS_KILLPAGES | MS_DEACTIVATE))
3090 mlen += sprintf(&buf[mlen], "UNKNOWN | ");
3091
3092 if (mlen)
3093 buf[mlen - 3] = '\0';
3094
3095 if (arg1)
3096 clen += printf(" [%3d]", arg1);
3097
3098 user_addr = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg1);
3099 clen += clip_64bit(" A=", user_addr);
3100
3101 user_size = (((off_t)(unsigned int)(ti->arg5)) << 32) | (unsigned int)(ti->arg2);
3102
3103 clen += printf(" B=0x%-16qx <%s>", user_size, buf);
3104
3105 break;
3106 }
3107
3108 case FMT_FCNTL:
3109 {
3110 /*
3111 * fcntl
3112 */
3113 char *p = NULL;
3114 int fd = -1;
3115
3116 if (arg1)
3117 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3118 else
3119 clen += printf(" F=%-3d", ti->arg1);
3120
3121 switch(ti->arg2) {
3122
3123 case F_DUPFD:
3124 p = "DUPFD";
3125 break;
3126
3127 case F_GETFD:
3128 p = "GETFD";
3129 break;
3130
3131 case F_SETFD:
3132 p = "SETFD";
3133 break;
3134
3135 case F_GETFL:
3136 p = "GETFL";
3137 break;
3138
3139 case F_SETFL:
3140 p = "SETFL";
3141 break;
3142
3143 case F_GETOWN:
3144 p = "GETOWN";
3145 break;
3146
3147 case F_SETOWN:
3148 p = "SETOWN";
3149 break;
3150
3151 case F_GETLK:
3152 p = "GETLK";
3153 break;
3154
3155 case F_SETLK:
3156 p = "SETLK";
3157 break;
3158
3159 case F_SETLKW:
3160 p = "SETLKW";
3161 break;
3162
3163 case F_PREALLOCATE:
3164 p = "PREALLOCATE";
3165 break;
3166
3167 case F_SETSIZE:
3168 p = "SETSIZE";
3169 break;
3170
3171 case F_RDADVISE:
3172 p = "RDADVISE";
3173 break;
3174
3175 case F_GETPATH:
3176 p = "GETPATH";
3177 break;
3178
3179 case F_FULLFSYNC:
3180 p = "FULLFSYNC";
3181 break;
3182
3183 case F_PATHPKG_CHECK:
3184 p = "PATHPKG_CHECK";
3185 break;
3186
3187 case F_OPENFROM:
3188 p = "OPENFROM";
3189
3190 if (arg1 == 0)
3191 fd = arg2;
3192 break;
3193
3194 case F_UNLINKFROM:
3195 p = "UNLINKFROM";
3196 break;
3197
3198 case F_CHECK_OPENEVT:
3199 p = "CHECK_OPENEVT";
3200 break;
3201
3202 case F_NOCACHE:
3203 if (ti->arg3)
3204 p = "CACHING OFF";
3205 else
3206 p = "CACHING ON";
3207 break;
3208
3209 case F_GLOBAL_NOCACHE:
3210 if (ti->arg3)
3211 p = "CACHING OFF (GLOBAL)";
3212 else
3213 p = "CACHING ON (GLOBAL)";
3214 break;
3215
3216 }
3217 if (p) {
3218 if (fd == -1)
3219 clen += printf(" <%s>", p);
3220 else
3221 clen += printf(" <%s> F=%d", p, fd);
3222 } else
3223 clen += printf(" <CMD=%d>", ti->arg2);
3224
3225 break;
3226 }
3227
3228 case FMT_IOCTL:
3229 {
3230 /*
3231 * fcntl
3232 */
3233 if (arg1)
3234 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3235 else
3236 clen += printf(" F=%-3d", ti->arg1);
3237
3238 clen += printf(" <CMD=0x%x>", ti->arg2);
3239
3240 break;
3241 }
3242
3243 case FMT_SPEC_IOCTL:
3244 {
3245 /*
3246 * fcntl
3247 */
3248 clen += printf(" <DKIOCSYNCHRONIZECACHE> /dev/%s", find_disk_name(arg1));
3249
3250 break;
3251 }
3252
3253 case FMT_SELECT:
3254 /*
3255 * select
3256 */
3257 if (arg1)
3258 clen += printf(" [%3d]", arg1);
3259 else
3260 clen += printf(" S=%-3d", arg2);
3261
3262 break;
3263
3264 case FMT_LSEEK:
3265 case FMT_PREAD:
3266 /*
3267 * pread, pwrite, lseek
3268 */
3269 clen += printf(" F=%-3d", ti->arg1);
3270
3271 if (arg1)
3272 clen += printf("[%3d] ", arg1);
3273 else {
3274 if (format == FMT_PREAD)
3275 clen += printf(" B=0x%-8x ", arg2);
3276 else
3277 clen += printf(" ");
3278 }
3279 if (format == FMT_PREAD)
3280 offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg4);
3281 else
3282 #ifdef __ppc__
3283 offset_reassembled = (((off_t)(unsigned int)(arg2)) << 32) | (unsigned int)(arg3);
3284 #else
3285 offset_reassembled = (((off_t)(unsigned int)(arg3)) << 32) | (unsigned int)(arg2);
3286 #endif
3287 clen += clip_64bit("O=", offset_reassembled);
3288
3289 if (format == FMT_LSEEK) {
3290 char *mode;
3291
3292 if (ti->arg4 == SEEK_SET)
3293 mode = "SEEK_SET";
3294 else if (ti->arg4 == SEEK_CUR)
3295 mode = "SEEK_CUR";
3296 else if (ti->arg4 == SEEK_END)
3297 mode = "SEEK_END";
3298 else
3299 mode = "UNKNOWN";
3300
3301 clen += printf(" <%s>", mode);
3302 }
3303 break;
3304
3305 case FMT_MMAP:
3306 /*
3307 * mmap
3308 */
3309 clen += printf(" F=%-3d ", ti->arg1);
3310
3311 if (arg1)
3312 clen += printf("[%3d] ", arg1);
3313 else {
3314
3315 user_addr = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3);
3316
3317 clen += clip_64bit("A=", user_addr);
3318
3319 offset_reassembled = (((off_t)(unsigned int)(ti->arg6)) << 32) | (unsigned int)(ti->arg7);
3320
3321 clen += clip_64bit("O=", offset_reassembled);
3322
3323 user_size = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg5);
3324
3325 clen += printf("B=0x%-16qx", user_size);
3326
3327 clen += printf(" <");
3328
3329 if (ti->arg8 & PROT_READ)
3330 clen += printf("READ");
3331
3332 if (ti->arg8 & PROT_WRITE)
3333 clen += printf("|WRITE");
3334
3335 if (ti->arg8 & PROT_EXEC)
3336 clen += printf("|EXEC");
3337
3338 clen += printf(">");
3339 }
3340 break;
3341
3342 case FMT_TRUNC:
3343 case FMT_FTRUNC:
3344 /*
3345 * ftruncate, truncate
3346 */
3347 if (format == FMT_FTRUNC)
3348 clen += printf(" F=%-3d", ti->arg1);
3349 else
3350 clen += printf(" ");
3351
3352 if (arg1)
3353 clen += printf("[%3d]", arg1);
3354
3355 #ifdef __ppc__
3356 offset_reassembled = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3);
3357 #else
3358 offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg2);
3359 #endif
3360 clen += clip_64bit(" O=", offset_reassembled);
3361
3362 nopadding = 1;
3363 break;
3364
3365 case FMT_FCHFLAGS:
3366 case FMT_CHFLAGS:
3367 {
3368 /*
3369 * fchflags, chflags
3370 */
3371 int mlen = 0;
3372
3373 if (format == FMT_FCHFLAGS) {
3374 if (arg1)
3375 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3376 else
3377 clen += printf(" F=%-3d", ti->arg1);
3378 } else {
3379 if (arg1)
3380 clen += printf(" [%3d] ", arg1);
3381 }
3382 buf[mlen++] = ' ';
3383 buf[mlen++] = '<';
3384
3385 if (ti->arg2 & UF_NODUMP)
3386 mlen += sprintf(&buf[mlen], "UF_NODUMP | ");
3387 if (ti->arg2 & UF_IMMUTABLE)
3388 mlen += sprintf(&buf[mlen], "UF_IMMUTABLE | ");
3389 if (ti->arg2 & UF_APPEND)
3390 mlen += sprintf(&buf[mlen], "UF_APPEND | ");
3391 if (ti->arg2 & UF_OPAQUE)
3392 mlen += sprintf(&buf[mlen], "UF_OPAQUE | ");
3393 if (ti->arg2 & SF_ARCHIVED)
3394 mlen += sprintf(&buf[mlen], "SF_ARCHIVED | ");
3395 if (ti->arg2 & SF_IMMUTABLE)
3396 mlen += sprintf(&buf[mlen], "SF_IMMUTABLE | ");
3397 if (ti->arg2 & SF_APPEND)
3398 mlen += sprintf(&buf[mlen], "SF_APPEND | ");
3399
3400 if (ti->arg2 == 0)
3401 mlen += sprintf(&buf[mlen], "CLEAR_ALL_FLAGS | ");
3402 else if (ti->arg2 & ~(UF_NODUMP | UF_IMMUTABLE | UF_APPEND | SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND))
3403 mlen += sprintf(&buf[mlen], "UNKNOWN | ");
3404
3405 if (mlen >= 3)
3406 mlen -= 3;
3407
3408 buf[mlen++] = '>';
3409 buf[mlen] = '\0';
3410
3411 if (mlen < 21) {
3412 memset(&buf[mlen], ' ', 21 - mlen);
3413 mlen = 21;
3414 }
3415 clen += printf("%s", buf);
3416
3417 nopadding = 1;
3418 break;
3419 }
3420
3421 case FMT_UMASK:
3422 case FMT_FCHMOD:
3423 case FMT_FCHMOD_EXT:
3424 case FMT_CHMOD:
3425 case FMT_CHMOD_EXT:
3426 {
3427 /*
3428 * fchmod, fchmod_extended, chmod, chmod_extended
3429 */
3430 int mode;
3431
3432 if (format == FMT_FCHMOD || format == FMT_FCHMOD_EXT) {
3433 if (arg1)
3434 clen += printf(" F=%-3d[%3d] ", ti->arg1, arg1);
3435 else
3436 clen += printf(" F=%-3d ", ti->arg1);
3437 } else {
3438 if (arg1)
3439 clen += printf(" [%3d] ", arg1);
3440 else
3441 clen += printf(" ");
3442 }
3443 if (format == FMT_UMASK)
3444 mode = ti->arg1;
3445 else if (format == FMT_FCHMOD || format == FMT_CHMOD)
3446 mode = ti->arg2;
3447 else
3448 mode = ti->arg4;
3449
3450 get_mode_string(mode, &buf[0]);
3451
3452 if (arg1 == 0)
3453 clen += printf("<%s> ", buf);
3454 else
3455 clen += printf("<%s>", buf);
3456 break;
3457 }
3458
3459 case FMT_ACCESS:
3460 {
3461 /*
3462 * access
3463 */
3464 char mode[4];
3465
3466 memset(mode, '_', 4);
3467 mode[4] = '\0';
3468
3469 if (ti->arg2 & R_OK)
3470 mode[0] = 'R';
3471 if (ti->arg2 & W_OK)
3472 mode[1] = 'W';
3473 if (ti->arg2 & X_OK)
3474 mode[2] = 'X';
3475 if (ti->arg2 == F_OK)
3476 mode[3] = 'F';
3477
3478 if (arg1)
3479 clen += printf(" [%3d] (%s) ", arg1, mode);
3480 else
3481 clen += printf(" (%s) ", mode);
3482
3483 nopadding = 1;
3484 break;
3485 }
3486
3487 case FMT_OPEN:
3488 {
3489 /*
3490 * open
3491 */
3492 char mode[7];
3493
3494 memset(mode, '_', 6);
3495 mode[6] = '\0';
3496
3497 if (ti->arg2 & O_RDWR) {
3498 mode[0] = 'R';
3499 mode[1] = 'W';
3500 } else if (ti->arg2 & O_WRONLY)
3501 mode[1] = 'W';
3502 else
3503 mode[0] = 'R';
3504
3505 if (ti->arg2 & O_CREAT)
3506 mode[2] = 'C';
3507
3508 if (ti->arg2 & O_APPEND)
3509 mode[3] = 'A';
3510
3511 if (ti->arg2 & O_TRUNC)
3512 mode[4] = 'T';
3513
3514 if (ti->arg2 & O_EXCL)
3515 mode[5] = 'E';
3516
3517 if (arg1)
3518 clen += printf(" [%3d] (%s) ", arg1, mode);
3519 else
3520 clen += printf(" F=%-3d (%s) ", arg2, mode);
3521
3522 nopadding = 1;
3523 break;
3524 }
3525
3526 case FMT_SOCKET:
3527 {
3528 /*
3529 * socket
3530 *
3531 */
3532 char *domain;
3533 char *type;
3534
3535 switch (ti->arg1) {
3536
3537 case AF_UNIX:
3538 domain = "AF_UNIX";
3539 break;
3540
3541 case AF_INET:
3542 domain = "AF_INET";
3543 break;
3544
3545 case AF_ISO:
3546 domain = "AF_ISO";
3547 break;
3548
3549 case AF_NS:
3550 domain = "AF_NS";
3551 break;
3552
3553 case AF_IMPLINK:
3554 domain = "AF_IMPLINK";
3555 break;
3556
3557 default:
3558 domain = "UNKNOWN";
3559 break;
3560 }
3561
3562 switch (ti->arg2) {
3563
3564 case SOCK_STREAM:
3565 type = "SOCK_STREAM";
3566 break;
3567
3568 case SOCK_DGRAM:
3569 type = "SOCK_DGRAM";
3570 break;
3571
3572 case SOCK_RAW:
3573 type = "SOCK_RAW";
3574 break;
3575
3576 case SOCK_SEQPACKET:
3577 type = "SOCK_SEQPACKET";
3578 break;
3579
3580 case SOCK_RDM:
3581 type = "SOCK_RDM";
3582 break;
3583
3584 default:
3585 type = "UNKNOWN";
3586 break;
3587 }
3588
3589 if (arg1)
3590 clen += printf(" [%3d] <%s, %s, 0x%x>", arg1, domain, type, ti->arg3);
3591 else
3592 clen += printf(" F=%-3d <%s, %s, 0x%x>", arg2, domain, type, ti->arg3);
3593 break;
3594 }
3595
3596 case FMT_AIO_FSYNC:
3597 {
3598 /*
3599 * aio_fsync [errno] AIOCBP OP
3600 */
3601 char *op;
3602
3603 if (ti->arg1 == O_SYNC || ti->arg1 == 0)
3604 op = "AIO_FSYNC";
3605 #if O_DSYNC
3606 else if (ti->arg1 == O_DSYNC)
3607 op = "AIO_DSYNC";
3608 #endif
3609 else
3610 op = "UNKNOWN";
3611
3612 if (arg1)
3613 clen += printf(" [%3d] P=0x%8.8x <%s>", arg1, ti->arg2, op);
3614 else
3615 clen += printf(" P=0x%8.8x <%s>", ti->arg2, op);
3616 break;
3617 }
3618
3619 case FMT_AIO_RETURN:
3620 /*
3621 * aio_return [errno] AIOCBP IOSIZE
3622 */
3623 if (arg1)
3624 clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg1);
3625 else
3626 clen += printf(" P=0x%8.8x B=0x%-8x", ti->arg1, arg2);
3627 break;
3628
3629 case FMT_AIO_SUSPEND:
3630 /*
3631 * aio_suspend [errno] NENTS
3632 */
3633 if (arg1)
3634 clen += printf(" [%3d] N=%d", arg1, ti->arg2);
3635 else
3636 clen += printf(" N=%d", ti->arg2);
3637 break;
3638
3639 case FMT_AIO_CANCEL:
3640 /*
3641 * aio_cancel [errno] FD or AIOCBP (if non-null)
3642 */
3643 if (ti->arg2) {
3644 if (arg1)
3645 clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg2);
3646 else
3647 clen += printf(" P=0x%8.8x", ti->arg2);
3648 } else {
3649 if (arg1)
3650 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3651 else
3652 clen += printf(" F=%-3d", ti->arg1);
3653 }
3654 break;
3655
3656 case FMT_AIO:
3657 /*
3658 * aio_error, aio_read, aio_write [errno] AIOCBP
3659 */
3660 if (arg1)
3661 clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg1);
3662 else
3663 clen += printf(" P=0x%8.8x", ti->arg1);
3664 break;
3665
3666 case FMT_LIO_LISTIO:
3667 {
3668 /*
3669 * lio_listio [errno] NENTS MODE
3670 */
3671 char *op;
3672
3673 if (ti->arg1 == LIO_NOWAIT)
3674 op = "LIO_NOWAIT";
3675 else if (ti->arg1 == LIO_WAIT)
3676 op = "LIO_WAIT";
3677 else
3678 op = "UNKNOWN";
3679
3680 if (arg1)
3681 clen += printf(" [%3d] N=%d <%s>", arg1, ti->arg3, op);
3682 else
3683 clen += printf(" N=%d <%s>", ti->arg3, op);
3684 break;
3685 }
3686
3687 }
3688 }
3689
3690 /*
3691 * Calculate space available to print pathname
3692 */
3693 if (columns > MAXCOLS || wideflag)
3694 clen = columns - (clen + 14 + 20);
3695 else
3696 clen = columns - (clen + 14 + 12);
3697
3698 if (class != FILEMGR_CLASS && !nopadding)
3699 clen -= 3;
3700
3701 if (framework_name)
3702 len = sprintf(&buf[0], " %s %s ", framework_type, framework_name);
3703 else if (*pathname != '\0')
3704 len = sprintf(&buf[0], " %s ", pathname);
3705 else
3706 len = 0;
3707
3708 if (clen > len) {
3709 /*
3710 * Add null padding if column length
3711 * is wider than the pathname length.
3712 */
3713 memset(&buf[len], ' ', clen - len);
3714 buf[clen] = '\0';
3715
3716 pathname = buf;
3717
3718 } else if (clen == len) {
3719 pathname = buf;
3720
3721 } else if ((clen > 0) && (clen < len)) {
3722 /*
3723 * This prints the tail end of the pathname
3724 */
3725 buf[len-clen] = ' ';
3726
3727 pathname = &buf[len - clen];
3728
3729 } else {
3730 pathname = "";
3731 }
3732
3733 /*
3734 * fudge some additional system call overhead
3735 * that currently isn't tracked... this also
3736 * insures that we see a minimum of 1 us for
3737 * an elapsed time
3738 */
3739 usecs = (unsigned long)(((now - stime) + (divisor-1)) / divisor);
3740 secs = usecs / 1000000;
3741 usecs -= secs * 1000000;
3742
3743 if (class != FILEMGR_CLASS && !nopadding)
3744 p1 = " ";
3745 else
3746 p1 = "";
3747
3748 if (waited)
3749 p2 = " W";
3750 else
3751 p2 = " ";
3752
3753 if (columns > MAXCOLS || wideflag)
3754 printf("%s%s %3ld.%06ld%s %-20.20s\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name);
3755 else
3756 printf("%s%s %3ld.%06ld%s %-12.12s\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name);
3757 }
3758
3759 int
3760 quit(s)
3761 char *s;
3762 {
3763 if (trace_enabled)
3764 set_enable(0);
3765
3766 /*
3767 * This flag is turned off when calling
3768 * quit() due to a set_remove() failure.
3769 */
3770 if (set_remove_flag)
3771 set_remove();
3772
3773 fprintf(stderr, "fs_usage: ");
3774 if (s)
3775 fprintf(stderr, "%s", s);
3776
3777 exit(1);
3778 }
3779
3780
3781 void getdivisor()
3782 {
3783 struct mach_timebase_info mti;
3784
3785 mach_timebase_info(&mti);
3786
3787 divisor = ((double)mti.denom / (double)mti.numer) * 1000;
3788 }
3789
3790
3791 void read_command_map()
3792 {
3793 size_t size;
3794 int i;
3795 int prev_total_threads;
3796 int mib[6];
3797
3798 if (mapptr) {
3799 free(mapptr);
3800 mapptr = 0;
3801 }
3802
3803 prev_total_threads = total_threads;
3804
3805 if (!RAW_flag) {
3806
3807 total_threads = bufinfo.nkdthreads;
3808 size = bufinfo.nkdthreads * sizeof(kd_threadmap);
3809
3810 if (size)
3811 {
3812 if ((mapptr = (kd_threadmap *) malloc(size)))
3813 {
3814 bzero (mapptr, size);
3815
3816 /* Now read the threadmap */
3817 mib[0] = CTL_KERN;
3818 mib[1] = KERN_KDEBUG;
3819 mib[2] = KERN_KDTHRMAP;
3820 mib[3] = 0;
3821 mib[4] = 0;
3822 mib[5] = 0; /* no flags */
3823 if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0)
3824 {
3825 /* This is not fatal -- just means I cant map command strings */
3826 free(mapptr);
3827 mapptr = 0;
3828 }
3829 }
3830 }
3831 } else {
3832 uint32_t count_of_names;
3833
3834 RAW_fd = open(RAW_file, O_RDONLY);
3835
3836 if (RAW_fd < 0) {
3837 perror("Can't open RAW file");
3838 exit(1);
3839 }
3840 if (read(RAW_fd, &count_of_names, sizeof(uint32_t)) != sizeof(uint32_t)) {
3841 perror("read of RAW file failed");
3842 exit(2);
3843 }
3844 total_threads = count_of_names;
3845 size = count_of_names * sizeof(kd_threadmap);
3846
3847 if (size)
3848 {
3849 if ((mapptr = (kd_threadmap *) malloc(size)))
3850 {
3851 bzero (mapptr, size);
3852
3853 if (read(RAW_fd, mapptr, size) != size) {
3854
3855 free(mapptr);
3856 mapptr = 0;
3857 }
3858 }
3859 }
3860 }
3861 if (mapptr && (filter_mode & (NETWORK_FILTER | FILESYS_FILTER)))
3862 {
3863 if (fdmapptr)
3864 {
3865 /* We accept the fact that we lose file descriptor state if the
3866 kd_buffer wraps */
3867 for (i = 0; i < prev_total_threads; i++)
3868 {
3869 if (fdmapptr[i].fd_setptr)
3870 free (fdmapptr[i].fd_setptr);
3871 }
3872 free(fdmapptr);
3873 fdmapptr = 0;
3874 }
3875
3876 size = total_threads * sizeof(fd_threadmap);
3877 if ((fdmapptr = (fd_threadmap *) malloc(size)))
3878 {
3879 bzero (fdmapptr, size);
3880 /* reinitialize file descriptor state map */
3881 for (i = 0; i < total_threads; i++)
3882 {
3883 fdmapptr[i].fd_thread = mapptr[i].thread;
3884 fdmapptr[i].fd_valid = mapptr[i].valid;
3885 fdmapptr[i].fd_setsize = 0;
3886 fdmapptr[i].fd_setptr = 0;
3887 }
3888 }
3889 }
3890
3891 /* Resolve any LaunchCFMApp command names */
3892 if (mapptr && arguments)
3893 {
3894 for (i=0; i < total_threads; i++)
3895 {
3896 int pid;
3897
3898 pid = mapptr[i].valid;
3899
3900 if (pid == 0 || pid == 1)
3901 continue;
3902 else if (!strncmp(mapptr[i].command,"LaunchCFMA", 10))
3903 {
3904 (void)get_real_command_name(pid, mapptr[i].command, sizeof(mapptr[i].command));
3905 }
3906 }
3907 }
3908 }
3909
3910
3911 void create_map_entry(uintptr_t thread, int pid, char *command)
3912 {
3913 int i, n;
3914 kd_threadmap *map;
3915 fd_threadmap *fdmap = 0;
3916
3917 if (!mapptr)
3918 return;
3919
3920 for (i = 0, map = 0; !map && i < total_threads; i++)
3921 {
3922 if (mapptr[i].thread == thread )
3923 {
3924 map = &mapptr[i]; /* Reuse this entry, the thread has been
3925 * reassigned */
3926 if ((filter_mode & (NETWORK_FILTER | FILESYS_FILTER)) && fdmapptr)
3927 {
3928 fdmap = &fdmapptr[i];
3929 if (fdmap->fd_thread != thread) /* This shouldn't happen */
3930 fdmap = (fd_threadmap *)0;
3931 }
3932 }
3933 }
3934
3935 if (!map) /* look for invalid entries that I can reuse*/
3936 {
3937 for (i = 0, map = 0; !map && i < total_threads; i++)
3938 {
3939 if (mapptr[i].valid == 0 )
3940 map = &mapptr[i]; /* Reuse this invalid entry */
3941 if ((filter_mode & (NETWORK_FILTER | FILESYS_FILTER)) && fdmapptr)
3942 {
3943 fdmap = &fdmapptr[i];
3944 }
3945 }
3946 }
3947
3948 if (!map)
3949 {
3950 /*
3951 * If reach here, then this is a new thread and
3952 * there are no invalid entries to reuse
3953 * Double the size of the thread map table.
3954 */
3955 n = total_threads * 2;
3956 mapptr = (kd_threadmap *) realloc(mapptr, n * sizeof(kd_threadmap));
3957 bzero(&mapptr[total_threads], total_threads*sizeof(kd_threadmap));
3958 map = &mapptr[total_threads];
3959
3960 if ((filter_mode & (NETWORK_FILTER | FILESYS_FILTER)) && fdmapptr)
3961 {
3962 fdmapptr = (fd_threadmap *)realloc(fdmapptr, n * sizeof(fd_threadmap));
3963 bzero(&fdmapptr[total_threads], total_threads*sizeof(fd_threadmap));
3964 fdmap = &fdmapptr[total_threads];
3965 }
3966
3967 total_threads = n;
3968 }
3969
3970 map->valid = 1;
3971 map->thread = thread;
3972 /*
3973 * The trace entry that returns the command name will hold
3974 * at most, MAXCOMLEN chars, and in that case, is not
3975 * guaranteed to be null terminated.
3976 */
3977 (void)strncpy (map->command, command, MAXCOMLEN);
3978 map->command[MAXCOMLEN] = '\0';
3979
3980 if (fdmap)
3981 {
3982 fdmap->fd_valid = 1;
3983 fdmap->fd_thread = thread;
3984 if (fdmap->fd_setptr)
3985 {
3986 free(fdmap->fd_setptr);
3987 fdmap->fd_setptr = (unsigned long *)0;
3988 }
3989 fdmap->fd_setsize = 0;
3990 }
3991
3992 if (pid == 0 || pid == 1)
3993 return;
3994 else if (!strncmp(map->command, "LaunchCFMA", 10))
3995 (void)get_real_command_name(pid, map->command, sizeof(map->command));
3996 }
3997
3998
3999 kd_threadmap *find_thread_map(uintptr_t thread)
4000 {
4001 int i;
4002 kd_threadmap *map;
4003
4004 if (!mapptr)
4005 return((kd_threadmap *)0);
4006
4007 for (i = 0; i < total_threads; i++)
4008 {
4009 map = &mapptr[i];
4010 if (map->valid && (map->thread == thread))
4011 {
4012 return(map);
4013 }
4014 }
4015 return ((kd_threadmap *)0);
4016 }
4017
4018 fd_threadmap *find_fd_thread_map(uintptr_t thread)
4019 {
4020 int i;
4021 fd_threadmap *fdmap = 0;
4022
4023 if (!fdmapptr)
4024 return((fd_threadmap *)0);
4025
4026 for (i = 0; i < total_threads; i++)
4027 {
4028 fdmap = &fdmapptr[i];
4029 if (fdmap->fd_valid && (fdmap->fd_thread == thread))
4030 {
4031 return(fdmap);
4032 }
4033 }
4034 return ((fd_threadmap *)0);
4035 }
4036
4037
4038 void
4039 kill_thread_map(uintptr_t thread)
4040 {
4041 kd_threadmap *map;
4042 fd_threadmap *fdmap;
4043
4044 if (thread == last_thread)
4045 map_is_the_same = 0;
4046
4047 if ((map = find_thread_map(thread))) {
4048 map->valid = 0;
4049 map->thread = 0;
4050 map->command[0] = '\0';
4051 }
4052
4053 if ((filter_mode & (NETWORK_FILTER | FILESYS_FILTER)))
4054 {
4055 if ((fdmap = find_fd_thread_map(thread)))
4056 {
4057 fdmap->fd_valid = 0;
4058 fdmap->fd_thread = 0;
4059 if (fdmap->fd_setptr)
4060 {
4061 free (fdmap->fd_setptr);
4062 fdmap->fd_setptr = (unsigned long *)0;
4063 }
4064 fdmap->fd_setsize = 0;
4065 }
4066 }
4067 }
4068
4069 void
4070 argtopid(str)
4071 char *str;
4072 {
4073 char *cp;
4074 int ret;
4075 int i;
4076
4077 ret = (int)strtol(str, &cp, 10);
4078 if (cp == str || *cp) {
4079 /* Assume this is a command string and find matching pids */
4080 if (!kp_buffer)
4081 find_proc_names();
4082
4083 for (i=0; i < kp_nentries && num_of_pids < (MAX_PIDS - 1); i++) {
4084 if(kp_buffer[i].kp_proc.p_stat == 0)
4085 continue;
4086 else {
4087 if(!strncmp(str, kp_buffer[i].kp_proc.p_comm,
4088 sizeof(kp_buffer[i].kp_proc.p_comm) -1))
4089 pids[num_of_pids++] = kp_buffer[i].kp_proc.p_pid;
4090 }
4091 }
4092 }
4093 else if (num_of_pids < (MAX_PIDS - 1))
4094 pids[num_of_pids++] = ret;
4095
4096 return;
4097 }
4098
4099
4100
4101 void
4102 lookup_name(uint64_t user_addr, char **type, char **name)
4103 {
4104 int i;
4105 int start, last;
4106
4107 *name = NULL;
4108 *type = NULL;
4109
4110 if (numFrameworks) {
4111
4112 if ((user_addr >= framework32.b_address && user_addr < framework32.e_address) ||
4113 (user_addr >= framework64.b_address && user_addr < framework64.e_address)) {
4114
4115 start = 0;
4116 last = numFrameworks;
4117
4118 for (i = numFrameworks / 2; start < last; i = start + ((last - start) / 2)) {
4119 if (user_addr > frameworkInfo[i].e_address) {
4120 start = i+1;
4121 } else {
4122 last = i;
4123 }
4124 }
4125 if (start < numFrameworks &&
4126 user_addr >= frameworkInfo[start].b_address && user_addr < frameworkInfo[start].e_address) {
4127 *type = frameworkType[frameworkInfo[start].r_type];
4128 *name = frameworkInfo[start].name;
4129 }
4130 }
4131 }
4132 }
4133
4134
4135 /*
4136 * Comparison routines for sorting
4137 */
4138 static int compareFrameworkAddress(const void *aa, const void *bb)
4139 {
4140 LibraryInfo *a = (LibraryInfo *)aa;
4141 LibraryInfo *b = (LibraryInfo *)bb;
4142
4143 if (a->b_address < b->b_address) return -1;
4144 if (a->b_address == b->b_address) return 0;
4145 return 1;
4146 }
4147
4148
4149 int scanline(char *inputstring, char **argv, int maxtokens)
4150 {
4151 int n = 0;
4152 char **ap = argv, *p, *val;
4153
4154 for (p = inputstring; n < maxtokens && p != NULL; )
4155 {
4156 while ((val = strsep(&p, " \t")) != NULL && *val == '\0');
4157 *ap++ = val;
4158 n++;
4159 }
4160 *ap = 0;
4161 return n;
4162 }
4163
4164
4165 int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name)
4166 {
4167 uint64_t b_address, e_address;
4168 char buf[1024];
4169 char *fnp;
4170 FILE *fd;
4171 char frameworkName[256];
4172 char *tokens[64];
4173 int ntokens;
4174 int type;
4175 int linkedit_found = 0;
4176 char *substring, *ptr;
4177
4178 bzero(buf, sizeof(buf));
4179 bzero(tokens, sizeof(tokens));
4180
4181 lr->b_address = 0;
4182 lr->e_address = 0;
4183
4184 if ((fd = fopen(path, "r")) == 0)
4185 {
4186 return 0;
4187 }
4188 while (fgets(buf, 1023, fd)) {
4189 if (strncmp(buf, "mapping", 7))
4190 break;
4191 }
4192 buf[strlen(buf)-1] = 0;
4193
4194 frameworkName[0] = 0;
4195
4196 for (;;) {
4197 /*
4198 * Extract lib name from path name
4199 */
4200 if ((substring = strrchr(buf, '.')))
4201 {
4202 /*
4203 * There is a ".": name is whatever is between the "/" around the "."
4204 */
4205 while ( *substring != '/') { /* find "/" before "." */
4206 substring--;
4207 }
4208 substring++;
4209 strncpy(frameworkName, substring, 256); /* copy path from "/" */
4210 frameworkName[255] = 0;
4211 substring = frameworkName;
4212
4213 while ( *substring != '/' && *substring) /* find "/" after "." and stop string there */
4214 substring++;
4215 *substring = 0;
4216 }
4217 else
4218 {
4219 /*
4220 * No ".": take segment after last "/"
4221 */
4222 ptr = buf;
4223 substring = ptr;
4224
4225 while (*ptr)
4226 {
4227 if (*ptr == '/')
4228 substring = ptr + 1;
4229 ptr++;
4230 }
4231 strncpy(frameworkName, substring, 256);
4232 frameworkName[255] = 0;
4233 }
4234 fnp = (char *)malloc(strlen(frameworkName) + 1);
4235 strcpy(fnp, frameworkName);
4236
4237 while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2))
4238 {
4239 /*
4240 * Get rid of EOL
4241 */
4242 buf[strlen(buf)-1] = 0;
4243
4244 ntokens = scanline(buf, tokens, 64);
4245
4246 if (ntokens < 4)
4247 continue;
4248
4249 if (strncmp(tokens[0], "__TEXT", 6) == 0)
4250 type = TEXT_R;
4251 else if (strncmp(tokens[0], "__DATA", 6) == 0)
4252 type = DATA_R;
4253 else if (strncmp(tokens[0], "__OBJC", 6) == 0)
4254 type = OBJC_R;
4255 else if (strncmp(tokens[0], "__IMPORT", 8) == 0)
4256 type = IMPORT_R;
4257 else if (strncmp(tokens[0], "__UNICODE", 9) == 0)
4258 type = UNICODE_R;
4259 else if (strncmp(tokens[0], "__IMAGE", 7) == 0)
4260 type = IMAGE_R;
4261 else if (strncmp(tokens[0], "__LINKEDIT", 10) == 0)
4262 type = LINKEDIT_R;
4263 else
4264 type = -1;
4265
4266 if (type == LINKEDIT_R && linkedit_found)
4267 break;
4268
4269 if (type != -1) {
4270 b_address = strtoull(tokens[1], 0, 16);
4271 e_address = strtoull(tokens[3], 0, 16);
4272
4273 frameworkInfo[numFrameworks].b_address = b_address;
4274 frameworkInfo[numFrameworks].e_address = e_address;
4275 frameworkInfo[numFrameworks].r_type = type;
4276
4277 if (type == LINKEDIT_R) {
4278 frameworkInfo[numFrameworks].name = linkedit_name;
4279 linkedit_found = 1;
4280 } else
4281 frameworkInfo[numFrameworks].name = fnp;
4282 #if 0
4283 printf("%s(%d): %qx-%qx\n", frameworkInfo[numFrameworks].name, type, b_address, e_address);
4284 #endif
4285 if (lr->b_address == 0 || b_address < lr->b_address)
4286 lr->b_address = b_address;
4287
4288 if (lr->e_address == 0 || e_address > lr->e_address)
4289 lr->e_address = e_address;
4290
4291 numFrameworks++;
4292 }
4293 if (type == LINKEDIT_R)
4294 break;
4295 }
4296 if (fgets(buf, 1023, fd) == 0)
4297 break;
4298
4299 buf[strlen(buf)-1] = 0;
4300 }
4301 fclose(fd);
4302
4303 #if 0
4304 printf("%s range, %qx-%qx\n", path, lr->b_address, lr->e_address);
4305 #endif
4306 return 1;
4307 }
4308
4309
4310 void
4311 SortFrameworkAddresses()
4312 {
4313
4314 frameworkInfo[numFrameworks].b_address = frameworkInfo[numFrameworks - 1].b_address + 0x800000;
4315 frameworkInfo[numFrameworks].e_address = frameworkInfo[numFrameworks].b_address;
4316 frameworkInfo[numFrameworks].name = (char *)0;
4317
4318 qsort(frameworkInfo, numFrameworks, sizeof(LibraryInfo), compareFrameworkAddress);
4319 }
4320
4321
4322 struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, uintptr_t thread, double curtime)
4323 {
4324 register struct diskio *dio;
4325 register kd_threadmap *map;
4326
4327 if ((dio = free_diskios))
4328 free_diskios = dio->next;
4329 else {
4330 if ((dio = (struct diskio *)malloc(sizeof(struct diskio))) == NULL)
4331 return (NULL);
4332 }
4333 dio->prev = NULL;
4334
4335 dio->type = type;
4336 dio->bp = bp;
4337 dio->dev = dev;
4338 dio->blkno = blkno;
4339 dio->iosize = io_size;
4340 dio->issued_time = curtime;
4341 dio->issuing_thread = thread;
4342
4343 if ((map = find_thread_map(thread)))
4344 {
4345 strncpy(dio->issuing_command, map->command, MAXCOMLEN);
4346 dio->issuing_command[MAXCOMLEN-1] = '\0';
4347 }
4348 else
4349 strcpy(dio->issuing_command, "");
4350
4351 dio->next = busy_diskios;
4352 if (dio->next)
4353 dio->next->prev = dio;
4354 busy_diskios = dio;
4355
4356 return (dio);
4357 }
4358
4359
4360 struct diskio *complete_diskio(int bp, int io_errno, int resid, uintptr_t thread, double curtime)
4361 {
4362 register struct diskio *dio;
4363
4364 for (dio = busy_diskios; dio; dio = dio->next) {
4365 if (dio->bp == bp) {
4366
4367 if (dio == busy_diskios) {
4368 if ((busy_diskios = dio->next))
4369 dio->next->prev = NULL;
4370 } else {
4371 if (dio->next)
4372 dio->next->prev = dio->prev;
4373 dio->prev->next = dio->next;
4374 }
4375 dio->iosize -= resid;
4376 dio->io_errno = io_errno;
4377 dio->completed_time = curtime;
4378 dio->completion_thread = thread;
4379
4380 return (dio);
4381 }
4382 }
4383 return ((struct diskio *)0);
4384 }
4385
4386
4387 void free_diskio(struct diskio *dio)
4388 {
4389 dio->next = free_diskios;
4390 free_diskios = dio;
4391 }
4392
4393
4394 void print_diskio(struct diskio *dio)
4395 {
4396 register char *p;
4397
4398 switch (dio->type) {
4399
4400 case P_RdMeta:
4401 p = " RdMeta";
4402 break;
4403 case P_WrMeta:
4404 p = " WrMeta";
4405 break;
4406 case P_RdData:
4407 p = " RdData";
4408 break;
4409 case P_WrData:
4410 p = " WrData";
4411 break;
4412 case P_PgIn:
4413 p = " PgIn";
4414 break;
4415 case P_PgOut:
4416 p = " PgOut";
4417 break;
4418 case P_RdMetaAsync:
4419 p = " RdMeta[async]";
4420 break;
4421 case P_WrMetaAsync:
4422 p = " WrMeta[async]";
4423 break;
4424 case P_RdDataAsync:
4425 p = " RdData[async]";
4426 break;
4427 case P_WrDataAsync:
4428 p = " WrData[async]";
4429 break;
4430 case P_PgInAsync:
4431 p = " PgIn[async]";
4432 break;
4433 case P_PgOutAsync:
4434 p = " PgOut[async]";
4435 break;
4436 default:
4437 p = " ";
4438 break;
4439 }
4440 if (check_filter_mode(NULL, dio->type, 0, 0, p))
4441 format_print(NULL, p, dio->issuing_thread, dio->type, 0, 0, 0, 0, FMT_DISKIO, dio->completed_time, dio->issued_time, 1, "", dio);
4442 }
4443
4444
4445 void cache_disk_names()
4446 {
4447 struct stat st;
4448 DIR *dirp = NULL;
4449 struct dirent *dir;
4450 struct diskrec *dnp;
4451
4452
4453 if ((dirp = opendir("/dev")) == NULL)
4454 return;
4455
4456 while ((dir = readdir(dirp)) != NULL) {
4457 char nbuf[MAXPATHLEN];
4458
4459 if (dir->d_namlen < 5 || strncmp("disk", dir->d_name, 4))
4460 continue;
4461 snprintf(nbuf, MAXPATHLEN, "%s/%s", "/dev", dir->d_name);
4462
4463 if (stat(nbuf, &st) < 0)
4464 continue;
4465
4466 if ((dnp = (struct diskrec *)malloc(sizeof(struct diskrec))) == NULL)
4467 continue;
4468
4469 if ((dnp->diskname = (char *)malloc(dir->d_namlen + 1)) == NULL) {
4470 free(dnp);
4471 continue;
4472 }
4473 strncpy(dnp->diskname, dir->d_name, dir->d_namlen);
4474 dnp->diskname[dir->d_namlen] = 0;
4475 dnp->dev = st.st_rdev;
4476
4477 dnp->next = disk_list;
4478 disk_list = dnp;
4479 }
4480 (void) closedir(dirp);
4481 }
4482
4483
4484 void recache_disk_names()
4485 {
4486 struct diskrec *dnp, *next_dnp;
4487
4488 for (dnp = disk_list; dnp; dnp = next_dnp) {
4489 next_dnp = dnp->next;
4490
4491 free(dnp->diskname);
4492 free(dnp);
4493 }
4494 disk_list = NULL;
4495
4496 cache_disk_names();
4497 }
4498
4499
4500 char *find_disk_name(int dev)
4501 {
4502 struct diskrec *dnp;
4503 int i;
4504
4505 if (dev == NFS_DEV)
4506 return ("NFS");
4507
4508 for (i = 0; i < 2; i++) {
4509 for (dnp = disk_list; dnp; dnp = dnp->next) {
4510 if (dnp->dev == dev)
4511 return (dnp->diskname);
4512 }
4513 recache_disk_names();
4514 }
4515 return ("NOTFOUND");
4516 }
4517
4518 void
4519 fs_usage_fd_set(thread, fd)
4520 unsigned int thread;
4521 unsigned int fd;
4522 {
4523 int n;
4524 fd_threadmap *fdmap;
4525
4526 if(!(fdmap = find_fd_thread_map(thread)))
4527 return;
4528
4529 /* If the map is not allocated, then now is the time */
4530 if (fdmap->fd_setptr == (unsigned long *)0)
4531 {
4532 fdmap->fd_setptr = (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE));
4533 if (fdmap->fd_setptr)
4534 {
4535 fdmap->fd_setsize = FS_USAGE_FD_SETSIZE;
4536 bzero(fdmap->fd_setptr,(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE)));
4537 }
4538 else
4539 return;
4540 }
4541
4542 /* If the map is not big enough, then reallocate it */
4543 while (fdmap->fd_setsize <= fd)
4544 {
4545 fprintf(stderr, "reallocating bitmap for threadid %d, fd = %d, setsize = %d\n",
4546 thread, fd, fdmap->fd_setsize);
4547 n = fdmap->fd_setsize * 2;
4548 fdmap->fd_setptr = (unsigned long *)realloc(fdmap->fd_setptr, (FS_USAGE_NFDBYTES(n)));
4549 bzero(&fdmap->fd_setptr[(fdmap->fd_setsize/FS_USAGE_NFDBITS)], (FS_USAGE_NFDBYTES(fdmap->fd_setsize)));
4550 fdmap->fd_setsize = n;
4551 }
4552
4553 /* set the bit */
4554 fdmap->fd_setptr[fd/FS_USAGE_NFDBITS] |= (1 << ((fd) % FS_USAGE_NFDBITS));
4555
4556 return;
4557 }
4558
4559 /*
4560 Return values:
4561 0 : File Descriptor bit is not set
4562 1 : File Descriptor bit is set
4563 */
4564
4565 int
4566 fs_usage_fd_isset(thread, fd)
4567 unsigned int thread;
4568 unsigned int fd;
4569 {
4570 int ret = 0;
4571 fd_threadmap *fdmap;
4572
4573 if(!(fdmap = find_fd_thread_map(thread)))
4574 return(ret);
4575
4576 if (fdmap->fd_setptr == (unsigned long *)0)
4577 return (ret);
4578
4579 if (fd < fdmap->fd_setsize)
4580 ret = fdmap->fd_setptr[fd/FS_USAGE_NFDBITS] & (1 << (fd % FS_USAGE_NFDBITS));
4581
4582 return (ret);
4583 }
4584
4585 void
4586 fs_usage_fd_clear(thread, fd)
4587 unsigned int thread;
4588 unsigned int fd;
4589 {
4590 fd_threadmap *map;
4591
4592 if (!(map = find_fd_thread_map(thread)))
4593 return;
4594
4595 if (map->fd_setptr == (unsigned long *)0)
4596 return;
4597
4598 /* clear the bit */
4599 if (fd < map->fd_setsize)
4600 map->fd_setptr[fd/FS_USAGE_NFDBITS] &= ~(1 << (fd % FS_USAGE_NFDBITS));
4601
4602 return;
4603 }
4604
4605
4606 /*
4607 * ret = 1 means print the entry
4608 * ret = 0 means don't print the entry
4609 */
4610 int
4611 check_filter_mode(struct th_info * ti, int type, int error, int retval, char *sc_name)
4612 {
4613 int ret = 0;
4614 int network_fd_isset = 0;
4615 unsigned int fd;
4616
4617 if (filter_mode == DEFAULT_DO_NOT_FILTER)
4618 return(1);
4619
4620 if (sc_name[0] == 'C' && !strcmp (sc_name, "CACHE_HIT")) {
4621 if (filter_mode & CACHEHIT_FILTER)
4622 /* Do not print if cachehit filter is set */
4623 return(0);
4624 return(1);
4625 }
4626
4627 if (filter_mode & EXEC_FILTER)
4628 {
4629 if (type == BSC_execve)
4630 return(1);
4631 return(0);
4632 }
4633
4634 if (filter_mode & PATHNAME_FILTER)
4635 {
4636 if (ti && ti->pathname[0])
4637 return(1);
4638 if (type == BSC_close || type == BSC_close_nocancel)
4639 return(1);
4640 return(0);
4641 }
4642
4643 if ( !(filter_mode & (FILESYS_FILTER | NETWORK_FILTER)))
4644 return(1);
4645
4646
4647 if (ti == (struct th_info *)0)
4648 {
4649 if (filter_mode & FILESYS_FILTER)
4650 ret = 1;
4651 else
4652 ret = 0;
4653 return(ret);
4654 }
4655
4656 switch (type) {
4657 case BSC_close:
4658 case BSC_close_nocancel:
4659 fd = ti->arg1;
4660 network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
4661 if (error == 0)
4662 {
4663 fs_usage_fd_clear(ti->thread,fd);
4664 }
4665
4666 if (network_fd_isset)
4667 {
4668 if (filter_mode & NETWORK_FILTER)
4669 ret = 1;
4670 }
4671 else if (filter_mode & FILESYS_FILTER)
4672 ret = 1;
4673 break;
4674 case BSC_read:
4675 case BSC_write:
4676 case BSC_read_nocancel:
4677 case BSC_write_nocancel:
4678 /* we don't care about error in this case */
4679 fd = ti->arg1;
4680 network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
4681 if (network_fd_isset)
4682 {
4683 if (filter_mode & NETWORK_FILTER)
4684 ret = 1;
4685 }
4686 else if (filter_mode & FILESYS_FILTER)
4687 ret = 1;
4688 break;
4689 case BSC_accept:
4690 case BSC_accept_nocancel:
4691 case BSC_socket:
4692 fd = retval;
4693 if (error == 0)
4694 fs_usage_fd_set(ti->thread, fd);
4695 if (filter_mode & NETWORK_FILTER)
4696 ret = 1;
4697 break;
4698 case BSC_recvfrom:
4699 case BSC_sendto:
4700 case BSC_recvmsg:
4701 case BSC_sendmsg:
4702 case BSC_connect:
4703 case BSC_bind:
4704 case BSC_listen:
4705 case BSC_sendto_nocancel:
4706 case BSC_recvfrom_nocancel:
4707 case BSC_recvmsg_nocancel:
4708 case BSC_sendmsg_nocancel:
4709 case BSC_connect_nocancel:
4710 fd = ti->arg1;
4711 if (error == 0)
4712 fs_usage_fd_set(ti->thread, fd);
4713 if (filter_mode & NETWORK_FILTER)
4714 ret = 1;
4715 break;
4716 case BSC_select:
4717 case BSC_select_nocancel:
4718 case BSC_socketpair:
4719 /* Cannot determine info about file descriptors */
4720 if (filter_mode & NETWORK_FILTER)
4721 ret = 1;
4722 break;
4723 case BSC_dup:
4724 case BSC_dup2:
4725 ret=0; /* We track these cases for fd state only */
4726 fd = ti->arg1; /* oldd */
4727 network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
4728 if (error == 0 && network_fd_isset)
4729 {
4730 /* then we are duping a socket descriptor */
4731 fd = retval; /* the new fd */
4732 fs_usage_fd_set(ti->thread, fd);
4733 }
4734 break;
4735
4736 default:
4737 if (filter_mode & FILESYS_FILTER)
4738 ret = 1;
4739 break;
4740 }
4741
4742 return(ret);
4743 }
4744
4745 /*
4746 * Allocate a buffer that is large enough to hold the maximum arguments
4747 * to execve(). This is used when getting the arguments to programs
4748 * when we see LaunchCFMApps. If this fails, it is not fatal, we will
4749 * simply not resolve the command name.
4750 */
4751
4752 void
4753 init_arguments_buffer()
4754 {
4755
4756 int mib[2];
4757 size_t size;
4758
4759 mib[0] = CTL_KERN;
4760 mib[1] = KERN_ARGMAX;
4761 size = sizeof(argmax);
4762 if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
4763 return;
4764
4765 #if 1
4766 /* Hack to avoid kernel bug. */
4767 if (argmax > 8192) {
4768 argmax = 8192;
4769 }
4770 #endif
4771
4772 arguments = (char *)malloc(argmax);
4773
4774 return;
4775 }
4776
4777
4778 int
4779 get_real_command_name(int pid, char *cbuf, int csize)
4780 {
4781 /*
4782 * Get command and arguments.
4783 */
4784 char *cp;
4785 int mib[4];
4786 char *command_beg, *command, *command_end;
4787
4788 if (cbuf == NULL) {
4789 return(0);
4790 }
4791
4792 if (arguments)
4793 bzero(arguments, argmax);
4794 else
4795 return(0);
4796
4797 /*
4798 * A sysctl() is made to find out the full path that the command
4799 * was called with.
4800 */
4801 mib[0] = CTL_KERN;
4802 mib[1] = KERN_PROCARGS2;
4803 mib[2] = pid;
4804 mib[3] = 0;
4805
4806 if (sysctl(mib, 3, arguments, (size_t *)&argmax, NULL, 0) < 0) {
4807 return(0);
4808 }
4809
4810 /* Skip the saved exec_path. */
4811 for (cp = arguments; cp < &arguments[argmax]; cp++) {
4812 if (*cp == '\0') {
4813 /* End of exec_path reached. */
4814 break;
4815 }
4816 }
4817 if (cp == &arguments[argmax]) {
4818 return(0);
4819 }
4820
4821 /* Skip trailing '\0' characters. */
4822 for (; cp < &arguments[argmax]; cp++) {
4823 if (*cp != '\0') {
4824 /* Beginning of first argument reached. */
4825 break;
4826 }
4827 }
4828 if (cp == &arguments[argmax]) {
4829 return(0);
4830 }
4831 command_beg = cp;
4832
4833 /*
4834 * Make sure that the command is '\0'-terminated. This protects
4835 * against malicious programs; under normal operation this never
4836 * ends up being a problem..
4837 */
4838 for (; cp < &arguments[argmax]; cp++) {
4839 if (*cp == '\0') {
4840 /* End of first argument reached. */
4841 break;
4842 }
4843 }
4844 if (cp == &arguments[argmax]) {
4845 return(0);
4846 }
4847 command_end = command = cp;
4848
4849 /* Get the basename of command. */
4850 for (command--; command >= command_beg; command--) {
4851 if (*command == '/') {
4852 command++;
4853 break;
4854 }
4855 }
4856
4857 (void) strncpy(cbuf, (char *)command, csize);
4858 cbuf[csize-1] = '\0';
4859
4860 return(1);
4861 }