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