2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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
22 * @APPLE_LICENSE_HEADER_END@
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
44 #include <sys/types.h>
45 #include <sys/param.h>
47 #include <sys/ioctl.h>
48 #include <sys/socket.h>
50 #include <sys/sysctl.h>
54 #ifndef KERNEL_PRIVATE
55 #define KERNEL_PRIVATE
56 #include <sys/kdebug.h>
59 #include <sys/kdebug.h>
60 #endif /*KERNEL_PRIVATE*/
62 #import <mach/clock_types.h>
63 #import <mach/mach_time.h>
67 #define F_OPENFROM 56 /* SPI: open a file relative to fd (must be a dir) */
68 #define F_UNLINKFROM 57 /* SPI: open a file relative to fd (must be a dir) */
69 #define F_CHECK_OPENEVT 58 /* SPI: if a process is marked OPENEVT, or in O_EVTONLY on opens of this vnode */
80 #define RAW_VERSION0 0x55aa0000
81 #define RAW_VERSION1 0x55aa0101
87 typedef struct LibraryRange
{
92 LibraryRange framework32
= {0,0};
93 LibraryRange framework64
= {0,0};
94 LibraryRange framework64h
= {0,0};
106 char *frameworkType
[] = {
117 typedef struct LibraryInfo
{
124 LibraryInfo frameworkInfo
[MAXINDEX
];
125 int numFrameworks
= 0;
129 * MAXCOLS controls when extra data kicks in.
130 * MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path.
131 * If NUMPARMS changes to match the kernel, it will automatically
132 * get reflected in the -w mode output.
135 #define PATHLENGTH (NUMPARMS*sizeof(uintptr_t))
138 #define MAX_WIDE_MODE_COLS (PATHLENGTH + 80)
139 #define MAXWIDTH MAX_WIDE_MODE_COLS + 64
141 #define MAX_PATHNAMES 3
142 #define MAX_SCALL_PATHNAMES 2
144 typedef struct th_info
*th_info_t
;
147 uintptr_t pathname
[NUMPARMS
+ 1]; /* add room for null terminator */
153 uintptr_t child_thread
;
174 struct lookup lookups
[MAX_PATHNAMES
];
178 typedef struct threadmap
* threadmap_t
;
184 unsigned int tm_setsize
; /* this is a bit count */
185 unsigned long *tm_setptr
; /* file descripter bitmap */
186 char tm_command
[MAXCOMLEN
+ 1];
190 typedef struct vnode_info
* vnode_info_t
;
193 vnode_info_t vn_next
;
195 uintptr_t vn_pathname
[NUMPARMS
+ 1];
198 typedef struct meta_info
* meta_info_t
;
206 #define HASH_SIZE 1024
207 #define HASH_MASK (HASH_SIZE - 1)
209 th_info_t th_info_hash
[HASH_SIZE
];
210 th_info_t th_info_freelist
;
212 threadmap_t threadmap_hash
[HASH_SIZE
];
213 threadmap_t threadmap_freelist
;
216 #define VN_HASH_SHIFT 3
217 #define VN_HASH_SIZE 16384
218 #define VN_HASH_MASK (VN_HASH_SIZE - 1)
220 vnode_info_t vn_info_hash
[VN_HASH_SIZE
];
221 meta_info_t m_info_hash
[VN_HASH_SIZE
];
224 int filemgr_in_progress
= 0;
225 int need_new_map
= 1;
229 int include_waited_flag
= 0;
232 int one_good_pid
= 0; /* Used to fail gracefully when bad pids given */
233 int select_pid_mode
= 0; /* Flag set indicates that output is restricted
234 to selected pids or commands */
241 #define USLEEP_BEHIND 2
242 #define USLEEP_MAX 32
243 int usleep_ms
= USLEEP_MIN
;
246 * Network only or filesystem only output filter
247 * Default of zero means report all activity - no filtering
249 #define FILESYS_FILTER 0x01
250 #define NETWORK_FILTER 0x02
251 #define EXEC_FILTER 0x08
252 #define PATHNAME_FILTER 0x10
253 #define DISKIO_FILTER 0x20
254 #define DEFAULT_DO_NOT_FILTER 0x00
256 int filter_mode
= DEFAULT_DO_NOT_FILTER
;
258 boolean_t show_cachehits
= FALSE
;
264 struct diskrec
*next
;
280 uintptr_t issuing_thread
;
281 uintptr_t completion_thread
;
282 char issuing_command
[MAXCOMLEN
+ 1];
284 double completed_time
;
288 struct diskrec
*disk_list
= NULL
;
289 struct diskio
*free_diskios
= NULL
;
290 struct diskio
*busy_diskios
= NULL
;
293 struct diskio
*insert_diskio();
294 struct diskio
*find_diskio(int);
295 struct diskio
*complete_diskio();
299 int check_filter_mode(struct th_info
*, int, int, int, char *);
300 void format_print(struct th_info
*, char *, uintptr_t, int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, int, double, double, int, char *, struct diskio
*);
301 void enter_event_now(uintptr_t, int, kd_buf
*, char *, double);
302 void enter_event(uintptr_t, int, kd_buf
*, char *, double);
303 void exit_event(char *, uintptr_t, int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, int, double);
304 void extend_syscall(uintptr_t, int, kd_buf
*);
306 char *generate_cs_disk_name(int, char *s
);
307 char *find_disk_name(int);
308 void cache_disk_names();
309 void recache_disk_names();
311 void lookup_name(uint64_t user_addr
, char **type
, char **name
);
312 int ReadSharedCacheMap(const char *, LibraryRange
*, char *);
313 void SortFrameworkAddresses();
315 void fs_usage_fd_set(uintptr_t, unsigned int);
316 int fs_usage_fd_isset(uintptr_t, unsigned int);
317 void fs_usage_fd_clear(uintptr_t, unsigned int);
319 void init_arguments_buffer();
320 int get_real_command_name(int, char *, int);
322 void delete_all_events();
323 void delete_event(th_info_t
);
324 th_info_t
add_event(uintptr_t, int);
325 th_info_t
find_event(uintptr_t, int);
326 void mark_thread_waited(uintptr_t);
328 void read_command_map();
329 void delete_all_map_entries();
330 void create_map_entry(uintptr_t, int, char *);
331 void delete_map_entry(uintptr_t);
332 threadmap_t
find_map_entry(uintptr_t);
334 char *add_vnode_name(uint64_t, char *);
335 char *find_vnode_name(uint64_t);
336 char *find_meta_name(uint64_t);
337 void add_meta_name(uint64_t, char *);
343 void set_pidexclude();
347 #define CLASS_MASK 0xff000000
348 #define CSC_MASK 0xffff0000
349 #define BSC_INDEX(type) ((type >> 2) & 0x3fff)
352 #define TRACE_DATA_NEWTHREAD 0x07000004
353 #define TRACE_DATA_EXEC 0x07000008
354 #define TRACE_STRING_NEWTHREAD 0x07010004
355 #define TRACE_STRING_EXEC 0x07010008
357 #define MACH_vmfault 0x01300008
358 #define MACH_pageout 0x01300004
359 #define MACH_sched 0x01400000
360 #define MACH_stkhandoff 0x01400008
361 #define MACH_idle 0x01400024
362 #define VFS_LOOKUP 0x03010090
363 #define VFS_ALIAS_VP 0x03010094
365 #define BSC_thread_terminate 0x040c05a4
367 #define HFS_update 0x3018000
368 #define HFS_modify_block_end 0x3018004
370 #define Throttled 0x3010184
371 #define SPEC_ioctl 0x3060000
372 #define SPEC_unmap_info 0x3060004
373 #define proc_exit 0x4010004
375 #define BC_IO_HIT 0x03070010
376 #define BC_IO_HIT_STALLED 0x03070020
377 #define BC_IO_MISS 0x03070040
378 #define BC_IO_MISS_CUT_THROUGH 0x03070080
379 #define BC_PLAYBACK_IO 0x03070100
380 #define BC_STR(s) ( \
381 (s == BC_IO_HIT) ? "HIT" : \
382 (s == BC_IO_HIT_STALLED) ? "STALL" : \
383 (s == BC_IO_MISS) ? "MISS" : \
384 (s == BC_IO_MISS_CUT_THROUGH) ? "CUT" : \
385 (s == BC_PLAYBACK_IO) ? "PLBK" : \
386 (s == 0x0) ? "NONE" : "UNKN" )
389 #define DKIO_NOCACHE 0x80
392 #define P_DISKIO_READ (DKIO_READ << 2)
393 #define P_DISKIO_ASYNC (DKIO_ASYNC << 2)
394 #define P_DISKIO_META (DKIO_META << 2)
395 #define P_DISKIO_PAGING (DKIO_PAGING << 2)
396 #define P_DISKIO_THROTTLE (DKIO_THROTTLE << 2)
397 #define P_DISKIO_PASSIVE (DKIO_PASSIVE << 2)
398 #define P_DISKIO_NOCACHE (DKIO_NOCACHE << 2)
399 #define P_DISKIO_TIER_MASK (DKIO_TIER_MASK << 2)
400 #define P_DISKIO_TIER_SHIFT (DKIO_TIER_SHIFT + 2)
402 #define P_DISKIO (FSDBG_CODE(DBG_DKRW, 0))
403 #define P_DISKIO_DONE (P_DISKIO | (DKIO_DONE << 2))
404 #define P_DISKIO_TYPE (P_DISKIO | P_DISKIO_READ | P_DISKIO_META | P_DISKIO_PAGING)
405 #define P_DISKIO_MASK (CSC_MASK | 0x4)
407 #define P_WrData (P_DISKIO)
408 #define P_RdData (P_DISKIO | P_DISKIO_READ)
409 #define P_WrMeta (P_DISKIO | P_DISKIO_META)
410 #define P_RdMeta (P_DISKIO | P_DISKIO_META | P_DISKIO_READ)
411 #define P_PgOut (P_DISKIO | P_DISKIO_PAGING)
412 #define P_PgIn (P_DISKIO | P_DISKIO_PAGING | P_DISKIO_READ)
414 #define P_CS_Class 0x0a000000 // DBG_CORESTORAGE
415 #define P_CS_Type_Mask 0xfffffff0
416 #define P_CS_IO_Done 0x00000004
418 #define P_CS_ReadChunk 0x0a000200 // chopped up request
419 #define P_CS_WriteChunk 0x0a000210
420 #define P_CS_MetaRead 0x0a000300 // meta data
421 #define P_CS_MetaWrite 0x0a000310
422 #define P_CS_TransformRead 0x0a000500 // background transform
423 #define P_CS_TransformWrite 0x0a000510
424 #define P_CS_MigrationRead 0x0a000600 // composite disk block migration
425 #define P_CS_MigrationWrite 0x0a000610
426 #define P_CS_SYNC_DISK 0x0a010000
428 #define MSC_map_fd 0x010c00ac
430 #define BSC_BASE 0x040C0000
431 #define MSC_BASE 0x010C0000
433 // Network related codes
434 #define BSC_recvmsg 0x040C006C
435 #define BSC_sendmsg 0x040C0070
436 #define BSC_recvfrom 0x040C0074
437 #define BSC_accept 0x040C0078
438 #define BSC_select 0x040C0174
439 #define BSC_socket 0x040C0184
440 #define BSC_connect 0x040C0188
441 #define BSC_bind 0x040C01A0
442 #define BSC_listen 0x040C01A8
443 #define BSC_sendto 0x040C0214
444 #define BSC_socketpair 0x040C021C
445 #define BSC_recvmsg_nocancel 0x040c0644
446 #define BSC_sendmsg_nocancel 0x040c0648
447 #define BSC_recvfrom_nocancel 0x040c064c
448 #define BSC_accept_nocancel 0x040c0650
449 #define BSC_connect_nocancel 0x040c0664
450 #define BSC_sendto_nocancel 0x040c0674
452 #define BSC_exit 0x040C0004
453 #define BSC_read 0x040C000C
454 #define BSC_write 0x040C0010
455 #define BSC_open 0x040C0014
456 #define BSC_close 0x040C0018
457 #define BSC_link 0x040C0024
458 #define BSC_unlink 0x040C0028
459 #define BSC_chdir 0x040c0030
460 #define BSC_fchdir 0x040c0034
461 #define BSC_mknod 0x040C0038
462 #define BSC_chmod 0x040C003C
463 #define BSC_chown 0x040C0040
464 #define BSC_getfsstat 0x040C0048
465 #define BSC_access 0x040C0084
466 #define BSC_chflags 0x040C0088
467 #define BSC_fchflags 0x040C008C
468 #define BSC_sync 0x040C0090
469 #define BSC_dup 0x040C00A4
470 #define BSC_ioctl 0x040C00D8
471 #define BSC_revoke 0x040C00E0
472 #define BSC_symlink 0x040C00E4
473 #define BSC_readlink 0x040C00E8
474 #define BSC_execve 0x040C00EC
475 #define BSC_umask 0x040C00F0
476 #define BSC_chroot 0x040C00F4
477 #define BSC_msync 0x040C0104
478 #define BSC_dup2 0x040C0168
479 #define BSC_fcntl 0x040C0170
480 #define BSC_fsync 0x040C017C
481 #define BSC_readv 0x040C01E0
482 #define BSC_writev 0x040C01E4
483 #define BSC_fchown 0x040C01EC
484 #define BSC_fchmod 0x040C01F0
485 #define BSC_rename 0x040C0200
486 #define BSC_flock 0x040C020C
487 #define BSC_mkfifo 0x040C0210
488 #define BSC_mkdir 0x040C0220
489 #define BSC_rmdir 0x040C0224
490 #define BSC_utimes 0x040C0228
491 #define BSC_futimes 0x040C022C
492 #define BSC_pread 0x040C0264
493 #define BSC_pwrite 0x040C0268
494 #define BSC_statfs 0x040C0274
495 #define BSC_fstatfs 0x040C0278
496 #define BSC_unmount 0x040C027C
497 #define BSC_mount 0x040C029C
498 #define BSC_fdatasync 0x040C02EC
499 #define BSC_stat 0x040C02F0
500 #define BSC_fstat 0x040C02F4
501 #define BSC_lstat 0x040C02F8
502 #define BSC_pathconf 0x040C02FC
503 #define BSC_fpathconf 0x040C0300
504 #define BSC_getdirentries 0x040C0310
505 #define BSC_mmap 0x040c0314
506 #define BSC_lseek 0x040c031c
507 #define BSC_truncate 0x040C0320
508 #define BSC_ftruncate 0x040C0324
509 #define BSC_undelete 0x040C0334
510 #define BSC_open_dprotected_np 0x040C0360
511 #define BSC_getattrlist 0x040C0370
512 #define BSC_setattrlist 0x040C0374
513 #define BSC_getdirentriesattr 0x040C0378
514 #define BSC_exchangedata 0x040C037C
515 #define BSC_checkuseraccess 0x040C0380
516 #define BSC_searchfs 0x040C0384
517 #define BSC_delete 0x040C0388
518 #define BSC_copyfile 0x040C038C
519 #define BSC_fgetattrlist 0x040C0390
520 #define BSC_fsetattrlist 0x040C0394
521 #define BSC_getxattr 0x040C03A8
522 #define BSC_fgetxattr 0x040C03AC
523 #define BSC_setxattr 0x040C03B0
524 #define BSC_fsetxattr 0x040C03B4
525 #define BSC_removexattr 0x040C03B8
526 #define BSC_fremovexattr 0x040C03BC
527 #define BSC_listxattr 0x040C03C0
528 #define BSC_flistxattr 0x040C03C4
529 #define BSC_fsctl 0x040C03C8
530 #define BSC_posix_spawn 0x040C03D0
531 #define BSC_ffsctl 0x040C03D4
532 #define BSC_open_extended 0x040C0454
533 #define BSC_umask_extended 0x040C0458
534 #define BSC_stat_extended 0x040C045C
535 #define BSC_lstat_extended 0x040C0460
536 #define BSC_fstat_extended 0x040C0464
537 #define BSC_chmod_extended 0x040C0468
538 #define BSC_fchmod_extended 0x040C046C
539 #define BSC_access_extended 0x040C0470
540 #define BSC_mkfifo_extended 0x040C048C
541 #define BSC_mkdir_extended 0x040C0490
542 #define BSC_aio_fsync 0x040C04E4
543 #define BSC_aio_return 0x040C04E8
544 #define BSC_aio_suspend 0x040C04EC
545 #define BSC_aio_cancel 0x040C04F0
546 #define BSC_aio_error 0x040C04F4
547 #define BSC_aio_read 0x040C04F8
548 #define BSC_aio_write 0x040C04FC
549 #define BSC_lio_listio 0x040C0500
550 #define BSC_sendfile 0x040C0544
551 #define BSC_stat64 0x040C0548
552 #define BSC_fstat64 0x040C054C
553 #define BSC_lstat64 0x040C0550
554 #define BSC_stat64_extended 0x040C0554
555 #define BSC_lstat64_extended 0x040C0558
556 #define BSC_fstat64_extended 0x040C055C
557 #define BSC_getdirentries64 0x040C0560
558 #define BSC_statfs64 0x040C0564
559 #define BSC_fstatfs64 0x040C0568
560 #define BSC_getfsstat64 0x040C056C
561 #define BSC_pthread_chdir 0x040C0570
562 #define BSC_pthread_fchdir 0x040C0574
563 #define BSC_lchown 0x040C05B0
565 #define BSC_read_nocancel 0x040c0630
566 #define BSC_write_nocancel 0x040c0634
567 #define BSC_open_nocancel 0x040c0638
568 #define BSC_close_nocancel 0x040c063c
569 #define BSC_msync_nocancel 0x040c0654
570 #define BSC_fcntl_nocancel 0x040c0658
571 #define BSC_select_nocancel 0x040c065c
572 #define BSC_fsync_nocancel 0x040c0660
573 #define BSC_readv_nocancel 0x040c066c
574 #define BSC_writev_nocancel 0x040c0670
575 #define BSC_pread_nocancel 0x040c0678
576 #define BSC_pwrite_nocancel 0x040c067c
577 #define BSC_aio_suspend_nocancel 0x40c0694
578 #define BSC_guarded_open_np 0x040c06e4
579 #define BSC_guarded_close_np 0x040c06e8
581 #define BSC_fsgetpath 0x040c06ac
583 #define BSC_getattrlistbulk 0x040c0734
585 #define BSC_openat 0x040c073c
586 #define BSC_openat_nocancel 0x040c0740
587 #define BSC_renameat 0x040c0744
588 #define BSC_chmodat 0x040c074c
589 #define BSC_chownat 0x040c0750
590 #define BSC_fstatat 0x040c0754
591 #define BSC_fstatat64 0x040c0758
592 #define BSC_linkat 0x040c075c
593 #define BSC_unlinkat 0x040c0760
594 #define BSC_readlinkat 0x040c0764
595 #define BSC_symlinkat 0x040c0768
596 #define BSC_mkdirat 0x040c076c
597 #define BSC_getattrlistat 0x040c0770
599 #define BSC_msync_extended 0x040e0104
600 #define BSC_pread_extended 0x040e0264
601 #define BSC_pwrite_extended 0x040e0268
602 #define BSC_mmap_extended 0x040e0314
603 #define BSC_mmap_extended2 0x040f0314
605 // Carbon File Manager support
606 #define FILEMGR_PBGETCATALOGINFO 0x1e000020
607 #define FILEMGR_PBGETCATALOGINFOBULK 0x1e000024
608 #define FILEMGR_PBCREATEFILEUNICODE 0x1e000028
609 #define FILEMGR_PBCREATEDIRECTORYUNICODE 0x1e00002c
610 #define FILEMGR_PBCREATEFORK 0x1e000030
611 #define FILEMGR_PBDELETEFORK 0x1e000034
612 #define FILEMGR_PBITERATEFORK 0x1e000038
613 #define FILEMGR_PBOPENFORK 0x1e00003c
614 #define FILEMGR_PBREADFORK 0x1e000040
615 #define FILEMGR_PBWRITEFORK 0x1e000044
616 #define FILEMGR_PBALLOCATEFORK 0x1e000048
617 #define FILEMGR_PBDELETEOBJECT 0x1e00004c
618 #define FILEMGR_PBEXCHANGEOBJECT 0x1e000050
619 #define FILEMGR_PBGETFORKCBINFO 0x1e000054
620 #define FILEMGR_PBGETVOLUMEINFO 0x1e000058
621 #define FILEMGR_PBMAKEFSREF 0x1e00005c
622 #define FILEMGR_PBMAKEFSREFUNICODE 0x1e000060
623 #define FILEMGR_PBMOVEOBJECT 0x1e000064
624 #define FILEMGR_PBOPENITERATOR 0x1e000068
625 #define FILEMGR_PBRENAMEUNICODE 0x1e00006c
626 #define FILEMGR_PBSETCATALOGINFO 0x1e000070
627 #define FILEMGR_PBSETVOLUMEINFO 0x1e000074
628 #define FILEMGR_FSREFMAKEPATH 0x1e000078
629 #define FILEMGR_FSPATHMAKEREF 0x1e00007c
631 #define FILEMGR_PBGETCATINFO 0x1e010000
632 #define FILEMGR_PBGETCATINFOLITE 0x1e010004
633 #define FILEMGR_PBHGETFINFO 0x1e010008
634 #define FILEMGR_PBXGETVOLINFO 0x1e01000c
635 #define FILEMGR_PBHCREATE 0x1e010010
636 #define FILEMGR_PBHOPENDF 0x1e010014
637 #define FILEMGR_PBHOPENRF 0x1e010018
638 #define FILEMGR_PBHGETDIRACCESS 0x1e01001c
639 #define FILEMGR_PBHSETDIRACCESS 0x1e010020
640 #define FILEMGR_PBHMAPID 0x1e010024
641 #define FILEMGR_PBHMAPNAME 0x1e010028
642 #define FILEMGR_PBCLOSE 0x1e01002c
643 #define FILEMGR_PBFLUSHFILE 0x1e010030
644 #define FILEMGR_PBGETEOF 0x1e010034
645 #define FILEMGR_PBSETEOF 0x1e010038
646 #define FILEMGR_PBGETFPOS 0x1e01003c
647 #define FILEMGR_PBREAD 0x1e010040
648 #define FILEMGR_PBWRITE 0x1e010044
649 #define FILEMGR_PBGETFCBINFO 0x1e010048
650 #define FILEMGR_PBSETFINFO 0x1e01004c
651 #define FILEMGR_PBALLOCATE 0x1e010050
652 #define FILEMGR_PBALLOCCONTIG 0x1e010054
653 #define FILEMGR_PBSETFPOS 0x1e010058
654 #define FILEMGR_PBSETCATINFO 0x1e01005c
655 #define FILEMGR_PBGETVOLPARMS 0x1e010060
656 #define FILEMGR_PBSETVINFO 0x1e010064
657 #define FILEMGR_PBMAKEFSSPEC 0x1e010068
658 #define FILEMGR_PBHGETVINFO 0x1e01006c
659 #define FILEMGR_PBCREATEFILEIDREF 0x1e010070
660 #define FILEMGR_PBDELETEFILEIDREF 0x1e010074
661 #define FILEMGR_PBRESOLVEFILEIDREF 0x1e010078
662 #define FILEMGR_PBFLUSHVOL 0x1e01007c
663 #define FILEMGR_PBHRENAME 0x1e010080
664 #define FILEMGR_PBCATMOVE 0x1e010084
665 #define FILEMGR_PBEXCHANGEFILES 0x1e010088
666 #define FILEMGR_PBHDELETE 0x1e01008c
667 #define FILEMGR_PBDIRCREATE 0x1e010090
668 #define FILEMGR_PBCATSEARCH 0x1e010094
669 #define FILEMGR_PBHSETFLOCK 0x1e010098
670 #define FILEMGR_PBHRSTFLOCK 0x1e01009c
671 #define FILEMGR_PBLOCKRANGE 0x1e0100a0
672 #define FILEMGR_PBUNLOCKRANGE 0x1e0100a4
675 #define FILEMGR_CLASS 0x1e
676 #define FILEMGR_BASE 0x1e000000
678 #define FMT_DEFAULT 0
685 #define FMT_CACHEHIT 7
689 #define FMT_FTRUNC 11
691 #define FMT_SELECT 13
693 #define FMT_AIO_FSYNC 15
694 #define FMT_AIO_RETURN 16
695 #define FMT_AIO_SUSPEND 17
696 #define FMT_AIO_CANCEL 18
698 #define FMT_LIO_LISTIO 20
701 #define FMT_ACCESS 23
703 #define FMT_FCHMOD 25
704 #define FMT_CHMOD_EXT 26
705 #define FMT_FCHMOD_EXT 27
706 #define FMT_CHFLAGS 28
707 #define FMT_FCHFLAGS 29
711 #define FMT_SENDFILE 33
712 #define FMT_IOCTL_SYNC 34
714 #define FMT_UNMOUNT 36
715 #define FMT_DISKIO_CS 37
716 #define FMT_SYNC_DISK_CS 38
717 #define FMT_IOCTL_UNMAP 39
718 #define FMT_UNMAP_INFO 40
719 #define FMT_HFS_update 41
722 #define FMT_CHMODAT 44
723 #define FMT_OPENAT 45
724 #define FMT_RENAMEAT 46
725 #define FMT_IOCTL_SYNCCACHE 47
727 #define MAX_BSD_SYSCALL 526
732 } bsd_syscalls
[MAX_BSD_SYSCALL
];
735 int bsd_syscall_types
[] = {
737 BSC_recvmsg_nocancel
,
739 BSC_sendmsg_nocancel
,
741 BSC_recvfrom_nocancel
,
748 BSC_connect_nocancel
,
818 BSC_open_dprotected_np
,
823 BSC_getdirentriesattr
,
852 BSC_aio_suspend_nocancel
,
869 BSC_lstat64_extended
,
870 BSC_fstat64_extended
,
879 BSC_guarded_close_np
,
899 #define MAX_FILEMGR 512
901 struct filemgr_call
{
903 } filemgr_calls
[MAX_FILEMGR
];
906 int filemgr_call_types
[] = {
907 FILEMGR_PBGETCATALOGINFO
,
908 FILEMGR_PBGETCATALOGINFOBULK
,
909 FILEMGR_PBCREATEFILEUNICODE
,
910 FILEMGR_PBCREATEDIRECTORYUNICODE
,
911 FILEMGR_PBCREATEFORK
,
912 FILEMGR_PBDELETEFORK
,
913 FILEMGR_PBITERATEFORK
,
917 FILEMGR_PBALLOCATEFORK
,
918 FILEMGR_PBDELETEOBJECT
,
919 FILEMGR_PBEXCHANGEOBJECT
,
920 FILEMGR_PBGETFORKCBINFO
,
921 FILEMGR_PBGETVOLUMEINFO
,
923 FILEMGR_PBMAKEFSREFUNICODE
,
924 FILEMGR_PBMOVEOBJECT
,
925 FILEMGR_PBOPENITERATOR
,
926 FILEMGR_PBRENAMEUNICODE
,
927 FILEMGR_PBSETCATALOGINFO
,
928 FILEMGR_PBSETVOLUMEINFO
,
929 FILEMGR_FSREFMAKEPATH
,
930 FILEMGR_FSPATHMAKEREF
,
932 FILEMGR_PBGETCATINFO
,
933 FILEMGR_PBGETCATINFOLITE
,
935 FILEMGR_PBXGETVOLINFO
,
939 FILEMGR_PBHGETDIRACCESS
,
940 FILEMGR_PBHSETDIRACCESS
,
950 FILEMGR_PBGETFCBINFO
,
953 FILEMGR_PBALLOCCONTIG
,
955 FILEMGR_PBSETCATINFO
,
956 FILEMGR_PBGETVOLPARMS
,
958 FILEMGR_PBMAKEFSSPEC
,
960 FILEMGR_PBCREATEFILEIDREF
,
961 FILEMGR_PBDELETEFILEIDREF
,
962 FILEMGR_PBRESOLVEFILEIDREF
,
966 FILEMGR_PBEXCHANGEFILES
,
973 FILEMGR_PBUNLOCKRANGE
,
983 int exclude_pids
= 0;
984 int exclude_default_pids
= 1;
987 struct kinfo_proc
*kp_buffer
= 0;
990 #define EVENT_BASE 60000
992 int num_events
= EVENT_BASE
;
995 #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END)
996 #define DBG_FUNC_MASK 0xfffffffc
998 double divisor
= 0.0; /* Trace divisor converts to microseconds */
1004 kbufinfo_t bufinfo
= {0, 0, 0, 0, 0};
1007 /* defines for tracking file descriptor state */
1008 #define FS_USAGE_FD_SETSIZE 256 /* Initial number of file descriptors per
1009 thread that we will track */
1011 #define FS_USAGE_NFDBITS (sizeof (unsigned long) * 8)
1012 #define FS_USAGE_NFDBYTES(n) (((n) / FS_USAGE_NFDBITS) * sizeof (unsigned long))
1014 int trace_enabled
= 0;
1015 int set_remove_flag
= 1;
1019 char *RAW_file
= (char *)0;
1023 uint64_t sample_TOD_secs
;
1024 uint32_t sample_TOD_usecs
;
1026 double bias_now
= 0.0;
1027 double start_time
= 0.0;
1028 double end_time
= 999999999999.9;
1042 void leave() /* exit under normal conditions -- INT handler */
1046 void set_pidcheck();
1047 void set_pidexclude();
1054 if (exclude_pids
== 0) {
1055 for (i
= 0; i
< num_of_pids
; i
++)
1056 set_pidcheck(pids
[i
], 0);
1059 for (i
= 0; i
< num_of_pids
; i
++)
1060 set_pidexclude(pids
[i
], 0);
1076 * This flag is turned off when calling
1077 * quit() due to a set_remove() failure.
1079 if (set_remove_flag
)
1082 fprintf(stderr
, "fs_usage: ");
1084 fprintf(stderr
, "%s", s
);
1090 void get_screenwidth()
1092 struct winsize size
;
1097 if (ioctl(1, TIOCGWINSZ
, &size
) != -1) {
1098 columns
= size
.ws_col
;
1100 if (columns
> MAXWIDTH
)
1116 struct mach_timebase_info mti
;
1118 mach_timebase_info(&mti
);
1120 divisor
= ((double)mti
.denom
/ (double)mti
.numer
) * 1000;
1125 exit_usage(char *myname
) {
1127 fprintf(stderr
, "Usage: %s [-e] [-w] [-f mode] [-b] [-t seconds] [-R rawfile [-S start_time] [-E end_time]] [pid | cmd [pid | cmd] ...]\n", myname
);
1128 fprintf(stderr
, " -e exclude the specified list of pids from the sample\n");
1129 fprintf(stderr
, " and exclude fs_usage by default\n");
1130 fprintf(stderr
, " -w force wider, detailed, output\n");
1131 fprintf(stderr
, " -f output is based on the mode provided\n");
1132 fprintf(stderr
, " mode = \"network\" Show network-related events\n");
1133 fprintf(stderr
, " mode = \"filesys\" Show filesystem-related events\n");
1134 fprintf(stderr
, " mode = \"pathname\" Show only pathname-related events\n");
1135 fprintf(stderr
, " mode = \"exec\" Show only exec and spawn events\n");
1136 fprintf(stderr
, " mode = \"diskio\" Show only disk I/O events\n");
1137 fprintf(stderr
, " mode = \"cachehit\" In addition, show cache hits\n");
1138 fprintf(stderr
, " -b annotate disk I/O events with BootCache info (if available)\n");
1139 fprintf(stderr
, " -t specifies timeout in seconds (for use in automated tools)\n");
1140 fprintf(stderr
, " -R specifies a raw trace file to process\n");
1141 fprintf(stderr
, " -S if -R is specified, selects a start point in microseconds\n");
1142 fprintf(stderr
, " -E if -R is specified, selects an end point in microseconds\n");
1143 fprintf(stderr
, " pid selects process(s) to sample\n");
1144 fprintf(stderr
, " cmd selects process(s) matching command string to sample\n");
1145 fprintf(stderr
, "\n%s will handle a maximum list of %d pids.\n\n", myname
, MAX_PIDS
);
1146 fprintf(stderr
, "By default (no options) the following processes are excluded from the output:\n");
1147 fprintf(stderr
, "fs_usage, Terminal, telnetd, sshd, rlogind, tcsh, csh, sh\n\n");
1153 int filemgr_index(type
) {
1156 return (((type
>> 2) & 0x3fff) + 256);
1158 return (((type
>> 2) & 0x3fff));
1162 void init_tables(void)
1168 for (i
= 0; i
< MAX_BSD_SYSCALL
; i
++) {
1169 bsd_syscalls
[i
].sc_name
= NULL
;
1170 bsd_syscalls
[i
].sc_format
= FMT_DEFAULT
;
1173 for (i
= 0; i
< MAX_FILEMGR
; i
++) {
1174 filemgr_calls
[i
].fm_name
= NULL
;
1177 for (i
= 0; (type
= bsd_syscall_types
[i
]); i
++) {
1179 code
= BSC_INDEX(type
);
1181 if (code
>= MAX_BSD_SYSCALL
) {
1182 printf("BSD syscall init (%x): type exceeds table size\n", type
);
1188 bsd_syscalls
[code
].sc_name
= "sendfile";
1189 bsd_syscalls
[code
].sc_format
= FMT_FD
; /* this should be changed to FMT_SENDFILE */
1190 break; /* once we add an extended info trace event */
1193 case BSC_recvmsg_nocancel
:
1194 bsd_syscalls
[code
].sc_name
= "recvmsg";
1195 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1199 case BSC_sendmsg_nocancel
:
1200 bsd_syscalls
[code
].sc_name
= "sendmsg";
1201 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1205 case BSC_recvfrom_nocancel
:
1206 bsd_syscalls
[code
].sc_name
= "recvfrom";
1207 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1211 case BSC_sendto_nocancel
:
1212 bsd_syscalls
[code
].sc_name
= "sendto";
1213 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1217 case BSC_select_nocancel
:
1218 bsd_syscalls
[code
].sc_name
= "select";
1219 bsd_syscalls
[code
].sc_format
= FMT_SELECT
;
1223 case BSC_accept_nocancel
:
1224 bsd_syscalls
[code
].sc_name
= "accept";
1225 bsd_syscalls
[code
].sc_format
= FMT_FD_2
;
1229 bsd_syscalls
[code
].sc_name
= "socket";
1230 bsd_syscalls
[code
].sc_format
= FMT_SOCKET
;
1234 case BSC_connect_nocancel
:
1235 bsd_syscalls
[code
].sc_name
= "connect";
1236 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1240 bsd_syscalls
[code
].sc_name
= "bind";
1241 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1245 bsd_syscalls
[code
].sc_name
= "listen";
1246 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1250 bsd_syscalls
[code
].sc_name
= "mmap";
1251 bsd_syscalls
[code
].sc_format
= FMT_MMAP
;
1254 case BSC_socketpair
:
1255 bsd_syscalls
[code
].sc_name
= "socketpair";
1259 bsd_syscalls
[code
].sc_name
= "getxattr";
1263 bsd_syscalls
[code
].sc_name
= "setxattr";
1266 case BSC_removexattr
:
1267 bsd_syscalls
[code
].sc_name
= "removexattr";
1271 bsd_syscalls
[code
].sc_name
= "listxattr";
1275 bsd_syscalls
[code
].sc_name
= "stat";
1279 bsd_syscalls
[code
].sc_name
= "stat64";
1282 case BSC_stat_extended
:
1283 bsd_syscalls
[code
].sc_name
= "stat_extended";
1286 case BSC_stat64_extended
:
1287 bsd_syscalls
[code
].sc_name
= "stat_extended64";
1291 bsd_syscalls
[code
].sc_name
= "mount";
1292 bsd_syscalls
[code
].sc_format
= FMT_MOUNT
;
1296 bsd_syscalls
[code
].sc_name
= "unmount";
1297 bsd_syscalls
[code
].sc_format
= FMT_UNMOUNT
;
1301 bsd_syscalls
[code
].sc_name
= "exit";
1305 bsd_syscalls
[code
].sc_name
= "execve";
1308 case BSC_posix_spawn
:
1309 bsd_syscalls
[code
].sc_name
= "posix_spawn";
1313 case BSC_open_nocancel
:
1314 bsd_syscalls
[code
].sc_name
= "open";
1315 bsd_syscalls
[code
].sc_format
= FMT_OPEN
;
1318 case BSC_open_extended
:
1319 bsd_syscalls
[code
].sc_name
= "open_extended";
1320 bsd_syscalls
[code
].sc_format
= FMT_OPEN
;
1323 case BSC_guarded_open_np
:
1324 bsd_syscalls
[code
].sc_name
= "guarded_open_np";
1325 bsd_syscalls
[code
].sc_format
= FMT_OPEN
;
1328 case BSC_open_dprotected_np
:
1329 bsd_syscalls
[code
].sc_name
= "open_dprotected";
1330 bsd_syscalls
[code
].sc_format
= FMT_OPEN
;
1334 bsd_syscalls
[code
].sc_name
= "dup";
1335 bsd_syscalls
[code
].sc_format
= FMT_FD_2
;
1339 bsd_syscalls
[code
].sc_name
= "dup2";
1340 bsd_syscalls
[code
].sc_format
= FMT_FD_2
;
1344 case BSC_close_nocancel
:
1345 bsd_syscalls
[code
].sc_name
= "close";
1346 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1349 case BSC_guarded_close_np
:
1350 bsd_syscalls
[code
].sc_name
= "guarded_close_np";
1351 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1355 case BSC_read_nocancel
:
1356 bsd_syscalls
[code
].sc_name
= "read";
1357 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1361 case BSC_write_nocancel
:
1362 bsd_syscalls
[code
].sc_name
= "write";
1363 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1367 bsd_syscalls
[code
].sc_name
= "fgetxattr";
1368 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1372 bsd_syscalls
[code
].sc_name
= "fsetxattr";
1373 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1376 case BSC_fremovexattr
:
1377 bsd_syscalls
[code
].sc_name
= "fremovexattr";
1378 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1381 case BSC_flistxattr
:
1382 bsd_syscalls
[code
].sc_name
= "flistxattr";
1383 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1387 bsd_syscalls
[code
].sc_name
= "fstat";
1388 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1392 bsd_syscalls
[code
].sc_name
= "fstat64";
1393 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1396 case BSC_fstat_extended
:
1397 bsd_syscalls
[code
].sc_name
= "fstat_extended";
1398 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1401 case BSC_fstat64_extended
:
1402 bsd_syscalls
[code
].sc_name
= "fstat64_extended";
1403 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1407 bsd_syscalls
[code
].sc_name
= "lstat";
1411 bsd_syscalls
[code
].sc_name
= "lstat64";
1414 case BSC_lstat_extended
:
1415 bsd_syscalls
[code
].sc_name
= "lstat_extended";
1418 case BSC_lstat64_extended
:
1419 bsd_syscalls
[code
].sc_name
= "lstat_extended64";
1423 bsd_syscalls
[code
].sc_name
= "link";
1427 bsd_syscalls
[code
].sc_name
= "unlink";
1431 bsd_syscalls
[code
].sc_name
= "mknod";
1435 bsd_syscalls
[code
].sc_name
= "umask";
1436 bsd_syscalls
[code
].sc_format
= FMT_UMASK
;
1439 case BSC_umask_extended
:
1440 bsd_syscalls
[code
].sc_name
= "umask_extended";
1441 bsd_syscalls
[code
].sc_format
= FMT_UMASK
;
1445 bsd_syscalls
[code
].sc_name
= "chmod";
1446 bsd_syscalls
[code
].sc_format
= FMT_CHMOD
;
1449 case BSC_chmod_extended
:
1450 bsd_syscalls
[code
].sc_name
= "chmod_extended";
1451 bsd_syscalls
[code
].sc_format
= FMT_CHMOD_EXT
;
1455 bsd_syscalls
[code
].sc_name
= "fchmod";
1456 bsd_syscalls
[code
].sc_format
= FMT_FCHMOD
;
1459 case BSC_fchmod_extended
:
1460 bsd_syscalls
[code
].sc_name
= "fchmod_extended";
1461 bsd_syscalls
[code
].sc_format
= FMT_FCHMOD_EXT
;
1465 bsd_syscalls
[code
].sc_name
= "chown";
1469 bsd_syscalls
[code
].sc_name
= "lchown";
1473 bsd_syscalls
[code
].sc_name
= "fchown";
1474 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1478 bsd_syscalls
[code
].sc_name
= "access";
1479 bsd_syscalls
[code
].sc_format
= FMT_ACCESS
;
1482 case BSC_access_extended
:
1483 bsd_syscalls
[code
].sc_name
= "access_extended";
1487 bsd_syscalls
[code
].sc_name
= "chdir";
1490 case BSC_pthread_chdir
:
1491 bsd_syscalls
[code
].sc_name
= "pthread_chdir";
1495 bsd_syscalls
[code
].sc_name
= "chroot";
1499 bsd_syscalls
[code
].sc_name
= "utimes";
1503 bsd_syscalls
[code
].sc_name
= "delete-Carbon";
1507 bsd_syscalls
[code
].sc_name
= "undelete";
1511 bsd_syscalls
[code
].sc_name
= "revoke";
1515 bsd_syscalls
[code
].sc_name
= "fsctl";
1519 bsd_syscalls
[code
].sc_name
= "ffsctl";
1520 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1524 bsd_syscalls
[code
].sc_name
= "chflags";
1525 bsd_syscalls
[code
].sc_format
= FMT_CHFLAGS
;
1529 bsd_syscalls
[code
].sc_name
= "fchflags";
1530 bsd_syscalls
[code
].sc_format
= FMT_FCHFLAGS
;
1534 bsd_syscalls
[code
].sc_name
= "fchdir";
1535 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1538 case BSC_pthread_fchdir
:
1539 bsd_syscalls
[code
].sc_name
= "pthread_fchdir";
1540 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1544 bsd_syscalls
[code
].sc_name
= "futimes";
1545 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1549 bsd_syscalls
[code
].sc_name
= "sync";
1553 bsd_syscalls
[code
].sc_name
= "symlink";
1557 bsd_syscalls
[code
].sc_name
= "readlink";
1561 case BSC_fsync_nocancel
:
1562 bsd_syscalls
[code
].sc_name
= "fsync";
1563 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1567 bsd_syscalls
[code
].sc_name
= "fdatasync";
1568 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1572 case BSC_readv_nocancel
:
1573 bsd_syscalls
[code
].sc_name
= "readv";
1574 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1578 case BSC_writev_nocancel
:
1579 bsd_syscalls
[code
].sc_name
= "writev";
1580 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1584 case BSC_pread_nocancel
:
1585 bsd_syscalls
[code
].sc_name
= "pread";
1586 bsd_syscalls
[code
].sc_format
= FMT_PREAD
;
1590 case BSC_pwrite_nocancel
:
1591 bsd_syscalls
[code
].sc_name
= "pwrite";
1592 bsd_syscalls
[code
].sc_format
= FMT_PREAD
;
1596 bsd_syscalls
[code
].sc_name
= "mkdir";
1599 case BSC_mkdir_extended
:
1600 bsd_syscalls
[code
].sc_name
= "mkdir_extended";
1604 bsd_syscalls
[code
].sc_name
= "mkfifo";
1607 case BSC_mkfifo_extended
:
1608 bsd_syscalls
[code
].sc_name
= "mkfifo_extended";
1612 bsd_syscalls
[code
].sc_name
= "rmdir";
1616 bsd_syscalls
[code
].sc_name
= "statfs";
1620 bsd_syscalls
[code
].sc_name
= "statfs64";
1624 bsd_syscalls
[code
].sc_name
= "getfsstat";
1627 case BSC_getfsstat64
:
1628 bsd_syscalls
[code
].sc_name
= "getfsstat64";
1632 bsd_syscalls
[code
].sc_name
= "fstatfs";
1633 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1637 bsd_syscalls
[code
].sc_name
= "fstatfs64";
1638 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1642 bsd_syscalls
[code
].sc_name
= "pathconf";
1646 bsd_syscalls
[code
].sc_name
= "fpathconf";
1647 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1650 case BSC_getdirentries
:
1651 bsd_syscalls
[code
].sc_name
= "getdirentries";
1652 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1655 case BSC_getdirentries64
:
1656 bsd_syscalls
[code
].sc_name
= "getdirentries64";
1657 bsd_syscalls
[code
].sc_format
= FMT_FD_IO
;
1661 bsd_syscalls
[code
].sc_name
= "lseek";
1662 bsd_syscalls
[code
].sc_format
= FMT_LSEEK
;
1666 bsd_syscalls
[code
].sc_name
= "truncate";
1667 bsd_syscalls
[code
].sc_format
= FMT_TRUNC
;
1671 bsd_syscalls
[code
].sc_name
= "ftruncate";
1672 bsd_syscalls
[code
].sc_format
= FMT_FTRUNC
;
1676 bsd_syscalls
[code
].sc_name
= "flock";
1677 bsd_syscalls
[code
].sc_format
= FMT_FLOCK
;
1680 case BSC_getattrlist
:
1681 bsd_syscalls
[code
].sc_name
= "getattrlist";
1684 case BSC_setattrlist
:
1685 bsd_syscalls
[code
].sc_name
= "setattrlist";
1688 case BSC_fgetattrlist
:
1689 bsd_syscalls
[code
].sc_name
= "fgetattrlist";
1690 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1693 case BSC_fsetattrlist
:
1694 bsd_syscalls
[code
].sc_name
= "fsetattrlist";
1695 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1698 case BSC_getdirentriesattr
:
1699 bsd_syscalls
[code
].sc_name
= "getdirentriesattr";
1700 bsd_syscalls
[code
].sc_format
= FMT_FD
;
1703 case BSC_exchangedata
:
1704 bsd_syscalls
[code
].sc_name
= "exchangedata";
1708 bsd_syscalls
[code
].sc_name
= "rename";
1712 bsd_syscalls
[code
].sc_name
= "copyfile";
1715 case BSC_checkuseraccess
:
1716 bsd_syscalls
[code
].sc_name
= "checkuseraccess";
1720 bsd_syscalls
[code
].sc_name
= "searchfs";
1724 bsd_syscalls
[code
].sc_name
= "aio_fsync";
1725 bsd_syscalls
[code
].sc_format
= FMT_AIO_FSYNC
;
1728 case BSC_aio_return
:
1729 bsd_syscalls
[code
].sc_name
= "aio_return";
1730 bsd_syscalls
[code
].sc_format
= FMT_AIO_RETURN
;
1733 case BSC_aio_suspend
:
1734 case BSC_aio_suspend_nocancel
:
1735 bsd_syscalls
[code
].sc_name
= "aio_suspend";
1736 bsd_syscalls
[code
].sc_format
= FMT_AIO_SUSPEND
;
1739 case BSC_aio_cancel
:
1740 bsd_syscalls
[code
].sc_name
= "aio_cancel";
1741 bsd_syscalls
[code
].sc_format
= FMT_AIO_CANCEL
;
1745 bsd_syscalls
[code
].sc_name
= "aio_error";
1746 bsd_syscalls
[code
].sc_format
= FMT_AIO
;
1750 bsd_syscalls
[code
].sc_name
= "aio_read";
1751 bsd_syscalls
[code
].sc_format
= FMT_AIO
;
1755 bsd_syscalls
[code
].sc_name
= "aio_write";
1756 bsd_syscalls
[code
].sc_format
= FMT_AIO
;
1759 case BSC_lio_listio
:
1760 bsd_syscalls
[code
].sc_name
= "lio_listio";
1761 bsd_syscalls
[code
].sc_format
= FMT_LIO_LISTIO
;
1765 case BSC_msync_nocancel
:
1766 bsd_syscalls
[code
].sc_name
= "msync";
1767 bsd_syscalls
[code
].sc_format
= FMT_MSYNC
;
1771 case BSC_fcntl_nocancel
:
1772 bsd_syscalls
[code
].sc_name
= "fcntl";
1773 bsd_syscalls
[code
].sc_format
= FMT_FCNTL
;
1777 bsd_syscalls
[code
].sc_name
= "ioctl";
1778 bsd_syscalls
[code
].sc_format
= FMT_IOCTL
;
1782 bsd_syscalls
[code
].sc_name
= "fsgetpath";
1785 case BSC_getattrlistbulk
:
1786 bsd_syscalls
[code
].sc_name
= "getattrlistbulk";
1790 bsd_syscalls
[code
].sc_name
= "openat";
1791 bsd_syscalls
[code
].sc_format
= FMT_OPENAT
;
1794 case BSC_openat_nocancel
:
1795 bsd_syscalls
[code
].sc_name
= "openat_nocanel";
1796 bsd_syscalls
[code
].sc_format
= FMT_OPENAT
;
1800 bsd_syscalls
[code
].sc_name
= "renameat";
1801 bsd_syscalls
[code
].sc_format
= FMT_RENAMEAT
;
1805 bsd_syscalls
[code
].sc_name
= "chmodat";
1806 bsd_syscalls
[code
].sc_format
= FMT_CHMODAT
;
1810 bsd_syscalls
[code
].sc_name
= "chownat";
1811 bsd_syscalls
[code
].sc_format
= FMT_AT
;
1815 bsd_syscalls
[code
].sc_name
= "fstatat";
1816 bsd_syscalls
[code
].sc_format
= FMT_AT
;
1820 bsd_syscalls
[code
].sc_name
= "fstatat64";
1821 bsd_syscalls
[code
].sc_format
= FMT_AT
;
1825 bsd_syscalls
[code
].sc_name
= "linkat";
1826 bsd_syscalls
[code
].sc_format
= FMT_AT
;
1830 bsd_syscalls
[code
].sc_name
= "unlinkat";
1831 bsd_syscalls
[code
].sc_format
= FMT_AT
;
1834 case BSC_readlinkat
:
1835 bsd_syscalls
[code
].sc_name
= "readlinkat";
1836 bsd_syscalls
[code
].sc_format
= FMT_AT
;
1840 bsd_syscalls
[code
].sc_name
= "symlinkat";
1841 bsd_syscalls
[code
].sc_format
= FMT_AT
;
1845 bsd_syscalls
[code
].sc_name
= "mkdirat";
1846 bsd_syscalls
[code
].sc_format
= FMT_AT
;
1849 case BSC_getattrlistat
:
1850 bsd_syscalls
[code
].sc_name
= "getattrlistat";
1851 bsd_syscalls
[code
].sc_format
= FMT_AT
;
1856 for (i
= 0; (type
= filemgr_call_types
[i
]); i
++) {
1859 code
= filemgr_index(type
);
1861 if (code
>= MAX_FILEMGR
) {
1862 printf("FILEMGR call init (%x): type exceeds table size\n", type
);
1867 case FILEMGR_PBGETCATALOGINFO
:
1868 p
= "GetCatalogInfo";
1871 case FILEMGR_PBGETCATALOGINFOBULK
:
1872 p
= "GetCatalogInfoBulk";
1875 case FILEMGR_PBCREATEFILEUNICODE
:
1876 p
= "CreateFileUnicode";
1879 case FILEMGR_PBCREATEDIRECTORYUNICODE
:
1880 p
= "CreateDirectoryUnicode";
1883 case FILEMGR_PBCREATEFORK
:
1887 case FILEMGR_PBDELETEFORK
:
1891 case FILEMGR_PBITERATEFORK
:
1892 p
= "PBIterateFork";
1895 case FILEMGR_PBOPENFORK
:
1899 case FILEMGR_PBREADFORK
:
1903 case FILEMGR_PBWRITEFORK
:
1907 case FILEMGR_PBALLOCATEFORK
:
1908 p
= "PBAllocateFork";
1911 case FILEMGR_PBDELETEOBJECT
:
1912 p
= "PBDeleteObject";
1915 case FILEMGR_PBEXCHANGEOBJECT
:
1916 p
= "PBExchangeObject";
1919 case FILEMGR_PBGETFORKCBINFO
:
1920 p
= "PBGetForkCBInfo";
1923 case FILEMGR_PBGETVOLUMEINFO
:
1924 p
= "PBGetVolumeInfo";
1927 case FILEMGR_PBMAKEFSREF
:
1931 case FILEMGR_PBMAKEFSREFUNICODE
:
1932 p
= "PBMakeFSRefUnicode";
1935 case FILEMGR_PBMOVEOBJECT
:
1939 case FILEMGR_PBOPENITERATOR
:
1940 p
= "PBOpenIterator";
1943 case FILEMGR_PBRENAMEUNICODE
:
1944 p
= "PBRenameUnicode";
1947 case FILEMGR_PBSETCATALOGINFO
:
1948 p
= "SetCatalogInfo";
1951 case FILEMGR_PBSETVOLUMEINFO
:
1952 p
= "SetVolumeInfo";
1955 case FILEMGR_FSREFMAKEPATH
:
1956 p
= "FSRefMakePath";
1959 case FILEMGR_FSPATHMAKEREF
:
1960 p
= "FSPathMakeRef";
1963 case FILEMGR_PBGETCATINFO
:
1967 case FILEMGR_PBGETCATINFOLITE
:
1968 p
= "GetCatInfoLite";
1971 case FILEMGR_PBHGETFINFO
:
1975 case FILEMGR_PBXGETVOLINFO
:
1976 p
= "PBXGetVolInfo";
1979 case FILEMGR_PBHCREATE
:
1983 case FILEMGR_PBHOPENDF
:
1987 case FILEMGR_PBHOPENRF
:
1991 case FILEMGR_PBHGETDIRACCESS
:
1992 p
= "PBHGetDirAccess";
1995 case FILEMGR_PBHSETDIRACCESS
:
1996 p
= "PBHSetDirAccess";
1999 case FILEMGR_PBHMAPID
:
2003 case FILEMGR_PBHMAPNAME
:
2007 case FILEMGR_PBCLOSE
:
2011 case FILEMGR_PBFLUSHFILE
:
2015 case FILEMGR_PBGETEOF
:
2019 case FILEMGR_PBSETEOF
:
2023 case FILEMGR_PBGETFPOS
:
2027 case FILEMGR_PBREAD
:
2031 case FILEMGR_PBWRITE
:
2035 case FILEMGR_PBGETFCBINFO
:
2039 case FILEMGR_PBSETFINFO
:
2043 case FILEMGR_PBALLOCATE
:
2047 case FILEMGR_PBALLOCCONTIG
:
2048 p
= "PBAllocContig";
2051 case FILEMGR_PBSETFPOS
:
2055 case FILEMGR_PBSETCATINFO
:
2059 case FILEMGR_PBGETVOLPARMS
:
2060 p
= "PBGetVolParms";
2063 case FILEMGR_PBSETVINFO
:
2067 case FILEMGR_PBMAKEFSSPEC
:
2071 case FILEMGR_PBHGETVINFO
:
2075 case FILEMGR_PBCREATEFILEIDREF
:
2076 p
= "PBCreateFileIDRef";
2079 case FILEMGR_PBDELETEFILEIDREF
:
2080 p
= "PBDeleteFileIDRef";
2083 case FILEMGR_PBRESOLVEFILEIDREF
:
2084 p
= "PBResolveFileIDRef";
2087 case FILEMGR_PBFLUSHVOL
:
2091 case FILEMGR_PBHRENAME
:
2095 case FILEMGR_PBCATMOVE
:
2099 case FILEMGR_PBEXCHANGEFILES
:
2100 p
= "PBExchangeFiles";
2103 case FILEMGR_PBHDELETE
:
2107 case FILEMGR_PBDIRCREATE
:
2111 case FILEMGR_PBCATSEARCH
:
2115 case FILEMGR_PBHSETFLOCK
:
2119 case FILEMGR_PBHRSTFLOCK
:
2123 case FILEMGR_PBLOCKRANGE
:
2127 case FILEMGR_PBUNLOCKRANGE
:
2128 p
= "PBUnlockRange";
2135 filemgr_calls
[code
].fm_name
= p
;
2146 char *myname
= "fs_usage";
2150 time_t stop_at_time
= 0;
2152 if (0 != reexec_to_match_kernel()) {
2153 fprintf(stderr
, "Could not re-execute: %d\n", errno
);
2162 if ((myname
= rindex(argv
[0], '/')) == 0)
2168 while ((ch
= getopt(argc
, argv
, "bewf:R:S:E:t:W")) != EOF
) {
2174 exclude_default_pids
= 0;
2179 if ((uint
)columns
< MAX_WIDE_MODE_COLS
)
2180 columns
= MAX_WIDE_MODE_COLS
;
2184 include_waited_flag
= 1;
2188 if (!strcmp(optarg
, "network"))
2189 filter_mode
|= NETWORK_FILTER
;
2190 else if (!strcmp(optarg
, "filesys"))
2191 filter_mode
|= FILESYS_FILTER
;
2192 else if (!strcmp(optarg
, "cachehit"))
2193 show_cachehits
= TRUE
;
2194 else if (!strcmp(optarg
, "exec"))
2195 filter_mode
|= EXEC_FILTER
;
2196 else if (!strcmp(optarg
, "pathname"))
2197 filter_mode
|= PATHNAME_FILTER
;
2198 else if (!strcmp(optarg
, "diskio"))
2199 filter_mode
|= DISKIO_FILTER
;
2207 stop_at_time
= time(NULL
) + strtoul(optarg
, NULL
, 10);
2216 start_time
= atof(optarg
);
2220 end_time
= atof(optarg
);
2228 if ( geteuid() != 0 ) {
2229 fprintf(stderr
, "'fs_usage' must be run as root...\n");
2237 * when excluding, fs_usage should be the first in line for pids[]
2239 * the !exclude_pids && argc == 0 catches the exclude_default_pids
2240 * case below where exclude_pids is later set and the fs_usage PID
2241 * needs to make it into pids[]
2243 if (exclude_pids
|| (!exclude_pids
&& argc
== 0)) {
2244 if (num_of_pids
< (MAX_PIDS
- 1))
2245 pids
[num_of_pids
++] = getpid();
2249 * If we process any list of pids/cmds, then turn off the defaults
2252 exclude_default_pids
= 0;
2254 while (argc
> 0 && num_of_pids
< (MAX_PIDS
- 1)) {
2261 * Exclude a set of default pids
2263 if (exclude_default_pids
) {
2264 argtopid("Terminal");
2265 argtopid("telnetd");
2268 argtopid("rlogind");
2275 for (i
= 0; i
< num_of_pids
; i
++) {
2277 fprintf(stderr
, "exclude pid %d\n", pids
[i
]);
2279 fprintf(stderr
, "pid %d\n", pids
[i
]);
2283 struct sigaction osa
;
2287 /* set up signal handlers */
2288 signal(SIGINT
, leave
);
2289 signal(SIGQUIT
, leave
);
2290 signal(SIGPIPE
, leave
);
2292 sigaction(SIGHUP
, (struct sigaction
*)NULL
, &osa
);
2294 if (osa
.sa_handler
== SIG_DFL
)
2295 signal(SIGHUP
, leave
);
2296 signal(SIGTERM
, leave
);
2298 * grab the number of cpus
2303 len
= sizeof(num_cpus
);
2305 sysctl(mib
, 2, &num_cpus
, &len
, NULL
, 0);
2306 num_events
= EVENT_BASE
* num_cpus
;
2308 signal(SIGWINCH
, sigwinch
);
2310 if ((my_buffer
= malloc(num_events
* sizeof(kd_buf
))) == (char *)0)
2311 quit("can't allocate memory for tracing info\n");
2313 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_i386.map", &framework32
, "/var/db/dyld/dyld_shared_cache_i386");
2315 if (0 == ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64h.map", &framework64h
, "/var/db/dyld/dyld_shared_cache_x86_64h")){
2316 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64.map", &framework64
, "/var/db/dyld/dyld_shared_cache_x86_64");
2319 SortFrameworkAddresses();
2326 set_numbufs(num_events
);
2329 if (exclude_pids
== 0) {
2330 for (i
= 0; i
< num_of_pids
; i
++)
2331 set_pidcheck(pids
[i
], 1);
2333 for (i
= 0; i
< num_of_pids
; i
++)
2334 set_pidexclude(pids
[i
], 1);
2336 if (select_pid_mode
&& !one_good_pid
) {
2338 * An attempt to restrict output to a given
2339 * pid or command has failed. Exit gracefully
2349 init_arguments_buffer();
2358 while (stop_at_time
== 0 || last_time
< stop_at_time
) {
2360 usleep(1000 * usleep_ms
);
2364 last_time
= time((long *)0);
2373 struct kinfo_proc
*kp
;
2377 mib
[2] = KERN_PROC_ALL
;
2380 if (sysctl(mib
, 4, NULL
, &bufSize
, NULL
, 0) < 0)
2381 quit("trace facility failure, KERN_PROC_ALL\n");
2383 if ((kp
= (struct kinfo_proc
*)malloc(bufSize
)) == (struct kinfo_proc
*)0)
2384 quit("can't allocate memory for proc buffer\n");
2386 if (sysctl(mib
, 4, kp
, &bufSize
, NULL
, 0) < 0)
2387 quit("trace facility failure, KERN_PROC_ALL\n");
2389 kp_nentries
= bufSize
/ sizeof(struct kinfo_proc
);
2398 mib
[1] = KERN_KDEBUG
;
2399 mib
[2] = KERN_KDENABLE
; /* protocol */
2402 mib
[5] = 0; /* no flags */
2404 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
2405 quit("trace facility failure, KERN_KDENABLE\n");
2414 set_numbufs(int nbufs
)
2417 mib
[1] = KERN_KDEBUG
;
2418 mib
[2] = KERN_KDSETBUF
;
2421 mib
[5] = 0; /* no flags */
2423 if (sysctl(mib
, 4, NULL
, &needed
, NULL
, 0) < 0)
2424 quit("trace facility failure, KERN_KDSETBUF\n");
2427 mib
[1] = KERN_KDEBUG
;
2428 mib
[2] = KERN_KDSETUP
;
2431 mib
[5] = 0; /* no flags */
2433 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
2434 quit("trace facility failure, KERN_KDSETUP\n");
2437 #define ENCODE_CSC_LOW(class, subclass) \
2438 ( (uint16_t) ( ((class) & 0xff) << 8 ) | ((subclass) & 0xff) )
2443 uint8_t type_filter_bitmap
[KDBG_TYPEFILTER_BITMAP_SIZE
];
2444 bzero(type_filter_bitmap
, sizeof(type_filter_bitmap
));
2446 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_TRACE
,DBG_TRACE_DATA
));
2447 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_TRACE
,DBG_TRACE_STRING
));
2449 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_MACH
,DBG_MACH_EXCP_SC
)); //0x010c
2450 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_MACH
,DBG_MACH_VM
)); //0x0130
2452 if (include_waited_flag
)
2453 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_MACH
,DBG_MACH_SCHED
)); //0x0140
2455 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_FSYSTEM
,DBG_FSRW
)); //0x0301
2456 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_FSYSTEM
,DBG_DKRW
)); //0x0302
2457 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_FSYSTEM
,DBG_IOCTL
)); //0x0306
2458 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_FSYSTEM
,DBG_BOOTCACHE
)); //0x0307
2460 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_BSD
,DBG_BSD_EXCP_SC
)); //0x040c
2461 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_BSD
,DBG_BSD_PROC
)); //0x0401
2462 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_BSD
,DBG_BSD_SC_EXTENDED_INFO
)); //0x040e
2463 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_BSD
,DBG_BSD_SC_EXTENDED_INFO2
)); //0x040f
2465 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_CORESTORAGE
,DBG_CS_IO
)); //0x0a00
2466 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(DBG_CORESTORAGE
, 1)); //0x0a01 for P_SCCS_SYNC_DIS
2468 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(FILEMGR_CLASS
, 0)); //Carbon File Manager
2469 setbit(type_filter_bitmap
, ENCODE_CSC_LOW(FILEMGR_CLASS
, 1)); //Carbon File Manager
2472 int mib
[] = { CTL_KERN
, KERN_KDEBUG
, KERN_KDSET_TYPEFILTER
};
2473 size_t needed
= KDBG_TYPEFILTER_BITMAP_SIZE
;
2474 if(sysctl(mib
, 3, type_filter_bitmap
, &needed
, NULL
, 0)) {
2475 quit("trace facility failure, KERN_KDSET_TYPEFILTER\n");
2480 set_pidcheck(int pid
, int on_off
)
2484 kr
.type
= KDBG_TYPENONE
;
2487 needed
= sizeof(kd_regtype
);
2489 mib
[1] = KERN_KDEBUG
;
2490 mib
[2] = KERN_KDPIDTR
;
2495 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0) {
2497 fprintf(stderr
, "pid %d does not exist\n", pid
);
2503 * on_off == 0 turns off pid exclusion
2504 * on_off == 1 turns on pid exclusion
2507 set_pidexclude(int pid
, int on_off
)
2513 kr
.type
= KDBG_TYPENONE
;
2516 needed
= sizeof(kd_regtype
);
2518 mib
[1] = KERN_KDEBUG
;
2519 mib
[2] = KERN_KDPIDEX
;
2524 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0) {
2526 fprintf(stderr
, "pid %d does not exist\n", pid
);
2531 get_bufinfo(kbufinfo_t
*val
)
2533 needed
= sizeof (*val
);
2535 mib
[1] = KERN_KDEBUG
;
2536 mib
[2] = KERN_KDGETBUF
;
2539 mib
[5] = 0; /* no flags */
2541 if (sysctl(mib
, 3, val
, &needed
, 0, 0) < 0)
2542 quit("trace facility failure, KERN_KDGETBUF\n");
2552 mib
[1] = KERN_KDEBUG
;
2553 mib
[2] = KERN_KDREMOVE
; /* protocol */
2556 mib
[5] = 0; /* no flags */
2558 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0) {
2559 set_remove_flag
= 0;
2562 quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n");
2564 quit("trace facility failure, KERN_KDREMOVE\n");
2572 kr
.type
= KDBG_RANGETYPE
;
2575 needed
= sizeof(kd_regtype
);
2578 mib
[1] = KERN_KDEBUG
;
2579 mib
[2] = KERN_KDSETREG
;
2582 mib
[5] = 0; /* no flags */
2584 if (sysctl(mib
, 3, &kr
, &needed
, NULL
, 0) < 0)
2585 quit("trace facility failure, KERN_KDSETREG\n");
2588 mib
[1] = KERN_KDEBUG
;
2589 mib
[2] = KERN_KDSETUP
;
2592 mib
[5] = 0; /* no flags */
2594 if (sysctl(mib
, 3, NULL
, &needed
, NULL
, 0) < 0)
2595 quit("trace facility failure, KERN_KDSETUP\n");
2605 uint32_t my_buffer_size
= 0;
2608 get_bufinfo(&bufinfo
);
2610 my_buffer_size
= num_events
* sizeof(kd_buf
);
2617 needed
= bufinfo
.nkdbufs
* sizeof(kd_buf
);
2620 mib
[1] = KERN_KDEBUG
;
2621 mib
[2] = KERN_KDREADTR
;
2624 mib
[5] = 0; /* no flags */
2626 if (sysctl(mib
, 3, my_buffer
, &needed
, NULL
, 0) < 0)
2627 quit("trace facility failure, KERN_KDREADTR\n");
2630 if (count
> (num_events
/ 8)) {
2631 if (usleep_ms
> USLEEP_BEHIND
)
2632 usleep_ms
= USLEEP_BEHIND
;
2633 else if (usleep_ms
> USLEEP_MIN
)
2636 } else if (count
< (num_events
/ 16)) {
2637 if (usleep_ms
< USLEEP_MAX
)
2641 if (bufinfo
.flags
& KDBG_WRAPPED
) {
2642 fprintf(stderr
, "fs_usage: buffer overrun, events generated too quickly: %d\n", count
);
2644 delete_all_events();
2654 if ((bytes_read
= read(RAW_fd
, my_buffer
, my_buffer_size
)) < sizeof(kd_buf
))
2656 count
= bytes_read
/ sizeof(kd_buf
);
2658 kd
= (kd_buf
*)my_buffer
;
2660 fprintf(stderr
, "READTR returned %d items\n", count
);
2662 for (i
= 0; i
< count
; i
++) {
2676 thread
= kd
[i
].arg5
;
2677 debugid
= kd
[i
].debugid
;
2678 type
= kd
[i
].debugid
& DBG_FUNC_MASK
;
2680 now
= kdbg_get_timestamp(&kd
[i
]);
2682 if (i
== 0 && !RAW_flag
) {
2684 curr_time
= time((long *)0);
2686 * Compute bias seconds after each trace buffer read.
2687 * This helps resync timestamps with the system clock
2688 * in the event of a system sleep.
2690 if (bias_secs
== 0 || curr_time
< last_time
|| curr_time
> (last_time
+ 2)) {
2691 l_usecs
= (long long)(now
/ divisor
);
2692 secs
= l_usecs
/ 1000000;
2693 bias_secs
= curr_time
- secs
;
2696 if (RAW_flag
&& bias_now
== 0.0)
2699 if ((type
& P_DISKIO_MASK
) == P_DISKIO
) {
2700 insert_diskio(type
, kd
[i
].arg1
, kd
[i
].arg2
, kd
[i
].arg3
, kd
[i
].arg4
, thread
, (double)now
);
2703 if ((type
& P_DISKIO_MASK
) == P_DISKIO_DONE
) {
2704 if ((dio
= complete_diskio(kd
[i
].arg1
, kd
[i
].arg4
, kd
[i
].arg3
, thread
, (double)now
))) {
2705 dio
->vnodeid
= kd
[i
].arg2
;
2712 if ((type
& CLASS_MASK
) == P_CS_Class
) {
2714 // the usual DBG_FUNC_START/END does not work for i/o since it will
2715 // return on a different thread, this code uses the P_CS_IO_Done (0x4) bit
2716 // instead. the trace command doesn't know how handle either method
2717 // (unmatched start/end or 0x4) but works a little better this way.
2719 int cs_type
= type
& P_CS_Type_Mask
; // strip out the done bit
2720 bool start
= (type
& P_CS_IO_Done
) != P_CS_IO_Done
;
2724 case P_CS_ReadChunk
:
2725 case P_CS_WriteChunk
:
2727 case P_CS_MetaWrite
:
2729 insert_diskio(cs_type
, kd
[i
].arg2
, kd
[i
].arg1
, kd
[i
].arg3
, kd
[i
].arg4
, thread
, (double)now
);
2731 if ((dio
= complete_diskio(kd
[i
].arg2
, kd
[i
].arg4
, kd
[i
].arg3
, thread
, (double)now
))) {
2738 case P_CS_TransformRead
:
2739 case P_CS_TransformWrite
:
2740 case P_CS_MigrationRead
:
2741 case P_CS_MigrationWrite
:
2743 insert_diskio(cs_type
, kd
[i
].arg2
, CS_DEV
, kd
[i
].arg3
, kd
[i
].arg4
, thread
, (double)now
);
2745 if ((dio
= complete_diskio(kd
[i
].arg2
, kd
[i
].arg4
, kd
[i
].arg3
, thread
, (double)now
))) {
2752 case P_CS_SYNC_DISK
:
2754 enter_event(thread
, cs_type
, &kd
[i
], NULL
, (double)now
);
2756 exit_event(" SyncCacheCS", thread
, cs_type
, kd
[i
].arg1
, 0, 0, 0, FMT_SYNC_DISK_CS
, (double)now
);
2761 continue; // ignore other cs timestamps
2766 case TRACE_DATA_NEWTHREAD
:
2768 if ((ti
= add_event(thread
, TRACE_DATA_NEWTHREAD
)) == NULL
)
2770 ti
->child_thread
= kd
[i
].arg1
;
2771 ti
->pid
= kd
[i
].arg2
;
2775 case TRACE_STRING_NEWTHREAD
:
2776 if ((ti
= find_event(thread
, TRACE_DATA_NEWTHREAD
)) == (struct th_info
*)0)
2779 create_map_entry(ti
->child_thread
, ti
->pid
, (char *)&kd
[i
].arg1
);
2784 case TRACE_DATA_EXEC
:
2785 if ((ti
= add_event(thread
, TRACE_DATA_EXEC
)) == NULL
)
2788 ti
->pid
= kd
[i
].arg1
;
2791 case TRACE_STRING_EXEC
:
2792 if ((ti
= find_event(thread
, BSC_execve
))) {
2793 if (ti
->lookups
[0].pathname
[0])
2794 exit_event("execve", thread
, BSC_execve
, 0, 0, 0, 0, FMT_DEFAULT
, (double)now
);
2796 } else if ((ti
= find_event(thread
, BSC_posix_spawn
))) {
2797 if (ti
->lookups
[0].pathname
[0])
2798 exit_event("posix_spawn", thread
, BSC_posix_spawn
, 0, 0, 0, 0, FMT_DEFAULT
, (double)now
);
2800 if ((ti
= find_event(thread
, TRACE_DATA_EXEC
)) == (struct th_info
*)0)
2803 create_map_entry(thread
, ti
->pid
, (char *)&kd
[i
].arg1
);
2808 case BSC_thread_terminate
:
2809 delete_map_entry(thread
);
2816 kd
[i
].arg1
= kd
[i
].arg2
>> 8;
2821 if (kd
[i
].arg4
& MAP_ANON
)
2827 case MACH_stkhandoff
:
2828 mark_thread_waited(thread
);
2832 case BC_IO_HIT_STALLED
:
2834 case BC_IO_MISS_CUT_THROUGH
:
2835 case BC_PLAYBACK_IO
:
2836 if ((dio
= find_diskio(kd
[i
].arg1
)) != NULL
)
2837 dio
->bc_info
= type
;
2840 case HFS_modify_block_end
:
2841 if ((ti
= find_event(thread
, 0))) {
2843 add_meta_name(kd
[i
].arg2
, ti
->nameptr
);
2848 add_vnode_name(kd
[i
].arg2
, find_vnode_name(kd
[i
].arg1
));
2852 if ((ti
= find_event(thread
, 0)) == (struct th_info
*)0)
2855 if (debugid
& DBG_FUNC_START
) {
2857 if (ti
->in_hfs_update
) {
2858 ti
->pn_work_index
= (MAX_PATHNAMES
- 1);
2860 if (ti
->pn_scall_index
< MAX_SCALL_PATHNAMES
)
2861 ti
->pn_work_index
= ti
->pn_scall_index
;
2865 sargptr
= &ti
->lookups
[ti
->pn_work_index
].pathname
[0];
2867 ti
->vnodeid
= kd
[i
].arg1
;
2869 *sargptr
++ = kd
[i
].arg2
;
2870 *sargptr
++ = kd
[i
].arg3
;
2871 *sargptr
++ = kd
[i
].arg4
;
2873 * NULL terminate the 'string'
2877 ti
->pathptr
= sargptr
;
2879 sargptr
= ti
->pathptr
;
2882 * We don't want to overrun our pathname buffer if the
2883 * kernel sends us more VFS_LOOKUP entries than we can
2884 * handle and we only handle 2 pathname lookups for
2885 * a given system call
2890 if ((uintptr_t)sargptr
< (uintptr_t)&ti
->lookups
[ti
->pn_work_index
].pathname
[NUMPARMS
]) {
2892 *sargptr
++ = kd
[i
].arg1
;
2893 *sargptr
++ = kd
[i
].arg2
;
2894 *sargptr
++ = kd
[i
].arg3
;
2895 *sargptr
++ = kd
[i
].arg4
;
2897 * NULL terminate the 'string'
2902 if (debugid
& DBG_FUNC_END
) {
2904 ti
->nameptr
= add_vnode_name(ti
->vnodeid
, &ti
->lookups
[ti
->pn_work_index
].pathname
[0]);
2906 if (ti
->pn_work_index
== ti
->pn_scall_index
) {
2908 ti
->pn_scall_index
++;
2910 if (ti
->pn_scall_index
< MAX_SCALL_PATHNAMES
)
2911 ti
->pathptr
= &ti
->lookups
[ti
->pn_scall_index
].pathname
[0];
2916 ti
->pathptr
= sargptr
;
2921 if (debugid
& DBG_FUNC_START
) {
2924 if ((type
& CLASS_MASK
) == FILEMGR_BASE
) {
2926 index
= filemgr_index(type
);
2928 if (index
>= MAX_FILEMGR
)
2931 if ((p
= filemgr_calls
[index
].fm_name
) == NULL
)
2936 enter_event(thread
, type
, &kd
[i
], p
, (double)now
);
2943 exit_event(" THROTTLED", thread
, type
, 0, 0, 0, 0, FMT_DEFAULT
, (double)now
);
2947 exit_event(" HFS_update", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, FMT_HFS_update
, (double)now
);
2950 case SPEC_unmap_info
:
2951 if (check_filter_mode(NULL
, SPEC_unmap_info
, 0, 0, "SPEC_unmap_info"))
2952 format_print(NULL
, " TrimExtent", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, kd
[i
].arg3
, 0, FMT_UNMAP_INFO
, now
, now
, 0, "", NULL
);
2956 if (kd
[i
].arg2
== DKIOCSYNCHRONIZECACHE
)
2957 exit_event("IOCTL", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, FMT_IOCTL_SYNCCACHE
, (double)now
);
2958 else if (kd
[i
].arg2
== DKIOCUNMAP
)
2959 exit_event("IOCTL", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, FMT_IOCTL_UNMAP
, (double)now
);
2960 else if (kd
[i
].arg2
== DKIOCSYNCHRONIZE
&& (debugid
& DBG_FUNC_ALL
) == DBG_FUNC_NONE
)
2961 exit_event("IOCTL", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, kd
[i
].arg3
, 0, FMT_IOCTL_SYNC
, (double)now
);
2963 if ((ti
= find_event(thread
, type
)))
2970 exit_event("PAGE_OUT_ANON", thread
, type
, 0, kd
[i
].arg1
, 0, 0, FMT_PGOUT
, (double)now
);
2972 exit_event("PAGE_OUT_FILE", thread
, type
, 0, kd
[i
].arg1
, 0, 0, FMT_PGOUT
, (double)now
);
2976 if (kd
[i
].arg4
== DBG_PAGEIN_FAULT
)
2977 exit_event("PAGE_IN", thread
, type
, 0, kd
[i
].arg1
, kd
[i
].arg2
, 0, FMT_PGIN
, (double)now
);
2978 else if (kd
[i
].arg4
== DBG_PAGEINV_FAULT
)
2979 exit_event("PAGE_IN_FILE", thread
, type
, 0, kd
[i
].arg1
, kd
[i
].arg2
, 0, FMT_PGIN
, (double)now
);
2980 else if (kd
[i
].arg4
== DBG_PAGEIND_FAULT
)
2981 exit_event("PAGE_IN_ANON", thread
, type
, 0, kd
[i
].arg1
, kd
[i
].arg2
, 0, FMT_PGIN
, (double)now
);
2982 else if (kd
[i
].arg4
== DBG_CACHE_HIT_FAULT
)
2983 exit_event("CACHE_HIT", thread
, type
, 0, kd
[i
].arg1
, kd
[i
].arg2
, 0, FMT_CACHEHIT
, (double)now
);
2985 if ((ti
= find_event(thread
, type
)))
2991 exit_event("map_fd", thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, 0, 0, FMT_FD
, (double)now
);
2994 case BSC_mmap_extended
:
2995 case BSC_mmap_extended2
:
2996 case BSC_msync_extended
:
2997 case BSC_pread_extended
:
2998 case BSC_pwrite_extended
:
2999 extend_syscall(thread
, type
, &kd
[i
]);
3003 if ((type
& CSC_MASK
) == BSC_BASE
) {
3005 if ((index
= BSC_INDEX(type
)) >= MAX_BSD_SYSCALL
)
3008 if (bsd_syscalls
[index
].sc_name
) {
3009 exit_event(bsd_syscalls
[index
].sc_name
, thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, kd
[i
].arg3
, kd
[i
].arg4
,
3010 bsd_syscalls
[index
].sc_format
, (double)now
);
3012 if (type
== BSC_exit
)
3013 delete_map_entry(thread
);
3015 } else if ((type
& CLASS_MASK
) == FILEMGR_BASE
) {
3017 if ((index
= filemgr_index(type
)) >= MAX_FILEMGR
)
3020 if (filemgr_calls
[index
].fm_name
) {
3021 exit_event(filemgr_calls
[index
].fm_name
, thread
, type
, kd
[i
].arg1
, kd
[i
].arg2
, kd
[i
].arg3
, kd
[i
].arg4
,
3022 FMT_DEFAULT
, (double)now
);
3031 enter_event_now(uintptr_t thread
, int type
, kd_buf
*kd
, char *name
, double now
)
3045 if ((ti
= add_event(thread
, type
)) == NULL
)
3049 ti
->arg1
= kd
->arg1
;
3050 ti
->arg2
= kd
->arg2
;
3051 ti
->arg3
= kd
->arg3
;
3052 ti
->arg4
= kd
->arg4
;
3057 ti
->in_hfs_update
= 1;
3061 if ((type
& CLASS_MASK
) == FILEMGR_BASE
&&
3062 (!RAW_flag
|| (now
>= start_time
&& now
<= end_time
))) {
3064 filemgr_in_progress
++;
3068 l_usecs
= (long long)((now
- bias_now
) / divisor
);
3069 l_usecs
+= (sample_TOD_secs
* 1000000) + sample_TOD_usecs
;
3071 l_usecs
= (long long)(now
/ divisor
);
3072 secs
= l_usecs
/ 1000000;
3073 curr_time
= bias_secs
+ secs
;
3075 sprintf(buf
, "%-8.8s", &(ctime(&curr_time
)[11]));
3076 tsclen
= strlen(buf
);
3078 if (columns
> MAXCOLS
|| wideflag
) {
3079 usecs
= l_usecs
- (long long)((long long)secs
* 1000000);
3080 sprintf(&buf
[tsclen
], ".%06ld", (long)usecs
);
3081 tsclen
= strlen(buf
);
3085 * Print timestamp column
3089 tme
= find_map_entry(thread
);
3091 sprintf(buf
, " %-25.25s ", name
);
3092 nmclen
= strlen(buf
);
3095 sprintf(buf
, "(%d, 0x%lx, 0x%lx, 0x%lx)", (short)kd
->arg1
, kd
->arg2
, kd
->arg3
, kd
->arg4
);
3096 argsclen
= strlen(buf
);
3099 * Calculate white space out to command
3101 if (columns
> MAXCOLS
|| wideflag
) {
3102 clen
= columns
- (tsclen
+ nmclen
+ argsclen
+ 20 + 11);
3104 clen
= columns
- (tsclen
+ nmclen
+ argsclen
+ 12);
3107 printf("%s", buf
); /* print the kdargs */
3108 memset(buf
, ' ', clen
);
3112 else if ((argsclen
+ clen
) > 0) {
3114 * no room so wipe out the kdargs
3116 memset(buf
, ' ', (argsclen
+ clen
));
3117 buf
[argsclen
+ clen
] = '\0';
3120 if (columns
> MAXCOLS
|| wideflag
)
3121 printf("%s.%d\n", tme
->tm_command
, (int)thread
);
3123 printf("%-12.12s\n", tme
->tm_command
);
3125 printf(" %-24.24s (%5d, %#lx, 0x%lx, 0x%lx)\n", name
, (short)kd
->arg1
, kd
->arg2
, kd
->arg3
, kd
->arg4
);
3131 enter_event(uintptr_t thread
, int type
, kd_buf
*kd
, char *name
, double now
)
3137 case P_CS_SYNC_DISK
:
3144 enter_event_now(thread
, type
, kd
, name
, now
);
3148 if ((type
& CSC_MASK
) == BSC_BASE
) {
3150 if ((index
= BSC_INDEX(type
)) >= MAX_BSD_SYSCALL
)
3153 if (bsd_syscalls
[index
].sc_name
)
3154 enter_event_now(thread
, type
, kd
, name
, now
);
3157 if ((type
& CLASS_MASK
) == FILEMGR_BASE
) {
3159 if ((index
= filemgr_index(type
)) >= MAX_FILEMGR
)
3162 if (filemgr_calls
[index
].fm_name
)
3163 enter_event_now(thread
, type
, kd
, name
, now
);
3169 * Handle system call extended trace data.
3171 * Wipe out the kd args that were collected upon syscall_entry
3172 * because it is the extended info that we really want, and it
3173 * is all we really need.
3177 extend_syscall(uintptr_t thread
, int type
, kd_buf
*kd
)
3182 case BSC_mmap_extended
:
3183 if ((ti
= find_event(thread
, BSC_mmap
)) == (struct th_info
*)0)
3185 ti
->arg8
= ti
->arg3
; /* save protection */
3186 ti
->arg1
= kd
->arg1
; /* the fd */
3187 ti
->arg3
= kd
->arg2
; /* bottom half address */
3188 ti
->arg5
= kd
->arg3
; /* bottom half size */
3190 case BSC_mmap_extended2
:
3191 if ((ti
= find_event(thread
, BSC_mmap
)) == (struct th_info
*)0)
3193 ti
->arg2
= kd
->arg1
; /* top half address */
3194 ti
->arg4
= kd
->arg2
; /* top half size */
3195 ti
->arg6
= kd
->arg3
; /* top half file offset */
3196 ti
->arg7
= kd
->arg4
; /* bottom half file offset */
3198 case BSC_msync_extended
:
3199 if ((ti
= find_event(thread
, BSC_msync
)) == (struct th_info
*)0) {
3200 if ((ti
= find_event(thread
, BSC_msync_nocancel
)) == (struct th_info
*)0)
3203 ti
->arg4
= kd
->arg1
; /* top half address */
3204 ti
->arg5
= kd
->arg2
; /* top half size */
3206 case BSC_pread_extended
:
3207 if ((ti
= find_event(thread
, BSC_pread
)) == (struct th_info
*)0) {
3208 if ((ti
= find_event(thread
, BSC_pread_nocancel
)) == (struct th_info
*)0)
3211 ti
->arg1
= kd
->arg1
; /* the fd */
3212 ti
->arg2
= kd
->arg2
; /* nbytes */
3213 ti
->arg3
= kd
->arg3
; /* top half offset */
3214 ti
->arg4
= kd
->arg4
; /* bottom half offset */
3216 case BSC_pwrite_extended
:
3217 if ((ti
= find_event(thread
, BSC_pwrite
)) == (struct th_info
*)0) {
3218 if ((ti
= find_event(thread
, BSC_pwrite_nocancel
)) == (struct th_info
*)0)
3221 ti
->arg1
= kd
->arg1
; /* the fd */
3222 ti
->arg2
= kd
->arg2
; /* nbytes */
3223 ti
->arg3
= kd
->arg3
; /* top half offset */
3224 ti
->arg4
= kd
->arg4
; /* bottom half offset */
3233 exit_event(char *sc_name
, uintptr_t thread
, int type
, uintptr_t arg1
, uintptr_t arg2
, uintptr_t arg3
, uintptr_t arg4
,
3234 int format
, double now
)
3238 if ((ti
= find_event(thread
, type
)) == (struct th_info
*)0)
3243 if (check_filter_mode(ti
, type
, arg1
, arg2
, sc_name
))
3244 format_print(ti
, sc_name
, thread
, type
, arg1
, arg2
, arg3
, arg4
, format
, now
, ti
->stime
, ti
->waited
, (char *)&ti
->lookups
[0].pathname
[0], NULL
);
3249 ti
->in_hfs_update
= 0;
3252 if ((type
& CLASS_MASK
) == FILEMGR_BASE
) {
3255 if (filemgr_in_progress
> 0)
3256 filemgr_in_progress
--;
3263 get_mode_nibble(char * buf
, int smode
, int special
, char x_on
, char x_off
)
3282 get_mode_string(int mode
, char *buf
)
3284 memset(buf
, '-', 9);
3287 get_mode_nibble(&buf
[6], mode
, (mode
& 01000), 't', 'T');
3288 get_mode_nibble(&buf
[3], (mode
>>3), (mode
& 02000), 's', 'S');
3289 get_mode_nibble(&buf
[0], (mode
>>6), (mode
& 04000), 's', 'S');
3293 int clip_64bit(char *s
, uint64_t value
)
3297 if ( (value
& 0xff00000000000000LL
) )
3298 clen
= printf("%s0x%16.16qx", s
, value
);
3299 else if ( (value
& 0x00ff000000000000LL
) )
3300 clen
= printf("%s0x%14.14qx ", s
, value
);
3301 else if ( (value
& 0x0000ff0000000000LL
) )
3302 clen
= printf("%s0x%12.12qx ", s
, value
);
3303 else if ( (value
& 0x000000ff00000000LL
) )
3304 clen
= printf("%s0x%10.10qx ", s
, value
);
3306 clen
= printf("%s0x%8.8qx ", s
, value
);
3313 format_print(struct th_info
*ti
, char *sc_name
, uintptr_t thread
, int type
, uintptr_t arg1
, uintptr_t arg2
, uintptr_t arg3
, uintptr_t arg4
,
3314 int format
, double now
, double stime
, int waited
, char *pathname
, struct diskio
*dio
)
3329 char *framework_name
;
3330 char *framework_type
;
3334 char cs_diskname
[32];
3336 static char timestamp
[32];
3337 static int last_timestamp
= -1;
3338 static int timestamp_len
= 0;
3342 // <rdar://problem/19852325> Filter out WindowServer/xcpm iocts in fs_usage
3343 if (format
== FMT_IOCTL
&& ti
->arg2
== 0xc030581d)
3347 l_usecs
= (long long)((now
- bias_now
) / divisor
);
3349 if ((double)l_usecs
< start_time
|| (double)l_usecs
> end_time
)
3352 l_usecs
+= (sample_TOD_secs
* 1000000) + sample_TOD_usecs
;
3355 l_usecs
= (long long)(now
/ divisor
);
3356 secs
= l_usecs
/ 1000000;
3357 curr_time
= bias_secs
+ secs
;
3362 command_name
= dio
->issuing_command
;
3366 if ((tme
= find_map_entry(thread
)))
3367 command_name
= tme
->tm_command
;
3369 if (last_timestamp
!= curr_time
) {
3370 timestamp_len
= sprintf(timestamp
, "%-8.8s", &(ctime(&curr_time
)[11]));
3371 last_timestamp
= curr_time
;
3373 if (columns
> MAXCOLS
|| wideflag
) {
3376 tlen
= timestamp_len
;
3378 usec
= (l_usecs
- (long long)((long long)secs
* 1000000));
3380 sprintf(×tamp
[tlen
], ".%06ld", (long)usec
);
3383 timestamp
[tlen
] = '\0';
3385 if (filemgr_in_progress
) {
3386 if (class != FILEMGR_CLASS
) {
3387 if (find_event(thread
, -1))
3394 if ((class == FILEMGR_CLASS
) && (columns
> MAXCOLS
|| wideflag
))
3395 clen
= printf("%s %-20.20s", timestamp
, sc_name
);
3396 else if (in_filemgr
)
3397 clen
= printf("%s %-15.15s", timestamp
, sc_name
);
3399 clen
= printf("%s %-17.17s", timestamp
, sc_name
);
3402 framework_name
= NULL
;
3404 if (columns
> MAXCOLS
|| wideflag
) {
3406 off_t offset_reassembled
= 0LL;
3414 * pathname based system calls or
3415 * calls with no fd or pathname (i.e. sync)
3418 clen
+= printf(" [%3d] ", arg1
);
3420 clen
+= printf(" ");
3425 * fd based system call... no I/O
3428 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
3430 clen
+= printf(" F=%-3d", ti
->arg1
);
3438 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
3440 clen
+= printf(" F=%-3d F=%-3d", ti
->arg1
, arg2
);
3445 * system calls with fd's that return an I/O completion count
3448 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
3450 clen
+= printf(" F=%-3d B=0x%-6x", ti
->arg1
, arg2
);
3457 user_addr
= ((uint64_t)arg2
<< 32) | (uint32_t)arg3
;
3459 lookup_name(user_addr
, &framework_type
, &framework_name
);
3460 clen
+= clip_64bit(" A=", user_addr
);
3467 user_addr
= ((uint64_t)arg2
<< 32) | (uint32_t)arg3
;
3469 lookup_name(user_addr
, &framework_type
, &framework_name
);
3470 clen
+= clip_64bit(" A=", user_addr
);
3477 clen
+= printf(" B=0x%-8x", arg2
);
3480 case FMT_HFS_update
:
3483 int sflag
= (int)arg2
;
3485 memset(sbuf
, '_', 6);
3502 clen
+= printf(" (%s) ", sbuf
);
3504 pathname
= find_vnode_name(arg1
);
3515 clen
+= printf(" D=0x%8.8x [%3d]", dio
->blkno
, dio
->io_errno
);
3518 clen
+= printf(" D=0x%8.8x B=0x%-6x BC:%s /dev/%s ", dio
->blkno
, dio
->iosize
, BC_STR(dio
->bc_info
), find_disk_name(dio
->dev
));
3520 clen
+= printf(" D=0x%8.8x B=0x%-6x /dev/%s ", dio
->blkno
, dio
->iosize
, find_disk_name(dio
->dev
));
3523 if (!(type
& P_DISKIO_READ
))
3524 pathname
= find_meta_name(dio
->blkno
);
3526 pathname
= find_vnode_name(dio
->vnodeid
);
3536 clen
+= printf(" D=0x%8.8x [%3d]", dio
->blkno
, dio
->io_errno
);
3538 clen
+= printf(" D=0x%8.8x B=0x%-6x /dev/%s", dio
->blkno
, dio
->iosize
, generate_cs_disk_name(dio
->dev
, &cs_diskname
[0]));
3541 case FMT_SYNC_DISK_CS
:
3543 * physical disk sync cache
3545 clen
+= printf(" /dev/%s", generate_cs_disk_name(arg1
, &cs_diskname
[0]));
3558 if (ti
->arg3
& MS_ASYNC
)
3559 mlen
+= sprintf(&buf
[mlen
], "MS_ASYNC | ");
3561 mlen
+= sprintf(&buf
[mlen
], "MS_SYNC | ");
3563 if (ti
->arg3
& MS_INVALIDATE
)
3564 mlen
+= sprintf(&buf
[mlen
], "MS_INVALIDATE | ");
3565 if (ti
->arg3
& MS_KILLPAGES
)
3566 mlen
+= sprintf(&buf
[mlen
], "MS_KILLPAGES | ");
3567 if (ti
->arg3
& MS_DEACTIVATE
)
3568 mlen
+= sprintf(&buf
[mlen
], "MS_DEACTIVATE | ");
3570 if (ti
->arg3
& ~(MS_ASYNC
| MS_SYNC
| MS_INVALIDATE
| MS_KILLPAGES
| MS_DEACTIVATE
))
3571 mlen
+= sprintf(&buf
[mlen
], "UNKNOWN | ");
3574 buf
[mlen
- 3] = '\0';
3577 clen
+= printf(" [%3d]", arg1
);
3579 user_addr
= (((off_t
)(unsigned int)(ti
->arg4
)) << 32) | (unsigned int)(ti
->arg1
);
3580 clen
+= clip_64bit(" A=", user_addr
);
3582 user_size
= (((off_t
)(unsigned int)(ti
->arg5
)) << 32) | (unsigned int)(ti
->arg2
);
3584 clen
+= printf(" B=0x%-16qx <%s>", user_size
, buf
);
3598 if (ti
->arg2
& LOCK_SH
)
3599 mlen
+= sprintf(&buf
[mlen
], "LOCK_SH | ");
3600 if (ti
->arg2
& LOCK_EX
)
3601 mlen
+= sprintf(&buf
[mlen
], "LOCK_EX | ");
3602 if (ti
->arg2
& LOCK_NB
)
3603 mlen
+= sprintf(&buf
[mlen
], "LOCK_NB | ");
3604 if (ti
->arg2
& LOCK_UN
)
3605 mlen
+= sprintf(&buf
[mlen
], "LOCK_UN | ");
3607 if (ti
->arg2
& ~(LOCK_SH
| LOCK_EX
| LOCK_NB
| LOCK_UN
))
3608 mlen
+= sprintf(&buf
[mlen
], "UNKNOWN | ");
3611 buf
[mlen
- 3] = '\0';
3614 clen
+= printf(" F=%-3d[%3d] <%s>", ti
->arg1
, arg1
, buf
);
3616 clen
+= printf(" F=%-3d <%s>", ti
->arg1
, buf
);
3630 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
3632 clen
+= printf(" F=%-3d", ti
->arg1
);
3696 case F_PATHPKG_CHECK
:
3697 p
= "PATHPKG_CHECK";
3711 case F_CHECK_OPENEVT
:
3712 p
= "CHECK_OPENEVT";
3722 case F_GLOBAL_NOCACHE
:
3724 p
= "CACHING OFF (GLOBAL)";
3726 p
= "CACHING ON (GLOBAL)";
3732 clen
+= printf(" <%s>", p
);
3734 clen
+= printf(" <%s> F=%d", p
, fd
);
3736 clen
+= printf(" <CMD=%d>", ti
->arg2
);
3747 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
3749 clen
+= printf(" F=%-3d", ti
->arg1
);
3751 clen
+= printf(" <CMD=0x%x>", ti
->arg2
);
3756 case FMT_IOCTL_SYNC
:
3761 clen
+= printf(" <DKIOCSYNCHRONIZE> B=%d /dev/%s", arg3
, find_disk_name(arg1
));
3766 case FMT_IOCTL_SYNCCACHE
:
3771 clen
+= printf(" <DKIOCSYNCHRONIZECACHE> /dev/%s", find_disk_name(arg1
));
3776 case FMT_IOCTL_UNMAP
:
3781 clen
+= printf(" <DKIOCUNMAP> /dev/%s", find_disk_name(arg1
));
3786 case FMT_UNMAP_INFO
:
3788 clen
+= printf(" D=0x%8.8x B=0x%-6x /dev/%s", arg2
, arg3
, find_disk_name(arg1
));
3798 clen
+= printf(" [%3d]", arg1
);
3800 clen
+= printf(" S=%-3d", arg2
);
3807 * pread, pwrite, lseek
3809 clen
+= printf(" F=%-3d", ti
->arg1
);
3812 clen
+= printf("[%3d] ", arg1
);
3814 if (format
== FMT_PREAD
)
3815 clen
+= printf(" B=0x%-8x ", arg2
);
3817 clen
+= printf(" ");
3819 if (format
== FMT_PREAD
)
3820 offset_reassembled
= (((off_t
)(unsigned int)(ti
->arg3
)) << 32) | (unsigned int)(ti
->arg4
);
3823 offset_reassembled
= (((off_t
)(unsigned int)(arg2
)) << 32) | (unsigned int)(arg3
);
3825 offset_reassembled
= (((off_t
)(unsigned int)(arg3
)) << 32) | (unsigned int)(arg2
);
3827 clen
+= clip_64bit("O=", offset_reassembled
);
3829 if (format
== FMT_LSEEK
) {
3832 if (ti
->arg4
== SEEK_SET
)
3834 else if (ti
->arg4
== SEEK_CUR
)
3836 else if (ti
->arg4
== SEEK_END
)
3841 clen
+= printf(" <%s>", mode
);
3849 clen
+= printf(" F=%-3d ", ti
->arg1
);
3852 clen
+= printf("[%3d] ", arg1
);
3855 user_addr
= (((off_t
)(unsigned int)(ti
->arg2
)) << 32) | (unsigned int)(ti
->arg3
);
3857 clen
+= clip_64bit("A=", user_addr
);
3859 offset_reassembled
= (((off_t
)(unsigned int)(ti
->arg6
)) << 32) | (unsigned int)(ti
->arg7
);
3861 clen
+= clip_64bit("O=", offset_reassembled
);
3863 user_size
= (((off_t
)(unsigned int)(ti
->arg4
)) << 32) | (unsigned int)(ti
->arg5
);
3865 clen
+= printf("B=0x%-16qx", user_size
);
3867 clen
+= printf(" <");
3869 if (ti
->arg8
& PROT_READ
)
3870 clen
+= printf("READ");
3872 if (ti
->arg8
& PROT_WRITE
)
3873 clen
+= printf("|WRITE");
3875 if (ti
->arg8
& PROT_EXEC
)
3876 clen
+= printf("|EXEC");
3878 clen
+= printf(">");
3885 * ftruncate, truncate
3887 if (format
== FMT_FTRUNC
)
3888 clen
+= printf(" F=%-3d", ti
->arg1
);
3890 clen
+= printf(" ");
3893 clen
+= printf("[%3d]", arg1
);
3896 offset_reassembled
= (((off_t
)(unsigned int)(ti
->arg2
)) << 32) | (unsigned int)(ti
->arg3
);
3898 offset_reassembled
= (((off_t
)(unsigned int)(ti
->arg3
)) << 32) | (unsigned int)(ti
->arg2
);
3900 clen
+= clip_64bit(" O=", offset_reassembled
);
3913 if (format
== FMT_FCHFLAGS
) {
3915 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
3917 clen
+= printf(" F=%-3d", ti
->arg1
);
3920 clen
+= printf(" [%3d] ", arg1
);
3925 if (ti
->arg2
& UF_NODUMP
)
3926 mlen
+= sprintf(&buf
[mlen
], "UF_NODUMP | ");
3927 if (ti
->arg2
& UF_IMMUTABLE
)
3928 mlen
+= sprintf(&buf
[mlen
], "UF_IMMUTABLE | ");
3929 if (ti
->arg2
& UF_APPEND
)
3930 mlen
+= sprintf(&buf
[mlen
], "UF_APPEND | ");
3931 if (ti
->arg2
& UF_OPAQUE
)
3932 mlen
+= sprintf(&buf
[mlen
], "UF_OPAQUE | ");
3933 if (ti
->arg2
& SF_ARCHIVED
)
3934 mlen
+= sprintf(&buf
[mlen
], "SF_ARCHIVED | ");
3935 if (ti
->arg2
& SF_IMMUTABLE
)
3936 mlen
+= sprintf(&buf
[mlen
], "SF_IMMUTABLE | ");
3937 if (ti
->arg2
& SF_APPEND
)
3938 mlen
+= sprintf(&buf
[mlen
], "SF_APPEND | ");
3941 mlen
+= sprintf(&buf
[mlen
], "CLEAR_ALL_FLAGS | ");
3942 else if (ti
->arg2
& ~(UF_NODUMP
| UF_IMMUTABLE
| UF_APPEND
| SF_ARCHIVED
| SF_IMMUTABLE
| SF_APPEND
))
3943 mlen
+= sprintf(&buf
[mlen
], "UNKNOWN | ");
3952 memset(&buf
[mlen
], ' ', 19 - mlen
);
3955 clen
+= printf("%s", buf
);
3963 case FMT_FCHMOD_EXT
:
3969 * fchmod, fchmod_extended, chmod, chmod_extended
3973 if (format
== FMT_FCHMOD
|| format
== FMT_FCHMOD_EXT
) {
3975 clen
+= printf(" F=%-3d[%3d] ", ti
->arg1
, arg1
);
3977 clen
+= printf(" F=%-3d ", ti
->arg1
);
3980 clen
+= printf(" [%3d] ", arg1
);
3982 clen
+= printf(" ");
3984 if (format
== FMT_UMASK
)
3986 else if (format
== FMT_FCHMOD
|| format
== FMT_CHMOD
|| format
== FMT_CHMODAT
)
3991 get_mode_string(mode
, &buf
[0]);
3994 clen
+= printf("<%s> ", buf
);
3996 clen
+= printf("<%s>", buf
);
4007 memset(mode
, '_', 4);
4010 if (ti
->arg2
& R_OK
)
4012 if (ti
->arg2
& W_OK
)
4014 if (ti
->arg2
& X_OK
)
4016 if (ti
->arg2
== F_OK
)
4020 clen
+= printf(" [%3d] (%s) ", arg1
, mode
);
4022 clen
+= printf(" (%s) ", mode
);
4031 clen
+= printf(" [%3d] <FLGS=0x%x> ", arg1
, ti
->arg3
);
4033 clen
+= printf(" <FLGS=0x%x> ", ti
->arg3
);
4043 if (ti
->arg2
& MNT_FORCE
)
4044 mountflag
= "<FORCE>";
4049 clen
+= printf(" [%3d] %s ", arg1
, mountflag
);
4051 clen
+= printf(" %s ", mountflag
);
4065 memset(mode
, '_', 6);
4068 if (ti
->arg2
& O_RDWR
) {
4071 } else if (ti
->arg2
& O_WRONLY
)
4076 if (ti
->arg2
& O_CREAT
)
4079 if (ti
->arg2
& O_APPEND
)
4082 if (ti
->arg2
& O_TRUNC
)
4085 if (ti
->arg2
& O_EXCL
)
4089 clen
+= printf(" [%3d] (%s) ", arg1
, mode
);
4091 clen
+= printf(" F=%-3d (%s) ", arg2
, mode
);
4125 domain
= "AF_IMPLINK";
4136 type
= "SOCK_STREAM";
4140 type
= "SOCK_DGRAM";
4147 case SOCK_SEQPACKET
:
4148 type
= "SOCK_SEQPACKET";
4161 clen
+= printf(" [%3d] <%s, %s, 0x%x>", arg1
, domain
, type
, ti
->arg3
);
4163 clen
+= printf(" F=%-3d <%s, %s, 0x%x>", arg2
, domain
, type
, ti
->arg3
);
4170 * aio_fsync [errno] AIOCBP OP
4174 if (ti
->arg1
== O_SYNC
|| ti
->arg1
== 0)
4177 else if (ti
->arg1
== O_DSYNC
)
4184 clen
+= printf(" [%3d] P=0x%8.8x <%s>", arg1
, ti
->arg2
, op
);
4186 clen
+= printf(" P=0x%8.8x <%s>", ti
->arg2
, op
);
4190 case FMT_AIO_RETURN
:
4192 * aio_return [errno] AIOCBP IOSIZE
4195 clen
+= printf(" [%3d] P=0x%8.8x", arg1
, ti
->arg1
);
4197 clen
+= printf(" P=0x%8.8x B=0x%-8x", ti
->arg1
, arg2
);
4200 case FMT_AIO_SUSPEND
:
4202 * aio_suspend [errno] NENTS
4205 clen
+= printf(" [%3d] N=%d", arg1
, ti
->arg2
);
4207 clen
+= printf(" N=%d", ti
->arg2
);
4210 case FMT_AIO_CANCEL
:
4212 * aio_cancel [errno] FD or AIOCBP (if non-null)
4216 clen
+= printf(" [%3d] P=0x%8.8x", arg1
, ti
->arg2
);
4218 clen
+= printf(" P=0x%8.8x", ti
->arg2
);
4221 clen
+= printf(" F=%-3d[%3d]", ti
->arg1
, arg1
);
4223 clen
+= printf(" F=%-3d", ti
->arg1
);
4229 * aio_error, aio_read, aio_write [errno] AIOCBP
4232 clen
+= printf(" [%3d] P=0x%8.8x", arg1
, ti
->arg1
);
4234 clen
+= printf(" P=0x%8.8x", ti
->arg1
);
4237 case FMT_LIO_LISTIO
:
4240 * lio_listio [errno] NENTS MODE
4244 if (ti
->arg1
== LIO_NOWAIT
)
4246 else if (ti
->arg1
== LIO_WAIT
)
4252 clen
+= printf(" [%3d] N=%d <%s>", arg1
, ti
->arg3
, op
);
4254 clen
+= printf(" N=%d <%s>", ti
->arg3
, op
);
4262 * Calculate space available to print pathname
4264 if (columns
> MAXCOLS
|| wideflag
)
4265 clen
= columns
- (clen
+ 14 + 20 + 11);
4267 clen
= columns
- (clen
+ 14 + 12);
4269 if (class != FILEMGR_CLASS
&& !nopadding
)
4273 len
= sprintf(&buf
[0], " %s %s ", framework_type
, framework_name
);
4274 else if (*pathname
!= '\0') {
4279 len
= sprintf(&buf
[0], " [%d]/%s ", ti
->arg1
, pathname
);
4282 len
= sprintf(&buf
[0], " [%d]/%s ", ti
->arg3
, pathname
);
4285 len
= sprintf(&buf
[0], " %s ", pathname
);
4288 if (format
== FMT_MOUNT
&& ti
->lookups
[1].pathname
[0]) {
4291 memset(&buf
[len
], ' ', 2);
4293 len2
= sprintf(&buf
[len
+2], " %s ", (char *)&ti
->lookups
[1].pathname
[0]);
4294 len
= len
+ 2 + len2
;
4301 * Add null padding if column length
4302 * is wider than the pathname length.
4304 memset(&buf
[len
], ' ', clen
- len
);
4309 } else if (clen
== len
) {
4312 } else if ((clen
> 0) && (clen
< len
)) {
4314 * This prints the tail end of the pathname
4316 buf
[len
-clen
] = ' ';
4318 pathname
= &buf
[len
- clen
];
4325 * fudge some additional system call overhead
4326 * that currently isn't tracked... this also
4327 * insures that we see a minimum of 1 us for
4330 usecs
= (unsigned long)(((now
- stime
) + (divisor
-1)) / divisor
);
4331 secs
= usecs
/ 1000000;
4332 usecs
-= secs
* 1000000;
4334 if (class != FILEMGR_CLASS
&& !nopadding
)
4344 if (columns
> MAXCOLS
|| wideflag
)
4345 printf("%s%s %3ld.%06ld%s %s.%d\n", p1
, pathname
, (unsigned long)secs
, (unsigned long)usecs
, p2
, command_name
, (int)thread
);
4347 printf("%s%s %3ld.%06ld%s %-12.12s\n", p1
, pathname
, (unsigned long)secs
, (unsigned long)usecs
, p2
, command_name
);
4352 add_meta_name(uint64_t blockno
, char *pathname
) {
4356 hashid
= blockno
& VN_HASH_MASK
;
4358 for (mi
= m_info_hash
[hashid
]; mi
; mi
= mi
->m_next
) {
4359 if (mi
->m_blkno
== blockno
)
4363 mi
= (meta_info_t
)malloc(sizeof(struct meta_info
));
4365 mi
->m_next
= m_info_hash
[hashid
];
4366 m_info_hash
[hashid
] = mi
;
4367 mi
->m_blkno
= blockno
;
4369 mi
->m_nameptr
= pathname
;
4373 find_meta_name(uint64_t blockno
) {
4377 hashid
= blockno
& VN_HASH_MASK
;
4379 for (mi
= m_info_hash
[hashid
]; mi
; mi
= mi
->m_next
) {
4380 if (mi
->m_blkno
== blockno
)
4381 return (mi
->m_nameptr
);
4388 add_vnode_name(uint64_t vn_id
, char *pathname
) {
4392 hashid
= (vn_id
>> VN_HASH_SHIFT
) & VN_HASH_MASK
;
4394 for (vn
= vn_info_hash
[hashid
]; vn
; vn
= vn
->vn_next
) {
4395 if (vn
->vn_id
== vn_id
)
4399 vn
= (vnode_info_t
)malloc(sizeof(struct vnode_info
));
4401 vn
->vn_next
= vn_info_hash
[hashid
];
4402 vn_info_hash
[hashid
] = vn
;
4405 strcpy(vn
->vn_pathname
, pathname
);
4407 return (&vn
->vn_pathname
);
4412 find_vnode_name(uint64_t vn_id
) {
4416 hashid
= (vn_id
>> VN_HASH_SHIFT
) & VN_HASH_MASK
;
4418 for (vn
= vn_info_hash
[hashid
]; vn
; vn
= vn
->vn_next
) {
4419 if (vn
->vn_id
== vn_id
)
4420 return (vn
->vn_pathname
);
4427 delete_event(th_info_t ti_to_delete
) {
4432 hashid
= ti_to_delete
->thread
& HASH_MASK
;
4434 if ((ti
= th_info_hash
[hashid
])) {
4435 if (ti
== ti_to_delete
)
4436 th_info_hash
[hashid
] = ti
->next
;
4440 for (ti
= ti
->next
; ti
; ti
= ti
->next
) {
4441 if (ti
== ti_to_delete
) {
4442 ti_prev
->next
= ti
->next
;
4449 ti
->next
= th_info_freelist
;
4450 th_info_freelist
= ti
;
4456 add_event(uintptr_t thread
, int type
) {
4461 if ((ti
= th_info_freelist
))
4462 th_info_freelist
= ti
->next
;
4464 ti
= (th_info_t
)malloc(sizeof(struct th_info
));
4466 hashid
= thread
& HASH_MASK
;
4468 ti
->next
= th_info_hash
[hashid
];
4469 th_info_hash
[hashid
] = ti
;
4471 ti
->thread
= thread
;
4476 ti
->in_hfs_update
= 0;
4478 ti
->pathptr
= &ti
->lookups
[0].pathname
[0];
4479 ti
->pn_scall_index
= 0;
4480 ti
->pn_work_index
= 0;
4482 for (i
= 0; i
< MAX_PATHNAMES
; i
++)
4483 ti
->lookups
[i
].pathname
[0] = 0;
4489 find_event(uintptr_t thread
, int type
) {
4493 hashid
= thread
& HASH_MASK
;
4495 for (ti
= th_info_hash
[hashid
]; ti
; ti
= ti
->next
) {
4496 if (ti
->thread
== thread
) {
4497 if (type
== ti
->type
)
4499 if (ti
->in_filemgr
) {
4508 return ((th_info_t
) 0);
4512 delete_all_events() {
4514 th_info_t ti_next
= 0;
4517 for (i
= 0; i
< HASH_SIZE
; i
++) {
4519 for (ti
= th_info_hash
[i
]; ti
; ti
= ti_next
) {
4521 ti
->next
= th_info_freelist
;
4522 th_info_freelist
= ti
;
4524 th_info_hash
[i
] = 0;
4530 mark_thread_waited(uintptr_t thread
) {
4534 hashid
= thread
& HASH_MASK
;
4536 for (ti
= th_info_hash
[hashid
]; ti
; ti
= ti
->next
) {
4537 if (ti
->thread
== thread
)
4543 void read_command_map()
4547 int total_threads
= 0;
4548 kd_threadmap
*mapptr
= 0;
4550 delete_all_map_entries();
4554 total_threads
= bufinfo
.nkdthreads
;
4555 size
= bufinfo
.nkdthreads
* sizeof(kd_threadmap
);
4558 if ((mapptr
= (kd_threadmap
*) malloc(size
))) {
4561 bzero (mapptr
, size
);
4563 * Now read the threadmap
4566 mib
[1] = KERN_KDEBUG
;
4567 mib
[2] = KERN_KDTHRMAP
;
4570 mib
[5] = 0; /* no flags */
4572 if (sysctl(mib
, 3, mapptr
, &size
, NULL
, 0) < 0) {
4574 * This is not fatal -- just means I cant map command strings
4585 RAW_fd
= open(RAW_file
, O_RDONLY
);
4588 perror("Can't open RAW file");
4591 if (read(RAW_fd
, &header
, sizeof(RAW_header
)) != sizeof(RAW_header
)) {
4592 perror("read failed");
4595 if (header
.version_no
!= RAW_VERSION1
) {
4596 header
.version_no
= RAW_VERSION0
;
4597 header
.TOD_secs
= time((long *)0);
4598 header
.TOD_usecs
= 0;
4600 lseek(RAW_fd
, (off_t
)0, SEEK_SET
);
4602 if (read(RAW_fd
, &header
.thread_count
, sizeof(int)) != sizeof(int)) {
4603 perror("read failed");
4607 sample_TOD_secs
= header
.TOD_secs
;
4608 sample_TOD_usecs
= header
.TOD_usecs
;
4610 total_threads
= header
.thread_count
;
4611 size
= total_threads
* sizeof(kd_threadmap
);
4614 if ((mapptr
= (kd_threadmap
*) malloc(size
))) {
4615 bzero (mapptr
, size
);
4617 if (read(RAW_fd
, mapptr
, size
) != size
) {
4623 if (header
.version_no
!= RAW_VERSION0
) {
4624 offset
= lseek(RAW_fd
, (off_t
)0, SEEK_CUR
);
4625 offset
= (offset
+ (4095)) & ~4095;
4627 lseek(RAW_fd
, offset
, SEEK_SET
);
4630 for (i
= 0; i
< total_threads
; i
++)
4631 create_map_entry(mapptr
[i
].thread
, mapptr
[i
].valid
, &mapptr
[i
].command
[0]);
4637 void delete_all_map_entries()
4639 threadmap_t tme
= 0;
4640 threadmap_t tme_next
= 0;
4643 for (i
= 0; i
< HASH_SIZE
; i
++) {
4645 for (tme
= threadmap_hash
[i
]; tme
; tme
= tme_next
) {
4647 free(tme
->tm_setptr
);
4648 tme_next
= tme
->tm_next
;
4649 tme
->tm_next
= threadmap_freelist
;
4650 threadmap_freelist
= tme
;
4652 threadmap_hash
[i
] = 0;
4657 void create_map_entry(uintptr_t thread
, int pid
, char *command
)
4662 if ((tme
= threadmap_freelist
))
4663 threadmap_freelist
= tme
->tm_next
;
4665 tme
= (threadmap_t
)malloc(sizeof(struct threadmap
));
4667 tme
->tm_thread
= thread
;
4668 tme
->tm_setsize
= 0;
4671 (void)strncpy (tme
->tm_command
, command
, MAXCOMLEN
);
4672 tme
->tm_command
[MAXCOMLEN
] = '\0';
4674 hashid
= thread
& HASH_MASK
;
4676 tme
->tm_next
= threadmap_hash
[hashid
];
4677 threadmap_hash
[hashid
] = tme
;
4679 if (pid
!= 0 && pid
!= 1) {
4680 if (!strncmp(command
, "LaunchCFMA", 10))
4681 (void)get_real_command_name(pid
, tme
->tm_command
, MAXCOMLEN
);
4687 find_map_entry(uintptr_t thread
)
4692 hashid
= thread
& HASH_MASK
;
4694 for (tme
= threadmap_hash
[hashid
]; tme
; tme
= tme
->tm_next
) {
4695 if (tme
->tm_thread
== thread
)
4703 delete_map_entry(uintptr_t thread
)
4705 threadmap_t tme
= 0;
4706 threadmap_t tme_prev
;
4709 hashid
= thread
& HASH_MASK
;
4711 if ((tme
= threadmap_hash
[hashid
])) {
4712 if (tme
->tm_thread
== thread
)
4713 threadmap_hash
[hashid
] = tme
->tm_next
;
4717 for (tme
= tme
->tm_next
; tme
; tme
= tme
->tm_next
) {
4718 if (tme
->tm_thread
== thread
) {
4719 tme_prev
->tm_next
= tme
->tm_next
;
4727 free(tme
->tm_setptr
);
4729 tme
->tm_next
= threadmap_freelist
;
4730 threadmap_freelist
= tme
;
4737 fs_usage_fd_set(uintptr_t thread
, unsigned int fd
)
4741 if ((tme
= find_map_entry(thread
)) == 0)
4744 * If the map is not allocated, then now is the time
4746 if (tme
->tm_setptr
== (unsigned long *)0) {
4747 if ((tme
->tm_setptr
= (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE
))) == 0)
4750 tme
->tm_setsize
= FS_USAGE_FD_SETSIZE
;
4751 bzero(tme
->tm_setptr
, (FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE
)));
4754 * If the map is not big enough, then reallocate it
4756 while (tme
->tm_setsize
<= fd
) {
4759 n
= tme
->tm_setsize
* 2;
4760 tme
->tm_setptr
= (unsigned long *)realloc(tme
->tm_setptr
, (FS_USAGE_NFDBYTES(n
)));
4762 bzero(&tme
->tm_setptr
[(tme
->tm_setsize
/FS_USAGE_NFDBITS
)], (FS_USAGE_NFDBYTES(tme
->tm_setsize
)));
4763 tme
->tm_setsize
= n
;
4768 tme
->tm_setptr
[fd
/FS_USAGE_NFDBITS
] |= (1 << ((fd
) % FS_USAGE_NFDBITS
));
4774 * 0 : File Descriptor bit is not set
4775 * 1 : File Descriptor bit is set
4778 fs_usage_fd_isset(uintptr_t thread
, unsigned int fd
)
4783 if ((tme
= find_map_entry(thread
))) {
4784 if (tme
->tm_setptr
&& fd
< tme
->tm_setsize
)
4785 ret
= tme
->tm_setptr
[fd
/FS_USAGE_NFDBITS
] & (1 << (fd
% FS_USAGE_NFDBITS
));
4792 fs_usage_fd_clear(uintptr_t thread
, unsigned int fd
)
4796 if ((tme
= find_map_entry(thread
))) {
4797 if (tme
->tm_setptr
&& fd
< tme
->tm_setsize
)
4798 tme
->tm_setptr
[fd
/FS_USAGE_NFDBITS
] &= ~(1 << (fd
% FS_USAGE_NFDBITS
));
4811 ret
= (int)strtol(str
, &cp
, 10);
4813 if (cp
== str
|| *cp
) {
4815 * Assume this is a command string and find matching pids
4820 for (i
= 0; i
< kp_nentries
&& num_of_pids
< (MAX_PIDS
- 1); i
++) {
4821 if (kp_buffer
[i
].kp_proc
.p_stat
== 0)
4824 if (!strncmp(str
, kp_buffer
[i
].kp_proc
.p_comm
,
4825 sizeof(kp_buffer
[i
].kp_proc
.p_comm
) -1))
4826 pids
[num_of_pids
++] = kp_buffer
[i
].kp_proc
.p_pid
;
4830 else if (num_of_pids
< (MAX_PIDS
- 1))
4831 pids
[num_of_pids
++] = ret
;
4837 lookup_name(uint64_t user_addr
, char **type
, char **name
)
4845 if (numFrameworks
) {
4847 if ((user_addr
>= framework32
.b_address
&& user_addr
< framework32
.e_address
) ||
4848 (user_addr
>= framework64
.b_address
&& user_addr
< framework64
.e_address
) ||
4849 (user_addr
>= framework64h
.b_address
&& user_addr
< framework64h
.e_address
)) {
4852 last
= numFrameworks
;
4854 for (i
= numFrameworks
/ 2; start
< last
; i
= start
+ ((last
- start
) / 2)) {
4855 if (user_addr
> frameworkInfo
[i
].e_address
)
4860 if (start
< numFrameworks
&&
4861 user_addr
>= frameworkInfo
[start
].b_address
&& user_addr
< frameworkInfo
[start
].e_address
) {
4862 *type
= frameworkType
[frameworkInfo
[start
].r_type
];
4863 *name
= frameworkInfo
[start
].name
;
4871 * Comparison routines for sorting
4873 static int compareFrameworkAddress(const void *aa
, const void *bb
)
4875 LibraryInfo
*a
= (LibraryInfo
*)aa
;
4876 LibraryInfo
*b
= (LibraryInfo
*)bb
;
4878 if (a
->b_address
< b
->b_address
) return -1;
4879 if (a
->b_address
== b
->b_address
) return 0;
4884 int scanline(char *inputstring
, char **argv
, int maxtokens
)
4887 char **ap
= argv
, *p
, *val
;
4889 for (p
= inputstring
; n
< maxtokens
&& p
!= NULL
; ) {
4891 while ((val
= strsep(&p
, " \t")) != NULL
&& *val
== '\0');
4902 int ReadSharedCacheMap(const char *path
, LibraryRange
*lr
, char *linkedit_name
)
4904 uint64_t b_address
, e_address
;
4908 char frameworkName
[256];
4912 int linkedit_found
= 0;
4913 char *substring
, *ptr
;
4915 bzero(buf
, sizeof(buf
));
4916 bzero(tokens
, sizeof(tokens
));
4921 if ((fd
= fopen(path
, "r")) == 0)
4924 while (fgets(buf
, 1023, fd
)) {
4925 if (strncmp(buf
, "mapping", 7))
4928 buf
[strlen(buf
)-1] = 0;
4930 frameworkName
[0] = 0;
4934 * Extract lib name from path name
4936 if ((substring
= strrchr(buf
, '.')))
4939 * There is a ".": name is whatever is between the "/" around the "."
4941 while ( *substring
!= '/') /* find "/" before "." */
4945 strncpy(frameworkName
, substring
, 256); /* copy path from "/" */
4946 frameworkName
[255] = 0;
4947 substring
= frameworkName
;
4949 while ( *substring
!= '/' && *substring
) /* find "/" after "." and stop string there */
4956 * No ".": take segment after last "/"
4963 substring
= ptr
+ 1;
4966 strncpy(frameworkName
, substring
, 256);
4967 frameworkName
[255] = 0;
4969 fnp
= (char *)malloc(strlen(frameworkName
) + 1);
4970 strcpy(fnp
, frameworkName
);
4972 while (fgets(buf
, 1023, fd
) && numFrameworks
< (MAXINDEX
- 2)) {
4976 buf
[strlen(buf
)-1] = 0;
4978 ntokens
= scanline(buf
, tokens
, 64);
4983 if (strncmp(tokens
[0], "__TEXT", 6) == 0)
4985 else if (strncmp(tokens
[0], "__DATA", 6) == 0)
4987 else if (strncmp(tokens
[0], "__OBJC", 6) == 0)
4989 else if (strncmp(tokens
[0], "__IMPORT", 8) == 0)
4991 else if (strncmp(tokens
[0], "__UNICODE", 9) == 0)
4993 else if (strncmp(tokens
[0], "__IMAGE", 7) == 0)
4995 else if (strncmp(tokens
[0], "__LINKEDIT", 10) == 0)
5000 if (type
== LINKEDIT_R
&& linkedit_found
)
5004 b_address
= strtoull(tokens
[1], 0, 16);
5005 e_address
= strtoull(tokens
[3], 0, 16);
5007 frameworkInfo
[numFrameworks
].b_address
= b_address
;
5008 frameworkInfo
[numFrameworks
].e_address
= e_address
;
5009 frameworkInfo
[numFrameworks
].r_type
= type
;
5011 if (type
== LINKEDIT_R
) {
5012 frameworkInfo
[numFrameworks
].name
= linkedit_name
;
5015 frameworkInfo
[numFrameworks
].name
= fnp
;
5017 printf("%s(%d): %qx-%qx\n", frameworkInfo
[numFrameworks
].name
, type
, b_address
, e_address
);
5019 if (lr
->b_address
== 0 || b_address
< lr
->b_address
)
5020 lr
->b_address
= b_address
;
5022 if (lr
->e_address
== 0 || e_address
> lr
->e_address
)
5023 lr
->e_address
= e_address
;
5027 if (type
== LINKEDIT_R
)
5030 if (fgets(buf
, 1023, fd
) == 0)
5033 buf
[strlen(buf
)-1] = 0;
5038 printf("%s range, %qx-%qx\n", path
, lr
->b_address
, lr
->e_address
);
5045 SortFrameworkAddresses()
5048 frameworkInfo
[numFrameworks
].b_address
= frameworkInfo
[numFrameworks
- 1].b_address
+ 0x800000;
5049 frameworkInfo
[numFrameworks
].e_address
= frameworkInfo
[numFrameworks
].b_address
;
5050 frameworkInfo
[numFrameworks
].name
= (char *)0;
5052 qsort(frameworkInfo
, numFrameworks
, sizeof(LibraryInfo
), compareFrameworkAddress
);
5056 struct diskio
*insert_diskio(int type
, int bp
, int dev
, int blkno
, int io_size
, uintptr_t thread
, double curtime
)
5061 if ((dio
= free_diskios
))
5062 free_diskios
= dio
->next
;
5064 if ((dio
= (struct diskio
*)malloc(sizeof(struct diskio
))) == NULL
)
5073 dio
->iosize
= io_size
;
5074 dio
->issued_time
= curtime
;
5075 dio
->issuing_thread
= thread
;
5079 if ((tme
= find_map_entry(thread
))) {
5080 strncpy(dio
->issuing_command
, tme
->tm_command
, MAXCOMLEN
);
5081 dio
->issuing_command
[MAXCOMLEN
] = '\0';
5083 strcpy(dio
->issuing_command
, "");
5085 dio
->next
= busy_diskios
;
5087 dio
->next
->prev
= dio
;
5093 struct diskio
*find_diskio(int bp
) {
5096 for (dio
= busy_diskios
; dio
; dio
= dio
->next
) {
5105 struct diskio
*complete_diskio(int bp
, int io_errno
, int resid
, uintptr_t thread
, double curtime
)
5109 if ((dio
= find_diskio(bp
)) == NULL
) return NULL
;
5111 if (dio
== busy_diskios
) {
5112 if ((busy_diskios
= dio
->next
))
5113 dio
->next
->prev
= NULL
;
5116 dio
->next
->prev
= dio
->prev
;
5117 dio
->prev
->next
= dio
->next
;
5120 dio
->iosize
-= resid
;
5121 dio
->io_errno
= io_errno
;
5122 dio
->completed_time
= curtime
;
5123 dio
->completion_thread
= thread
;
5129 void free_diskio(struct diskio
*dio
)
5131 dio
->next
= free_diskios
;
5136 void print_diskio(struct diskio
*dio
)
5141 int format
= FMT_DISKIO
;
5147 if ((type
& P_CS_Class
) == P_CS_Class
) {
5151 case P_CS_ReadChunk
:
5154 format
= FMT_DISKIO_CS
;
5156 case P_CS_WriteChunk
:
5159 format
= FMT_DISKIO_CS
;
5164 format
= FMT_DISKIO_CS
;
5166 case P_CS_MetaWrite
:
5169 format
= FMT_DISKIO_CS
;
5171 case P_CS_TransformRead
:
5175 case P_CS_TransformWrite
:
5179 case P_CS_MigrationRead
:
5183 case P_CS_MigrationWrite
:
5188 strncpy(buf
, p
, len
);
5191 switch (type
& P_DISKIO_TYPE
) {
5224 strncpy(buf
, p
, len
);
5228 if (type
& P_DISKIO_ASYNC
)
5233 if (type
& P_DISKIO_NOCACHE
)
5236 int tier
= (type
& P_DISKIO_TIER_MASK
) >> P_DISKIO_TIER_SHIFT
;
5239 if (tier
> 0 && tier
< 10)
5240 buf
[len
++] = '0' + tier
;
5243 if (type
& P_DISKIO_PASSIVE
)
5251 if (check_filter_mode(NULL
, type
, 0, 0, buf
))
5252 format_print(NULL
, buf
, dio
->issuing_thread
, type
, 0, 0, 0, 0, format
, dio
->completed_time
, dio
->issued_time
, 1, "", dio
);
5256 void cache_disk_names()
5261 struct diskrec
*dnp
;
5264 if ((dirp
= opendir("/dev")) == NULL
)
5267 while ((dir
= readdir(dirp
)) != NULL
) {
5268 char nbuf
[MAXPATHLEN
];
5270 if (dir
->d_namlen
< 5 || strncmp("disk", dir
->d_name
, 4))
5273 snprintf(nbuf
, MAXPATHLEN
, "%s/%s", "/dev", dir
->d_name
);
5275 if (stat(nbuf
, &st
) < 0)
5278 if ((dnp
= (struct diskrec
*)malloc(sizeof(struct diskrec
))) == NULL
)
5281 if ((dnp
->diskname
= (char *)malloc(dir
->d_namlen
+ 1)) == NULL
) {
5285 strncpy(dnp
->diskname
, dir
->d_name
, dir
->d_namlen
);
5286 dnp
->diskname
[dir
->d_namlen
] = 0;
5287 dnp
->dev
= st
.st_rdev
;
5289 dnp
->next
= disk_list
;
5292 (void) closedir(dirp
);
5296 void recache_disk_names()
5298 struct diskrec
*dnp
, *next_dnp
;
5300 for (dnp
= disk_list
; dnp
; dnp
= next_dnp
) {
5301 next_dnp
= dnp
->next
;
5303 free(dnp
->diskname
);
5312 char *find_disk_name(int dev
)
5314 struct diskrec
*dnp
;
5323 for (i
= 0; i
< 2; i
++) {
5324 for (dnp
= disk_list
; dnp
; dnp
= dnp
->next
) {
5325 if (dnp
->dev
== dev
)
5326 return (dnp
->diskname
);
5328 recache_disk_names();
5330 return ("NOTFOUND");
5334 char *generate_cs_disk_name(int dev
, char *s
)
5339 sprintf(s
, "disk%ds%d", (dev
>> 16) & 0xffff, dev
& 0xffff);
5347 * ret = 1 means print the entry
5348 * ret = 0 means don't print the entry
5352 * meaning of filter flags:
5353 * cachehit turn on display of CACHE_HIT events (which are filtered out by default)
5355 * exec show exec/posix_spawn
5356 * pathname show events with a pathname and close()
5357 * diskio show disk I/Os
5358 * filesys show filesystem events
5359 * network show network events
5361 * filters may be combined; default is all filters on (except cachehit)
5364 check_filter_mode(struct th_info
*ti
, int type
, int error
, int retval
, char *sc_name
)
5367 int network_fd_isset
= 0;
5370 /* cachehit is special -- it's not on by default */
5371 if (sc_name
[0] == 'C' && !strcmp(sc_name
, "CACHE_HIT")) {
5372 if (show_cachehits
) return 1;
5376 if (filter_mode
== DEFAULT_DO_NOT_FILTER
)
5379 if (filter_mode
& DISKIO_FILTER
) {
5380 if ((type
& P_DISKIO_MASK
) == P_DISKIO
)
5384 if (filter_mode
& EXEC_FILTER
) {
5385 if (type
== BSC_execve
|| type
== BSC_posix_spawn
)
5389 if (filter_mode
& PATHNAME_FILTER
) {
5390 if (ti
&& ti
->lookups
[0].pathname
[0])
5392 if (type
== BSC_close
|| type
== BSC_close_nocancel
||
5393 type
== BSC_guarded_close_np
)
5397 if (ti
== (struct th_info
*)0) {
5398 if (filter_mode
& FILESYS_FILTER
)
5406 case BSC_close_nocancel
:
5407 case BSC_guarded_close_np
:
5409 network_fd_isset
= fs_usage_fd_isset(ti
->thread
, fd
);
5412 fs_usage_fd_clear(ti
->thread
,fd
);
5414 if (network_fd_isset
) {
5415 if (filter_mode
& NETWORK_FILTER
)
5418 if (filter_mode
& FILESYS_FILTER
)
5424 case BSC_read_nocancel
:
5425 case BSC_write_nocancel
:
5427 * we don't care about error in these cases
5430 network_fd_isset
= fs_usage_fd_isset(ti
->thread
, fd
);
5432 if (network_fd_isset
) {
5433 if (filter_mode
& NETWORK_FILTER
)
5436 if (filter_mode
& FILESYS_FILTER
)
5441 case BSC_accept_nocancel
:
5446 fs_usage_fd_set(ti
->thread
, fd
);
5447 if (filter_mode
& NETWORK_FILTER
)
5458 case BSC_sendto_nocancel
:
5459 case BSC_recvfrom_nocancel
:
5460 case BSC_recvmsg_nocancel
:
5461 case BSC_sendmsg_nocancel
:
5462 case BSC_connect_nocancel
:
5466 fs_usage_fd_set(ti
->thread
, fd
);
5467 if (filter_mode
& NETWORK_FILTER
)
5472 case BSC_select_nocancel
:
5473 case BSC_socketpair
:
5475 * Cannot determine info about file descriptors
5477 if (filter_mode
& NETWORK_FILTER
)
5484 * We track these cases for fd state only
5487 network_fd_isset
= fs_usage_fd_isset(ti
->thread
, fd
);
5489 if (error
== 0 && network_fd_isset
) {
5491 * then we are duping a socket descriptor
5493 fd
= retval
; /* the new fd */
5494 fs_usage_fd_set(ti
->thread
, fd
);
5499 if (filter_mode
& FILESYS_FILTER
)
5508 * Allocate a buffer that is large enough to hold the maximum arguments
5509 * to execve(). This is used when getting the arguments to programs
5510 * when we see LaunchCFMApps. If this fails, it is not fatal, we will
5511 * simply not resolve the command name.
5515 init_arguments_buffer()
5521 mib
[1] = KERN_ARGMAX
;
5522 size
= sizeof(argmax
);
5524 if (sysctl(mib
, 2, &argmax
, &size
, NULL
, 0) == -1)
5527 /* Hack to avoid kernel bug. */
5528 if (argmax
> 8192) {
5532 arguments
= (char *)malloc(argmax
);
5537 get_real_command_name(int pid
, char *cbuf
, int csize
)
5540 * Get command and arguments.
5544 char *command_beg
, *command
, *command_end
;
5550 bzero(arguments
, argmax
);
5555 * A sysctl() is made to find out the full path that the command
5559 mib
[1] = KERN_PROCARGS2
;
5563 if (sysctl(mib
, 3, arguments
, (size_t *)&argmax
, NULL
, 0) < 0)
5567 * Skip the saved exec_path
5569 for (cp
= arguments
; cp
< &arguments
[argmax
]; cp
++) {
5572 * End of exec_path reached
5577 if (cp
== &arguments
[argmax
])
5581 * Skip trailing '\0' characters
5583 for (; cp
< &arguments
[argmax
]; cp
++) {
5586 * Beginning of first argument reached
5591 if (cp
== &arguments
[argmax
])
5596 * Make sure that the command is '\0'-terminated. This protects
5597 * against malicious programs; under normal operation this never
5598 * ends up being a problem..
5600 for (; cp
< &arguments
[argmax
]; cp
++) {
5603 * End of first argument reached
5608 if (cp
== &arguments
[argmax
])
5611 command_end
= command
= cp
;
5614 * Get the basename of command
5616 for (command
--; command
>= command_beg
; command
--) {
5617 if (*command
== '/') {
5622 (void) strncpy(cbuf
, (char *)command
, csize
);
5623 cbuf
[csize
-1] = '\0';