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